/* =====================================================================
   Skin editor only. Shared look (background, frame, buttons, panels)
   lives in theme.css.
   ===================================================================== */

.editor-page .portal-container {
  user-select: none;
  -webkit-user-select: none;
}
.editor-page input[type="text"] {
  user-select: text;
  -webkit-user-select: text;
}

/* ---------- Toolbar & Workspace Grid ---------- */
.editor-page .panel {
  padding: 10px 12px;
}
.editor-workspace-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 12px;
}
@media (min-width: 1024px) {
  .editor-workspace-grid {
    grid-template-columns: 224px minmax(0, 1fr) 268px;
    align-items: stretch;
  }
}
.editor-toolbar {
  position: relative;
  z-index: 30;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px 8px;
  margin-bottom: 12px;
  padding: 8px 12px;
}
.editor-toolbar-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  min-width: 0;
}
.skin-title-wrap {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  min-height: 32px;
}
.skin-title-display-wrap {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  max-width: 100%;
  padding: 3px 8px;
  border-radius: 0;
  border: 0;
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease;
  user-select: none;
  overflow: hidden;
}
.skin-title-display-wrap:focus-visible {
  background-color: var(--dough-bg);
  border-color: var(--crust-dark);
}
@media (hover: hover) {
  .skin-title-display-wrap:hover {
    background-color: var(--dough-bg);
    border-color: var(--crust-dark);
  }
}
.skin-title-text {
  display: block;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--crust-dark);
  line-height: 1.2;
}
.skin-title-pencil-icon {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  color: var(--crust-muted);
  opacity: 0.6;
  transition: opacity 0.15s ease, color 0.15s ease;
}
.skin-title-display-wrap:focus-visible .skin-title-pencil-icon {
  opacity: 1;
  color: var(--marinara);
}
@media (hover: hover) {
  .skin-title-display-wrap:hover .skin-title-pencil-icon {
    opacity: 1;
    color: var(--marinara);
  }
}
.badge {
  display: inline-block;
  flex: 0 0 auto;
  padding: 1px 6px;
  background: var(--cheese-highlight);
  border: 0;
  border-radius: 0;
  font-family: var(--font-mono);
  font-size: 0.65rem;
  font-weight: 700;
}
.skin-title-wrap .badge {
  position: absolute;
  left: 8px;
  top: calc(100% + 1px);
  z-index: 2;
  pointer-events: none;
}
.btn-group { display: flex; align-items: center; gap: 8px; }

/* Keep the toolbar in one fixed row on desktop so button positions never depend
   on the skin title length or the autosave badge. */
@media (min-width: 1024px) {
  .editor-toolbar {
    display: grid;
    grid-template-columns: 200px max-content minmax(0, 1fr);
    flex-wrap: nowrap;
    gap: 8px;
  }
  .skin-title-wrap {
    width: 200px;
  }
  .editor-toolbar-actions {
    flex-wrap: nowrap;
    justify-content: flex-end;
    gap: 6px;
  }
}

/* ---------- Editor mode switch (sliding segmented control) ---------- */
.mode-switch {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  padding: 3px;
  background: var(--mozzarella-white);
  border: 0;
  border-radius: 0;
  box-shadow: 3px 3px 0 var(--crust-dark);
}
.mode-switch-highlight {
  position: absolute;
  top: 3px;
  bottom: 3px;
  left: 3px;
  width: calc(50% - 3px);
  background: var(--pesto-green);
  border: 0;
  border-radius: 0;
  transition: transform 0.25s cubic-bezier(0.34, 1.3, 0.64, 1);
  pointer-events: none;
}
.mode-switch[data-mode="modular"] .mode-switch-highlight { transform: translateX(100%); }
.mode-switch-option {
  position: relative;
  z-index: 1;
  padding: 3px 5px;
  font-family: var(--font-display);
  font-size: 0.65rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  white-space: nowrap;
  color: var(--crust-dark);
  transition: color 0.2s ease;
}
.mode-switch-option.is-active { color: var(--mozzarella-white); }
@media (hover: hover) {
  .mode-switch-option:not(.is-active):hover { color: var(--marinara); }
}
.mode-switch-option:focus-visible { outline: 2px solid var(--crust-dark); outline-offset: 1px; border-radius: 0; }

/* Tighter desktop toolbar for narrower landscape windows, still one fixed row. */
@media (min-width: 1024px) and (max-width: 1099px) {
  .editor-toolbar {
    grid-template-columns: 175px max-content minmax(0, 1fr);
    gap: 6px;
  }
  .skin-title-wrap {
    width: 175px;
  }
  .skin-title-text {
    font-size: 1rem;
  }
  .editor-toolbar-actions {
    gap: 5px;
  }
  .editor-toolbar-actions .btn-para.btn-sm {
    padding: 5px 6px;
    font-size: 0.76rem;
  }
  .editor-toolbar-actions .btn-para.btn-xs {
    padding: 3px 5px;
    font-size: 0.66rem;
  }
  .mode-switch-option {
    padding: 3px 5px;
    font-size: 0.62rem;
  }
}

.modular-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 460px;
  text-align: center;
}
.modular-placeholder.hidden,
.editor-workspace-grid.hidden { display: none; }

/* ---------- Drawing tools 2x2 grid ---------- */
.tool-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px 10px;
}
.tool-grid .tool-btn {
  width: 100%;
  text-align: center;
  white-space: nowrap;
}

.publish-dropdown {
  position: relative;
}
.publish-menu {
  position: absolute;
  right: 0;
  top: calc(100% + 8px);
  width: 240px;
  z-index: 50;
}

/* ---------- 3D viewport ---------- */
.viewport {
  position: relative;
  border: 0;
  box-shadow: 5px 5px 0 var(--crust-dark);
  border-radius: 0;
  overflow: hidden;
  background: radial-gradient(circle at 50% 42%, #5a392d 0%, #2b1b17 68%, #1a0f0c 100%);
}
.hud {
  background: rgba(246, 231, 203, 0.94);
  border: 0;
  border-radius: 0;
  box-shadow: 3px 3px 0 rgba(0, 0, 0, 0.4);
  color: var(--crust-dark);
  font-size: 0.7rem;
}

/* Keep the viewport controls clear of the gizmo in the top-right corner. */
.viewport-topbar {
  padding-right: 128px;
}

/* ---------- Orientation cube gizmo (top-right of the 3D viewport) ---------- */
.axis-gizmo {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 108px;
  height: 108px;
  z-index: 20;
  user-select: none;
  -webkit-user-select: none;
}
.axis-gizmo canvas {
  display: block;
  width: 100%;
  height: 100%;
  cursor: pointer;
  filter: drop-shadow(3px 3px 0 rgba(0, 0, 0, 0.35));
  touch-action: manipulation;
}
.dot { width: 8px; height: 8px; border-radius: 0; border: 0; display: inline-block; }
.dot.green { background: var(--pesto-green); }
.dot.red { background: var(--marinara); }

/* ---------- 2D Body & Armor limb selector ---------- */
.limb-selector-stage {
  display: flex;
  justify-content: space-around;
  align-items: flex-start;
  gap: 16px;
  padding: 10px 12px 12px;
  background: var(--mozzarella-white);
  border: 0;
  border-radius: 0;
  box-shadow: inset 0 0 0 2px rgba(212, 140, 70, 0.22);
}

.limb-doll-col {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}

.limb-doll-label {
  font-family: var(--font-display);
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--crust-dark);
  padding: 2px 10px;
  border-radius: 0;
  border: 0;
  background: var(--mozzarella-white);
  box-shadow: 2px 2px 0 var(--crust-dark);
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease, transform 0.1s ease;
}
@media (hover: hover) {
  .limb-doll-label:hover {
    background: var(--cheese-highlight);
    color: var(--crust-dark);
    transform: translateY(-1px);
  }
}
.limb-doll-label.is-on {
  background: var(--pesto-green);
  border-color: var(--crust-dark);
  color: var(--mozzarella-white);
}
@media (hover: hover) {
  .limb-doll-label.is-on:hover {
    background: var(--cheese-highlight);
    color: var(--crust-dark);
  }
}
.limb-doll-label.all-off {
  background: #eae0cf;
  color: var(--crust-muted);
  opacity: 0.7;
  box-shadow: 1px 1px 0 var(--crust-dark);
}

.limb-doll-grid {
  display: grid;
  grid-template-columns: repeat(16, 5px);
  grid-template-rows: repeat(32, 5px);
}

.limb-head { grid-column: 5 / 13; grid-row: 1 / 9; }
.limb-torso { grid-column: 5 / 13; grid-row: 9 / 21; }
.limb-right-arm { grid-column: 1 / 5; grid-row: 9 / 21; }
.limb-doll-grid.is-slim .limb-right-arm { grid-column: 2 / 5; }
.limb-left-arm { grid-column: 13 / 17; grid-row: 9 / 21; }
.limb-doll-grid.is-slim .limb-left-arm { grid-column: 13 / 16; }
.limb-right-leg { grid-column: 5 / 9; grid-row: 21 / 33; }
.limb-left-leg { grid-column: 9 / 13; grid-row: 21 / 33; }

.limb-btn {
  position: relative;
  padding: 0;
  border: 0;
  outline: 0;
  outline-offset: 0;
  background-color: #f3e8d0;
  background-image:
    linear-gradient(45deg, #dcc9a0 25%, transparent 25%),
    linear-gradient(-45deg, #dcc9a0 25%, transparent 25%),
    linear-gradient(45deg, transparent 75%, #dcc9a0 75%),
    linear-gradient(-45deg, transparent 75%, #dcc9a0 75%);
  background-size: 10px 10px;
  background-position: 0 0, 0 5px, 5px -5px, -5px 0;
  overflow: hidden;
  transition: opacity 0.15s ease, filter 0.15s ease;
}
.limb-btn canvas {
  width: 100%;
  height: 100%;
  display: block;
}
@media (hover: hover) {
  .limb-btn:hover {
    z-index: 2;
    filter: brightness(1.08);
    outline-offset: 0;
  }
}
.limb-btn:focus-visible {
  z-index: 2;
  outline: 2px solid var(--crust-dark);
  outline-offset: 1px;
}

.limb-btn.hidden-part,
.limb-btn.hidden-outer {
  background-image: none;
  background-color: #7c8599;
  opacity: 0.45;
  filter: grayscale(0.7);
}
.limb-btn.hidden-part::after,
.limb-btn.hidden-outer::after {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(116, 125, 148, 0.55);
  pointer-events: none;
}
@media (hover: hover) {
  .limb-btn.hidden-part:hover,
  .limb-btn.hidden-outer:hover {
    opacity: 0.68;
  }
}

/* ---------- Color slots & swatches ---------- */
.swatch-slot {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 2px;
  border: 0;
  border-radius: 0;
  box-shadow: 3px 3px 0 var(--crust-dark);
  transition: transform 0.15s ease;
}
@media (hover: hover) {
  .swatch-slot:hover { transform: translateY(-2px); }
}
.swatch-slot.active-slot { outline: 3px solid var(--pesto-green); outline-offset: 3px; }

/* Photoshop-style stacked slots: 1 sits on top-left, 2 peeks out bottom-right */
.swatch-stack {
  position: relative;
  flex-shrink: 0;
  width: 54px;
  height: 54px;
}
.swatch-stack .swatch-slot {
  position: absolute;
  box-shadow: 2px 2px 0 var(--crust-dark);
}
.swatch-stack .swatch-slot-front { top: 0; left: 0; z-index: 2; }
.swatch-stack .swatch-slot-back { right: 0; bottom: 0; z-index: 1; }
.swatch-stack .swatch-slot.active-slot { outline-offset: 1px; }
.slot-tag {
  padding: 0 4px;
  background: var(--crust-dark);
  color: var(--mozzarella-white);
  border-radius: 0;
  font-size: 9px;
  font-weight: 800;
}
.swatch {
  width: 100%;
  aspect-ratio: 1;
  border: 0;
  border-radius: 0;
  transition: transform 0.15s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@media (hover: hover) {
  .swatch:hover { transform: scale(1.18) rotate(-3deg); position: relative; z-index: 1; }
}

.link-btn {
  font-size: 0.7rem;
  font-weight: 700;
  color: var(--marinara);
  text-decoration: underline;
  text-underline-offset: 2px;
}
@media (hover: hover) {
  .link-btn:hover { color: var(--crust-dark); }
}
.link-btn.quiet { color: var(--crust-muted); }

kbd {
  padding: 1px 5px;
  background: var(--mozzarella-white);
  border: 0;
  border-radius: 0;
  font-family: var(--font-mono);
  font-size: 0.65rem;
  font-weight: 700;
}

/* ---------- Range sliders ---------- */
input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 20px;
  background: transparent;
  cursor: pointer;
}
input[type="range"]::-webkit-slider-runnable-track {
  height: 10px;
  background: var(--mozzarella-white);
  border: 0;
  border-radius: 0;
}
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 14px;
  height: 22px;
  margin-top: -8px;
  background: var(--marinara);
  border: 0;
  border-radius: 0;
}
input[type="range"]::-moz-range-track {
  height: 6px;
  background: var(--mozzarella-white);
  border: 0;
  border-radius: 0;
}
input[type="range"]::-moz-range-thumb {
  width: 10px;
  height: 18px;
  background: var(--marinara);
  border: 0;
  border-radius: 0;
}
input[type="range"]:focus-visible { outline: 3px solid var(--cheese-highlight); outline-offset: 2px; }
.range-brightness::-webkit-slider-runnable-track { background: linear-gradient(90deg, #000, #fff); }
.range-brightness::-moz-range-track { background: linear-gradient(90deg, #000, #fff); }

/* ---------- Mobile HSV sliders ---------- */
.hsv-sliders {
  flex-direction: column;
  gap: 4px;
  width: 100%;
  margin-top: 2px;
}
.hsv-row {
  display: grid;
  grid-template-columns: 26px minmax(0, 1fr) 38px;
  align-items: center;
  gap: 8px;
}
.hsv-label {
  font-size: 0.64rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--crust-dark);
}
.hsv-value {
  font-family: var(--font-mono);
  font-size: 0.62rem;
  text-align: right;
  color: var(--crust-muted);
}
input[type="range"].hsv-range {
  height: 26px;
}
/* Track gradients are driven per-channel from JS through --hsv-track. */
input[type="range"].hsv-range::-webkit-slider-runnable-track {
  background: var(--hsv-track, var(--mozzarella-white));
}
input[type="range"].hsv-range::-moz-range-track {
  background: var(--hsv-track, var(--mozzarella-white));
}

/* ---------- Layers ---------- */
/* Fixed height that fits exactly 4 rows; scrolls when there are more. */
.layer-list {
  --layer-row-h: 50px;
  --layer-gap: 6px;
  display: flex;
  flex-direction: column;
  gap: var(--layer-gap);
  height: calc(4 * var(--layer-row-h) + 3 * var(--layer-gap) + 8px);
  overflow-y: auto;
  padding: 4px;
}
.layer-row {
  position: relative;
  flex-shrink: 0;
  box-sizing: border-box;
  height: var(--layer-row-h);
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 6px;
  background: var(--mozzarella-white);
  border: 0;
  border-radius: 0;
  cursor: grab;
  transition: background-color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease, opacity 0.15s ease;
}
.layer-row:active { cursor: grabbing; }
.layer-row.dragging { opacity: 0.45; }
.layer-row.drop-above::before,
.layer-row.drop-below::after {
  content: "";
  position: absolute;
  left: -2px;
  right: -2px;
  height: 4px;
  background: var(--marinara);
  border-radius: 0;
  pointer-events: none;
}
.layer-row.drop-above::before { top: -6px; }
.layer-row.drop-below::after { bottom: -6px; }
.layer-kebab {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 28px;
  border-radius: 0;
  color: var(--crust-dark);
}
.layer-kebab[aria-expanded="true"] { background: rgba(43, 27, 23, 0.14); }
@media (hover: hover) {
  .layer-kebab:hover { background: rgba(43, 27, 23, 0.14); }
}
.layer-kebab svg { width: 16px; height: 16px; }
.layer-kebab-menu {
  position: fixed;
  z-index: 70;
  width: 150px;
}
.layer-kebab-menu .menu-item { padding: 6px 10px; }
.layer-kebab-menu .menu-item-danger strong { color: var(--marinara); }
@media (hover: hover) {
  .layer-row:hover { background: #fff3c4; }
}
.layer-row.active {
  background: var(--cheese-highlight);
  box-shadow: 3px 3px 0 var(--crust-dark);
  transform: translate(-1px, -1px);
}
.layer-eye {
  flex-shrink: 0;
  padding: 4px;
  border-radius: 0;
  color: var(--pesto-green);
}
@media (hover: hover) {
  .layer-eye:hover { background: rgba(43, 27, 23, 0.12); }
}
.layer-eye.off { color: #9b8570; }
.layer-eye svg { width: 16px; height: 16px; }
.layer-thumb {
  box-sizing: content-box;
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  border: 0;
  border-radius: 0;
}
.layer-info { min-width: 0; flex: 1; }
.layer-name {
  font-size: 0.78rem;
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.layer-name.dim { color: var(--crust-muted); }
.layer-meta {
  font-family: var(--font-mono);
  font-size: 0.65rem;
  color: var(--crust-muted);
}

/* ---------- Import dialog ---------- */
.modal-backdrop {
  background: rgba(43, 27, 23, 0.65);
  backdrop-filter: blur(2px);
}
.modal-card {
  width: 100%;
  max-width: 560px;
  padding: 18px;
  background: var(--dough-bg);
  box-shadow: 8px 8px 0 var(--crust-dark);
}
.check-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  background: var(--mozzarella-white);
  border: 0;
  border-radius: 0;
  font-size: 0.78rem;
  font-weight: 700;
  cursor: pointer;
}
.check-row:has(input:checked) { background: var(--cheese-highlight); }
.check-row:focus-within { outline: 3px solid var(--crust-dark); outline-offset: 2px; }

/* ---------- Pointer / touch input on the interactive canvases ---------- */
/* `touch-action: none` is what makes dragging usable on a touchscreen: without it the
   browser scrolls (or pinch-zooms) the page instead of delivering the move events a
   stroke needs. The callout/selection rules stop iOS long-press from popping a menu
   over the model mid-stroke. */
#skin3dCanvas,
#uv2dCanvas,
#colorWheelCanvas {
  touch-action: none;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}

/* The 3D viewport is the one element that should never be a scroll target. */
#viewportContainer,
.viewport {
  overscroll-behavior: contain;
}

/* Input legends: both are rendered and CSS picks one, so a device with both a mouse
   and a touchscreen still shows the binding that matches its primary pointer. */
.input-legend-touch { display: none; }
@media (hover: none) and (pointer: coarse) {
  .input-legend-mouse { display: none; }
  .input-legend-touch { display: flex; }
}

/* Comfortable touch targets for the tool row on small screens. */
@media (hover: none) and (pointer: coarse) {
  .tool-grid .tool-btn,
  .brush-size-btn {
    min-height: 40px;
  }
  .axis-gizmo { width: 84px; height: 84px; }
}

/* Mobile HSV sliders: desktop uses the colour wheel, so keep these out of the way. */
.hsv-sliders { display: none; }
.wheel-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
}

/* 2D skin texture frame: fixed on desktop, flexible on mobile. */
.uv2d-frame {
  box-sizing: content-box;
  width: 192px;
  height: 192px;
}

/* Desktop (and anything above the mobile breakpoint): the mobile chrome is not
   rendered at all. The mobile block below re-enables these elements. */
.m-header,
.m-stage-controls,
.m-sheet,
.m-tabbar,
.m-project-menu,
.m-view-menu { display: none; }

/* =====================================================================
   MOBILE LAYOUT (dedicated app-style shell)

   The breakpoint below is mirrored in editor.js as MOBILE_LAYOUT_MQ — both
   must stay in sync. Above it, nothing in this block applies, so the desktop
   workspace keeps its three-column grid untouched.

   The mobile UI reuses the desktop markup: editor.js moves the four editing
   panels into #mobileSheetBody and the 2D panel into #mobileStage2D, and moves
   them back to their original parents when the breakpoint stops matching.
   ===================================================================== */
@media (max-width: 767px), (max-width: 1023px) and (max-height: 540px) {
  /* ---- App shell: no page scrolling, everything fits the viewport ---- */
  html {
    height: 100%;
    overflow: hidden;
  }
  body.editor-page {
    display: flex;
    flex-direction: column;
    height: 100%;
    padding: 0;
    overflow: hidden;
  }
  body.editor-page .portal-topbar,
  body.editor-page .site-footer {
    display: none; /* replaced by the compact in-editor header */
  }
  /* Pin the shell to the box the browser actually shows. `position: fixed` is used
     instead of dvh/visualViewport maths because it is the one box the Android system
     navigation bar and Chrome's toolbars can never overlap. */
  body.editor-page .portal-container {
    position: fixed;
    inset: 0;
    width: auto;
    max-width: none;
    height: auto;
    min-height: 0;
    margin: 0;
    background: transparent;
    box-shadow: none;
    display: flex;
    overflow: visible;
    /* Lifted only by the height the visual viewport says is actually covered (an open
       keyboard, or an edge-to-edge system bar). It stays 0 on the common Android
       configuration where the layout viewport already ends above the navigation bar,
       which is why no env(safe-area-inset-bottom) reservation is used here. */
    bottom: var(--m-bottom-gap, 0px);
  }
  body.editor-page .portal-main.compact {
    flex: 1 1 auto;
    min-height: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0;
  }
  body.editor-page .flash-messages {
    margin: 6px 8px 0;
    font-size: 0.75rem;
  }

  /* ---- Compact header ---- */
  .m-header {
    display: flex;
    align-items: center;
    gap: 6px;
    flex: 0 0 auto;
    padding: 6px 8px;
    background: linear-gradient(180deg, #3d2620 0%, var(--crust-dark) 100%);
    box-shadow: 0 3px 8px rgba(0, 0, 0, 0.35);
    z-index: 40;
  }
  .m-title-btn {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 4px 6px;
    color: var(--mozzarella-white);
    font-family: var(--font-display);
    font-size: 0.92rem;
    font-weight: 700;
    text-align: left;
  }
  .m-title {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .m-autosave-dot {
    flex: 0 0 auto;
    width: 7px;
    height: 7px;
    background: var(--cheese-highlight);
    box-shadow: 0 0 0 2px rgba(255, 252, 185, 0.25);
  }
  .m-icon-btn {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    padding: 0;
    color: var(--mozzarella-white);
    background: rgba(255, 255, 255, 0.09);
    box-shadow: 0 0 0 0 transparent;
    transition: background-color 0.12s ease, transform 0.1s ease;
  }
  .m-icon-btn svg { width: 20px; height: 20px; }
  .m-icon-btn:active:not(:disabled) { transform: translateY(1px); }
  .m-icon-btn:disabled { opacity: 0.35; }
  .m-icon-btn-sm { width: 32px; height: 32px; }
  .m-icon-btn-sm svg { width: 17px; height: 17px; }

  /* Toolbar, workspace sections and the 2D column are not used on mobile:
     their panels are re-parented into the sheet / stage by editor.js. */
  body.editor-page .editor-toolbar { display: none; }

  /* ---- Workspace grid becomes a single stack: stage + sheet + tabbar ---- */
  #paintEditorWorkspace {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
    gap: 0;
  }
  #paintEditorWorkspace > section {
    display: none;
    min-height: 0;
  }
  #paintEditorWorkspace > #viewportSection {
    display: flex;
    flex: 1 1 auto;
    min-height: 0;
  }

  /* ---- Stage ---- */
  #viewportSection .viewport {
    flex: 1 1 auto;
    min-height: 0;
    box-shadow: inset 0 0 0 0 transparent;
    position: relative;
  }
  /* The view toggles move into the #mobileViewMenu popover, which leaves a single
     HUD row; keep it pinned to the bottom of the stage. */
  #viewportSection .viewport-topbar { display: none; }
  #viewportSection .viewport { justify-content: flex-end; }
  #viewportSection .viewport > .p-2\.5 { padding: 6px 8px; }
  /* No hover on touch, and the target readout both costs stage height and reads
     "Drag a body part to paint" as a permanent label. Drop it on phones. */
  #viewportHudTarget { display: none; }
  /* Gesture legends: keep them, but as a single quiet line. */
  #viewportSection .input-legend-mouse { display: none; }
  #viewportSection .input-legend-touch {
    font-size: 0.6rem;
    gap: 6px;
    padding: 3px 6px;
    opacity: 0.85;
    box-shadow: none;
    background: rgba(246, 231, 203, 0.8);
  }
  #viewportSection .input-legend-touch b { font-weight: 700; }
  #viewportSection .input-legend-touch .dot { width: 6px; height: 6px; }
  #viewportSection .axis-gizmo { width: 74px; height: 74px; top: 44px; right: 6px; }

  #mobileStage2D {
    display: none;
    flex: 1 1 auto;
    min-height: 0;
    align-items: center;
    justify-content: center;
    padding: 44px 8px 8px;
    background: radial-gradient(circle at 50% 42%, #5a392d 0%, #2b1b17 68%, #1a0f0c 100%);
    overflow: hidden;
  }
  body.m-stage-2d #mobileStage2D { display: flex; }
  body.m-stage-2d #viewportSection .viewport { display: none; }
  #mobileStage2D #panel2D {
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 100%;
    max-height: 100%;
    padding: 0;
    background: transparent;
    box-shadow: none;
  }
  #mobileStage2D #panel2D .m-panel-head { display: none; }
  /* Square frame; editor.js sets the px size so it always fits the stage. */
  .uv2d-frame {
    box-sizing: content-box;
    flex: 0 0 auto;
    aspect-ratio: 1;
    box-shadow: 5px 5px 0 var(--crust-dark);
  }
  /* Short viewports (landscape phones): the sheet must not eat the stage. */
  body.m-short .m-sheet { height: min(34%, 200px); }
  body.m-short #mobileStage2D { padding: 38px 6px 6px; }

  /* ---- Stage controls (float over the stage) ---- */
  .m-stage-controls {
    position: absolute;
    top: 6px;
    left: 6px;
    right: 6px;
    z-index: 25;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    pointer-events: none;
  }
  .m-stage-controls > * { pointer-events: auto; }

  /* ---- Segmented control (3D/2D, model, mode) ---- */
  .m-seg {
    display: inline-flex;
    padding: 2px;
    background: rgba(246, 231, 203, 0.92);
    box-shadow: 3px 3px 0 rgba(0, 0, 0, 0.4);
  }
  .m-seg-btn {
    padding: 5px 12px;
    min-height: 30px;
    font-family: var(--font-display);
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--crust-dark);
  }
  .m-seg-btn.is-active {
    background: var(--pesto-green);
    color: var(--mozzarella-white);
  }

  /* ---- Contextual sheet ---- */
  /* The sheet has ONE height for every tab. Sizing it to its content meant the 3D stage
     grew and shrank on every tab tap, which resized (squashed/stretched) the canvas. */
  .m-sheet {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    min-height: 0;
    height: min(30%, 220px);
    margin: 0 6px;
    background: var(--dough-card);
    box-shadow: 0 -3px 0 var(--crust-dark);
    z-index: 30;
    overflow: hidden;
  }
  .m-sheet.is-collapsed { height: 0; margin: 0; box-shadow: none; border: 0; }
  .m-sheet.is-collapsed .m-sheet-body { display: none; }
  /* Slim grabber instead of a title bar: the active tab is already labelled and
     highlighted in the bottom navigation, so a header row would only cost height. */
  .m-sheet-grabber {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 14px;
    padding: 0;
    background: transparent;
  }
  .m-sheet-grabber-bar {
    width: 38px;
    height: 4px;
    background: rgba(43, 27, 23, 0.26);
    border-radius: 2px;
  }
  .m-sheet-grabber:active .m-sheet-grabber-bar { background: rgba(43, 27, 23, 0.5); }
  /* The tab name stays in the DOM for screen readers only. */
  .m-sheet-title {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }
  .m-sheet-body {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    padding: 8px 8px 12px;
  }
  /* Panels render flat inside the sheet (the sheet itself is the frame). */
  /* Only the panel for the selected tab is shown; the rest stay in the DOM (state,
     canvas buffers and event listeners are untouched). */
  .m-sheet-body > .panel { display: none; }
  .m-sheet[data-tab="draw"] #panelDraw,
  .m-sheet[data-tab="color"] #panelColor,
  .m-sheet[data-tab="layers"] #panelLayers,
  .m-sheet[data-tab="parts"] #panelParts {
    display: block;
  }
  .m-sheet-body .panel {
    padding: 0;
    background: transparent;
    box-shadow: none;
    min-height: 0;
  }
  .m-sheet-body .panel + .panel { margin-top: 8px; }
  .m-sheet-body .m-panel-head { display: none; }
  /* Fill the fixed-height sheet with the list rather than leaving dead space.
     Scoped to the active tab so it cannot out-specify the hide rule above. */
  .m-sheet[data-tab="layers"] #panelLayers {
    display: flex;
    flex-direction: column;
    height: 100%;
  }
  .m-sheet-body #panelLayers .layer-list {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
  }
  .m-sheet-body #panelLayers .m-panel-head {
    display: flex;
    justify-content: flex-end;
    margin-bottom: 6px;
  }
  /* The sheet header already names the tab; keep only the "+ New" action here. */
  .m-sheet-body #panelLayers .m-panel-head .panel-title { display: none; }

  /* Draw tab: tools on top, size/options anchored to the bottom of the fixed sheet so
     the panel reads as a toolbar instead of ending in a dead gap. Scoped to the tab so
     it cannot out-specify the "hide inactive panels" rule. */
  .m-sheet[data-tab="draw"] #panelDraw {
    display: flex;
    flex-direction: column;
    height: 100%;
  }
  .m-sheet-body #panelDraw > .divider { margin-top: auto; }

  /* Draw tab: 4 tool buttons in one row, size chips below. */
  .m-sheet-body .tool-grid {
    grid-template-columns: repeat(4, 1fr);
    gap: 6px;
    margin-bottom: 8px;
    padding: 0;
  }
  .m-sheet-body .tool-grid .tool-btn {
    min-height: 46px;
    padding: 6px 2px;
    font-size: 0.66rem;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .m-sheet-body .tool-grid .tool-btn svg {
    width: 18px;
    height: 18px;
    margin-right: 3px;
    vertical-align: -3px;
  }
  .m-sheet-body .brush-size-btn { min-height: 36px; }

  /* Color tab: the wheel + brightness strip are replaced by three compact
     horizontal HSV sliders, which fit a phone far better than a 240px wheel. */
  .m-sheet-body .wheel-wrap { display: none; }
  .m-sheet-body .hsv-sliders { display: flex; }
  .m-sheet-body .hsv-range { height: 30px; }
  .m-sheet-body .swatch-stack { width: 46px; height: 46px; }
  .m-sheet-body .swatch-slot { width: 30px; height: 30px; }
  .m-sheet-body #hexColorInput { font-size: 0.95rem; padding: 6px 8px; }

  /* Layers tab: the list scrolls inside the sheet. */
  .m-sheet-body .layer-list {
    --layer-row-h: 44px;
    height: auto;
    max-height: none;
    overflow: visible;
    padding: 2px;
    margin-bottom: 6px;
  }
  .m-sheet-body .layer-kebab { width: 32px; height: 32px; }
  .m-sheet-body .layer-row { padding: 4px 5px; gap: 6px; }

  /* Parts tab: two doll columns side by side. */
  .m-sheet-body .limb-selector-stage {
    padding: 6px 4px 8px;
    gap: 8px;
  }

  /* ---- Bottom navigation ---- */
  .m-tabbar {
    flex: 0 0 auto;
    display: flex;
    align-items: stretch;
    gap: 2px;
    /* The system-bar inset is cleared once, on the shell (see .portal-container), so
       it must not be added again here. */
    padding: 4px 6px 6px;
    background: var(--dough-bg);
    box-shadow: 0 -3px 0 var(--crust-dark);
    z-index: 35;
  }
  .m-tab {
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    min-height: 46px;
    padding: 4px 2px;
    color: var(--crust-muted);
    font-family: var(--font-display);
    font-size: 0.62rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
  }
  .m-tab svg { width: 20px; height: 20px; }
  .m-tab.is-active {
    color: var(--mozzarella-white);
    background: var(--pesto-green);
    box-shadow: 2px 2px 0 var(--crust-dark);
  }

  /* ---- Popovers ---- */
  .m-project-menu,
  .m-view-menu {
    position: fixed;
    top: 52px;
    right: 8px;
    z-index: 60;
    width: min(280px, calc(100vw - 16px));
    max-height: calc(100vh - 70px);
    overflow-y: auto;
  }
  /* The base rules hide the popovers; re-enable them here (open state only). */
  .m-project-menu:not(.hidden),
  .m-view-menu:not(.hidden) { display: block; }
  .m-project-menu .menu-item { min-height: 42px; }
  .m-menu-divider {
    height: 2px;
    margin: 4px 2px;
    background: rgba(43, 27, 23, 0.16);
  }
  .m-menu-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 5px 10px;
  }
  .m-menu-label {
    font-family: var(--font-display);
    font-size: 0.66rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--crust-muted);
    padding: 0 10px;
  }
  .m-menu-row .m-menu-label { padding: 0; }
  .m-view-menu-body #viewTogglesHud {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
    padding: 4px;
    background: transparent;
    box-shadow: none;
    font-size: 0.78rem;
  }
  .m-view-menu-body #viewTogglesHud label { min-height: 32px; }
  .m-view-menu-body #viewTogglesHud input[type="checkbox"] {
    width: 18px;
    height: 18px;
  }

  /* ---- Modular designer mode: the paint chrome steps aside ---- */
  /* (the ID selector above would otherwise beat the .hidden class on the workspace) */
  body.m-modular #paintEditorWorkspace { display: none; }
  body.m-modular #mobileSheet,
  body.m-modular #mobileTabBar,
  body.m-modular #mobileStageControls { display: none; }
  body.m-modular .modular-placeholder {
    display: flex;
    flex: 1 1 auto;
    min-height: 0;
    margin: 0 8px 8px;
  }

  /* ---- Misc: keep overlays clear of the tab bar ---- */
  body.editor-page .toast {
    bottom: 64px;
    left: 10px;
    right: 10px;
    max-width: none;
  }
  body.editor-page .menu.layer-kebab-menu { width: 170px; }
  body.editor-page .layer-kebab-menu .menu-item { min-height: 38px; }
  /* Import dialog: stack the preview under the limb picker. */
  body.editor-page .modal-card { padding: 12px; }
  body.editor-page .modal-card > .flex.gap-4 { flex-direction: column; }
  body.editor-page .modal-card > .flex.gap-4 > .shrink-0 { width: 100%; }
  body.editor-page .modal-card > .flex.gap-4 > .shrink-0 > .w-32 { margin: 0 auto; }
}
