@font-face {
  font-family: "Inter";
  src: url("/static/vendor/Inter-v20-subset.woff2") format("woff2");
  font-weight: 900;
  font-display: swap;
}

:root {
  --bg: #e8dcc6;
  --surface: #f3ebdc;
  --text: #2e2823;
  --muted: #6a6054;
  --line: #a08b73;

  --accent: #cf7336;
  --accent-edge: #8a4a1f;
  --ink: #5b4e43;
  --ink-edge: #2f2721;
  --red: #b8383b;
  --blu: #5885a2;
  --ok: #3d8b52;
  --busy: #b5782a;

  --radius: 0;
  --depth-x: 4px;
  --depth-y: 2px;
  --gap: 12px;
  --header-h: 64px;
  --font: 15px/1.4 system-ui, sans-serif;
  --font-brand: "Inter", system-ui, sans-serif;

  color-scheme: light;
}

* { box-sizing: border-box; }

[hidden] { display: none !important; }

/* A column at least a screen tall, with main taking the slack, so a short
   page keeps its footer at the bottom of the window without scrolling. */
body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: var(--font);
}

/* The icon, huge and faint, behind every page. */
body::after {
  content: "";
  position: fixed;
  right: -22vmin;
  bottom: -30vmin;
  z-index: -1;
  width: 120vmin;
  height: 120vmin;
  background: url("favicon.svg") center / contain no-repeat;
  opacity: 0.07;
  pointer-events: none;
}

main {
  flex: 1 0 auto;
  width: 100%;
  max-width: 1400px;
  margin: 0 auto;
  padding: var(--gap);
}

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

/* Quiet links under the page: plain text, so they never compete with the nav. */
.site-footer {
  display: flex;
  width: 100%;
  gap: calc(var(--gap) * 1.5);
  max-width: 1400px;
  margin: 0 auto;
  padding: var(--gap);
  border-top: 2px solid var(--line);
}

.site-footer a { color: var(--muted); font-size: 0.9em; text-decoration: none; }
.site-footer a:hover { color: var(--text); text-decoration: underline; }
.site-footer a[aria-current="page"] { color: var(--text); }
.site-footer .version { margin-left: auto; color: var(--muted); font: 0.75em ui-monospace, monospace; }

/* A player's own line breaks, kept. */
td.message { white-space: pre-wrap; overflow-wrap: anywhere; }

/* Text in a pane: the grid's gap spaces it, not margins. */
.pane-body > p { margin: 0; }

/* Questions and their answers, one pair per block. */
.qa dt { font-weight: 700; }
.qa dd { margin: 4px 0 0; }

/* Plain text leading a pane's form. */
.prompt { font-weight: 600; }

/* Dismissed: kept, but out of the way of the unread ones. */
tr.read td { color: var(--muted); }
td > button + button { margin-left: 8px; }

.site-header {
  position: sticky;
  top: 0;
  z-index: 3;
  display: flex;
  align-items: center;
  gap: calc(var(--gap) * 2);
  height: var(--header-h);
  padding: 0 var(--gap);
  background: var(--bg);
}

/* The header's edge is its own layer so main::before can hide it at the top of
   the page and scroll away to reveal it -- a switch with no JS or scroll API. */
body::before, main::before {
  content: "";
  display: block;
  height: calc(2px + var(--depth-y));
}

body::before {
  position: sticky;
  top: var(--header-h);
  z-index: 1;
  margin-bottom: calc(-2px - var(--depth-y));
  background: var(--line);
}

main::before {
  position: relative;
  z-index: 2;
  margin: calc(-1 * var(--gap)) 0 calc(var(--gap) - 2px - var(--depth-y));
  background: var(--bg);
  box-shadow: 0 0 0 100vmax var(--bg);
  clip-path: inset(0 -100vmax);
}

/* The buttons' slab, on letters: a stack of 1px shadows is the slab, and the
   face rises and sinks over it while the slab's base stays put. */
.site-header .brand {
  display: flex;
  align-items: center;
  color: var(--accent);
  font-family: var(--font-brand);
  font-size: 1.35em;
  font-weight: 900;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  text-decoration: none;
  transition: transform 60ms;
}

.defs { position: absolute; width: 0; height: 0; }

/* No rounding filter at this size: it works on pixels, and at 20px there are
   too few of them for anything but jagged edges. */
.site-header .brand span {
  --e: var(--accent-edge);

  text-shadow: 0 1px 0 var(--e), 0 2px 0 var(--e), 0 3px 0 var(--e), 0 4px 0 var(--e);
  transition: text-shadow 60ms;
}

/* favicon.svg without its drawn slab: each bar has the letters' slab instead,
   six copies of itself that follow the face down as far as --depth. Copies,
   not a drop-shadow: a filter on an svg shape is clipped to it.
   A margin, not a gap: a gap would also part "demoreview" from ".tf". */
.mark {
  --n: 30;
  --depth: 4;

  width: calc(var(--n) * 1px);
  height: calc(var(--n) * 1px);
  margin-right: 0.35em;
  overflow: visible;
}

.brand:hover .mark { --depth: 6; }
.brand:active .mark { --depth: 2; }

.mark .bar { --e: var(--ink-edge); fill: var(--ink); stroke: var(--ink); stroke-width: 1.6; stroke-linejoin: round; }
.mark .arrow { --e: var(--accent-edge); fill: var(--accent); stroke: var(--accent); }

/* A length on an svg shape is in the viewBox's units, 64 across. */
.mark use {
  fill: var(--e);
  stroke: var(--e);
  transform: translateY(calc(64px / var(--n) * min(var(--k), var(--depth))));
  transition: transform 60ms;
}

.mark use:nth-child(1) { --k: 6; }
.mark use:nth-child(2) { --k: 5; }
.mark use:nth-child(3) { --k: 4; }
.mark use:nth-child(4) { --k: 3; }
.mark use:nth-child(5) { --k: 2; }
.mark use:nth-child(6) { --k: 1; }

@media (max-width: 500px) {
  .site-header .brand span { display: none; }
  .mark { --n: 38; margin-right: 0; }
}

.site-header .brand .tf,
.wordmark [aria-hidden] .tf {
  --e: var(--ink-edge);

  color: var(--ink);
}

.site-header .brand:hover { transform: translateY(-2px); }

.site-header .brand:hover span {
  text-shadow: 0 1px 0 var(--e), 0 2px 0 var(--e), 0 3px 0 var(--e), 0 4px 0 var(--e),
               0 5px 0 var(--e), 0 6px 0 var(--e);
}

.site-header .brand:active { transform: translateY(2px); }
.site-header .brand:active span { text-shadow: 0 1px 0 var(--e), 0 2px 0 var(--e); }

.site-header nav { flex: 1; }
.site-header .row { flex-wrap: nowrap; }
.pane > header > .push { margin-left: auto; }
details.submit { margin-bottom: var(--gap); }
details.submit[open] > summary { margin-bottom: var(--gap); }

nav { display: flex; gap: calc(var(--gap) * 2); }

nav a {
  color: var(--muted);
  font-weight: 600;
  text-decoration: none;
}

nav a:hover { color: var(--text); }

/* Between everyone's pages and an admin's. */
.nav-divider { width: 2px; align-self: stretch; background: var(--line); }

/* The signed-in name: a link to the demos they are in, boxed like a button so
   it does not read as the current page. */
.me { font-weight: 700; }

nav a[aria-current="page"] {
  color: var(--text);
  text-decoration: underline 2px var(--accent);
  text-underline-offset: 6px;
}

/* A face lifted off a bordered slab: the slab is two shadows, edge under fill,
   and the face moves while the slab's base stays put. */
button, .btn, input, select, textarea {
  --fill: var(--bg);
  --edge: var(--line);
  --slab: var(--line);
  --lift: 4px;

  display: inline-block;
  min-height: calc(1.4em + 24px);
  padding: 10px 18px;
  font: inherit;
  color: var(--text);
  background: var(--fill);
  border: 2px solid var(--edge);
  margin-bottom: 4px;
  border-radius: var(--radius);
  transform: translateY(calc(4px - var(--lift)));
  box-shadow:
    0 var(--lift) 0 -2px var(--slab),
    0 var(--lift) 0 0 var(--edge);
  transition: transform 60ms, box-shadow 60ms;
}

input:focus, select:focus, textarea:focus { --slab: var(--accent); }

/* A checkbox stays native, beside its label; the slab is for fields. */
input[type="checkbox"] {
  width: 1.1em;
  height: 1.1em;
  min-height: 0;
  margin: 0;
  padding: 0;
  transform: none;
  box-shadow: none;
  accent-color: var(--accent);
}

.check { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; }

textarea { resize: vertical; }

button, .btn {
  --fill: var(--surface);
  --slab: var(--accent);

  display: inline-flex;
  align-items: center;
  gap: 12px;

  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
}

button:hover, .btn:hover { --lift: 6px; }

button:active, .btn:active, button[aria-pressed="true"] { --lift: 2px; }

button[aria-pressed="true"] { --edge: var(--accent-edge); }

button:disabled, input:disabled, textarea:disabled {
  --lift: 4px;
  opacity: 0.5;
  cursor: default;
}

.primary { --fill: var(--accent); --slab: color-mix(in srgb, var(--accent), black 15%); --edge: var(--accent-edge); }

:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.pane {
  margin-bottom: calc(var(--gap) * 2);
  background: var(--surface);
  border: 2px solid var(--line);
  border-radius: var(--radius);
  box-shadow: 0 4px 0 var(--line);
}

.pane > header {
  display: flex;
  align-items: baseline;
  gap: var(--gap);
  padding: 10px var(--gap);
  background: var(--bg);
  border-bottom: 2px solid var(--line);
}

.pane h2 {
  margin: 0;
  font-size: 0.85em;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.pane-body {
  display: grid;
  gap: var(--gap);
  margin: 0;
  padding: var(--gap);
}

.pane-foot {
  padding: var(--gap);
  border-top: 2px solid var(--line);
}

.pane-foot > .pane-body { padding: var(--gap) 0 0; }
.pane th, .pane td { padding: 10px var(--gap); }
.pane td { vertical-align: middle; }
.pane td:last-child:has(> button) { text-align: right; }
.pane td:last-child > .row { justify-content: flex-end; flex-wrap: nowrap; }
.pane tr:last-child td { border-bottom: 0; }

/* A button labelled by an icon alone, as tall as a worded one; `small` sits
   inline with text, like the rename pencil. A label.icon is a checkbox toggle. */
.icon { padding: 10px 12px; }
.icon svg { display: block; width: 1.4em; height: 1.4em; }
.icon.small { min-height: 0; margin-left: 6px; padding: 3px 5px; vertical-align: 1px; }
.icon.small svg { width: 14px; height: 14px; }
.icon:has(:checked) { --lift: 2px; --edge: var(--accent-edge); }
.icon[aria-pressed="true"], .icon:has(:checked) { color: var(--accent); }
.icon:has(:focus-visible) { outline: 2px solid var(--accent); outline-offset: -2px; }
.icon .slash { display: none; }
.icon[aria-pressed="true"] .slash, .icon:has(:checked) .slash { display: inline; }

/* Off the top of the page until it has focus, then over the header. */
.skip { position: absolute; top: 0; left: var(--gap); z-index: 4; transform: translateY(-200%); }
.skip:focus { transform: none; }

/* Out of sight but still focusable and announced. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* The form the pencil swaps in. */
.demo-title.rename { display: grid; gap: 6px; }
.demo-title.rename .row { flex-wrap: nowrap; }
button.link {
  min-height: 0;
  margin: 0;
  padding: 0;
  justify-self: start;
  font-weight: 400;
  color: var(--muted);
  text-decoration: underline;
  background: none;
  border: 0;
  box-shadow: none;
  transform: none;
}
button.link:hover { color: var(--accent); }

.sources a { display: block; color: var(--text); font-weight: 600; text-decoration: none; }
.sources a:hover { color: var(--accent); }

.pager { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; justify-items: start; gap: var(--gap); }
.pager > :last-child { justify-self: end; }

.stats {
  grid-template-columns: repeat(auto-fill, minmax(9em, 1fr));
}

.stats dt { font-size: 0.75em; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted); }
.stats dd { margin: 2px 0 0; font-size: 1.4em; font-weight: 700; }
/* Back to body size, so a timestamp reads the same as in any table. */
.stats dd time { font-size: calc(1em / 1.4); font-weight: 600; }

/* Date, then the time under it, wherever a timestamp appears. */
time { white-space: nowrap; }
time small { display: block; color: var(--muted); font: 0.75em ui-monospace, monospace; }

.player-head { display: grid; gap: 8px; margin: var(--gap) 0 calc(var(--gap) * 2); }
.player-head h1 { margin: 0; }
.player-head .row { gap: var(--gap); }
.player-head .tag { padding: 5px 10px; font-size: 0.95em; }
a.name + .tag { margin-left: 6px; padding: 1px 5px; font-size: 0.65em; vertical-align: 2px; }
.pane-rule { border-top: 2px solid var(--line); }
/* A log's timestamp column: as narrow as its dates, text beside it. */
td.when { width: 1%; padding-right: calc(var(--gap) * 2); }

a.name { color: var(--text); font-weight: 600; text-decoration: none; }
a.name:hover { color: var(--accent); }
.links { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.links a { color: var(--muted); }
.links a:hover { color: var(--accent); }

/* Buttons at the right; the hint or notice beside them takes the rest. */
.actions { display: flex; align-items: center; justify-content: flex-end; gap: var(--gap); }
.actions > .hint { flex: 1; }
.steps ol { margin: 4px 0 0; padding-left: 1.4em; }

/* Always holds its line, so a notice arriving never moves the fields. */
.hint { min-height: 1.4em; margin: 0; font-size: 0.85em; color: var(--muted); }
.hint.warn { color: var(--red); }
.hint.notice { color: var(--busy); }
td .hint { display: block; min-height: 0; }

.fields {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(20em, 1fr));
  gap: var(--gap);
}

/* One field per line, for a form read top to bottom. */
.fields.stacked { grid-template-columns: 1fr; }

.field { display: grid; gap: 6px; align-content: start; }
.field > span:first-child, .field > label { font-size: 0.85em; font-weight: 600; color: var(--muted); }

/* Flat, borderless and unlifted: nothing about a tag looks pressable. */
.tag {
  --fill: var(--line);

  display: inline-block;
  padding: 3px 8px;
  font-size: 0.75em;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--surface);
  background: var(--fill);
  border-radius: var(--radius);
}

.tag.red { --fill: var(--red); }
.tag.blu { --fill: var(--blu); }
.tag.ok { --fill: var(--ok); }
.tag.busy { --fill: var(--busy); }
.tag.bad { --fill: var(--red); }

.warn { color: var(--red); }
.notice { color: var(--busy); }

.row { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.row > input, .row > .grow { flex: 1 1 14em; }
.row small { white-space: nowrap; }

summary { cursor: pointer; color: var(--muted); }

table { width: 100%; border-collapse: collapse; }
th { text-align: left; font-weight: 400; color: var(--muted); }
th, td { padding: 6px 8px; border-bottom: 2px solid var(--line); }
td small { display: block; color: var(--muted); font: 0.75em ui-monospace, monospace; }

.muted { color: var(--muted); }

.group {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px;
  background: var(--surface);
  border: 2px solid var(--line);
  border-radius: var(--radius);
  box-shadow: 0 4px 0 var(--line);
}

.joined { display: flex; }
.joined > * + * { margin-left: -2px; }
.joined > [aria-pressed="true"] { position: relative; }

kbd {
  display: inline-block;
  margin: 0 2px;
  padding: 1px 5px;
  font: 0.8em ui-monospace, monospace;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: inset calc(var(--depth-x) / 4) calc(var(--depth-y) / 4) 0 var(--line);
}

kbd:has(kbd) { all: unset; }

/* A shortcut beside its button's label, smaller so the label still leads. */
button > kbd, .btn > kbd { margin: 0; padding: 0 3px; font-size: 0.62em; opacity: 0.7; box-shadow: none; }
button:has(> kbd) { gap: 5px; justify-content: center; }

input[type="range"] {
  appearance: none;
  min-height: 0;
  height: 14px;
  padding: 0;
  cursor: pointer;
  background:
    linear-gradient(var(--accent), var(--accent)) 0 / var(--pos, 0%) 100% no-repeat,
    var(--bg);
}

input[type="range"]::-webkit-slider-thumb {
  appearance: none;
  width: 10px;
  height: 22px;
  background: var(--surface);
  border: 2px solid var(--line);
  border-radius: var(--radius);
}

input[type="range"]::-moz-range-thumb {
  width: 10px;
  height: 22px;
  box-sizing: border-box;
  background: var(--surface);
  border: 2px solid var(--line);
  border-radius: var(--radius);
}

.session-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px var(--gap);
  margin-bottom: 8px;
}

.session-head .demo-title b { font-size: 1.2em; }
.session-head .demo-title small { display: inline; margin-left: 8px; font-size: 0.8em; color: var(--muted); }
.session-head .demo-title.rename { flex: 1; }
.session-head .log { color: var(--muted); }
.session-head .log:hover { color: var(--accent); }

/* As wide as the panels around it, and 16:9 so the recording fills it with
   no black bars. */
.player {
  position: relative;
  background: #000;
  border: 2px solid var(--line);
}

.player video { display: block; width: 100%; aspect-ratio: 16 / 9; }

.player .join {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: grid;
  place-items: center;
  background: rgb(0 0 0 / 0.5);
}

.player .video-error {
  position: absolute;
  inset: auto 0 0 0;
  z-index: 3;
  margin: 0;
  padding: var(--gap);
  text-align: center;
  color: #fff;
  background: var(--red);
}

.player-panel {
  display: grid;
  gap: var(--gap);
  padding: var(--gap) 0;
}

.player-panel button { min-height: 0; padding: 4px 10px; }
.progress { display: flex; align-items: center; gap: var(--gap); }
.scrub { position: relative; flex: 1; }
.scrub #scrubber { width: 100%; }
/* One line where each round starts, on the track's face rather than its slab:
   inside the 2px border, and inset by half the thumb so a line is where the
   thumb's centre lands. Clicks go through to the slider. */
.rounds { position: absolute; top: 2px; height: 14px; left: 7px; right: 7px; pointer-events: none; }
.rounds span { position: absolute; top: 0; bottom: 0; width: 2px; margin-left: -1px; background: var(--line); }
#mute { width: 5.5em; justify-content: center; }

.player-row {
  display: grid;
  grid-template-columns: 1fr 40em 1fr;
  grid-template-rows: repeat(3, auto) 1fr;
  column-gap: var(--gap);
  row-gap: 6px;
  align-items: start;
}

.player-controls {
  grid-column: 2;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--gap);
}

.player-controls .group { display: flex; }
.player-controls .transport { grid-column: 1 / -1; }
.transport > button, .joined, .joined > button, #volume { flex: 1 1 0; justify-content: center; }
/* As small as the other buttons here, whatever .icon would make it. */
#fullscreen svg { width: 1.2em; height: 1.2em; }
#volume { min-width: 0; }

.clock {
  min-width: 13ch;
  padding: 4px 10px;
  font: 600 1em ui-monospace, monospace;
  text-align: center;
  background: var(--bg);
  border: 2px solid var(--line);
  border-radius: var(--radius);
  box-shadow: 0 4px 0 var(--line);
}

.pov-bar { display: contents; }

/* Two columns a team, so six players take three rows rather than six. */
.team {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-content: start;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.team.red { grid-column: 1; grid-row: 1 / span 4; }
.team.blu { grid-column: 3; grid-row: 1 / span 4; }
.team.blu .pov { text-align: right; }
.team.other { grid-column: 2; display: flex; flex-wrap: wrap; justify-content: center; }
.team.other:empty { display: none; }

.pov {
  display: block;
  width: 100%;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  text-align: left;
}

.pov.red, .pov.blu { color: var(--surface); }
.pov.red { --fill: var(--red); }
.pov.blu { --fill: var(--blu); }

.watching { grid-column: 2; margin: 0; font-size: 0.85em; }

.watching ul {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
  list-style: none;
}

/* A dot for "here now", rather than a chip that reads like a button. */
.watching li { display: flex; align-items: center; gap: 6px; font-weight: 600; }
.watching li::before { content: ""; width: 7px; height: 7px; background: var(--ok); }

/* One column for the whole page, so the pitch and the section under it
   start at the same left edge. */
.home, .featured { max-width: 72rem; margin-inline: auto; }

/* The pitch on the left, how it works on the right. */
.home {
  --mark: clamp(2rem, 4.4vw, 4.2rem);

  display: grid;
  grid-template-columns: auto auto;
  justify-content: space-between;
  gap: calc(var(--gap) * 4);
  padding: 16vh 0 8vh;
}

/* As tall as the steps beside it, with the button on their bottom edge. */
.hero {
  display: grid;
  grid-template-rows: auto 1fr auto;
  justify-items: start;
  gap: calc(var(--gap) * 2);
}

.hero .btn { margin-bottom: 0; }

/* The header brand's slab at display size: depths in em, so it scales with
   the letters. */
.wordmark {
  margin: 0;
  color: var(--accent);
  font-family: var(--font-brand);
  font-size: var(--mark);
  font-weight: 900;
  line-height: 1;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  white-space: nowrap;
  cursor: default;
  user-select: none;
}

.wordmark [aria-hidden] span {
  --e: var(--accent-edge);

  --slab: drop-shadow(0 0.09em 0 var(--e));

  display: inline-block;
  filter: url(#round-l) var(--slab);
  transition: transform 80ms;
}

/* The slab is a drop-shadow after the rounding filter: a text-shadow would be
   blurred into the face. One copy, not a stack: a 0.015em step is under a
   pixel and is dropped, and the strokes are thicker than the slab, so one copy
   leaves no gap.
   The blur is in px, not em: a smaller wordmark takes the smaller one. */
@media (max-width: 600px) {
  .wordmark [aria-hidden] span { filter: url(#round-m) var(--slab); }
}

.wordmark [aria-hidden] span:hover {
  --slab: drop-shadow(0 0.135em 0 var(--e));

  transform: translateY(-0.045em);
}

.wordmark [aria-hidden] span:active {
  --slab: drop-shadow(0 0.045em 0 var(--e));

  transform: translateY(0.045em);
}

.lede { max-width: 34em; margin: 0; font-size: 1.25em; color: var(--muted); }

/* Three equal rows of steps, with a gutter either side for the arrows. */
.flow {
  --g: 40px;
  --loop: 64px;
  /* Wider on the left, where the arrow has a loop to fit. */
  --curl: 96px;

  display: grid;
  grid-template-columns: var(--curl) auto var(--loop);
  grid-auto-rows: 1fr;
  justify-content: start;
  gap: var(--g) 8px;
  /* Down to the top of the wordmark's capitals, which sit below their line box. */
  margin-top: calc(var(--mark) * 0.115);
}

/* A pane without its header, and text no louder than the lede. */
.step {
  grid-column: 2;
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 0;
  padding: 10px 18px;
  font-size: 1.15em;
  font-weight: 600;
  color: var(--muted);
  white-space: nowrap;
  background: var(--surface);
  border: 2px solid var(--line);
  box-shadow: 0 4px 0 var(--line);
}

/* The wordmark's letters, as numerals: raised by half the slab, so face and
   slab together sit in the middle of the box, and lifting the same way. */
.step b {
  --e: var(--accent-edge);

  color: var(--accent);
  font-size: 2em;
  font-weight: 900;
  line-height: 1;
  text-shadow: 0 1px 0 var(--e), 0 2px 0 var(--e), 0 3px 0 var(--e), 0 4px 0 var(--e);
  transform: translateY(-2px);
  transition: transform 60ms, text-shadow 60ms;
  cursor: default;
  user-select: none;
}

.step b:hover {
  transform: translateY(-4px);
  text-shadow: 0 1px 0 var(--e), 0 2px 0 var(--e), 0 3px 0 var(--e), 0 4px 0 var(--e),
               0 5px 0 var(--e), 0 6px 0 var(--e);
}

.step b:active {
  transform: translateY(0);
  text-shadow: 0 1px 0 var(--e), 0 2px 0 var(--e);
}

/* An arrow spans two rows and runs from the middle of one step to the middle
   of the next: a quarter of what is left once the gap is taken out. The bend
   is stretched to fit, so its stroke is kept from scaling with it.
   The slab is the wordmark's, on a shape: each drop-shadow copies what is
   above it, so four of them sweep the line downwards with no gaps. */
.loop {
  --e: var(--accent-edge);
  --d: 1px;
  --mid: calc((100% - var(--g)) / 4);

  position: relative;
  filter: drop-shadow(0 var(--d) 0 var(--e)) drop-shadow(0 var(--d) 0 var(--e))
          drop-shadow(0 var(--d) 0 var(--e)) drop-shadow(0 var(--d) 0 var(--e));
  transition: transform 60ms;
}

.loop:hover { --d: 1.5px; transform: translateY(-2px); }
.loop:active { --d: 0.5px; transform: translateY(2px); }

.loop.right { grid-area: 1 / 3 / span 2; }
.loop.left { grid-area: 2 / 1 / span 2; }

/* Out over the column gap, so the line starts and ends on the steps' edge. */
.loop svg {
  position: absolute;
  top: var(--mid);
  left: -8px;
  width: calc(100% + 8px);
  height: calc(100% - 2 * var(--mid));
  overflow: visible;
}

.loop.left svg { left: 0; transform: scaleX(-1); }

.loop path {
  fill: none;
  stroke: var(--accent);
  stroke-width: 4px;
  vector-effect: non-scaling-stroke;
}

/* The head, centred on the end of the line. */
.loop::after {
  content: "";
  position: absolute;
  bottom: calc(var(--mid) - 8px);
  width: 14px;
  height: 16px;
  background: var(--accent);
}

/* Turned to meet its line, which comes in on a slant. */
.loop.right::after { left: -8px; clip-path: polygon(100% 0, 0 50%, 100% 100%); transform: rotate(-37deg); }
.loop.left::after { right: -8px; clip-path: polygon(0 0, 100% 50%, 0 100%); }

/* Underlined with a slab: an accent bar on its edge, as the buttons have.
   Two backgrounds on the word itself, so the bar can sit up under the
   letters and not at the foot of their box. */
.lede b {
  font-weight: 600;
  color: var(--text);
  background:
    linear-gradient(var(--accent), var(--accent)) 0 calc(100% - 4px) / 100% 2px no-repeat,
    linear-gradient(var(--accent-edge), var(--accent-edge)) 0 calc(100% - 2px) / 100% 2px no-repeat;
}

/* One per featured event; the rule above each is its separator. */
.featured { padding: calc(var(--gap) * 3) 0; border-top: 2px solid var(--line); }
.featured > header { display: flex; align-items: center; gap: calc(var(--gap) * 1.5); margin-bottom: calc(var(--gap) * 2); }
/* Whatever its shape, fitted whole into the same square. */
.logo { flex: none; width: 84px; height: 84px; object-fit: contain; }
.featured h2 { margin: 10px 0 4px; font-size: 1.5em; }
.featured header p { margin: 0; }

/* Four columns and four equal rows. Tracks are fixed, so a line can be as
   long as the tracks it crosses; rows are equal, so the middle of any span of
   them is known. */
.bracket {
  --join: 48px;
  --col: 15.5rem;
  --rows: calc(var(--gap) * 2);

  display: grid;
  grid-template-columns: repeat(4, var(--col));
  grid-auto-rows: 1fr;
  justify-content: center;
  gap: var(--rows) var(--join);
}

.ub-s1 { grid-area: 1 / 1; }
.ub-s2 { grid-area: 2 / 1; }
.lb-q1 { grid-area: 3 / 1; }
.lb-q2 { grid-area: 4 / 1; }
.lb-s { grid-area: 3 / 2 / span 2; }
.ub-f { grid-area: 1 / 3 / span 2; }
.lb-f { grid-area: 3 / 3 / span 2; }
.gf { grid-area: 1 / 4 / span 4; }

/* Stretched over the rows that feed it, the card in the middle. */
/* minmax(0, ...) so a long pair of names is cut short, not the card widened. */
.bracket > div { position: relative; display: grid; grid-template-columns: minmax(0, 1fr); align-content: center; }

.match {
  position: relative;
  background: var(--surface);
  border: 2px solid var(--line);
  box-shadow: 0 4px 0 var(--line);
}

.match h3 {
  margin: 0;
  padding: 6px 10px;
  font-size: 0.7em;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--muted);
  background: var(--bg);
  border-bottom: 2px solid var(--line);
}

/* One line; a pair of names too long for the card is cut short. */
.teams {
  margin: 0;
  padding: 8px 10px 0;
  overflow: hidden;
  font-size: 0.9em;
  white-space: nowrap;
  text-overflow: ellipsis;
  color: var(--muted);
}
.teams b { color: var(--text); }
.teams span { font-size: 0.85em; }

/* The maps are the point of a card: one full-width button each, the score an aside. */
.maps { display: grid; gap: 4px; padding: 10px; }
/* Laid out here and not by the button rule, so a placeholder lines its score
   up exactly as a button does. */
.map { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 8px 14px; min-height: 0; }
.map small { font-size: 0.8em; font-weight: 400; color: var(--muted); }
.map small b { color: var(--text); }
.map i { font-size: 0.8em; font-style: normal; font-weight: 400; color: var(--muted); }

/* A series on its own: its maps side by side across the page, no card. */
.maps.series { grid-template-columns: repeat(auto-fit, minmax(13.5em, 1fr)); gap: var(--gap); padding: 0; }
.featured header b { color: var(--text); }
/* A name never breaks from its mode. */
.map > span, .map small { white-space: nowrap; }
/* A map as a card: its picture, then the way in. */
.tile {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 8px;
  padding: 8px;
  background: var(--surface);
  border: 2px solid var(--line);
  box-shadow: 0 4px 0 var(--line);
}

.shot { display: block; width: 100%; aspect-ratio: 16 / 9; object-fit: cover; border: 2px solid var(--line); }

/* A map and the golden cap that decided it, on one line. */
.stack { display: flex; gap: 6px; }
/* Two on a line is tight: less padding. */
.stack .map { flex: 1; min-width: 0; padding-inline: 10px; }
.stack .cap { flex: none; justify-content: center; }

/* Not recorded: the same shape, flat and dashed, so nothing looks pressable. */
span.map { margin-bottom: 4px; font-weight: 600; color: var(--muted); border: 2px dashed var(--line); }

.bracket ::before, .bracket ::after { position: absolute; border: 0 solid var(--line); }

/* Two into one: a bracket from the middle of each feeding half, a quarter of
   what is left once the gap between the halves is taken out, as the arrows
   above find theirs. */
.lb-s::before, .ub-f::before, .gf::before {
  --mid: calc((100% - var(--rows)) / 4);

  content: "";
  top: var(--mid);
  bottom: var(--mid);
  left: calc(-1 * var(--join));
  width: calc(var(--join) / 2);
  border-width: 2px 2px 2px 0;
}

/* The upper final's feeders are two columns back, past the lower semifinal's. */
.ub-f::before { left: calc(-2 * var(--join) - var(--col)); width: calc(1.5 * var(--join) + var(--col)); }

/* The stub from that bracket's middle to the card. */
.lb-s .match::before, .ub-f .match::before, .gf .match::before {
  content: "";
  top: 50%;
  right: 100%;
  width: calc(var(--join) / 2);
  margin: -1px 2px 0 0;
  border-top-width: 2px;
}

/* One into one: straight across the gap. */
.lb-f .match::before {
  content: "";
  top: 50%;
  right: 100%;
  width: var(--join);
  margin: -1px 2px 0 0;
  border-top-width: 2px;
}

/* Too narrow for the tree: the cards in a column, and no lines. */
@media (max-width: 1180px) {
  .bracket { grid-template-columns: minmax(0, 24em); grid-auto-rows: auto; }
  .bracket > div { grid-area: auto; }
  .bracket ::before, .bracket ::after { display: none; }
}

@media (max-width: 1100px) {
  .home { grid-template-columns: minmax(0, 1fr); gap: calc(var(--gap) * 4); padding: 6vh 0; }
  .home { --mark: clamp(1.8rem, 8.5vw, 5rem); }
  .flow { margin-top: 0; }
}

@media (max-width: 500px) {
  .flow { --loop: 40px; --curl: 56px; }
  .step { font-size: 1em; }
}

/* The lifts and sinks are decoration; anyone who asked for less motion gets
   the same page standing still. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; }
  .wordmark [aria-hidden] span:hover, .wordmark [aria-hidden] span:active,
  .loop:hover, .loop:active, .site-header .brand:hover, .site-header .brand:active { transform: none; }
}

/* Narrow screens. Everything above lays the site out for a desktop; from here
   down it is taken apart, widest change first. */

/* A table wider than its pane scrolls inside it and leaves the page alone. */
.pane { overflow-x: auto; }

/* Beside the controls there is room for one name a row, not two. */
@media (max-width: 1400px) {
  .team.red, .team.blu { grid-template-columns: minmax(0, 1fr); }
}

/* Too narrow for teams either side of the controls: the controls across the
   top, the teams side by side under them, two names a row again. */
@media (max-width: 1100px) {
  .player-row { grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-rows: none; }
  .player-controls, .team.other, .watching { grid-column: 1 / -1; }
  .team.red, .team.blu { grid-row: auto; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .team.red { grid-column: 1; }
  .team.blu { grid-column: 2; }
}

/* The header on two rows, and scrolling away with the page: brand and
   account, then the nav. body::before is the sticky header's edge. */
@media (max-width: 1000px) {
  .site-header { position: static; flex-wrap: wrap; gap: 4px calc(var(--gap) * 2); height: auto; padding-block: 8px; }
  .site-header nav { order: 3; flex: 1 0 100%; flex-wrap: wrap; gap: 0 calc(var(--gap) * 2); }
  .site-header nav a { padding: 10px 0; }
  .site-header > .row, .site-header > .btn { margin-left: auto; }
  body::before { display: none; }
}

@media (max-width: 600px) {
  .player-controls { grid-template-columns: minmax(0, 1fr); }
  .transport > button { padding-inline: 4px; }
  /* A whole name on each button matters more than a short list. */
  .team.red, .team.blu { grid-template-columns: minmax(0, 1fr); }
  /* Match, when, and the way in; the rest is on the session page. */
  #demo-list :is(th, td):is(:nth-child(2), :nth-child(4), :nth-child(5)) { display: none; }
  #my-queue :is(th, td):nth-child(2) { display: none; }
}

@media (max-width: 400px) {
  .flow { --curl: 44px; --loop: 32px; }
}

/* A finger, or a screen too small for a keyboard to be likely: no shortcut
   hints, and controls tall enough to hit. */
@media (pointer: coarse), (max-width: 600px) {
  button > kbd, .btn > kbd { display: none; }
  .player-panel button { min-height: 44px; }
  input[type="range"] { height: 24px; }
}

/* iOS zooms the page on focusing a field set smaller than this. */
@media (pointer: coarse) {
  input, select, textarea { font-size: 16px; }
}

/* A phone on its side: the whole picture on screen at once. */
@media (orientation: landscape) and (max-height: 500px) {
  .player video { max-height: calc(100dvh - 2 * var(--gap)); }
}
