/* Word cloud: layout and components.
   Mobile first. Almost everyone using this is on a phone in a hall, and the
   one person who is not is projecting the display view. */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--wc-bg);
  color: var(--wc-text);
  font-family: var(--wc-body);
  font-size: 1rem;
  line-height: 1.5;
  min-height: 100vh;
  min-height: 100dvh;
}

h1, h2, h3 {
  font-family: var(--wc-display);
  font-weight: 800;
  line-height: 1.1;
  margin: 0;
  letter-spacing: -0.01em;
}
h1 { font-size: clamp(2rem, 7vw, 3rem); }
h2 { font-size: clamp(1.35rem, 4.5vw, 1.75rem); }

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

/* ── Layout ── */

.wrap {
  width: 100%;
  max-width: 46rem;
  margin: 0 auto;
  padding: var(--wc-s4);
}
.narrow { max-width: 32rem; }
.stack > * + * { margin-top: var(--wc-s4); }
.center { text-align: center; }

.topbar {
  border-bottom: 1px solid var(--wc-line);
  background: var(--wc-bg-2);
}
.topbar-inner {
  max-width: 46rem;
  margin: 0 auto;
  padding: var(--wc-s3) var(--wc-s4);
  display: flex;
  align-items: baseline;
  gap: var(--wc-s3);
  flex-wrap: wrap;
}
.brand {
  font-family: var(--wc-display);
  font-weight: 800;
  font-size: 1.25rem;
  color: var(--wc-text);
  text-decoration: none;
}
.brand span { color: var(--wc-accent); }

.panel {
  background: var(--wc-bg-2);
  border: 1px solid var(--wc-line);
  border-radius: var(--wc-r-lg);
  padding: var(--wc-s5);
}

.muted { color: var(--wc-muted); }
.tiny  { font-size: 0.8125rem; }
.hidden { display: none !important; }

/* ── Controls ── */

label {
  display: block;
  font-weight: 600;
  font-size: 0.875rem;
  margin-bottom: var(--wc-s2);
}

input[type="text"], select {
  width: 100%;
  padding: var(--wc-s3);
  font: inherit;
  color: var(--wc-text);
  background: var(--wc-bg-3);
  border: 1px solid var(--wc-line);
  border-radius: var(--wc-r);
}
input[type="text"]:focus-visible, select:focus-visible {
  outline: 2px solid var(--wc-accent);
  outline-offset: 1px;
}
input::placeholder { color: var(--wc-muted); }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--wc-s2);
  width: 100%;
  padding: var(--wc-s3) var(--wc-s4);
  font: inherit;
  font-weight: 600;
  color: var(--wc-bg);
  background: var(--wc-accent);
  border: 1px solid transparent;
  border-radius: var(--wc-r);
  cursor: pointer;
  /* Some buttons are anchors, so the link styling has to be undone here. */
  text-decoration: none;
  /* Nothing on this page should ever be small enough to miss with a thumb. */
  min-height: 3rem;
}
.btn:hover { filter: brightness(1.08); }
.btn:disabled { opacity: 0.5; cursor: default; }
.btn.secondary {
  color: var(--wc-text);
  background: var(--wc-bg-3);
  border-color: var(--wc-line);
}

.row { display: flex; gap: var(--wc-s3); align-items: flex-end; }
.row > * { flex: 1; }
.row > .shrink { flex: 0 0 auto; width: auto; }

.err {
  padding: var(--wc-s3) var(--wc-s4);
  border-radius: var(--wc-r);
  background: rgba(245, 101, 101, 0.12);
  border: 1px solid var(--wc-bad);
  color: var(--wc-text);
}

/* ── The join code ──
   Read off a projector from the back of a hall, so it is as big as it can be
   without wrapping, and monospaced so O and 0 cannot be confused. The code
   alphabet excludes both anyway, but the shape helps people trust it. */

.code {
  font-family: var(--wc-num);
  font-weight: 700;
  letter-spacing: 0.12em;
  font-size: clamp(2rem, 11vw, 3.5rem);
  color: var(--wc-accent);
  word-break: break-all;
}

.link-box {
  display: flex;
  gap: var(--wc-s2);
  align-items: center;
  padding: var(--wc-s3);
  background: var(--wc-bg-3);
  border: 1px solid var(--wc-line);
  border-radius: var(--wc-r);
  font-size: 0.875rem;
  word-break: break-all;
}

/* ── Cloud list on the home page ── */

.cloud-list { list-style: none; margin: 0; padding: 0; }
.cloud-list li + li { margin-top: var(--wc-s2); }
.cloud-list a {
  display: flex;
  justify-content: space-between;
  gap: var(--wc-s3);
  align-items: center;
  padding: var(--wc-s3);
  background: var(--wc-bg-3);
  border: 1px solid var(--wc-line);
  border-radius: var(--wc-r);
  color: var(--wc-text);
  text-decoration: none;
}
.cloud-list .code-tag {
  font-family: var(--wc-num);
  font-size: 0.8125rem;
  color: var(--wc-accent);
}

/* ── The bubble field ──

   A wrapping field of pills, not a spiral word cloud. A spiral re-solves its
   whole layout whenever anything is added or resized, which during live use
   would make bubbles jump under a thumb mid tap. This reflows gracefully, and
   every bubble stays a comfortable target at any size. */

.field {
  display: flex;
  flex-wrap: wrap;
  gap: var(--wc-s2) var(--wc-s3);
  justify-content: center;
  align-items: center;
  padding: var(--wc-s4) 0;

  /* The size range the scale factor maps onto. Kept modest on a phone on
     purpose: the point of the field is that you can scan a dozen ideas at once
     and tap the ones you match with, and two or three giant pills per screen
     would lose that entirely. */
  --bubble-min: 0.9rem;
  --bubble-max: 1.6rem;
}

@media (min-width: 40rem) {
  .field { --bubble-max: 2.1rem; }
}

/* The tap field. Every bubble the same size on purpose: this one is a list to
   work through, not a picture. Uniform size keeps it dense enough to scan a
   lot of ideas at once, gives every idea the same chance of being noticed
   rather than burying the new ones, and stops the layout reflowing as counts
   change while somebody is tapping. Growth is shown in the preview above the
   input and on the host's display, where nobody is aiming at anything. */
.field.uniform .bubble {
  font-size: 0.95rem;
  /* 44px, so a bubble is a comfortable thumb target however short its word
     is. Everything in this field is tapped, repeatedly and quickly. */
  min-height: 2.75rem;
  padding: 0.4em 0.9em;
}

button.bubble {
  cursor: pointer;
  user-select: none;
  /* Fast repeated tapping should not select the words or flash a grey box. */
  -webkit-tap-highlight-color: transparent;
}
button.bubble:focus-visible {
  outline: 2px solid var(--wc-text);
  outline-offset: 2px;
}
button.bubble:active { transform: scale(0.96); }

/* The preview above the input: the real cloud, scaled down to a glance.

   Height capped and faded out at the bottom, because this grows without limit
   and must never push the input or the tap field off the screen. It is a
   glance at the shape of the answer, not the record: the full cloud is the
   thing on the wall. */
.field.mini {
  --bubble-min: 0.6rem;
  --bubble-max: 1.15rem;
  gap: var(--wc-s1) var(--wc-s2);
  padding: 0;
  max-height: 24vh;
  overflow: hidden;
  mask-image: linear-gradient(to bottom, #000 76%, transparent 100%);
}

.field.mini .bubble {
  padding: 0.2em 0.6em;
  border-width: 1px;
}
.field.mini .bubble .n { font-size: 0.7em; }

.bubble {
  --hue: var(--wc-b1);
  --s: 0;
  font-size: calc(var(--bubble-min) + (var(--bubble-max) - var(--bubble-min)) * var(--s));
  /* A long phrase should wrap inside its own pill rather than force the pill
     wider than the screen. */
  max-width: 100%;
  display: inline-flex;
  align-items: baseline;
  gap: 0.45em;
  padding: 0.4em 0.85em;
  font-family: inherit;
  font-weight: 600;
  line-height: 1.25;
  color: var(--hue);
  background: color-mix(in srgb, var(--hue) 14%, transparent);
  border: 2px solid color-mix(in srgb, var(--hue) 45%, transparent);
  border-radius: var(--wc-r-pill);
  /* Font size is set inline per bubble, scaled by support. */
  transition: transform 180ms ease, background-color 180ms ease, border-color 180ms ease;
}

/* Entries you are behind, whether you added them or tapped them. Being able
   to see at a glance what you have already claimed is what makes scanning the
   field feel like collecting rather than reading. */
.bubble.mine {
  color: var(--wc-bg);
  background: var(--hue);
  border-color: var(--hue);
}

.bubble .n {
  font-family: var(--wc-num);
  font-size: 0.62em;
  opacity: 0.75;
}

/* Applied for one frame when a count changes, so growth is noticed. */
.bubble.pop { transform: scale(1.14); }

.field-empty {
  color: var(--wc-muted);
  padding: var(--wc-s5) 0;
  text-align: center;
}

/* ── Compose ── */

.compose {
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  background: var(--wc-bg);
  padding: var(--wc-s3) 0;
}

/* ── Host tidying ── */

.manage-bar {
  padding: var(--wc-s3);
  border-radius: var(--wc-r);
  background: var(--wc-bg-3);
  border: 1px solid var(--wc-accent);
}
.manage-bar p { margin: 0 0 var(--wc-s2); color: var(--wc-accent); }
/* Three actions have to fit one phone width without any of them wrapping to
   a second line, which reads as a broken layout mid moderation. */
.manage-bar .btn {
  font-size: 0.9rem;
  padding-inline: var(--wc-s2);
  white-space: nowrap;
}

/* The idea the host has picked. A dashed ring rather than a colour change, so
   it cannot be confused with the filled "you back this" state. */
.bubble.picked {
  outline: 3px dashed var(--wc-text);
  outline-offset: 3px;
}

/* While tidying, nothing in the field is a vote, so the filled state would
   only mislead. */
body.managing .field.uniform .bubble.mine {
  color: var(--hue);
  background: color-mix(in srgb, var(--hue) 14%, transparent);
  border-color: color-mix(in srgb, var(--hue) 45%, transparent);
}

/* The "did you mean" strip, between the input and the tap field. Tinted so it
   reads as a prompt rather than as more of the cloud. */
.suggest {
  padding: var(--wc-s3);
  border-radius: var(--wc-r);
  background: color-mix(in srgb, var(--wc-accent-2) 10%, var(--wc-bg-2));
  border: 1px solid color-mix(in srgb, var(--wc-accent-2) 40%, transparent);
}
.suggest p { margin: 0 0 var(--wc-s2); color: var(--wc-accent-2); }
.suggest .field { padding: 0; justify-content: flex-start; }

.toast {
  padding: var(--wc-s3);
  border-radius: var(--wc-r);
  background: var(--wc-bg-3);
  border: 1px solid var(--wc-line);
  font-size: 0.875rem;
}
.toast.bad { border-color: var(--wc-bad); }
.toast.good { border-color: var(--wc-good); }

/* ── Connection status ── */

.status {
  display: inline-flex;
  align-items: center;
  gap: var(--wc-s2);
  font-size: 0.8125rem;
  color: var(--wc-muted);
}
.status::before {
  content: '';
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--wc-muted);
}
.status.open::before { background: var(--wc-good); }
.status.reconnecting::before { background: var(--wc-accent-2); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}
