/* ═══════════════════════════════════════════════════════════════════════════
   PICKER UI STANDARD — shared chrome
   ═══════════════════════════════════════════════════════════════════════════
   The layout for the tool action row and the tabbed control panel, for pages
   being converted to the picker UI standard (Phase 5).

   ⚠️ WHY THIS FILE EXISTS.
   These rules were written for classic-wheel and live in
   `classic-wheel-styles.css`, which no other page loads. The first converted
   bespoke page therefore rendered `.wsp-tool-head` as a plain block: the action
   row dropped onto its OWN line below the H1 (measured — H1 top 98, row top
   194), which is precisely the regression the standard exists to prevent, since
   the row is supposed to cost zero vertical height.

   ⚠️ THESE RULES ARE CURRENTLY DUPLICATED, ON PURPOSE.
   `classic-wheel-styles.css` keeps its own copy and is NOT edited, so
   classic-wheel — the page carrying the hard-won fold baseline — is untouched
   by the rollout. Once enough of the rollout is proven, de-duplicate by
   deleting the block from `classic-wheel-styles.css` and loading this file
   there instead, and re-run `check-fold.js` immediately after.
   ⇒ If you change a rule here, change it in `classic-wheel-styles.css` too
     until that consolidation happens. The blocks are marked in both files.

   Colour comes from theme variables and EVERY var needs an inline fallback:
   on the default light theme `theme-bootstrap.php` removes `data-theme`
   entirely, so no `--theme-*` variable exists at all.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Tool action row ──────────────────────────────────────────────────────
   Shares the H1's line so it adds NO vertical space. Two other placements were
   tried on 2026-08-13 and both regressed the fold:
     • inside the right column → pushed the settings card below the stage card
     • on its own row above the grid → an empty full-width band above the stage
   Keep it here. */
.wsp-tool-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}
.wsp-tool-head .tool-intro {
  text-align: left;
  margin: 0;
  padding: 0;
  max-width: none;
  flex: 1 1 320px;
}
.wsp-tool-head .tool-intro h1 { margin-bottom: 0.25rem; }
.wsp-tool-head .wsp-tool-actions { flex: 0 0 auto; padding-top: 0.35rem; }

@media (max-width: 767.98px) {
  .wsp-tool-head { justify-content: center; }
  .wsp-tool-head .tool-intro { text-align: center; flex-basis: 100%; }
  .wsp-tool-head .wsp-tool-actions { width: 100%; padding-top: 0; }
}

.wsp-tool-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  flex-wrap: wrap;
  gap: 0.4rem;
  align-self: end;
  margin-right: 12px;
  /* ⚠️ THE BUTTONS WERE ONLY PARTLY CLICKABLE, ON EVERY PICKER.
     Owner 2026-08-23: "the fullscreen button click area is very small.. and its
     on every picker.. the moment pointer is inside the border of the fullscreen
     button, it should be clickable".

     It was never small. MEASURED with a hit test (hit-area-check.js): the box is
     a full 38x38, but the NEXT container overlaps this row by 24px on every page
     and — being later in the DOM, and `position:relative` on some pages — paints
     ON TOP. document.elementsFromPoint at the button's own centre returned
     `.container.pb-4` and `#settingsDrawer` ABOVE `#fullscreenBtnTop`. Only
     32-72% of each button's own box actually took the click.

     Lifting the row into its own stacking context fixes the clicks and moves
     NOTHING: no size, position, spacing or colour changes here. */
  position: relative;
  z-index: 3;
}

/* ⛔⛔ THE SAME RULE LIVES IN classic-wheel-styles.css, AND THAT IS THE HAZARD.
   Fixing only that copy changed nothing on most pickers: the views link
   picker-ui.css directly, this rule comes later in the cascade, and its
   `transparent` won. The measurement went from 151 failing page-theme
   combinations to 151 — a "fix" that moved nothing (SKILLS 38: two stylesheets
   that are equivalent WILL drift; here they had not even drifted, and one was
   simply invisible to me).

   ⛔ THE DEFECT ITSELF: `background-color: transparent` + `color:
   var(--theme-text)`. --theme-text is the ink for the PAGE background, but this
   row sits over the STAGE wrapper, whose colour is picked per picker and is dark
   on many of them. Measured across all 151 on the public site:

       149/300 page-theme combinations clean — 151 FAILING
       element-picker     light  1.23:1
       date-ideas-picker  light  1.31:1
       ~every picker      dark   3.58-4.19:1

   Painting the surface behind the ink makes the pair self-contained, so the row
   reads the same on every picker whatever stage is behind it.
   ⚠️ --theme-surface-text, not --theme-text: the ink belongs to the surface it
   is now on (SKILLS 115). */
/* ⚠️ `.btn`, NOT `.wsp-ta-btn` — AND THE FALLBACK LITERAL MATTERS. In app mode
   app-shell.js moves the settings gear (#off-sett-btn, a .btn-small, NOT a
   .wsp-ta-btn) into this row, so a selector keyed on .wsp-ta-btn styled four
   controls and left the gear in accent blue. On the public site the row contains
   only the ta-btns, so this widening changes nothing there.
   ⚠️ The fallback is #1f2430 to match .wsp-app-topbar-back and the app list:
   --theme-surface-text is undefined in the light default, so the FALLBACK is
   what renders, and #212529 vs #1f2430 is two different treatments to any check
   that compares them exactly. */
.wsp-tool-actions .wsp-ta-btn,
.wsp-tool-actions #shareWheelBtn,
.wsp-tool-actions .btn {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--theme-border, #dee2e6);
  background-color: var(--theme-surface, #fff);
  color: var(--theme-surface-text, #1f2430);
  border-radius: 8px;
  padding: 0.36rem 0.7rem;
  font-size: 0.8125rem;
  font-weight: 600;
  white-space: nowrap;
}

/* ⛔ AND themes.css:472 OUT-RANKS THE RULE ABOVE IN EVERY THEMED MODE:

       body[data-theme] .btn-sm:not(.btn-primary):not(.btn-outline-primary)
       :not(.btn-success):not(.btn-danger):not(.btn-warning):not(.btn-info)
           { color: var(--theme-accent) !important; background: transparent }

   specificity (0,8,1) — each :not() argument counts as a class. That is why the
   row measured ~4.19:1 in dark on nearly every picker regardless of what this
   file said. Mirroring the chain gives (0,9,1) and names the rule being
   answered, rather than padding with a repeated class. ⚠️ If themes.css gains a
   seventh :not(), this must grow with it. (SKILLS 121.) */
body[data-theme] .wsp-tool-actions .btn-sm:not(.btn-primary):not(.btn-outline-primary):not(.btn-success):not(.btn-danger):not(.btn-warning):not(.btn-info) {
  color: var(--theme-surface-text, #1f2430) !important;
  background-color: var(--theme-surface, #fff) !important;
}

/* the glyph follows the button, not themes.css's site-wide .bi paint */
.wsp-tool-actions .wsp-ta-btn .bi,
.wsp-tool-actions #shareWheelBtn .bi {
  color: inherit !important;
  opacity: 1 !important;
}

.wsp-tool-actions .wsp-ta-btn:hover,
.wsp-tool-actions #shareWheelBtn:hover {
  border-color: var(--theme-accent, #4a5bd4);
  color: var(--theme-accent, #4a5bd4);
}

/* Every button in the row looks the same. Fullscreen only takes the accent when
   it is ACTIVE — that is state, not emphasis. */
.wsp-tool-actions .wsp-ta-btn.zen-active {
  border-color: var(--theme-accent, #4a5bd4);
  background: var(--theme-accent, #4a5bd4);
  color: #fff;
}

/* ── ICON-ONLY at every width ─────────────────────────────────────────────
   Each button keeps its title + aria-label, so the name is one hover (or one
   screen reader) away. ⚠️ `.wsp-ta-label` is display:none at EVERY width — the
   partial's own comment claiming it "collapses to icons below md" is wrong. */
.wsp-tool-actions .wsp-ta-label { display: none; }

.wsp-tool-actions .wsp-ta-btn,
.wsp-tool-actions #shareWheelBtn,
.wsp-tool-actions #ecwTriggerBtn {
  width: 38px;
  height: 38px;
  padding: 0;
  justify-content: center;
  flex: 0 0 auto;
}
.wsp-tool-actions .wsp-ta-btn i,
.wsp-tool-actions #shareWheelBtn i,
.wsp-tool-actions #ecwTriggerBtn i {
  margin-right: 0 !important;
  font-size: 1rem;
}

@media (max-width: 767.98px) {
  .wsp-tool-actions {
    width: 100%;
    flex-wrap: nowrap;
    gap: 0.35rem;
    margin-right: 0px;
  /* ⚠️ CENTRED, NOT RIGHT-ALIGNED (owner 2026-08-25: "the 4 buttons have a lot
     of empty space to the left"). Above md this row shares the H1's line and
     `justify-content: flex-end` is what pins it to the right of the title. Below
     md .wsp-tool-head stacks it onto its own full-width line — but flex-end was
     never overridden, so four 36px buttons sat against the right edge of a
     375px row and the other ~230px read as a hole in the layout.
     Centred here only: the H1 above it is centred at this width too, so the two
     line up. Desktop is untouched.
     ⛔ Do NOT "simplify" this block by rewriting .wsp-tool-actions wholesale —
     the base rule's `position: relative; z-index: 3` is the 2026-08-23 hit-area
     fix (the next container was painting over 32-72% of every button) and it
     must survive. */
    justify-content: center;
  }
  .wsp-tool-actions .wsp-ta-btn,
  .wsp-tool-actions #shareWheelBtn,
  .wsp-tool-actions #ecwTriggerBtn {
    width: 36px;
    height: 36px;
  }
}

/* ── Tabbed control panel ─────────────────────────────────────────────────
   Tab labels stay VISIBLE at every width. An earlier `display:none` under
   400px left unlabelled icons, and just above that breakpoint the labels were
   cut mid-word ("Setting" with the s clipped). The row scrolls horizontally
   instead, and the padding gives way before the words do. */
.wsp-panel-tabs {
  flex-wrap: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  border-bottom: 1px solid var(--theme-border, #dee2e6);
}
.wsp-panel-tabs::-webkit-scrollbar { display: none; }

.wsp-panel-tabs .nav-link {
  white-space: nowrap;
  padding: 0.5rem 0.45rem;
  font-size: 0.82rem;
}

/* Superscript count rather than a pill: same information, ~22px narrower. */
.wsp-tab-count {
  margin-left: 0.15rem;
  font-size: 0.62rem;
  font-weight: 700;
  line-height: 1;
  top: -0.55em;
  /* B13: measured 3.33:1 on the dark theme's tab strip — the worst chrome
     reading on the page, and one B13 had not found. TEXT takes the ink. */
  color: var(--theme-accent-ink, var(--theme-accent, #4a5bd4));
  background: none;
  padding: 0;
}

@media (max-width: 575.98px) {
  .wsp-panel-tabs .nav-link {
    padding: 0.5rem 0.5rem;
    font-size: 0.8125rem;
  }
  .wsp-panel-tabs .nav-link i { margin-right: 0.2rem !important; }
  .wsp-tab-count { margin-left: 0.25rem; font-size: 0.62rem; }
}

@media (max-width: 400px) {
  .wsp-panel-tabs .nav-link { padding: 0.5rem 0.35rem; font-size: 0.78rem; }
  /* Icons go before the labels do — the word is what identifies the tab. */
  .wsp-panel-tabs .nav-link i { display: none; }
}

/* ── Panel header: title left, Advanced right ─────────────────────────────
   ⚠️ The title shares its line with the toggle inside a col-lg-4 (~332px). At
   the default h5 size a title like "Who is on the reef?" wrapped to two lines
   in the SIMPLE view but not the advanced one — because the button says
   "Advanced" (wider) rather than "Simple". Trim the title a little and give the
   button a fixed floor so the header never reflows as the label changes. */
/* MEASURED at a 300px header: title gets 197px once the button (95px) and the
   8px gap are taken. Natural title widths at the old 17.28px were 213px
   ("Who is in the running?") and 218px ("Who is in the meadow?") — both wrapped
   to two lines. At 1rem they are 199 and 204, which fits once the button gives
   back ~11px. Chosen over rewriting the page copy: the titles are the pages'
   own words, and over truncating, which hides them.

   ⚠️ SHRINKING THE TITLE WAS THE WRONG LEVER. 1rem still wrapped (pets needed
   exactly 197 of 197, insects 202) and 0.94rem, which did fit, left the heading
   SMALLER THAN THE BODY TEXT beneath it — the owner spotted that immediately.
   The width was being eaten by the BUTTON, not the title: "Advanced" + its icon
   would not compress below 95px.
   FIX: the toggle goes ICON-ONLY (owner's call), the same 38px square as the
   tool action row, which hands ~57px back. The title then keeps its full h5
   size — available becomes ~254px against a worst case of 218px. */
.wsp-panel-head {
  line-height: 1.3;
  flex-wrap: nowrap;
}
.wsp-panel-head > span {
  min-width: 0;                 /* let the title be the thing that flexes */
}

/* Icon-only, matching .wsp-ta-btn's 38px square in the action row. The label
   stays in the DOM as visually-hidden text and the button keeps title +
   aria-label, so the name is one hover — or one screen reader — away.

   ⚠️ GEOMETRY ONLY. This rule must NOT set `color`, `background` or `border`.
   The button's colour is theme-driven (it inherits the site's `.btn` + theme
   treatment, exactly as on classic-wheel where `.advanced-toggle` carries only
   positioning). An earlier version added `color: var(--theme-text)` here and
   turned a themed blue control BLACK — the owner caught it immediately.
   Changing the shape is the job; the palette belongs to the theme. */
.wsp-panel-head .advanced-toggle {
  width: 38px;
  height: 38px;
  padding: 0;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
}
.wsp-panel-head .advanced-toggle i { margin: 0 !important; font-size: 1rem; }

/* ── The stage's start button must not wrap ───────────────────────────────
   MEASURED across three converted engines (owner 2026-08-15): at 390px and
   430px the overlay button was FOUR line-heights tall — ~102px — because the
   label wrapped to three lines, and it was still two lines at 768px. Cause: the
   button inherits `white-space: normal` and carries ~30px of horizontal padding
   each side, so at 390px only ~107px of content width is left for a label that
   needs ~125px ("Make the Splash", "Take the Shot").

   `[id$="StartOverlay"]` is the shared handle — every bespoke picker names it
   `#{prefix}StartOverlay`, while the CLASS is per-page. picker-ui.css is only
   loaded by converted pages, so this cannot reach an unconverted one.

   The padding tightens below sm so nowrap never pushes the button past the
   stage edge. */
[id$="StartOverlay"] {
  white-space: nowrap;
}

@media (max-width: 575.98px) {
  [id$="StartOverlay"] {
    padding-left: 1rem;
    padding-right: 1rem;
  }
}

/* ── Roster grid: 3 across, capped, scrollable ────────────────────────────
   MEASURED problem (owner 2026-08-15): narrowing the panel to col-lg-4 dropped
   the chips to 2 per row, so the 20-item pages grew a 976px grid — a 1218px
   panel against a 779px stage — and pushed "Add" and "Take the Shot" to y=1353
   in an 804px viewport. Two changes, because neither alone is enough:
     • 3 across  — the page rule's minmax(104px) only fits 2 in the ~300px
                   content width; 88px fits 3. Takes 20 chips from 10 rows to 7.
     • a CAP     — 3-across alone still leaves ~680px of grid. The cap is what
                   actually brings the buttons back up, and it keeps the panel
                   shorter than the stage card so the columns read as balanced.

   ⚠️ `!important` on the columns is deliberate. The page rule is
   `.page-<slug> .<pfx>-item-grid` (0,0,2,0) and picker-ui.css is linked BEFORE
   the page stylesheet, so on equal specificity the page wins on source order. */
.wsp-roster {
  grid-template-columns: repeat(auto-fill, minmax(88px, 1fr)) !important;
  max-height: 380px;
  overflow-y: auto;
  overscroll-behavior: contain;

  /* ⚠️ A BORDER, so the roster reads as its own area instead of merging into
     the "add your own" field below it (owner 2026-08-15). Matched to the site
     standard by MEASURING classic-wheel's #itemsTextarea rather than guessing:
     computed `1px solid rgb(222,226,230)`, radius 6px, white background. */
  border: 1px solid var(--theme-border, #dee2e6);
  border-radius: 6px;
  background: var(--theme-surface, #fff);

  /* ⚠️ The top padding is not cosmetic. Chips lift on hover, and with
     `overflow-y: auto` a lifted chip in the first row had its top border
     clipped by the scroll container. 10px clears the lift; the extra right
     padding keeps the scrollbar off the chip borders. */
  padding: 10px;
  padding-right: 6px;
}

/* ⚠️ The 3-across rule above only bites on a GRID roster. Several engines lay
   theirs out with `display:flex` and let variable-width chips wrap naturally
   (the sports pages, where team names differ wildly in length) — there
   `grid-template-columns` computes but does nothing, and forcing a column count
   would be standardising the STAGE by the back door. What matters is the
   OUTCOME: the roster is capped, it scrolls, and the buttons under it stay
   reachable. The verifier asserts that, not a column count. */

/* A shorter cap, opt-in per page, for rosters with many chips over a shorter
   stage: 30 NBA teams at the 380px default made the panel 611px against a 553px
   stage card and pushed the action button below the fold. Opt in rather than
   moving the shared default, which is already signed off elsewhere. */
.wsp-roster.wsp-roster-tight { max-height: 300px; }

/* A quiet scrollbar — a chunky default one inside a card reads as a defect. */
.wsp-roster { scrollbar-width: thin; }
.wsp-roster::-webkit-scrollbar { width: 8px; }
.wsp-roster::-webkit-scrollbar-thumb {
  background: var(--theme-border, #dee2e6);
  border-radius: 4px;
}
.wsp-roster::-webkit-scrollbar-track { background: transparent; }

/* ── One-row-per-setting rhythm ───────────────────────────────────────────
   Label left, control right, on a single line. Replaces the stacked
   heading/control/help-paragraph pattern that turns a panel into a long scroll.
   ⚠️ Without these a converted page renders raw checkboxes in a row — the
   controls are all present and it still looks nothing like classic-wheel. */
.wsp-set {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  min-height: 2.35rem;
  padding: 0.2rem 0;
  border-bottom: 1px solid var(--theme-border, #f0f2f4);
}
.wsp-set:last-of-type { border-bottom: 0; }

.wsp-set-label {
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--theme-text, #212529);
  margin: 0;
  flex: 0 1 auto;
  white-space: nowrap;
}

.wsp-set-ctl {
  flex: 0 1 auto;
  display: flex;
  align-items: center;
  gap: 0.4rem;
  min-width: 0;
  margin: 0;
  padding: 0;
}

/* Bootstrap's .form-switch indents for a label that isn't there in this layout. */
.wsp-set .form-check.form-switch { padding-left: 0; min-height: 0; }
.wsp-set .form-check-input { margin: 0; float: none; }

.wsp-set-ctl .form-select { min-width: 150px; }

.wsp-range-ctl { flex: 1 1 auto; max-width: 62%; }
.wsp-range-ctl .form-range { flex: 1 1 auto; }

.wsp-set-val {
  flex: 0 0 auto;
  min-width: 2.6rem;
  text-align: right;
  font-size: 0.8125rem;
  font-weight: 700;
  /* B13: measured 3.73:1 on the dark theme's --theme-surface. TEXT takes the ink. */
  color: var(--theme-accent-ink, var(--theme-accent, #4a5bd4));
  /* the page classes these readouts used to carry (.{p}-speed-val etc) supplied
     tabular figures; they are being removed so the readout follows the PANEL
     theme, so the standard picks the property up instead of losing it. */
  font-variant-numeric: tabular-nums;
}

/* A setting whose control needs the full width (a text field). */
.wsp-set-stack {
  display: block;
  min-height: 0;
  padding-bottom: 0.6rem;
}
.wsp-set-stack .wsp-set-label { display: block; margin-bottom: 0.3rem; }

/* ── Provably-fair shield handle ──────────────────────────────────────────
   The receipt is COLLAPSED by default and opened by this shield. Without it a
   converted page dumps the whole receipt under the stage permanently, which is
   the old pre-standard behaviour. */
.wsp-fair-handle-row {
  display: flex;
  justify-content: flex-start;
  margin-top: 0.35rem;
}

.wsp-fair-handle {
  position: relative;
  appearance: none;
  -webkit-appearance: none;
  border: 1px solid var(--theme-border, #dee2e6);
  background: var(--theme-surface, #fff);
  color: var(--theme-muted, #6c757d);
  width: 34px;
  height: 34px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
  transition: color .15s, border-color .15s, background .15s;
}

/* ⚠️ The open/hover state uses a TINTED ACCENT, not --theme-accent-soft. On
   dark themes --theme-accent-soft is a near-white wash, so the pressed shield
   became a bright blob with an invisible icon. rgba() over the surface tints
   correctly on light and dark alike. */
.wsp-fair-handle:hover,
.wsp-fair-handle.is-open {
  color: var(--theme-accent, #4a5bd4);
  border-color: var(--theme-accent, #4a5bd4);
  background: rgba(var(--theme-accent-rgb, 74, 91, 212), .14);
}

.wsp-fair-handle:focus-visible {
  outline: 2px solid var(--theme-accent, #4a5bd4);
  outline-offset: 2px;
}

/* A sealed draw waiting behind the icon — without a cue it reads as inert. */
.wsp-fair-handle.is-sealed::after {
  content: '';
  position: absolute;
  right: -2px;
  bottom: -2px;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: #22c55e;
  border: 2px solid var(--theme-bg, #fff);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .06);
}

/* ── FULLSCREEN: the winner bar must not move the stage ───────────────────
   ⚠️ The fix for this already exists in winner-result-bar.css, but it is scoped
   to `body.zen-mode .main-layout-left > .wsp-result` — a DIRECT CHILD. On
   classic-wheel the bar is one. On a bespoke picker the bar sits INSIDE the
   stage card, so the rule never matched and the stage jumped every time a
   winner appeared (owner 2026-08-15, and the same complaint he made about
   classic-wheel on 2026-08-13).

   CAUSE: the fullscreen column is vertically centred, so the moment the bar
   gains height the whole stack re-centres.

   ⚠️ RESERVING A SLOT IS NOT ENOUGH, AND THAT IS WHY THIS BROKE TWICE.
   classic-wheel reserves `min-height: 78px`. Copying that number here fixed the
   synthetic test and still shifted the real page: **measured, this bar fills to
   150px** — it carries Save-card and Share buttons that wrap in the 620px zen
   column — so the FIRST real reveal grew the slot by 72px and the stack jumped
   −44px. Every reveal after that was stable, which is exactly what the owner
   described. Any fixed reservation is a guess about content that can wrap.

   ⚠️ AND PINNING IT TO THE VIEWPORT IS NOT THE ANSWER EITHER. That was the
   second attempt: `position: fixed` removed it from the flow so the stage
   genuinely could not move — but out of flow it OVERLAPPED the "N in frame"
   count line inside the card (owner 2026-08-15, with a screenshot).

   FIX = exactly what classic-wheel does, with the right number.
   MEASURED on classic-wheel in zen: the bar is `display:flex`,
   `visibility:hidden`, `min-height:78px`, sitting in flow below the card — so
   the empty slot IS counted when the column centres, which is what puts the
   stage "a little up" and means revealing the bar changes nothing.
   The only thing wrong here was the VALUE: this bar fills to 150px, not 78.
   `--wsp-zen-bar-h` lets a page raise it, and photo-standard-check.js asserts
   the reservation is >= the bar's real filled height, so an engine whose bar
   outgrows it FAILS THE SUITE instead of surprising the owner. */
/* ⚠️ THE RESERVATION SITS ON THE SLOT, NOT THE CARD (2026-08-22). With it on
   .wsp-result the visible card STRETCHED to the reserved height, so a short
   winner showed dead space inside it. The slot keeps the centred column from
   moving; the card hugs its content. */
body.zen-mode .main-layout-left .wsp-result-slot {
  align-self: stretch;
  width: 100%;
  min-height: var(--wsp-zen-bar-h, 150px);
  display: block;
}

/* ── THE SAME RESERVATION, ONE BUTTON ROW TALLER ON A PHONE ─────────────────
   ⚠️ FOUND 2026-08-25 (owner: "this issue was fixed recently for desktop... but
   for mobile responsive its still there — in full screen mode, when winner card
   is displayed, the stage is shifted a little up").

   MEASURED in real fullscreen at 390x844: classic-wheel's slot goes 78 -> 121px
   the moment the card fills (+43) and the stage jumps 21px; coin-toss the same;
   dice-roll 92 -> 126 (+34) = 17px; random-picker 133 -> 144 (+11). At 500x900
   and at 1440x950 every one of them is 0px, so the band is exactly the <=480px
   breakpoint that already exists in winner-result-bar.css.

   CAUSE. Above 480px .wsp-result-actions is position:absolute — OUT OF FLOW, so
   the buttons cost the bar no height at all and only the floated ::before corner
   reserves room beside the text. At <=480px (winner-result-bar.css:171) the
   corner stands down and the actions become a static full-width row IN FLOW.
   --wsp-zen-bar-h was measured at 1440 on every page, so it never covered that
   row: filled > reserved, the slot grows on reveal, and a vertically-centred zen
   column turns half the growth into the stage moving up.

   FIX. Add back exactly the block that entered the flow. 34px is
   .wsp-result-save.wsp-result-icon's fixed height and .55rem is the row's own
   margin-top — both literals lifted from that same <=480 block, not guessed.

   ⚠️ A NEW VARIABLE, NOT AN OVERRIDE OF --wsp-zen-bar-h. ~60 views declare that
   constant in an inline <style> emitted AFTER this file's <link>; same
   specificity, later in the document, so a media query here would lose on every
   one of them. Nothing sets --wsp-zen-bar-mobile, so it is unopposed.

   ⚠️ THE PER-PAGE KNOB IS ABSOLUTE, NOT AN ADDEND. --wsp-zen-bar-mobile holds the
   swept worst case for that page AT 390px, written verbatim from the tool's
   output. An addend would have to be derived by subtracting a reservation that
   lives in one of THREE places (this file, classic-wheel-styles.css, or the
   view's own inline <style>) — arithmetic against a number you would have to
   probe per page, on ~150 pages, to say something the sweep already said.

   ⚠️ THE DEFAULT LIVES IN THE var() FALLBACK AND IS NEVER DECLARED ON THE SLOT.
   A value set directly on an element beats one it merely inherits — the trap
   documented at winner-result-bar.css:20. Declared here, a per-page
   body.page-{slug} { --wsp-zen-bar-mobile } would silently lose.

   ⚠️ NOT wired to --wsp-result-actions-h (winner-result.js:114). That property is
   set on the BAR, which a parent cannot read, and it is set AT REVEAL — a
   min-height that changes on reveal is the defect, not the fix. */
@media (max-width: 480px) {
  body.zen-mode .main-layout-left .wsp-result-slot {
    min-height: var(--wsp-zen-bar-mobile,
                    calc(var(--wsp-zen-bar-h, 150px) + 34px + .55rem));
  }
}
body.zen-mode .main-layout-left .wsp-result {
  width: 100%;
}
body.zen-mode .main-layout-left .wsp-result[hidden] {
  /* ⚠️ MUST MATCH THE VISIBLE BAR'S DISPLAY, or the reserved slot is laid out
     differently from the thing it is reserving for. This said `flex`, left from
     when the bar WAS a flex row; once it became block+float the hidden bar
     measured 150px against a visible 133px and the stage jumped 8px on reveal —
     caught by the harness's bar-toggle check, not by eye. Change both together. */
  display: block !important;
  visibility: hidden;
  pointer-events: none;
}

/* `.fairp` keeps its own styling from verify-fair.css; this adds the motion. */
.fairp {
  overflow: hidden;
  transition: max-height .22s ease, opacity .18s ease, margin .22s ease;
  max-height: 1200px;
}

.fairp.is-collapsed {
  max-height: 0;
  opacity: 0;
  margin-top: 0;
  margin-bottom: 0;
}

@media (prefers-reduced-motion: reduce) {
  .fairp { transition: none; }
}

/* ── A preset / filter strip mounted under the stage card's title ─────────
   Some spin-landing pages inject a category strip (fast-food's "Popular /
   Burgers / Chicken", restaurant's vibes). It used to sit ABOVE the card, which
   pushed the whole left column down and left the two cards 33px out of line —
   measured, and pre-existing. It is now mounted inside the card body, directly
   under the title, which lines the columns up.
   The title carries a 16px bottom margin that is generous once a 33px strip
   follows it, and that pair cost the last 4px of the wheel on the fold. Tighten
   just this combination. */
.main-layout-left .card-body > .card-title + div[role="group"] {
  margin-top: -10px;
}

/* ── STAGE-SIDE CONFIGURATION IS HIDDEN IN FULLSCREEN ────────────────────
   Several pickers keep a preset / mode / region strip on the stage rather
   than in the panel — .gac-modes-wrap, .flg-regions-wrap, #odoPresets and
   friends. In zen mode the panel is hidden, so this configuration was the
   only settings UI left on screen, which is what the owner reported
   (2026-08-20: "it shouldn't show any pre-sets on top in case of
   fullscreen"). PRE-EXISTING — measured on the pre-conversion views too.
   The converter marks those blocks with .wsp-zen-hide; one rule hides them,
   so a new page needs a descriptor field and no new CSS. */
body.zen-mode .wsp-zen-hide { display: none !important; }
/* ── COLOUR CONTROL ──────────────────────────────────────────────────────────
   The picker + hex field + reset trio, exactly as classic-wheel's Appearance tab
   uses it for "Text colour" (owner 2026-08-18 pointed at that control by name).
   ⚠️ Duplicated from classic-wheel-styles.css:366 ON PURPOSE — classic-wheel does
   not load this file and a converted picker does not load that one, which is the
   same arrangement the rest of the standard's CSS already has. Change one, change
   the other. */
.wsp-colour-ctl input[type="color"] { width: 34px; padding: 2px; }
.wsp-colour-ctl input[type="text"]  { width: 88px; }

/* ─────────────────────────────────────────────────────────────────────────────
 * BATCH 26 — the tabbed panel's own classes, ported from classic-wheel-styles.css.
 * ─────────────────────────────────────────────────────────────────────────────
 * classic-wheel.php loads classic-wheel-styles.css and NOT picker-ui.css; every
 * other converted picker loads picker-ui.css and NOT classic-wheel-styles.css.
 * The two files are meant to be equivalent for the SHARED components, and they
 * had drifted: seven classes used by tabs/entries.php and tabs/appearance.php
 * existed only in the classic-wheel copy. On the four batch-26 pages that showed
 * up immediately — "Clear all" is a bare <button> whose entire appearance lives
 * in .wsp-clear-all, so without it Bootstrap painted a lopsided grey box where
 * classic-wheel shows a red text link.
 * Copied VERBATIM, not re-derived (SKILLS rule 33). Change one, change the other.
 */

/* ── Entries tab ─────────────────────────────────────────────────────────── */
.wsp-add-entry .form-control:focus { box-shadow: none; }

.wsp-entries-list { max-height: 340px; }

/* A bare <button> styled as a text link. It carries NO .btn class — with one it
   inherited Bootstrap's border box, padding and focus ring, and the "text link"
   rendered as a lopsided red-outlined button. Everything it needs is here. */
.wsp-entries-foot { padding: 0.1rem 0.15rem; }

.wsp-entries-foot .wsp-clear-all {
  appearance: none;
  -webkit-appearance: none;
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  font-size: 0.8125rem;
  font-weight: 600;
  line-height: 1.2;
  color: var(--bs-danger, #dc3545);
  cursor: pointer;
  text-decoration: none;
  box-shadow: none;
}
.wsp-entries-foot .wsp-clear-all:hover { text-decoration: underline; }
.wsp-entries-foot .wsp-clear-all:focus-visible {
  outline: 2px solid var(--theme-accent, #4a5bd4);
  outline-offset: 2px;
  border-radius: 2px;
}

/* ── Appearance tab ──────────────────────────────────────────────────────── */
.wsp-btn-ctl { flex-wrap: wrap; justify-content: flex-end; }

/* A GROUP owns the separator, so a switch plus the row it reveals reads as one
   feature. */
.wsp-set-group { border-bottom: 1px solid var(--theme-border, #f0f2f4); }
.wsp-set-group .wsp-set { border-bottom: 0; }
.wsp-set-group:last-of-type { border-bottom: 0; }

/* The revealed row: indented and slightly quieter, so it reads as belonging to
   the switch above rather than competing with it. */
.wsp-set-follow {
  padding-left: 0.9rem;
  min-height: 2.1rem;
}
.wsp-set-follow .wsp-set-label {
  font-weight: 400;
  font-size: 0.8125rem;
  color: var(--theme-muted, #6c757d);
}

/* The settings column is narrower than the phone on mobile; let the entry rows
   use the width that is actually there. */
@media (max-width: 768px) {
  .wsp-entries-list { max-height: 46vh; }
}

/* ─────────────────────────────────────────────────────────────────────────────
 * BATCH 26b — a start control that is always reachable in FULLSCREEN.
 * ─────────────────────────────────────────────────────────────────────────────
 * A below-stage start button falls outside the fullscreen viewport once the
 * winner bar's --wsp-zen-bar-h slot is reserved: measured on center-spin, the
 * zen column is a fixed 824px, so from a ~800px window down the button sits at
 * y=740–789 against a 702px viewport and needs a scroll to reach (owner
 * 2026-08-21). This is the same failure the food pickers hit in batches 6–7.
 *
 * The reel's own geometry is load-bearing and cannot simply be shrunk: the
 * pointer is centred on .centerspin-reel-wrapper (top:50%) while the strip is
 * translated by an ABSOLUTE offset, so changing the wrapper height would move
 * the pointer off the winning item.
 *
 * So the control moves ONTO the stage for fullscreen only — normal view keeps
 * its familiar button untouched. It sits at the FOOT of the stage, inside the
 * container's existing padding, rather than dead-centre like the 16c overlay:
 * a reel's centre cell is exactly where the result appears.
 *
 * ⚠️ Not added to classic-wheel-styles.css (rule 38's pair): classic-wheel's
 * start control is already on its stage — the SPIN hub in the wheel's centre —
 * so it never had this problem and has no element with this class.
 */
.wsp-zen-start { display: none; }

/* ⚠️ NORMAL FLOW, NOT ABSOLUTE. This was absolutely positioned inside the stage
   with a padding strip reserved for it — symmetric only if every stage's content
   really ends at its padding box, and lucky-box's does not: its WINNING tile
   scales up on reveal and overflowed the strip, so the button still landed on
   top of it. In flow, directly after the stage, it is below the content on every
   engine by construction (owner 2026-08-21: "make a symmetry"). */
body.zen-mode .wsp-zen-start {
  display: flex;
  align-items: center;
  gap: .5rem;
  width: fit-content;
  margin: 14px auto 0;
  border: 0;
  border-radius: 999px;
  padding: .5rem 1.5rem;
  font-size: .95rem;
  font-weight: 800;
  letter-spacing: .04em;
  color: #fff;
  background: var(--theme-accent, #4a5bd4);
  cursor: pointer;
  box-shadow: 0 10px 26px -10px rgba(0, 0, 0, .7);
}
body.zen-mode .wsp-zen-start:hover { filter: brightness(1.08); }
body.zen-mode .wsp-zen-start:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 2px;
}
/* Hidden while a run is in progress — set by disableControls() in the engine.
   ⚠️ KEEP THE BOX. This was `display: none`, which removed 53px (button +
   margin) from the column — and the zen column is vertically CENTRED, so the
   stage jumped 26px at the START and again at the END of every run (owner
   2026-08-21: "almost all these spinners in full screen, shift the moment spin
   is over"). That is exactly the bug the winner bar's reserved slot exists to
   prevent, reintroduced by hiding a DIFFERENT element in the same column.
   Reserve the space the same way the bar does: keep the display, drop only the
   ink. */
body.zen-mode .wsp-zen-start[hidden] {
  display: flex !important;
  visibility: hidden;
  pointer-events: none;
}


/* ─────────────────────────────────────────────────────────────────────────────
 * BATCH 26c — the fullscreen winner-bar reservation, MEASURED per page.
 * ─────────────────────────────────────────────────────────────────────────────
 * `body.zen-mode .main-layout-left .wsp-result` above reserves
 * var(--wsp-zen-bar-h, 150px) so revealing the winner never shifts the stage.
 * These eight pages never set the variable, so they inherited the 150px
 * fallback while their bar actually fills to 78px — a 72px slab of dead space
 * under a one-line winner (owner 2026-08-21: "the winner card at the bottom is
 * too big in height.. since it doesn't have any extra lines").
 *
 * Measured, not guessed: every entry on every one of these pages was pushed
 * through the bar and the tallest result recorded. Nothing wraps at 78px —
 * "American Football" and "Cooking Together" both fit on one line. The three
 * combo pages show a COMBINATION of three reel values, which wraps to two lines,
 * and 110px covers even the longest possible combination on each of them
 * ("Poke Bowl + With Fries + Sparkling Water" = 110px).
 *
 * This is the value the reservation is FOR — not headroom. As the note above
 * says: headroom here is dead space at the bottom of the card.
 */
body.page-center-spin,
body.page-lucky-box,
body.page-coin-toss,
body.page-random-sport-picker,
body.page-surprise-gift-picker { --wsp-zen-bar-h: 78px; }

body.page-combo-spin,
body.page-meal-combo-picker,
body.page-date-night-picker { --wsp-zen-bar-h: 110px; }

/* ⚠️ IN FULLSCREEN THE CARD IS THE SCREEN, NOT A CARD. random-sport-picker's
   page CSS gives .main-layout-left .card a 2px accent border, which in normal
   view reads as the picker's identity but in fullscreen draws a second frame
   around the already-framed stage (owner 2026-08-21: "there is an outer orange
   type border again"). It is the only one of these eight with a card border —
   the other seven measure 0px — so this is page-scoped, not a blanket rule. */
body.zen-mode.page-random-sport-picker .main-layout-left > .card {
  border-color: transparent !important;
}

/* ─────────────────────────────────────────────────────────────────────────────
 * BATCH 27 — the fullscreen winner-bar reservation, MEASURED per page.
 * ─────────────────────────────────────────────────────────────────────────────
 * These 35 pages never set --wsp-zen-bar-h, so they inherited the 150px
 * fallback above while their bar fills to 78–150px. On a one-line winner that
 * is up to 72px of dead space under the card in fullscreen — the thing the
 * fallback's own note calls out: headroom here IS dead space.
 *
 * ⚠️ EVERY NUMBER IS THE PAGE'S OWN WORST CASE, not the height of one winner.
 * zen-bar-worst-case.js drives a real run, then swaps the winner name — AND the
 * verdict line, where the bar has one — to each of that page's own entries in
 * turn and takes the tallest. That matters: superhero-picker fills 118px on a
 * typical winner but 150px on "Powerhouse" once its verdict wraps, and
 * mlb / dc-character / nhl / ocean-animals / date-ideas are all taller than one
 * run suggested. Reserving the single-run number would have turned 72px of
 * slack into a STAGE JUMP, which is strictly worse.
 *
 * Re-measure with:  node writable/ui-tools/zen-bar-worst-case.js <slug>
 * Verify with:      node writable/ui-tools/zen-bar-reservation-sweep.js <slug>
 */

body.page-spin-the-wheel,
body.page-wheel-of-names,
body.page-prize-wheel,
body.page-yes-no-wheel,
body.page-restaurant-picker-wheel,
body.page-fast-food-picker { --wsp-zen-bar-h: 78px; }

/* ────────────────────────────────────────────────────────────────────────────
 * BATCH 28 — the 14 pages batch 27 held back, now MEASURED.
 * ────────────────────────────────────────────────────────────────────────────
 * Batch 27 left these 14 on the 150px fallback because zen-bar-worst-case.js
 * could not measure them. BOTH of the reasons recorded at the time were wrong,
 * and re-measuring found the real ones (2026-08-21):
 *
 * 1. The 8 food pages did NOT lack a roster. FERRIS_CONFIG carries `dishes`
 *    (15–27 entries of {slug,label,verdict}) and the engine re-exposes it as
 *    WhatToEatWheel._dishes — but the tool required a key literally named
 *    `items`, so it reported NO ENTRIES on a roster in plain sight. It now
 *    finds entries by SHAPE (SKILLS rule 36).
 *
 * 2. The conversation family's winner DOES reach .wsp-result-name — measured
 *    non-empty on every run. The real cause: `.wsp-result-body::before` is a
 *    float:right spacer sized from the action buttons, and this family's kicker
 *    is "<player> · <CATEGORY>". A slightly longer player drops the kicker
 *    BELOW the float and the whole bar grows 17px:
 *        Mia / Leo / Zoe      kicker 16px → bar  97px
 *        Alex / Sam / Jordan  kicker 33px → bar 114px
 *    The tool varied only .wsp-result-name, so it returned 97 or 114 for the
 *    SAME page depending on who won that run — and 97 was the number declared,
 *    which is why the sweep later caught the 114px UNDER. It now varies the
 *    kicker across the page's own roster too (SKILLS rule 44).
 *
 * ⚠️ conversation-starter-picker is the ONLY one of the six that crosses the
 * wrap threshold: its category tail is the longest, so 114px. The other five
 * measure a flat 97px across all six of their players.
 *
 * ⚠️ what-to-eat-picker and world-cuisine-picker need 150px — the same as the
 * fallback, but now DECLARED rather than inherited. "Fried Chicken" and
 * "Mediterranean" are the only labels on those pages that wrap to two lines
 * (64px vs 32px); three real runs never drew either, which is exactly why the
 * reservation comes from a worst-case sweep and never from one run's fill.
 *
 * Re-measure with:  node writable/ui-tools/zen-bar-worst-case.js --runs=3 <slug>
 * Verify with:      node writable/ui-tools/zen-bar-reservation-sweep.js <slug>
 */

/* the conversation family — kicker "<player> · <CATEGORY>" */
body.page-truth-or-dare-wheel,
body.page-would-you-rather-picker,
body.page-never-have-i-ever-picker,
body.page-icebreaker-picker,
body.page-deep-questions-picker { --wsp-zen-bar-h: 97px; }

body.page-conversation-starter-picker { --wsp-zen-bar-h: 114px; }

/* the ferris / revolving-table food pages — label + verdict */
body.page-street-food-picker,
body.page-breakfast-picker,
body.page-cocktail-recipe-picker,
body.page-coffee-order-picker,
body.page-desserts-picker,
body.page-healthy-food-picker { --wsp-zen-bar-h: 133px; }

body.page-what-to-eat-picker,
body.page-world-cuisine-picker { --wsp-zen-bar-h: 150px; }

/* BATCH 30 — dice-roll. It was the site's LAST UNDER (reserved 0, filled 92)
   because it loaded NEITHER picker-ui.css nor classic-wheel-styles.css, so the
   reservation mechanism never reached it. The conversion adds picker-ui.css;
   this is its measured worst case, corroborated by three real rolls. */
body.page-dice-roll { --wsp-zen-bar-h: 92px; }

body.page-animal-picker-wheel,
body.page-nba-team-picker-wheel,
body.page-nfl-team-picker-wheel,
body.page-premier-league-picker-wheel,
body.page-cricket-team-picker,
body.page-fifa-team-picker,
body.page-pets-picker,
body.page-disney-princess-picker,
body.page-ai-chatbot-picker { --wsp-zen-bar-h: 101px; }

body.page-date-ideas-picker { --wsp-zen-bar-h: 110px; }

body.page-nhl-team-picker-wheel,
body.page-ipl-team-picker,
body.page-psl-team-picker,
body.page-insects-picker,
body.page-ocean-animals-picker,
body.page-ai-coding-assistant-picker,
body.page-ai-image-generator-picker,
body.page-ai-startup-idea-picker,
body.page-ai-video-generator-picker { --wsp-zen-bar-h: 133px; }

body.page-superhero-picker,
body.page-disney-character-picker,
body.page-mlb-team-picker-wheel,
body.page-dc-character-picker { --wsp-zen-bar-h: 150px; }

/* ── WHEEL-THEME TILES ───────────────────────────────────────────────────────
   Owner 2026-08-22, of giveaway-wheel: "themes should be same as classic wheel
   style". classic-wheel's Appearance tab renders the palettes as mini-wheel
   previews via advance/wheel-palette.php with $wheel_palette_tiles = true.
   ⚠️ That partial's own note says the tile styling "lives in
   classic-wheel-styles.css" — and a converted picker loads THIS file instead,
   so the tiles came out unstyled. SKILLS rule 38 (these two stylesheets drift)
   and rule 48 (a class existing in SOME stylesheet proves nothing).
   Ported VERBATIM from classic-wheel-styles.css:596-631, exactly as batch 26
   ported 7 classes for the same reason. Change one, change the other.
   The `.wheel-pal*` BASE styling is not here — it is in a <style> block inside
   wheel-palette.php itself, so it travels with the partial. */

/* 5 across -> the nine palettes fit in two rows instead of three. */
.wheel-pal-row.wsp-pal-tiles {
  grid-template-columns: repeat(5, 1fr);
  gap: 5px;
  margin-bottom: 0.25rem;
}

.wsp-pal-tiles .wheel-pal {
  align-items: center;
  text-align: center;
  padding: 5px 2px;
  gap: 3px;
}

/* The mini wheel preview. The conic-gradient is written by renderPalettes(). */
.wsp-pal-tiles .wheel-pal-disc {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: 1px solid rgba(0, 0, 0, .12);
  box-shadow: inset 0 0 0 2px var(--theme-surface, #fff);
}

.wsp-pal-tiles .wheel-pal-nm {
  font-size: 9.5px;
  line-height: 1.1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
}

@media (max-width: 420px) {
  .wheel-pal-row.wsp-pal-tiles { grid-template-columns: repeat(4, 1fr); }
}

/* ─────────────────────────────────────────────────────────────────────────────
 * MOBILE WORST CASE — what the winner bar actually fills to at 390px (2026-08-25)
 * ─────────────────────────────────────────────────────────────────────────────
 * Swept with:  node writable/ui-tools/zen-bar-worst-case.js --size=390x844 <slug>
 * over each page's OWN roster, varying the name AND the kicker, on 117 page(s).
 *
 * These are ABSOLUTE reservations for <=480px, not addends — see the rule above.
 * Each one replaces the shared default (--wsp-zen-bar-h + one button row), which
 * is structurally right but blind to how much a given page's text wraps at a
 * 326px content width: it under-reserved conversation-starter-picker by 25px and
 * over-reserved random-picker by 32px.
 *
 * A page NOT listed here keeps the shared default on purpose — it is one of the
 * 30 the sweep refused (no winner bar at all, no findable roster, or unmeasured),
 * and an invented number would be worse than the structural one.
 */
body.page-center-spin,
body.page-fast-food-picker,
body.page-lucky-box,
body.page-prize-wheel,
body.page-random-sport-picker,
body.page-restaurant-picker-wheel,
body.page-spin-the-wheel,
body.page-surprise-gift-picker,
body.page-wheel-of-names,
body.page-yes-no-wheel { --wsp-zen-bar-mobile: 121px; }

body.page-dice-roll { --wsp-zen-bar-mobile: 126px; }

body.page-ai-chatbot-picker,
body.page-ai-coding-assistant-picker,
body.page-ai-image-generator-picker,
body.page-ai-video-generator-picker,
body.page-breakfast-picker,
body.page-classroom-wheel,
body.page-cricket-team-picker,
body.page-decision-wheel,
body.page-name-from-a-hat,
body.page-random-name-picker,
body.page-random-picker,
body.page-workout-picker { --wsp-zen-bar-mobile: 144px; }

body.page-combo-spin,
body.page-date-ideas-picker { --wsp-zen-bar-mobile: 153px; }

body.page-animal-picker-wheel,
body.page-birds-picker,
body.page-card-game-picker,
body.page-cartoon-character-picker,
body.page-coffee-order-picker,
body.page-desserts-picker,
body.page-disney-princess-picker,
body.page-draft-order-generator,
body.page-f1-track-picker,
body.page-fifa-team-picker,
body.page-hobby-picker,
body.page-marvel-character-picker,
body.page-minecraft-mob-picker,
body.page-mlb-team-picker-wheel,
body.page-nba-team-picker-wheel,
body.page-nfl-team-picker-wheel,
body.page-pets-picker,
body.page-premier-league-picker-wheel,
body.page-sandbox-game-picker,
body.page-street-food-picker,
body.page-superhero-picker,
body.page-video-game-genre-picker,
body.page-what-to-eat-picker,
body.page-world-cuisine-picker { --wsp-zen-bar-mobile: 164px; }

body.page-deep-questions-picker,
body.page-icebreaker-picker,
body.page-never-have-i-ever-picker,
body.page-truth-or-dare-wheel,
body.page-would-you-rather-picker { --wsp-zen-bar-mobile: 166px; }

body.page-ai-startup-idea-picker,
body.page-board-game-picker,
body.page-business-idea-picker,
body.page-dinner-ideas-picker,
body.page-dinosaur-picker,
body.page-drawing-ideas-picker,
body.page-esports-game-picker,
body.page-fps-game-picker,
body.page-gym-exercise-picker,
body.page-healthy-food-picker,
body.page-home-workout-picker,
body.page-horror-game-picker,
body.page-indie-game-picker,
body.page-mobile-game-picker,
body.page-nhl-team-picker-wheel,
body.page-party-game-picker,
body.page-psl-team-picker,
body.page-racing-game-picker,
body.page-roblox-game-picker,
body.page-rpg-game-picker,
body.page-school-subject-picker,
body.page-self-care-picker,
body.page-strategy-game-picker,
body.page-tiktok-ideas-picker,
body.page-yoga-pose-picker,
body.page-youtube-ideas-picker { --wsp-zen-bar-mobile: 176px; }

body.page-disney-character-picker,
body.page-disney-villain-picker { --wsp-zen-bar-mobile: 180px; }

body.page-conversation-starter-picker { --wsp-zen-bar-mobile: 182px; }

body.page-hp-character-picker,
body.page-hp-professor-picker,
body.page-hp-spell-picker,
body.page-hp-wand-picker { --wsp-zen-bar-mobile: 184px; }

body.page-date-night-picker,
body.page-meal-combo-picker { --wsp-zen-bar-mobile: 185px; }

body.page-dc-character-picker,
body.page-goal-picker,
body.page-habit-picker,
body.page-minecraft-biome-picker,
body.page-minecraft-challenge-picker,
body.page-minecraft-item-picker,
body.page-ocean-animals-picker,
body.page-retro-game-picker,
body.page-superpower-picker { --wsp-zen-bar-mobile: 196px; }

body.page-hp-creature-picker,
body.page-hp-location-picker,
body.page-river-picker { --wsp-zen-bar-mobile: 204px; }

body.page-comment-picker,
body.page-instagram-comment-picker,
body.page-ipl-team-picker,
body.page-kindness-picker,
body.page-retweet-picker,
body.page-social-media-picker,
body.page-twitter-reply-picker,
body.page-writing-prompt-picker,
body.page-youtube-comment-picker { --wsp-zen-bar-mobile: 208px; }

body.page-cartoon-villain-picker,
body.page-villain-picker { --wsp-zen-bar-mobile: 212px; }

body.page-mountain-picker,
body.page-tourist-destination-picker { --wsp-zen-bar-mobile: 216px; }

body.page-hp-book-picker { --wsp-zen-bar-mobile: 224px; }

body.page-tiktok-comment-picker { --wsp-zen-bar-mobile: 240px; }

body.page-story-starter-picker { --wsp-zen-bar-mobile: 241px; }
