/* =============================================================================
 * chrome.css — Índice de secciones (§22.6xx.656k Sprint 5)
 * =============================================================================
 * Estructura:
 *   1. Globals              — is-selected check badge, app-shell, x-cloak
 *   2. WCO                  — Window Controls Overlay
 *   3. Tabler icons         — .ti, animations
 *   4. Botones físicos      — .btn-wood + modificadores
 *   5. Color picker         — color-wheel, approximate, settings-color-circle
 *   6. HUD toolbar          — undo-redo, recent-colors, hud-toolbar-*
 *   7. Desk light           — .desk-light overrides
 *   8. Floating panel      — base, header, actions, resize-handle
 *   9. Brush viewport      — .brush-view, brush-view-list/settings/scroll
 *  10. Dialog panel        — .dialog-panel + info-text
 *  11. Form inputs         — text-field, range, slider, pro-slider
 *  12. Brushes panel       — .brushes-floating-pill, .brush-item
 *  13. Brush thumbnails    — .brush-card-*
 *  14. Library dialog      — .library-dialog, .library-card, .library-pad-*
 *  15. Settings dialog     — .settings-row, .settings-section, .settings-pane-*
 *  16. Page viewport       — .page-viewport, paper/binder/noise overlays
 *  17. Workspace sidebar   — .workspace-*
 *  18. Navbar              — .navbar-*
 *  19. Tools menu          — .tools-menu-*
 *  20. Washi tape          — .washi-tape-*
 *  21. Save indicator      — .save-indicator, .save-indicator--*
 *  22. Coverflow overlay   — .coverflow-*
 *  23. Reorder overlay     — .reorder-*
 *  24. Export dialog       — .export-* (legacy refs)
 *  25. Welcome dialog      — .welcome-*
 *  26. Cursor              — .cursor-*
 *  27. Theme row details   — .theme-row-details
 *  28. Layers panel        — .layers-menu, .layer-row, .layer-*
 *  29. Texto grabado       — .engraved-*
 *
 * Sistema .tile BEM (modificadores, elementos, estados): ver css/tiles.css
 * =============================================================================
 */

[x-cloak] {
  display: none !important;
}.orientation-pill.is-active {
  background: var(--panel-cream, #FCF7EE);
  color: rgba(92, 51, 23, 0.95);
  box-shadow:
    0 1px 2px rgba(60, 40, 20, 0.12),
    inset 0 0 0 1px rgba(146, 106, 26, 0.18);
}
.orientation-pill.is-active .ti {
  color: rgba(92, 51, 23, 0.85);
}


/* §22.6xx.656t — DROP del bloque completo del check badge de selección.
   El `.is-selected::after` global ponía un círculo brass con un check
   (`\ea5e` de tabler-icons) en la esquina superior derecha de CUALQUIER
   elemento con clase `.is-selected`. Roberto pidió eliminar esta
   funcionalidad — el check ya no debe aparecer en los tiles seleccionados.
   El estado de selección ahora se indica SOLO por el cambio de border-
   color (a `var(--brass)` en tiles hand-drawn/solid/circular) y/o
   background, sin el badge. */

/* === Globals (no-bounce, app-shell) === */

.no-bounce {
  overscroll-behavior: none;
}

.app-shell {
  width: 100%;
  height: var(--app-height);
  min-height: var(--app-height);
}
.tray-island-host {
  padding-top: env(safe-area-inset-top, 0);
}


/* === Window Controls Overlay (WCO) === */

/* §22.6xx.658dr.67 — El desplegable Tools debe verse por encima de TODO
 * excepto los dialogs en overlay.
 *
 * El problema es un stacking context, no un z-index suelto: el desplegable
 * vive DENTRO de `.app-header`, que tiene `position: fixed` + `z-index: 80`.
 * Eso crea un stacking context propio, así que el `z-[60]` del desplegable
 * solo se compara contra sus hermanos dentro del header — nunca puede subir
 * por encima de 80 en el contexto raíz. Los floating panels (ventana de color,
 * brushes, layers…) llevan z dinámico hasta PANEL_Z_CAP = 89
 * (js/ui/state/panel-system.js:35), así que siempre ganaban.
 *
 * Al abrir el menú se sube el header entero a 95:
 *   95 > 89  → por encima de cualquier floating panel, sea cual sea su z
 *   95 < 100 → los dialogs overlay (`fixed inset-0 z-[100]`) siguen encima
 *
 * El header solo sube mientras el menú está abierto, para no alterar el
 * stacking del resto del HUD cuando el menú está cerrado. */
.app-header.z-tools-menu-open {
  z-index: 95;
}

.wco-active .tray-island-host {
  padding-top: 0;
}
.wco-active .app-header,
.wco-active .tray-island-host,
.wco-active .tray-island-top,
.wco-active .tray-island-shadow,
.wco-active .tray-island-groove {
  -webkit-app-region: drag;
}
.wco-active .tray-island-content button,
.wco-active .tray-island-content a,
.wco-active .tray-island-content input,
.wco-active .tray-island-content [role="button"],
.wco-active .tray-island-content select,
.wco-active .tray-island-content textarea,
.wco-active .tray-island-content label {
  -webkit-app-region: no-drag;
}
/* Cuando WCO está activo, el workspace necesita menos padding-top
   porque la navbar ya no compite con el title bar del browser. */
.wco-active .workspace-host {
  padding-top: 0;
}
/* En Linux, los controles de ventana están a la izquierda; en
   Windows/macOS a la derecha. Usamos env() para reservar espacio. */
.wco-active .tray-island-right {
  padding-right: env(titlebar-area-width, 0);
  padding-left: env(titlebar-area-width, 0);
}

.immersive-mode .app-header {
  padding-top: max(0.35rem, calc(var(--safe-top) + var(--viewport-offset-top) * 0.5));
  padding-bottom: 0.55rem;
}

.immersive-mode .workspace-sidebar {
  width: 4.35rem;
  gap: 0.75rem !important;
  padding-top: 0.75rem;
  padding-bottom: calc(0.75rem + var(--safe-bottom) + var(--viewport-offset-bottom));
  padding-left: 0.45rem;
  padding-right: 0.45rem;
}

.immersive-mode .color-launcher {
  width: 3.35rem;
  height: 3.35rem;
  border-radius: 1rem;
}

.immersive-mode .pro-slider-track {
  width: 3rem;
}

.immersive-mode .floating-info-card {
  display: none !important;
}

.immersive-mode .panel-sheet {
  width: min(15rem, calc(100vw - 4.25rem));
}.tabler-icon {
  display: block;
  flex: 0 0 auto;
  width: 1.2rem;
  height: 1.2rem;
  stroke-width: 2;
  shape-rendering: geometricPrecision;
  vector-effect: non-scaling-stroke;
  overflow: visible;
}


/* === Tabler icons (ti) styling === */

.ti {
  display: block;
  flex: 0 0 auto;
  font-size: 1.2rem;
  line-height: 1;
}
button i.ti,
button i[class*="ti-"] {
  color: inherit;
}

/* §22.6xx.331 — Animación de spin (reemplaza la animación interna del */
svg.ti-spin,
.ti-spin svg {
  animation: spin 1s linear infinite;
}
@keyframes spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}


/* === C. Botones físicos (.btn-wood) === */

.btn .tabler-icon,
.btn-square .tabler-icon,
.btn-wood-icon .tabler-icon,
.btn .ti,
.btn-square .ti,
.btn-wood-icon .ti {
  width: 1.25rem;
  height: 1.25rem;
  font-size: 1.25rem;
}

/* === Color picker global (color-picker launcher) === */

.color-launcher .tabler-icon {
  width: 1.45rem;
  height: 1.45rem;
  filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.18));
}

.btn-primary,
.bg-primary {
  border-color: var(--brass, #c85a29) !important;
  background-color: var(--brass, #c85a29) !important;
  color: #fff !important;
}

.btn-primary:hover,
.toggle-primary[checked="checked"] {
  border-color: var(--brass, #c85a29) !important;
  background-color: var(--brass, #c85a29) !important;
} .hud-top {
   min-height: 4rem;
 }

/* === HUD toolbar (undo-redo, recent colors) === */

.hud-toolbar-pill {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0.25rem;
  padding: 0.5rem 0.45rem;
  pointer-events: auto;
  user-select: none;
}


/* Active state for pill toolbar buttons — icon only turns red */
.hud-toolbar-pill .btn.is-active,
.hud-toolbar-pill .btn.is-active i {
  color: var(--brass);
}


/* === §22.6xx.interface-texture-rotate-vertical.v4 ===
   Bloque compartido para barras verticales (1100×300 horizontal texture).
   - Padre: `isolation: isolate` crea stacking context + `overflow: hidden`
             recorta el pseudo. El padre conserva su `background-color`
             (color wood base visible donde la textura sea transparente).
   - Pseudo: z-index: -1 (queda DETRÁS del contenido/box-shadow del padre).
             Tamaño FIJO 1100×300 px (= tamaño nativo de la textura, NO
             cover ni scaling). Tras rotar 90° se vuelve 300×1100 visual
             — siempre igual en todos los módulos verticales, mismo tamaño
             que las barras horizontales (que también usan 1100×300).
   - **Shadow layers**: pseudo CON `background-color: var(--bar-wood-color)`
             + `background-blend-mode: multiply` para tintar la textura con
             el wood-dark, idéntico a como lo hacen las shadow layers
             horizontales. Roberto lo pidió: "en las barras verticales la
             imagen que se aplica como shadow, debe tener el tono shadow".
   - **Top + groove layers**: pseudo SIN blend. La textura se muestra en
             sus colores nativos sobre el wood-light del padre (vía zonas
             transparentes). */

.undo-redo-pill-top,
.undo-redo-pill-shadow,
.color-floating-pill-top,
.color-floating-pill-shadow,
.brushes-floating-pill-top,
.brushes-floating-pill-shadow,
.navbar-status-pill-top,
.navbar-status-pill-shadow,
.recent-colors-pill-top,
.recent-colors-pill-shadow,
.tray-island-vertical .tray-island-top,
.tray-island-vertical .tray-island-shadow,
.tray-island-vertical .tray-island-groove {
  isolation: isolate;
  overflow: hidden;
}

/* --- Pseudo compartido: TOP + GROOVE (textura sin tinte, color nativo) --- */
.undo-redo-pill-top::before,
.color-floating-pill-top::before,
.brushes-floating-pill-top::before,
.navbar-status-pill-top::before,
.recent-colors-pill-top::before,
.tray-island-vertical .tray-island-top::before,
.tray-island-vertical .tray-island-groove::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 1100px;
  height: 300px;
  transform: translate(-50%, -50%) rotate(90deg);
  background-image: var(--ui-texture-interface, url('../resources/ui-textures/interface-texture.webp'));
  background-size: 1100px 300px;
  background-position: center;
  background-repeat: no-repeat;
  z-index: -1;
  pointer-events: none;
}

/* --- Pseudo compartido: SHADOW (textura + tinte multiply con wood-dark) --- */
.undo-redo-pill-shadow::before,
.color-floating-pill-shadow::before,
.brushes-floating-pill-shadow::before,
.navbar-status-pill-shadow::before,
.recent-colors-pill-shadow::before,
.tray-island-vertical .tray-island-shadow::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 1100px;
  height: 300px;
  transform: translate(-50%, -50%) rotate(90deg);
  background-color: var(--bar-wood-color, #a08250);
  background-image: var(--ui-texture-interface, url('../resources/ui-textures/interface-texture.webp'));
  background-size: 1100px 300px;
  background-position: center;
  background-repeat: no-repeat;
  background-blend-mode: multiply;
  z-index: -1;
  pointer-events: none;
}

/* Override horizontal del brush pill: la orientación cambia a horizontal.
   La textura va directa en el element a tamaño nativo 1100×300 (NO cover),
   sin pseudo. */
.brushes-floating-pill--horizontal .brushes-floating-pill-shadow,
.brushes-floating-pill--horizontal .brushes-floating-pill-top {
  background-image: var(--ui-texture-interface, url('../resources/ui-textures/interface-texture.webp'));
  background-size: 1100px 300px;
  background-position: center;
  background-repeat: no-repeat;
}
.brushes-floating-pill--horizontal .brushes-floating-pill-shadow::before,
.brushes-floating-pill--horizontal .brushes-floating-pill-top::before {
  display: none;
}

/* §22.6xx.658dr.80 — El TINT de la capa shadow se perdía en horizontal.
 * En vertical, el `::before` compartido lleva `background-color:
 * var(--bar-wood-color)` + `background-blend-mode: multiply`, que es lo que
 * funde la interface-texture con la madera. El override horizontal pone la
 * textura directamente en el elemento y oculta ese pseudo, pero se olvidaba
 * del blend: la textura quedaba pintada ENCIMA de la madera en vez de
 * multiplicada con ella, y el relieve de la píldora se perdía. Medido:
 * `blend: normal` en el elemento y `multiply` en un pseudo con
 * `display: none`.
 * Solo para `-shadow`: la capa `-top` lleva la textura en sus colores nativos
 * (sin blend), igual que el pseudo vertical. */
.brushes-floating-pill--horizontal .brushes-floating-pill-shadow {
  background-blend-mode: multiply;
}

.undo-redo-pill-wrap {
  position: fixed;
  bottom: 18px;
  left: 18px;
  z-index: 80;
  pointer-events: auto;
  user-select: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4rem;
  padding: 0.7rem 0.6rem 0.8rem;
  /* §22.6xx.658dr.18 — El wrap vuelve a su estado previo: SIN surface.
     El cream va en la TARJETA INTERNA (`.undo-redo-pill`), que es lo que
     se ve; aquí solo va la madera de las capas -top/-shadow. Ponerlo aquí
     lo dejaba oculto detrás de la madera. */
  border-radius: 16px;
  box-shadow:
    0 4px 0 rgba(60, 30, 10, 0.30),
    0 6px 12px rgba(60, 30, 10, 0.35),
    inset 0 1px 0 rgba(255, 253, 248, 0.95),
    inset 0 -2px 0 rgba(60, 30, 10, 0.18);
}

.undo-redo-pill {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.3rem;
  pointer-events: auto;
  user-select: none;
}

.undo-redo-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 999px;
  background: transparent;
  border: none;
  color: rgba(40, 22, 8, 0.95);
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  transition: background 0.12s ease, color 0.12s ease, opacity 0.12s ease;
}
.undo-redo-btn i {
  stroke-width: 2.5;
}

.undo-redo-btn:hover:not(:disabled) {
  background: rgba(60, 35, 12, 0.08);
  color: rgba(60, 35, 12, 1);
}

.undo-redo-btn:active:not(:disabled) {
  background: rgba(60, 35, 12, 0.14);
}

.undo-redo-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 36px;
  height: 32px;
  padding: 0 0.4rem;
  font-size: 1.6rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: rgba(40, 22, 8, 1);
  line-height: 1;
  user-select: none;
}

.undo-redo-btn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}


.recent-colors-pill-wrap {
  position: fixed;
  top: 50%;
  transform: translateY(-50%);
  z-index: 80;
  pointer-events: none;
  display: flex;
  align-items: center;
  /* §22.6xx.658dr.18 — Sin surface propio: el cream va en la tarjeta
     interna `.recent-colors-pill`. */
}
.recent-colors-pill-left  { left: 18px;  }
.recent-colors-pill-right { right: 18px; }


/* === Desk light theme === */

.desk-light .recent-colors-pill-wrap.recent-colors-pill-wrap--touch {
  top: auto !important;
  bottom: 4px !important;
  left: 50% !important;
  right: auto !important;
  transform: translateX(-50%) !important;
  flex-direction: row !important;
}

/* Inner pill: specificity (0,4,0) para ganar contra */
.desk-light .recent-colors-pill-wrap.recent-colors-pill-wrap--touch .recent-colors-pill {
  flex-direction: row !important;
  gap: 0.40rem;
  padding: 0.40rem 0.50rem;
  margin-top: 8px;
  position: relative;
  z-index: 2;
}

.desk-light .recent-colors-pill-wrap.recent-colors-pill-wrap--touch .recent-colors-pill-top {
  inset: 8px 0 0 0;
  border-top-left-radius: 15px;
  border-top-right-radius: 15px;
  border-bottom-right-radius: 0;
  border-bottom-left-radius: 0;
  background-position: top center;
}

.desk-light .recent-colors-pill-wrap.recent-colors-pill-wrap--touch .recent-colors-pill-shadow {
  border-top-left-radius: 15px;
  border-top-right-radius: 15px;
  border-bottom-right-radius: 0;
  border-bottom-left-radius: 0;
  background-position: bottom center;
}

.recent-colors-pill {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.30rem;
  padding: 0.50rem 0.40rem;
  border-radius: 999px;
  border: 1px solid rgba(92, 64, 51, 0.18);
  /* §22.6xx.658dr.19 — Cream SOLIDO + paper-noise, igual que
     `.navbar-stepper`. El degradado ivory→cream + panel-birch se leía como
     una tarjeta BLANCA (el `--ivory` es #FFFDF8) y sin textura. */
  background-color: var(--panel-cream);
  background-image: var(--ui-texture-paper-noise);
  background-repeat: repeat;
  background-size: 240px 240px;
  background-blend-mode: normal;
  box-shadow:
    /* Sombra direccional sobre la mesa */
    0 8px 22px rgba(60, 30, 10, 0.30),
    /* Ribete superior marfil */
    inset 0 1px 0 rgba(255, 253, 248, 0.85),
    /* Hilo de latón inferior */
    inset 0 -1.5px 0 var(--brass);
  pointer-events: auto;
  user-select: none;
  min-height: 36px;
}

.recent-colors-chip {
  display: inline-block;
  width: 22px;
  height: 22px;
  border-radius: 999px;
  border: 1.5px solid rgba(60, 30, 10, 0.30);
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.10),
    0 2px 4px rgba(60, 30, 10, 0.25);
  cursor: pointer;
  padding: 0;
  background-clip: padding-box;
  transition: transform 110ms ease-out, box-shadow 110ms ease-out;
}

.recent-colors-chip:hover {
  transform: scale(1.15);
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.20),
    0 4px 8px rgba(60, 30, 10, 0.35);
}

.recent-colors-chip:focus-visible {
  outline: none;
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.30),
    0 0 0 2px var(--brass-light),
    0 4px 8px rgba(60, 30, 10, 0.35);
}

.recent-colors-chip:active {
  transform: scale(0.95);
}.hud-dock-btn.is-active {
  border-color: color-mix(in srgb, var(--brass) 38%, transparent);
  background: rgba(200, 90, 41, 0.18);
  color: #fff;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.04);
}

/* Active state for sidebar toolbar buttons — icon only turns red */
.hud-toolbar-sidebar .btn.is-active {
  color: var(--brass);
}


/* === Floating panel (base + header + actions) === */

.floating-panel {
  display: flex;
  flex-direction: column;
  /* ancho base a 300px (18.75rem). Sigue siendo un panel */
  width: min(92vw, 18.75rem);
  max-height: min(78vh, 44rem);
  min-height: 200px;
  /* §22.6xx.656n — Drop: border, box-shadow, backdrop-filter. Solo fondo plano. */
  border: 1px solid rgba(92, 64, 51, 0.20);
  border-radius: 1.35rem;
  background-color: var(--panel-cream);
  /* §22.6xx.656bl iter 6 — multiply en vez de soft-light. */
  background-image: var(--ui-texture-paper-noise);
  background-repeat: repeat;
  background-size: 240px 240px;
  background-blend-mode: multiply;
  /* overflow hidden para que el panel-body no sobresalga */
  overflow: hidden;
  will-change: transform, opacity;
  /* §22.160: transition reducido de 160ms → 100ms para INP. */
  transition: opacity 100ms ease-out, transform 100ms ease-out;
}

.floating-panel:hover {
  /* §22.6xx.656n — Drop del hover shadow. Sin sombras. */
}

.floating-panel-visible {
  opacity: 1;
  pointer-events: auto;
  transform: translate3d(0, 0, 0) scale(1);
}

.floating-panel-hidden {
  opacity: 0;
  pointer-events: none;
  transform: translate3d(0, 10px, 0) scale(0.98);
}.floating-panel-header {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.65rem;
  /* §22.128 — flex-shrink: 0 para que el header NO se encoja cuando */
  flex-shrink: 0;
  /* §22.6xx.658ci — Padding-bottom reducido de 1rem a 0.5rem para que
   * TODAS las cabeceras de floating panels tengan el mismo tamaño
   * pequeño (estilo panel-color). Antes había 2 tipos: pequeñas
   * (panel-color) y grandes (panel-brushes con su decoración extra).
   * El user pidió unificar todo al tamaño pequeño.
   * §22.6xx.658cj — Padding-bottom subido de 0.5rem a 0.65rem para
   * evitar que los botones se solapen con la zona inferior del header.
   * Roberto pidió "pocos píxeles más, no mucho". */
  padding: 0.35rem 0.8rem 0.65rem 0.8rem;
  /* Color base del panel (rgba(11, 29, 28, 0.92)) — capa de respaldo */
  background-color: rgba(11, 29, 28, 0.92);
  background-image: var(--ui-texture-interface, url('../resources/ui-textures/interface-texture.webp'));
  /* §22.6xx.interface-texture-rotate-vertical.v3 — Header HORIZONTAL.
     Tamaño FIJO 1100×300 (nativo de la textura), centrado. Sin scaling. */
  background-size: 1100px 300px;
  background-repeat: no-repeat;
  background-position: center;
  color: var(--sepia);
  cursor: grab;
  touch-action: none;
  overflow: hidden;
}
/* Fase shadow (grosor) justo debajo del header — usa la misma textura */
.floating-panel-header::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 6px;
  background-color: #a08250;
  background-image: var(--ui-texture-interface, url('../resources/ui-textures/interface-texture.webp'));
  /* §22.6xx.interface-texture-rotate-vertical.v3 — Strip horizontal.
     Tamaño nativo 1100×300. */
  background-size: 1100px 300px;
  background-blend-mode: multiply;
  z-index: 0;
}

.floating-panel-header:active {
  cursor: grabbing;
}
/* El contenido del header va encima del strip shadow. */
.floating-panel-header > * {
  position: relative;
  z-index: 1;
}

.floating-panel-header--no-drag {
  cursor: default;
  touch-action: auto;
}
.floating-panel-header--no-drag:active {
  cursor: default;
}

.floating-panel-header--light-title {
  color: #F4D58D !important;
}
.floating-panel-header--light-title .floating-panel-title,
.floating-panel-header--light-title i,
.floating-panel-header--light-title p {
  color: #F4D58D !important;
}

.floating-panel-title {
  margin: 0;
  font-family: 'Cherry Swash', cursive;
  font-size: 1.15rem;
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: 0.05em;
  color: rgba(255, 255, 255, 0.92);
  /* §22.6xx.outline-title — Efecto de contorno para legibilidad del título
     sobre el wood-texture del header. En modo oscuro (wood bg) el texto
     es claro y el contorno es oscuro (`--sepia` = color del texto en
     modo claro). En modo claro (`.desk-light`, ver dialogs.css) el
     contorno se invierte a `--ivory` (color del texto en modo oscuro).
     Drop shadow original (offset y=1px) se elimina porque el outline
     de 4 lados ya cubre el efecto de profundidad. */
  text-shadow:
    -1px -1px 0 var(--sepia),
     1px -1px 0 var(--sepia),
    -1px  1px 0 var(--sepia),
     1px  1px 0 var(--sepia);
}
.floating-panel-actions {
  display: flex;
  align-items: center;
  gap: 0.25rem;
}

/* §22.6xx.658dj — `:is()` para cubrir los dos nombres: los botones de madera
   ya no llevan `btn-square` (usan `.btn-wood-icon`), pero los demás del panel
   sí. Mismo valor de especificidad que antes, así que no cambia el orden. */
.floating-panel-actions :is(.btn-square, .btn-wood-icon) {
  min-width: 1.75rem;
  min-height: 1.75rem;
  width: 1.75rem;
  height: 1.75rem;
  font-size: 0.95rem;
}



/* === Brush viewport (brush-view list/settings/scroll) === */

.brush-viewport {
  position: relative;
  width: 100%;
  min-height: 0;
  overflow: hidden;
  max-width: 100%;
}

.floating-panel .brush-viewport {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  max-width: 100%;
}

.brush-view {
  width: 100%;
  max-width: 100%;
  transition: transform 280ms cubic-bezier(0.32, 0.72, 0.32, 1.04);
  will-change: transform;
  min-height: 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  overflow: clip;
}

.brush-view-list {
  transform: translateX(0);
  flex: 1 1 auto;
}

.brush-view-list.is-out {
  transform: translateX(-100%);
}

.brush-view-settings {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  transform: translateX(100%);
  max-width: 100%;
  overflow: clip;
}

.brush-view-settings.is-in {
  transform: translateX(0);
}

.brush-view-scroll {
  flex: 1 1 auto;
  /* min-height:0 → flex item puede encogerse verticalmente (scroll vertical) */
  min-height: 0;
  min-width: 0;
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-gutter: stable;
}
/* la mayoría de paneles pasan a ~300px (mismo que el */
.floating-panel-wide {
  width: min(92vw, 18.75rem);
}

.floating-panel-xl {
  width: min(92vw, 22rem);
}

.floating-panel-resize-handle {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 12px;
  cursor: ns-resize;
  z-index: 4;
  display: flex;
  align-items: center;
  justify-content: center;
  touch-action: none;
  border-bottom-left-radius: inherit;
  border-bottom-right-radius: inherit;
}

.floating-panel-resize-handle::before {
  content: '';
  width: 48px;
  height: 3px;
  background: var(--brass, #c85a29);
  opacity: 0.5;
  border-radius: 999px;
  transition: opacity 140ms ease, width 140ms ease;
}

.floating-panel:hover .floating-panel-resize-handle::before {
  opacity: 0.8;
}

.floating-panel-resize-handle:hover::before,
.floating-panel-resize-handle.is-resizing::before {
  opacity: 1;
  width: 64px;
}



/* === Dialog panel === */

.dialog-panel {
  /* §22.6xx.656n — Drop del dark transparent y el box-shadow. Solo fondo plano. */
  background-color: var(--panel-cream);
  /* §22.6xx.656bl iter 6 — Cambio soft-light → multiply. El sepia
     oscuro sobre cream con soft-light aclaraba (efecto "blanco").
     Multiply oscurece claramente. */
  background-image: var(--ui-texture-paper-noise);
  background-repeat: repeat;
  background-size: 240px 240px;
  background-blend-mode: multiply;
  /* fix: overflow: hidden para que el border-radius */
  overflow: hidden;
}

.dialog-panel .text-base.font-semibold {
  font-family: 'Cherry Swash', cursive !important;
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: 0.04em;
}

.floating-panel .panel-body {
  overflow-y: auto;
}

.global-brush-settings-inline-actions :is(.btn-square, .btn-wood-icon) {
  min-width: 2.25rem;
  min-height: 2.25rem;
  width: 2.25rem;
  height: 2.25rem;
}.range,

/* === Form inputs (text-field, range, mono) === */

.range-primary,
input[type="range"] {
  /* §22.6xx.43c — Reset total del appearance nativo del input range. */
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  box-sizing: border-box;
  background: transparent !important;
  background-color: transparent !important;
  /* §22.6xx.43e — width: 100% + padding: 0 → el input ocupa todo el */
  width: 100%;
  padding: 0;
  height: 22px;
  accent-color: var(--brass, #c85a29) !important;
  --range-shdw: var(--brass, #c85a29) !important;
}

input[type="range"]::-webkit-slider-runnable-track {
  /* §22.6xx.43f — appearance: none en el TRACK (no solo en el input). */
  -webkit-appearance: none;
  appearance: none;
  /* §22.6xx.43d — El track se queda en top:0 del input (default WebKit, */
  height: 6px;
  border-radius: 999px;
  /* §22.6xx.43e — color del track más sutil. Antes era rgba(60,40,20,0.4) */
  background: linear-gradient(to right,
    var(--brass, #c85a29) 0%,
    var(--brass, #c85a29) var(--track-value, 0%),
    rgba(92, 64, 51, 0.22) var(--track-value, 0%),
    rgba(92, 64, 51, 0.22) 100%);
}
input[type="range"]::-moz-range-track {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  height: 6px;
  border-radius: 999px;
  background: rgba(92, 64, 51, 0.22);
}
input[type="range"]::-moz-range-progress {
  height: 6px;
  border-radius: 999px;
  background: var(--brass, #c85a29);
}

input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 22px;
  height: 22px;
  /* §22.6xx.43d — margin-top: -8px centra el thumb 22x22 sobre el track */
  margin-top: -8px;
  border-radius: 50%;
  /* background-color sólido SIEMPRE visible */
  background-color: var(--btn-bg, #5C3317);
  /* Solo textura (sin linear/radial encima) */
  background-image: var(--ui-texture-panel, url('../resources/ui-textures/panel-birch.webp'));
  background-size: 240px 240px;
  background-blend-mode: soft-light;
  border: 1px solid rgba(255, 253, 248, 0.35);
  box-shadow:
    inset 0 1px 0 rgba(255, 253, 248, 0.45),
    inset 4px 4px 6px rgba(255, 255, 255, 0.30),
    inset 0 -3px 0 rgba(0, 0, 0, 0.35),
    inset 1.5px 0 0 rgba(0, 0, 0, 0.20),
    inset -1.5px 0 0 rgba(0, 0, 0, 0.20);
  cursor: pointer;
}
input[type="range"]::-moz-range-thumb {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  /* §22.6xx.43d — Firefox: margin-top negativo para centrar el thumb */
  margin-top: -8px;
  background-color: var(--btn-bg, #5C3317);
  background-image: var(--ui-texture-panel, url('../resources/ui-textures/panel-birch.webp'));
  background-size: 240px 240px;
  background-blend-mode: soft-light;
  border: 1px solid rgba(255, 253, 248, 0.35);
  box-shadow:
    inset 0 1px 0 rgba(255, 253, 248, 0.45),
    inset 4px 4px 6px rgba(255, 255, 255, 0.30),
    inset 0 -3px 0 rgba(0, 0, 0, 0.35),
    inset 1.5px 0 0 rgba(0, 0, 0, 0.20),
    inset -1.5px 0 0 rgba(0, 0, 0, 0.20);
  cursor: pointer;
}

input[type="range"]::-webkit-slider-thumb:active {
  background-color: var(--brass, #c85a29) !important;
}
input[type="range"]::-moz-range-thumb:active {
  background-color: var(--brass, #c85a29) !important;
}

/* Sobreescribe .range-primary con el look base (.btn-wood-like). */
.range-primary::-webkit-slider-thumb {
  background-color: var(--btn-bg, #5C3317) !important;
  background-image: var(--ui-texture-panel, url('../resources/ui-textures/panel-birch.webp')) !important;
  background-size: 240px 240px !important;
  background-blend-mode: soft-light !important;
  border: 1px solid rgba(255, 253, 248, 0.35) !important;
  box-shadow:
    inset 0 1px 0 rgba(255, 253, 248, 0.45),
    inset 4px 4px 6px rgba(255, 255, 255, 0.30),
    inset 0 -3px 0 rgba(0, 0, 0, 0.35),
    inset 1.5px 0 0 rgba(0, 0, 0, 0.20),
    inset -1.5px 0 0 rgba(0, 0, 0, 0.20) !important;
  cursor: pointer;
}.color-control-box {
  position: relative;
  width: min(100%, 16rem);
  max-width: 16rem;
  overflow: visible;
  flex: 0 0 auto;
}
.color-wheel-ryb {
  position: absolute;
  inset: 0;
  display: block;
  width: 100% !important;
  height: 100% !important;
  max-width: none !important;
  cursor: crosshair;
  touch-action: none;
}

/* §22.6xx.658dr.114 — Fila de códigos HEX + RGB. El dot del color activo
   se movió a la esquina superior derecha de la rueda, así que esta fila
   ya solo tiene los dos botones de código y gana ~28px.
   `min-width: 0` + `flex: 1` permiten que los botones se encojan en vez
   de desbordar: rgb(255, 255, 255) es más ancho que rgb(51, 51, 51) y
   antes eso empujaba la fila y saltaba un scroll en el panel. */
.color-wheel-compact-header {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 2px 2px 2px;
  min-width: 0;
  /* §22.6xx.658dr.118 — Los botones de código miden 30px sea cual sea la
     altura del panel. Sin esto, al encoger el panel el flex los aplastaba
     hasta 6px. */
  flex-shrink: 0;
  overflow: hidden;
}
.color-wheel-compact-code {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 24px;
  padding: 0 8px;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.45);
  border: 1px solid rgba(80, 60, 45, 0.18);
  color: #2a1f17;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: background 0.12s ease-out, transform 0.1s ease-out;
  white-space: nowrap;
  min-width: 0;
  flex: 0 1 auto;
}
.color-wheel-compact-code span {
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
/* El código RGB es el que más varía de ancho (2 vs 3 cifras por canal), así
   que se deja encoger; el HEX tiene siempre 6 cifras. */
.color-wheel-compact-code:has(+ .color-wheel-compact-code) {
  flex-shrink: 1;
}
.color-wheel-compact-code:last-child {
  flex-shrink: 0;
}

/* §22.6xx.658dr.114 — Dot del color activo, en la esquina superior derecha
   del panel, espejando el botón de info de la superior izquierda. Mantiene
   la interacción de "volver al color base". */
.color-wheel-active-dot {
  position: absolute;
  top: 18px;
  right: 18px;
  z-index: 5;
  width: 32px;
  height: 32px;
  padding: 0;
  border-radius: 50%;
  border: 1.5px solid rgba(80, 60, 45, 0.45);
  box-shadow:
    inset 0 1px 1px rgba(255, 255, 255, 0.4),
    0 1px 2px rgba(0, 0, 0, 0.18);
  cursor: pointer;
  outline: none;
  transition: transform 0.1s ease-out, box-shadow 0.12s ease-out;
}
.color-wheel-active-dot:hover {
  transform: scale(1.12);
  box-shadow:
    inset 0 1px 1px rgba(255, 255, 255, 0.5),
    0 2px 4px rgba(0, 0, 0, 0.25);
}
.color-wheel-active-dot:active {
  transform: scale(0.92);
}

.color-wheel-compact-code:hover {
  background: rgba(255, 255, 255, 0.75);
}
.color-wheel-compact-code:active {
  transform: scale(0.95);
}
.color-wheel-compact-code i {
  font-size: 11px;
  opacity: 0.6;
}

.color-wheel-canvas-wrap {
  display: flex;
  justify-content: center;
  padding: 2px 0;
  /* §22.6xx.658dr.118 — El canvas mide 260px fijos; el wrap solo lo envuelve. */
  flex-shrink: 0;
}
.color-wheel-canvas-wrap .color-control-box {
  width: 260px;
  height: 260px;
}
.color-wheel-canvas-wrap .color-wheel-ryb {
  width: 260px;
  height: 260px;
}

.color-panel-body {
  padding: 10px 10px 10px 10px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  position: relative;
}
/* §22.6xx.658dr.119 — `.panel-body` (chrome.css, más abajo) fija
   `padding-bottom: calc(1.25rem + safe-bottom)`, y al ir más abajo con la
   misma especificidad pisaba el padding-bottom de este panel. Con 1.25rem el
   contenido de Variations pasaba de la altura máxima por 1-7px y el scrollbar
   se quedaba visible a tamaño máximo. Se baja a 0.75rem conservando el
   safe-bottom de las pantallas con notch. */
.panel-body.color-panel-body {
  padding-bottom: calc(0.75rem + var(--safe-bottom));
}

/* §22.520j — Botón info: esquina superior izquierda del content cream */
.color-wheel-info-btn {
  position: absolute;
  top: 18px;
  left: 18px;
  z-index: 5;
  width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 248, 232, 0.7);
  border: none;
  border-radius: 50%;
  color: #6b4d33;
  cursor: pointer;
  font-size: 17px;
  padding: 0;
  transition: background 0.12s ease-out, transform 0.1s ease-out;
}
.color-wheel-info-btn:hover {
  background: rgba(255, 255, 255, 0.95);
  transform: scale(1.08);
}
.color-wheel-info-btn:active {
  transform: scale(0.94);
}

/* §22.6xx.658-iter11 — Containers de colors (Lights/Shadows/Variations) con
   estilo theme-card: paper texture cream + border 3px brass-gold hand-drawn.
   Mismo lenguaje visual que los theme-cards del settings y los tiles del
   support. Override del radius a 8px en desk-light para consistencia. */
.color-wheel-harmonics {
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background-color: transparent !important;  /* el ::before pone la textura */
  border: none !important;  /* el border lo pinta el ::before con filtro hand-drawn */
  border-radius: 16px;
  padding: 4px 8px;
  isolation: isolate;
}
/* Paper texture cream + paper-noise como capa base (mismo patrón que
   support-link-block::before y layer-row base). */
.color-wheel-harmonics::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-color: var(--panel-cream, #f7e6c0) !important;
  background-image: var(--ui-texture-paper-noise) !important;
  background-repeat: repeat !important;
  background-size: 240px 240px !important;
  background-blend-mode: normal !important;
  border-radius: inherit;
  pointer-events: none;
}
/* Border brass-gold hand-drawn (mismo que theme-card::before con scale 2.5). */
.color-wheel-harmonics::after {
  content: "";
  position: absolute;
  inset: 0;
  box-sizing: border-box;
  border: 3px solid var(--ink-stroke, #c5a059);
  border-radius: inherit;
  filter: url(#hand-drawn-filter);
  pointer-events: none;
}
.desk-light .color-wheel-harmonics {
  border-radius: 8px !important;
}
.color-wheel-harmonics-row {
  display: flex;
  align-items: center;
  gap: 8px;
}
.color-wheel-harmonics-row-variations {
  align-items: stretch;
  flex-direction: column;
  gap: 6px;
}
.color-wheel-harmonics-row-variations > .color-wheel-harmonics-label {
  margin-bottom: 2px;
}
.color-wheel-harmonics-label {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #6b4d33;
  flex-shrink: 0;
  min-width: 72px;
}
.color-wheel-harmonics-label i {
  font-size: 12px;
}
.color-wheel-harmonics-label-lights i {
  color: #d97706;
}
.color-wheel-harmonics-label-shadows i {
  color: #5a6ad9;
}
/* §22.520g — Variations: icono ti-binary-tree-2 (estructura de árbol */
.color-wheel-harmonics-label-variations i {
  font-size: 12px;
  color: #4a9b8e;  /* solo el icono mantiene el verde-teal distintivo */
}
.color-wheel-swatches-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 4px;
  align-items: center;
  justify-items: center;
  place-items: center;
  flex: 1;
}
.color-wheel-variations-stack {
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex: 1;
}
.color-wheel-variations-row {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 4px;
  align-items: center;
  justify-items: center;
  place-items: center;
  width: 100%;
}.color-wheel-swatch-compact {
  border-radius: 50%;
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  aspect-ratio: 1;
  justify-self: center;
  align-self: center;
  padding: 0;
  box-sizing: border-box;
}
.color-wheel-swatch-connected {
  position: relative;
}
.color-wheel-swatch-connected::after {
  content: '';
  position: absolute;
  left: calc(100% - 3px);
  top: 50%;
  transform: translateY(-50%);
  width: 10px;
  height: 3px;
  background: #4a3524;
  border-radius: 1.5px;
  pointer-events: none;
  z-index: 1;
  display: none;
}
/* §22.520g — Swatch base: bordes, sombra, cursor. El TAMAÑO y la */
.color-wheel-swatch {
  border: 1px solid rgba(80, 60, 45, 0.22);
  box-shadow:
    inset 0 1px 1px rgba(255, 255, 255, 0.3),
    0 1px 2px rgba(0, 0, 0, 0.12);
  cursor: pointer;
  padding: 0;
  position: relative;
  overflow: hidden;
  transition: transform 0.12s cubic-bezier(0.4, 0, 0.2, 1);
}
.color-wheel-swatch::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.12) 0%, transparent 60%);
  pointer-events: none;
}
.color-wheel-swatch:hover {
  transform: scale(1.12);
  z-index: 2;
  box-shadow:
    inset 0 1px 1px rgba(255, 255, 255, 0.3),
    0 4px 10px rgba(0, 0, 0, 0.22);
}
.color-wheel-swatch:active {
  transform: scale(0.92);
}.color-wheel-mode-btn.is-active {
  background: rgba(217, 119, 6, 0.12);
  border-color: var(--brass, #c85a29);
  color: var(--brass-text, #93411c);
}.color-floating-pill {
  position: relative;
  width: 200px;
  height: 440px;
  border-radius: 100px 100px 16px 16px;
  filter: drop-shadow(0 10px 28px rgba(0, 0, 0, 0.55))
          drop-shadow(0 3px 8px rgba(0, 0, 0, 0.35));
  transition: filter 0.15s;
}
.color-floating-pill:hover {
  filter: drop-shadow(0 14px 32px rgba(0, 0, 0, 0.6))
          drop-shadow(0 4px 10px rgba(0, 0, 0, 0.4));
}

/* Capa 1: shadow (wood oscura, full size) — texture va en pseudo rotado. */
.color-floating-pill-shadow {
  position: absolute;
  inset: 0;
  z-index: 0;
  /* §22.6xx.interface-texture-rotate-vertical — Vertical bar: textura en
     pseudo rotado 90°. Padre mantiene background-color + box-shadow +
     border-radius (no se aplican al pseudo). */
  --bar-wood-color: #a08250;
  background-color: #a08250;
  box-shadow: inset 0 3px 5px rgba(50, 25, 5, 0.6);
  border-radius: 100px 100px 16px 16px;
}

/* Capa 2: top (wood clara) — texture va en pseudo rotado. */
.color-floating-pill-top {
  position: absolute;
  inset: 0 0 15px 0;
  z-index: 1;
  --bar-wood-color: #e7c89a;
  background-color: #e7c89a;
  border-radius: 100px 100px 16px 16px;
  box-shadow: inset 0 -2px 4px rgba(0, 0, 0, 0.1);
}

/* Capa 3: content (cream tallado). §22.520g iter5 — Padding */
.color-floating-pill-content {
  position: absolute;
  z-index: 2;
  top: 12px;
  right: 12px;
  /* §22.6xx.46h — bottom 52 → 46 para que el content se ajuste */
  bottom: 46px;
  left: 12px;
  border-radius: 82px 82px 12px 12px;
  /* §22.6xx.658dr.77 — Papel con noise, como el resto de ventanas, wrappers y
     steppers. Era un gradiente blanco→crema plano, que no era el color correcto
     y además rompía el papel de toda la app. Se copia la receta canónica
     (`--panel-cream` + `--ui-texture-paper-noise`, 240px, blend normal), la
     misma que usan los paneles y el grid Approximate. Los `inset` del
     box-shadow de abajo se conservan: dan el relieve que el gradiente
     aportaba. */
  background-color: var(--panel-cream, #f7e6c0);
  background-image: var(--ui-texture-paper-noise);
  background-repeat: repeat;
  background-size: 240px 240px;
  background-blend-mode: normal;
  box-shadow:
    3px 3px 2px -1px rgba(255, 253, 253, 0.85),
    -2px -3px 4px 0px rgba(0, 0, 0, 0.28),
    inset 0 0 0 1px rgba(0, 0, 0, 0.06),
    inset 2px 3px 2px 2px rgba(0, 0, 0, 0.18),
    0 4px 10px rgba(0, 0, 0, 0.20);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  gap: 4px;
}


.color-floating-pill-wheel {
  display: flex;
  align-items: center;
  justify-content: center;
}
.color-floating-pill-wheel .color-control-box {
  width: 170px;
  height: 170px;
}
.color-floating-pill-wheel .color-wheel-ryb {
  width: 170px;
  height: 170px;
}

/* §22.6xx.658-iter11 — Versión floating-pill de los containers de colors.
   Cada row individual (LIGHTS, SHADOWS, VARIATIONS) tiene estilo theme-card
   en vez de ser un container con rows separados. */
.color-floating-pill-harmonics {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 0;
  margin-bottom: 0;
}
.color-floating-pill-harmonics-row {
  position: relative;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 6px;
  background-color: transparent !important;
  border: none !important;
  border-radius: 12px;
  overflow: hidden;
  isolation: isolate;
}
.color-floating-pill-harmonics-row::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-color: var(--panel-cream, #f7e6c0) !important;
  background-image: var(--ui-texture-paper-noise) !important;
  background-repeat: repeat !important;
  background-size: 240px 240px !important;
  background-blend-mode: normal !important;
  border-radius: inherit;
  pointer-events: none;
}
.color-floating-pill-harmonics-row::after {
  content: "";
  position: absolute;
  inset: 0;
  box-sizing: border-box;
  border: 2px solid var(--ink-stroke, #c5a059);
  border-radius: inherit;
  filter: url(#hand-drawn-filter);
  pointer-events: none;
}
.color-floating-pill-harmonics-row:last-child {
  padding-bottom: 4px;
}

.color-floating-pill-variations-row {
  align-items: stretch;
  flex-direction: column;
  gap: 4px;
}
.color-floating-pill-variations-stack {
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex: 1;
  width: 100%;
}
.color-floating-pill-variations-line {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 4px;
  align-items: center;
  width: 100%;
  justify-items: center;
}
.color-floating-pill-icon-sun,
.color-floating-pill-icon-moon,
.color-floating-pill-icon-variations {
  font-size: 11px;
  flex-shrink: 0;
  width: 13px;
  text-align: center;
}
.color-floating-pill-icon-sun {
  color: #d97706;
}
.color-floating-pill-icon-moon {
  color: #5a6ad9;
}.color-floating-pill-pigment-btn.is-active {
  background: rgba(217, 119, 6, 0.12);
  border-color: var(--brass, #c85a29);
  color: var(--brass-text, #93411c);
}

/* §22.520g — Variations en la pill: 2 filas compactas con líneas */
.color-floating-pill-swatches {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 4px;
  align-items: center;
  flex: 1;
}
.color-floating-pill-swatches .color-floating-pill-swatch {
  margin: 0 auto;
}
.color-floating-pill-variations-row {
  align-items: flex-start;
}
.color-floating-pill-variations-stack {
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex: 1;
}
.color-floating-pill-swatch-connected {
  position: relative;
}
.color-floating-pill-swatch-connected::after {
  content: '';
  position: absolute;
  left: calc(100% - 1px);
  top: 50%;
  transform: translateY(-50%);
  width: 6px;
  height: 2px;
  background: #4a3524;
  border-radius: 1px;
  pointer-events: none;
  z-index: 1;
  display: none;
}
.color-floating-pill-swatch {
  width: 22px;
  height: 22px;
  min-width: 22px;
  max-width: 22px;
  min-height: 22px;
  max-height: 22px;
  border-radius: 50%;
  aspect-ratio: 1 / 1;
  border: 1.2px solid rgba(80, 60, 45, 0.3);
  box-shadow:
    inset 0 1px 1px rgba(255, 255, 255, 0.3),
    0 1px 1px rgba(0, 0, 0, 0.12);
  cursor: pointer;
  padding: 0;
  transition: transform 0.12s ease-out;
  flex-shrink: 0;
  display: block;
  box-sizing: border-box;
}
.color-floating-pill-swatch:hover {
  transform: scale(1.18);
  z-index: 2;
}
.color-floating-pill-swatch:active {
  transform: scale(0.9);
}

/* §22.520d — 3 botones (maximize, drag, close) en la MISMA FILA */
.color-floating-handle,
.color-floating-maximize,
.color-floating-close {
  position: absolute;
  width: 28px;
  height: 28px;
  bottom: 18px;
  z-index: 4;
}
.color-floating-maximize {
  left: 44px;
}
.color-floating-handle {
  left: 86px;
}
.color-floating-close {
  left: 128px;
}

.color-floating-handle,
.color-floating-maximize,
.color-floating-close {
  position: absolute;
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background-color: var(--btn-bg, #5C3317);
  background-image:
    linear-gradient(180deg, rgba(255, 255, 255, 0.12), rgba(0, 0, 0, 0) 55%),
    var(--ui-texture-panel, url('../resources/ui-textures/panel-birch.webp'));
  background-size: cover, 240px 240px;
  background-blend-mode: normal, soft-light;
  color: var(--btn-text-color, #F4D58D);  /* §22.6xx.658-iter26: auto-contraste por luminancia */
  border: none;
  border-radius: 5px;
  cursor: pointer;
  flex-shrink: 0;
  font-size: 0.75rem;
  padding: 0;
  box-shadow:
    inset 0 1px 0 rgba(255, 253, 248, 0.35),
    inset 0 -2px 0 rgba(0, 0, 0, 0.35),
    inset 1.5px 0 0 rgba(0, 0, 0, 0.20),
    inset -1.5px 0 0 rgba(0, 0, 0, 0.20),
    0 2px 0 var(--btn-bg-raised, #3D2314),
    0 3px 6px rgba(0, 0, 0, 0.30);
  transition: transform 90ms ease, box-shadow 90ms ease, background-color 140ms ease;
  z-index: 4;
  user-select: none;
  -webkit-user-drag: none;
  touch-action: none;
}
.color-floating-handle > i,
.color-floating-maximize > i,
.color-floating-close > i,
.color-floating-handle .ti,
.color-floating-maximize .ti,
.color-floating-close .ti {
  color: var(--btn-text-color, #F4D58D) !important;  /* §22.6xx.658-iter26 */
}
.color-floating-handle:hover,
.color-floating-maximize:hover,
.color-floating-close:hover {
  background-color: var(--btn-bg-hover, #6B3E20);
}
.color-floating-handle:active,
.color-floating-maximize:active,
.color-floating-close:active {
  transform: translateY(2px);
  box-shadow:
    inset 0 2px 3px rgba(0, 0, 0, 0.40),
    inset 0 1px 0 rgba(255, 253, 248, 0.15),
    0 1px 0 var(--btn-bg-raised, #3D2314),
    0 1px 2px rgba(0, 0, 0, 0.30);
}
.color-floating-handle:active {
  cursor: grabbing;
}
.color-floating-handle {
  cursor: grab;
}

/* === Brushes floating panel === */

.brushes-floating-pill {
  position: relative;
  /* §22.438d — Border-radius 15px (era 16) para consistencia con */
  border-radius: 15px;
  /* Mismo drop-shadow exterior que el .lofi-youtube-pill. */
  filter: drop-shadow(0 10px 28px rgba(0, 0, 0, 0.55))
          drop-shadow(0 3px 8px rgba(0, 0, 0, 0.35));
  transition: filter 0.15s;
}

.brushes-floating-pill:hover {
  filter: drop-shadow(0 14px 32px rgba(0, 0, 0, 0.6))
          drop-shadow(0 4px 10px rgba(0, 0, 0, 0.4));
}

.brushes-floating-pill-shadow {
  position: absolute;
  inset: 0;
  z-index: 0;
  /* §22.6xx.interface-texture-rotate-vertical — Vertical bar default
     (orientation='vertical' en brushes-panel.js). Textura en pseudo rotado. */
  --bar-wood-color: #a08250;
  background-color: #a08250;
  box-shadow: inset 0 3px 5px rgba(50, 25, 5, 0.6);
  border-radius: 15px;
}

/* §22.438d — Capa 2: top (wood clara). Antes era `inset 0 0 5% 0` */
.brushes-floating-pill-top {
  position: absolute;
  inset: 0 0 15px 0;
  z-index: 1;
  --bar-wood-color: #e7c89a;
  background-color: #e7c89a;
  border-radius: 15px;
  box-shadow: inset 0 -2px 4px rgba(0, 0, 0, 0.1);
}

/* §22.6xx.interface-texture-rotate-vertical — Las overrides
   `.brushes-floating-pill--vertical` (re-declaraban el background-image)
   eran redundantes: el base ya lo declaraba. Eliminadas.
   El override `.brushes-floating-pill--horizontal` sigue vivo en el
   bloque compartido arriba (oculta el pseudo y aplica textura directa). */

.brushes-floating-pill-content {
  position: absolute;
  z-index: 2;
  top: 12px;
  right: 12px;
  bottom: 22px;
  left: 36px;
  border-radius: 10px;
  /* §22.6xx.658dr.79 — Papel con noise, como el resto de ventanas, wrappers y
     steppers (mismo criterio que §658dr.77 para el pill de color). Era un
     gradiente blanco→crema plano. */
  background-color: var(--panel-cream, #f7e6c0);
  background-image: var(--ui-texture-paper-noise);
  background-repeat: repeat;
  background-size: 240px 240px;
  background-blend-mode: normal;
  box-shadow:
    3px 3px 2px -1px rgba(255, 253, 253, 0.85),
    -2px -3px 4px 0px rgba(0, 0, 0, 0.28),
    inset 0 0 0 1px rgba(0, 0, 0, 0.06),
    inset 2px 3px 2px 2px rgba(0, 0, 0, 0.18),
    0 4px 10px rgba(0, 0, 0, 0.20);
  overflow: hidden;
}

/* §22.438d — Horizontal: el "borde ancho" es el TOP. Content con */
.brushes-floating-pill--horizontal .brushes-floating-pill-content {
  top: 38px;
  left: 12px;
  bottom: 24px;
}

.brushes-floating-handle,
.brushes-floating-orientation,
.brushes-floating-close,
.brushes-floating-maximize,
.layers-floating-btn-add,
.layers-floating-btn-hide,
.layers-floating-btn-delete {
  position: absolute;
  width: 24px;
  height: 24px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background-color: var(--btn-bg, #5C3317);
  background-image:
    linear-gradient(180deg, rgba(255, 255, 255, 0.12), rgba(0, 0, 0, 0) 55%),
    var(--ui-texture-panel, url('../resources/ui-textures/panel-birch.webp'));
  background-size: cover, 240px 240px;
  background-blend-mode: normal, soft-light;
  color: var(--btn-text-color, #F4D58D);  /* §22.6xx.658-iter26: auto-contraste por luminancia */
  border: none;
  border-radius: 5px;
  cursor: pointer;
  flex-shrink: 0;
  font-size: 0.7rem;
  padding: 0;
  box-shadow:
    inset 0 1px 0 rgba(255, 253, 248, 0.35),
    inset 0 -2px 0 rgba(0, 0, 0, 0.35),
    inset 1.5px 0 0 rgba(0, 0, 0, 0.20),
    inset -1.5px 0 0 rgba(0, 0, 0, 0.20),
    0 2px 0 var(--btn-bg-raised, #3D2314),
    0 3px 6px rgba(0, 0, 0, 0.30);
  transition: transform 90ms ease, box-shadow 90ms ease, background-color 140ms ease;
  z-index: 4;
  user-select: none;
  -webkit-user-drag: none;
  touch-action: none;
}
.brushes-floating-handle > i,
.brushes-floating-orientation > i,
.brushes-floating-close > i,
.brushes-floating-maximize > i,
.layers-floating-btn-add > i,
.layers-floating-btn-hide > i,
.layers-floating-btn-delete > i,
.brushes-floating-handle .ti,
.brushes-floating-orientation .ti,
.brushes-floating-close .ti,
.brushes-floating-maximize .ti {
  color: var(--btn-text-color, #F4D58D) !important;  /* §22.6xx.658-iter26 */
}
.brushes-floating-handle:hover,
.brushes-floating-orientation:hover,
.brushes-floating-close:hover,
.brushes-floating-maximize:hover,
.layers-floating-btn-add:hover,
.layers-floating-btn-hide:hover,
.layers-floating-btn-delete:hover {
  background-color: var(--btn-bg-hover, #6B3E20);
}
.brushes-floating-handle:active,
.brushes-floating-orientation:active,
.brushes-floating-close:active,
.brushes-floating-maximize:active {
  transform: translateY(2px);
  box-shadow:
    inset 0 2px 3px rgba(0, 0, 0, 0.40),
    inset 0 1px 0 rgba(255, 253, 248, 0.15),
    0 1px 0 var(--btn-bg-raised, #3D2314),
    0 1px 2px rgba(0, 0, 0, 0.30);
}
.brushes-floating-handle:active {
  cursor: grabbing;
}

/* §22.438d — Posiciones de los botones en el BORDER wood del pill. */
.brushes-floating-handle {
  top: 6px;
  left: 6px;
  cursor: grab;
}

/* Switch de orientación: VERTICAL → segundo en columna izquierda. */
.brushes-floating-orientation {
  top: 36px;
  left: 6px;
}
.brushes-floating-pill--horizontal .brushes-floating-orientation {
  top: 6px;
  left: 36px;
}

/* Maximize: VERTICAL → tercero en columna izquierda. */
.brushes-floating-maximize {
  top: 66px;
  left: 6px;
}
.brushes-floating-pill--horizontal .brushes-floating-maximize {
  top: 6px;
  right: 36px;
  left: auto;
}

/* Close: VERTICAL → último en columna izquierda. */
.brushes-floating-close {
  top: 96px;
  left: 6px;
}
.brushes-floating-pill--horizontal .brushes-floating-close {
  top: 6px;
  right: 6px;
  left: auto;
}

.brushes-floating-grid {
  position: absolute;
  top: 4px;
  right: 6px;
  bottom: 4px;
  left: 6px;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: flex-start;
}
/* Vertical: columna. Padding-top/bottom 6px para que los brushes */
.brushes-floating-pill--vertical .brushes-floating-grid {
  flex-direction: column;
  overflow-y: auto;
  overflow-x: hidden;
  align-items: stretch;
  gap: 4px;
}
/* Horizontal: fila. */
.brushes-floating-pill--horizontal .brushes-floating-grid {
  flex-direction: row;
  overflow-x: auto;
  overflow-y: hidden;
  justify-content: flex-start;
  align-items: center;
  gap: 4px;
}

.brushes-floating-item {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 0.5rem;
  background: linear-gradient(180deg, #ffffff 0%, #f4ebe1 100%);
  border: 2px solid rgba(92, 64, 51, 0.18);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.6),
    0 1px 2px rgba(0, 0, 0, 0.10);
  cursor: pointer;
  padding: 0;
  position: relative;
  transition:
    transform 100ms ease-out,
    background 180ms cubic-bezier(0.2, 0, 0, 1),
    border-color 180ms cubic-bezier(0.2, 0, 0, 1),
    box-shadow 180ms cubic-bezier(0.2, 0, 0, 1);
}
.brushes-floating-item:hover {
  transform: scale(1.08);
  border-color: color-mix(in srgb, var(--brass) 50%, transparent);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.6),
    0 4px 8px rgba(60, 30, 10, 0.25);
}
/* §22.6xx.568 — Selected: estilo "destacado" coherente con el main
 * brush panel y el .layer-row.layer-active. Border 2.5px brass,
 * gradient cream→naranja, box-shadow con glow brass. Mismo lenguaje
 * visual que los formatos destacados del create-pad. */
.brushes-floating-item.is-selected {
  border-color: var(--brass, #c85a29) !important;
  border-width: 2.5px !important;
  background:
    linear-gradient(135deg, rgba(254, 245, 235, 0.95) 0%, rgba(252, 232, 220, 0.65) 100%) !important;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.8),
    0 0 0 1px rgba(200, 90, 41, 0.10),
    0 2px 6px rgba(200, 90, 41, 0.10) !important;
}
.brushes-floating-item-canvas {
  width: 30px;
  height: 30px;
  border-radius: 0.35rem;
  display: block;
}

/* §22.438b — Resize bar: SIBLING del content, posicionada en el */
.brushes-floating-resize-bar {
  position: absolute;
  z-index: 4;
  touch-action: none;
  background-color: rgba(92, 64, 51, 0.5);
  transition: background-color 120ms ease;
  border-radius: 3px;
}
.brushes-floating-resize-bar-bottom {
  bottom: 3px;
  left: 37.5%;
  right: 37.5%;
  height: 6px;
  cursor: ns-resize;
}
.brushes-floating-resize-bar-right {
  top: 37.5%;
  bottom: 37.5%;
  right: 3px;
  width: 6px;
  cursor: ew-resize;
}
.brushes-floating-resize-bar:hover {
  background-color: var(--brass, #c85a29);
}


/* §22.6xx.audit-a2 — Badge "Built-in" / "Theme" del pane de Resources:
   píldora coral. Tinte de --brass al 10% + borde al 28% (patrón del workspace). */
.badge-wood {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.1rem 0.5rem;
  font-size: 0.7rem;
  font-weight: 600;
  line-height: 1.4;
  white-space: nowrap;
  color: var(--brass-dark, #93411c);
  background: rgba(200, 90, 41, 0.10);
  border: 1px solid rgba(200, 90, 41, 0.28);
  border-radius: 999px;
}
.badge-wood .ti {
  font-size: 0.8rem;
}

.recent-color-chip {
  aspect-ratio: 1 / 1;
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 0.85rem;
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.05),
    0 8px 18px rgba(0, 0, 0, 0.14);
  transition: transform 110ms ease-out, box-shadow 110ms ease-out;
}

.recent-color-chip:hover,
.recent-color-chip:focus-visible {
  transform: scale(1.05);
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.08),
    0 10px 20px rgba(0, 0, 0, 0.18);
}

/* §22.6xx.519 — Palettes panel: tab bar usa el patrón shared
   "Modo de jitter" del Pincel Sucio). NO se redefine aquí.
   Solo añadimos los estilos específicos del tab "My Colors":
   slot unificado (lleno vs vacío) + delete X sobre chip en edit mode. */

/* Wrapper de cada slot del grid. Necesita position:relative para que
   el .my-color-delete (absolute) se posicione relativo al slot. */
.my-color-slot-wrapper {
  position: relative;
  width: 100%;
}

/* Botón unificado de slot. Cambia su apariencia según la clase
   `.is-filled` (chip con color de fondo) o `.is-empty` ("+ slot"
   con borde dashed). Aspect-ratio 1:1 para mantener la grid
   perfectamente cuadrada. */
.my-color-slot {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  aspect-ratio: 1 / 1;
  border-radius: 0.85rem;
  cursor: pointer;
  transition: border-color 140ms ease, color 140ms ease,
              background 140ms ease, transform 110ms ease-out;
  padding: 0;
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.05),
    0 8px 18px rgba(0, 0, 0, 0.14);
}

/* Slot LLENO: chip de color con borde sutil blanco (mismo look que
   .recent-color-chip). */
.my-color-slot.is-filled {
  border: 1px solid rgba(255, 255, 255, 0.14);
}

.my-color-slot.is-filled:hover,
.my-color-slot.is-filled:focus-visible {
  transform: scale(1.05);
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.08),
    0 10px 20px rgba(0, 0, 0, 0.18);
}

/* Slot VACÍO: "+ slot" con dashed border sepia suave y + centrado.
   Hover: glow brass. */
.my-color-slot.is-empty {
  border: 1.5px dashed rgba(92, 64, 51, 0.28);
  background: rgba(252, 247, 238, 0.5);
  color: rgba(92, 64, 51, 0.5);
}

.my-color-slot.is-empty:hover,
.my-color-slot.is-empty:focus-visible {
  border-color: var(--brass, #c85a29);
  color: var(--brass-text, #93411c);
  background: rgba(200, 90, 41, 0.06);
  transform: scale(1.02);
}

/* El icono + DENTRO del slot: oculto cuando el slot está lleno. */
.my-color-slot-plus {
  font-size: 1.25rem;
  line-height: 1;
}

/* Cuando el slot está lleno, ocultamos el + con display:none. Usamos
   clase CSS (no x-show) para evitar el bug previo de x-show con
   múltiples condicionales anidados. */
.my-color-slot.is-filled .my-color-slot-plus {
  display: none;
}

/* Botón X para borrar un color en edit mode. Posición absoluta en la
   esquina superior derecha del chip. Cubre el chip para que el click
   NO propague al chip (stopPropagation en el handler del template). */
.my-color-delete {
  position: absolute;
  top: -4px;
  right: -4px;
  width: 1.4rem;
  height: 1.4rem;
  border-radius: 999px;
  border: 1.5px solid var(--ivory, #FFFDF8);
  background: var(--brass, #c85a29);
  color: var(--ivory, #FFFDF8);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
  transition: transform 110ms ease, background 140ms ease;
  z-index: 2;
  padding: 0;
}

.my-color-delete i {
  font-size: 0.85rem;
  line-height: 1;
}

.my-color-delete:hover,
.my-color-delete:focus-visible {
  transform: scale(1.12);
  background: #d8341e;
}.control-value {
  font-size: 0.72rem;
  color: rgba(255, 255, 255, 0.72);
}

/* === Brush thumbnail cards === */

.brush-soft {
  filter: blur(0.25px);
}

.brush-ink {
  border-radius: 0.2rem;
}

.brush-charcoal {
  background:
    radial-gradient(circle, rgba(255, 255, 255, 0.84) 0 28%, rgba(255, 255, 255, 0.32) 46%, transparent 58%),
    radial-gradient(circle at 30% 30%, rgba(255, 255, 255, 0.28), transparent 26%);
}

.brush-marker {
  width: 1rem;
  border-radius: 0.2rem;
}

.color-wheel {
  display: block;
  height: 15rem;
  width: 15rem;
  cursor: crosshair;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.22);
}.brush-preview-tile {
  border-radius: 12px;
  /* §22.6xx.554 — Fondo cream translúcido coherente con .theme-card
   * (antes: #ffffff blanco puro que destacaba como un "relieve feo"
   * sobre el panel cream del floating-panel). */
  background: rgba(255, 255, 255, 0.55);
  border: 1px solid rgba(92, 64, 51, 0.12);
}

.brush-collection {
  display: grid;
}

.brush-collection-grid {
  /* §22.6xx.658-iter9 — 4 items por fila en vez de 3, y gap reducido de
     0.625rem a 0.3rem (5px) para que los tiles se vean más compactos
     y menos espaciados. Acompañado de .brush-item-grid con padding 0.25rem
     para maximizar el área del preview. */
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.3rem;
}

.brush-collection-list {
  grid-template-columns: 1fr;
  gap: 0.5rem;
}

/* §22.387.3 — Pack selector (dropdown ARRIBA del grid de brushes). */
.brush-pack-selector {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.4rem 0.5rem 0.5rem;
  margin-bottom: 0.25rem;
}

/* §22.6xx.39o-packs-ui-iter28 — .brush-pack-selector-select ya no tiene
   estilos custom. Hereda todo del rule global `select` (chrome.css:4680).
   La clase se mantiene solo para semántica. */
.brush-pack-selector-select {
  flex: 1 1 auto;
  min-width: 0;
}

/* §22.6xx.658-iter22 — El botón refresh del pack selector ahora usa
   btn-wood btn-square btn-xs (mismo patrón que los icon-buttons del header).
   Las reglas .brush-pack-selector-refresh quedan obsoletas (removidas). */

/* §22.6xx.658-iter23 — Override del tamaño del botón refresh del pack
   selector. btn-square default es 3rem (48px), demasiado grande para
   acompañar al dropdown. Reducido a 2rem (32px) — mismo tamaño que
   los btn-square btn-xs del page-nav-pill-content (chrome.css:2667). */
.brush-pack-selector > .btn-wood-icon {
  min-width: 2rem;
  min-height: 2rem;
  width: 2rem;
  height: 2rem;
  padding: 0;
}

.brush-item {
  display: flex;
  border-radius: 12px;
  position: relative;
  /* §22.6xx.554 — Estilo unificado con .theme-card (paneles claros
   * cream). Reemplaza los rings de Tailwind (ring-1 ring-base-300 y
   * ring-2 ring-primary) que creaban un "relieve feo" gris/azul sobre
   * el panel cream. Ahora: fondo cream translúcido + border sepia
   * sutil, igual que las .theme-row del resto de dialogs. */
  background: rgba(255, 255, 255, 0.55);
  border: 2px solid rgba(92, 64, 51, 0.12);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.02), inset 0 1px 0 rgba(255, 255, 255, 0.8);
  transition:
    background 180ms cubic-bezier(0.2, 0, 0, 1),
    border-color 180ms cubic-bezier(0.2, 0, 0, 1),
    box-shadow 180ms cubic-bezier(0.2, 0, 0, 1);
}

.brush-item:hover {
  background: rgba(255, 255, 255, 0.75);
  border-color: rgba(92, 64, 51, 0.22);
}

/* §22.6xx.568 — Selected: estilo "destacado" coherente con

 * El feedback anterior (border 1px brass + cream flat + box-shadow
 * 12% brass) era demasiado sutil. Ahora la grid de pinceles destaca
 * con:
 *   - border 2.5px brass (era 1px)
 *   - gradient cream→naranja claro (era flat cream)
 *   - box-shadow con glow brass exterior (efecto "destacado")
 *   - thumbnail con ring brass-gradient
 *   - nombre del brush en color brass
 * Mismo lenguaje visual que los "formatos destacados" del create-pad
 * y la capa activa del layers panel, para coherencia cross-UI. */
.brush-item.is-selected,
.brush-item[class*="ring-primary"] {
  background:
    linear-gradient(135deg, rgba(254, 245, 235, 0.95) 0%, rgba(252, 232, 220, 0.65) 100%) !important;
  border-color: var(--brass, #c85a29) !important;
  border-width: 2.5px !important;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.8),
    0 0 0 1px rgba(200, 90, 41, 0.10),
    0 2px 6px rgba(200, 90, 41, 0.10) !important;
}
/* Thumbnail ring cuando el brush está selected: brass-gradient. */
.brush-item.is-selected .brush-preview-tile {
  background: linear-gradient(135deg, rgba(200, 90, 41, 0.30) 0%, color-mix(in srgb, var(--brass) 22%, transparent) 100%) !important;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.6), 0 1px 3px rgba(200, 90, 41, 0.20);
}
/* Nombre del brush selected en color brass — coherente con el

 * .layer-row.layer-active .text-field-transparent. */
.brush-item.is-selected .brush-name {
  color: var(--brass-text, #93411c) !important;
}

/* §22.6xx.555f — Badge del loader durante el warmup. Mismo tamaño
 * que el badge de dynamics, fondo cream translúcido para encajar con
 * el estilo del panel. Animación de pulse sutil para llamar la
 * atención sin ser intrusivo. */
.absolute.warmup-active {
  background: rgba(255, 248, 230, 0.9);
  border: 1px solid rgba(200, 90, 41, 0.35);
  animation: warmup-pulse 1.4s ease-in-out infinite;
}

@keyframes warmup-pulse {
  0%, 100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(200, 90, 41, 0.0); }
  50% { transform: scale(1.08); box-shadow: 0 0 0 4px rgba(200, 90, 41, 0.18); }
}

/* §22.6xx.555g — Loader CENTRADO sobre la imagen del brush. Overlay
 * absoluto que cubre el brush-preview-tile y muestra un spinner
 * brass en el centro exacto. Más prominente que el badge de la
 * esquina. Animación de pulse del fondo para llamar la atención. */
.brush-warmup-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 248, 230, 0.55);
  border-radius: 12px;
  animation: warmup-overlay-pulse 1.4s ease-in-out infinite;
  z-index: 2;
}

.brush-warmup-spinner {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.2rem;
  height: 2.2rem;
  border-radius: 999px;
  background: rgba(255, 248, 230, 0.95);
  border: 1.5px solid rgba(200, 90, 41, 0.45);
  color: var(--brass-text, #93411c);
  font-size: 1.05rem;
  box-shadow: 0 4px 12px rgba(200, 90, 41, 0.15);
}

@keyframes warmup-overlay-pulse {
  0%, 100% { background: rgba(255, 248, 230, 0.45); }
  50% { background: rgba(255, 248, 230, 0.7); }
}

.brush-item-grid {
  min-height: 5.6rem;
  flex-direction: column;
  align-items: center;
  gap: 0.25rem;
  padding: 0.25rem;
}

.brush-item-list {
  align-items: center;
  gap: 0.55rem;
  padding: 0.42rem 0.55rem;
}

.brush-preview-grid {
  width: 100%;
  aspect-ratio: 1 / 1;
}

.brush-preview-list {
  flex: 0 0 auto;
  width: 2.9rem;
  height: 2.9rem;
}

.brush-name {
  min-width: 0;
}

.brush-name-grid {
  width: 100%;
  text-align: center;
  font-size: 0.625rem;
  line-height: 1.1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.brush-name-list {
  flex: 1 1 auto;
  text-align: left;
  font-size: 0.72rem;
  font-weight: 600;
  line-height: 1.15;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.btn-square {
  min-height: 3rem;
  min-width: 3rem;
}

.logo-mark {
  filter: drop-shadow(0 8px 18px rgba(0, 0, 0, 0.18));
}

.panel-sheet {
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  touch-action: pan-y;
  will-change: transform, opacity;
}
.pinned-color-wheel-sheet .panel-body {
  padding: 0.8rem;
}

.pinned-color-wheel-sheet .color-control-box {
  width: min(15rem, calc(100vw - 8.25rem));
  max-width: 15rem;
}

.panel-body {
  scroll-padding-top: 1rem;
  scroll-padding-bottom: calc(1rem + var(--safe-bottom));
  padding-bottom: calc(1.25rem + var(--safe-bottom));
}

/* §22.6xx.658dr.131 — La scrollbar de .panel-sheet (blanco translúcido) se
   eliminó: era la única definición global de la app y ya estaba aquí. Además
   estaba muerta por cascada (widgets.css carga después y gana a igual
   especificidad), y sobre crema un blanco al 12% era casi invisible. */


/* === Library dialog === */

.library-dialog .library-grid,
.library-dialog .library-pad-list,
.dialog-panel>.flex-1.overflow-y-auto,

/* === Settings dialog (panes, sections, rows) === */

.settings-tab-pane {
  /* Evitar que el scroll "salte" al fondo del body al hacer scroll */
  overscroll-behavior: contain;
}


.panel-sheet .btn,
.panel-sheet .toggle,
.panel-sheet .select,
.panel-sheet input[type="color"],
.panel-sheet button {
  touch-action: manipulation;
}

.panel-sheet .btn,
.panel-sheet .select,
.panel-sheet input[type="color"] {
  min-height: 2.75rem;
}

/* Importante: las clases se aplican al <section x-ref="viewport">, */

/* === Page viewport (paper texture, binder rings, hand-drawn filter, noise) === */

.page-viewport.page-pan-ready {
  cursor: grab !important;
}

.page-viewport.page-pan-ready canvas {
  cursor: grab !important;
}

.page-viewport.page-pan-active {
  cursor: grabbing !important;
}

.page-viewport.page-pan-active canvas {
  cursor: grabbing !important;
}

.page-viewport.page-zoom-ready,
.page-viewport.page-zoom-active {
  cursor: zoom-in !important;
}

.page-viewport.page-zoom-ready canvas,
.page-viewport.page-zoom-active canvas {
  cursor: zoom-in !important;
}


@media (max-width: 1279px) {
}

@media (max-width: 767px) {
  body {
    padding: 0;
  }



}

@media (max-height: 950px) {
  :root {
    --sidebar-slider-height: 15.5rem;
    --sidebar-slider-input-height: 228px;
  }


/* === Workspace sidebar === */


}

@media (max-height: 820px) {
  :root {
    --sidebar-slider-height: 12.5rem;
    --sidebar-slider-input-height: 186px;
  }



}

@media (max-height: 760px) {
  :root {
    --sidebar-slider-height: 9.75rem;
    --sidebar-slider-input-height: 146px;
  }








  .panel-sheet {
    width: min(18.75rem, calc(100vw - 5rem));
  }


  .panel-body>*+* {
    margin-top: 0.8rem !important;
  }

  .panel-sheet .btn,
  .panel-sheet .select,
  .panel-sheet input[type="color"] {
    min-height: 2.35rem;
  }
}

@media (max-width: 767px) {

  .pinned-color-wheel-sheet .color-control-box {
    width: min(13.5rem, calc(100vw - 7.25rem));
    max-width: 13.5rem;
  }
}.navbar-pressure-toggle-indicator.is-on {
  color: var(--brass);
  /* color primary de la marca */
}/* Active state — panel abierto (Library, Preview, Settings) */

/* === Navbar (sliders, status pills, pressure toggle) === */

.navbar-icon-btn.is-active {
  background: rgba(255, 255, 255, 0.10);
  color: var(--brass);
}/* Track y thumb usan los estilos .range / .range-primary / .range-xs */


/* Pressure toggle button: estado activo se indica con color del icono */
.navbar-pressure-btn.is-active {
  color: var(--brass);
}

.navbar-pressure-btn.is-active:hover {
  background: rgba(200, 90, 41, 0.18);
}

.navbar-status-pill-wrap {
  position: absolute;
  z-index: 80;
  /* Left/top se setean inline via Alpine (:style="left:..;top:.."). */
  pointer-events: none; /* el pill hijo re-habilita */
}

/* ==== Container (island) ==== */
/* Igual que .tray-island pero con ancho FIJO (no crece con el */
.navbar-status-pill {
  position: relative;
  display: inline-flex;
  align-items: stretch;
  pointer-events: none;
  user-select: none;
  cursor: grab;
  -webkit-user-drag: none;
  touch-action: none; /* desactiva scroll/zoom del browser en touch */
  color: rgba(50, 25, 5, 0.92);
  font-size: 0.78rem;
  font-weight: 500;
  /* Ancho FIJO: no crece con el contenido. */
  width: 180px;
  /* Padding interno asimétrico: menos arriba (10px), mucho más */
  padding: 10px 10px 24px 10px;
}

.navbar-status-pill:active {
  cursor: grabbing;
}

/* Hijos directos re-habilitan pointer-events para clicks/drag */
.navbar-status-pill > * {
  pointer-events: auto;
}

/* ==== Capa 1: superficie de la madera (.tray-island-top equivalente) ==== */
.navbar-status-pill-top {
  position: absolute;
  inset: 0 0 10% 0; /* bottom: 10% deja ver el shadow por debajo */
  z-index: 0;
  /* §22.6xx.interface-texture-rotate-vertical — Vertical bar (180px wide).
     Textura en pseudo rotado. Padre mantiene background-color + box-shadow
     + border-radius. */
  --bar-wood-color: #e7c89a;
  background-color: #e7c89a;
  border-radius: 15px;
  box-shadow: inset 0 -2px 4px rgba(0, 0, 0, 0.1);
}

/* ==== Capa 2: grosor lateral de la madera (.tray-island-shadow equivalente) ==== */
.navbar-status-pill-shadow {
  position: absolute;
  inset: 0;
  z-index: -1;
  --bar-wood-color: #a08250;
  background-color: #a08250;
  box-shadow: inset 0 3px 5px rgba(50, 25, 5, 0.6);
  border-radius: 15px;
}

/* ==== Wrapper interior (track de slider equivalente) ==== */
/* Look "track de slider" con efecto de relieve "carved" en la madera */
.navbar-status-pill-content {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: stretch;
  /* Padding generoso: el wrapper necesita aire alrededor del texto */
  padding: 0.55rem 0.7rem;
  border-radius: 16px;
  /* §22.6xx.658dr.79 — Papel con noise, igual que las demás ventanas y
     wrappers. Este bloque decía ser "EXACTO del .navbar-status-pill-content",
     así que arrastraba el mismo gradiente blanco plano que ya se corrigió en
     el pill de color (§658dr.77) y en el de brushes. */
  background-color: var(--panel-cream, #f7e6c0);
  background-image: var(--ui-texture-paper-noise);
  background-repeat: repeat;
  background-size: 240px 240px;
  background-blend-mode: normal;
  /* 4 sombras combinadas (3 carved del groove + 1 drop shadow de */
  box-shadow:
    /* 1. Drop shadow BLANCO (highlight carved) */
    3px 3px 2px -1px rgba(255, 253, 253, 0.85),
    /* 2. Drop shadow NEGRO (profundidad carved) */
    -2px -3px 4px 0px rgba(0, 0, 0, 0.28),
    /* 3. Inset ring NEGRO sutil (línea interior) */
    inset 0 0 0 1px rgba(0, 0, 0, 0.06),
    /* 4. Inset NEGRO (inner shadow del well) */
    inset 2px 3px 2px 2px rgba(0, 0, 0, 0.18),
    /* 5. Drop shadow NEGRO exterior (elevación sobre la madera) */
    0 4px 10px rgba(0, 0, 0, 0.20);
  width: 100%;
}

/* ==== Contenido (rows) ==== */
.navbar-status-pill-rows {
  display: flex;
  flex-direction: column;
  /* Más espacio entre brush y color, para que la fila del color */
  gap: 0.55rem;
  justify-content: center;
  min-width: 0;
  width: 100%;
}

/* ==== Row (icono + texto) ==== */
.navbar-status-pill-row {
  position: relative;
  min-height: 1.45em; /* mínimo = 1 línea de texto */
}

.navbar-status-pill-tool-icon,
.navbar-status-pill-zoom-icon {
  position: absolute;
  left: 0;
  top: 0;
  /* Mismo line-height que el texto para alinear con la primera línea. */
  line-height: 1.45;
  font-size: 0.95rem;
  color: var(--sepia);
}

.navbar-status-pill-text {
  display: block;
  font-family: 'Cherry Swash', cursive;
  font-size: 0.95rem;
  line-height: 1.45; /* mismo que el icono */
  color: rgba(50, 25, 5, 0.92); /* marrón oscuro para contraste con blanco */
  font-weight: 700;
  letter-spacing: 0.01em;
  /* width:100% + padding-left:22px con box-sizing:border-box hace que */
  width: 100%;
  box-sizing: border-box;
  padding-left: 22px;
  /* overflow-wrap:break-word permite romper palabras MUY largas (sin */
  overflow-wrap: break-word;
}

.navbar-status-pill-color-swatch {
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  display: inline-block;
  width: 0.85rem;
  height: 0.85rem;
  border-radius: 50%;
  border: 1px solid rgba(0, 0, 0, 0.28);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.15);
}

.page-nav-pill-wrap {
  position: fixed;
  bottom: 18px;
  right: 18px;
  z-index: 80;
  pointer-events: none;
  display: flex;
  align-items: center;
  justify-content: flex-end;
}

.page-nav-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  height: 40px;
  padding: 0 0.5rem 0 0.55rem;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.08);
  /* §22.6xx.658 — Mismo color cream + paper-noise que los panels (coherencia visual). */
  background-color: var(--panel-cream, #f7e6c0);
  background-image: var(--ui-texture-paper-noise) !important;
  background-repeat: repeat !important;
  background-size: 240px 240px !important;
  background-blend-mode: normal !important;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.32);
  color: rgba(255, 255, 255, 0.85);
  user-select: none;
  pointer-events: auto;
  /* width fit-content para que el pill se ajuste a su */
  width: fit-content;
}

.page-nav-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 999px;
  background: transparent;
  border: none;
  color: rgba(255, 255, 255, 0.85);
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
  transition: background 0.12s ease, color 0.12s ease;
}

.page-nav-pill-content {
  position: relative;
  z-index: 3;
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.3rem;
  pointer-events: auto;
}

.page-nav-pill-content .tray-island-groove {
  padding: 0.3rem;
}
.page-nav-pill-content .tray-island-groove .btn-wood-icon {
  min-width: 2rem;
  min-height: 2rem;
  width: 2rem;
  height: 2rem;
  font-size: 1.25rem;
  padding: 0;
}

.page-nav-btn:hover {
  background: rgba(255, 255, 255, 0.08);
  color: rgba(255, 255, 255, 1);
}

.page-nav-btn:active {
  background: rgba(255, 255, 255, 0.14);
}

.page-nav-btn:disabled {
  color: rgba(255, 255, 255, 0.28);
  cursor: not-allowed;
}

.page-nav-btn:disabled:hover,
.page-nav-btn:disabled:active {
  background: transparent;
}

.page-nav-counter {
  display: inline-block;
  min-width: 3.2rem;
  text-align: center;
  font-size: 0.82rem;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.9);
  letter-spacing: 0.02em;
}

/* §22.6xx.658dr.31 — Hueco fijo que sostiene el contador y el icono de
   guardado. Sin `min-width` en el contenedor, la píldora cambiaría de ancho al
   inhibirse el paginador y el layout daría un tirón en cada cambio de página.
   La animación NO se declara aquí: se reutiliza la utilidad global
   `.loader-bounce` (dialogs.css), la misma que usa el toast de guardado. */
.page-nav-counter-slot {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 3.2rem;
}

.page-nav-busy-icon {
  width: 1.05rem;
  height: 1.05rem;
  opacity: 0.9;
}

/* §22.6xx.658dr.34 — Las flechas se ocultan SIN salir del flujo.
 * `x-show`/`display: none` lasSacaba de la maquetación y la píldora encogía
 * de 118 a 67 px en cada cambio de página: un tirón visible.
 * `visibility: hidden` conserva el ancho, además de quitar el hover y sacar el
 * botón del árbol de accesibilidad. Ya están `disabled`, así que el clic no
 * llega al handler aunque alguien lo intente con el ratón. */
.page-nav-btn--hidden {
  visibility: hidden;
}

.tray-island-groove .tools-btn-trigger {
  min-width: 3rem;
  min-height: 3rem;     /* §22.190o: misma altura que btn-square (3rem = 48px) */
  height: 3rem;          /* fuerza 3rem para igualar al .btn-square.btn-xs neighbor */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 0.95rem;
  padding: 0 0.65rem;
  border-radius: 0.5rem;     /* btn-xs rounded */
  background-color: var(--btn-bg, #5C3317);
  background-image:
    linear-gradient(180deg, rgba(255, 255, 255, 0.12), rgba(0, 0, 0, 0) 55%),
    var(--ui-texture-panel, url('../resources/ui-textures/panel-birch.webp'));
  background-size: cover, 240px 240px;
  background-blend-mode: normal, soft-light;
  color: var(--btn-text-color, #F4D58D);  /* §22.6xx.658-iter26: auto-contraste por luminancia */
  font-weight: 600;
  border: none;
  cursor: pointer;
  user-select: none;
  box-shadow:
    inset 0 1px 0 rgba(255, 253, 248, 0.35),
    inset 0 -3px 0 rgba(0, 0, 0, 0.35),
    inset 1.5px 0 0 rgba(0, 0, 0, 0.20),
    inset -1.5px 0 0 rgba(0, 0, 0, 0.20),
    0 4px 0 var(--btn-bg-raised, #3D2314),
    0 6px 14px rgba(0, 0, 0, 0.45);
  transition: transform 90ms ease, box-shadow 90ms ease, background-color 140ms ease;
  font-size: 0.78rem;     /* btn-xs text */
}
.tray-island-groove .tools-btn-trigger:hover {
  background-color: var(--btn-bg-hover, #6B3E20);
}
.tray-island-groove .tools-btn-trigger.is-open,
.tray-island-groove .tools-btn-trigger:active {
  background-color: color-mix(in srgb, var(--brass, #c85a29) 55%, var(--btn-bg, #5C3317));
  transform: translateY(1px);
  color: #fff;
  box-shadow:
    inset 0 2px 4px rgba(0, 0, 0, 0.40),
    inset 0 1px 0 rgba(255, 253, 248, 0.15),
    0 1px 0 var(--btn-bg-raised, #3D2314),
    0 1px 2px rgba(0, 0, 0, 0.30);
}

/* Línea vertical entre los 2 iconos del botón tools. */
.tray-island-groove .tools-btn-divider {
  display: inline-block;
  width: 1px;
  height: 0.95rem;
  margin: 0 0.35rem;
  border-radius: 1px;
  background-color: rgba(92, 64, 51, 0.22);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.15),
    inset 0 -1px 0 rgba(0, 0, 0, 0.20);
}
.tray-island-groove .tools-btn-trigger.is-open .tools-btn-divider,
.tray-island-groove .tools-btn-trigger:active .tools-btn-divider {
  background-color: rgba(255, 255, 255, 0.25);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.25),
    inset 0 -1px 0 rgba(0, 0, 0, 0.20);
}


/* === Tools menu === */

.tools-menu-wrap {
  /* El wrap es TRANSPARENTE — la madera la ponen los siblings */
  background: transparent;
  background-image: none;
  min-width: 14rem;
  border-radius: 12px;
  position: relative;
  isolation: isolate;   /* evita que el blend mode del menu-top afecte al canvas */
  /* Sin padding ni border — todo lo hace el menu-content */
  overflow: hidden;    /* recorta el pseudo de la textura, como las barras verticales */
}

.tools-menu-top,
.tools-menu-shadow {
  /* §22.6xx.658dr.14 — El desplegable de tools es un elemento VERTICAL: la
     textura va en un pseudo rotado 90°, como el resto de barras verticales
     (ver bloque compartido al inicio de este fichero). Antes iba como
     background-image directo a 1100×300 sin rotar, que es el tratamiento
     de las horizontales — incoherente con un panel que es más alto que
     ancho. El tamaño nativo se mantiene: 1100×300, que tras rotar se ve
     300×1100. */
  background-image: none;
  border-radius: 12px;
}

/* Capa TOP: textura en colores nativos sobre el wood del padre. */
.tools-menu-top::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 1100px;
  height: 300px;
  transform: translate(-50%, -50%) rotate(90deg);
  background-image: var(--ui-texture-interface, url('../resources/ui-textures/interface-texture.webp'));
  background-size: 1100px 300px;
  background-position: center;
  background-repeat: no-repeat;
  z-index: -1;
  pointer-events: none;
}

/* Capa SHADOW: misma textura con tinte multiply del wood-dark. */
.tools-menu-shadow::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 1100px;
  height: 300px;
  transform: translate(-50%, -50%) rotate(90deg);
  background-color: var(--bar-wood-color, #a08250);
  background-image: var(--ui-texture-interface, url('../resources/ui-textures/interface-texture.webp'));
  background-size: 1100px 300px;
  background-position: center;
  background-repeat: no-repeat;
  background-blend-mode: multiply;
  z-index: -1;
  pointer-events: none;
}

.tools-menu-top {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 8%;
  z-index: 0;
  background-color: #e7c89a;
  box-shadow: inset 0 -2px 4px rgba(0, 0, 0, 0.10);
}

.tools-menu-shadow {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: -1;
  background-color: #a08250;
  box-shadow: inset 0 3px 5px rgba(50, 25, 5, 0.6);
}

.tools-menu-content {
  position: relative;
  z-index: 1;
  background-color: var(--panel-cream, #FCF7EE);
  background-image:
    linear-gradient(180deg, rgba(255, 253, 248, 0.5), rgba(255, 248, 232, 0) 50%),
    var(--ui-texture-panel, url('../resources/ui-textures/panel-birch.webp'));
  background-size: cover, 240px 240px;
  background-blend-mode: normal, soft-light;
  border-radius: 10px;
  margin: 4px;
  /* Inset shadow "carved" — el cream se ve tallado en la madera */
  box-shadow:
    inset 0 1px 0 rgba(255, 253, 248, 0.7),
    inset 0 -1.5px 0 var(--brass, #c85a29);
  padding: 0.35rem 0;
  display: flex;
  flex-direction: column;
  min-width: calc(14rem - 8px);
}

.tools-menu-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.75rem;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--sepia, #5C4033);
  text-align: left;
  width: 100%;
  background: transparent;
  border: none;
  cursor: pointer;
  font-family: inherit;
  isolation: isolate;
  overflow: hidden;
  transition: color 90ms ease;
}
/* §22.6xx.658-iter17 — Silueta rasgada en tools-menu-item (hover/active).
   Mismo patrón que .settings-tab-btn: el ::before tiene la textura paper
   + filter #torn-silhouette. El color del bg del ::before cambia en hover
   y active via --tab-bg-color. */
.tools-menu-item::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-color: var(--tab-bg-color, transparent) !important;
  background-image: var(--ui-texture-paper-noise) !important;
  background-repeat: repeat !important;
  background-size: 240px 240px !important;
  background-blend-mode: normal !important;
  filter: url(#torn-silhouette);
  pointer-events: none;
  transition: background-color 90ms ease;
}
.tools-menu-item:hover:not(:disabled) {
  /* §22.6xx.658-iter17 — Brass via --tab-bg-color. Misma silueta que active,
     solo cambia el alpha del color. */
  --tab-bg-color: color-mix(in srgb, var(--brass, #c85a29) 14%, transparent);
  color: var(--brass-text, #93411c);
}
/* §22.6xx.555zz8 — Roberto: "el icono no pasa a color de acento al hacer
   hover". El `text-sepia/70` del icono define el `color` directamente,
   así que el `currentColor` del background-color del icono lee SU
   color (sepia alpha 0.7), no el del button. Hay que sobreescribir el
   `color` del icono explícitamente en hover. El selector captura
   tanto `rp-icon-mini` como `ti-*` (los items que aún no se han
   migrado a `rp`). */
.tools-menu-item:hover:not(:disabled) i {
  color: var(--brass-text, #93411c);
}
.tools-menu-item:active:not(:disabled) {
  background-color: rgba(200, 90, 41, 0.18);
}
.tools-menu-item.is-disabled {
  color: rgba(92, 64, 51, 0.5);
  cursor: not-allowed;
}
/* §22.292 — Section labels en el Tools menu (e.g., "Filters", "Decorations"). */
.tools-menu-section {
  padding: 0.6rem 0.75rem 0.25rem;
  border-top: 1px solid rgba(92, 64, 51, 0.18);
  margin-top: 0.4rem;
}
.tools-menu-section:first-of-type {
  border-top: none;
  margin-top: 0;
  padding-top: 0.4rem;
}
.tools-menu-section-label {
  display: block;
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--sepia-soft-text, #6B4D33);
}

/* === Washi tape panel === */

.washi-tape-icon {
  display: inline-block;
  width: 18px;
  height: 15px;
  background-color: rgba(92, 64, 51, 0.7);
  -webkit-mask: url('../resources/ui-icons/washi-tape.svg') no-repeat center / contain;
          mask: url('../resources/ui-icons/washi-tape.svg') no-repeat center / contain;
}
   blanco) para tener contraste sobre el fondo cream. Sin esta
   regla, el .page-nav-counter heredaba el blanco del rule base
   y era invisible sobre el pill cream. 
.desk-light .page-nav-counter {
  color: var(--sepia) !important;
}

.settings-tab-pane {
  /* Cada panel de tab: visibilidad controlada por x-show (que añade */
}.library-pad-item.is-drop-target {
  background: color-mix(in srgb, var(--brass) 12%, transparent);
  box-shadow: inset 0 0 0 1.5px var(--brass);
  transform: translateX(2px);
}


/* Insert-before: barra accent en el borde superior de la card. */

/* Insert-after: barra accent en el borde inferior de la card. */
.library-pad-item.is-active {
  background: color-mix(in srgb, var(--brass) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--brass) 32%, transparent);
  padding: calc(0.55rem - 1px) calc(0.75rem - 1px);
}.library-pad-item.is-active .library-pad-title {
  color: var(--brass);
  font-weight: 500;
}.library-pad-item:hover .library-pad-actions,
.library-pad-item.is-active .library-pad-actions {
  opacity: 1;
}.library-card.is-active {
  border-color: var(--brass);
  background: color-mix(in srgb, var(--brass) 8%, transparent);
  box-shadow: 0 0 0 1px var(--brass) inset;
}.library-card.is-active .library-card-title {
  color: var(--brass);
}.library-card:hover .library-card-actions,
.library-card.is-active .library-card-actions {
  opacity: 1;
}/* Save indicator: toast flotante que aparece SOLO cuando hay error */

/* === Save indicator (status, error, offline) === */

.save-indicator {
  position: fixed;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 95;
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  padding: 0.65rem 0.75rem 0.65rem 0.95rem;
  background: rgba(11, 29, 28, 0.94);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 14px;
  font-size: 0.78rem;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.92);
  pointer-events: auto;
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  max-width: min(92vw, 28rem);
}

.save-indicator-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.25rem;
  height: 1.25rem;
  flex: 0 0 auto;
  margin-top: 1px;
}

.save-indicator-body {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  min-width: 0;
}

.save-indicator-label {
  font-size: 0.8rem;
  font-weight: 600;
  line-height: 1.2;
}

.save-indicator-message {
  font-size: 0.74rem;
  font-weight: 400;
  color: rgba(255, 255, 255, 0.7);
  line-height: 1.35;
}

.save-indicator-dismiss {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.4rem;
  height: 1.4rem;
  border-radius: 999px;
  background: transparent;
  border: none;
  color: rgba(255, 255, 255, 0.55);
  cursor: pointer;
  flex: 0 0 auto;
  transition: background 0.12s ease, color 0.12s ease;
}

.save-indicator-dismiss:hover {
  background: rgba(255, 255, 255, 0.1);
  color: rgba(255, 255, 255, 1);
}


.save-indicator--error .save-indicator-icon {
  color: #ef4444;
}

.save-indicator--error .save-indicator-label {
  color: #fca5a5;
}
.save-indicator--offline .save-indicator-icon {
  color: #fbbf24;
}

.save-indicator--offline .save-indicator-label {
  color: #fde68a;
}

.save-indicator--pending .save-indicator-icon i {
  animation: save-indicator-spin 1.1s linear infinite;
}

.save-indicator--pending .save-indicator-icon {
  color: #fbbf24;
}

@keyframes save-indicator-spin {
  from {
    transform: rotate(0deg);
  }

  to {
    transform: rotate(360deg);
  }
}

text-* aplicadas via x-bind:class (success/error/info).  @keyframes backup-status-spin {
  from {
    transform: rotate(0deg);
  }

  to {
    transform: rotate(360deg);
  }
}

.ti-loader {
  animation: backup-status-spin 1.1s linear infinite;
  display: inline-block;
}
/* Banner persistente que aparece cuando un guardado a IndexedDB */
.storage-error-banner {
  position: fixed;
  top: 64px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 95;
  display: flex;
  align-items: center;
  gap: 0.85rem;
  padding: 0.75rem 1rem;
  background: rgba(127, 29, 29, 0.96);
  border: 1px solid rgba(248, 113, 113, 0.55);
  border-radius: 16px;
  box-shadow: 0 12px 24px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(248, 113, 113, 0.18) inset;
  color: white;
  max-width: 760px;
  pointer-events: auto;
  backdrop-filter: blur(2px);
  animation: storage-error-pulse 2.5s ease-in-out infinite;
}

@keyframes storage-error-pulse {

  0%,
  100% {
    box-shadow: 0 16px 40px rgba(0, 0, 0, 0.55), 0 0 0 1px rgba(248, 113, 113, 0.18) inset;
  }

  50% {
    box-shadow: 0 16px 40px rgba(0, 0, 0, 0.55), 0 0 0 3px rgba(248, 113, 113, 0.35) inset;
  }
}

.storage-error-icon {
  color: #fbbf24;
  font-size: 1.4rem;
  flex-shrink: 0;
  line-height: 1;
}

.storage-error-icon i {
  filter: drop-shadow(0 0 4px rgba(251, 191, 36, 0.4));
}

.storage-error-body {
  flex: 1;
  min-width: 0;
}

.storage-error-title {
  font-weight: 600;
  font-size: 0.85rem;
  margin: 0 0 2px 0;
  color: #fef3c7;
}

.storage-error-message {
  font-size: 0.72rem;
  margin: 0;
  color: rgba(254, 243, 199, 0.85);
  line-height: 1.4;
}

.storage-error-actions {
  display: flex;
  gap: 0.4rem;
  flex-shrink: 0;
}


/* Overlay fullscreen con efecto Cover Flow 3D nativo (CSS perspective + */

/* === Coverflow overlay === */

.coverflow-overlay {
  position: fixed;
  inset: 0;
  z-index: 110;
  display: flex;
  align-items: center;
  justify-content: center;
  /* El background se aplica via inline style (workspaceStyle). */
  background-color: var(--panel-cream, #FCF7EE);
  padding: 80px 40px 40px;
  user-select: none;
  -webkit-user-select: none;
}

/* close button con estilo btn-wood (mismo que la UI */
.coverflow-close-btn {
  position: absolute;
  top: 16px;
  right: 16px;
  z-index: 2;
  width: 44px;
  height: 44px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}


.coverflow-spread-pill {
  position: absolute;
  top: 16px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 2;
  pointer-events: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.35rem 0.85rem;
  min-width: 8rem;
  /* Wood pill look: mismo gradiente y border-radius que page-nav-pill */
  background-color: rgba(255, 255, 255, 0.85);
  border: 1px solid rgba(92, 64, 51, 0.25);
  border-radius: 0.65rem;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.10);
  font-family: 'Cherry Swash', cursive;
  font-weight: 700;
  font-size: 0.95rem;
  line-height: 1.1;
  color: rgba(92, 64, 51, 0.92);
  white-space: nowrap;
  letter-spacing: 0.01em;
  /* El text-shadow sutil da el efecto "tallado" del estilo wood-pill. */
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.6);
}
.coverflow-spread-label {
  display: inline-block;
  vertical-align: middle;
}

/* Stage 3D: la perspectiva define la profundidad de la escena. */
.coverflow-stage {
  width: 100%;
  height: 100%;
  /* perspective más generosa que Cover Flow para que el lomo */
  perspective: 2000px;
  perspective-origin: 50% 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: grab;
  touch-action: none;
  /* evitar scroll/zoom del navegador durante drag */
}

.coverflow-stage:active {
  cursor: grabbing;
}

/* Book: contenedor 3D. En desktop 400x540, pero en tablet/phone se */
.coverflow-book {
  position: relative;
  /* §22.6xx.506g — Tamaño responsive con aspect ratio 4:5 (relación
   * clásica de libreta). min(400px, calc(100vw - 80px)) garantiza
   * que el book quepa en el padding del overlay (80px horizontal).
   * El aspect-ratio mantiene la proporción al escalar. */
  width: min(400px, calc(100vw - 80px));
  height: auto;
  aspect-ratio: 4 / 5;
  max-height: calc(100vh - 120px);
  transform-style: preserve-3d;
  transform: translateX(50%);
  /* Transición suave cuando el usuario cambia de pad (al abrir */
  transition: width 220ms ease, height 220ms ease;
}

/* El contenedor debe respetar la transición también. */

/* Cada hoja: tarjeta rígida que gira alrededor del LOMO IZQUIERDO. */
.coverflow-leaf {
  position: absolute;
  inset: 0;
  transform-origin: left center;
  transform-style: preserve-3d;
  /* will-change se aplica INLINE desde JS solo durante la
   * animación activa (ver getLeafTransform §22.6xx.506i). */
}

/* Cada cara de la hoja: papel de libreta. backface-visibility: hidden */
.coverflow-page {
  position: absolute;
  inset: 0;
  background: #fdfdfc;
  background-image:
    linear-gradient(135deg, rgba(0, 0, 0, 0.012) 0%, transparent 35%, transparent 65%, rgba(0, 0, 0, 0.012) 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  /* padding 0. La imagen ahora ocupa todo el área */
  padding: 0;
  box-sizing: border-box;
  overflow: hidden;
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 2px 8px 8px 2px;
  /* sutil asimetría: lomo recto, esquina externa redondeada */
  box-shadow:
    0 14px 32px rgba(0, 0, 0, 0.35),
    0 4px 8px rgba(0, 0, 0, 0.18),
    0 0 0 1px rgba(255, 255, 255, 0.05) inset;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

/* Reverso: rotada 180° en Y para que mire al otro lado. translateZ */
.coverflow-page-back {
  transform: rotateY(180deg) translateZ(0.001px);
}

/* §22.6xx.663 — Solo la textura, sin color ni velo.
 *
 * `pad-covers.webp` (1500×1500, VP8 sin canal alfa → opaca) ya es un diseño
 * de portada COMPLETO: papel marbled crema con el marco coral. Encima se le
 * ponían dos capas que solo la ensuciaban:
 *   - `background-color: var(--btn-bg)`: el marrón del BOTÓN, no el color de
 *     la portada. Dejaba la tapa teñida de marrón según el tema.
 *   - `linear-gradient(180deg, rgba(255,255,255,0.12), transparent 55%)`: un
 *     velo blanco que aclaraba la mitad de arriba.
 * El `soft-light` se iba con el color: mezclaba la textura contra él. */
.coverflow-page-back.coverflow-back-cover {
  /* `background-origin: border-box` es lo que hace desaparecer el borde
   * blanco. Sin esto, `background-size: cover` se mide sobre el PADDING box,
   * que es 1 px menor que el border box por el `border` de `.coverflow-page`:
   * la textura no llega al anillo y se ve el `background: #fdfdfc` de la regla
   * base. Medido: 2 px de (244,230,222) alrededor de todo el cover. Con el
   * `background-color: var(--btn-bg)` que había hasta §658dr.663 ese anillo
   * salía marrón y no se notaba; al quitarlo quedó al descubierto. */
  background-origin: border-box;
  background-image: var(--ui-texture-pad-covers, url('../resources/ui-textures/pad-covers.webp'));
  background-size: cover;
  background-repeat: no-repeat;
  background-position: center;
  box-shadow: inset 0 1px 0 rgba(255, 253, 248, 0.35),
              inset 0 -3px 0 rgba(0, 0, 0, 0.35),
              inset 1.5px 0 0 rgba(0, 0, 0, 0.20),
              inset -1.5px 0 0 rgba(0, 0, 0, 0.20);
}

.coverflow-page-front.coverflow-front-cover {
  /* Mismo criterio que la contraportada de arriba: solo la textura, y
   * `background-origin: border-box` para que llegue al anillo del borde. */
  background-origin: border-box;
  background-image: var(--ui-texture-pad-covers, url('../resources/ui-textures/pad-covers.webp'));
  background-size: cover;
  background-repeat: no-repeat;
  background-position: center;
  box-shadow: inset 0 1px 0 rgba(255, 253, 248, 0.35),
              inset 0 -3px 0 rgba(0, 0, 0, 0.35),
              inset 1.5px 0 0 rgba(0, 0, 0, 0.20),
              inset -1.5px 0 0 rgba(0, 0, 0, 0.20);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 12% 14%;
  box-sizing: border-box;
}
.coverflow-portada-title {
  font-family: 'Cherry Swash', cursive;
  font-weight: 700;
  font-size: clamp(1.4rem, 7cqw, 3.5rem);
  line-height: 1.05;
  letter-spacing: 0.01em;
  text-align: center;
  color: #FFF6E5;
  text-shadow:
    0 1px 0 rgba(80, 50, 20, 0.55),
    0 2px 6px rgba(0, 0, 0, 0.45),
    0 0 18px rgba(255, 220, 170, 0.18);
  word-break: break-word;
  max-width: 100%;
  max-height: 100%;
  overflow: hidden;
  /* backface-visibility: hidden para que el texto NO */
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

.coverflow-empty-page {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  pointer-events: none;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  padding: 0.75rem;
}

.coverflow-empty-logo {
  /* §22.181 — El logo se renderiza como <div> con background-image */
  width: 60px;
  height: 60px;
  background-image: url('../img/robinpad-icon.svg');
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
  filter: grayscale(100%) brightness(1.6) opacity(0.4);
  flex-shrink: 0;
}

.coverflow-empty-label {
  font-family: 'Cherry Swash', cursive;
  font-weight: 700;
  font-size: clamp(0.7rem, 1.8cqw, 1rem);
  color: rgba(60, 50, 40, 0.4);
  letter-spacing: 0.02em;
}
/* El .coverflow-book es el contenedor con aspect ratio del pad */
.coverflow-book {
  container-type: inline-size;
}

.coverflow-page-front {
  clip-path: url(#pageHolesFront);
  -webkit-clip-path: url(#pageHolesFront);
}
.coverflow-page-back {
  clip-path: url(#pageHolesBack);
  -webkit-clip-path: url(#pageHolesBack);
}

.coverflow-page-front {
  transform: translateZ(0.001px);
}

.preview-rings-layer {
  position: absolute;
  /* Cubre todo el book en altura para que los `top: X%` se calculen */
  inset: 0;
  z-index: 10;
  pointer-events: none;
  transform-style: preserve-3d;
  transform: translateZ(60px);
}

/* Anilla individual — barra horizontal (12% × 2.5px). Cada "anilla doble" */
.preview-ring {
  position: absolute;
  width: 12%;
  height: 2.5px;
  left: -6%;
  border-radius: 1.5px;
  box-sizing: border-box;
  background: linear-gradient(90deg,
    #926A1A 0%,
    #D6AC3D 27.96%,
    #FFE9AE 45.5%,
    #D6AC3D 62.87%,
    #926A1A 100%);
  box-shadow:
    inset 0 0.5px 0.8px rgba(0, 0, 0, 0.45),
    inset 0 -0.3px 0.6px rgba(255, 240, 200, 0.25),
    0 0 1.2px rgba(0, 0, 0, 0.4);
}

/* El anverso hereda el transform del padre (rotateY(0)). No se rota. */

.coverflow-page img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  user-select: none;
  -webkit-user-drag: none;
  display: block;
}

.coverflow-washi-overlay {
  position: absolute !important;
  inset: 0 !important;
  width: 100% !important;
  height: 100% !important;
  object-fit: cover !important;
  object-position: center !important;
  pointer-events: none !important;
  user-select: none !important;
  -webkit-user-drag: none !important;
  /* §22.254 — washi-overlay DEBAJO del thumbnail para que la */
  z-index: -1 !important;
  display: block !important;
}
/* Prefijo "p." para páginas numeradas (no "Untitled"). CSS puro */

.coverflow-nav {
  position: absolute;
  bottom: 28px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 0.5rem;
  z-index: 2;
}

.coverflow-nav-btn {
  width: 44px;
  height: 44px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}



/* === Reorder overlay === */

.reorder-overlay {
  position: fixed;
  inset: 0;
  z-index: 109;  /* debajo del coverflow (110) por si se solapan */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /* El background lo aplica el x-bind:style inline (workspaceStyle). */
  padding: 80px 40px 40px;
  box-sizing: border-box;
  overflow: hidden;
}

.reorder-close-btn {
  position: absolute;
  top: 16px;
  right: 16px;
  z-index: 2;
}

.reorder-title-pill {
  position: absolute;
  top: 16px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 0.4rem 1rem;
  background-color: rgba(255, 255, 255, 0.85);
  border: 1px solid rgba(92, 64, 51, 0.25);
  border-radius: 0.65rem;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.10);
  white-space: nowrap;
}
.reorder-title-label {
  font-family: "Cherry Swash", cursive;
  font-weight: 700;
  font-size: 0.95rem;
  line-height: 1.1;
  color: rgba(92, 64, 51, 0.92);
  /* §22.6xx.outline-title — outline `#F4D58D` (4 lados) para coherencia
     con `.floating-panel-title` (cabecera de dialogs/windows). El
     `text-shadow: 0 1px 0 rgba(255,255,255,0.6)` original (subtle white
     highlight) se reemplaza por el outline completo de 4 lados. */
  text-shadow:
    -1px -1px 0 #F4D58D,
     1px -1px 0 #F4D58D,
    -1px  1px 0 #F4D58D,
     1px  1px 0 #F4D58D;
}
.reorder-title-hint {
  font-family: "Cherry Swash", cursive;
  font-weight: 400;
  font-size: 0.7rem;
  line-height: 1;
  color: rgba(92, 64, 51, 0.6);
  font-style: italic;
}

/* §22.6xx.383 — Grid container: MÁS GRANDE (1300px max), gap 20px. */
.reorder-container {
  --reorder-cols: 5;
  --reorder-rows: 3;  /* 3 filas = los 15 huecos de siempre */
  --reorder-gap: 20px;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
/* §22.6xx.658dr.220 — Fila de ALTURA FIJA: la que tendría con 15 páginas.
   Antes era `1fr`, que reparte el alto del contenedor entre las filas que
   haya. Con 15 páginas (3 filas) daba el tamaño correcto, pero un pad de 6
   páginas (2 filas) estiraba cada módulo 1.5×: los `::before`/`::after` que
   dibujan el marco se separan y los módulos se ven descuadrados. Ahora el
   tamaño no depende de cuántas páginas tenga el cuaderno, y sobran huecos
   vacíos abajo —que es lo que se pidió. */
  grid-auto-rows: calc((100% - (var(--reorder-rows) - 1) * var(--reorder-gap)) / var(--reorder-rows));
  gap: var(--reorder-gap);
  max-width: min(1300px, 96vw);
  width: 100%;
  aspect-ratio: 5 / 3;  /* 5 cols × 3 rows para 15 huecos */
  max-height: 88vh;
}

.reorder-slot {
  position: relative;
  display: block;
  /* Padding = grosor del "wood frame" alrededor del content cream. */
  padding: 5px;
  background: transparent;
  border-radius: 16px;
  /* Drop shadow exterior (la "isla" elevada sobre el workspace). */
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.25);
  transition:
    transform 160ms ease,
    opacity 160ms ease;
  cursor: grab;
  user-select: none;
  min-height: 0;
  position: relative;  /* necesario para que el position:absolute del content se ancle aquí */
  /* Isolation para stacking context local (pseudo-elements + children). */
  isolation: isolate;
}
.reorder-slot::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  background-color: #a08250;
  background-image: var(--ui-texture-interface, url('../resources/ui-textures/interface-texture.webp'));
  /* §22.6xx.interface-texture-rotate-vertical.v3 — Reorder slot horizontal
     (5×3 grid). Tamaño nativo 1100×300. */
  background-size: 1100px 300px;
  background-repeat: no-repeat;
  background-position: center;
  background-blend-mode: multiply;
  box-shadow: inset 0 3px 5px rgba(50, 25, 5, 0.6);
  border-radius: 16px;
  pointer-events: none;
}
.reorder-slot::after {
  content: '';
  position: absolute;
  inset: 0 0 10% 0;
  z-index: 1;
  background-color: #e7c89a;
  background-image: var(--ui-texture-interface, url('../resources/ui-textures/interface-texture.webp'));
  /* §22.6xx.interface-texture-rotate-vertical.v3 — Tamaño nativo 1100×300. */
  background-size: 1100px 300px;
  background-repeat: no-repeat;
  background-position: center;
  box-shadow: inset 0 -2px 4px rgba(0, 0, 0, 0.1);
  border-radius: 16px;
  pointer-events: none;
}
.reorder-slot:hover {
  /* §22.6xx.399 — Hover: NO cambiamos background (mantenemos la wood */
  filter: brightness(1.05);
}
.reorder-slot:active {
  cursor: grabbing;
}
.reorder-slot--chosen {
  /* Estado cuando el user clickea y empieza a arrastrar un slot. */
  box-shadow:
    inset 0 0 0 2px var(--brass, #c85a29),
    0 4px 10px rgba(0, 0, 0, 0.25);
}
.reorder-slot--dragging {
  /* Estado mientras el slot está siendo arrastrado. Opacidad */
  opacity: 0.65;
  transform: scale(1.02);
  cursor: grabbing;
  box-shadow:
    inset 0 0 0 2px var(--brass, #c85a29),
    0 4px 14px rgba(0, 0, 0, 0.35);
}
.reorder-slot--ghost {
  /* Estado del "placeholder" que aparece donde el slot va a caer */
  opacity: 0.4;
}
/* §22.6xx.399 — Slot de la pageActivoId: highlight brass ring + glow. */
.reorder-slot--active {
  box-shadow:
    inset 0 0 0 2px var(--brass, #c85a29),
    0 4px 16px rgba(200, 90, 41, 0.45);
}

/* §22.6xx.408 — Número del slot: BANDERA (flag) SVG en lugar de círculo. */
.reorder-slot-number {
  position: absolute;
  top: -7px;
  left: 20px;
  z-index: 4;  /* sobre el wood + content (que es z-2) */
  background-image: url('../resources/ui-icons/page-flag.svg');
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center top;
  width: 44px;
  height: 48px;
  color: #fff8e8;
  font-family: "Cherry Swash", cursive;
  font-size: 1rem;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  /* El número se renderiza EN LA MITAD SUPERIOR del flag (donde está */
  padding-bottom: 14px;  /* empuja el número hacia el centro del body */
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.3);  /* sutil depth al número */
  pointer-events: none;  /* el flag no intercepta clicks del slot */
  /* El número del slot SIEMPRE visible (no opacity 0). Es la identidad */
}

/* §22.6xx.412 — El flag (SVG background) NO se mueve. Solo el NÚMERO */
.reorder-slot-number > span {
  display: inline-block;
  transform: translateX(-3px);  /* §22.6xx.413 — 5px a la derecha del offset anterior (-8px) */
}


/* §22.6xx.384 + ... + §22.6xx.401 — Page content (cream carved well). */
.reorder-slot-content {
  position: absolute;
  inset: 5% 5% 15% 5%;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2;
  /* Cream gradient EXACTO del .navbar-status-pill-content. */
  background: linear-gradient(180deg, #ffffff 0%, #f4ebe1 100%);
  border-radius: 16px;
  /* 5 box-shadows carved 1:1 del navbar. */
  box-shadow:
    3px 3px 2px -1px rgba(255, 253, 253, 0.85),
    -2px -3px 4px 0px rgba(0, 0, 0, 0.28),
    inset 0 0 0 1px rgba(0, 0, 0, 0.06),
    inset 2px 3px 2px 2px rgba(0, 0, 0, 0.18),
    0 4px 10px rgba(0, 0, 0, 0.20);
  /* Padding generoso para que la page no toque el borde del well. */
  padding: 6px;
  box-sizing: border-box;
  min-height: 0;
  min-width: 0;
  overflow: hidden;
}

/* Thumbnail: object-fit contain para respetar el aspect sin crop. */
.reorder-slot-thumbnail {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
  pointer-events: none;  /* no interceptar drag */
  -webkit-user-drag: none;
  user-drag: none;
}

/* Empty placeholder (page sin thumbnailBlob). */
.reorder-slot-empty {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #fdfdfc;
}
.reorder-slot-empty-logo {
  width: 40%;
  height: 40%;
  /* Logo silhouette simple (mismo treatment que .coverflow-empty-logo). */
  background-color: rgba(0, 0, 0, 0.04);
  mask-image: url('img/robinpad-icon.svg');
  -webkit-mask-image: url('img/robinpad-icon.svg');
  mask-repeat: no-repeat;
  -webkit-mask-repeat: no-repeat;
  mask-position: center;
  -webkit-mask-position: center;
  mask-size: contain;
  -webkit-mask-size: contain;
}

/* §22.6xx.658dr.45 — Botón "ver esta página". Va dentro del cream well
   (.reorder-slot-content), en su esquina inferior derecha, sobre el
   thumbnail. Reutiliza btn-wood btn-square btn-xs (mismo patrón que el
   .reorder-close-btn de este mismo overlay).
   OJO con la especificidad: `.btn-wood` (chrome.css:4608) declara
   `position: relative` y `display: inline-flex`, y está MÁS ABAJO en el
   cascado que esta regla. Con el selector de una sola clase, ganaba
   btn-wood por orden de fuente y el botón se quedaba en el flujo como
   flex item (a la derecha del thumbnail, centrado verticalmente) en vez
   de anclarse a la esquina. El descendant selector (0,2,0) gana al
   (0,1,0) de btn-wood sin depender del orden. */
.reorder-slot-content > .reorder-slot-btn {
  position: absolute;
  right: 8px;
  bottom: 8px;
  z-index: 5;
  width: 1.6rem;
  min-width: 1.6rem;
  height: 1.6rem;
  min-height: 1.6rem;
  cursor: pointer;
  pointer-events: auto;
}

/* En la página ya activa el botón no tiene nada a lo que ir: se atenúa. */
.reorder-slot--active .reorder-slot-btn {
  opacity: 0.4;
}

/* Responsive: en pantallas estrechas, menos columnas. */
@media (max-width: 900px) {
  .reorder-container {
    grid-template-columns: repeat(3, 1fr);
/* §22.6xx.658dr.220 — 3 cols × 5 filas = 15 huecos. La fila se sigue
       midiendo contra 5, no contra las que haya. */
    --reorder-rows: 5;
    aspect-ratio: 3 / 5;
    max-width: 92vw;
  }
  .reorder-overlay {
    padding: 80px 16px 16px;
  }
}
@media (max-width: 600px) {
  .reorder-container {
    grid-template-columns: repeat(2, 1fr);
    --reorder-rows: 8;
    aspect-ratio: 2 / 8;  /* 2 cols × ~7.5 rows (15 items) */
  }
}


.coverflow-paper-texture {
  position: absolute;
  inset: 0;
  /* §22.6xx.658v — el JS del tool paper-texture sobreescribe
     background-size inline con cover × paperTextureScale para
     coincidir con el workspace (consistencia con §22.6xx.656az). */
  background-size: 1500px 1500px;
  background-position: center;
  /* §22.6xx.658v — repeat por defecto (a scale=1 el repeat es
     invisible porque cover = exacto). A escalas <1 tilea sin
     dejar huecos. */
  background-repeat: repeat;
  /* §22.6xx.506i — mix-blend-mode SOLO en desktop. En touch mode
   * (tablets) los mix-blend-mode son la causa #1 de parpadeos
   * durante animaciones 3D — el browser recompone los layers
   * continuamente, generando flickering visible. En touch mode
   * usamos opacity simple (mismo efecto visual, sin coste GPU). */
  mix-blend-mode: multiply;
  opacity: 0.85;
  isolation: isolate;
  pointer-events: none;
}

/* §22.6xx.658cs — Paper texture per-page del preview flipbook.
   Equivalente per-page del .coverflow-paper-texture (que era global).
   Cada leaf del flipbook tiene su propio data URL (calculado en
   _renderTextureOverlayForPage) que se aplica como <img>. El img se
   ve igual que el div con background-image del workspace: cover × scale,
   mix-blend-mode multiply, opacity 0.85. La clase es distinta
   (.coverflow-page-texture) para que _updateOverlaySize del tool
   paper-texture NO la toque — solo afecta .coverflow-paper-texture. */
.coverflow-page-texture {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* §22.6xx.506i — mix-blend-mode SOLO en desktop. Ver comentario
     en .coverflow-paper-texture sobre el flickering en touch mode. */
  mix-blend-mode: multiply;
  opacity: 0.85;
  isolation: isolate;
  pointer-events: none;
}

.coverflow-noise-filter {
  position: absolute;
  inset: 0;
  background-repeat: repeat;
  background-position: center;
  mix-blend-mode: overlay;
  isolation: isolate;
  pointer-events: none;
  /* El opacity se setea inline desde getNoiseFilterOverlayStyle(). */
}/* §22.6xx.357 — check badge ELIMINADO. Era redundante con el border */
/* Section heading "Choose what to export" en Cherry Swash brass */

/* === Export dialog (legacy refs) === */

/* §22.6xx.658dr.276 — Título de sección canónico de TODO el workspace.
   Antes cada panel y dialogo llevaba el estilo pegado en línea y había cuatro
   colores distintos: `--brass` coral claro (64 casos), `--brass-text` (2),
   `rgba(92,51,23,.85)` translúcido (2) y un rojo suelto `#b32d1f` en el Reset
   de Ajustes. Aquí hay un solo estilo: el de "Qué exportar" / "Cuántas", que
   es el que ya usaba `.export-tab-section-title`. Se unifica el COLOR, que es
   lo que se veía desparejo; el tamaño se mantiene en dos niveles para no
   aplanar la jerarquía dentro de los paneles compactos. */
.rp-section-title {
  font-family: 'Cherry Swash', cursive;
  color: var(--brass-text, #93411c);
  font-size: 1.2rem;
  font-weight: 700;
  margin: 0;
  line-height: 1.1;
  letter-spacing: 0.005em;
}

/* Subsección: mismo color y familia, un punto menor porque va dentro de un
   panel compacto y no debe competir con el título de arriba. */
.rp-section-title--sm {
  font-size: 0.95rem;
}

/* Alias legacy: se mantiene por si algo lo referencia todavía. */
.export-tab-section-title {
  font-family: 'Cherry Swash', cursive;
  color: var(--brass-text, #93411c);
  font-size: 1.2rem;
  font-weight: 700;
  margin: 0;
  line-height: 1.1;
  letter-spacing: 0.005em;
}

.export-quality-message {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.74rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--sepia, #5c3317);
  opacity: 0.7;
  line-height: 1.4;
  text-align: center;
  padding: 0.5rem 0.4rem 0.1rem;
  white-space: normal;
  min-height: 2.4rem;
  transition: opacity 180ms ease-out;
}

.dialog-info-text {
  font-size: 0.8125rem; /* 13px */
  line-height: 1.5;
  color: var(--sepia, #5c3317);
  opacity: 0.82;
  font-weight: 500;
}.export-loader-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  z-index: 5;
  pointer-events: auto;
}

/* §22.6xx.first-boot-defaults — El card del loader hereda el estilo
   hand-drawn del welcome dialog (mismo lenguaje visual que el resto de
   dialogs): ::before con filter url(#thick-torn-edge) + paper-noise-bg
   para textura de papel sutil. El border-radius se mantiene pero el
   ::before lo sobreescribe visualmente con el trazo hand-drawn. */
.export-loader-card {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.95rem;
  padding: 2rem 3rem;
  background: var(--panel-cream, #FCF7EE);
  border: 1px solid rgba(92, 64, 51, 0.22);
  border-radius: 1.25rem;
  box-shadow: 0 16px 48px rgba(0, 0, 0, 0.55), 0 2px 6px rgba(0, 0, 0, 0.30);
  min-width: 340px;
  /* Capa sutil de ruido de papel para coherencia con dialogs/popovers */
  background-image:
    var(--paper-noise, url('../resources/ui-textures/paper-noise.png')),
    linear-gradient(var(--panel-cream, #FCF7EE), var(--panel-cream, #FCF7EE));
  background-blend-mode: multiply;
  background-size: 220px 220px, cover;
}

/* Hand-drawn border via filter SVG (mismo patrón que .dialog-panel). */
body .export-loader-card::before {
  content: "";
  position: absolute;
  inset: 0;
  border: 3px solid var(--ink-stroke, #c5a059);
  border-radius: inherit;
  filter: url(#thick-torn-edge);
  pointer-events: none;
}

.export-loader-text {
  font-family: 'Cherry Swash', cursive;
  font-size: 1.25rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  color: var(--sepia, #5c3317);
  margin: 0;
  text-align: center;
  white-space: pre-line;
  line-height: 1.25;
}

.export-loader-subtext {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.78rem;
  color: rgba(92, 64, 51, 0.65);
  margin: 0;
  text-align: center;
  letter-spacing: 0.02em;
}

/* §22.6xx.658bo — Input range nativo (hereda TODO el estilo hand-drawn
   del workspace: track gradiente brass-to-sepia, thumb con textura
   panel-birch + box-shadow 3D). Solo override de width. */
.export-loader-progress {
  width: 75%;
  margin-top: 0.4rem;
  pointer-events: none;
}

/* §22.6xx.658bo — Roberto pidió solo la línea de progreso, sin el círculo
   thumb. Mantenemos el track gradiente brass↔sepia (heredado del global)
   y ocultamos el thumb en ambos engines. */
.export-loader-progress::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  display: none;
}
.export-loader-progress::-moz-range-thumb {
  display: none;
}

/* §22.6xx.658bo — Modo indeterminate: anima --track-value de 0 a 100%
   para dar sensación de progreso sin valor real. Single-page export. */
.export-loader-progress.is-indeterminate {
  animation: export-loader-indeterminate 1.6s ease-in-out infinite;
}

@keyframes export-loader-indeterminate {
  0%   { --track-value: 0%; }
  50%  { --track-value: 100%; }
  100% { --track-value: 0%; }
}.export-dialog-preview-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6rem;
  width: 100%;
}

.export-dialog-preview-canvas {
  max-width: 100%;
  max-height: 540px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.10);
  /* §22.500 — Sin border-radius: el preview representa la imagen que */
  border-radius: 0;
  display: block;
  image-rendering: -webkit-optimize-contrast;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.30);
}
.export-thumb-tile {
  display: flex;
  flex-direction: column;
  cursor: pointer;
  border-radius: 0.5rem;
  padding: 0.35rem;
  background: rgba(252, 247, 238, 0.55);
  border: 1px solid transparent;
  transition: border-color 140ms ease, background 140ms ease, transform 100ms ease;
}
.export-thumb-tile:hover {
  background: rgba(252, 247, 238, 0.85);
  border-color: rgba(200, 90, 41, 0.28);
}
.export-thumb-tile:active {
  transform: translateY(1px);
}
.export-thumb-tile.is-active {
  background: rgba(200, 90, 41, 0.10);
  border-color: var(--brass, #c85a29);
  box-shadow: 0 0 0 1px var(--brass, #c85a29);
}

.export-thumb-wrap {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  background: rgba(255, 255, 255, 0.65);
  border-radius: 0.4rem;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid rgba(92, 64, 51, 0.10);
}

.export-thumb-placeholder {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: rgba(92, 51, 23, 0.4);
  background: rgba(252, 247, 238, 0.6);
}

/* §22.6xx.415 — Logo de Robinpad para thumbnails vacíos en el export. */
.export-thumb-robinpad-logo {
  background-color: rgba(252, 247, 238, 0.92);  /* cream tint — cubre el wrap */
  background-image: url('../img/robinpad-icon.svg');
  background-size: 50% 50%;
  background-repeat: no-repeat;
  background-position: center center;
  filter: sepia(0.4) saturate(0.6) brightness(0.85);
  opacity: 0.85;
}


/* === Welcome dialog === */

/* §22.6xx.658-iter7 — Estilo "tile" para los support blocks (Patreon, Print Stores,
   Digital Store). Cada bloque es un papelito con borde hand-drawn que se asienta
   sobre el fondo cream del dialog (que ya tiene el filtro torn-paper del panel).
   Mismo lenguaje visual que .layer-row (border 2px sepia + hand-drawn-filter +
   paper-noise + cream): papelitos distintos dentro de un papel mayor. */
.support-link-block {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.85rem;
  padding: 0.95rem 1.1rem;
  background: transparent !important;
  border: none !important;  /* el border lo pinta el ::after con filtro hand-drawn */
  border-radius: 1rem;
  cursor: pointer;
  text-decoration: none;
  color: inherit;
  transition:
    background 180ms cubic-bezier(0.2, 0, 0, 1),
    transform 140ms ease;
  user-select: none;
  outline: none;
  overflow: hidden;
  isolation: isolate;
}
/* §22.6xx.658-iter7 — ::before pone el cream + paper-noise como capa base.
   Se ve a través del padding del block (que ahora es transparente) para que
   el tile tenga textura papel como el resto del UI, sin tapar el contenido. */
.support-link-block::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-color: var(--panel-cream, #f7e6c0) !important;
  background-image: var(--ui-texture-paper-noise) !important;
  background-repeat: repeat !important;
  background-size: 240px 240px !important;
  background-blend-mode: normal !important;
  border-radius: inherit;
  pointer-events: none;
}
/* §22.6xx.658-iter7 — ::after dibuja el borde hand-drawn encima del paper.
   hand-drawn-filter (scale=2.5) ondula los 2px del border de forma sutil
   sin destruir el border-radius del tile. */
.support-link-block::after {
  content: "";
  position: absolute;
  inset: 0;
  box-sizing: border-box;
  border: 2px solid var(--ink-stroke, #c5a059);
  border-radius: inherit;
  filter: url(#hand-drawn-filter);
  pointer-events: none;
  transition: border-color 180ms cubic-bezier(0.2, 0, 0, 1);
}

.support-link-block:hover {
  transform: translateX(2px);
}
.support-link-block:hover::after {
  border-color: rgba(200, 90, 41, 0.75);  /* brass hover */
}

.support-link-block:focus-visible {
  box-shadow: 0 0 0 2px rgba(200, 90, 41, 0.32);
}

.support-link-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 0.65rem;
  background: rgba(217, 119, 87, 0.14);
  color: var(--robin, #D97757);
  font-size: 1.4rem;
  line-height: 1;
  flex-shrink: 0;
}

.support-link-text {
  flex: 1;
  min-width: 0;
}

.support-link-title {
  font-family: 'Cherry Swash', cursive;
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--sepia, #5c3317);
  margin: 0;
  line-height: 1.2;
}

.support-link-description {
  font-size: 0.78rem;
  line-height: 1.45;
  color: var(--sepia, #5c3317);
  opacity: 0.72;
  margin: 0.25rem 0 0 0;
}

.support-link-arrow {
  color: var(--robin, #D97757);
  font-size: 1.05rem;
  flex-shrink: 0;
  opacity: 0.55;
  transition: opacity 140ms ease, transform 140ms ease;
}

.support-link-block:hover .support-link-arrow {
  opacity: 1;
  transform: translate(2px, -2px);
}


.text-primary {
  color: var(--brass-text, #93411c) !important;
}

.border-primary {
  border-color: var(--brass, #c85a29) !important;
}

.bg-primary {
  background-color: var(--brass, #c85a29) !important;
}
/* Variantes con alpha sufijo (/10, /20, etc.) — el sufijo después del */
.bg-primary\/10 {
  background-color: rgba(200, 90, 41, 0.10) !important;
}

.bg-primary\/15 {
  background-color: color-mix(in srgb, var(--brass) 15%, transparent) !important;
}

.bg-primary\/20 {
  background-color: color-mix(in srgb, var(--brass) 20%, transparent) !important;
}

.bg-primary\/40 {
  background-color: color-mix(in srgb, var(--brass) 40%, transparent) !important;
}
.dialog-panel .text-base-content {
  color: rgba(255, 255, 255, 0.96);
}

.dialog-panel .text-base-content\/65 {
  color: rgba(255, 255, 255, 0.72);
}

/* descripciones de backup */
.dialog-panel .text-base-content\/55 {
  color: rgba(255, 255, 255, 0.55);
}

/* labels uppercase muy secundarios */
.dialog-panel .text-base-content\/50 {
  color: rgba(255, 255, 255, 0.55);
}

/* PSD Exports footer / dragOver */
.dialog-panel .text-base-content\/40 {
  color: rgba(255, 255, 255, 0.40);
}

/* iconos / labels inactivos */
.dialog-panel .text-base-content\/35 {
  color: rgba(255, 255, 255, 0.35);
}

/* hover/inactivo */
.dialog-panel .text-base-content\/30 {
  color: rgba(255, 255, 255, 0.30);
}

.dialog-panel .text-base-content\/20 {
  color: rgba(255, 255, 255, 0.20);
}

.dialog-panel .text-base-content\/10 {
  color: rgba(255, 255, 255, 0.10);
}


.settings-rows>*+*:not(.settings-row-runa) {
  border-top: 1px solid rgba(255, 255, 255, 0.07);
}

/* Contenedor del tab derecho. Override del overflow del scroll para */
.settings-tab-pane {
  padding: 1.5rem 1.75rem;
}

.settings-tab-pane {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}/* §22.216 — 4 runas en las esquinas con halo CIRCULAR del color */
.settings-row-runa {
  position: absolute;
  width: 22px;
  height: 22px;
  font-family: 'Cherry Swash', 'Times New Roman', serif;
  /* §22.216 — font-size 14px (antes 18px) para que la estrella */
  font-size: 14px;
  line-height: 1;
  color: var(--brass-text, #93411c);
  background: #FCF7EE;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  z-index: 1;
  opacity: 1;
}
/* §22.216 — Offsets -8px para que la runa esté centrada en el */
.settings-row-runa.tl { top: -8px;    left: -8px; }
.settings-row-runa.tr { top: -8px;    right: -8px; }
.settings-row-runa.bl { bottom: -8px; left: -8px; }
.settings-row-runa.br { bottom: -8px; right: -8px; }.settings-interface-texture-thumb {
  border-radius: 0.25rem;
  background-color: rgba(255, 255, 255, 0.06);
  background-position: center;
  background-repeat: no-repeat;
  position: relative;
  max-width: 100%;
  max-height: 100%;
}
.settings-interface-texture-thumb[data-theme-texture-aspect="wide"] {
  /* interface texture: franja horizontal 1100×300 → aspect 11:3 */
  aspect-ratio: 11 / 3;
  width: 100%;
  background-size: contain;
}
.settings-interface-texture-thumb[data-theme-texture-aspect="square"] {
  /* pad-cover 1500×1500 → 1:1 */
  aspect-ratio: 1 / 1;
  width: 100%;
  height: 100%;
  background-size: contain;
}/* §22.6xx.249 — Titles color row: layout horizontal con radios a la */
.settings-titles-color-preview {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0.25rem;
  border-radius: 0.5rem;
  background: rgba(0, 0, 0, 0.06);
  border: 1px solid rgba(0, 0, 0, 0.1);
}
.settings-titles-color-preview-bar {
  width: 100%;
  height: 40px;
  border-radius: 0.4rem;
  display: flex;
  align-items: center;
  justify-content: center;
  /* §22.6xx.interface-texture-rotate-vertical.v3 — Preview horizontal.
     Tamaño nativo 1100×300. */
  background-size: 1100px 300px;
  background-position: center;
  background-repeat: no-repeat;
  background-color: rgba(120, 80, 40, 0.6);
  position: relative;
  overflow: hidden;
}
.settings-titles-color-preview-bar::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(0,0,0,0.10) 0%, rgba(0,0,0,0) 35%, rgba(0,0,0,0) 70%, rgba(0,0,0,0.10) 100%);
  pointer-events: none;
}
.settings-titles-color-preview-text {
  position: relative;
  z-index: 1;
  font-family: 'Cherry Swash Q Fix', 'Cherry Swash', cursive;
  font-size: 1.1rem;
  font-weight: 700;
  /* El color se aplica via JS (applyHeaderTextColor testea ambos */
  color: #4a341c;
  /* §22.6xx.outline-title.fix2 — outline `#F4D58D` (4 lados) para coherencia
     con `.floating-panel-title` (modo `.desk-light` = texto oscuro). El
     `text-shadow: 0 1px 2px rgba(255,255,255,0.4)` original (subtle white
     highlight) se reemplaza por el outline completo. Roberto pidió
     explícitamente que la regla del contorno se aplique también a este
     preview del theme editor. */
  text-shadow:
    -1px -1px 0 #F4D58D,
     1px -1px 0 #F4D58D,
    -1px  1px 0 #F4D58D,
     1px  1px 0 #F4D58D;
}
.settings-titles-color-preview-text.is-light {
  color: #f1c575;
  /* §22.6xx.outline-title.fix2 — outline `var(--sepia)` (4 lados) para
     coherencia con `.floating-panel-header--light-title` (texto claro
     sobre fondo oscuro). El `text-shadow: 0 1px 3px rgba(0,0,0,0.5)`
     original (subtle dark shadow) se reemplaza por el outline completo. */
  text-shadow:
    -1px -1px 0 var(--sepia),
     1px -1px 0 var(--sepia),
    -1px  1px 0 var(--sepia),
     1px  1px 0 var(--sepia);
}/* §22.6xx.658dr.74 — La fila de washi lleva su botón a la esquina DERECHA
   (la etiqueta ocupa la izquierda). Antes esta regla apuntaba a
   `> .btn-wood-square`, una clase que no existe en ningún CSS, así que no
   aplicaba nunca y el botón se posicionaba solo con estilos en línea.
   La esquina base (izquierda) la pone `.theme-custom-delete` en dialogs.css. */
.settings-washi-tape-row { position: relative; }
.settings-washi-tape-row > .theme-custom-delete {
  top: 4px;
  right: 4px;
  left: auto;
}.settings-row-hint.mono {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}.settings-grid-tile .settings-grid-tile-check,
.settings-grid-tile.is-selected .settings-grid-tile-check {
  display: none !important;
}.cursor-tile-img {
  object-fit: contain !important;
  padding: 0.5rem;
  image-rendering: -webkit-optimize-contrast;
}

/* §22.6xx.438 — Tile "None" del cursor: usa un <span> con icono ti-ban */

/* === Cursor (custom cursors) === */

.cursor-tile-none-bg {
  display: flex !important;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.35);
}.settings-grid-tile--compact .settings-grid-tile-label {
  display: none;
}
/* Tab lateral izquierdo: nav items */
.settings-tab-btn {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.55rem 0.75rem;
  border-radius: 0.75rem;
  font-size: 0.86rem;
  font-weight: 700;  /* §22.6xx.555zz3 — Roberto: "el menú de settings debe tener el mismo estilo de letra que el del menú desplegable de tools, en cuanto a que debe ser también 700". Mismo peso que .tools-menu-item (§22.6xx.555zz2). */
  color: rgba(255, 255, 255, 0.65);
  background: transparent;
  border: none;
  cursor: pointer;
  text-align: left;
  transition: background 140ms ease, color 140ms ease;
}

.settings-tab-btn:hover {
  background: rgba(255, 255, 255, 0.04);
  color: rgba(255, 255, 255, 0.92);
}

.settings-tab-btn.is-active {
  background: rgba(200, 90, 41, 0.18);
  color: rgba(255, 255, 255, 0.98);
}

.settings-tab-btn i {
  font-size: 1rem;
  width: 1.2rem;
  text-align: center;
  flex-shrink: 0;
}


@keyframes settings-row-listen {

  0%,
  100% {
    box-shadow: 0 0 0 0 rgba(251, 191, 36, 0.0);
  }

  50% {
    box-shadow: 0 0 0 6px rgba(251, 191, 36, 0.18);
  }
}

.settings-row input.input:focus {
  outline: 2px solid color-mix(in srgb, var(--brass) 35%, transparent);
  outline-offset: 1px;
}

.settings-row input.input {
  font-feature-settings: "tnum" 1;
}

/* ════════════════════════════════════════════════════════════════════ */



/* === C. Botones físicos (CONTINUACIÓN — see also L169) === */

/* === C. Botones físicos =========================================== */
/* §22.6xx.658dk — Sombra de los botones de madera: UNA definición, 3 capas.
 *
 * Antes eran 6 capas repetidas literalmente en 4 sitios (.btn-wood,
 * :focus-visible, .btn-wood-round y .btn-wood-round.is-selected). Ahora hay
 * una sola variable que los 4 usan, así que no pueden divergir.
 *
 * Lo que se quitó y por qué (Roberto, 7-oct-2026):
 *   - `inset ±1.5px 0 0` (canto izquierdo y derecho): simulaban las paredes
 *     del bloque. Con border-radius 12px no se perciben.
 *   - `inset 0 1px 0 rgba(255,253,248,0.35)` (brillo superior): se probó a
 *     quitar también y se pierde el filo de arriba. Se puede recuperar
 *     añadiendo esta línea al principio de --btn-wood-shadow.
 *
 * Lo que se queda:
 *   - el hundido inferior — es la que da el volumen al bloque;
 *   - la extrusión de 4px — sin ella deja de parecer un objeto físico;
 *   - la sombra difusa — lo despega del fondo.
 *
 * NINGUNA de las dos sombras es negro puro: se derivan de `--btn-bg`, el color
 * base del botón. Negro sobre madera se veía sucio; un tono apenas más oscuro
 * que la base da el mismo volumen. Y como `--btn-bg` lo redefine cada variante
 * (`.btn-wood-danger`), las sombras la siguen solas.
 * `color-mix` es lo que ya usa el scrollbar (§22.6xx.658dr.132).
 */
.btn-wood,
.btn-wood-round {
  /* NINGUNA sombra es negro puro (Roberto, 7-oct-2026). Se usan los tokens
     que el proyecto ya tenía para el escritorio, que son sepia cálido:
       --desk-shadow-deep  rgba(60, 30, 10, 0.45)  → el hundido inferior
       --btn-bg-raised     #5B3015                 → la extrusión
       --desk-shadow       rgba(80, 40, 15, 0.25)  → la sombra difusa
     Negro sobre madera se veía sucio; un tono apenas más oscuro que la base
     da el mismo volumen. Y como `--btn-bg-raised` lo redefine cada variante
     (`.btn-wood-danger`), la extrusión la sigue sola. */
  --btn-wood-shadow:
    inset 0 -3px 0 var(--desk-shadow-deep, rgba(60, 30, 10, 0.45)),
    0 4px 0 var(--btn-bg-raised, #5B3015),
    0 6px 14px var(--desk-shadow, rgba(80, 40, 15, 0.25));
}

/* .btn-wood: bloque de madera natural con texto sepia. */
.btn-wood {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  padding: 0.5rem 0.9rem;
  border-radius: 12px;
  background-color: var(--btn-bg, #5C3317);
  background-image:
    linear-gradient(180deg, rgba(255, 255, 255, 0.12), rgba(0, 0, 0, 0) 55%),
    var(--ui-texture-panel, url('../resources/ui-textures/panel-birch.webp'));
  background-size: cover, 240px 240px;
  background-blend-mode: normal, soft-light;
  color: var(--btn-text-color, #F4D58D);  /* §22.6xx.658-iter26: auto-contraste por luminancia */
  font-weight: 600;
  font-size: 0.78rem;
  cursor: pointer;
  user-select: none;
  border: none;
  box-shadow: var(--btn-wood-shadow);
  transition: transform 90ms ease, box-shadow 90ms ease, background-color 140ms ease;
}

.btn-wood:hover {
  background-color: var(--btn-bg-hover, #6B3E20);
}

.btn-wood:focus-visible {
  outline: none;
  box-shadow: var(--btn-wood-shadow), 0 0 0 2px var(--brass-light);
}

/* §22.6xx.656ag — Estado "selected" para los toggles del scene dialog
   (aspect ratio 16:9/1:1/4:5/Libre, format PNG/JPG/WebP, resolution 1x/2x/4x).
   Color brass más oscuro + un border brass para que se vea "pressed/active".
   Se usa junto con x-bind:class en los <button class="btn-wood ...">. */
.btn-wood.is-selected {
  background-color: var(--brass-dark);
  /* §22.6xx.658-iter26 — is-selected usa brass-dark (oscuro) como bg,
     por lo tanto el texto debe ser claro siempre, independiente del
     color del theme elegido. Forzamos el color explícitamente. */
  color: #F4D58D;
  /* §22.6xx.656bb — Estado "pressed" persistente: el botón se hunde
     4px (translateY 4px) y se QUITA la raised shadow (raised=0) para
     que se vea "embebido" en la superficie, no elevado. Mismo lenguaje
     visual que el `:active` pressed momentáneo (chrome.css:4416) pero
     persistente. Combina con el border brass como identifier del
     estado activo. La transición de 90ms del .btn-wood base anima
     el movimiento suavemente al togglear. */
  transform: translateY(4px);
  /* §22.6xx.656bc — Sin inset de "hendidura oscura" (inset 0 2px 4px
     rgba(0,0,0,0.40)) que simularía sombra interior de botón físicamente
     presionado. Roberto pidió quitarla: el is-selected debe verse
     "limpio" por dentro, sin sensación de ahuecamiento. Solo se mantiene
     el highlight superior sutil (inset 0 1px 0 ...). */
  box-shadow:
    inset 0 1px 0 rgba(255, 253, 248, 0.15),
    0 1px 2px rgba(0, 0, 0, 0.30);
}

/* === §22.6xx.656ah — Scene dialog: iconos visuales de aspect ratio + texto overlay.
   Cada aspect button tiene un <span class="aspect-icon"> con un
   width/height diferente que representa visualmente el ratio (16:9 →
   rect horizontal, 1:1 → cuadrado, 4:5 → rect vertical). El user reconoce
   el ratio INMEDIATAMENTE sin leer el label. Patrón "visual > text" de
   ui-ux-pro-max. */
.aspect-icon {
  display: inline-block;
  background: currentColor;
  border-radius: 1px;
  vertical-align: middle;
}
.aspect-icon-wide { width: 14px; height: 8px; }   /* 16:9 */
.aspect-icon-square { width: 10px; height: 10px; } /* 1:1 */
.aspect-icon-tall { width: 8px; height: 10px; }    /* 4:5 */

/* === §22.6xx.656ah — Scene dialog: texto overlay (sobre el cropper).
   Cursor: grab por defecto, grabbing durante drag. Cuando está seleccionado,
   muestra un border brass + 4 corner handles tipo Photoshop/Snapseed. */
/* §22.6xx.658dw — Vista previa del logo de Robinpad dentro del crop.
 *
 * El SVG del logo es coral, así que con `brightness(0) invert(1)` se
 * fuerza a blanco igual que en el estampado real del export (§658dw):
 * así el preview y lo exportado se ven IGUALES, que es justo para lo que
 * sirve un preview. `pointer-events: none` para que no robe el drag del
 * cropBox al usuario. */
.scene-logo-preview {
  position: absolute;
  pointer-events: none;
  user-select: none;
  z-index: 2;
  filter: brightness(0) invert(1) drop-shadow(0 1px 2px rgba(0, 0, 0, 0.45));
  opacity: 0.85;
  transition: left 90ms ease, top 90ms ease, width 90ms ease;
}
.scene-text-overlay {
  cursor: grab;
  border-radius: 4px;
  transition: outline 80ms ease;
}
.scene-text-overlay:active,
.scene-text-overlay.is-dragging {
  cursor: grabbing;
}
.scene-text-overlay.is-selected {
  outline: 2px solid var(--brass, #c85a29);
  outline-offset: 2px;
  /* 4 corner handles via box-shadow (4 dots en las esquinas) */
  box-shadow:
    -3px -3px 0 0 var(--brass, #c85a29),
    3px -3px 0 0 var(--brass, #c85a29),
    -3px 3px 0 0 var(--brass, #c85a29),
    3px 3px 0 0 var(--brass, #c85a29);
  background: rgba(0, 0, 0, 0.12);
}

.btn-wood:active,
.btn-wood.active {
  transform: translateY(3px);
  box-shadow:
    inset 0 2px 4px rgba(0, 0, 0, 0.40),
    inset 0 1px 0 rgba(255, 253, 248, 0.15),
    0 1px 0 var(--btn-bg-raised, #3D2314),
    0 1px 2px rgba(0, 0, 0, 0.30);
}

/* §22.6xx.11 — Botón activo persistente (e.g. orientación de la espiral */
.btn-wood.is-active {
  outline: 2px solid var(--brass, #c85a29);
  outline-offset: 1px;
}

/* §22.6xx.658dj — Variantes de los botones de madera.
 *
 * Antes cada botón repetía sus modificadores: `btn-wood btn-square btn-xs`,
 * `btn-wood flex items-center gap-1 rounded-lg px-3`… 58 combinaciones
 * distintas para 134 botones, y `btn-xs` vivía en
 * `css/brush-creator-editor.css` — un fichero de otra cosa, cargado
 * globalmente, que fijaba el tamaño de los botones de toda la app.
 *
 * Estas tres variantes CONGELAN lo que el navegador calculaba antes. Los
 * valores no están copiados de memoria: se midieron con `getComputedStyle` en
 * las 14 pantallas, y el test `tests/btn-wood-variants.test.mjs` vuelve a
 * medirlos para que no puedan desviarse.
 *
 * ── OJO: los comentarios que siguen son el porqué de valores que parecen
 * arbitrarios. No "simplificarlos" sin volver a medir. */
.btn-wood-icon {
  /* = btn-square (3rem) + btn-xs. */
  min-height: 3rem;
  min-width: 3rem;
  /* `!important` como en btn-xs: hay reglas que lo ganaban por especificidad. */
  font-size: 0.75rem !important;
  padding: 0.3rem 0.6rem !important;
  /* NO se declara `display`: el botón hereda el `inline-flex` de .btn-wood y se
     convierte en `flex` cuando su padre es flex. Medido: 48×48 en la mayoría,
     `inline-flex` real en los que cuelgan de un padre en bloque. Declararlo
     aquí cambiaría 14 de ellos. */
}

.btn-wood-label {
  /* = flex + items-center + gap-1 + rounded-lg + px-3. */
  display: flex;              /* el `flex` explícito, NO el inline-flex de .btn-wood:
                                 medido, 33 de 34 botones de etiqueta cuelgan de un
                                 padre en BLOQUE, donde flex ≠ inline-flex. */
  align-items: center;
  gap: 0.25rem;               /* gap-1 */
  border-radius: 0.3rem;      /* rounded-lg — 0.3rem, no los 8px que sugiere el nombre */
  padding-left: 0.75rem;      /* px-3 */
  padding-right: 0.75rem;
}

.btn-wood-label-sm {
  /* = btn-xs + flex + items-center + gap-1 + rounded-lg (sin px-3). */
  display: flex;
  align-items: center;
  gap: 0.25rem;
  border-radius: 0.3rem;
  font-size: 0.75rem !important;
  padding: 0.3rem 0.6rem !important;
}

.btn-wood-danger {
  background-color: #8B2C1A !important;   /* rojo teja oscuro */
  --btn-bg: #8B2C1A;
  --btn-bg-raised: #5A1D11;
  color: #F4D58D !important;               /* Light Academia (mismo que .btn-wood) */
}
.btn-wood-danger:hover {
  background-color: #A33623 !important;
  --btn-bg: #A33623;
}
.btn-wood-danger > i {
  color: #F4D58D !important;
}

/* selector de intervalo del auto-backup. Estilo similar a los chips  */
/* de color, sin textura de madera — fondo sepia/cream con borde.     */
/* El estado activo usa outline de brass. */
.backup-interval-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 3.5rem;
  padding: 0.25rem 0.6rem;
  border-radius: 999px;
  background: rgba(255, 248, 232, 0.6);
  border: 1px solid rgba(92, 64, 51, 0.20);
  color: var(--sepia, #5C4033);
  font-size: 0.72rem;
  font-weight: 600;
  cursor: pointer;
  user-select: none;
  transition: background-color 140ms ease, border-color 140ms ease, color 140ms ease;
}
.backup-interval-chip:hover {
  background: rgba(200, 90, 41, 0.10);
  border-color: rgba(200, 90, 41, 0.35);
}
.backup-interval-chip.is-active {
  background: rgba(200, 90, 41, 0.15);
  border-color: var(--brass, #c85a29);
  color: var(--brass-text, #93411c);
  outline: 2px solid var(--brass, #c85a29);
  outline-offset: 1px;
}

/* <details> DENTRO de theme-card se vea como un theme-row más, pero   */
/* con capacidad de colapsar/expandir. El <summary> se estiliza con */
/* la misma apariencia que un theme-row (icono + título + chevron).  */

/* === Theme row details === */

.theme-row-details {
  border-bottom: 1px solid rgba(92, 64, 51, 0.08);
  transition: background-color 0.2s ease;
}
.theme-row-details:last-child {
  border-bottom: none;
}
.theme-row-details:hover {
  background-color: rgba(255, 255, 255, 0.4);
}
.theme-row-details > summary {
  list-style: none;        /* quita el marker default (▶) */
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1.1rem 1.25rem;
  gap: 1rem;
  user-select: none;
}
.theme-row-details > summary::-webkit-details-marker {
  display: none;            /* Safari */
}
.theme-row-details > summary > .theme-row-content {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-width: 0;
  flex: 1;
}
.theme-row-details > summary > .theme-row-chevron {
  font-size: 1.1rem;
  color: var(--sepia, #5C4033);
  opacity: 0.6;
  flex-shrink: 0;
  transition: transform 0.2s ease;
}
.theme-row-details[open] > summary > .theme-row-chevron {
  transform: rotate(180deg);
  opacity: 1;
}
.theme-row-details > .theme-row-body {
  padding: 0.75rem 1.25rem 1.1rem 1.25rem;
}

#panel-layers .btn-wood:not(.floating-panel-actions .btn-wood) {
  width: 2rem;
  height: 2rem;
  min-width: 2rem;
  min-height: 2rem;
  padding: 0;
  gap: 0;
}
/* El grid de acciones globales: el `align-items: center` evita */
#panel-layers .grid-cols-6 {
  align-items: center;
  justify-items: center;
}

.btn-wood-round {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;                /* 44px */
  aspect-ratio: 1 / 1;
  border-radius: 50%;
  background-color: var(--btn-bg, #5C3317);
  background-image:
    linear-gradient(180deg, rgba(255, 255, 255, 0.12), rgba(0, 0, 0, 0) 55%),
    var(--ui-texture-panel, url('../resources/ui-textures/panel-birch.webp'));
  background-size: cover, 240px 240px;
  background-blend-mode: normal, soft-light;
  color: var(--btn-text-color, #F4D58D);  /* §22.6xx.658-iter26: auto-contraste por luminancia */
  border: none;
  cursor: pointer;
  user-select: none;
  box-shadow: var(--btn-wood-shadow);
  transition: transform 90ms ease, box-shadow 90ms ease, background-color 140ms ease;
}
.btn-wood-round > i {
  opacity: 0;                    /* hidden por defecto */
  font-size: 1.5rem;             /* más grande para que se vea claro */
  line-height: 1;
  transition: opacity 140ms ease, transform 140ms ease;
  transform: scale(0.6);
  /* Sombra sutil alrededor del icono para que destaque sobre la madera */
  filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.5));
}
.btn-wood-round:hover {
  background-color: var(--btn-bg-hover, #6B3E20);
  transform: translateY(-1px);
}
/* §22.457 — btn-wood-round: el "anillo brass-light + check interno" */
.btn-wood-round.is-selected {
  border: 2px solid var(--brass, #c85a29);
  box-shadow: var(--btn-wood-shadow);
}
/* §22.6xx.658-iter24 — El icono rp-check se muestra al seleccionar
   (antes era `opacity: 0` por el DROP de §22.6xx.656t). Roberto pidió
   que el check vuelva a ser visible para reforzar la selección. */
.btn-wood-round.is-selected > i {
  opacity: 1;
  transform: scale(1);
}
/* §22.6xx.658-iter30 — El icono rp-palette (default del botón Custom)
   debe verse cuando el botón NO está selected, en vez de quedarse
   invisible con opacity 0. Override de la regla .btn-wood-round > i
   que está pensada para el rp-check (que solo aparece al seleccionar).
   Usamos :not(.is-selected) para que cuando se active el botón y
   aparezca el check, el palette se oculte con x-show (display: none)
   y la opacity 1 ya noe. */
.btn-wood-round:not(.is-selected) > i.rp-palette {
  opacity: 1;
  transform: scale(1);
}
.btn-wood-round:active,
.btn-wood-round.active {
  transform: translateY(3px);
  box-shadow:
    inset 0 2px 4px rgba(0, 0, 0, 0.40),
    inset 0 1px 0 rgba(255, 253, 248, 0.15),
    0 1px 0 var(--btn-bg-raised, #3D2314),
    0 1px 2px rgba(0, 0, 0, 0.30);
}
.btn-wood-round:disabled {
  opacity: 0.45;
  cursor: not-allowed;
  filter: saturate(0.4);
}

.btn-wood:disabled {
  opacity: 0.45;
  cursor: not-allowed;
  filter: saturate(0.4);
}/* === D2. Text fields unificados (.text-field* / §22.190) ============= */
/* Sistema compartido: TODOS los text inputs del proyecto usan .text-field */
.text-field {
  display: block;
  width: 100%;
  border-radius: 0.75rem;        /* rounded-xl */
  box-sizing: border-box;        /* §22.190d: 2px border no cambia size total */
  padding: calc(0.5rem - 1px) 0.625rem;  /* py-2 - 1px = 7px para mantener alto similar (border-box incluye el border 2px) */
  font-size: 0.875rem;           /* text-sm */
  line-height: 1.25rem;
  /* §22.6xx.39o-packs-ui-iter14 — font-weight semibold (600) para que
     el texto tenga más presencia en los inputs, coherente con el
     look hand-drawn del resto de la app (layer names, theme card titles). */
  font-weight: 600;
  color: var(--sepia);
  background-color: transparent;  /* plano: sin textura de paper */
  outline: none;
  /* §22.6xx.39o-packs-ui-iter8 — appearance: none para resetear el
     browser default de <input> (background blanco, border 1px sólido). */
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  /* §22.6xx.39o-packs-ui-iter10 — position: relative para que el
     ::before con el border hand-drawn se posicione relativo al input. */
  position: relative;
  border: 2px solid var(--sepia);  /* §22.6xx.39o-packs-ui-iter10 — MISMO border original, con filter hand-drawn aplicado al input */
  transition: background-color 0.15s ease, border-color 0.15s ease;
  /* §22.6xx.39o-packs-ui-iter13 — filter hand-drawn-INPUT (scale=1.5)
     aplicado al input. Más wobble que subtle (0.8) pero sin distorsionar
     el texto perceptiblemente. El subtle era casi imperceptible;
     este da un hand-drawn look más evidente manteniendo el texto legible. */
  filter: url(#hand-drawn-filter-input);
}

.text-field::placeholder {
  color: rgba(92, 64, 51, 0.40);
  opacity: 1;
}

.text-field:hover {
  background-color: rgba(92, 64, 51, 0.04);
}

/* §22.6xx.39o-packs-ui-iter10 — focus cambia el border del input (que ahora
   tiene border propio, no ::before). Mantiene box-shadow como halo
   focus ring (no rompe el hand-drawn). */
.text-field:focus {
  background-color: transparent;
  border-color: var(--brass, #c85a29);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--brass) 30%, transparent);
}

/* === §22.6xx.39o-packs-ui-iter26 — Selects con estilo hand-drawn compartido
   Mismo styling que .text-field (border 2px sepia + filter hand-drawn-input
   + font-weight 600 + border-radius 0.75rem). Aplica a TODOS los <select>
   del workspace. Caret SVG custom sepia a la derecha. */
select {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  display: block;
  width: 100%;
  border-radius: 0.75rem;
  box-sizing: border-box;
  padding: calc(0.5rem - 1px) 0.625rem;
  padding-right: 1.85rem;  /* espacio para el caret */
  font-size: 0.875rem;
  line-height: 1.25rem;
  font-weight: 600;
  color: var(--sepia, #5C4033);
  background-color: transparent;
  outline: none;
  position: relative;
  border: 2px solid var(--sepia, #5C4033);
  transition: background-color 0.15s ease, border-color 0.15s ease;
  filter: url(#hand-drawn-filter-input);
  background-image:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='%235C3317'><path d='M0 0l6 8 6-8z'/></svg>");
  background-size: 10px 7px;
  background-position: right 0.7rem center;
  background-repeat: no-repeat;
  cursor: pointer;
}
select:hover {
  background-color: rgba(92, 64, 51, 0.04);
}
select:focus {
  background-color: transparent;
  border-color: var(--brass, #c85a29);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--brass) 30%, transparent);
}
select:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

/* Variante inline: fondo transparente y border transparente (se ve el bg */
.text-field-transparent {
  background-color: transparent;
  background-image: none;
  border-color: transparent;
}

.text-field-transparent:hover {
  background-color: transparent;
}

.text-field-transparent:focus::before {
  border-color: var(--brass, #c85a29);
}

/* Variante compacta: padding/font-size reducidos. Combina con cualquier */
.text-field-tight {
  padding: 0.25rem 0.5rem;
  font-size: 0.75rem;
  border-radius: 0.5rem;
}

/* === J. Layers panel (REWORK) === */

/* === J. Layers Panel (§22.537 — REWORK) ========================== */

/* Ancho fijo del panel (override del .floating-panel-wide genérico */
#panel-layers.panel-layers {
  width: 360px !important;
  max-height: calc(100dvh - 110px);
}

/* Fila de capa. Compacta: gap-1, p-1, thumbnail 36x36. */
.layer-row {
  position: relative;
  background: var(--panel-cream, #FCF7EE);
  border: none !important;  /* §22.6xx.39o-packs-ui-iter12 — el border lo pone el ::before con filtro hand-drawn */
  /* §22.6xx.39o-packs-ui-iter12 — overflow:hidden para que el ::before con
     border hand-drawn quede clipped al bounds del layer-row. */
  overflow: hidden;
  /* §22.6xx.658 — más padding interno (p-2 + extra) para que el contenido
     no quede tan pegado al borde hand-drawn del item. */
  padding: 0.55rem 0.7rem !important;
  transition:
    background 180ms cubic-bezier(0.2, 0, 0, 1),
    box-shadow 180ms cubic-bezier(0.2, 0, 0, 1);
  user-select: none;
}

/* §22.6xx.39o-packs-ui-iter12 — Borde hand-drawn via ::before + SVG filter.
   Mismo patrón que .theme-card::before pero con border 2px (más fino que
   theme-card 3px) y color var(--ink-stroke) (mismo gold que theme-card). */
.layer-row::before {
  content: "";
  position: absolute;
  inset: 0;
  box-sizing: border-box;
  border: 2px solid var(--ink-stroke, #c5a059);
  border-radius: inherit;
  filter: url(#hand-drawn-filter);
  pointer-events: none;
  transition: border-color 180ms cubic-bezier(0.2, 0, 0, 1);
}
.layer-row:hover::before {
  border-color: rgba(80, 60, 45, 0.45);
}
.layer-row:hover {
  background: rgba(255, 248, 232, 0.85);
}
/* §22.6xx.567 — ACTIVE layer: estilo "destacado" coherente con

 * anterior (border 2px + tint naranja 8%) era demasiado sutil. Ahora
 * la capa activa destaca con:
 *   - border 2.5px brass (sólido)
 *   - gradient cream→naranja claro (en lugar de flat tint)
 *   - box-shadow con inset highlight + glow brass exterior
 *   - thumbnail con ring brass-gradient
 *   - nombre de la capa en color brass
 * Mismo lenguaje visual que los "formatos destacados" del dialog

/* §22.6xx.555zp — Restaurado el border brass 2.5px de la active.
   §22.6xx.555zo (1 turno) lo había quitado por una interpretación
   errónea del feedback de Roberto: "no debe aparecer el borde
   extra". El feedback iba sobre el border DASHED del selected
   (§22.6xx.555zn) — no del active. La active SÍ debe tener un
   border de color de acento (brass 2.5px) porque es el affordance
   principal de "esta es la capa activa" en cualquier editor de
   layers. Roberto confirmó en el siguiente turno: "la capa activa
   que tenga el borde de color de acento". Ahora la active tiene:
     - border 2.5px brass (sólido, doble — row + ::before)
     - background gradient cream→naranja claro
     - box-shadow con glow brass exterior
     - thumbnail con ring brass-gradient
     - nombre de la capa en color brass
   (Nota: el border del ::before replica el del row para que el
   hand-drawn filter se aplique al brass, manteniendo la coherencia
   visual del panel.) */
.layer-row.layer-active {
  border-color: var(--brass, #c85a29) !important;
  border-width: 2.5px !important;
  background:
    linear-gradient(135deg, rgba(254, 245, 235, 0.95) 0%, rgba(252, 232, 220, 0.65) 100%) !important;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.8),
    0 0 0 1px rgba(200, 90, 41, 0.10),
    0 2px 6px rgba(200, 90, 41, 0.10) !important;
}
/* §22.6xx.555zp — active cambia el border del ::before al brass
   (replicando el del row para que el filtro hand-drawn se aplique
   al accent). Hereda la estructura del ::before normal pero con
   el color/grosor del active. */
.layer-row.layer-active::before {
  border-color: var(--brass, #c85a29);
  border-width: 2.5px;
}
/* Thumbnail ring cuando la capa está activa: mismo brass-gradient
.layer-row.layer-active .paper-light {
  background: linear-gradient(135deg, rgba(200, 90, 41, 0.30) 0%, color-mix(in srgb, var(--brass) 22%, transparent) 100%) !important;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.6), 0 1px 3px rgba(200, 90, 41, 0.20);
}
/* Nombre de la capa activa en color brass — coherente con el
.layer-row.layer-active .text-field-transparent {
  color: var(--brass-text, #93411c) !important;
}
/* §22.6xx.555zn — SELECTED (multi-select sin ser active): solo
 * background accent atenuado, SIN border. Roberto: "al seleccionar
 * capas, con el check, aparecen unos bordes extra en las capas
 * seleccionadas, no debe aparecer ese borde extra, solo debe cambiar
 * el color de fondo de la capa al color de acento atenuado. No añadir
 * ningún borde". Antes había un border 2px dashed brass (capas
 * seleccionadas sin ser activas se rodeaban con borde discontinuo).
 * Ahora solo cambia el background a un tono brass muy suave. El
 * border hand-drawn por defecto del layer-row (2px solid gold) se
 * mantiene — es la identidad visual del panel, no un "borde extra".
 * Alpha subido de 0.04 a 0.10: el 4% era prácticamente invisible
 * y daba la sensación de "no pasa nada al seleccionar". */
.layer-row.layer-selected:not(.layer-active) {
  background: rgba(200, 90, 41, 0.10) !important;
}
/* §22.6xx.555zq — Border brass en el ::before del selected.
   Roberto: "la capa seleccionada con el check, que se ponga el
   thumb de la capa con el borde de color de acento, y el borde
   de la capa también con el color de acento". El border del
   row SIEMPRE va en el ::before (porque .layer-row tiene
   `border: none !important;` desde §22.6xx.39o-packs-ui-iter12).
   Aplicamos border brass sólido 2px (mismo color que el active
   pero grosor ligeramente menor para no competir con el active
   2.5px). El active gana por grosor si una capa está activa Y
   seleccionada. */
.layer-row.layer-selected:not(.layer-active)::before {
  border-color: var(--brass, #c85a29);
  border-width: 2px;
  border-style: solid;
}
/* §22.6xx.555zq — Thumb (paper-light) del selected con ring brass
   sólido. El active usa un ring brass-gradient (línea ~4802); el
   selected usa un border sólido más simple para diferenciar
   visualmente "seleccionada con check" vs "activa". */
.layer-row.layer-selected:not(.layer-active) .paper-light {
  border: 1.5px solid var(--brass, #c85a29) !important;
  box-shadow: 0 0 0 1px rgba(200, 90, 41, 0.15);
}
/* §22.6xx.555zr — Active+selected thumb: el border brass del thumb
   debe MANTENERSE aunque la capa también esté activa. Roberto: "si
   la capa está seleccionada y a la vez activa, debe mantenerse el
   borde de color de acento del thumb de la capa". El selector
   `:not(.layer-active)` del bloque anterior EXCLUYE el caso
   active+selected, así que necesitamos esta regla explícita. La
   active+selected tiene el ring gradient del active + el border
   brass 1.5px del selected. El checkbox marcado es el discriminador
   principal entre active-only y active+selected; el border brass
   del thumb es un refuerzo visual secundario. */
.layer-row.layer-active.layer-selected .paper-light {
  border: 1.5px solid var(--brass, #c85a29) !important;
}
/* Si está activa Y seleccionada: el background del active ya manda
   (gradient cream→naranja). El background del selected (alpha 0.10
   brass) NO se aplica porque el `!important` del active gana. Eso
   es correcto: la activa+seleccionada muestra el gradient activo,
   no la atenuación de selected. Si Roberto quiere que la
   seleccionada con check SOBRE la active muestre algún cambio
   visual extra (e.g. un tick extra en el checkbox), se hace en el
   HTML del checkbox, no en el border (que ahora no existe). */
.layer-row.layer-active.layer-selected {
  background:
    linear-gradient(135deg, rgba(254, 245, 235, 0.95) 0%, rgba(252, 232, 220, 0.65) 100%) !important;
}
/* Cursor de drag (Sortable.js añade .sortable-drag, .sortable-ghost */
.layer-row.sortable-ghost {
  opacity: 0.4;
  background: rgba(197, 160, 89, 0.20) !important;
}
.layer-row.sortable-chosen {
  cursor: grabbing !important;
}
.layer-row.sortable-drag {
  opacity: 0.95;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
}

/* Checkbox de multi-select. Estilo consistente con la app (sepia/cream */

/* === §22.6xx.39o-packs-ui-iter15 — Radio & Check hand-drawn (runa) === */
/* Estilo custom para radio buttons y checkboxes con look hand-drawn.
   El input nativo se oculta (appearance:none) y se reemplaza por un
   visual custom via ::before (border) + ::after (indicador de selección).
   El border usa el filter hand-drawn para el wobble característico.
   El indicador de selección es:
   - Check: diamante (runa) rotated 45deg
   - Radio: círculo sólido (punto) */

/* --- CHECKBOX hand-drawn (.rune-check) --- */
.rune-check {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  position: relative;
  display: inline-block;
  width: 18px;
  height: 18px;
  margin: 0;
  cursor: pointer;
  vertical-align: middle;
  background: transparent;
  border: none;
  outline: none;
  flex-shrink: 0;
}
.rune-check::before {
  content: "";
  position: absolute;
  inset: 0;
  box-sizing: border-box;
  border: 2px solid var(--ink-stroke, #c5a059);
  border-radius: 3px;          /* esquinas suaves, no 0 — más "caja" */
  filter: url(#hand-drawn-filter);
  pointer-events: none;
  transition: border-color 0.15s ease;
  background: var(--panel-cream, #FCF7EE);
}
.rune-check:checked::before {
  border-color: var(--brass, #c85a29);
}
.rune-check:checked::after {
  content: "";
  position: absolute;
  /* Diamante (runa) centrado: 8x8 rotated 45deg */
  top: 50%;
  left: 50%;
  width: 9px;
  height: 9px;
  background: var(--brass, #c85a29);
  transform: translate(-50%, -50%) rotate(45deg);
  pointer-events: none;
  /* Sin filter — el diamante es sólido, no necesita wobble */
}
.rune-check:hover::before {
  border-color: rgba(80, 60, 45, 0.6);
}
.rune-check:focus-visible::before {
  border-color: var(--brass, #c85a29);
  box-shadow: 0 0 0 2px rgba(200, 90, 41, 0.20);
}

/* --- RADIO hand-drawn (.rune-radio) --- */

/* --- Variante más grande (para usar en dialogs con texto al lado) --- */
.rune-check.rune-lg, .rune-radio.rune-lg {
  width: 22px;
  height: 22px;
}
.rune-check.rune-lg:checked::after {
  width: 11px;
  height: 11px;
}

/* Menú desplegable (ti-dots-vertical). Mismo lenguaje visual que el */
.layers-menu {
  background: var(--panel-cream, #FCF7EE) !important;
  border: 1.5px solid var(--brass, #c85a29) !important;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  font-family: 'Nunito', system-ui, sans-serif;
}
.layers-menu-item {
  display: flex !important;
  align-items: center !important;
  gap: 0.5rem;
  width: 100%;
  padding: 0.4rem 0.75rem;
  font-size: 12px;
  color: var(--sepia, #5C3317);
  background: transparent;
  border: none;
  cursor: pointer;
  text-align: left;
  transition: background-color 0.10s ease;
}
.layers-menu-item:hover:not(:disabled) {
  background: rgba(197, 160, 89, 0.15);
}
.layers-menu-item:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
.layers-menu-item i {
  font-size: 0.9rem;
  width: 1.1rem;
  text-align: center;
  color: rgba(80, 60, 45, 0.6);
}
.layers-menu-item:hover:not(:disabled) i {
  color: var(--brass-text, #93411c);
}
.layers-menu-sep {
  height: 1px;
  margin: 0.25rem 0.5rem;
  background: rgba(80, 60, 45, 0.15);
}


/* === F. Texto grabado (.engraved-*) === */

/* === F. Texto grabado (.engraved-*) =============================== */

/* §22.6xx.658df — Help engine: info icon button + dialog visuals.
 * El `.section-help-trigger` es el icono "i" reusable que se coloca al
 * lado de cualquier <h3> de sección. El handler delegado vive en
 * js/ui/help-engine.js (un solo listener global).
 * El dialog se estiliza con `.dialog-panel` y `.paper-noise-bg` ya
 * existentes — sin header (estilo welcome body, §22.6xx.205).
 */
.section-help-trigger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  margin-left: 0.4rem;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 50%;
  background: transparent;
  color: var(--brass-text, #93411c);
  cursor: help;
  opacity: 0.55;
  transition: opacity 0.16s ease, transform 0.16s ease, background 0.16s ease;
  vertical-align: middle;
  flex-shrink: 0;
}
.section-help-trigger:hover,
.section-help-trigger:focus-visible {
  opacity: 1;
  background: rgba(200, 90, 41, 0.08);
  border-color: rgba(200, 90, 41, 0.25);
  transform: translateY(-1px);
  outline: none;
}
.section-help-trigger:active {
  transform: translateY(0);
}
.section-help-trigger .ti {
  font-size: 0.95rem;
  line-height: 1;
  pointer-events: none;
}
/* Wrapper del dialog de ayuda: centra y limita el ancho para lectura
   cómoda (~560px). El panel real usa `.dialog-panel` reaprovechado. */
.dialog-panel-wrapper {
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}
.dialog-panel-wrapper > .dialog-panel {
  pointer-events: auto;
}
/* Contenido fetched del help: respetar los <p>/<strong>/<ul> del HTML
   pre-renderizado que Roberto escribe en resources/help/<lang>/*.md. */
.dialog-info-text p {
  margin: 0 0 0.7rem;
}
.dialog-info-text p:last-child {
  margin-bottom: 0;
}
.dialog-info-text strong {
  color: var(--brass-text, #93411c);
  font-weight: 700;
}
.dialog-info-text code {
  font-family: ui-monospace, "SF Mono", "Menlo", monospace;
  font-size: 0.78rem;
  padding: 0.08em 0.32em;
  background: rgba(92, 64, 51, 0.08);
  border-radius: 4px;
  color: var(--sepia, #5c4033);
}
/* §22.6xx.audit-a2 — Teclas de atajo del help dialog: chip de tecla.
   Comparte paleta y radio con `.dialog-info-text code` de arriba; añade borde
   + luz interior para leer como tecla física. */
.kbd {
  display: inline-flex;
  align-items: center;
  font-family: ui-monospace, "SF Mono", "Menlo", monospace;
  font-size: 0.78rem;
  line-height: 1.5;
  padding: 0.08em 0.36em;
  color: var(--sepia, #5c4033);
  background: rgba(92, 64, 51, 0.08);
  border: 1px solid rgba(92, 64, 51, 0.18);
  border-radius: 4px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.5);
  white-space: nowrap;
}
/* Los pares de teclas van pegados en el markup (p.ej. `[` y `]`), sin espacio
   entre ellos: sin este margen los bordes se tocan. */
.kbd + .kbd {
  margin-left: 0.25em;
}
.kbd-sm {
  font-size: 0.72rem;
  padding: 0.05em 0.3em;
}
.kbd-xs {
  font-size: 0.66rem;
  padding: 0.02em 0.24em;
  border-radius: 3px;
}
.dialog-info-text ul,
.dialog-info-text ol {
  margin: 0.4rem 0 0.7rem 1.25rem;
  padding: 0;
}
.dialog-info-text li {
  margin-bottom: 0.25rem;
}
.dialog-info-text a {
  color: var(--brass-text, #93411c);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.dialog-info-text a:hover {
  color: var(--brass-dark, #a0451c);
}

/* §22.6xx.658dr.75 — Grid "Approximate" compacto del pill minimizado.
 *
 * El elemento lleva las dos clases (`color-wheel-approximate-grid
 * color-floating-pill-approximate-grid`), así que ambas reglas compiten con la
 * MISMA especificidad y gana la que se carga después. La base declara
 * `repeat(17, 1fr)` / `repeat(9, 1fr)` porque esa rejilla es la del panel
 * completo, pero el pill usa la variante compacta de 11×5
 * (`getApproximateGridCompact`): 6 columnas y 4 filas vacías se comían el 35%
 * del ancho y el 44% del alto, y el `aspect-ratio: 17/9` obligaba además a una
 * caja con la proporción equivocada. Medido: celdas de 7×7 px.
 *
 * Doble clase a propósito (0,2,0) para no depender del orden de carga de los
 * CSS. Se recorta también el padding y el gap del grid compacto, que a este
 * tamaño se-come un porcentaje alto del poco ancho disponible. */
/* §22.6xx.658dr.78 — 2 filas más. El pill dejaba 30px vacíos bajo el grid y
   cada fila consume ~13.9px, así que 11×7 llena ese hueco sin tocar el alto
   del pill. El aspect-ratio tiene que acompañar al template o la caja
   seguiría con proporción de 11×5 y aplastaría las celdas. */
.color-wheel-approximate-grid.color-floating-pill-approximate-grid {
  grid-template-columns: repeat(11, 1fr);
  grid-template-rows: repeat(7, 1fr);
  aspect-ratio: 11 / 7;
  gap: 1px;
  padding: 4px;
}

/* El hover escala 1.4× un cuadrado de 14px: a ese tamaño el saliente se sale
   de la caja y el grid la recorta (overflow: hidden). Bajar a 1.25× mantiene
   el feedback de "punteo" sin que se corte. */
.color-floating-pill-approximate-grid .color-wheel-approximate-cell:hover {
  transform: scale(1.25);
}
.color-floating-pill-approximate-grid .color-wheel-approximate-cell.is-selected:hover {
  transform: scale(1.25);
}

/* §22.6xx.658dr.89 — Botón fantasma: sin textura, sin fondo, solo borde e icono.
 *
 * Nace de un problema medido: con 10 capas, el panel de capas lleva 4 botones
 * `.btn-wood` por fila = 40 botones. Cada `.btn-wood` cuesta una textura
 * (`--ui-texture-panel`), un gradiente, un `background-blend-mode: soft-light`
 * y SEIS sombras (tres inset + una de relieve + una difuminada). Multiplicado
 * por 40, cada paso del ratón sobre el panel tenía que recomponer todo eso, y
 * se notaba en la cola de fotogramas: p95 32,3 ms → 13,7 ms al quitar los
 * botones (medido por Roberto, fases 0 y 1 de un diagnóstico por fases).
 *
 * Aquí se deja el área clicable y el tamaño intactos y se quita TODO lo demás:
 * sin fondo, sin textura, sin blend y con una sola sombra. El icono pasa a
 * color de acento (--brass) para que se lea igual sin el relleno de madera.
 *
 * SIN `filter: url(#hand-drawn-filter)` a propósito: es un feTurbulence +
 * feDisplacementMap, y ponerlo en 40 botones serían 40 rasterizaciones de
 * turbulencia por fila-set — bastante más caro que lo que se quita. El borde
 * es plano. Si se quiere el trazo a mano, el sitio barato es aplicarlo
 * únicamente a la fila sobre la que está el ratón (uno a la vez), no a los 40.
 *
 * Hover: se usa un fondo translúcido, que es barato. Evitar cambiar
 * `box-shadow` en el hover, que sí obliga a repintar.
 */
.btn-ghost {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
/* §22.6xx.658dr.91 — Sin borde: el único afordance es el icono en color de
   acento y, al pasar por encima, un fondo translúcido. Menos pintura por
   botón, que es justo lo que se buscaba en §658dr.89. */
  border: none;
  border-radius: 6px;
  color: var(--brass, #c85a29);
  cursor: pointer;
  user-select: none;
  box-shadow: none;
  transition: background 110ms ease, color 110ms ease;
}
.btn-ghost:hover:not(:disabled) {
  background: rgba(200, 90, 41, 0.10);
  border-color: var(--brass, #c85a29);
}
.btn-ghost:active:not(:disabled) {
  background: rgba(200, 90, 41, 0.18);
}
.btn-ghost:focus-visible {
  outline: 2px solid var(--brass, #c85a29);
  outline-offset: 1px;
}
.btn-ghost:disabled {
  opacity: 0.35;
  cursor: default;
}
.btn-ghost > i {
  background-color: currentColor;
}

/* §22.6xx.658dr.89 — Variante destructiva del botón fantasma: el icono de
 * borrar mantiene el rojo de siempre para que siga leyéndose como "esto
 * borra". El color va en `color` (y el icono hereda con currentColor), sin
 * tocar el fondo: el hover es el mismo translúido del resto.
 * El rojo es el mismo que usaba `.btn-wood-danger` (#8B2C1A) para no abrir un
 * debate de paleta. */
.btn-ghost-danger {
  color: #8B2C1A;
}
.btn-ghost-danger:hover:not(:disabled) {
  background: rgba(139, 44, 26, 0.10);
}
.btn-ghost-danger:active:not(:disabled) {
  background: rgba(139, 44, 26, 0.18);
}

/* §22.6xx.658dr.90 — Tamaño de los botones fantasma dentro de la fila de capa.
 *
 * Medido en el panel: con `.btn-square` (3rem) los 4 botones ocupan **198 de
 * los 304 px de la fila** — el 65% — y al nombre de la capa le quedaban 20 px
 * medidos. El nombre era ilegible, que es justo lo que se veía.
 *
 * A 1.75rem (28 px) los 4 botones ocupan 118 px, el nombre recupera ~132 px y
 * la fila baja de 66 a ~54 px, que ahora la manda la miniatura (36 px) y no los
 * botones.
 *
 * Se anula el `padding` con `!important` porque `.btn-xs` lo declara también con
 * `!important` (css/brush-creator-editor.css), y su `min-height`/`min-width`
 * vienen de `.btn-square` (chrome.css). Se ajusta a mano aquí en vez de tocar
 * esas clases globales, que se usan en toda la app.
 *
 * Si en algún momento el área clicable resulta corta, `1.75rem` es el único
 * número que hay que cambiar.
 */
.layer-row .btn-ghost {
  min-height: 1.75rem;
  min-width: 1.75rem;
  padding: 0 !important;
  border-radius: 5px;
}
.layer-row .btn-ghost > i {
  width: 0.95rem;
  height: 0.95rem;
  font-size: 0.95rem;
}

/* §22.6xx.658dr.92 — Los botones solo existen en la fila del ratón o la activa.
 *
 * Motivo (medido por Roberto, no supuesto): con 10 capas el panel pintaba 40
 * botones y eso era lo que costaba, no lo que llevaban encima. Su diagnóstico
 * por fases lo dejó claro — quitar la textura (fase 6) NO mejoró el p95
 * (32,4 ms) mientras que quitar 4 de cada 5 botones (fase 1) lo bajó a 13,7 ms.
 * O sea: el coste escala con el número de botones, no con su contenido.
 *
 * `visibility` y no `display` a propósito. `display: none` sacaría el botón del
 * flujo, la fila encogería y el nombre de la capa saltaría de ancho cada vez que
 * el ratón entra o sale — y con `display` el botón ni siquiera es hit-testable.
 * `visibility: hidden` conserva el hueco (cero layout shift) y Blink lo salta
 * entero en la fase de paint, que es justo lo que se quiere ahorrar.
 *
 * Sin estado en Alpine: todo el comportamiento sale de `:hover`, así que mover
 * el ratón por el panel no dispara ni una reevaluación reactiva.
 *
 * `:focus-within` no es adorno: `visibility: hidden` saca el botón del orden de
 * tabulación, así que sin esto el teclado no llegaría a ellos. Al tabular hasta
 * el checkbox de la fila, la fila gana `:focus-within`, los botones aparecen y
 * el siguiente tab ya los alcanza.
 */
.layer-row .layer-row-actions > .btn-ghost {
  visibility: hidden;
}
.layer-row:hover .layer-row-actions > .btn-ghost,
.layer-row.layer-active .layer-row-actions > .btn-ghost,
.layer-row:focus-within .layer-row-actions > .btn-ghost {
  visibility: visible;
}

/* §22.6xx.658dr.93 — Miniatura de la capa, sin canvas.
 *
 * El thumbnail se pinta desde JS como `background-image` en línea sobre este div
 * (el canvas 40x40 horneado vive en js/ui/layer-thumbnails.js). El fondo de abajo
 * es solo el estado "todavía no hay miniatura", para que se vea el papel.
 *
 * Esta clase existe en vez de reutilizar `paper-light` por una razón concreta:
 * `css/dialogs.css` declara `background-image: var(--ui-texture-paper-noise)
 * !important` sobre `.paper-light`, y en la cascada un `!important` de autor gana
 * al estilo en línea aunque el elemento lo declare directamente. Con
 * `paper-light` el thumbnail se aplicaba correctamente y aun así no se veía
 * ningún cambio en pantalla. Aquí nada lleva `!important`, así que el
 * `background-image` en línea gana como debe.
 */
.layer-thumb {
  background-color: var(--panel-cream);
  background-image: var(--ui-texture-paper-noise);
  background-size: 240px 240px;
  background-blend-mode: multiply;
  background-repeat: repeat;
}

/* §22.6xx.658dr.741 — Estado "capa oculta" de la miniatura.
 *
 * Va como CLASE y no como estilo en línea a propósito: Alpine resuelve
 * `x-bind:style` con `setAttribute('style', ...)`, que REEMPLAZA el atributo
 * entero. La miniatura vive justamente ahí (el `background-image` en línea
 * que aplica js/ui/layer-thumbnails.js), así que con el estilo en línea
 * cada vez que la visibilidad de la capa cambiaba, Alpine borraba la
 * miniatura y la fila se quedaba mostrando el papel. Con una clase, el
 * atributo `style` es territorio exclusivo de la miniatura. */
.layer-thumb.is-layer-hidden {
  opacity: 0.35;
  filter: grayscale(1);
}

/* ═══ §22.6xx.658dr.127 — Pill de capas ═══
   Reutiliza toda la madera, sombra, botones y resize del pill de pinceles
   (`.brushes-floating-*`), que ya están probados. Solo se declara lo que es
   propio de capas: las filas de thumbnail y la barra de acciones. */
.layers-floating-content {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 4px;
  overflow-y: auto;
}
.layers-floating-row {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2px;
  border-radius: 6px;
  cursor: grab;
  user-select: none;
  touch-action: none;
}
.layers-floating-row:hover {
  background: rgba(92, 64, 51, 0.08);
}
/* §22.6xx.658dr.128 — El marco de la capa activa lo lleva ahora la MINIATURA
   (borde brass hand-drawn), no la fila: con los dos, el brass salia duplicado
   a 2px de distancia. La fila solo conserva el tinte de fondo. */
.layers-floating-row.is-active {
  background: rgba(200, 90, 41, 0.12);
}
/* §22.6xx.658dr.128 — Estados de arrastre de Sortable.js. Declarados DESPUES
   de :hover / .is-active a proposito: los tres tienen la misma especificidad
   (0,2,0), asi que el orden en la hoja es lo que decide, y mientras se arrastra
   manda el ghost. */
.layers-floating-row.sortable-ghost {
  opacity: 0.4;
  background: rgba(197, 160, 89, 0.2);
}
.layers-floating-row.sortable-chosen {
  cursor: grabbing;
}
.layers-floating-row.sortable-drag {
  opacity: 0.95;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
}
/* §22.6xx.658dr.128 — Miniatura con borde hand-drawn. Mismo patron del
   workspace (`.layer-row::before`, `.rune-check::before`): el borde lo pinta
   un ::before con `filter: url(#hand-drawn-filter)` porque un `border` normal
   no ondula. El fondo del thumbnail llega como `background-image` en linea
   desde js/ui/layer-thumbnails.js, asi que el ::before NO lleva fondo: solo el
   marco, encima de la imagen. */
.layers-floating-thumb {
  width: 42px;
  height: 42px;
  position: relative;
  overflow: hidden;
  border-radius: 5px;
  background-size: cover;
  background-position: center;
}
.layers-floating-thumb::before {
  content: "";
  position: absolute;
  inset: 0;
  box-sizing: border-box;
  border: 2px solid var(--ink-stroke, #c5a059);
  border-radius: inherit;
  filter: url(#hand-drawn-filter);
  pointer-events: none;
  transition: border-color 180ms cubic-bezier(0.2, 0, 0, 1);
}
.layers-floating-row:hover .layers-floating-thumb::before {
  border-color: rgba(80, 60, 45, 0.55);
}
/* §22.6xx.658dr.128 — La capa activa pasa su miniatura a brass. El orden visual
   es el de la ventana: la de arriba se ve arriba. */
.layers-floating-row.is-active .layers-floating-thumb::before {
  border-color: var(--brass, #c85a29);
}
/* §22.6xx.658dr.127 — Los botones de anadir, ocultar y borrar van en la MISMA
   columna que el resto (entre el handle y el maximize), asi que heredan el
   estilo de `.brushes-floating-*` y solo fijan su hueco.
   §22.6xx.658dr.129 — Entra "ocultar capa" debajo de "anadir", asi que TODO lo
   que venia despues baja 30px: handle 6, anadir 36, ocultar 66, borrar 96,
   maximize 126, cerrar 156. El boton de 24px con paso de 30 deja 6px de hueco. */
.layers-floating-btn-add,
.layers-floating-btn-hide,
.layers-floating-btn-delete {
  left: 6px;
}
.layers-floating-btn-add > i,
.layers-floating-btn-hide > i,
.layers-floating-btn-delete > i {
  font-size: 0.875rem;
}
/* El pill de capas no usa el boton de orientacion: maximize y cerrar bajan. */
.layers-floating-pill .brushes-floating-maximize { top: 126px; }
.layers-floating-pill .brushes-floating-close { top: 156px; }
.layers-floating-btn-add { top: 36px; }
.layers-floating-btn-hide { top: 66px; }
.layers-floating-btn-delete { top: 96px; }
