/* ============ Catculator — estilos ============ */

/* ---------- Pelaje del gato ---------- */
:root {
  --fur: #3a3942;       /* carbón (predeterminado) */
  --fur-line: #16151a;  /* boca, deditos, cejas, zzz */
  --whisker: #c9c9d4;
}

:root[data-fur="naranja"] { --fur: #e8913a; --fur-line: #7a4514; --whisker: #fff3e0; }
:root[data-fur="gris"]    { --fur: #8a8e9b; --fur-line: #3d4049; --whisker: #f3f3f7; }
:root[data-fur="negro"]   { --fur: #211f29; --fur-line: #8e8c9e; --whisker: #d9d9e3; }
:root[data-fur="blanco"]  { --fur: #f6f4f0; --fur-line: #5a5561; --whisker: #b9b7c2; }

:root, :root[data-theme="cian"] {
  --bg1: #aef0fa;
  --bg2: #d8f9ff;
  --panel: #ffffff;
  --display-bg: #e6fbff;
  --key-bg: #ffffff;
  --key-hover: #eafcff;
  --key-op-bg: #67e8f9;
  --key-op-hover: #4dd9ee;
  --key-eq-bg: #22d3ee;
  --key-eq-hover: #0fc4e0;
  --key-fn-bg: #cff7fd;
  --key-fn-hover: #b8f1fa;
  --accent: #06b6d4;
  --text: #111111;
  --shadow: rgba(6, 182, 212, 0.35);
  --eye-color: #67e8f9;
  --ear-inner: #f9a8d4;
  --nose-color: #f472b6;
  --bubble-bg: #ffffff;
}

:root[data-theme="rosa"] {
  --bg1: #fbc6e2;
  --bg2: #ffe4f2;
  --panel: #ffffff;
  --display-bg: #fff0f7;
  --key-bg: #ffffff;
  --key-hover: #fff0f7;
  --key-op-bg: #f9a8d4;
  --key-op-hover: #f58fc7;
  --key-eq-bg: #ec4899;
  --key-eq-hover: #db2777;
  --key-fn-bg: #fcd9ec;
  --key-fn-hover: #fac7e2;
  --accent: #ec4899;
  --shadow: rgba(236, 72, 153, 0.35);
  --eye-color: #f9a8d4;
  --ear-inner: #fbcfe8;
  --nose-color: #ec4899;
  --bubble-bg: #ffffff;
  --text: #111111;
}

:root[data-theme="menta"] {
  --bg1: #a9f0d1;
  --bg2: #dcfcee;
  --panel: #ffffff;
  --display-bg: #ecfdf5;
  --key-bg: #ffffff;
  --key-hover: #ecfdf5;
  --key-op-bg: #6ee7b7;
  --key-op-hover: #4fdda4;
  --key-eq-bg: #10b981;
  --key-eq-hover: #0aa371;
  --key-fn-bg: #d1fae5;
  --key-fn-hover: #bcf5d9;
  --accent: #10b981;
  --shadow: rgba(16, 185, 129, 0.35);
  --eye-color: #6ee7b7;
  --ear-inner: #fbcfe8;
  --nose-color: #f472b6;
  --bubble-bg: #ffffff;
  --text: #111111;
}

:root[data-theme="lavanda"] {
  --bg1: #d5c9fd;
  --bg2: #efeafe;
  --panel: #ffffff;
  --display-bg: #f5f2ff;
  --key-bg: #ffffff;
  --key-hover: #f5f2ff;
  --key-op-bg: #c4b5fd;
  --key-op-hover: #b09cf9;
  --key-eq-bg: #8b5cf6;
  --key-eq-hover: #7c46f0;
  --key-fn-bg: #e6defe;
  --key-fn-hover: #dbd0fc;
  --accent: #8b5cf6;
  --shadow: rgba(139, 92, 246, 0.35);
  --eye-color: #c4b5fd;
  --ear-inner: #fbcfe8;
  --nose-color: #f472b6;
  --bubble-bg: #ffffff;
  --text: #111111;
}

:root[data-theme="atigrado"] {
  --bg1: #ffd9a8;
  --bg2: #fff0dc;
  --panel: #ffffff;
  --display-bg: #fff7ec;
  --key-bg: #ffffff;
  --key-hover: #fff7ec;
  --key-op-bg: #fdba74;
  --key-op-hover: #fca855;
  --key-eq-bg: #f97316;
  --key-eq-hover: #ea630a;
  --key-fn-bg: #ffe6c7;
  --key-fn-hover: #fedbb0;
  --accent: #f97316;
  --shadow: rgba(249, 115, 22, 0.35);
  --eye-color: #fdba74;
  --ear-inner: #fbcfe8;
  --nose-color: #f472b6;
  --bubble-bg: #ffffff;
  --text: #111111;
}

:root[data-theme="noche"] {
  --bg1: #0f172a;
  --bg2: #1e2a45;
  --panel: #1e293b;
  --display-bg: #a5f3fc;
  --key-bg: #cffafe;
  --key-hover: #b5f4fb;
  --key-op-bg: #67e8f9;
  --key-op-hover: #4dd9ee;
  --key-eq-bg: #22d3ee;
  --key-eq-hover: #0fc4e0;
  --key-fn-bg: #99e9f5;
  --key-fn-hover: #83e2f1;
  --accent: #22d3ee;
  --shadow: rgba(0, 0, 0, 0.55);
  --eye-color: #fde047;
  --ear-inner: #7a4f63;
  --nose-color: #f472b6;
  --bubble-bg: #e2f8fd;
  --text: #111111;
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  user-select: none;
  -webkit-tap-highlight-color: transparent; /* sin destello azul al tocar en Android */
}

html, body {
  height: 100%;
}

body {
  font-family: "Segoe UI", system-ui, sans-serif;
  background: linear-gradient(160deg, var(--bg1), var(--bg2) 60%, var(--bg1));
  color: var(--text);
  transition: background 0.5s ease;
  overflow: hidden;
  overscroll-behavior: none;  /* sin rebote ni recarga al arrastrar */
  touch-action: manipulation; /* elimina el retardo de 300ms del doble-toque */
}

#app {
  position: relative; /* ancla de los paneles: pegados a la app, no a la ventana */
  height: 100vh;
  height: 100dvh; /* en el móvil 100vh no descuenta la barra del navegador */
  max-width: 460px;
  margin: 0 auto;
  padding: 10px 16px 8px;
  /* respeta el notch y la barra de gestos en pantalla completa */
  padding-top: calc(10px + env(safe-area-inset-top));
  padding-bottom: calc(8px + env(safe-area-inset-bottom));
  padding-left: calc(16px + env(safe-area-inset-left));
  padding-right: calc(16px + env(safe-area-inset-right));
  display: flex;
  flex-direction: column;
}

/* ---------- Barra superior ---------- */
.topbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;                        /* que el nombre no quede pegado a los botones */
  padding: 2px 4px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 8px;
}

.brand-paw {
  font-size: 22px;
  animation: wiggle 3s ease-in-out infinite;
}

@keyframes wiggle {
  0%, 90%, 100% { transform: rotate(0deg); }
  93% { transform: rotate(-14deg); }
  96% { transform: rotate(14deg); }
}

.brand h1 {
  font-size: 22px;
  font-weight: 800;
  letter-spacing: 0.5px;
  color: var(--text);
}

:root[data-theme="noche"] .brand h1 { color: #e2f8fd; }
:root[data-theme="noche"] .footer { color: #9fd8e4; }

/* Los botones no se encogen ni se salen NUNCA: si falta sitio, lo cede el
   nombre. Sin esto, quien pierde es siempre el último botón de la fila, que
   se va fuera de pantalla sin avisar — pasó con 🎨 al entrar el de idioma.
   Un nombre recortado se entiende; un botón que no está, no se encuentra. */
.topbar-actions {
  display: flex;
  gap: 8px;
  flex: 0 0 auto;
}

.brand { min-width: 0; }
.brand h1 {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.icon-btn {
  width: 40px;
  height: 40px;
  border: none;
  border-radius: 12px;
  background: var(--panel);
  font-size: 19px;
  cursor: pointer;
  box-shadow: 0 3px 8px var(--shadow);
  transition: transform 0.15s ease, background 0.3s ease;
}

.icon-btn:hover { transform: scale(1.08); }
.icon-btn:active { transform: scale(0.94); }

/* El de idioma lleva letras en vez de emoji. Letras y no bandera a propósito:
   Windows no dibuja los emoji de bandera —los deja en dos cuadritos con las
   siglas—, así que la bandera se veía distinta en cada sistema. "ES"/"EN" se
   lee igual en todos y encima ocupa menos. */
.icon-btn-texto {
  width: 30px;            /* más estrecho que los de emoji: dos letras ocupan menos */
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 0.5px;
  color: var(--accent);
}

/* En teléfono la barra de arriba no cabe sola. Con cinco botones de 40 px más
   el nombre ya sumaba 407 px contra los 360 del celular más común, y el botón
   de personalizar (🎨) se salía de pantalla arrastrando la página de lado. Al
   entrar el sexto botón (el de idioma) hubo que volver a apretar: medido, a
   360 px faltaban 11 y a 320 faltaban 31.

   El corte estuvo en 415 px mientras hubo cinco botones, con la idea de que
   por debajo estaban los celulares y por encima la ventana del escritorio,
   que siempre cupo. Con seis botones dejó de ser verdad y hubo que subirlo a
   470, porque la ventana del escritorio NO mide 440 px de CSS: main.js la crea
   con 440 dp y en una pantalla al 110% eso son 426 px de CSS. Entre 416 y 465
   quedaba una franja sin ninguna media query donde los botones seguían a 40 px
   y pedían 443: el de personalizar (🎨) se salía 27 px. Justo la ventana por
   defecto.

   Moraleja para el próximo que toque esto: los dp de main.js no son px de CSS.
   Hay un script que mide la ventana de verdad en vez de adivinarlo. */
@media (max-width: 470px) {
  .brand { gap: 6px; }
  .brand-paw { font-size: 19px; }
  .brand h1 { font-size: 18px; letter-spacing: 0.2px; }
  .topbar-actions { gap: 4px; }
  .icon-btn { width: 32px; height: 32px; font-size: 15px; border-radius: 10px; }
  .icon-btn-texto { width: 27px; font-size: 12px; }
}

/* Este corte subió de 350 a 365 al entrar el sexto botón: a 360 px —que es el
   ancho de celular más repetido— con los botones de 32 px la barra se quedaba
   en 6 px negativos y el nombre empezaba a comprimirse. */
@media (max-width: 365px) {
  .brand-paw { font-size: 16px; }
  .brand h1 { font-size: 16px; }
  .topbar-actions { gap: 3px; }
  .icon-btn { width: 29px; height: 29px; font-size: 14px; }
  .icon-btn-texto { width: 25px; font-size: 11px; }
}

/* A 320 px no caben el nombre y seis botones por mucho que se aprieten. Se va
   el nombre y se queda la patita. La alternativa era esconder un botón, y un
   botón escondido no se encuentra; el nombre de la app, dentro de la propia
   app, no le dice nada a nadie. */
@media (max-width: 335px) {
  .brand h1 { display: none; }
}

/* Quien pidió "reducir movimiento" en su sistema no quiere la patita moviéndose
   sola, ni los paneles saltando, ni las huellas volando. Se apaga todo: las
   animaciones no llevan información, solo adorno. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ---------- Panel de temas ---------- */
.theme-panel {
  position: absolute;
  top: 62px;
  right: 18px;
  z-index: 50;
  background: var(--panel);
  border-radius: 16px;
  padding: 14px;
  box-shadow: 0 10px 30px var(--shadow);
  animation: pop-in 0.22s ease;
  max-height: min(72vh, 560px);
  overflow-y: auto;
  /* El panel se ajustaba al contenido sin tope, así que la etiqueta más larga
     decidía su ancho: con "Leopardo de las nieves" se iba a más de 400 px y en
     la ventana por defecto (426 px de CSS) quedaba pegado al borde izquierdo;
     en un móvil de 360 se salía. Con tope, el nombre largo parte en dos
     líneas, que es justo lo que debe ceder. */
  width: max-content;
  max-width: min(340px, calc(100vw - 36px));
}
/* Sin esto el texto no parte: una celda de rejilla no baja de su contenido */
.theme-grid > * { min-width: 0; }

:root[data-theme="noche"] .theme-panel { color: #e2f8fd; }

@keyframes pop-in {
  from { opacity: 0; transform: translateY(-8px) scale(0.95); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

.theme-title {
  font-size: 13px;
  font-weight: 700;
  margin-bottom: 10px;
  text-align: center;
}

.theme-title.sub { margin-top: 14px; }

.theme-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}

.theme-swatch,
.fur-swatch,
/* Los botones de idioma comparten el aspecto de los atuendos */
.outfit-swatch,
.lang-swatch {
  display: flex;
  align-items: center;
  gap: 8px;
  border: 2px solid transparent;
  border-radius: 10px;
  background: transparent;
  color: inherit;
  padding: 7px 12px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s ease;
}

.theme-swatch:hover,
.fur-swatch:hover,
.outfit-swatch:hover,
.lang-swatch:hover { background: rgba(127, 127, 127, 0.12); }
.theme-swatch.active,
.fur-swatch.active,
.outfit-swatch.active,
.lang-swatch.active { border-color: var(--accent); }

.mini {
  width: 18px;
  font-size: 15px;
  text-align: center;
  display: inline-block;
}

/* ---------- Atuendos del gato ---------- */
.outfit { display: none; }
:root[data-outfit="ninja"] #outfit-ninja,
:root[data-outfit="ninja"] #outfit-ninja-paws,
:root[data-outfit="futbol"] #outfit-futbol,
:root[data-outfit="futbol"] #outfit-futbol-ball,
:root[data-outfit="pirata"] #outfit-pirata,
:root[data-outfit="pirata"] #outfit-pirata-paws,
:root[data-outfit="mago"] #outfit-mago,
:root[data-outfit="mago"] #outfit-mago-paws,
:root[data-outfit="capucha"] #outfit-capucha,
:root[data-outfit="capucha"] #outfit-capucha-extra { display: block; }

/* El pirata cambia SOLO la patita izquierda por la pata de palo (la derecha
   sigue siendo patita normal); si no, la pata de palo quedaría encima de ella */
:root[data-outfit="pirata"] #paws .paw:nth-child(1) { display: none; }

.dot {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  display: inline-block;
  box-shadow: inset 0 0 0 2px rgba(0,0,0,0.12);
}

.dot-cian     { background: #22d3ee; }
.dot-rosa     { background: #ec4899; }
.dot-menta    { background: #10b981; }
.dot-lavanda  { background: #8b5cf6; }
.dot-atigrado { background: #f97316; }
.dot-noche    { background: #0f172a; }

.dot-carbon  { background: #3a3942; }
.dot-naranja { background: #e8913a; }
.dot-gris    { background: #8a8e9b; }
.dot-negro   { background: #16151a; }
.dot-blanco  { background: #ffffff; }

/* ---------- Escena del gato ---------- */
.cat-scene {
  position: relative;
  display: flex;
  justify-content: center;
  margin-bottom: -26px;
  z-index: 2;
}

#cat {
  width: 210px;
  height: 143px;
  filter: drop-shadow(0 4px 6px rgba(0,0,0,0.18));
}

#cat-head {
  transform-origin: 110px 90px;
  animation: head-bob 5s ease-in-out infinite;
}

@keyframes head-bob {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  30% { transform: translateY(-2px) rotate(-1.2deg); }
  65% { transform: translateY(1px) rotate(1.2deg); }
}

#tail {
  transform-origin: 197px 148px;
  animation: tail-swing 3.2s ease-in-out infinite;
}

@keyframes tail-swing {
  0%, 100% { transform: rotate(0deg); }
  50% { transform: rotate(10deg); }
}

.ear { transform-origin: center 45px; transition: transform 0.25s ease; }

#cat.mood-angry #ear-left  { transform: rotate(-22deg) translateY(4px); }
#cat.mood-angry #ear-right { transform: rotate(22deg) translateY(4px); }
#cat.mood-angry #tail { animation-duration: 0.5s; }

#cat.mood-surprised .pupil { rx: 9; ry: 11; }
#cat.mood-happy .pupil { ry: 12; }

.eye { transition: transform 0.1s linear; }

#cat.blinking .eye-part,
#cat.mood-sleep .eye-part {
  transform: scaleY(0.06);
  transform-origin: center;
  transform-box: fill-box;
}

.hidden-part { opacity: 0; transition: opacity 0.3s ease; }
#cat.mood-angry #angry-brows { opacity: 1; }
#cat.mood-sleep #zzz { opacity: 1; }

#cat.mood-sleep #cat-head { animation: sleep-breathe 3s ease-in-out infinite; }

@keyframes sleep-breathe {
  0%, 100% { transform: translateY(0) scale(1); }
  50% { transform: translateY(2px) scale(1.015); }
}

.paw { animation: paw-tap 6s ease-in-out infinite; }
.paw:nth-child(2) { animation-delay: 3s; }

@keyframes paw-tap {
  0%, 92%, 100% { transform: translateY(0); }
  95% { transform: translateY(-5px); }
}

/* ---------- Burbuja de diálogo ---------- */
.speech {
  position: absolute;
  top: -6px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--bubble-bg);
  color: #111;
  border-radius: 14px;
  padding: 8px 14px;
  font-size: 13.5px;
  font-weight: 600;
  box-shadow: 0 6px 18px var(--shadow);
  white-space: nowrap;
  z-index: 10;
  opacity: 1;
  transition: opacity 0.35s ease, transform 0.35s ease;
}

.speech::after {
  content: "";
  position: absolute;
  bottom: -7px;
  left: 50%;
  transform: translateX(-50%);
  border-left: 8px solid transparent;
  border-right: 8px solid transparent;
  border-top: 8px solid var(--bubble-bg);
}

.speech.hidden {
  opacity: 0;
  transform: translateX(-50%) translateY(6px);
  pointer-events: none;
}

.theme-panel.hidden { display: none; }

/* ---------- Paneles laterales: historial y conversor ---------- */
.side-panel {
  position: absolute;
  top: 62px;
  right: 18px;
  z-index: 50;
  width: min(320px, calc(100vw - 36px));
  background: var(--panel);
  border-radius: 16px;
  padding: 14px;
  box-shadow: 0 10px 30px var(--shadow);
  animation: pop-in 0.22s ease;
  max-height: min(72vh, 560px);
  overflow-y: auto;
}
:root[data-theme="noche"] .side-panel { color: #e2f8fd; }
.side-panel.hidden { display: none; }

/* En pantallas anchas (escritorio) los paneles se abren al costado de la app,
   sin tapar al gato ni a la pantalla; en angostas caen encima, como siempre. */
@media (min-width: 1140px) {
  .theme-panel,
  .side-panel { right: auto; left: calc(100% + 14px); }
}

.history-list { display: flex; flex-direction: column; gap: 4px; }

.history-item {
  border: none;
  background: transparent;
  border-radius: 10px;
  padding: 7px 10px;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 10px;
  cursor: pointer;
  color: inherit;
  font-size: 13.5px;
  font-weight: 600;
}
.history-item:hover { background: rgba(127, 127, 127, 0.12); }

.history-expr {
  opacity: 0.6;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.history-res { font-weight: 800; white-space: nowrap; }

.history-empty {
  font-size: 13px;
  opacity: 0.65;
  text-align: center;
  padding: 8px 0;
}

.panel-action {
  margin-top: 10px;
  width: 100%;
  border: none;
  border-radius: 10px;
  background: var(--accent);
  color: #fff;
  font-weight: 700;
  font-size: 13px;
  padding: 8px;
  cursor: pointer;
}
.panel-action:active { transform: scale(0.97); }

.conv-input,
.conv-select {
  width: 100%;
  border: 2px solid rgba(127, 127, 127, 0.25);
  border-radius: 10px;
  padding: 7px 9px;
  font-size: 14px;
  font-weight: 600;
  font-family: inherit;
  background: var(--display-bg);
  color: var(--text);
  margin-bottom: 8px;
}
.conv-row { display: flex; gap: 6px; align-items: center; }
.conv-row .conv-select { margin-bottom: 0; min-width: 0; }

.conv-swap {
  border: none;
  background: var(--accent);
  color: #fff;
  border-radius: 10px;
  width: 34px;
  height: 34px;
  flex: 0 0 auto;
  font-size: 16px;
  cursor: pointer;
}
.conv-swap:active { transform: scale(0.92); }

.conv-result {
  margin-top: 10px;
  font-size: 15px;
  font-weight: 800;
  text-align: center;
  min-height: 20px;
  overflow-wrap: break-word;
}

/* ---------- Modo compras ---------- */
.shop-row {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 6px;
  font-size: 13px;
  font-weight: 700;
}
.shop-name {
  flex: 0 0 72px;
  opacity: 0.75;
}
.shop-unit { opacity: 0.6; font-size: 12px; }
.shop-pct {
  width: 54px;
  border: 2px solid rgba(127, 127, 127, 0.25);
  border-radius: 8px;
  padding: 4px 6px;
  font-family: inherit;
  font-size: 13px;
  font-weight: 700;
  background: var(--display-bg);
  color: var(--text);
  text-align: center;
}
.shop-pct.wide { width: 84px; }
.shop-res {
  flex: 1;
  min-width: 0;
  border: none;
  border-radius: 8px;
  background: rgba(127, 127, 127, 0.14);
  color: inherit;
  font-family: inherit;
  font-size: 13px;
  font-weight: 800;
  padding: 5px 8px;
  cursor: pointer;
  text-align: right;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.shop-res:hover { background: var(--accent); color: #fff; }

/* Conversor de divisas dentro del Modo compras (estilo Google Translate) */
.shop-conv-row { margin-bottom: 8px; }
.shop-conv-row .conv-select { flex: 1; }
.shop-conv-res {
  display: block;
  width: 100%;
  text-align: center;
  font-size: 15px;
  padding: 9px 8px;
  margin-bottom: 4px;
}
.shop-rate-row {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0 0 8px;
  font-size: 13px;
  font-weight: 700;
}
.shop-rate-label { flex: 0 0 auto; opacity: 0.7; }
.shop-rate-code { flex: 1; opacity: 0.65; font-size: 12px; }
.shop-note {
  font-size: 11px;
  opacity: 0.6;
  text-align: center;
  margin-top: 8px;
  line-height: 1.45;
}

/* ---------- Bloc de notas ---------- */
.notes-textarea {
  width: 100%;
  min-height: 200px;
  resize: none;
  border: 2px solid rgba(127, 127, 127, 0.25);
  border-radius: 10px;
  padding: 9px 10px;
  font-family: inherit;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.45;
  background: var(--display-bg);
  color: var(--text);
}
.notes-row { display: flex; gap: 8px; }
.notes-row .panel-action { flex: 1; width: auto; }
.panel-action.secondary {
  background: rgba(127, 127, 127, 0.3);
  color: inherit;
}
.ctrl-btn.active {
  background: var(--accent);
  color: #fff;
}

/* Botón de modo activo (quiz) y ayudas de copiado */
.icon-btn.active { background: var(--accent); }
.result { cursor: pointer; }
.copy-helper { position: fixed; left: -9999px; top: 0; }

/* ---------- Cursor de edición ----------
   Es un <span> SIN texto: la raya la pinta el fondo. Importa porque fitResult()
   decide el tamaño de letra midiendo la longitud del contenido, y un cursor
   hecho con un carácter (│ o |) engordaba la cuenta y encogía los números. */
.caret {
  display: inline-block;
  width: 2px;
  height: 0.92em;
  vertical-align: -0.1em;
  margin: 0 1px;
  background: var(--accent);
  animation: parpadeo 1.05s step-end infinite;
}
@keyframes parpadeo {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0; }
}
/* Un cursor parpadeando es justo lo que molesta a quien pide menos movimiento;
   se queda fijo, que sigue marcando el sitio igual de bien. */
@media (prefers-reduced-motion: reduce) {
  .caret { animation: none; }
}
/* Cada pulsación es su propio trozo para poder tocarla, pero tiene que leerse
   como texto corrido: sin esto los espacios de ' mod ' se colapsaban. */
.tok { white-space: pre; }

/* Partes decorativas del gato que no deben robarle el clic al SVG. Vive aquí y
   no en un style="" porque la CSP de la página no permite estilos en línea: los
   descartaba en silencio. */
.sin-raton { pointer-events: none; }

/* ---------- Pantalla ---------- */
.display {
  position: relative;
  z-index: 1;
  background: var(--display-bg);
  border-radius: 20px;
  padding: 30px 20px 14px;
  box-shadow: 0 8px 24px var(--shadow), inset 0 2px 6px rgba(0,0,0,0.06);
  text-align: right;
  transition: background 0.4s ease;
}

.expression {
  min-height: 22px;
  font-size: 16px;
  font-weight: 600;
  color: var(--text);
  opacity: 0.55;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.result {
  font-size: 46px;
  font-weight: 800;
  color: var(--text);
  line-height: 1.15;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  transition: font-size 0.15s ease;
}

/* El resultado se copia al tocarlo, así que también tiene que poder recibir el
   foco del teclado y verse cuando lo tiene. */
.result:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 4px;
  border-radius: 8px;
}

.result.small { font-size: 33px; }
.result.tiny  { font-size: 25px; }

.result.pop { animation: result-pop 0.3s ease; }

/* Botón para alternar resultado decimal ↔ fracción */
.frac-chip {
  position: absolute;
  left: 12px;
  bottom: 12px;
  border: 2px solid var(--accent);
  border-radius: 12px;
  padding: 3px 10px;
  font-size: 15px;
  font-weight: 800;
  color: var(--accent);
  background: transparent;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease, transform 0.1s ease;
}
.frac-chip:active { transform: scale(0.92); }
.frac-chip.hidden { display: none; }
.frac-chip.active {
  background: var(--accent);
  color: #fff;
}

@keyframes result-pop {
  0% { transform: scale(1); }
  40% { transform: scale(1.06); }
  100% { transform: scale(1); }
}

/* ---------- Controles ---------- */
.calc-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  padding: 10px 2px 2px;
}

.ctrl-btn {
  border: none;
  border-radius: 12px;
  background: var(--key-fn-bg);
  color: var(--text);
  font-family: inherit;
  font-size: 13px;
  font-weight: 700;
  padding: 7px 12px;
  cursor: pointer;
  box-shadow: 0 3px 8px var(--shadow);
  transition: background 0.15s ease, transform 0.08s ease;
}
.ctrl-btn:hover { background: var(--key-fn-hover); }
.ctrl-btn:active { transform: scale(0.95); }
#btn-angle { min-width: 54px; }

.mem-chip {
  margin-left: auto;
  font-size: 12px;
  font-weight: 800;
  color: #fff;
  background: var(--accent);
  width: 22px;
  height: 22px;
  line-height: 22px;
  text-align: center;
  border-radius: 50%;
  opacity: 0;
  transition: opacity 0.2s ease;
}
.mem-chip.on { opacity: 1; }

/* ---------- Área de teclado ---------- */
.pad-wrap {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding-top: 10px;
  overflow-y: auto;
}

/* ---------- Teclado científico ---------- */
.sci-pad {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 7px;
  flex: 0 0 auto;
}
.sci-pad.hidden { display: none; }

.skey {
  border: none;
  border-radius: 12px;
  background: var(--key-fn-bg);
  color: var(--text);
  font-family: inherit;
  font-size: 15px;
  font-weight: 700;
  padding: 12px 2px;
  cursor: pointer;
  box-shadow: 0 3px 7px var(--shadow);
  transition: background 0.15s ease, transform 0.08s ease;
}
.skey:hover { background: var(--key-fn-hover); }
.skey:active, .skey.pressed { transform: scale(0.93); }
.skey.mem { background: var(--key-op-bg); font-size: 14px; }
.skey.mem:hover { background: var(--key-op-hover); }
#btn-2nd { background: var(--key-op-bg); }
#btn-2nd.active { background: var(--key-eq-bg); color: #fff; }

/* En modo científico el gato ocupa menos alto */
#app.sci-on #cat { width: 150px; height: 102px; }
#app.sci-on .cat-scene { margin-bottom: -20px; }

/* ---------- Teclado ---------- */
.keypad {
  flex: 1 0 auto;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(5, minmax(46px, 1fr));
  gap: 10px;
  min-height: 0;
}

.key {
  border: none;
  border-radius: 16px;
  background: var(--key-bg);
  color: var(--text);
  font-size: 24px;
  font-weight: 700;
  font-family: inherit;
  cursor: pointer;
  box-shadow: 0 4px 10px var(--shadow);
  transition: background 0.15s ease, transform 0.08s ease;
}

.key:hover { background: var(--key-hover); }
.key:active, .key.pressed { transform: scale(0.93); }

.key-op { background: var(--key-op-bg); }
.key-op:hover { background: var(--key-op-hover); }

.key-fn { background: var(--key-fn-bg); font-size: 21px; }
.key-fn:hover { background: var(--key-fn-hover); }

.key-eq { background: var(--key-eq-bg); font-size: 28px; }
.key-eq:hover { background: var(--key-eq-hover); }

/* ---------- Huellitas ---------- */
.paw-print {
  position: fixed;
  font-size: 26px;
  z-index: 100;
  pointer-events: none;
  animation: paw-walk 1.6s ease-out forwards;
}

@keyframes paw-walk {
  0%   { opacity: 0; transform: translateY(0) rotate(-20deg) scale(0.6); }
  15%  { opacity: 0.9; }
  100% { opacity: 0; transform: translateY(-90px) rotate(15deg) scale(1.1); }
}

/* ---------- Pie ---------- */
.footer {
  text-align: center;
  font-size: 11.5px;
  opacity: 0.65;
  padding: 8px 0 2px;
  color: var(--text);
}

/* Cuándo se actualizó una tasa de cambio. En gris es un dato de fondo; cuando
   pasa de dos meses se pone ámbar, porque ahí deja de ser una aproximación
   razonable y empieza a dar números equivocados. */
.shop-rate-edad {
  font-size: 11px;
  opacity: 0.6;
  margin: -4px 0 8px 2px;
  color: var(--text);
}

.shop-rate-edad.vieja {
  opacity: 1;
  font-weight: 700;
  color: #b45309;
}

:root[data-theme="noche"] .shop-rate-edad.vieja { color: #fbbf24; }


/* ---------- Otros felinos ----------
   Van dentro del mismo selector de pelaje (data-fur) en vez de crear una
   dimensión aparte: no existe un "leopardo de las nieves naranja", así que
   multiplicar colores por especies solo daría combinaciones absurdas.

   Cada especie trae su paleta y enciende su propia capa de dibujo. El volumen
   lo siguen poniendo los gradientes neutros de siempre, así que no hace falta
   definir luces y sombras por especie. */
.especie { display: none; }

:root[data-fur="leon"] {
  --fur: #d9a45f;
  --fur-line: #7c4d17;
  --whisker: #fff6e6;
  --ear-inner: #b06a3c;
  --melena: #a2651f;
  --melena-clara: #c58a33;
  --melena-oscura: #6f3f0e;
  --hocico: #f2dcb4;
  --nariz-leon: #7d4a33;
}
:root[data-fur="leon"] #especie-leon,
:root[data-fur="leon"] #leon-cara { display: block; }
/* El león trae su propia nariz, ancha y oscura */
:root[data-fur="leon"] .nariz { display: none; }
/* Los felinos grandes traen orejas redondas, así que las del gato sobran */
:root[data-fur="leon"] #orejas-redondas,
:root[data-fur="tigre"] #orejas-redondas { display: block; }
:root[data-fur="leon"] #ear-left,
:root[data-fur="leon"] #ear-right,
:root[data-fur="tigre"] #ear-left,
:root[data-fur="tigre"] #ear-right { display: none; }

/* El tigre. Naranja fuerte, rayas casi negras y todo lo pálido en el mismo
   crema: hocico, parches de los ojos y gorguera. */
:root[data-fur="tigre"] {
  --fur: #e79233;
  --fur-line: #4e2a0c;
  --whisker: #fffdf6;
  --ear-inner: #4a2c1a;
  --raya: #2a1a0d;
  --hocico: #fdf4e4;
  --nariz-tigre: #d98a78;
}
:root[data-fur="tigre"] #tigre-atras,
:root[data-fur="tigre"] #tigre-base,
:root[data-fur="tigre"] #tigre-cara { display: block; }
/* El tigre trae su propia nariz, ancha y asalmonada */
:root[data-fur="tigre"] .nariz { display: none; }

/* ---------- Los cuatro manchados ----------
   Comparten la base pálida, la nariz y las orejas redondas; lo único propio de
   cada uno son sus manchas y sus colores. Se agrupan los selectores en vez de
   repetir cuatro bloques iguales: cuando se añada un quinto, se toca una lista
   y no cuatro sitios. */
:root[data-fur="leopardo"] #manchado-base,
:root[data-fur="jaguar"] #manchado-base,
:root[data-fur="guepardo"] #manchado-base,
:root[data-fur="nieves"] #manchado-base,
:root[data-fur="leopardo"] #manchado-nariz,
:root[data-fur="jaguar"] #manchado-nariz,
:root[data-fur="guepardo"] #manchado-nariz,
:root[data-fur="nieves"] #manchado-nariz,
:root[data-fur="leopardo"] #leopardo-cara,
:root[data-fur="jaguar"] #jaguar-cara,
:root[data-fur="guepardo"] #guepardo-cara,
:root[data-fur="nieves"] #nieves-cara,
:root[data-fur="nieves"] #nieves-atras { display: block; }

/* Los cuatro traen nariz propia, así que la rosada del gato sobra */
:root[data-fur="leopardo"] .nariz,
:root[data-fur="jaguar"] .nariz,
:root[data-fur="guepardo"] .nariz,
:root[data-fur="nieves"] .nariz { display: none; }

/* Y orejas redondas, como el león y el tigre */
:root[data-fur="leopardo"] #orejas-redondas,
:root[data-fur="jaguar"] #orejas-redondas,
:root[data-fur="guepardo"] #orejas-redondas,
:root[data-fur="nieves"] #orejas-redondas { display: block; }
:root[data-fur="leopardo"] #ear-left,
:root[data-fur="leopardo"] #ear-right,
:root[data-fur="jaguar"] #ear-left,
:root[data-fur="jaguar"] #ear-right,
:root[data-fur="guepardo"] #ear-left,
:root[data-fur="guepardo"] #ear-right,
:root[data-fur="nieves"] #ear-left,
:root[data-fur="nieves"] #ear-right { display: none; }

/* Leopardo: oro cálido y rosetas casi negras */
:root[data-fur="leopardo"] {
  --fur: #dfa94e;
  --fur-line: #5a3a12;
  --whisker: #fff6e2;
  --ear-inner: #6b4420;
  --mancha: #2e2113;
  --hocico: #f7e9cd;
  --nariz-manchado: #c98a80;
}

/* Jaguar: más rojizo y más macizo que el leopardo, que es justo la diferencia
   que se ve de lejos entre los dos */
:root[data-fur="jaguar"] {
  --fur: #d99038;
  --fur-line: #4d2f0f;
  --whisker: #fff3dd;
  --ear-inner: #5c3418;
  --mancha: #241a0f;
  --hocico: #f6e4c2;
  --nariz-manchado: #9d6455;
}

/* Guepardo: arena clara, manchas puras y la lágrima negra */
:root[data-fur="guepardo"] {
  --fur: #e2bd74;
  --fur-line: #6a4b22;
  --whisker: #fffaf0;
  --ear-inner: #7d5a2c;
  --mancha: #22190e;
  --lagrima: #1b140b;
  --hocico: #fbf1dc;
  --nariz-manchado: #6f4c3d;
}

/* Leopardo de las nieves: casi sin color. Es el único de los cuatro que no es
   dorado, así que se distingue antes por el gris que por las manchas. */
:root[data-fur="nieves"] {
  --fur: #d9dae2;
  --fur-line: #4a4c57;
  --whisker: #ffffff;
  --ear-inner: #9a9cab;
  --mancha: #3b3d49;
  --hocico: #f7f8fb;
  --nariz-manchado: #7d6f74;
}

.dot-leon { background: linear-gradient(135deg, #d9a45f 55%, #a2651f 55%); }
.dot-tigre { background: repeating-linear-gradient(115deg, #e79233 0 4px, #2a1a0d 4px 6px); }
/* Los puntos del selector imitan la marca de cada uno: anillo, anillo con
   punto, mancha llena y mancha gris difusa. */
.dot-leopardo {
  background: #dfa94e;
  box-shadow: inset 0 0 0 2px #2e2113, inset 0 0 0 4px #dfa94e;
}
.dot-jaguar {
  background: radial-gradient(circle at 50% 50%, #241a0f 0 1.5px, #d99038 1.5px);
  box-shadow: inset 0 0 0 2px #241a0f, inset 0 0 0 4px #d99038;
}
.dot-guepardo {
  background: radial-gradient(circle at 50% 50%, #22190e 0 3.5px, #e2bd74 3.5px);
}
.dot-nieves {
  background: radial-gradient(circle at 50% 50%, #3b3d49 0 2px, #d9dae2 2px);
  box-shadow: inset 0 0 0 2px #3b3d49aa;
}

/* ---------- Pantalla de poca altura ----------
   Teléfono girado, ventana chica, pantalla dividida. Con 360 px de alto el
   gato, la pantalla y las pestañas se comían todo y el teclado numérico quedaba
   fuera de la vista: .pad-wrap tiene su propio scroll, pero con casi cero
   píxeles de alto no había nada que rodar. Aquí el gato es quien cede — encoge
   a la mitad y el resto se aprieta a su alrededor.

   Va al final del archivo A PROPÓSITO: son selectores de la misma especificidad
   que los que corrige (#cat, .display, .result), así que solo ganan si aparecen
   después. Puesta arriba con las otras media queries no hacía absolutamente
   nada, que fue justo lo que pasó al primer intento. */
@media (max-height: 520px) {
  #app {
    padding-top: calc(4px + env(safe-area-inset-top));
    padding-bottom: calc(4px + env(safe-area-inset-bottom));
  }
  .topbar { padding: 0 4px; }
  .icon-btn { width: 30px; height: 30px; font-size: 15px; border-radius: 9px; }
  #cat { width: 104px; height: 71px; }
  .cat-scene { margin-bottom: -10px; }
  .display { padding: 12px 16px 8px; border-radius: 14px; }
  .expression { min-height: 15px; font-size: 13px; }
  .result { font-size: 30px; }
  .result.small { font-size: 24px; }
  .result.tiny  { font-size: 19px; }
  .pad-wrap { padding-top: 6px; gap: 7px; }
  .keypad { grid-template-rows: repeat(5, minmax(38px, 1fr)); gap: 7px; }
  .footer { display: none; }         /* el pie es adorno; el teclado no */
}

/* ---------- Horizontal: dos columnas ----------
   Girando el móvil se pierde alto y se gana el doble de ancho. Con una sola
   columna de 460px eso significaba media pantalla vacía a cada lado mientras
   el teclado se aplastaba hasta ser incómodo de usar.

   En dos columnas cabe todo sin encoger nada: la cuenta a la izquierda, las
   teclas a la derecha, y cada pulgar con lo suyo cerca. Vale igual para la
   tablet en horizontal y para la ventana de escritorio estirada. El móvil de
   pie y la ventana estrecha no se enteran: nada de esto les aplica.

   Va al final del archivo a propósito, para pisar a las dos reglas de arriba
   con las que se solapa (la de min-width:1140px y la de max-height:520px). */
@media (orientation: landscape) and (min-width: 600px) {
  #app {
    max-width: 940px;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-rows: auto auto auto minmax(0, 1fr);
    column-gap: 18px;
  }
  .topbar        { grid-column: 1 / -1; grid-row: 1; }
  .cat-scene     { grid-column: 1; grid-row: 2; }
  .display       { grid-column: 1; grid-row: 3; }
  .calc-controls { grid-column: 1; grid-row: 4; align-self: start; }
  .pad-wrap      { grid-column: 2; grid-row: 2 / -1; padding-top: 0; }
  .footer        { display: none; }  /* aquí el pie solo le robaría alto a las teclas */

  /* En la columna izquierda sobra alto, así que el gato puede volver a
     respirar: la regla de pantallas bajas lo encoge a 104px porque allí compite
     con el teclado, y aquí ya no compite con nada.

     Pero se mide contra SU columna y no en píxeles fijos: con la científica
     abierta en una ventana de 640 esa columna baja de 200px, y un gato de 132
     le plantaba las patas encima de la vista previa. El alto va en auto para
     que el SVG conserve su proporción. */
  #cat { width: min(132px, 62%); height: auto; }
  .cat-scene { margin-bottom: -14px; }
  /* Hueco arriba para las patas, que asoman por el borde de la pantalla */
  .display { padding-top: 26px; }

  /* Teclas cómodas, pero con techo: en una tablet de 768 de alto, cinco filas a
     partes iguales salían de 141px cada una — botones de juguete. Con el tope
     puesto, el bloque se queda de tamaño humano y se centra en su columna.

     El height:100% no es decorativo y cuesta un párrafo explicarlo: en cuanto
     se pone align-self distinto de stretch, la casilla deja de imponer altura y
     el teclado pasa a medir por su contenido. Con filas de tope fijo eso
     significaba que cada una cogía su máximo SIEMPRE —86px— y las cinco se
     salían por abajo de una pantalla de 390. Con height:100% la altura vuelve a
     ser la de la casilla, las filas en fr se reparten lo que hay, y el
     max-height es el que pone el techo en pantallas altas. */
  .keypad {
    grid-template-rows: repeat(5, minmax(40px, 1fr));
    align-self: center;
    height: 100%;
    max-height: 520px;
  }

  /* Los paneles vuelven a abrirse DENTRO de la app. Con la ventana ya en 940px
     no quedan 320px libres al costado, y la regla de min-width:1140px —pensada
     para la columna estrecha— los mandaba fuera de la pantalla. Y con tope de
     alto, que es justo lo que aquí escasea. */
  .theme-panel,
  .side-panel {
    left: auto;
    right: 18px;
    max-height: calc(100dvh - 80px);
    overflow-y: auto;
  }
}

/* Con la científica abierta son diez filas de teclas apiladas en una columna:
   en 390px de alto el '=' quedaba fuera de la pantalla.

   La salida es la misma que usan las calculadoras del sistema al girar el
   móvil: en vez de apilar, se abre una TERCERA columna. La cuenta a la
   izquierda, las funciones en medio, el teclado a la derecha, y todo del mismo
   tamaño que sin la científica.

   Para eso hay que deshacer la caja de .pad-wrap, y así sus dos hijos ascienden
   a casillas de la rejilla de #app. Envuelto en @supports porque
   display:contents no existe antes de Chrome 65 (el mínimo de la app es Android
   7, cuyo WebView original es más viejo, aunque se actualiza por su cuenta).
   Donde no esté, queda la regla de arriba: los dos teclados apilados en la
   columna derecha con su barra de desplazamiento. Más apretado, pero entero. */
@supports (display: contents) {
  @media (orientation: landscape) and (min-width: 600px) {
    .pad-wrap { display: contents; }
    .keypad  { grid-column: 2; grid-row: 2 / -1; }
    /* Oculta no ocupa casilla, así que sin científica el teclado se queda con
       la columna 2 y la rejilla sigue teniendo dos. */
    #sci-pad {
      grid-column: 2;
      grid-row: 2 / -1;
      align-self: center;
      height: 100%;
      max-height: 520px;
      grid-auto-rows: minmax(34px, 1fr);
    }
    #app.sci-on { grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.05fr) minmax(0, 1fr); }
    #app.sci-on .keypad { grid-column: 3; }
  }
}
