/* --------------------------------------------------------------------------
   Match settings — the shape of the game, set in the lobby
   -------------------------------------------------------------------------- */
.wf-match { display: flex; flex-direction: column; gap: 10px; }
.wf-match-line {
  margin: 0;
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
}
#match-controls { display: flex; flex-direction: column; gap: 12px; }
.wf-choice { border: none; margin: 0; padding: 0; min-width: 0; }
.wf-choice legend {
  padding: 0 0 6px;
  font-family: var(--font-display);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.2em;
  color: var(--muted);
}
.wf-choice-row { display: flex; gap: 6px; flex-wrap: wrap; }
/* Same chamfered family as every other control, at the size of a chip. The
   chosen one is filled, not merely outlined — colour is never the only
   channel, so it also carries aria-checked. */
.wf-opt {
  position: relative;
  isolation: isolate;
  appearance: none;
  border: none;
  padding: 9px 14px;
  min-width: 62px;
  background: var(--btn-edge);
  color: var(--ink);
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.12em;
  cursor: pointer;
  clip-path: polygon(0 0, calc(100% - 8px) 0, 100% 8px, 100% 100%, 8px 100%, 0 calc(100% - 8px));
  transition: background 0.15s ease, color 0.15s ease;
}
.wf-opt::before {
  content: "";
  position: absolute;
  inset: 1.5px;
  z-index: -1;
  clip-path: inherit;
  background: var(--chip);
  transition: inset 0.12s ease, background 0.15s ease;
}
.wf-opt:hover { background: var(--accent); }
.wf-opt.is-on { background: var(--accent); color: var(--on-status); }
.wf-opt.is-on::before { background: var(--accent); }
.wf-opt:focus-visible { outline: none; background: var(--accent); }
.wf-opt:focus-visible::before { inset: 3.5px; }
.wf-opt.is-on:focus-visible::before { background: var(--accent); }

/* The menu's worked example. It borrows .wf-row and .tile wholesale, so what it
   shows is literally the game's own board at a smaller --wc-tile — nothing to
   keep in sync, and no chance of it drifting from what play actually looks
   like. Six rows always, and the finished round stays up. */
.wf-demo {
  --wc-tile: 34px;
  --wc-tgap: 5px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  margin-top: 2px;
  padding-top: 16px;
  border-top: 1px solid var(--rule);
}
.wf-demo-board {
  display: flex;
  flex-direction: column;
  gap: var(--wc-tgap);
}
.wf-demo-cap {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.2em;
  color: var(--muted);
}
@media (max-height: 760px) {
  .wf-demo { --wc-tile: 29px; --wc-tgap: 4px; padding-top: 12px; }
}
@media (max-height: 620px) {
  .wf-demo { --wc-tile: 24px; --wc-tgap: 3px; gap: 7px; padding-top: 10px; }
}
@media (max-height: 470px) {
  .wf-demo { display: none; }   /* the menu itself has to fit first */
}

/* The lobby reads as three things, in the order you need them: how to invite
   people, what the match is, and who is here. Each one is a titled block with
   its own rule above, so the eye can skip to the one it wants instead of
   wading through a single column of controls. */
.wf-block { display: flex; flex-direction: column; gap: 10px; }

/* THE LOBBY IS TWO PANELS, and they are the whole screen.
 *
 *   LEFT   the invite box, and the match setup underneath it — everything you
 *          DO to get a room going, in the order you do it.
 *   RIGHT  who is in the room, and the button that waits on them.
 *
 * The invite used to run full width across the top with match and players
 * squeezed into half of a 520px column each, which made three cramped bands
 * instead of two readable ones. Left is now the doing, right is the room.
 *
 * The 520px cap on .wf-stage exists for the BOARD — five tiles inside a
 * thumb's reach — and applies to every other screen. The lobby is read and
 * operated rather than tapped at speed, so it opts out via `is-lobby` on the
 * body (set in app.js beside is-playing). Below 56rem it collapses to one
 * column in DOM order, which is already invite → setup → room. */
body.is-lobby .wf-stage { max-width: 60rem; }

@media (min-width: 56rem) {
  #wf-lobby {
    display: grid;
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
    grid-template-areas:
      "lead   lead"
      "idle   idle"
      "invite players"
      "match  players";
    /* NOT align-items:start — the right panel must stretch to the full height
       of the left one, because its left border IS the separator between the
       two. Sized to content it would stop wherever the roster happened to
       end, and a rule that stops halfway reads as a mistake. */
    column-gap: 0;
    row-gap: 0;
  }
  #lobby-instruction { grid-area: lead; }
  #wf-idle           { grid-area: idle; }
  #wf-invite         { grid-area: invite; }
  #wf-match          { grid-area: match; }
  #wf-players        { grid-area: players; }

  /* The breathing room either side of the separator. On the invite box it has
     to be a MARGIN, outside the frame: as padding it grew the card until its
     own border sat exactly on the rule, and two lines a pixel apart read as
     one broken one rather than a card beside a divider. #wf-match draws no
     frame, so padding is right there — it keeps the rule above it running all
     the way to the junction. */
  #wf-invite { margin-right: 28px; }
  #wf-match  { padding-right: 28px; }
  #wf-players {
    padding-left: 28px;
    padding-top: 13px;                /* card padding + its 1px frame, so both
                                         headings sit on one line */
    border-left: 1px solid var(--rule);
    border-top: none;
  }
  /* THE LEFT COLUMN DOES NOT GROW WITH THE RIGHT ONE.
     #wf-players spans both rows and must stretch, because its left border is
     the separator — but with the grid stretching everything, a room filling up
     made the roster taller, which made the rows taller, which pulled the
     invite box and the match settings open with it. The invite card got taller
     every time somebody joined. These two keep their own height; the empty
     space simply falls below them. */
  #wf-invite, #wf-match { align-self: start; }

  /* the setup sits under the invite box in the same column, so it keeps a
     rule above it — the two are different jobs, not one long form */
  #wf-match { padding-top: 18px; margin-top: 18px; border-top: 1px solid var(--rule); }
  /* Nothing is set on #wf-invite here on purpose. It used to carry
     `border-top: none; padding-top: 0`, meant to cancel the .wf-block divider
     — but that divider needs a .wf-block immediately before it and the only
     thing before the invite box is the lead paragraph, so the rule never
     applied and the override only ever hit the card's OWN frame. The result
     was an open-topped box with its heading sitting in the gap, which reads
     as a cropped header rather than a card. */
}
.wf-block + .wf-block { padding-top: 16px; border-top: 1px solid var(--rule); }
.wf-block > h2 {
  font-family: var(--font-display);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.2em;
  color: var(--muted);
  margin: 0;
}
/* The invite box is the loudest thing in the lobby and does not need to be:
   the code is read once, at a glance, from across a table at most. Sized down
   about an eighth from its first version so it clears the separator and sits
   under the two-panel grid instead of straining against it. The buttons take
   the size the narrow layout already gives them, which also lets all three
   copy controls sit on one row rather than wrapping SHARE onto a second. */
.wf-invite-box {
  position: relative;              /* the copy confirmation overlays inside it */
  border: 1px solid var(--rule);
  border-radius: 10px;
  background: var(--chip);
  padding: 12px 14px;
  margin: 0;
  gap: 8px;
}
.wf-invite-box .btn { padding: 11px 20px; font-size: 12px; }
/* the invite block carries its own frame, so it does not take the divider */
.wf-block.wf-invite-box + .wf-block { border-top: none; padding-top: 4px; }
.wf-invite-box > summary {
  cursor: pointer;
  list-style: none;
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  color: var(--accent-text);
}
.wf-invite-box > summary::-webkit-details-marker { display: none; }
.wf-invite-box > summary::before { content: "+ "; }
.wf-invite-box[open] > summary::before { content: "\2212 "; }
.wf-code {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(26px, 9vw, 39px);
  letter-spacing: 0.24em;
  text-indent: 0.24em;
  color: var(--accent-text);
  margin: 8px 0 6px;
  line-height: 1;
}
.wf-code-inline { font-family: var(--font-display); font-weight: 700; letter-spacing: 0.2em; color: var(--accent-text); }
.wf-url {
  width: 100%;
  padding: 9px 11px;
  border: 1px solid var(--rule);
  border-radius: 9px;
  background: var(--bg);
  color: var(--muted);
  font-family: var(--font-body);
  font-size: 13px;
  text-overflow: ellipsis;
}
/* The field CUSTOM opens. Sits under its own preset row rather than inside it:
   it is not one of the radios, and arrow keys walking the group must not land
   on a text box. */
.wf-custom {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 10px 0 0;
  font-size: 12px;
  color: var(--muted);
}
.wf-custom label { font-family: var(--font-display); letter-spacing: 0.12em; }
.wf-num {
  width: 5.5rem;
  padding: 8px 10px;
  border: 1px solid var(--rule);
  border-radius: 8px;
  background: var(--field-bg, var(--bg));
  color: var(--ink);
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.wf-num:focus-visible { outline: 2px solid var(--accent-text); outline-offset: 2px; }
.wf-custom-hint { font-size: 11px; }

/* One line under the mode chooser saying what the chosen one feels like.
   Reserved height rather than a paragraph that appears and disappears: the
   two blurbs are the same length by design, but a mode added later might not
   be, and settings that shove the card while you are reading them are the
   thing .wf-copy-said below was written to stop. */
.wf-mode-blurb {
  margin: 6px 0 0;
  min-height: 1.2em;
  font-size: 11px;
  line-height: 1.2;
  color: var(--muted);
}

/* Said under the copy buttons, and said WITHOUT MOVING ANYTHING.
 *
 * As an ordinary paragraph it pushed the note beneath it down the moment it
 * appeared and pulled it back up when it went, so confirming a copy shoved the
 * card people were reading. `position: absolute` with no top/left keeps it at
 * exactly the place it would have occupied in the flow — its static position —
 * while taking it out of that flow, so it lays over the text below instead of
 * displacing it. A pill, in the same ink-on-background as the game's toast, so
 * it is legible over whatever it covers.
 *
 * Faded rather than hidden: `hidden` cannot transition. `visibility` is
 * delayed out so the fade finishes before it is taken away, and so it is not
 * read aloud while invisible. */
.wf-copied {
  position: absolute;
  /* Anchored to the bottom of the card, NOT left to fall where it would have
     sat in the flow. The invite box is a flex column, and inside one an
     absolutely positioned child's static position is the container's content
     origin rather than its place among its siblings — so with `auto` offsets
     this landed on top of the room code, which is the one thing in the box
     nobody may cover. Down here it lays over the paragraph about who can join,
     which can wait three seconds. */
  left: 50%;
  bottom: 13px;
  max-width: calc(100% - 28px);
  z-index: 3;
  margin: 0;
  padding: 7px 13px;
  border-radius: 9px;
  background: var(--ink);
  color: var(--bg);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-align: center;
  box-shadow: var(--shadow-toast);
  opacity: 0;
  visibility: hidden;
  transform: translate(-50%, 5px);
  transition: opacity 0.18s ease, transform 0.18s ease, visibility 0s linear 0.18s;
}
.wf-copied.is-on {
  opacity: 1;
  visibility: visible;
  transform: translate(-50%, 0);
  transition-delay: 0s;
}
/* a failure is asking the reader to do something, so it is not a quiet tick */
.wf-copied.is-bad { background: var(--accent); color: var(--on-status, var(--bg)); }

.wf-invite-row { display: flex; flex-direction: column; gap: 10px; margin: 0 0 10px; }
.wf-invite-btns { display: flex; gap: 10px; flex-wrap: wrap; }

.wf-roster { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.wf-player {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 11px 0;
  border-bottom: 1px solid var(--rule);
}
.wf-player .nm {
  flex: 1;
  min-width: 0;
  font-weight: 600;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.wf-player .tag {
  font-family: var(--font-display);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.18em;
  color: var(--accent-text);
  border: 1px solid var(--rule);
  border-radius: 6px;
  padding: 3px 7px;
}
.wf-count { color: var(--muted); }

/* opponents, while a room round is running */
.wf-opps { width: 100%; }
.wf-opps h3 {
  font-family: var(--font-display);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.2em;
  color: var(--muted);
  margin: 0 0 8px;
}
#opps-list { display: flex; gap: 14px; overflow-x: auto; padding-bottom: 4px; }

