/* Screens 02 Public rooms, 03 Create room, 04 Room lobby. */

.link {
  color: var(--muted);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.link:hover {
  color: var(--text-dim);
}

/* The message bar. It has no padding of its own: it occurs both on a bare
   screen and inside a column of fields, and fields glued to it pushed it out of
   the row — in the lobby it ended up narrower than everything standing around
   it. The padding provides the room it was placed in. Still, it has to be
   zeroed explicitly: this is a paragraph, and without the declaration the
   browser's own `1em` top and bottom returns, and in the lobby column such
   fields do not collapse, so the gap around the bar comes out half again as
   wide as between everything else. */
.banner {
  margin: 0;
  font-size: 14px;
  line-height: 1.5;
  color: var(--muted);
  background: var(--sunken);
  border: 1px solid var(--border);
  border-radius: var(--r-ui);
  padding: 12px 14px;
}

/* And on a bare screen there is nowhere to put it: it lies right between the
   title bar and the content, and holds its own vertical rhythm — along the
   title bar's edge. */
.screen > .banner {
  margin: 16px 24px;
}

.banner--error {
  color: var(--danger-fg);
  background: var(--danger-bg);
  border-color: transparent;
}

/* ── fields ──────────────────────────────────────────────────────────────── */

.field {
  background: var(--sunken);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-ui);
  color: var(--text);
  font: inherit;
  font-size: 17px;
  padding: 14px 16px;
  width: 100%;
}

.field::placeholder {
  color: var(--muted-3);
}

.field:focus {
  outline: none;
  border-color: #5a5a5a;
}

.field--sm {
  font-size: 14px;
  padding: 11px 14px;
  width: 190px;
}

.field-group {
  display: flex;
  flex-direction: column;
  gap: 9px;
}

.field-group__label {
  font-size: 11px;
  letter-spacing: 0.12em;
  color: #7a7a7a;
}

.choice,
.diskpick {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.choice__item {
  font: inherit;
  font-size: 14px;
  padding: 10px 14px;
  border: 0;
  border-radius: var(--r-ui);
  background: #2b2b2b;
  color: var(--muted);
  cursor: pointer;
}

.choice__item--on {
  background: var(--primary-bg);
  color: var(--primary-fg);
}

/* ── 02 Public rooms ─────────────────────────────────────────────────────── */

.listing__title {
  font-size: 18px;
  letter-spacing: -0.01em;
}

.listing__tools {
  display: flex;
  gap: 10px;
  align-items: center;
  flex-wrap: wrap;
}

.listing__grid {
  /* The same side padding as the title bar: otherwise the heading and the
     first tile stand on different verticals. */
  padding: 20px 24px 32px;
  display: grid;
  /* The grid computes its columns itself from the tile's readable width: at
     900 that comes to three — the same width as in the 1280 mockup — and on a
     phone, one. This way the threshold does not have to be kept in mind
     separately from the page width. */
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 16px;
}

/* The "more" button.

   It stands below the grid rather than above it: a list is read top to
   bottom, and its continuation belongs at the bottom. The grid loses its own
   bottom padding at the same time — otherwise a fifty-pixel gap opens between
   the last tile and the button, and the button stops reading as a continuation
   of the same list. */
.listing__grid:has(+ .more) {
  padding-bottom: 0;
}

.more {
  display: flex;
  justify-content: center;
  padding: 20px 24px 32px;
}

/* In the disk picker box the button occupies the list's last row and lives by
   its rules: full width, no padding of its own. */
.diskpick .more {
  padding: 4px 0 0;
}

.diskpick .more .btn {
  width: 100%;
}

@media (max-width: 760px) {
  .more {
    padding: 16px 16px 28px;
  }
}

/* ── an empty shelf ────────────────────────────────────────────────────────
   The same padding as the tile grid: the placeholder stands exactly where the
   first tile would, and the move from an empty screen to a full one shifts
   nothing.

   The border is dashed — the only one in the interface: an ordinary border
   says "there is something here", this one says "something will stand here".
   */
.empty {
  margin: 20px 24px 32px;
  padding: 48px 24px 44px;
  border: 1px dashed var(--border);
  border-radius: var(--r-panel);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 10px;
}

/* The disk here is paler than in the lists: this is a place for it, not the
   disk itself. */
.empty__art {
  --disk-ink: #383838;
  --disk-edge: #3a3a3a;
  margin-bottom: 12px;
}

.empty__title {
  font-size: 17px;
  color: var(--text-dim);
}

.empty__note {
  /* The explanation line must not spread the full width of the card: a long
     line centred is harder to read than a short one. */
  max-width: 42ch;
  font-size: 14px;
  line-height: 1.5;
  color: var(--muted-2);
}

.empty__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  margin-top: 14px;
}

.tile {
  background: var(--sunken);
  border: 1px solid var(--border);
  border-radius: var(--r-panel);
  padding: 22px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.tile__status {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 11px;
  letter-spacing: 0.1em;
}

.tile__state {
  color: var(--ok-fg);
}

.tile__state--running {
  color: #e0e0e0;
}

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

.tile__title {
  font-size: 20px;
  letter-spacing: -0.015em;
}

.tile__disk {
  display: flex;
  gap: 12px;
  align-items: center;
}

.tile__diskmeta {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 13px;
  color: #d4d4d4;
  min-width: 0;
}

.tile__hash {
  color: var(--muted-3);
  font-size: 11px;
}

/* The caption beneath a tile: in the library that is the author and the
   disk's dimensions. The class used to be called `tile__host` — after the
   line with the room creator's nickname, which no longer exists. */
.tile__meta {
  font-size: 13px;
  color: var(--muted-2);
}

/* ── ghost tiles ──────────────────────────────────────────────────────────
   Bars stand where content will go while the list is on its way from the
   server. The shape repeats the real tile: the list's arrival must not shift
   anything.

   One flat colour — a ghost reads as room for content, not as content itself.
   The pulse is shared across every bar: a highlight running along each row
   individually would turn waiting into a spectacle. */

.tile--ghost,
.diskpick__item--ghost {
  pointer-events: none;
}

.ghost {
  display: block;
  border-radius: var(--r-ui);
  background: #2a2a2a;
  animation: ghost-pulse 1.5s ease-in-out infinite;
}

/* The gap between the bars of one paragraph is taken from real lines' leading
   (13px × 1.45), not eyeballed. */
.ghost__lines {
  display: flex;
  flex-direction: column;
  gap: 10px;
  flex: 1;
  min-width: 0;
}

/* The heights are taken from real lines, not eyeballed: a tile's heading is
   20px, a description line is 13px, a button with its own padding is 40px. */
.ghost--title {
  height: 20px;
  width: 62%;
}

.ghost--line {
  height: 11px;
  width: 100%;
}

.ghost--line-md {
  width: 72%;
}

.ghost--line-sm {
  width: 44%;
}

.ghost--chip {
  height: 12px;
  width: 84px;
  border-radius: var(--r-chip);
}

.ghost--chip-sm {
  width: 46px;
}

.ghost--btn {
  height: 40px;
  width: 100%;
}

.ghost--field {
  height: 38px;
  width: 190px;
}

/* In the disk's place stands the disk itself, not a shape standing in for it.
   Dimmed to the bars' colour: a ghost must read as room for content, but the
   shape of that room is exactly what will appear. The two-class selector beats
   `.disk`, which sets its own colours. */
.ghost__disk {
  display: flex;
  flex: 0 0 auto;
}

.ghost__disk .disk {
  /* A ghost disk is a silhouette, not an outline: with a single border in the
     bars' colour it would get lost against the tile's backing. The body is
     filled with the same tone as the bars, and its inner details are taken in
     the tile's colour — they read as cutouts, and the disk's shape stays
     recognisable while depicting nothing. */
  --disk-ink: var(--sunken);
  --disk-edge: #2a2a2a;
  background: #2a2a2a;
  animation: ghost-pulse 1.5s ease-in-out infinite;
}

.ghost__disk .disk__shutter {
  background: var(--sunken);
}

@keyframes ghost-pulse {
  0%,
  100% {
    opacity: 1;
  }

  50% {
    opacity: 0.45;
  }
}

/* Not everyone needs the blinking, and it is not always useful: the bars
   remain, only the motion goes. */
@media (prefers-reduced-motion: reduce) {
  .ghost {
    animation: none;
  }
}

.btn--wide {
  width: 100%;
  text-align: center;
}

.btn--danger {
  background: var(--danger-bg);
  color: var(--danger-fg);
}

/* A disk is the one place the mockup is allowed to be retro.
   A component from the design: everything is computed from a single quantity,
   `--size`, so the same element lives honestly both at 40 pixels in a list and
   at 260 on the landing screen. The 1:1.06 ratio, 13% padding, a 15% shutter, a
   7.5% bar — none of it eyeballed, all of it taken from Disk.dc.html. */
.disk {
  --size: 42px;
  --disk-edge: #3d3d3d;
  --disk-ink: #4a4a4a;
  width: var(--size);
  height: calc(var(--size) * 1.06);
  flex: none;
  box-sizing: border-box;
  border: 1px solid var(--disk-edge);
  border-radius: var(--r-ui);
  background: rgba(255, 255, 255, 0.025);
  padding: max(4px, calc(var(--size) * 0.13));
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: calc(var(--size) * 0.09);
}

.disk__top {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 8%;
}

.disk__patch {
  width: calc(var(--size) * 0.46);
  height: max(5px, calc(var(--size) * 0.2));
  background: var(--disk-ink);
  border-radius: var(--r-chip);
  flex: none;
}

.disk__shutter {
  width: max(6px, calc(var(--size) * 0.15));
  aspect-ratio: 1;
  border: 1px solid var(--disk-edge);
  border-radius: var(--r-chip);
  flex: none;
}

.disk__bar {
  height: max(5px, calc(var(--size) * 0.075));
  background: var(--disk-ink);
  border-radius: var(--r-chip);
}

/* The mockup shows the caption only at large sizes — at small ones it is
   unreadable anyway, and it still takes up room. */
.disk__caption {
  font-family: var(--font-mono);
  font-size: 13px;
  color: #d4d4d4;
  margin-top: auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── 03 Create room ──────────────────────────────────────────────────────── */

.form {
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 22px;
}

.form__title {
  font-size: 17px;
}

.diskpick {
  flex-direction: column;
}

.diskpick__item {
  display: flex;
  gap: 14px;
  align-items: center;
  text-align: left;
  font: inherit;
  background: var(--sunken);
  border: 1px solid var(--border);
  border-radius: var(--r-ui);
  padding: 14px 16px;
  color: var(--text);
  cursor: pointer;
}

.diskpick__item--on {
  border-color: #5a5a5a;
  background: #262626;
}

.diskpick__meta {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 15px;
  min-width: 0;
}

.diskpick__sub {
  font-size: 13px;
  color: var(--muted-2);
}

/* ── what a disk gets ────────────────────────────────────────────────────
   Two columns: granted and blocked. On a narrow screen, one, and granted comes
   first: that is the news for a person. */

.grants {
  padding: 18px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.grants__label {
  font-size: 11px;
  letter-spacing: 0.12em;
  color: var(--warn-fg);
}

.grants__cols {
  display: flex;
  gap: 22px;
}

.grants__col {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* A row of the list. Not a button and does not look like one: there is
   nothing to choose here. */
.grants__row {
  display: flex;
  gap: 9px;
  align-items: flex-start;
  font-size: 14px;
  color: #c4c4c4;
}

.grants__mark {
  width: 12px;
  flex: none;
}

.grants__mark--yes {
  color: var(--ok-fg);
}

.grants__mark--no {
  color: var(--danger-fg);
}

.grants__text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.grants__hint {
  font-size: 12px;
  line-height: 1.35;
  color: var(--muted-3);
}

@media (max-width: 560px) {
  .grants__cols {
    flex-direction: column;
    gap: 10px;
  }
}

/* ── 04 Room lobby ───────────────────────────────────────────────────────── */

.lobby__title {
  font-size: 17px;
}

.lobby__code {
  font-size: 13px;
  color: var(--muted);
  background: #2b2b2b;
  padding: 7px 11px;
  border-radius: var(--r-ui);
  letter-spacing: 0.08em;
}

.lobby {
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 22px;
}

.inserted {
  display: flex;
  gap: 18px;
  align-items: center;
  padding: 18px;
}

.inserted__meta {
  display: flex;
  flex-direction: column;
  gap: 7px;
  flex: 1;
  min-width: 0;
}

.inserted__line {
  font-size: 16px;
}

.inserted__sub {
  font-size: 13px;
  color: var(--muted-2);
}

.inserted__tags {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

/* The verification panel.

   The one place where the verification badge is not an icon in a card's
   corner but a paragraph: in the library a disk is examined, here it is one
   press away from running on your own machine. Set off with a bar on the left,
   it steps out of the row of otherwise-identical lobby panels, but stays a
   panel — a badge shouting louder than the "Run disk" button would stop reading
   after the third room.

   Colour carries only the tone: the meaning lives entirely in the words, and
   on a monochrome screen the panel loses exactly the bar's hue. */
.verdict {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 16px 18px;
  border-left: 3px solid var(--border-strong);
}

.verdict__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.verdict__title {
  font-size: 17px;
  letter-spacing: 0.08em;
}

.verdict__kind {
  font-size: 11px;
  letter-spacing: 0.12em;
  color: var(--muted-3);
}

.verdict__lead {
  margin: 0;
  font-size: 14px;
  line-height: 1.5;
  color: var(--muted);
}

.verdict__points {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* The marker is drawn as a pseudo-element rather than a list bullet: a
   browser bullet has its own indent, and it will not line up with the rest of
   the text's left edge. */
.verdict__point {
  position: relative;
  padding-left: 16px;
  font-size: 13px;
  line-height: 1.45;
  color: #c4c4c4;
}

.verdict__point::before {
  content: '—';
  position: absolute;
  left: 0;
  color: var(--muted-3);
}

.verdict__foot {
  margin: 0;
  font-size: 12px;
  line-height: 1.45;
  color: var(--muted-3);
}

.verdict--ok {
  border-left-color: var(--ok-fg);
}

.verdict--ok .verdict__title {
  color: var(--ok-fg);
}

.verdict--warn {
  border-left-color: var(--warn-fg);
  background: var(--warn-bg);
}

.verdict--warn .verdict__title {
  color: var(--warn-fg);
}

.verdict--danger {
  border-left-color: var(--danger-fg);
  background: var(--danger-bg);
}

.verdict--danger .verdict__title {
  color: var(--danger-fg);
}

@media (max-width: 460px) {
  .verdict__head {
    flex-direction: column;
    gap: 4px;
  }
}

.seats {
  display: grid;
  /* `minmax(0, 1fr)`, not `1fr`: with `1fr` the minimum equals the content,
     and one long name pushed its column apart, stealing room from its
     neighbours. The ellipsis on `.seat__nick` never fired at all in that case —
     there was nothing to cut, since its width was granted on request. */
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px;
}

.seat {
  background: var(--sunken);
  border: 1px solid var(--border);
  border-radius: var(--r-panel);
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: center;
  /* The same reason as the columns: without the zero, room is claimed for the
     width of the longest word inside. */
  min-width: 0;
}

.seat__avatar {
  width: 34px;
  height: 34px;
  border-radius: var(--r-ui);
  background: #3d3d3d;
}

.seat__avatar--1 { background: #4a4a4a; }
.seat__avatar--2 { background: #5a5a5a; }
.seat__avatar--3 { background: #333; }
.seat__avatar--4 { background: #46504a; }
.seat__avatar--5 { background: #504a46; }
.seat__avatar--6 { background: #4a4650; }
.seat__avatar--7 { background: #465050; }

.seat__nick {
  font-size: 13px;
  color: var(--text-dim);
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.seat__badges {
  display: flex;
  gap: 6px;
  align-items: center;
  flex-wrap: wrap;
  justify-content: center;
}

.seat__badge {
  font-size: 9px;
  letter-spacing: 0.1em;
  color: var(--muted-3);
}

.seat__badge--host {
  color: var(--warn-fg);
}

.seat__badge--ready {
  color: var(--ok-fg);
}

/* The disk is mounted. That is a fact about the frame, not about the game's
   progress: what is happening inside it is not something the platform
   knows. */
.seat__badge--playing {
  color: var(--ok-fg);
  background: var(--ok-bg);
  border-radius: var(--r-chip);
  padding: 3px 6px;
}

.btn--on {
  background: var(--ok-bg);
  color: var(--ok-fg);
}

/* The mark on the button. The room for the sign is constant, and the sign is
   centred inside it: a tick and a cross are different widths, and without this
   the button would change size on its own press. The cross is dimmed — it is
   not a refusal but "not yet". */
.btn__mark {
  display: inline-block;
  width: 1em;
  margin-left: 6px;
  text-align: center;
  color: var(--muted);
}

.btn__mark--on {
  color: inherit;
}

.btn--on:hover {
  background: #2c3a2c;
}

.roomlog {
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 9px;
}

.roomlog__lines {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 14px;
  color: var(--muted);
  max-height: 160px;
  overflow-y: auto;
}

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

.lobby__actions {
  display: flex;
  gap: 10px;
}

/* "Ready" keeps its own width, the main button takes the rest of the row.
   Without this its neighbour's `width: 100%` squeezed "Ready" until it wrapped,
   and its tick moved to a second line, stretching both buttons twice as
   tall. */
.lobby__actions > .btn {
  flex: none;
  white-space: nowrap;
}

.lobby__actions > .btn--wide {
  flex: 1;
  width: auto;
}

.joinbox {
  display: flex;
  gap: 8px;
  align-items: center;
}

/* ── M1 Rooms mobile ─────────────────────────────────────────────────────── */

@media (max-width: 760px) {
  .listing__grid {
    padding: 16px 16px 28px;
  }

  /* The same padding as the grid: the placeholder and the tiles stand on one
     vertical. */
  .empty {
    margin: 16px 16px 28px;
    padding: 36px 18px 32px;
  }

  /* Full-width buttons: they no longer fit in one row, and a stack of
     different-width buttons centred looks ragged. */
  .empty__actions {
    flex-direction: column;
    align-self: stretch;
  }

  /* The platform header must stay readable: it is what tells the diskroom
     interface from what a disk could draw. We shrink it, but do not hide
     it. */
  .topbar {
    padding: 12px 16px;
    gap: 10px;
  }

  .topbar__left {
    gap: 12px;
  }

  .nav {
    gap: 0;
    font-size: 13px;
    min-width: 0;
  }

  .nav a {
    padding: 8px 10px;
  }

  .nav__me {
    font-size: 13px;
  }

  .listing__tools {
    width: 100%;
  }

  .joinbox {
    flex: 1;
  }

  .joinbox .field {
    flex: 1;
    width: auto;
  }

  .screen__head {
    min-height: 60px;
    padding: 10px 16px;
  }

  .form,
  .lobby {
    padding: 16px;
  }

  .seats {
    grid-template-columns: repeat(2, 1fr);
  }

  .field--sm,
  .ghost--field {
    width: 100%;
  }
}

/* On a phone the header parts with what can be learned another way: the
   platform's name next to the logo, and the nickname as text. What remains is
   the platform's mark, the sections, "New room" and the profile square — that
   is, navigation and identification. Hiding the header entirely is not allowed:
   on the room screen it is exactly what tells the platform from a disk's
   drawing. */
@media (max-width: 560px) {
  /* The name next to the mark goes, but the nickname does not: the platform's
     mark is recognised without a caption, while nothing can replace the
     nickname. */
  .brand__name {
    display: none;
  }

  /* The header stays one row at any width. Wrapping the buttons made it 62
     pixels here, 100 there — the height depended on which page you were on, and
     the content beneath it jumped on every transition. Short captions replace
     the wrap. */
  .topbar {
    min-height: 57px;
    padding: 8px 16px;
  }

  /* Measured, not eyeballed: at 390 the header row is 71 pixels short.
     The "Studio" section gives back 58, the tightened padding another
     twenty or so. */
  .nav__studio {
    display: none;
  }

  .nav a {
    padding: 8px 6px;
  }

  .wide-only {
    display: none;
  }

  .narrow-only {
    display: inline;
  }

  .topbar__action {
    padding: 9px 10px;
  }

  .topbar__me {
    padding-left: 8px;
  }

  /* On a phone the ceiling for the name is lower: there is one row, and it has
     to be shared with the sections and two buttons. */
  .nav__me {
    max-width: 10ch;
  }

  .topbar__left {
    gap: 8px;
  }
}

/* The chosen disk sits as a separate panel above the list. It must stay in
   view always: inside a scrollable list the choice slides off the edge, and a
   person loses sight of the one thing that matters here.

   It is styled the same way as a chosen row inside the list — a light border
   and a raised background. The same look means the same thing: "this one". */
.diskpick__chosen {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
  background: #262626;
  border: 1px solid #5a5a5a;
  border-radius: var(--r-panel);
}

.diskpick__chosen .diskpick__meta {
  flex: 1;
  font-size: 15px;
}

/* The list is its own box with its own heading, separate from the chosen one.
   Without this boundary the chosen disk and the rows it is chosen from run
   together in one flow, and which of them is already chosen shows only by the
   highlight. */
.diskpick__browse {
  border: 1px solid var(--border);
  border-radius: var(--r-panel);
  overflow: clip;
}

.diskpick__browsehead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  padding: 12px 14px;
  background: var(--sunken);
  border-bottom: 1px solid var(--border);
}

/* The disk list grows, but the form does not. The height is held, then it
   scrolls: otherwise the twentieth disk pushes the "Open room" button off
   screen. `nowrap` is mandatory: a height-limited column with wrapping allowed
   lays itself out into several columns, and the list slides sideways. */
.diskpick {
  flex-wrap: nowrap;
  gap: 0;
  max-height: 232px;
  overflow-y: auto;
  scrollbar-gutter: stable;
}

/* Inside the box the rows are separated by lines rather than gaps: that way
   it reads as one list, not a stack of separate cards. */
.diskpick__browse .diskpick__item {
  border: 0;
  border-bottom: 1px solid var(--border);
  border-radius: 0;
  background: transparent;
}

.diskpick__browse .diskpick__item:last-child {
  border-bottom: 0;
}

.diskpick__browse .diskpick__item:hover {
  background: #262626;
}

/* The chosen row now stays in the list, so it must be visible, and visible
   differently from the row under the cursor: both used to be #262626, that is,
   "chosen" and "currently hovered" looked identical. A lighter backing plus a
   bar at the left edge, and the same thing under the cursor too — otherwise
   hovering erases the choice. */
.diskpick__browse .diskpick__item--on,
.diskpick__browse .diskpick__item--on:hover {
  background: #2f2f2f;
  box-shadow: inset 3px 0 0 #7d7d7d;
}

/* The verification badge stands at the right edge, one column for the whole
   list: otherwise it chases the description and lands in a new spot on every
   row. */
.diskpick__browse .diskpick__meta {
  flex: 1;
}

.diskpick__browse .diskpick__item > .tag {
  flex: none;
}

.diskpick__empty {
  padding: 14px 16px;
  font-size: 13px;
  color: var(--muted-2);
}

/* ── a single disk's page ──────────────────────────────────────────────── */

.diskpage {
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 22px;
}

.diskpage__head {
  display: flex;
  gap: 22px;
  align-items: flex-start;
}

/* The column's rhythm: the name and its line of small details sit close, and
   everything else has air around it. An equal gap between every row turned the
   card into an even stack where nothing relates to anything else. */
.diskpage__title {
  font-size: 24px;
  letter-spacing: -0.015em;
}

.diskpage__title + .diskpage__sub {
  margin-top: -10px;
}

.diskpage__meta {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 14px;
  min-width: 0;
}

.diskpage__sub {
  font-size: 14px;
  color: var(--muted-2);
}

.diskpage__about {
  font-size: 15px;
  line-height: 1.5;
  color: #c4c4c4;
}

.diskpage__by {
  font-size: 13px;
  color: var(--muted-2);
}

/* The hash is shown in full: it is the disk's name, and the whole of it is
   what gets compared. On a narrow screen it wraps rather than gets truncated —
   a truncated name is worse than a long one. */
.diskpage__hash {
  font-size: 13px;
  color: var(--muted);
  word-break: break-all;
  background: var(--sunken);
  border: 1px solid var(--border);
  border-radius: var(--r-ui);
  padding: 10px 12px;
}

.diskpage__source {
  margin: 0;
  max-height: 420px;
  overflow: auto;
  font-size: 13px;
  line-height: 1.55;
  color: #c4c4c4;
  background: var(--sunken);
  border: 1px solid var(--border);
  border-radius: var(--r-panel);
  padding: 16px;
  white-space: pre;
}

@media (max-width: 620px) {
  .diskpage__head {
    flex-direction: column;
  }
}

/* The code field: it is short, typed by hand and read out loud — large and
   letter-spaced so the letters do not blur together while checking it. */
.field--code {
  font-size: 24px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
}
