/* Sheets — slice 3 of 9 of the former components.css.

   ⚠️ LOAD ORDER IS PART OF THESE FILES. They are CONTIGUOUS slices of one
   6841-line sheet, cut at section banners and never re-sorted, so concatenating
   them in the order index.html lists them reproduces the original byte for byte
   — which is the proof the cascade did not shift. Moving a rule to a different
   slice throws that guarantee away. index.html and sw.js's SHELL_ASSETS must
   list all 9 in the same order as each other.

   Contents: Activity sheet + timer overlay, PIN gate, parent confirm queue, activity picker, parent settings panel, quest composer tree. */

/* ── Activity sheet + timer overlay ──────────────────────── */

.wu-sheet-backdrop,
.wu-timer-overlay {
  position: fixed;
  inset: 0;
  z-index: 400;
  background: color-mix(in srgb, var(--colour-text-primary) 32%, transparent);
  display: flex;
  align-items: center;
  justify-content: center;
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
}

/* ⚠️ A WIDTH CLAMPED AGAINST 100% IS A BORDER-BOX STATEMENT, and there is no
   global box-sizing reset here (#90). Content-box bounded only the MIDDLE, so
   the 40px padding either side and the 1px border sat OUTSIDE the clamp: on a
   375px phone `calc(100% - 64px)` asked for 311 of content and produced a
   393px BOX, which the backdrop's flex silently shrank to 375 — every sheet in
   the app edge to edge, with the gutter its own rule asks for nowhere on
   screen. Third instance of this trap (#98/v399 the rail drawer, #166 the
   confirm sheet), and the first one where the symptom was invisible because
   flex-shrink was covering for it.

   THE NUMBERS MOVED WITH THE FIX, so that no sheet ends up with LESS room than
   it has today — this is a bug fix, not a re-layout: 500px keeps a desktop
   sheet's content at ~418 (it was 420), and on a phone the padding drops to
   --space-lg so 351px of box still yields 301 of content (it was 293) while
   finally leaving a 12px gutter. */
.wu-sheet {
  box-sizing: border-box;
  position: relative;
  background: var(--colour-surface);
  border: 1px solid var(--colour-border);
  border-radius: var(--radius-card);
  padding: var(--space-xl);
  width: min(500px, calc(100% - var(--space-lg)));
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-md);
  box-shadow: 0 16px 48px rgba(0, 0, 0, 0.18);
  /* A SHEET IS NEVER TALLER THAN THE SCREEN (owner, batch item 2: "when
     creating a new book on mobile it does not allow to scroll"). The library's
     cover-maker measured 988px on an 812px phone, 88px off the top AND 88 off
     the bottom, with no way to reach either end — the ✕ and the Save button
     both unreachable. Nothing about that is specific to books: any sheet whose
     content grows (a long picker, a list, a translated label) has the same
     cliff, so the guarantee belongs on the sheet rather than on the one that
     was reported. --vh, never 100vh (§6). */
  max-height: calc(var(--vh) - var(--space-lg) * 2);
  overflow-y: auto;
  /* A modal that scrolls must not hand the scroll on to the page behind it
     once it hits its end. */
  overscroll-behavior: contain;
}
/* A 40px inset is a tenth of a phone's width from each side. The sheet keeps
   its dialog padding where there is room and takes the page's own inset where
   there is not — which is what buys back the content the gutter costs. */
@media (max-width: 480px) {
  .wu-sheet {
    padding: var(--space-lg);
  }
}

.wu-sheet-icon {
  font-size: 40px;
  line-height: 1;
}

.wu-sheet-icon-img {
  width: 44px;
  height: 44px;
  object-fit: contain;
  display: block;
}

.wu-confirm-icon-img {
  width: 26px;
  height: 26px;
  object-fit: contain;
  display: block;
}

.wu-sheet-title {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--font-size-lg);
  color: var(--colour-text-primary);
}

.wu-sheet-notes {
  width: 100%;
  resize: none;
  font-family: var(--font-body);
  font-size: var(--font-size-md);
  padding: var(--space-md);
  border: 1px solid var(--colour-border);
  border-radius: var(--radius-button);
  background: var(--colour-bg);
  color: var(--colour-text-primary);
  box-sizing: border-box;
}

.wu-sheet-notes:focus {
  outline: 2px solid var(--colour-accent);
  border-color: transparent;
}

.wu-sheet-label {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: var(--font-size-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--colour-text-secondary);
}

.wu-sheet-input {
  width: 100%;
  font-family: var(--font-body);
  font-size: var(--font-size-md);
  padding: var(--space-sm) var(--space-md);
  border: 1px solid var(--colour-border);
  border-radius: var(--radius-button);
  background: var(--colour-bg);
  color: var(--colour-text-primary);
  box-sizing: border-box;
}

.wu-sheet-input:focus {
  outline: 2px solid var(--colour-accent);
  border-color: transparent;
}

/* 🔑 Guest session sheet (decision #68). Only three rules: it is a normal
   sheet with a code field, and the less it invents the more it reads like the
   rest of the app. */
.wu-guest-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  font-size: var(--font-size-sm);
  color: var(--colour-text-secondary);
  text-align: left;
}
.wu-guest-input {
  font-family: var(--font-mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-align: center;
}
/* The one line that says the device gets wiped. Bold on the body colour, not a
   warm accent — see the contrast note on .wu-sync-warn (#121). */
.wu-guest-warn {
  margin: 0;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-bold);
  line-height: var(--line-height-relaxed, 1.5);
  color: var(--colour-text-primary);
  text-align: left;
}

.wu-sheet-actions {
  display: flex;
  gap: var(--space-md);
}

.wu-sheet-actions-col {
  flex-direction: column;
  width: 100%;
}

.wu-sheet-actions-col .wu-sheet-btn {
  width: 100%;
}

.wu-sheet-btn {
  /* Unified box model so a <button> and an <a> with this class render at the
     exact same size (the install sheet stacks one of each — without this the
     button's UA box model made it a different height than the APK link). */
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  text-decoration: none;
  line-height: var(--line-height-normal);
  padding: var(--space-md) var(--space-lg);
  font-family: var(--font-display);
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-bold);
  background: var(--colour-bg);
  color: var(--colour-text-primary);
  border: 1px solid var(--colour-border);
  border-radius: var(--radius-button);
  cursor: pointer;
  min-height: var(--tap-target-min);
}

.wu-sheet-btn:hover { border-color: var(--colour-accent); }

/* The commit button on a sheet — solid, so "which one do I press" is answered
   by weight rather than by reading both labels (#98's one-filled-control rule).
   White on solid accent, never accent-as-text on a tint: every warm accent in
   this palette measures under the 4.5:1 body-text floor that way (#121).
   MUST stay after .wu-sheet-btn — same specificity, so order decides. */
.wu-sheet-primary {
  background: var(--colour-accent);
  border-color: var(--colour-accent);
  color: #fff;
  font-weight: var(--font-weight-bold);
}
.wu-sheet-primary:hover { filter: brightness(1.05); }
.wu-sheet-primary:disabled { opacity: 0.6; cursor: default; }

/* iOS / generic "Add to Home Screen" guided steps */
.wu-install-steps {
  width: 100%;
  text-align: left;
  background: var(--colour-bg);
  border: 1px solid var(--colour-border);
  border-radius: var(--radius-button);
  padding: var(--space-sm) var(--space-md);
}

.wu-install-steps .wu-sheet-label {
  margin-bottom: var(--space-xs);
}

.wu-install-steps ol,
.wu-install-steps p {
  margin: 0;
  padding-left: 1.2em;
  font-size: var(--font-size-sm);
  color: var(--colour-text-primary);
  line-height: var(--line-height-normal);
}

.wu-install-steps p {
  padding-left: 0;
}

/* The line under a way to install that says where the board goes (#183). */
.wu-install-note {
  margin: var(--space-xs) 0 0;
  font-size: var(--font-size-sm);
  line-height: 1.4;
  color: var(--colour-text-secondary);
  text-align: left;
}

.wu-sheet-done {
  background: color-mix(in srgb, var(--colour-success) 18%, var(--colour-surface));
  border-color: var(--colour-success);
  color: var(--colour-success);
}

.wu-sheet-timer {
  background: color-mix(in srgb, var(--colour-accent) 14%, var(--colour-surface));
  border-color: var(--colour-accent);
  color: var(--colour-accent);
}

/* The corner control on every sheet — including the ✓ that COMMITS the language
   choice (decision #77), which makes it the least appropriate control in the
   app to be a 28px target. Grown to 44 (v290 audit). */
.wu-sheet-cancel {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: none;
  background: transparent;
  color: var(--colour-text-secondary);
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
}

.wu-sheet-cancel:hover { color: var(--colour-text-primary); }

/* ✓ variant — same corner button, but reads as "confirm my choice" (used on
   the avatar picker, where a pick applies immediately). */
.wu-sheet-cancel.wu-sheet-ok {
  color: var(--colour-success);
  background: color-mix(in srgb, var(--colour-success) 12%, transparent);
  font-weight: var(--font-weight-bold);
}
.wu-sheet-cancel.wu-sheet-ok:hover {
  background: color-mix(in srgb, var(--colour-success) 22%, transparent);
}

.wu-timer-display {
  font-family: var(--font-mono);
  font-size: var(--font-size-3xl);
  font-weight: var(--font-weight-bold);
  color: var(--colour-accent);
}

/* Countdown reached zero — chimed; child still taps Stop & finish */
.wu-timer-display.wu-timer-done {
  color: var(--colour-success);
  font-family: var(--font-display);
}

.wu-timer-notes {
  margin: 0;
  color: var(--colour-text-secondary);
  font-size: var(--font-size-sm);
  text-align: center;
}

/* ── PIN gate ────────────────────────────────────────────── */

.wu-pin-card {
  max-width: 320px;
}

.wu-pin-sub {
  margin: 0;
  font-size: var(--font-size-sm);
  color: var(--colour-text-secondary);
}

.wu-pin-dots {
  display: flex;
  gap: 14px;
  margin: var(--space-sm) 0;
}

.wu-pin-dot {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 2px solid var(--colour-border);
}

.wu-pin-dot-filled {
  background: var(--colour-accent);
  border-color: var(--colour-accent);
}

.wu-pin-pad {
  grid-template-columns: repeat(3, 64px);
  padding-bottom: 0;
}

.wu-pin-pad button {
  height: 52px;
}

.wu-pin-pad button[data-key="none"] {
  visibility: hidden;
}

.wu-pin-shake {
  animation: wu-shake 300ms ease;
}

.wu-pin-forgot {
  background: none;
  border: none;
  color: var(--colour-text-secondary);
  font-size: var(--font-size-xs);
  cursor: pointer;
  text-decoration: underline;
  padding: var(--space-xs);
}

.wu-pin-forgot:hover {
  color: var(--colour-text-primary);
}

/* ── Parent confirmation queue ───────────────────────────── */

/* THE QUEUE AS A SHEET (#166). The default .wu-sheet is 420px wide with 40px of
   padding and centres its children — right for a question with two buttons,
   wrong for a LIST: a confirm row carries an icon, two lines of text and two
   44px controls, which had 231px to do it in on a 375px phone. This variant is
   as wide as the list's own max (560px), pads like a panel rather than a
   dialog, and stretches its children so the rows use the full width.

   The LIST scrolls, not the sheet: the title and ⚙️ Parent settings must stay
   put while a long week's worth of rows moves under them. */
.wu-confirm-sheet {
  /* ⚠️ A WIDTH CLAMPED AGAINST 100% IS A BORDER-BOX STATEMENT, and there is no
     global box-sizing reset here (#90). Content-box bounds only the MIDDLE, so
     the 24px padding either side and the 1px border sat OUTSIDE the clamp:
     measured 325px of content rendering as a 375px box on a 375px phone, edge
     to edge with no gutter at all. Same bug as the rail drawer's (#98/v399). */
  box-sizing: border-box;
  width: min(560px, calc(100% - var(--space-lg)));
  max-height: min(80vh, calc(var(--vh) - var(--space-xl)));
  padding: var(--space-lg);
  align-items: stretch;
  gap: var(--space-sm);
  /* The base lets a sheet scroll as a whole; this one pins its title and
     ⚙️ Parent settings and scrolls the LIST between them instead, so a long
     week's rows never carry the controls off screen. */
  overflow: hidden;
}
.wu-confirm-sheet .wu-sheet-title {
  /* Clear of the ✕, which is absolutely placed in the corner. */
  padding-right: var(--space-xl);
  text-align: left;
}
.wu-confirm-sheet .wu-confirm-host {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  min-height: 0;
  overflow: hidden;
}
.wu-confirm-sheet .wu-confirm-list {
  width: 100%;
  max-height: none;
}

/* ✓ Approve all — full width under the list on both surfaces, so it reads as
   "everything above" rather than as one more row's control. */
.wu-confirm-all {
  flex: none;
  width: 100%;
}

.wu-confirm-list {
  flex: 1;
  width: min(560px, 100%);
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  overflow-y: auto;
  padding: var(--space-md) 0;
}

.wu-confirm-row {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  background: var(--colour-bg);
  border: 1px solid var(--colour-border);
  border-radius: var(--radius-button);
  padding: var(--space-sm) var(--space-md);
}

.wu-confirm-grace-row {
  border-color: var(--colour-warning);
  background: color-mix(in srgb, var(--colour-warning) 8%, var(--colour-bg));
}

.wu-confirm-grace {
  color: var(--colour-warning);
  font-style: normal;
  font-weight: 700;
}

/* Website (link) tiles list — parent dashboard → Settings → School websites */
.wu-link-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  margin-bottom: var(--space-sm);
}

.wu-link-row {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  background: var(--colour-bg);
  border: 1px solid var(--colour-border);
  border-radius: var(--radius-button);
  padding: var(--space-xs) var(--space-sm);
}

.wu-link-ic {
  font-size: 20px;
  flex: none;
}

.wu-link-meta {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.wu-link-meta small {
  color: var(--colour-text-secondary);
  font-size: var(--font-size-xs);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ✏️ edit and ✕ remove. REAL 44px boxes, not a 26px button with a 44px
   pseudo-element underneath: two of those sit 40px apart in this row, so their
   hit areas would overlap and the later sibling would quietly take the sliver
   nearest its neighbour — the overlap #100 kept a 10px gap to avoid. */
.wu-link-edit,
.wu-link-del {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  width: 44px;
  height: 44px;
  padding: 0;
  border: none;
  background: none;
  font-size: 18px;
  cursor: pointer;
  border-radius: var(--radius-pill);
}

.wu-link-edit { color: var(--colour-text-secondary); }
.wu-link-del { color: var(--colour-danger); }

.wu-link-edit:hover {
  background: color-mix(in srgb, var(--colour-accent) 12%, transparent);
}

.wu-link-del:hover {
  background: color-mix(in srgb, var(--colour-danger) 12%, transparent);
}

/* The row whose site the form below is editing. */
.wu-link-row.wu-link-on {
  border-color: var(--colour-accent);
  background: color-mix(in srgb, var(--colour-accent) 8%, var(--colour-surface));
}

.wu-confirm-icon {
  font-size: 24px;
  flex: none;
}

.wu-confirm-text {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.wu-confirm-text small {
  color: var(--colour-text-secondary);
  font-size: var(--font-size-xs);
}

.wu-confirm-yes,
.wu-confirm-no {
  position: relative;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  cursor: pointer;
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-bold);
  flex: none;
}
/* 44px HIT AREA under a 40px disc (#88-#90). The discs stay 40 — a bigger pair
   would unbalance a row that is mostly text — and the target grows underneath,
   the house pattern. Their centres sit 56px apart, so two 44px areas clear each
   other by 12 and neither can steal the other's tap (the arithmetic #100 did
   for the filter chips). */
.wu-confirm-yes::after,
.wu-confirm-no::after {
  content: "";
  position: absolute;
  inset: 50% auto auto 50%;
  width: 44px;
  height: 44px;
  transform: translate(-50%, -50%);
}

.wu-confirm-yes {
  background: color-mix(in srgb, var(--colour-success) 18%, var(--colour-surface));
  border: 1px solid var(--colour-success);
  color: var(--colour-success);
}

.wu-confirm-no {
  background: transparent;
  border: 1px solid var(--colour-border);
  color: var(--colour-text-secondary);
}

.wu-confirm-no:hover {
  border-color: var(--colour-danger);
  color: var(--colour-danger);
}

/* ── Activity picker ─────────────────────────────────────── */

.wu-picker {
  max-width: 420px;
}

.wu-picker-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-sm);
  width: 100%;
}

.wu-picker-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-xs);
  padding: var(--space-md) var(--space-sm);
  background: color-mix(in srgb, var(--tile-color) 8%, var(--colour-surface));
  border: 1px solid color-mix(in srgb, var(--tile-color) 45%, var(--colour-border));
  border-radius: var(--radius-button);
  cursor: pointer;
  min-height: var(--tap-target-min);
}

.wu-picker-item:hover {
  background: color-mix(in srgb, var(--tile-color) 18%, var(--colour-surface));
  border-color: var(--tile-color);
}

.wu-picker-item.wu-picker-current {
  border-width: 2px;
  border-color: var(--tile-color);
}

/* Unavailable, but still SHOWN (#79 — greyed rather than hidden). Desaturated
   so the tile stops reading as "one of my options" while its icon stays
   recognisable; it keeps its tap target, because tapping it is how the child
   hears why. Hover is suppressed so nothing offers a lift it will not deliver. */
.wu-picker-item.wu-picker-off,
.wu-picker-item.wu-picker-off:hover {
  filter: grayscale(1);
  opacity: 0.45;
  background: var(--colour-surface);
  border-color: var(--colour-border);
  cursor: default;
}

.wu-picker-icon { font-size: 28px; line-height: 1; }

.wu-picker-icon-img {
  width: 32px;
  height: 32px;
  object-fit: contain;
  display: block;
}

.wu-picker-label {
  font-size: var(--font-size-xs);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--colour-text-secondary);
}

/* ── Parent settings panel ───────────────────────────────── */

.wu-set-list {
  flex: 1;
  width: min(560px, 100%);
  min-width: 0;
  max-width: 100%;
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  overflow-y: auto;
  /* overflow-y:auto makes the cross-axis compute to auto too — clip it so a
     sub-pixel-wide row can't add a horizontal scrollbar on mobile. */
  overflow-x: hidden;
  padding: var(--space-md) 0;
}

/* No global box-sizing reset exists, so padded settings boxes (groups, rows,
   dash rows) would otherwise add their side padding ON TOP of width:100% and
   spill past the right edge — clipped on mobile. Scope border-box to the whole
   settings subtree so every nested box fits its width. */
.wu-set-list,
.wu-set-list * {
  box-sizing: border-box;
}

/* Portrait phones: the settings nest three padded levels deep (panel → group →
   row). Trim the side padding at each level so rows aren't pushed wide and the
   rounded right corners stay on-screen — and the controls scale down a touch. */
@media (max-width: 540px) {
  .wu-dash-settings,
  .wu-set-group {
    padding-left: var(--space-sm);
    padding-right: var(--space-sm);
  }
  .wu-set-row,
  .wu-dash-row {
    padding-left: var(--space-sm);
    padding-right: var(--space-sm);
  }
  .wu-set-group > summary {
    padding-left: 0;
    padding-right: 0;
  }
  /* Stack any segmented control under its label so multi-option rows (music
     practice length, maths difficulty/length) wrap fully into view instead of
     clipping the last button. */
  .wu-set-row:has(.wu-set-seg) {
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-sm);
  }
  .wu-set-row:has(.wu-set-seg) .wu-set-seg {
    justify-content: flex-start;
  }
}

.wu-set-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  background: var(--colour-bg);
  border: 1px solid var(--colour-border);
  border-radius: var(--radius-button);
  padding: var(--space-sm) var(--space-md);
  min-height: 56px;
}

.wu-set-label {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  flex-wrap: wrap;
  color: var(--colour-text-primary);
  font-size: var(--font-size-sm);
}

.wu-set-label small {
  color: var(--colour-text-secondary);
  font-size: var(--font-size-xs);
}

.wu-set-icon {
  width: 22px;
  height: 22px;
  object-fit: contain;
  display: block;
}

.wu-set-seg {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 4px;
  flex: none;
}

/* "Choose a look" sheet grid (Slots panel Music/Sport icon picker). */
.wu-sheet-sub {
  margin: 0;
  color: var(--colour-text-secondary);
  font-size: var(--font-size-sm);
}
.wu-look-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-sm);
  margin-top: var(--space-sm);
}
.wu-look-grid .wu-icon-pick {
  font-size: var(--font-size-xl);
  padding: var(--space-md);
  min-height: 56px;
}

/* Stacked row — label on top, control wraps full-width below. Used by the
   day pickers (8 options) that overflow the narrow dashboard column inline. */
.wu-set-row.wu-set-stack {
  flex-direction: column;
  align-items: stretch;
  gap: var(--space-sm);
}
.wu-set-row.wu-set-stack .wu-set-seg {
  justify-content: flex-start;
}

/* ── 🗺️ Quest composer: a scrollable TREE (owner, 2026-08-28) ────────────────
   Nested <details>, which is the dashboard's own accordion — so the whole menu
   of exercises is scannable at once instead of four stacked segmented rows that
   hid every branch but the chosen one. Depth is shown by indent alone; a second
   card outline inside a card reads as clutter at this size. */
.wu-q-leaf {
  margin-left: var(--space-md);
  border-left: 2px solid var(--colour-border);
  border-radius: 0;
  padding-left: var(--space-sm);
}
.wu-q-leaf > summary {
  font-size: var(--font-size-sm);
}

/* Multi-select chips wrap rather than scroll sideways: twelve tables must be
   reachable without a horizontal gesture inside a vertically-scrolling panel. */
.wu-set-multi {
  flex-wrap: wrap;
  /* 10px ROW gap, so a wrapped chip's 44px hit area (below) clears the row
     above it: 44 − 36 = 8px of overhang, and 8 < 10. Column gap stays at the
     seg default of 4px because the hit area is grown vertically only — the
     same measured trade-off as .wu-set-toggle::after, and the same reason
     decision #100's filter chips use a 10px row gap. */
  row-gap: 10px;
}

/* A wrapped multi-select chip needs the 44px floor too (#88–#90). The plain
   .wu-set-seg is deliberately excluded — its options sit 4px apart on ONE row,
   where a taller target would steal its neighbour's taps. Wrapping is what makes
   it safe here, and the row-gap above is what makes wrapping safe. */
.wu-set-multi button::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 44px;
  transform: translateY(-50%);
}
/* The one action in each leaf, so it reads as the commit rather than as another
   option among the chips above it. */
.wu-set-toggle.wu-set-primary {
  width: 100%;
  margin-top: var(--space-sm);
  background: var(--colour-accent);
  border-color: var(--colour-accent);
  color: #fff;
  font-weight: var(--font-weight-bold);
}

.wu-set-seg button,
.wu-set-toggle,
.wu-set-stepper button {
  padding: var(--space-xs) var(--space-sm);
  min-height: 36px;
  background: var(--colour-surface);
  border: 1px solid var(--colour-border);
  border-radius: var(--radius-button);
  color: var(--colour-text-secondary);
  font-size: var(--font-size-sm);
  font-family: var(--font-body);
  cursor: pointer;
  position: relative;
}

/* 36px box, 44px hit area (#88–#90). Grown VERTICALLY ONLY, and that is
   measured rather than assumed: stacked toggles sit 12px apart, so 4px of
   overhang each side is clear — but same-row segmented options are only 4px
   apart, and widening them would make each option steal its neighbour's taps.
   A too-small target is bad; a target that activates the wrong control is
   worse. The box stays 36px because growing it would re-flow every settings row
   in the dashboard. */
.wu-set-toggle::after,
.wu-set-stepper button::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 44px;
  transform: translateY(-50%);
}

.wu-set-seg button:hover,
.wu-set-toggle:hover,
.wu-set-stepper button:hover {
  border-color: var(--colour-accent);
}

.wu-set-seg button.wu-set-on,
.wu-set-toggle.wu-set-on {
  background: color-mix(in srgb, var(--colour-accent) 14%, var(--colour-surface));
  border-color: var(--colour-accent);
  color: var(--colour-accent);
  font-weight: var(--font-weight-bold);
}

/* Vocab language chips — compact flag + code, all five on one row */
.wu-set-langs {
  flex-wrap: nowrap;
  justify-content: stretch;
  gap: 4px;
}

.wu-set-langs .wu-set-toggle {
  flex: 1 1 0;
  min-width: 0;
  padding: var(--space-xs) 2px;
  font-size: var(--font-size-xs);
  text-align: center;
}

/* Collapsible settings subpanels (decision #55, settings rethink) */
.wu-set-group {
  border: 1px solid var(--colour-border);
  border-radius: var(--radius-card);
  background: var(--colour-bg);
  padding: 0 var(--space-md) var(--space-xs);
  margin-bottom: var(--space-sm);
}

.wu-set-group[open] > .wu-set-row,
.wu-set-group[open] > .wu-set-iconpick {
  margin-bottom: var(--space-xs);
}

.wu-set-group > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding: var(--space-sm) 0;
  font-family: var(--font-display);
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-bold);
  color: var(--colour-text-primary);
}

.wu-set-group > summary::-webkit-details-marker {
  display: none;
}

/* Count badge in a panel summary (e.g. Confirm activities pending count) */
.wu-grp-count {
  font-family: var(--font-mono);
  font-size: var(--font-size-xs);
  color: #fff;
  background: var(--colour-danger);
  border-radius: var(--radius-pill);
  padding: 0 7px;
  min-width: 18px;
  text-align: center;
}

.wu-grp-count:empty {
  display: none;
}

.wu-set-group > summary::after {
  content: "›";
  margin-left: auto;
  font-size: var(--font-size-lg);
  color: var(--colour-text-secondary);
  transition: transform var(--transition-fast);
}

.wu-set-group[open] > summary::after {
  transform: rotate(90deg);
}

.wu-set-group[open] > summary {
  border-bottom: 1px solid var(--colour-border);
  margin-bottom: var(--space-sm);
}

/* Icon picker (Music / Sports) */
.wu-set-iconpick {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
  justify-content: flex-start;
}

.wu-icon-pick {
  width: 44px;
  height: 44px;
  font-size: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--colour-border);
  border-radius: var(--radius-button);
  background: var(--colour-surface);
  cursor: pointer;
}

.wu-icon-pick.wu-set-on {
  border-color: var(--colour-accent);
  background: color-mix(in srgb, var(--colour-accent) 14%, var(--colour-surface));
}

/* Activity recolour swatches (Phase 5 activity-type config) */
.wu-colour-row {
  gap: var(--space-sm);
}
.wu-colour-pick {
  width: 34px;
  height: 34px;
  padding: 0;
  border-radius: 50%;
  border: 2px solid var(--colour-border);
  background: var(--sw);
  cursor: pointer;
  transition: transform 120ms ease, box-shadow 120ms ease;
}
.wu-colour-pick.wu-set-on {
  border-color: var(--colour-text-primary);
  box-shadow: 0 0 0 2px var(--colour-surface), 0 0 0 4px var(--sw);
  transform: scale(1.08);
}


