/*
 * 闺蜜团 — the page's own rules.
 *
 * The shell comes from app.css (column, topbar, brand mark, buttons, the input
 * row, status line, panel and its head/foot) and the checkbox free-rides on it
 * too, the same way 摘作业's rows do. What is left for this file is what no
 * other page has: a second, quieter input for the options, the roster of
 * friends, and the two things the answer is made of — a joint verdict and one
 * card per friend.
 */

/* ---------------------------------------------------------------- compose */

.compose {
  display: flex;
  flex-direction: column;
  gap: var(--s3);
}

/* -------------------------------------------------------------- the options */

/*
 * The options field is deliberately below the dilemma and quieter than it.
 *
 * It is the optional half of the input, and a form that does not distinguish
 * required from optional makes people fill in the optional part. So: smaller
 * text, muted ink, a hairline border and no shadow — the same "preset" register
 * as the example buttons in app.css, which is the register for things that are
 * there if you want them.
 */
.opts {
  width: 100%;
  padding: var(--s4) var(--s5);
  font: inherit;
  font-size: var(--t3);
  color: var(--text-dim);
  background: transparent;
  border: 1px dashed var(--border-soft);
  border-radius: var(--radius-lg);
  transition:
    border-color var(--dur-fast) var(--ease),
    color var(--dur-fast) var(--ease);
}

.opts::placeholder {
  color: var(--text-faint);
}

.opts:focus {
  outline: none;
  color: var(--text);
  border-color: var(--primary);
  border-style: solid;
}

.opts:disabled {
  opacity: 0.6;
}

/* ------------------------------------------------------------------ guess */

/*
 * The bet, sitting between the options and the roster.
 *
 * Deliberately not styled like a form field: no border, no background, just a
 * small line and the same pills the offline rung uses. It has to be visible
 * enough to be played and quiet enough that skipping it does not feel like
 * leaving something blank — the tool's real input is the dilemma above it.
 */
.guess {
  display: flex;
  flex-direction: column;
  gap: var(--s2);
  margin-top: var(--s2);
  padding: 0 var(--s2);
}

.guess-label {
  font-size: var(--t2);
  color: var(--text-dim);
}

/* The verdict of the bet, under the friends' verdict. */
.guess-result {
  margin: 0;
  font-size: var(--t3);
  color: var(--text-dim);
}

.guess-result b {
  color: var(--text);
}

.guess-result[data-hit='true'] b {
  color: var(--brand);
}

/* ------------------------------------------------------------------ roster */

.roster-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-top: var(--s2);
  padding: 0 var(--s2);
  font-size: var(--t2);
  color: var(--text-dim);
}

.roster-count {
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
}

/*
 * Flex with a wrapping basis rather than a grid of fixed tracks: the roster is
 * six items wide at most and the count is what matters, so the row should fill
 * whatever width it is given instead of leaving a hole at the end.
 */
.roster {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
}

/*
 * A friend in the roster is a small capsule — emoji, name, and the one line
 * that says what she weighs. The tagline is on the chip rather than revealed on
 * selection because choosing between six friends by name alone is choosing
 * between six words; 「清醒姐」 says nothing about *when* to pick her, 「只看一年后」
 * does.
 */
.friend {
  display: flex;
  align-items: baseline;
  gap: var(--s2);
  padding: var(--s2) var(--s5);
  font-size: var(--t3);
  color: var(--text-dim);
  background: var(--bg-card);
  border: 1px solid var(--border-soft);
  border-radius: 999px;
  transition:
    color var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease),
    background var(--dur-fast) var(--ease),
    opacity var(--dur-fast) var(--ease);
}

.friend .friend-emoji {
  font-size: var(--t4);
  line-height: 1;
}

.friend .friend-name {
  font-weight: 600;
  color: var(--text);
}

.friend .friend-tag {
  font-size: var(--t1);
  color: var(--text-faint);
}

.friend:hover:not(:disabled) {
  border-color: var(--primary);
}

/*
 * Selected is the filled state, unlike the checklist rows in app.css where the
 * emphasis goes on the *unselected* ones. The difference is what the states
 * mean: there, most rows are correct and the exception is interesting; here the
 * default is three of six and the interesting thing is which three, so the
 * chosen ones are the ones that should be legible at a glance.
 */
.friend[aria-pressed='true'] {
  background: var(--primary-soft);
  border-color: var(--primary);
}

.friend[aria-pressed='true'] .friend-tag {
  color: var(--text-dim);
}

/* At the cap, the unselected chips dim instead of disappearing: a friend who
   vanishes when you pick a fourth reads as a bug, a dimmed one reads as "one at
   a time". */
.friend:disabled {
  opacity: 0.4;
  cursor: default;
}

/* --------------------------------------------------------------- verdict */

.verdict {
  display: flex;
  flex-direction: column;
  gap: var(--s3);
  padding: 0 var(--s3) var(--s6);
}

.verdict-line {
  margin: 0;
  font-size: var(--t5);
  font-weight: 650;
}

.verdict-line .verdict-option {
  color: var(--brand);
}

/*
 * The split bar: one segment per option, width proportional to the votes, in
 * the order the options are offered. It is a bar chart with no axis, and the
 * counts are written underneath it — the bar is what gets read first, the
 * numbers are what settle an argument about it.
 */
.tally {
  display: flex;
  flex-direction: column;
  gap: var(--s2);
}

.tally-bar {
  display: flex;
  gap: 2px;
  height: 8px;
}

.tally-seg {
  border-radius: 999px;
  background: var(--bg-sunken);
}

.tally-seg[data-on='true'] {
  background: var(--primary);
}

.tally-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s5);
  font-size: var(--t2);
  color: var(--text-dim);
}

.tally-legend b {
  font-variant-numeric: tabular-nums;
  color: var(--text);
}

/* The joint reading of the five misreadings: shown here, once, when the friends
   agree — see the render rule in bestie.js for why it is not repeated per card. */
.verdict-note {
  margin: 0;
  font-size: var(--t3);
  color: var(--text-dim);
}

/* ---------------------------------------------------------------- cards */

.cards {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s5);
}

/*
 * Columns, not a stack, for the reason 摘作业's groups share the panel: the
 * shell's column is 1180px and one friend per line at that width is a card and
 * a half-screen of nothing. `flex: 1 1 260px` rather than a grid, so two or
 * three cards fill the row instead of leaving collapsed tracks empty.
 */
.card {
  flex: 1 1 260px;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--s3);
  padding: var(--s5);
  background: var(--bg-card);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-lg);
}

.card-head {
  display: flex;
  align-items: baseline;
  gap: var(--s3);
}

.card-emoji {
  font-size: var(--t5);
  line-height: 1;
}

.card-name {
  font-weight: 650;
}

.card-tag {
  font-size: var(--t1);
  color: var(--text-faint);
}

/*
 * Her vote, as a badge. Pushed to the right edge and never wrapped: the badge is
 * the one thing on the card that has to be findable without reading, because
 * comparing six badges is how the page is actually used.
 */
.card-vote {
  margin-left: auto;
  padding: 2px var(--s4);
  font-size: var(--t1);
  font-weight: 600;
  white-space: nowrap;
  color: var(--primary-ink);
  background: var(--primary-soft);
  border-radius: 999px;
}

/* The friend did not answer and the person is answering for her: the badge would
   be a claim, so there is none. */
.card-vote[data-simulated='true'] {
  color: var(--text-dim);
  background: var(--bg-sunken);
  font-weight: 500;
}

.card-line {
  margin: 0;
  font-size: var(--t4);
  color: var(--text);
}

.card-misread {
  margin: 0;
  padding-top: var(--s2);
  font-size: var(--t3);
  color: var(--text-dim);
  border-top: 1px dashed var(--border-soft);
}

.card-ask {
  margin: 0;
  font-size: var(--t3);
  color: var(--text-dim);
}

/* ------------------------------------------------------- the distribution */

/*
 * The segmented bar behind her vote: one segment per option, proportional to
 * the probability the model returned. Exported from the API rather than derived
 * from the pick, because two very different distributions — 0.25/0.51/0.24 and
 * 0.34/0.33/0.33 — produce the same vote, and the shape is the honest part.
 *
 * A fixed 132px rather than the card's width, and that is not a detail: a bar
 * that stretches to fill a 260px card reads as a progress bar or a rule, and the
 * whole point of this one is that its *shape* is comparable between cards. Four
 * friends with four 132px charts can be read against each other at a glance;
 * four full-width bars cannot.
 *
 * Decorative in the accessibility tree: the sentence above already carries the
 * claim, and a bar chart read aloud is a list of numbers nobody asked for.
 */
.dist {
  display: flex;
  gap: 2px;
  width: 132px;
  height: 4px;
  border-radius: 999px;
  overflow: hidden;
}

.dist-seg {
  min-width: 2px;
  background: var(--border-soft);
}

.dist-seg[data-on='true'] {
  background: var(--primary);
}

/* ------------------------------------------------------- picking for her */

/*
 * The offline rung: the model did not answer, so each friend's question is put
 * to the person herself. Pills rather than a select, because tapping the answer
 * is the whole interaction and a dropdown hides the options behind a tap that
 * does not look like the answer.
 */
.pick-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
}

.pick {
  padding: var(--s2) var(--s4);
  font-size: var(--t2);
  color: var(--text-dim);
  background: var(--bg-card);
  border: 1px solid var(--border-soft);
  border-radius: 999px;
  transition:
    color var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease),
    background var(--dur-fast) var(--ease);
}

.pick:hover {
  color: var(--text);
  border-color: var(--primary);
}

.pick[aria-pressed='true'] {
  color: var(--primary-ink);
  background: var(--primary-soft);
  border-color: var(--primary);
}

/* Cards rise in, staggered — the same entrance 摘作业's rows use, and for the
   same reason: these were just made, and there is nowhere for them to have
   come from. */
@keyframes card-in {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
}

@media (prefers-reduced-motion: no-preference) {
  .card {
    animation: card-in var(--dur) var(--ease) both;
    animation-delay: calc(var(--i, 0) * 40ms);
  }
}

/* Suppressed once the table is being filled in by hand: the entrance means "this
   just arrived", and it is not true of a tap on the third friend's pill. */
.cards.settled .card {
  animation: none;
}

/* -------------------------------------------------------------- the options */

/* The example row sits between the question and the options, so it needs less
   room above it than app.css's margin gives — the form is one column of four
   rows and a gap is a gap. */
.quick {
  margin-top: 0;
}

/* ---------------------------------------------------------------- narrow */

@media (max-width: 560px) {
  /*
   * The input row collapses differently here than in app.css.
   *
   * There, the button takes the remaining width on a narrow screen, which is
   * right for the other tools: their input holds a short phrase and the button
   * is the action. A dilemma is a full sentence and this field is the page's
   * main input — measured at 390px with that rule, it showed nine characters and
   * cut the question in half while the button took half the row. So the button
   * drops to its own line and the input keeps the row, the same shape 摘作业's
   * compose-foot collapses into.
   */
  .bar input {
    flex: 1 1 100%;
  }

  /* The roster already wraps; what needs help is the friend chip, which at this
     width drops its tagline to a second line rather than being squeezed. */
  .friend {
    align-items: center;
  }

  .roster-head {
    padding: 0;
  }

  .verdict {
    padding: 0 0 var(--s5);
  }

  .panel-foot {
    flex-direction: column;
  }

  .panel-foot .btn {
    width: 100%;
  }
}
