/*
 * 摘作业 — the page's own rules.
 *
 * The shell comes from app.css, which this page links even though it runs none
 * of the scatter engine: the column, topbar, brand mark, buttons, status line
 * and the panel itself are the family's, and a second copy of them here is a
 * second copy that drifts. What is left for this file is the one control app.css
 * has no opinion about — the paste box — and the grouped checklist the answer
 * arrives in.
 *
 * One thing is borrowed outright rather than restated: the checkbox. The rows
 * use app.css's `.chip-box` exactly as the other two pages do, because it *is*
 * the same control — a 4px-radius box with a tick that scales in — and only the
 * states around it (`.row[aria-pressed]`) are this page's.
 */

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

/*
 * The input is a textarea rather than the single-line field the other tools
 * use, and that is the whole difference between this page and them: their input
 * is a sentence describing what you want, this one is a message you already
 * have, and it arrives with its own line breaks. Those line breaks are
 * structure the splitter reads, so the box has to keep them.
 */
.compose {
  display: flex;
  flex-direction: column;
  gap: var(--s3);
}

.compose textarea {
  width: 100%;
  padding: var(--s5) var(--s6);
  font: inherit;
  /* 16px, same as the other tools' input, and not for looks: iOS zooms the page
     when a control smaller than 16px takes focus, and a page that jumps on the
     tap that starts the interaction is a page that feels broken. */
  font-size: var(--t5);
  line-height: 1.65;
  color: var(--text);
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  /* Resizable downward only in effect: a notice is longer than six rows often
     enough that the handle is worth having, and the handle is the browser's. */
  resize: vertical;
  transition: border-color var(--dur-fast) var(--ease);
}

.compose textarea::placeholder {
  color: var(--text-faint);
  /* The placeholder is two lines of example. Without this they run together
     into one sentence when the box is wide enough to fit them side by side. */
  white-space: pre-line;
}

.compose textarea:focus {
  outline: none;
  border-color: var(--primary);
}

.compose textarea:disabled {
  opacity: 0.6;
}

/*
 * The example sits left and the action sits right: a preset is a way to avoid
 * the work, and the primary button is the work. `margin-right: auto` rather
 * than space-between so that when the sample button is disabled mid-request it
 * does not drag the primary button leftward with it.
 */
.compose-foot {
  display: flex;
  align-items: center;
  gap: var(--s3);
}

.compose-foot .quick-btn {
  margin-right: auto;
}

/* --------------------------------------------------------------- checklist */

/*
 * The panel follows the form directly on this page instead of being pushed to
 * the floor of the first screen, so it needs a top margin — app.css gives it
 * only a bottom one, because there it sits above the pile and the gap it needs
 * is underneath. See index.html for why the layout differs.
 */
#panel:not([hidden]) {
  margin-top: var(--s6);
}

/*
 * Columns, not a single stack, because of the width the panel is given: the
 * shell's column is 1180px, and a one-item-per-line list at that width is a
 * line of text followed by 900px of nothing five times over. The three groups
 * sit side by side and share the width instead.
 *
 * Flex, not `repeat(auto-fit, minmax(230px, 1fr))`, and that is not a style
 * preference — the grid version was measured and left two groups at 274px each
 * with 570px of empty panel beside them. `auto-fit` creates the tracks the
 * container can hold, collapses the empty ones, and does *not* hand their space
 * to the survivors, so a result with two groups instead of three is a result
 * with a third of the panel blank. `flex-grow` does exactly the opposite, which
 * is what a set of columns of unknown count actually wants.
 *
 * The 260px basis is the wrap point, not a width: below roughly a phone and a
 * half the groups stack, and above it they share the line. `min-width: 0` is
 * required because a flex item refuses to shrink below its content, and one
 * long notice line would otherwise widen its column past its share.
 */
.groups {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s5);
}

.group {
  flex: 1 1 260px;
  min-width: 0;
}

.group-head {
  display: flex;
  align-items: baseline;
  gap: var(--s3);
  /* Aligned with the checkbox column of the rows below it rather than with
     their text: the heading labels the column, and the boxes are its edge. */
  margin: 0 0 var(--s2);
  padding: 0 var(--s4);
  font-size: var(--t3);
  font-weight: 650;
  color: var(--text-dim);
}

.group-count {
  font-size: var(--t1);
  font-weight: 500;
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
}

.rows {
  display: flex;
  flex-direction: column;
  /* 2px, not the 10px of a button row: these are lines of a list, and the
     grouping above them is what separates one set from the next. */
  gap: 2px;
}

.row {
  display: flex;
  /* flex-start, not center: a homework item wraps to two lines often, and the
     box belongs beside the first line, not floating halfway down the row. */
  align-items: flex-start;
  gap: var(--s4);
  width: 100%;
  min-width: 0;
  padding: var(--s3) var(--s4);
  border-radius: var(--radius);
  text-align: left;
  transition: background var(--dur-fast) var(--ease);
}

/* Nudges the 18px box onto the first line's baseline. */
.row .chip-box {
  margin-top: 2px;
}

.row-text {
  min-width: 0;
  font-size: var(--t4);
  color: var(--text);
  /* A class number run or a long URL is one word as far as the line breaker is
     concerned, and `anywhere` is the only value that will break inside it. */
  overflow-wrap: anywhere;
}

.row:hover {
  background: var(--bg-hover);
}

/*
 * Same reading as the other tools' list: the checked rows are the list, and the
 * emphasis goes on the *unchecked* ones.
 *
 * Filling every ticked row with the brand colour was the first version there
 * and it failed the same way it would here — on a real result most rows are
 * ticked, so the tint stops marking anything and the eye slides off the whole
 * panel. The state worth finding is the exception, which is the row the user
 * just turned off.
 */
.row[aria-pressed='false'] {
  background: var(--bg-sunken);
}

.row[aria-pressed='false'] .row-text {
  color: var(--text-faint);
}

.row[aria-pressed='false']:hover {
  background: var(--bg-hover);
}

/* The two halves of the tick that app.css's `.list .chip` rules would have
   supplied, restated for the states this page actually has. */
.row[aria-pressed='true'] .chip-box {
  background: var(--primary);
  border-color: var(--primary);
}

.row[aria-pressed='true'] .chip-box::after {
  transform: rotate(-45deg) scale(1);
}

/*
 * Rows arrive staggered, which is the whole of this page's motion. There is no
 * pile for them to fly out of, so a flight would be a lie about where they came
 * from; a short rise says "these were just made" without pretending they moved
 * from anywhere. `--i` is set per row by buildRow(), capped at 16.
 */
@keyframes row-in {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
}

@media (prefers-reduced-motion: no-preference) {
  .row {
    /* `both` holds the from-state through the delay; without it every row
       flashes at full opacity and then animates. */
    animation: row-in var(--dur) var(--ease) both;
    animation-delay: calc(var(--i, 0) * 24ms);
  }
}

/* ------------------------------------------------------- pieces not used */

/*
 * Takes a line of its own under the columns rather than becoming one of them —
 * it is a footnote to the whole result, not a fourth group.
 */
.dropped {
  flex: 0 0 100%;
  padding: 0 var(--s4);
  font-size: var(--t2);
  color: var(--text-faint);
}

.dropped summary {
  padding: var(--s2) 0;
  color: inherit;
  cursor: pointer;
  border-radius: var(--radius);
}

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

.dropped ul {
  margin: var(--s2) 0 0;
  padding-left: var(--s6);
  list-style: disc;
}

.dropped li {
  margin: 2px 0;
  overflow-wrap: anywhere;
}

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

@media (max-width: 560px) {
  /* The groups need no rule here — the 260px basis already wraps them one per
     line below roughly this width. */

  /* The sample button drops to its own line and the action takes the rest of
     it, the same shape the other tools' prompt bar collapses into. */
  .compose-foot {
    flex-wrap: wrap;
  }

  .compose-foot .quick-btn {
    margin-right: 0;
  }

  .compose-foot .btn {
    flex: 1;
  }
}

/* ------------------------------------------------------------------ touch */

/*
 * Same reasoning as the block in app.css: only a finger needs these, and the
 * 560px query above cannot tell a phone from a narrow window.
 */
@media (hover: none) {
  /*
   * A to-do line is read while walking, and 37px was under the fingertip
   * minimum — so was the noise disclosure, which is a tap target people hit
   * with a thumb while holding a phone one-handed.
   */
  .row,
  .dropped summary {
    min-height: 44px;
  }

  /* The group counts are the only text on the page still under 12px; at arm's
     length they read as specks. */
  .group-count {
    font-size: var(--t2);
  }
}
