/* ============================================================================
   mobile.css — Mobile-only overrides (html.mobile-ui scope).

   MHUR Tuning Optimizer — fan-made tool for My Hero Ultra Rumble.
   Author: RDH
   ============================================================================ */

/* ============================================================================
   MOBILE-ONLY UI (mobile.css + mobile.js)
   ----------------------------------------------------------------------------
   An app-style interface used ONLY on phones - both the mobile-browser site
   and the installed "Add to Home Screen" PWA (they share these exact styles;
   the only PWA-specific parts are the env(safe-area-inset-*) paddings, which
   are 0 in a normal browser tab).

   HOW IT ACTIVATES: mobile.js watches matchMedia("(max-width: 820px)") and
   toggles the `mobile-ui` class on <html>. EVERY layout-changing rule in this
   file is scoped under `html.mobile-ui`, so desktop never sees any of it, and
   resizing a desktop window across the breakpoint cleanly switches both ways.
   The injected chrome elements (tab bar, view switcher, quick bar, page
   title) stay in the DOM when mobile-ui turns off - they're display:none by
   default and only shown under html.mobile-ui, so no teardown is needed.

   DESIGN INTENT: this is the same product identity as desktop (dark panels,
   gold accents, the hero-blue → villain-red gradient as the brand thread) -
   not a new theme. The gradient that paints the desktop brand title is
   reused as the active-tab treatment in the bottom bar, which is the one
   deliberate "signature" of the mobile UI. Everything else stays quiet:
   bigger tap targets, one-column flow, bottom-sheet modals.
   ========================================================================= */

/* Injected chrome is inert unless the mobile UI is active. */
.m-tabbar, .m-viewswitch, .m-quickbar, .m-page-title { display: none; }
html:not(.mobile-ui) .m-only { display: none !important; }

/* ---------------------------------------------------------------- base --- */
html.mobile-ui body {
  font-size: 14.5px;
  /* Clear the fixed bottom tab bar (+ home indicator on notched phones). */
  padding-bottom: calc(66px + env(safe-area-inset-bottom));
}
/* Build editor also has the floating quick bar above the tab bar. */
html.mobile-ui.m-page-build body {
  padding-bottom: calc(122px + env(safe-area-inset-bottom));
}

/* -------------------------------------------------------------- header --- */
/* The header stops being sticky on mobile - persistent navigation moves to
   the bottom tab bar instead, and content gets the full screen back while
   scrolling (the optimizer's Setup/Results switcher is the one thing that
   stays pinned, below). */
html.mobile-ui header.top {
  position: static;
  padding: 9px 12px;
  padding-top: calc(9px + env(safe-area-inset-top));
  gap: 8px;
}
html.mobile-ui header.top h1 { font-size: 14px; }
html.mobile-ui header.top .sub { display: none; }
/* On mobile the desktop nav links and the page-name label are hidden; the header
   Sign in / account button takes the top-right slot instead (it toggles between
   "Sign in" and the user's display name via auth.js). display:contents keeps the
   .top-nav box out of the header flex row so its button child joins the header;
   it auto-reverts to the normal desktop nav when the mobile-ui class comes off. */
html.mobile-ui .top-nav { display: contents; }
html.mobile-ui .top-nav a { display: none; }
html.mobile-ui .m-page-title { display: none; }
html.mobile-ui .auth-nav-btn { margin-left: auto; }

/* ------------------------------------------------------ bottom tab bar --- */
html.mobile-ui .m-tabbar {
  display: flex;
  align-items: stretch;
  gap: 4px;
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 150;
  background: rgba(10, 14, 23, .97);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border-top: 1px solid var(--border);
  padding: 6px max(10px, env(safe-area-inset-right)) calc(6px + env(safe-area-inset-bottom)) max(10px, env(safe-area-inset-left));
}
/* Clash Royale style: inactive tabs are icon-only equal-width cells; the
   active tab grows into a raised highlighted card with its label revealed.
   Everything animates via flex-grow + max-width/opacity transitions, so
   tapping a tab visibly EXPANDS it rather than snapping. */
html.mobile-ui .m-tab {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: row;          /* icon + label side by side, like CR */
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 10px 6px;
  text-decoration: none;
  color: var(--text-dim);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .02em;
  border-radius: 12px;
  border: 1px solid transparent;
  position: relative;
  -webkit-tap-highlight-color: transparent;
  transition:
    flex-grow .32s cubic-bezier(.4, 0, .2, 1),
    background .32s ease,
    border-color .32s ease,
    box-shadow .32s ease;
}
html.mobile-ui .m-tab .m-tab-icon {
  font-size: 21px;
  line-height: 1;
  transition: transform .32s cubic-bezier(.34, 1.4, .5, 1);
}
/* Inactive labels: fully collapsed (zero width + invisible) so the tab is a
   pure icon cell. max-width (not display) so the reveal can animate. */
html.mobile-ui .m-tab .m-tab-label {
  white-space: nowrap;
  overflow: hidden;
  max-width: 0;
  opacity: 0;
  transform: translateX(-4px);
  transition:
    max-width .32s cubic-bezier(.4, 0, .2, 1),
    opacity .22s ease .06s,
    transform .32s cubic-bezier(.4, 0, .2, 1);
}
html.mobile-ui .m-tab:active .m-tab-icon { transform: scale(.88); }

/* ---- Active tab: expands into a raised card ---- */
html.mobile-ui .m-tab[aria-current="page"] {
  flex-grow: 2.4;
  background: linear-gradient(180deg, var(--panel-2), var(--panel));
  border-color: var(--border-strong, var(--border));
  box-shadow:
    0 -2px 10px rgba(0, 0, 0, .35),
    inset 0 1px 0 rgba(255, 255, 255, .05);
}
html.mobile-ui .m-tab[aria-current="page"] .m-tab-icon {
  transform: scale(1.12);
}
html.mobile-ui .m-tab[aria-current="page"] .m-tab-label {
  max-width: 110px;
  opacity: 1;
  transform: translateX(0);
  font-weight: 800;
  background: linear-gradient(90deg, var(--hero), var(--villain));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
/* Gradient indicator above the active card */
html.mobile-ui .m-tab[aria-current="page"]::before {
  content: "";
  position: absolute;
  top: -7px; left: 18%; right: 18%;
  height: 3px;
  border-radius: 0 0 3px 3px;
  background: linear-gradient(90deg, var(--hero), var(--villain));
  animation: m-indicator-in .32s cubic-bezier(.4, 0, .2, 1);
}
@keyframes m-indicator-in {
  from { left: 45%; right: 45%; opacity: 0; }
  to   { left: 18%; right: 18%; opacity: 1; }
}

/* ------------------------------------- optimizer: Setup / Results flow --- */
/* The desktop sidebar+results two-pane becomes two full screens on a phone,
   switched by a pinned segmented control. Same DOM, same handlers - the
   switcher only toggles which pane is visible. */
html.mobile-ui .m-viewswitch {
  display: flex;
  position: sticky;
  top: 0;
  z-index: 60;
  gap: 6px;
  margin: 0;
  /* Padding is CONSTANT and the status-bar clearance comes from the sticky
     `top` offset instead. It used to be the other way round - .is-stuck added
     env(safe-area-inset-top) to padding-top the moment the switcher pinned -
     but that grew the element's height mid-scroll, which reflowed everything
     below it and made the whole page visibly jump the instant you scrolled
     down from the top. Only ever showed up in the installed PWA, because the
     inset is 0 in a normal browser tab so the growth was 0px there.
     Pinning at `top: inset` keeps the height fixed (no reflow, no jump) while
     still parking the buttons below the status bar/notch. At rest the offset
     is inert - sticky `top` does nothing until the element actually pins. */
  padding: 7px 10px;
  top: env(safe-area-inset-top);
  background: rgba(14, 17, 22, .94);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border);
}
/* Because it pins at `top: inset` rather than 0, the strip between the top of
   the display and the switcher would show page content sliding underneath it.
   This fills that strip - but only while pinned, since at the top of the page
   the same strip is the header's own notch padding and must stay visible.
   Toggling opacity is paint-only, so it can't reintroduce the jump. */
html.mobile-ui .m-viewswitch::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 100%;
  height: env(safe-area-inset-top);
  background: inherit;
  opacity: 0;
  pointer-events: none;
}
html.mobile-ui .m-viewswitch.is-stuck::before { opacity: 1; }
html.mobile-ui .m-stick-sentinel { height: 1px; margin: 0; padding: 0; }
/* Throwaway element mobile.js measures to learn the safe-area inset in px;
   env() isn't readable from JS any other way. Never visible. */
html.mobile-ui .m-inset-probe {
  position: absolute;
  top: 0;
  left: 0;
  width: 0;
  height: env(safe-area-inset-top);
  visibility: hidden;
  pointer-events: none;
}
html.mobile-ui .m-viewswitch button {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  border: 1px solid var(--border);
  background: var(--panel);
  color: var(--text-dim);
  font-size: 13px;
  font-weight: 700;
  padding: 9px 8px;
  border-radius: 10px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
html.mobile-ui .m-viewswitch button[aria-pressed="true"] {
  background: linear-gradient(90deg, var(--hero), var(--villain));
  border-color: transparent;
  color: #fff;
}
html.mobile-ui .m-badge {
  min-width: 19px;
  padding: 1px 6px;
  border-radius: 10px;
  background: var(--gold-dim);
  border: 1px solid var(--gold);
  color: var(--gold);
  font-size: 10.5px;
  font-weight: 800;
  text-align: center;
}
html.mobile-ui .m-viewswitch button[aria-pressed="true"] .m-badge {
  background: rgba(0, 0, 0, .35);
  border-color: rgba(255, 255, 255, .55);
  color: #fff;
}
@keyframes m-badge-pop {
  0% { transform: scale(1); }
  40% { transform: scale(1.35); }
  100% { transform: scale(1); }
}
html.mobile-ui .m-badge.m-badge-pulse { animation: m-badge-pop .5s ease; }

/* Pane switching (index page only). Panes slide in from their spatial side
   (setup lives left of results), so switching feels like moving between two
   screens of one app rather than content popping in. The animation runs
   whenever a pane transitions display:none -> visible, which is exactly the
   moment data-mview flips. Swiping horizontally also drives this (mobile.js). */
html.mobile-ui.m-page-index[data-mview="setup"] .layout .main { display: none; }
html.mobile-ui.m-page-index[data-mview="results"] .layout .sidebar { display: none; }
html.mobile-ui.m-page-index[data-mview="setup"] .layout .sidebar {
  animation: m-pane-in-left .26s cubic-bezier(.25, .1, .25, 1);
}
html.mobile-ui.m-page-index[data-mview="results"] .layout .main {
  animation: m-pane-in-right .26s cubic-bezier(.25, .1, .25, 1);
}
@keyframes m-pane-in-left {
  from { transform: translateX(-26px); opacity: .35; }
  to   { transform: translateX(0);     opacity: 1; }
}
@keyframes m-pane-in-right {
  from { transform: translateX(26px); opacity: .35; }
  to   { transform: translateX(0);    opacity: 1; }
}

/* ------------------------------------------------------ layout / panels --- (RDH) */
html.mobile-ui .layout { padding: 10px 10px 4px; gap: 10px; }
html.mobile-ui .build-layout { padding: 10px 10px 4px; gap: 4px; }
html.mobile-ui .panel { padding: 12px; border-radius: 12px; }
html.mobile-ui .panel + .panel { margin-top: 10px; }
html.mobile-ui .panel h2 { font-size: 13px; }
html.mobile-ui .footer-note { padding: 18px 14px 8px; }

/* Collapsible setup sections (optimizer sidebar): the section heading is the
   whole tap target, with a chevron that flips when collapsed. mobile.js adds
   .m-acc to the sidebar panels and toggles .m-collapsed on heading taps. */
html.mobile-ui .m-acc > h2 {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  margin: -12px;
  /* No extra bottom margin when expanded: the heading's own 12px padding-bottom
     already gives a clean gap to the content below. The previous 8px here stacked
     on top of that padding into a ~20px band that felt too loose on mobile.
     (Collapsed state overrides this to -12px to pull the box edge-to-edge.) */
  margin-bottom: 0;
  padding: 12px;
  -webkit-tap-highlight-color: transparent;
}
html.mobile-ui .m-acc > h2::after {
  content: "⌄";
  font-size: 15px;
  color: var(--text-dim);
  transition: transform .18s ease;
  transform: rotate(0deg);
}
html.mobile-ui .m-acc.m-collapsed > h2 { margin-bottom: -12px; }
html.mobile-ui .m-acc.m-collapsed > h2::after { transform: rotate(-90deg); }
html.mobile-ui .m-acc.m-collapsed > *:not(h2) { display: none !important; }

/* ------------------------------------------------------------- results --- */
html.mobile-ui .results-head { margin: 8px 2px 10px; }
html.mobile-ui .results-head h2 { font-size: 14.5px; }
html.mobile-ui .results-grid {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}
html.mobile-ui .costume-card .imgwrap { height: 120px; }
html.mobile-ui .costume-card .body { padding: 7px 9px 9px; gap: 3px; }
html.mobile-ui .costume-card .cname { font-size: 12px; }
html.mobile-ui .costume-card:hover { transform: none; } /* no hover-lift on touch */
html.mobile-ui .costume-card:active { border-color: var(--gold); }

/* Larger phones / small tablets in the mobile range get a third results
   column so cards don't feel oversized on wider screens. */
@media (min-width: 560px) and (max-width: 820px) {
  html.mobile-ui .results-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  html.mobile-ui .builds-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ------------------------------------------------- bottom-sheet modals --- */
html.mobile-ui .modal-overlay { padding: 0; align-items: flex-end; }
html.mobile-ui .modal {
  max-width: 100%;
  width: 100%;
  max-height: 90vh;
  max-height: 90dvh;
  border-radius: 18px 18px 0 0;
  border-bottom: none;
  padding-bottom: calc(10px + env(safe-area-inset-bottom));
  animation: m-sheet-up .22s ease-out;
}
html.mobile-ui .modal::before {
  content: "";
  display: block;
  width: 44px;
  height: 4px;
  border-radius: 2px;
  background: var(--border);
  margin: 10px auto 0;
}
@keyframes m-sheet-up {
  from { transform: translateY(24px); opacity: .6; }
  to { transform: translateY(0); opacity: 1; }
}
html.mobile-ui .modal-close { width: 40px; height: 40px; font-size: 19px; }
html.mobile-ui .modal-top { padding: 12px 16px 16px; }
html.mobile-ui .modal-section { padding: 14px 16px; }

/* -------------------------------------------------- inputs / tap targets --- */
html.mobile-ui select,
html.mobile-ui input[type="text"] { padding: 12px 12px; border-radius: 10px; }
html.mobile-ui input[type="checkbox"] { width: 18px; height: 18px; }
html.mobile-ui .skill-row { padding: 10px 11px; }
/* Effects search ☰ menu: rows are the real tap targets once it's open. */
html.mobile-ui .ssm-option { padding: 12px 12px; font-size: 14px; }
html.mobile-ui .skill-search-menu-btn {
  width: 46px;
  font-size: 17px;
  /* Match the mobile input's larger corner radius, or the button's square
     corner pokes out past the field's rounded one. */
  border-radius: 0 10px 10px 0;
}
/* ⚠️ The rule above at line ~352 (`html.mobile-ui input[type="text"]`) resets
   padding to `12px 12px`, which WIPES the right padding that keeps typed text
   and the placeholder clear of the ☰ - the words ran underneath it, so the
   button looked like it had text inside. It out-specifies a plain
   `.skill-search` (0,2,2 vs 0,1,0), so restoring the gap needs a selector that
   beats it: this one is (0,3,2). Keep it >= 46px button + breathing room. */
html.mobile-ui .skill-search-wrap input.skill-search {
  padding-right: 56px;
}
/* About page: the TOC is two columns on desktop, unreadable at phone width. */
html.mobile-ui .about-toc ol { columns: 1; line-height: 2.1; }
html.mobile-ui .about-link { flex-basis: 100%; }
html.mobile-ui .skill-list { max-height: 300px; }
/* Filter pills get bigger touch targets on phones (44px-ish rows once padding
   and line-height are counted) and are allowed to wrap onto two lines rather
   than shrinking below a comfortable tap size. */
html.mobile-ui .skill-cat-btn { padding: 8px 14px; font-size: 13px; }
html.mobile-ui .skill-cat-filters { gap: 7px; margin: 9px 0 10px; }
html.mobile-ui .chip { padding: 6px 11px; font-size: 12.5px; }
html.mobile-ui .fs-option, html.mobile-ui .cs-option { padding: 12px 12px; font-size: 14px; }
html.mobile-ui .face-select-list, html.mobile-ui .char-select-list {
  max-height: 46vh;
  /* Mobile scroll hardening (2026-07-15) — RDH. Symptom: scrolling the special-
     tuning list would work for a few seconds then lock up completely, in both ST1
     and ST2. Cause: this list is a nested scroll region living inside the RELOCATED
     special-tuning bar; when momentum scrolling hit the list's top/bottom the touch
     was handed to an ancestor that can't scroll, orphaning subsequent touches and
     freezing the list. These three properties keep the scroll owned by the list:
     - overscroll-behavior: contain  → the boundary bounce never leaks to the page
     - -webkit-overflow-scrolling: touch → proper momentum scrolling on iOS
     - touch-action: pan-y → the list claims vertical drags outright */
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  touch-action: pan-y;
}
/* The options wrapper is the actual scrolled content; make sure vertical panning is
   never intercepted by a parent gesture handler. The sticky search box above it can
   otherwise cause iOS to lose the scroll target after a repaint. */
html.mobile-ui .fs-options {
  touch-action: pan-y;
  overscroll-behavior: contain;
}
/* On iOS a position:sticky child inside a -webkit-overflow-scrolling:touch region
   can drop the scroll target mid-momentum (the exact "freezes after a few seconds"
   report). The search field doesn't need to be sticky on mobile — the list is short
   and the ☰ opener already gives a no-keyboard path — so pin it static here. */
html.mobile-ui .fs-search { position: static; }
html.mobile-ui .face-select-btn, html.mobile-ui .char-display-btn { padding: 12px 12px; border-radius: 10px; }
html.mobile-ui .costume-picker-grid { grid-template-columns: repeat(auto-fill, minmax(86px, 1fr)); max-height: 300px; }
html.mobile-ui .create-build-btn, html.mobile-ui .publish-btn {
  padding: 12px 16px;
  font-size: 14px;
  border-radius: 11px;
}
html.mobile-ui .build-save-row { gap: 10px; }
html.mobile-ui .build-save-row .create-build-btn,
html.mobile-ui .build-save-row .publish-btn { flex: 1 1 46%; }

/* ------------------------------------------- My Builds / Community pages --- */
html.mobile-ui .sort-tabs {
  flex-wrap: nowrap;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  padding-bottom: 4px;
  margin-right: -12px;
  padding-right: 12px;
}
html.mobile-ui .sort-tabs::-webkit-scrollbar { display: none; }
html.mobile-ui .sort-tab { white-space: nowrap; padding: 9px 14px; font-size: 13px; flex-shrink: 0; }
html.mobile-ui .build-search-input { padding: 12px 14px; border-radius: 11px; }
html.mobile-ui .builds-grid { grid-template-columns: 1fr; gap: 10px; margin-top: 12px; }
html.mobile-ui .build-card { padding: 0; border-radius: 13px; }
html.mobile-ui .bc-head { padding: 10px 11px; }
html.mobile-ui .bc-portrait { width: 42px; height: 52px; }
html.mobile-ui .build-card .bc-info { padding: 10px 11px 11px; gap: 9px; }
html.mobile-ui .build-card .bc-name { font-size: 13.5px; }
html.mobile-ui .build-card button { font-size: 12px; padding: 7px 9px; border-radius: 7px; }
html.mobile-ui .tag-chip { padding: 8px 13px; font-size: 13px; }
html.mobile-ui .preview-banner { font-size: 12px; padding: 10px 12px; border-radius: 11px; }

/* -------------------------------------------------------- build editor --- (RDH) */
html.mobile-ui .undo-btn { padding: 8px 10px; font-size: 12px; border-radius: 8px; }
html.mobile-ui .build-slot-select { padding: 10px 9px; border-radius: 9px; font-size: 13.5px; }
html.mobile-ui .build-face-select .face-select-btn { padding: 10px 9px; }
/* Mobile split trigger: reveal the ☰ end-cap, which opens the list WITHOUT the
   keyboard. The main (left) part of the same rectangle still opens the list with
   the search field focused, for anyone who wants to type. The ▾ chevron is hidden
   because the ☰ is now the affordance. (RDH) */
html.mobile-ui .fs-menu-btn { display: flex; }
html.mobile-ui .build-face-select .face-select-btn::after { display: none; }
/* Same for any split trigger (e.g. the optimizer's special-tuning selects):
   once the hamburger is the affordance, the chevron is noise. */
html.mobile-ui .fs-trigger .face-select-btn::after { display: none; }

/* Build editor panel: tighter header row on small screens */
html.mobile-ui .build-editor-panel > div:first-child { flex-wrap: wrap; gap: 8px; }
html.mobile-ui .build-editor-panel > div:first-child > div { flex-wrap: wrap; gap: 6px; }

/* Center the "Build your loadout" header + its button row on mobile — the
   left-aligned heading with wrapped buttons underneath read as asymmetrical.
   (2026-07-17, user request; may be reverted if it doesn't look right.) */
html.mobile-ui .build-editor-panel > div:first-child {
  justify-content: center;
  text-align: center;
}
html.mobile-ui .build-editor-panel > div:first-child > h2 {
  width: 100%;
}
html.mobile-ui .build-editor-panel > div:first-child > div {
  justify-content: center;
  width: 100%;
}
html.mobile-ui .build-editor-panel > .build-hint { text-align: center; }

/* Same centering for the "Save & Share" and "Shareable Build Card" panels */
html.mobile-ui .build-save-panel > h2,
html.mobile-ui .build-card-panel > h2,
html.mobile-ui .build-card-panel > .build-hint {
  text-align: center;
}

/* Slot grid: 1 column (LEFT then RIGHT stacked) on narrow phones */
html.mobile-ui .build-slot-grid {
  grid-template-columns: 1fr;
  gap: 16px;
}

/* Save & Share panel: stack buttons vertically, full width */
html.mobile-ui .build-save-row {
  flex-direction: column;
  gap: 8px;
}
html.mobile-ui .build-save-row .create-build-btn,
html.mobile-ui .build-save-row .publish-btn {
  flex: none;
  width: 100%;
}
html.mobile-ui .create-build-btn, html.mobile-ui .publish-btn {
  padding: 12px 14px;
  font-size: 14px;
  border-radius: 11px;
}

/* ---- Build detail modal (community "preview"): phone button ORDER ----
   DOM order is the PC order [Copy Build][View Tuning Totals][Copy Link];
   Robert's phone spec puts Totals first. Flex `order` reorders visually
   without touching the DOM, so desktop stays untouched. (2026-07-24) */
html.mobile-ui .bd-actions #bdTotalsBtn { order: 1; }
html.mobile-ui .bd-actions #bdCopyBuildBtn { order: 2; }
html.mobile-ui .bd-actions #bdCopyLinkBtn { order: 3; }

/* ---- Build page (build-view): collapse action buttons to a compact icon
   row so the Discussion section is visible without scrolling past four
   full-width stacked buttons. Labels are hidden, icons shown; every button
   keeps its aria-label + title for assistive tech and long-press. ---- */
html.mobile-ui .bv-actions {
  flex-direction: row;      /* undo the generic column stacking above */
  flex-wrap: nowrap;
  gap: 8px;
}
html.mobile-ui .bv-actions .create-build-btn,
html.mobile-ui .bv-actions .publish-btn {
  flex: 1 1 0;              /* equal-width compact row */
  width: auto;
  min-width: 0;
  padding: 11px 0;          /* ~44px touch target with the 16px icon */
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
html.mobile-ui .bv-actions .btn-label { display: none; }
html.mobile-ui .bv-actions .btn-ico { font-size: 17px; line-height: 1; }

/* Desktop shows labels; the icon doubles as a small glyph prefix there. */


/* Build card panel: bleed to screen edges so the card fills the full width */
html.mobile-ui .build-card-panel {
  margin-left: -10px;
  margin-right: -10px;
  padding-left: 6px;
  padding-right: 6px;
  border-left: none;
  border-right: none;
  border-radius: 0;
}

/* Build costume head: tighter on mobile */
html.mobile-ui .build-costume-panel { padding: 10px 12px; }

/* Build hint text: slightly smaller */
html.mobile-ui .build-hint { font-size: 12.5px; line-height: 1.5; margin-bottom: 10px; }

/* Tag picker chips */
html.mobile-ui .tag-chip { padding: 7px 11px; font-size: 12.5px; }

/* Build name input */
html.mobile-ui #buildNameInput { font-size: 15px; padding: 11px 12px; }

/* Floating quick actions on the Build Editor - shortcuts that just click the
   real Save / Totals buttons, pinned above the tab bar. */
html.mobile-ui .m-quickbar {
  display: flex;
  position: fixed;
  left: 12px; right: 12px;
  bottom: calc(64px + env(safe-area-inset-bottom));
  z-index: 140;
  gap: 10px;
}
html.mobile-ui .m-quickbar button {
  flex: 1;
  border: 1px solid var(--gold);
  background: rgba(22, 27, 34, .96);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  color: var(--gold);
  font-size: 13.5px;
  font-weight: 700;
  padding: 12px 10px;
  border-radius: 12px;
  cursor: pointer;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .45);
  -webkit-tap-highlight-color: transparent;
}
html.mobile-ui .m-quickbar button:active { background: var(--gold-dim); }

/* ------------------------------------------------ tuning-totals combos --- */
/* Bigger + buttons for thumbs; everything else about the combo feature is
   shared with desktop in style.css. */
html.mobile-ui .tt-combo-btn { width: 32px; height: 32px; font-size: 17px; }
html.mobile-ui .tt-combo-spacer { width: 32px; }

/* ------------------------------------------------- builds sub-nav (mobile) --- */
/* Thumb-sized segmented control feel on phones; the two builds pages behave
   as one screen with two panes (swipe or tap to switch). */
html.mobile-ui .builds-subnav {
  margin: 0 0 12px;
  border-radius: 12px;
}
html.mobile-ui .bsnav-btn {
  padding: 11px 14px;
  font-size: 13.5px;
}

/* --------------------------------------------------------------- motion --- */
@media (prefers-reduced-motion: reduce) {
  html.mobile-ui .modal { animation: none; }
  html.mobile-ui .m-badge.m-badge-pulse { animation: none; }
  html.mobile-ui .m-acc > h2::after { transition: none; }
  html.mobile-ui .bc-desc-toggle::after { transition: none; }
  html.mobile-ui .m-tab,
  html.mobile-ui .m-tab .m-tab-icon,
  html.mobile-ui .m-tab .m-tab-label { transition: none; }
  html.mobile-ui .m-tab[aria-current="page"]::before { animation: none; }
  html.mobile-ui.m-page-index[data-mview="setup"] .layout .sidebar,
  html.mobile-ui.m-page-index[data-mview="results"] .layout .main { animation: none; }

}

/* ---- Effect priority chips (mobile) ----  (RDH)
   The ⠿ grip is the only drag target, so give it a proper thumb-sized tap area
   and keep touch-action:none confined to it - touching the chip body (or the
   rest of the page) must still scroll normally. */
/* Effect priority list on mobile: thumb-sized targets. The list is vertical, so
   rows are full width and easy to hit. touch-action:none stays scoped to the ⠿
   grip alone, so touching the rest of a row still scrolls the page. (RDH) */
/* Priority rows on mobile: taller so they are easy to grab and read. The whole
   row is the drag handle (touch-action:none lives on .prio-item in style.css),
   so there is no small target to hit. The ▲▼ buttons are gone - they squeezed the
   effect name into an ellipsis. (RDH) */
html.mobile-ui .prio-item { padding: 12px 11px; font-size: 13.5px; gap: 10px; }
html.mobile-ui .prio-rank { min-width: 21px; height: 21px; font-size: 11px; }
html.mobile-ui .prio-grip { font-size: 17px; }
html.mobile-ui .prio-remove { padding: 6px 4px; font-size: 19px; }
html.mobile-ui .prio-hint { font-size: 11.5px; }

/* Recommended Builds — carousel tuning for touch. Slightly narrower cards so
   the next card peeks in, signaling the row is swipeable. */
html.mobile-ui .rec-carousel > .rec-card { flex-basis: 232px; width: 232px; }
html.mobile-ui .rec-section-title { font-size: 16px; }
html.mobile-ui .rec-charpick { max-width: none; }

/* Tag picker becomes a real dropdown on mobile: the trigger shows a summary of
   selected tags and toggles the chip grid open. Desktop keeps the always-open
   chip grid (trigger stays display:none from build.css). */
html.mobile-ui .tag-dropdown-trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  gap: 8px;
  padding: 10px 12px;
  border-radius: 9px;
  border: 1px solid var(--border);
  background: var(--panel-2);
  color: var(--text);
  font-size: 13px;
  cursor: pointer;
}
html.mobile-ui .tag-dropdown-summary {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
html.mobile-ui .tag-dropdown-caret {
  flex: none;
  color: var(--text-dim);
  transition: transform 0.15s ease;
}
html.mobile-ui .tag-picker.open .tag-dropdown-caret {
  transform: rotate(180deg);
}
/* Collapsed by default on mobile; the chip grid appears only when open. */
html.mobile-ui .tag-chip-grid {
  display: none;
  margin-top: 8px;
  padding: 10px;
  border: 1px solid var(--border);
  border-radius: 9px;
  background: var(--panel);
}
html.mobile-ui .tag-picker.open .tag-chip-grid {
  display: flex;
}
html.mobile-ui .tag-chip {
  font-size: 13px;
  padding: 7px 13px;
}


/* ---- Session 33 (2026-07-20) ---- */
/* Top Builders on phones: it floated in a moat of margin (screenshot). */
html.mobile-ui .top-builders { margin: 8px 0 10px; }

/* Detail modal on phones: the sheet's ::before drag handle already supplies
   the top breathing room, so the header padding can be tighter than desktop
   without the content feeling flush. (2026-07-20) */
/* (stale session-33 header pair removed in session 45 - superseded below) */

/* Detail modal header on phones: .modal-close is 40px here, so the author
   line matches that height for exact centring. (2026-07-20) */
html.mobile-ui .build-detail-modal #bdAuthor { min-height: 40px; }
html.mobile-ui .build-detail-modal .modal-section { padding-top: 10px; }
/* Centre-pinned like desktop: 10px padding + half the 40px mobile line. */
html.mobile-ui .build-detail-modal .modal-close { top: calc(10px + 20px); transform: translateY(-50%); right: 10px; }

/* Community Edit modal's tag chips must stay visible on phones - they are NOT
   inside a .tag-picker dropdown, so the collapse rule above must not apply. */
html.mobile-ui .em-tags { display: flex; }
