/* ============================================================
   CLOTH TO GO · components.css
   Header, catálogo, carrito, checkout, confirmación y toast
   ============================================================ */

/* ---- Iconos SVG en línea ----
   Sustituyen a los emojis. Heredan el color del contenedor (currentColor) y
   traen su tamaño en el atributo, así que NO se dimensionan con font-size.
   El vertical-align compensa que un SVG se asienta sobre la línea base y
   quedaría alto respecto al texto que acompaña. */
.ico { vertical-align: -.18em; flex: 0 0 auto; }
/* Dentro de un contenedor flex el vertical-align no aplica: ahí centra el flex. */
.ico-box { display: inline-flex; align-items: center; justify-content: center; }

/* ---- Header ---- */
header {
  padding: 38px 20px 14px;
  background: var(--bg);
  border-bottom: 1px solid var(--line);
  z-index: 30;
}
.brand {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.brand-id { display: flex; align-items: center; gap: 10px; min-width: 0; }

/* Logo de marca (img/logo.webp): ícono de camiseta, fondo transparente. */
.brand-logo { flex: 0 0 auto; display: grid; place-items: center; }
.brand-logo img { height: 38px; width: auto; display: block; }
.brand-text { min-width: 0; }
.brand h1 {
  font-size: 18px;
  margin: 0;
  letter-spacing: -.5px;
  font-weight: 800;
  line-height: 1.05;
  white-space: nowrap;        /* CLOTH TO GO siempre en una sola línea */
}
.brand h1 span { color: var(--accent); }
.tagline { font-size: 12px; color: var(--muted); margin-top: 2px; }

.brand-actions { display: flex; align-items: center; gap: 9px; flex: 0 0 auto; }
.icon-btn {
  background: var(--accent-soft);
  color: var(--accent);
  border: 1px solid var(--line);
  width: 44px; height: 44px;
  border-radius: 13px;
  font-size: 20px;          /* tamaño del emoji 📝 */
  cursor: pointer;
  display: grid;
  place-items: center;
  flex: 0 0 auto;
}
.icon-btn svg { width: 21px; height: 21px; }
.icon-btn:active { transform: scale(.96); }
/* Carrito: acción primaria del header → relleno vivo con realce. */
.cart-btn {
  position: relative;
  background: linear-gradient(135deg, var(--cta), var(--cta-strong));
  color: #fff;
  border: none;
  width: 46px; height: 46px;
  border-radius: 14px;
  cursor: pointer;
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  box-shadow: 0 6px 14px var(--cta-glow);
}
.cart-btn svg { width: 23px; height: 23px; }
.cart-btn:active { transform: scale(.96); }
.cart-badge {
  position: absolute;
  top: -6px; right: -6px;
  background: var(--danger);
  /* --bg invierte bien en ambos temas: en oscuro --danger es un salmón claro
     sobre el que el blanco no se leía. */
  color: var(--bg);
  font-size: 11px;
  font-weight: 700;
  min-width: 20px; height: 20px;
  border-radius: 10px;
  display: grid;
  place-items: center;
  padding: 0 5px;
  border: 2px solid var(--bg);
}
/* Sacudida al aterrizar una prenda. La animación se declara aquí y la clase la
   pone bumpBadge(): el badge cambia en una esquina que nadie mira mientras
   pulsa, y sin este acuse hubo quien pulsó dos veces creyendo que no pasó nada.
   El bloque de reduce-motion de base.css la desactiva por su cuenta. */
.cart-badge.bump { animation: badge-bump .42s cubic-bezier(.3,1.4,.5,1); }
@keyframes badge-bump {
  0%   { transform: scale(1); }
  35%  { transform: scale(1.45); }
  70%  { transform: scale(.92); }
  100% { transform: scale(1); }
}

/* Miniatura que vuela de la tarjeta al carrito al agregar una prenda.
   position:fixed y coordenadas de viewport: el fantasma sale del flujo para
   poder cruzar la página por encima de todo, sin desplazar nada a su paso.
   El gradiente de respaldo se ve solo cuando la prenda no tiene foto — un
   cuadro vacío volando parecería un error de carga. */
.fly-ghost {
  position: fixed;
  z-index: 120;
  pointer-events: none;
  border-radius: 14px;
  background: linear-gradient(135deg, var(--cta), var(--cta-strong));
  background-size: cover;
  background-position: center;
  box-shadow: 0 10px 26px rgba(0, 0, 0, .28);
}

/* ---- Barra de filtros/orden bajo las categorías ---- */
.cat-toolbar {
  display: flex;
  align-items: stretch;
  gap: 8px;
  margin-top: 10px;
}
.filter-toggle {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  background: var(--card);
  color: var(--ink);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 9px 14px;
  font-size: 13px;
  font-weight: 700;
  font-family: inherit;
  cursor: pointer;
  flex: 0 0 auto;
}
.filter-toggle svg { width: 16px; height: 16px; color: var(--accent); }
.filter-toggle:active { transform: scale(.98); }
.filter-count {
  background: var(--accent);
  color: var(--on-accent);
  font-size: 11px;
  font-weight: 800;
  min-width: 18px; height: 18px;
  border-radius: 9px;
  display: grid;
  place-items: center;
  padding: 0 4px;
}
.sort-inline {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 1;
  min-width: 0;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 0 12px 0 12px;
}
.sort-inline svg { width: 16px; height: 16px; color: var(--accent); flex: 0 0 auto; }
.sort-inline select {
  appearance: none; -webkit-appearance: none;
  width: 100%;
  border: none; background: var(--card); color: var(--ink);
  padding: 9px 18px 9px 0;
  font-size: 13px; font-family: inherit; font-weight: 600; cursor: pointer;
  background-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%237d8a76' stroke-width='3'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right center; background-size: 12px;
}
.sort-inline select:focus { outline: none; }
/* La lista desplegable la pinta el sistema, no el CSS del panel: hereda el
   fondo del <select>, y con `background: transparent` resolvía a blanco mientras
   el texto seguía siendo el `--ink` claro del tema oscuro → blanco sobre blanco.
   Solo se veía en escritorio; en la laptop el tema oscuro del sistema lo tapaba.
   Los <option> se pintan explícitos porque no heredan del padre en Windows. */
.sort-inline select option {
  background: var(--card);
  color: var(--ink);
}

/* ---- Filtros ---- */
.filters {
  display: flex;
  gap: 8px;
  margin-top: 14px;
  overflow-x: auto;
  padding-bottom: 2px;
  scrollbar-width: none;
}
.filters::-webkit-scrollbar { display: none; }
.chip {
  flex: 0 0 auto;
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--muted);
  padding: 7px 14px;
  border-radius: 20px;
  font-size: 13px;
  cursor: pointer;
  white-space: nowrap;
  font-weight: 600;
}
/* Inversión real: en claro queda oscuro con texto claro y en oscuro al revés,
   sin necesidad de una regla por tema. Antes era #fff fijo y en oscuro
   resultaba texto blanco sobre fondo claro. */
.chip.active {
  background: var(--ink);
  color: var(--bg);
  border-color: var(--ink);
}

/* ---- Panel de filtros (sheet) ----
   Grupos plegables propios en vez de <select>: el desplegable nativo no deja
   meter el medidor de calidad ni el punto de color dentro de un <option>. */
.filter-sheet { display: flex; flex-direction: column; gap: 10px; }
.fs-group {
  border: 1px solid var(--line); border-radius: 14px;
  background: var(--card); overflow: hidden;
}
.fs-head {
  width: 100%; display: flex; align-items: center; gap: 10px;
  background: none; border: none; color: var(--ink);
  padding: 13px 14px; font-family: inherit; font-size: 14px; cursor: pointer;
  text-align: left;
}
.fs-head-l { font-weight: 700; }
/* El valor vigente ocupa el hueco para quedar pegado a la flecha: el grupo
   cerrado tiene que decir qué filtra sin abrirlo. */
.fs-head-v {
  flex: 1; text-align: right; color: var(--muted);
  font-size: 13px; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.fs-group.open .fs-head-v { color: var(--accent); }
.fs-chev { display: flex; color: var(--muted); transition: transform .22s ease; }
.fs-group.open .fs-chev { transform: rotate(180deg); color: var(--accent); }
/* grid-template-rows 0fr→1fr: anima la apertura sin fijar una altura máxima a
   ojo, que es lo que rompe cuando un grupo crece (una talla nueva, un material
   nuevo). El hijo necesita overflow oculto para poder colapsar. */
.fs-opts { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .24s ease; }
.fs-group.open .fs-opts { grid-template-rows: 1fr; }
.fs-opts-in { overflow: hidden; display: flex; flex-direction: column; gap: 6px; padding: 0 10px; }
.fs-group.open .fs-opts-in { padding-bottom: 10px; }
.fs-hint { margin: 0 0 2px; padding: 0 4px; font-size: 11.5px; color: var(--muted); }

/* Opción de filtro. La fila entera es pulsable: en el móvil el objetivo real
   es el renglón, no las palabras. */
.fs-opt {
  display: flex; align-items: center; gap: 9px;
  border: 1px solid transparent; border-radius: 10px;
  background: var(--bg); color: var(--ink);
  padding: 10px 12px; font-family: inherit; font-size: 13.5px; font-weight: 600;
  cursor: pointer; text-align: left;
}
.fs-opt.sel { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); }
.fs-opt:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.fs-opt svg { color: var(--muted); flex: 0 0 auto; }
.fs-opt.sel svg { color: var(--accent); }
/* El texto empuja al medidor/conteo al otro extremo, y ambos quedan centrados
   con él en la misma línea base óptica. */
.fs-row .fs-opt-t { flex: 1; }
.fs-opt-n { font-size: 12px; color: var(--muted); font-weight: 600; }
.fs-opt.sel .fs-opt-n { color: var(--accent); }
.fs-row .qmeter { flex: 0 0 auto; }

/* Tallas: son etiquetas cortas, así que van en rejilla y no en filas sueltas. */
.fs-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.fs-chips .fs-opt { padding: 9px 14px; justify-content: center; }
/* Rótulo de escala dentro del grupo de talla (Ropa / Calzado): una talla de
   zapato y una de camisa no se comparan, y sin él la fila de números parecía
   la misma regla con un salto raro a la mitad. */
.fs-sub {
  margin: 4px 0 0; padding: 0 4px;
  font-size: 11.5px; font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: .04em;
}

/* Color: NO se pliega (catorce opciones), va en rejilla con la muestra a la
   izquierda de cada botón. */
.fs-static { padding: 12px 12px 12px; }
.fs-static-l { display: block; margin: 0 2px 9px; font-size: 14px; }
.fs-colors { display: grid; grid-template-columns: repeat(auto-fill, minmax(126px, 1fr)); gap: 6px; }
.fs-colors .fs-opt { gap: 7px; padding: 9px 10px; }
.fs-color .fs-opt-t { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Muestra del color en la ficha del detalle. Lleva borde y halo propios porque
   tiene que sobrevivir a los dos extremos de la paleta: sin ellos, el blanco
   desaparece sobre la tarjeta clara y el negro sobre la oscura.
   inline-block y no inline: un span en línea ignora width/height y la muestra
   se queda en una raya. */
.color-dot {
  display: inline-block;
  width: 13px; height: 13px; border-radius: 50%;
  border: 1px solid rgba(0, 0, 0, .22);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .35);
}
.filter-foot { display: flex; gap: 10px; align-items: stretch; }
.filter-foot .fs-apply { flex: 1; }
.fs-clear {
  flex: 0 0 auto;
  background: var(--accent-soft); color: var(--accent);
  border: none; border-radius: 14px; padding: 15px 18px;
  font-size: 15px; font-weight: 700; font-family: inherit; cursor: pointer;
}
.fs-clear:disabled { opacity: .5; cursor: not-allowed; }

/* ---- Catálogo ---- */
main {
  flex: 1;
  overflow-y: auto;
  padding: 16px 16px 100px;
  scrollbar-width: none;
}
main::-webkit-scrollbar { display: none; }

/* ---- Barra de resultados (conteo + limpiar filtros) ---- */
.results-bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; margin-bottom: 12px; min-height: 24px;
}
.results-count { font-size: 12px; color: var(--muted); font-weight: 700; }
.clear-filters {
  background: none; border: none; color: var(--accent);
  font-size: 12px; font-weight: 700; cursor: pointer; padding: 4px 2px;
}

.grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}
.card {
  background: var(--card);
  border-radius: 18px;
  overflow: hidden;
  box-shadow: 0 4px 14px rgba(0,0,0,.05);
  display: flex;
  flex-direction: column;
}
.thumb {
  height: 130px;
  position: relative;
  overflow: hidden;
}
/* ---- Placeholder de imagen ---- */
.img-ph {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  color: var(--accent);
  background-image:
    repeating-linear-gradient(45deg, rgba(63,125,58,.06) 0 10px, transparent 10px 20px);
}
.img-ph svg { width: 30px; height: 30px; opacity: .55; }
.img-ph .ph-txt { font-size: 10px; font-weight: 700; letter-spacing: .3px; opacity: .7; text-transform: uppercase; }
.thumb img, .ci-thumb img, .detail-img img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 1;
}
.cond-tag {
  position: absolute;
  top: 8px; left: 8px;
  background: rgba(255,255,255,.92);
  border-radius: 8px;
  padding: 3px 7px;
  font-size: 10px;
  font-weight: 700;
  /* Tinta fija, no var(--ink): la pastilla es blanca en ambos temas (va sobre
     la foto), y en oscuro --ink se vuelve clara → texto invisible. */
  color: #23301f;
}
/* ---- Prenda alquilada: sigue en el catálogo, pero apagada ----
   Antes desaparecía del grid, y con ella el escaparate: nadie podía verla ni
   volver a por ella, y el catálogo parecía más pequeño de lo que es. Ahora se
   queda al final, en gris. El estado se DERIVA de los pedidos (isRented), como
   siempre: al archivarse el pedido vuelve sola al frente. */
/* Solo `filter`, nunca `opacity`: el placeholder (.img-ph, con el icono y el
   nombre) vive DEBAJO de la foto, así que bajarle la opacidad a la imagen lo
   deja verse a través. El apagado se consigue desaturando y oscureciendo, con
   la foto opaca del todo. */
.card-off .thumb img { filter: grayscale(1) brightness(.62); }
.card-off .card-name,
.card-off .card-meta,
.card-off .price-row { opacity: .6; }
/* El medidor de calidad no se desatura: es un dato de la prenda, no de su
   disponibilidad, y en gris se confundiría con "calidad baja". */
/* Abajo a la izquierda: las otras dos esquinas ya están ocupadas por la
   condición (arriba izq.) y la talla (arriba der.). */
.off-tag {
  position: absolute;
  bottom: 8px; left: 8px;
  background: rgba(35,48,31,.92);
  color: #fff;
  border-radius: 8px;
  padding: 3px 7px;
  font-size: 10px;
  font-weight: 700;
}
.size-tag {
  position: absolute;
  top: 8px; right: 8px;
  background: rgba(31,42,28,.82);
  color: #fff;
  border-radius: 8px;
  padding: 3px 7px;
  font-size: 10px;
  font-weight: 700;
}
.card-body { padding: 11px 11px 12px; display: flex; flex-direction: column; gap: 5px; flex: 1; }
.card-name { font-size: 14px; font-weight: 700; line-height: 1.2; }
.card-meta {
  display: flex; align-items: center; gap: 5px; flex-wrap: wrap;
  font-size: 11px; color: var(--muted);
}
.card-meta .cm-dot { opacity: .6; }
.card-meta .cm-mat { color: var(--accent); font-weight: 700; }
/* Estrellas: reservadas para las reseñas de clientes (feature futura). */
.stars { font-size: 12px; letter-spacing: 1px; color: var(--star); }
.stars small { color: var(--muted); margin-left: 3px; letter-spacing: 0; }

/* ---- Medidor de calidad ----
   Cinco pastillas en vez de estrellas: la calidad la fija el negocio al
   catalogar la prenda, no los clientes, y con las reseñas en camino dibujar
   ambas cosas igual sería decir que son lo mismo. Un medidor lee como "nivel",
   que es exactamente lo que es. */
.qmeter { display: inline-flex; gap: 2px; vertical-align: middle; }
.qm-seg {
  width: 9px; height: 5px; border-radius: 2px;
  background: var(--line);
  /* La pastilla vacía necesita cuerpo propio: sin esto, en alto contraste
     desaparece y el medidor miente sobre el nivel. */
  box-shadow: inset 0 0 0 1px var(--line);
}
.qm-seg.on { background: var(--star); box-shadow: none; }
.quality, .detail-quality, .ci-quality { display: flex; align-items: center; gap: 6px; }
.quality { font-size: 12px; }
.quality small, .detail-quality small { color: var(--muted); letter-spacing: 0; }
.ci-quality { font-size: 11px; }
/* En el chip del detalle el medidor acompaña a "5/5", así que va algo mayor. */
.qm-fact { display: flex; align-items: center; gap: 6px; }
.qm-fact .qm-seg { width: 7px; height: 6px; }
/* El precio ya no es lineal por día, así que la tarjeta ancla en el primer día
   y deja el coste del día extra debajo, en vez de en la misma línea. */
.price-row {
  margin-top: auto;
  padding-top: 4px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1px;
}
.price-extra { font-size: 11px; color: var(--muted); font-weight: 600; }
.price { display: inline-flex; align-items: baseline; gap: 4px; }
.price .price-amt { font-size: 18px; font-weight: 800; color: var(--accent); letter-spacing: -.3px; }
.price .price-per { font-size: 11px; color: var(--muted); font-weight: 600; }
/* Acción primaria de la card: relleno vivo para destacar en el catálogo. */
.add-btn {
  background: linear-gradient(135deg, var(--cta), var(--cta-strong));
  color: #fff;
  border: none;
  border-radius: 11px;
  padding: 10px;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  margin-top: 9px;
  box-shadow: 0 4px 12px var(--cta-glow);
}
.add-btn:active { transform: scale(.97); }
/* Ya en el carrito: estado confirmado, secundario (no compite con "Alquilar"). */
.add-btn.in-cart {
  background: var(--accent-soft);
  color: var(--accent);
  box-shadow: none;
}
.add-btn:disabled {
  background: var(--disabled-bg);
  color: var(--disabled-ink);
  box-shadow: none;
  cursor: not-allowed;
}

/* ---- Panel deslizante (carrito / checkout) ---- */
.overlay {
  position: absolute;
  inset: 0;
  background: rgba(0,0,0,.45);
  opacity: 0;
  pointer-events: none;
  transition: opacity .25s;
  z-index: 40;
}
.overlay.show { opacity: 1; pointer-events: auto; }

.sheet {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  background: var(--bg);
  border-radius: 24px 24px 0 0;
  transform: translateY(100%);
  transition: transform .3s cubic-bezier(.4,0,.2,1);
  z-index: 50;
  max-height: 88%;
  display: flex;
  flex-direction: column;
}
.sheet.show { transform: translateY(0); }
/* Ventana completa (perfil y derivadas): ocupa todo, sin esquinas redondeadas
   ni asa, porque ya no es un panel que asoma sino una pantalla en la que uno
   se queda. Ver FULL_VIEWS en dom.js. */
.sheet.full { max-height: 100%; top: 0; border-radius: 0; }
.sheet.full .grip { display: none; }
/* Con top:0 el encabezado quedaría debajo de la muesca del mockup (26px,
   z-index 60): se baja el título para que no lo tape. */
.sheet.full .sheet-head { padding-top: 36px; }
/* Pestaña de detalle apilada: sube por encima del panel principal (50) con su
   propio overlay, que atenúa el perfil igual que el overlay base atenúa el
   home. Ver openStackSheet() en dom.js. Los selectores llevan la clase base
   (.overlay/.sheet) para ganar por especificidad y no por orden en el archivo:
   si no, mover este bloque devolvería el overlay a su z-index de siempre. */
.overlay.stack-overlay { z-index: 52; }
.sheet.stack { z-index: 55; }
.sheet-head {
  padding: 16px 20px 10px;
  border-bottom: 1px solid var(--line);
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.sheet-head h2 { margin: 0; font-size: 18px; }
.grip {
  width: 40px; height: 4px;
  background: var(--grip);
  border-radius: 4px;
  margin: 8px auto 0;
}
.close-x {
  background: none; border: none; font-size: 24px; color: var(--muted); cursor: pointer; line-height: 1;
}
.back-x {
  background: none; border: none; font-size: 22px; color: var(--muted);
  cursor: pointer; line-height: 1; padding: 0; width: 26px; height: 26px;
  display: grid; place-items: center;
}

/* ---- Formulario de tarjeta (pago) ---- */
.card-form { display: flex; flex-direction: column; gap: 12px; margin-bottom: 6px; }
.card-row { display: flex; gap: 10px; }
.card-row .pf-fld { flex: 1; }
.pay-note {
  font-size: 11px; color: var(--muted); line-height: 1.4;
  background: var(--accent-soft); border-radius: 8px; padding: 8px 10px; margin: 2px 0 0;
}
.sheet-body { overflow-y: auto; padding: 14px 18px; flex: 1; scrollbar-width: none; }
.sheet-body::-webkit-scrollbar { display: none; }

/* ---- Items del carrito ---- */
.cart-item {
  display: flex;
  gap: 12px;
  background: var(--card);
  border-radius: 14px;
  padding: 10px;
  margin-bottom: 10px;
  align-items: center;
}
.ci-thumb { width: 50px; height: 50px; border-radius: 10px; position: relative; overflow: hidden; flex: 0 0 auto; }
.ci-thumb .img-ph svg { width: 18px; height: 18px; }
.ci-thumb .img-ph .ph-txt { display: none; }
/* Miniaturas que abren el detalle de la prenda (pedidos del perfil). El propio
   data-action las distingue de las del carrito, que solo ilustran. */
.ci-thumb[data-action] { cursor: pointer; }
.ci-thumb[data-action]:active { transform: scale(.96); }
.ci-info { flex: 1; min-width: 0; }
.ci-name { font-size: 14px; font-weight: 700; }
.ci-meta { font-size: 11px; color: var(--muted); }
/* .ci-quality vive junto al resto del medidor, más arriba. */
.days-ctrl {
  display: flex;
  align-items: center;
  gap: 0;
  margin-top: 6px;
  background: var(--accent-soft);
  border-radius: 8px;
  width: fit-content;
  overflow: hidden;
}
.days-ctrl button {
  border: none; background: none; color: var(--accent);
  width: 26px; height: 26px; font-size: 16px; cursor: pointer; font-weight: 700;
}
.days-ctrl span { font-size: 12px; min-width: 54px; text-align: center; font-weight: 600; }
.ci-price { text-align: right; font-weight: 800; color: var(--accent); font-size: 14px; flex: 0 0 auto; }
.ci-remove { background: none; border: none; color: var(--danger); font-size: 11px; cursor: pointer; margin-top: 4px; padding: 0; }

.empty {
  text-align: center;
  color: var(--muted);
  padding: 50px 20px;
}
.empty .em { display: flex; justify-content: center; color: var(--line-strong, #c9bfb2); margin-bottom: 6px; }

/* ---- Entrega ---- */
.section-label { font-size: 13px; font-weight: 700; margin: 8px 0 8px; }
.delivery-opts { display: flex; flex-direction: column; gap: 10px; margin-bottom: 6px; }
.delivery-opt {
  border: 2px solid var(--line);
  background: var(--card);
  border-radius: 14px;
  padding: 12px 14px;
  cursor: pointer;
  display: flex;
  gap: 12px;
  align-items: flex-start;
}
.delivery-opt.active { border-color: var(--accent); background: var(--accent-soft); }
.do-icon { display: flex; align-items: center; color: var(--accent); flex: 0 0 auto; }
.do-text { flex: 1; }
.do-title { font-size: 14px; font-weight: 700; display: flex; justify-content: space-between; }
.do-desc { font-size: 11px; color: var(--muted); margin-top: 2px; }
.do-radio {
  width: 20px; height: 20px; border-radius: 50%;
  border: 2px solid var(--radio-line); flex: 0 0 auto; margin-top: 2px;
  display: grid; place-items: center;
}
.delivery-opt.active .do-radio { border-color: var(--accent); }
.delivery-opt.active .do-radio::after {
  content: ""; width: 10px; height: 10px; border-radius: 50%; background: var(--accent);
}
.pickup-detail, .ship-detail {
  font-size: 12px; color: var(--ink);
  background: var(--card); border-radius: 12px; padding: 12px 14px;
  margin: -2px 0 6px; border: 1px solid var(--line);
}
/* Detalle colgado de la opción elegida. Va sangrado y sin separación arriba
   para que se lea como parte de esa tarjeta y no como un bloque suelto: la
   pertenencia la dice la posición, no un rótulo. */
.opt-detail {
  margin: -4px 0 2px 12px;
  padding-left: 10px;
  border-left: 2px solid var(--accent);
}
.opt-detail .pickup-detail,
.opt-detail .ship-detail { margin: 0; }
.pickup-detail b { color: var(--accent); }
.ship-detail input {
  width: 100%; border: 1px solid var(--line); border-radius: 8px;
  padding: 9px 10px; font-size: 13px; margin-top: 6px; font-family: inherit;
}

/* ---- Resumen ---- */
.summary { background: var(--card); border-radius: 14px; padding: 12px 14px; margin-top: 6px; }
.summary-row { display: flex; justify-content: space-between; font-size: 13px; padding: 4px 0; color: var(--muted); }
.summary-row.total { color: var(--ink); font-weight: 800; font-size: 17px; border-top: 1px dashed var(--line); margin-top: 6px; padding-top: 10px; }
.summary-note { font-size: 11px; color: var(--muted); line-height: 1.4; margin: 8px 2px 0; }
/* Fila de total: el depósito reembolsable va pegado a la izquierda del monto,
   para que el número grande nunca se lea sin su contrapeso. */
.total-vals { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; justify-content: flex-end; }
.refund-inline {
  font-size: 11px; font-weight: 700; color: var(--accent);
  background: var(--accent-soft); border-radius: 20px; padding: 3px 8px;
  white-space: nowrap;
}
.total-amount { white-space: nowrap; }

/* ---- Foco visible (accesibilidad por teclado) ---- */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 6px;
}
.card-name[role="button"] { cursor: pointer; display: inline-block; }

.sheet-foot { padding: 12px 18px 20px; border-top: 1px solid var(--line); background: var(--bg); }
.pay-btn {
  width: 100%;
  background: linear-gradient(135deg, var(--cta), var(--cta-strong));
  color: #fff;
  border: none;
  border-radius: 14px;
  padding: 15px;
  font-size: 16px;
  font-weight: 700;
  cursor: pointer;
  box-shadow: 0 6px 16px var(--cta-glow);
}
.pay-btn:disabled { background: var(--disabled-bg); color: var(--disabled-ink); box-shadow: none; cursor: not-allowed; }
.pay-btn:active:not(:disabled) { transform: scale(.99); }
/* Acceso directo a "Mis pedidos" desde la confirmación (acción principal). */
.pay-btn.ver-pedidos { margin-top: 18px; }
/* "Volver al catálogo": acción secundaria, sin relleno de color. */
.pay-btn.ghost {
  background: none; color: var(--accent);
  box-shadow: none; border: 1px solid var(--line);
}

/* ---- Confirmación ---- */
.confirm { text-align: center; padding: 30px 20px; }
.confirm .big { display: flex; justify-content: center; color: var(--accent); margin-bottom: 4px; }
.confirm h2 { margin: 12px 0 6px; }
.confirm p { color: var(--muted); font-size: 13px; line-height: 1.5; }
.confirm .box {
  background: var(--card); border-radius: 14px; padding: 14px; margin: 16px 0; text-align: left; font-size: 13px;
}
.toast {
  position: absolute;
  bottom: calc(18px + env(safe-area-inset-bottom, 0px));
  left: 50%;
  transform: translateX(-50%) translateY(80px);
  background: var(--ink);
  color: var(--bg);
  padding: 11px 20px;
  border-radius: 30px;
  font-size: 13px;
  font-weight: 600;
  /* Por encima de la bienvenida (80). Estaba en 70 y quedaba DETRÁS de ella:
     un fallo de login en la pantalla de entrada no se veía en absoluto, que es
     el único sitio donde el toast es la última línea de defensa. Solo el modal
     (90) y el visor a pantalla completa (120) van por encima. */
  z-index: 85;
  opacity: 0;
  transition: all .3s;
  white-space: nowrap;
  max-width: calc(100% - 40px);
}
.toast.show { transform: translateX(-50%) translateY(0); opacity: 1; }

/* ---- Modal de confirmación in-app ---- */
.modal-overlay {
  position: absolute;
  inset: 0;
  background: rgba(0,0,0,.5);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 28px;
  z-index: 90;
  opacity: 0;
  pointer-events: none;
  transition: opacity .2s;
}
.modal-overlay.show { opacity: 1; pointer-events: auto; }
.modal {
  background: var(--card);
  border-radius: 20px;
  padding: 22px 20px 18px;
  width: 100%;
  max-width: 310px;
  box-shadow: 0 18px 40px rgba(0,0,0,.28);
  /* Sube unos píxeles al aparecer: da sensación de "emerge", no de "aparece". */
  transform: scale(.94) translateY(8px);
  transition: transform .22s cubic-bezier(.2,.9,.3,1.2);
}
.modal-overlay.show .modal { transform: scale(1) translateY(0); }
/* Icono dentro de un disco de color: ancla visual del diálogo. */
.modal-icon {
  width: 54px; height: 54px; margin: 0 auto 14px;
  display: flex; align-items: center; justify-content: center;
  line-height: 1; color: var(--accent);
  background: var(--accent-soft); border-radius: 50%;
}
.modal-icon.danger { background: var(--danger-soft); color: var(--danger); }
.modal-icon.tone-brown { background: #f0e7de; color: var(--ico-brown); }
.modal-title {
  margin: 0 0 6px; text-align: center;
  font-size: 17px; font-weight: 800; color: var(--ink);
}
.modal-text {
  font-size: 14px; line-height: 1.5; color: var(--ink);
  margin: 0 0 18px; white-space: pre-line;        /* respeta los saltos \n */
}
.modal-title + .modal-text { text-align: center; color: var(--muted); font-size: 13px; }

/* ---- Ficha de datos del modal ---- */
.modal-detail {
  background: var(--bg); border-radius: 14px;
  padding: 10px 12px; margin: 14px 0 18px;
}
.md-row {
  display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
  flex-wrap: wrap; padding: 5px 0; font-size: 12px;
}
.md-row + .md-row { border-top: 1px solid var(--line); }
.md-k { color: var(--muted); flex: 0 0 auto; }
/* Con varias prendas el valor puede ser largo: que baje a su propia línea en
   vez de partirse en una columna estrecha contra la etiqueta. */
.md-v { color: var(--ink); font-weight: 700; text-align: right; flex: 1 1 auto; min-width: 0; }
.md-refund {
  display: flex; justify-content: space-between; align-items: center; gap: 10px;
  margin-top: 8px; padding: 8px 10px;
  background: var(--accent-soft); border-radius: 10px;
  font-size: 12px; font-weight: 700; color: var(--accent);
}
.md-refund b { font-size: 14px; }
/* Reembolso $0: nada que devolver todavía. Gris neutro, no verde de "recibirás". */
.md-refund.zero { background: var(--card); color: var(--muted); border: 1px solid var(--line); }

/* Miniaturas de las prendas del pedido dentro del modal. */
.md-thumbs { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; padding: 4px 0 10px; }

/* ---- Resumen de confirmación del pedido ----
   Va dentro de .modal-detail, así que hereda su fondo y su caja. El depósito se
   separa de "Pagas ahora" y se repite abajo en verde: el total se lee caro
   porque lo incluye, y este es el último punto donde el cliente puede
   arrepentirse. */
.order-confirm { text-align: left; }
.oc-dates {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  font-size: 13px; color: var(--ink); padding-bottom: 8px;
}
.oc-days {
  margin-left: auto; font-size: 11px; font-weight: 700;
  background: var(--accent-soft); color: var(--accent);
  border-radius: 999px; padding: 2px 8px;
}
.oc-items { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--line); }
.oc-item {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 0; font-size: 12px;
}
.oc-item + .oc-item { border-top: 1px solid var(--line); }
/* La miniatura reusa .img-ph de imgPlaceholder(): se le fija caja y recorte
   aquí porque en la tarjeta del catálogo la hereda del contenedor. */
.oc-thumb {
  position: relative; flex: 0 0 auto; width: 34px; height: 34px;
  border-radius: 8px; overflow: hidden; background: var(--accent-soft);
}
.oc-thumb img { width: 100%; height: 100%; object-fit: cover; }
.oc-thumb .img-ph { position: absolute; inset: 0; }
.oc-thumb .ph-txt { display: none; }   /* no cabe en 34px: solo el icono */
.oc-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.oc-price { flex: 0 0 auto; font-weight: 700; }
.oc-rows { border-top: 1px solid var(--line); padding-top: 6px; margin-top: 2px; }
.oc-row { display: flex; justify-content: space-between; gap: 12px; padding: 3px 0; font-size: 12px; }
.oc-row span:first-child { color: var(--muted); }
.oc-row.discount span:last-child { color: var(--ok); font-weight: 700; }
.oc-row.pay {
  border-top: 1px solid var(--line); margin-top: 4px; padding-top: 7px;
  font-size: 14px; font-weight: 800;
}
.oc-row.pay span:first-child { color: var(--ink); }
.oc-refund {
  display: flex; align-items: center; gap: 6px; margin-top: 10px;
  background: var(--accent-soft); color: var(--accent);
  border-radius: 10px; padding: 8px 10px; font-size: 11px; font-weight: 600;
}

/* Oculta partes opcionales sin usar style.display inline, que rompería el
   layout (flex/grid) que cada una define en su propia regla. */
.is-hidden { display: none !important; }

.modal-actions { display: flex; gap: 10px; }
.modal-btn {
  flex: 1; border: none; border-radius: 12px;
  padding: 12px; font-size: 14px; font-weight: 700; cursor: pointer; font-family: inherit;
  transition: filter .15s;
}
.modal-btn.cancel { background: var(--accent-soft); color: var(--accent); }
.modal-btn.ok { background: var(--accent); color: var(--on-accent); }
.modal-btn.ok.danger { background: var(--danger); }
.modal-btn:hover { filter: brightness(1.06); }
.modal-btn:active { transform: scale(.98); }

/* ---- Bienvenida ---- */
.login {
  position: absolute;
  inset: 0;
  z-index: 80;
  background: linear-gradient(160deg, var(--welcome-from), var(--welcome-to));
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 26px;
  transition: opacity .3s, transform .3s;
  overflow: hidden;
}
/* Patrón de fondo: retícula diagonal + halos suaves, por encima del degradado. */
.login::before {
  content: "";
  position: absolute;
  inset: -20%;
  background:
    radial-gradient(circle at 20% 12%, var(--welcome-halo), transparent 45%),
    radial-gradient(circle at 85% 88%, var(--welcome-halo-soft), transparent 45%),
    repeating-linear-gradient(45deg, var(--welcome-grid) 0 2px, transparent 2px 14px),
    repeating-linear-gradient(-45deg, var(--welcome-grid) 0 2px, transparent 2px 14px);
  pointer-events: none;
}
.login.hide { opacity: 0; transform: translateY(-12px); pointer-events: none; }
.login-card {
  position: relative;
  background: var(--card);
  border-radius: 22px;
  padding: 30px 22px 26px;
  width: 100%;
  box-shadow: var(--shadow);
}
.login-mark {
  width: 84px; height: 84px;
  margin: 0 auto 14px;
  border-radius: 24px;
  background: var(--accent-soft);
  display: grid; place-items: center;
  box-shadow: 0 6px 18px rgba(31,42,28,.14);
}
.login-mark img { width: 62px; height: 62px; object-fit: contain; }
.login-logo { font-size: 26px; font-weight: 800; letter-spacing: -.5px; text-align: center; }
.login-logo span { color: var(--accent); }
.login-sub { text-align: center; color: var(--muted); font-size: 13px; margin: 4px 0 22px; }
.fld { display: block; font-size: 12px; font-weight: 700; color: var(--ink); margin-bottom: 12px; }
.fld input {
  display: block; width: 100%; margin-top: 5px;
  border: 1px solid var(--line); border-radius: 10px;
  padding: 11px 12px; font-size: 14px; font-family: inherit;
}
.fld input:focus { outline: none; border-color: var(--accent); }
/* Acción principal: entrar como invitado. */
.login-guest {
  width: 100%; border: none; border-radius: 14px;
  background: linear-gradient(180deg, var(--cta), var(--cta-strong));
  color: #fff; padding: 16px; font-size: 16px; font-weight: 800; letter-spacing: .2px;
  cursor: pointer; box-shadow: 0 8px 20px var(--cta-glow);
  transition: transform .15s, box-shadow .15s;
}
.login-guest:hover { transform: translateY(-1px); box-shadow: 0 10px 24px var(--cta-glow); }
.login-guest:active { transform: translateY(0); }
/* Botón de Google (lo inyecta GSI). Centrado; oculto por file:// vía [hidden]. */
.login-google { display: flex; justify-content: center; min-height: 40px; }
.login-google[hidden] { display: none; }
/* En oscuro, la variante personalizada del botón ("Iniciar sesión como …") la
   pinta el SDK dentro de su iframe y no respeta del todo el `filled_black` que
   le pasamos en renderGoogleButton(): deja un marco claro que en la tarjeta
   oscura se ve como un recuadro blanco pegado. No podemos tocar el contenido
   del iframe, así que se recorta desde fuera: el radio y el color de fondo son
   nuestros, y el marco del SDK queda dentro de ellos.
   Solo en oscuro — en claro el botón ya encaja tal cual viene. */
:root[data-theme="dark"] .login-google > div,
:root[data-theme="dark"] .login-google iframe {
  border-radius: 30px;
  background: transparent;
  color-scheme: dark;
}
/* Separador "o" entre el acceso de invitado y el login con Google. */
.login-sep {
  display: flex; align-items: center; gap: 10px;
  color: var(--muted); font-size: 12px; margin: 18px 0 16px;
}
.login-sep::before, .login-sep::after { content: ""; flex: 1; height: 1px; background: var(--line); }
/* Aviso de que el invitado es una demo sin registro. */
.login-guest-note { text-align: center; color: var(--muted); font-size: 11px; margin: 10px 0 0; }
.login-hint { text-align: center; color: var(--muted); font-size: 11px; margin: 14px 0 0; }

/* ---- Buscador ---- */
.search {
  display: flex; align-items: center; gap: 8px;
  background: var(--card); border: 1px solid var(--line);
  border-radius: 12px; padding: 9px 12px; margin-top: 12px;
}
.search svg { width: 17px; height: 17px; color: var(--muted); flex: 0 0 auto; }
.search input {
  border: none; outline: none; background: none;
  font-size: 14px; font-family: inherit; width: 100%; color: var(--ink);
}
.no-results { text-align: center; color: var(--muted); font-size: 13px; padding: 40px 20px; }

/* ---- Tarjeta clicable (detalle) ---- */
.card .thumb, .card .card-name { cursor: pointer; }

/* ---- Vista de detalle ---- */
/* La proporción 3:4 coincide con el recorte de origen (600x800), así que la
   prenda se ve completa sin recorte; el max-height evita que en pantallas altas
   la foto empuje el botón de "Agregar al carrito" fuera de la hoja. */
.detail-img {
  position: relative;
  aspect-ratio: 3 / 4;
  max-height: 44vh;
  border-radius: 16px;
  overflow: hidden;
  margin-bottom: 14px;
}
/* ---- Galería de fotos del detalle ----
   Solo aparece con dos o más fotos; con una, el marcado es el de siempre. */
.gallery.detail-img { margin-bottom: 8px; }
.gal-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 3;
  display: flex; align-items: center; justify-content: center;
  width: 34px; height: 34px;
  border: none; border-radius: 50%;
  background: rgba(20,26,18,.55);
  color: #fff;
  cursor: pointer;
  /* Sobre una foto cualquiera, el círculo oscuro puede perderse: el reborde
     claro lo separa igual en una prenda negra que en una blanca. */
  box-shadow: 0 0 0 1px rgba(255,255,255,.25);
}
.gal-nav:hover { background: rgba(20,26,18,.75); }
.gal-prev { left: 8px; }
.gal-next { right: 8px; }
.gal-count {
  position: absolute;
  right: 8px; bottom: 8px;
  z-index: 3;
  background: rgba(20,26,18,.6);
  color: #fff;
  border-radius: 20px;
  padding: 2px 9px;
  font-size: 11px; font-weight: 700;
}
.gal-dots { display: flex; justify-content: center; gap: 2px; margin-bottom: 12px; }
/* El botón mide 22px aunque el punto se dibuje de 7: un objetivo de 7px es
   imposible de acertar con el pulgar. El área táctil va en el botón y el
   dibujo en el ::before, así que agrandar una no engorda el otro. */
.gal-dot {
  width: 22px; height: 22px; padding: 0;
  border: none; background: none;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
}
.gal-dot::before {
  content: "";
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--line);
  transition: background .15s;
}
.gal-dot.on::before { background: var(--accent); }

.detail-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; }
.detail-name { font-size: 20px; font-weight: 800; line-height: 1.15; }
.detail-cat { font-size: 12px; color: var(--muted); margin-top: 2px; }
.detail-price { font-size: 22px; font-weight: 800; color: var(--accent); white-space: nowrap; }
.detail-price span { font-size: 12px; color: var(--muted); font-weight: 500; }
.detail-quality { margin: 12px 0 4px; }
.detail-quality small { font-size: 12px; }
/* En el detalle el medidor es la pieza principal de la ficha: algo más grande. */
.detail-quality .qm-seg { width: 13px; height: 6px; }
.detail-desc { font-size: 14px; line-height: 1.55; color: var(--ink); margin: 10px 0; }
.detail-avail { font-size: 13px; font-weight: 700; color: var(--ok); margin: 12px 0 0; }
/* Con la quinta celda (Color) los datos ya no caben en una fila: a ~75 px por
   celda, "Sintético" y el medidor de calidad se partían. En rejilla de dos
   columnas cada dato se lee entero, y la última celda ocupa el ancho sobrante
   en vez de dejar un hueco. */
.detail-facts {
  display: grid; grid-template-columns: repeat(2, 1fr);
  gap: 10px; margin: 14px 0 4px;
}
.fact {
  background: var(--card); border: 1px solid var(--line);
  border-radius: 12px; padding: 10px 12px;
}
.fact:last-child:nth-child(odd) { grid-column: 1 / -1; }
.fact .k { font-size: 11px; color: var(--muted); }
.fact .v { font-size: 15px; font-weight: 800; color: var(--ink); margin-top: 2px; }
.fact .v .color-dot { vertical-align: -1px; }

/* Tabla de tarifa por duración en el detalle: hace visible que el precio por
   día baja con los días, que es el argumento de venta del modelo. */
.detail-tarifa {
  margin: 16px 0 4px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--card-2, transparent);
}
.dt-title { font-size: 12px; font-weight: 800; color: var(--ink); margin-bottom: 8px; }
.dt-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: 13px;
  padding: 4px 0;
  color: var(--ink);
}
.dt-row + .dt-row { border-top: 1px solid var(--line); }
.dt-row small { color: var(--muted); font-weight: 600; font-size: 11px; }
.dt-note { font-size: 11px; color: var(--muted); line-height: 1.4; margin: 8px 0 0; }

/* ---- Selector de fechas de alquiler ---- */
.date-box {
  background: var(--card); border: 1px solid var(--line);
  border-radius: 14px; padding: 12px 14px; margin-bottom: 12px;
}
.date-box .dl { font-size: 13px; font-weight: 700; margin-bottom: 8px; }
.date-row { display: flex; gap: 10px; }
.date-field { flex: 1; }
.date-field label { font-size: 11px; color: var(--muted); display: block; margin-bottom: 4px; }
.date-field input {
  width: 100%; border: 1px solid var(--line); border-radius: 9px;
  padding: 8px 9px; font-size: 13px; font-family: inherit; color: var(--ink);
}
.date-field input:focus { outline: none; border-color: var(--accent); }
.date-total { font-size: 12px; color: var(--accent); font-weight: 700; margin-top: 8px; }
.date-total.pending { color: var(--muted); }

/* ---- Calendario de tarifas ----
   Bajo cada día se imprime lo que ese día suma al total. Es el mismo modelo de
   precios de data.js, solo que visible: los días que caen en el piso de coste
   salen en verde con "+$0" y empujan a alargar el alquiler, que es lo que
   conviene al negocio (un ciclo de lavandería rinde más días) y le da al
   cliente margen para devolver sin recargo. */
.cal { margin-top: 12px; }
.cal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; }
.cal-month { font-size: 13px; font-weight: 700; text-transform: capitalize; }
.cal-nav {
  background: none; border: 1px solid var(--line); border-radius: 8px;
  color: var(--ink); padding: 3px 7px; cursor: pointer; line-height: 0;
}
.cal-nav:disabled { opacity: .35; cursor: default; }
.cal-dow { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
/* Sin separación entre columnas: el rango se lee como una barra continua y no
   como una fila de cajas sueltas. La separación entre semanas sí se mantiene. */
.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px 0; }
.cal-dow span { font-size: 10px; color: var(--muted); text-align: center; font-weight: 700; }
.cal-day {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 1px; min-height: 38px; padding: 3px 0;
  background: none; border: 0; border-radius: 0;
  color: var(--ink); font-family: inherit; cursor: pointer;
}
.cal-day .cd-n { font-size: 12px; font-weight: 600; line-height: 1; }
/* La franja de coste ocupa sitio siempre, aunque vaya vacía: sin esto las filas
   sin tarifa encogen y la cuadrícula da un salto al cambiar de rango. */
.cal-day .cd-c { font-size: 9px; font-weight: 700; line-height: 1; min-height: 9px; }
.cal-day.out .cd-n { color: var(--muted); opacity: .55; }
.cal-day.past { opacity: .3; cursor: default; }
.cal-day:hover:not(:disabled):not(.in) { background: var(--accent-soft); border-radius: 9px; }

/* La barra del rango. Solo los extremos redondean, así los días de en medio
   empalman y el tramo se ve de una pieza. */
.cal-day.in { background: var(--accent-soft); }
.cal-day.in.start { border-top-left-radius: 9px; border-bottom-left-radius: 9px; }
.cal-day.in.end { border-top-right-radius: 9px; border-bottom-right-radius: 9px; }
/* Una semana cortada a medias también cierra su extremo: si no, la barra
   parece continuar fuera de la cuadrícula. */
.cal-day.in:first-child { border-top-left-radius: 9px; border-bottom-left-radius: 9px; }
.cal-day.in:last-child { border-top-right-radius: 9px; border-bottom-right-radius: 9px; }
.cal-day.in:nth-child(7n + 1) { border-top-left-radius: 9px; border-bottom-left-radius: 9px; }
.cal-day.in:nth-child(7n) { border-top-right-radius: 9px; border-bottom-right-radius: 9px; }
.cal-day.in .cd-n { color: var(--accent); font-weight: 800; }
/* Rango a medio elegir: un solo día punteado, para que se note que falta el
   segundo clic y no se confunda con un rango ya cerrado. */
.cal-day.pending { outline: 1px dashed var(--accent); outline-offset: -1px; border-radius: 9px; }

.cd-c.free { color: var(--ok); }
.cd-c.paid { color: var(--warn-ink); }
.cd-c.base { color: var(--muted); }

/* ---- Perfil ---- */
.profile-head {
  display: flex; align-items: center; gap: 14px;
  background: var(--card); border: 1px solid var(--line);
  border-radius: 16px; padding: 14px; margin-bottom: 14px;
}
.avatar {
  width: 56px; height: 56px; border-radius: 50%;
  background: var(--accent); color: var(--on-accent);
  display: grid; place-items: center;
  font-size: 24px; font-weight: 800; flex: 0 0 auto;
}
/* Avatar con foto de Google: llena el círculo sin deformar. */
.avatar.has-img { background: none; }
.avatar-img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; }
.ph-info { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 3px; }
.profile-name { font-size: 17px; font-weight: 800; line-height: 1.2; }
.profile-email { font-size: 13px; color: var(--muted); word-break: break-all; }
/* Distintivo del tipo de sesión: verde para cuenta real, neutro para invitado. */
.session-badge {
  align-self: flex-start; font-size: 11px; font-weight: 700;
  padding: 2px 8px; border-radius: 999px; line-height: 1.5;
}
.session-badge.user  { background: var(--accent-soft); color: var(--accent); }
.session-badge.guest { background: var(--line); color: var(--muted); }
/* Cerrar sesión: icono discreto arriba a la derecha de la tarjeta de perfil. */
.logout-btn {
  flex: 0 0 auto; align-self: flex-start;
  width: 36px; height: 36px; border-radius: 10px;
  display: grid; place-items: center; cursor: pointer;
  background: none; border: 1px solid var(--line); color: var(--muted);
  transition: background .15s, color .15s, border-color .15s;
}
.logout-btn svg { width: 18px; height: 18px; }
.logout-btn:hover { background: var(--danger-soft, var(--accent-soft)); color: var(--danger, var(--accent)); border-color: transparent; }

.points-card {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  /* Mezclaba --accent con un verde fijo oscuro: en tema oscuro --accent es
     claro y la mitad del degradado dejaba el texto blanco ilegible. */
  background: linear-gradient(135deg, var(--cta), var(--cta-strong));
  color: #fff; border-radius: 16px; padding: 14px 16px; margin-bottom: 10px;
  width: 100%; border: none; cursor: pointer; font-family: inherit; text-align: left;
}
.points-card.big { cursor: default; margin-bottom: 12px; }
.points-card:not(.big):active { transform: scale(.99); }
.pc-label { font-size: 12px; opacity: .85; }
.pc-value { font-size: 26px; font-weight: 800; margin-top: 2px; }
.pc-value span { font-size: 13px; font-weight: 600; opacity: .85; }
/* inline-flex + gap: antes el "→" era un glifo de texto pegado a la palabra,
   y su caja de línea lo dejaba descentrado respecto al fondo de la píldora. */
.pc-cta {
  display: inline-flex; align-items: center; gap: 6px; flex: 0 0 auto;
  font-size: 13px; font-weight: 700; background: rgba(255,255,255,.22);
  padding: 7px 13px; border-radius: 20px; white-space: nowrap;
}
.pc-emoji { display: flex; align-items: center; opacity: .9; flex: 0 0 auto; }

/* ---- Agua ahorrada (perfil) ---- */
/* ---- Ahorro de agua con metas ----
   Sustituye a la antigua .water-stat, que era una tarjeta con un número suelto:
   parecía pulsable sin serlo y no daba escala. Aquí el número va con barra,
   meta siguiente y los puntos que paga. NO es un botón: no lleva a ningún
   sitio, así que no lleva cursor ni flecha. */
.water-goal {
  background: var(--water-soft); border: 1px solid rgba(43,140,209,.25);
  border-radius: 16px; padding: 12px 16px; margin-bottom: 10px;
}
.wg-head { display: flex; align-items: center; gap: 12px; }
.wg-icon { display: flex; align-items: center; color: var(--water); flex: 0 0 auto; }
.wg-titles { flex: 1 1 auto; min-width: 0; }
.wg-label { font-size: 12px; color: var(--muted); font-weight: 700; }
.wg-value { font-size: 22px; font-weight: 800; color: var(--water); margin-top: 2px; }
.wg-value span { font-size: 13px; font-weight: 600; opacity: .85; }
.wg-next { font-size: 11px; font-weight: 700; color: var(--muted); flex: 0 0 auto; align-self: flex-end; }
/* El riel envuelve a la barra para que los marcadores (absolutos) puedan
   sobresalir de ella: la barra recorta con overflow y los cortaría. */
.wg-track { position: relative; margin: 14px 0 4px; }
.wg-bar {
  height: 7px; border-radius: 999px;
  background: rgba(43,140,209,.20); overflow: hidden;
}
.wg-fill {
  display: block; height: 100%; border-radius: 999px;
  background: var(--water); transition: width .4s ease;
}
/* Marcador de meta sobre la barra. El último cae en left:100%: el translate
   de -100% (en vez de centrarlo) lo mete dentro del riel para que no se
   salga de la tarjeta. */
.wg-mark {
  position: absolute; top: 50%; transform: translate(-100%, -50%);
  width: 15px; height: 15px; border-radius: 50%; padding: 0;
  border: 2px solid var(--water); background: var(--bg);
  color: var(--on-accent); cursor: pointer;
  display: grid; place-items: center;
}
.wg-mark.done { background: var(--water); }
.wg-mark.active { box-shadow: 0 0 0 3px rgba(43,140,209,.30); }
/* Detalle de la meta tocada: solo existe mientras un marcador está activo. */
.wg-goal-info {
  display: flex; align-items: flex-start; gap: 7px;
  margin-top: 8px; padding: 8px 10px; border-radius: 10px;
  background: rgba(43,140,209,.12); font-size: 11px;
  color: var(--muted); line-height: 1.45;
}
.wg-goal-info b { color: var(--water); }
.wgi-ico { display: flex; align-items: center; color: var(--water); margin-top: 1px; }

/* Meta conseguida, anunciada en la confirmación del pedido. */
.goal-hit {
  display: flex; align-items: center; justify-content: center; gap: 7px;
  background: var(--water-soft); color: var(--water);
  border-radius: 10px; padding: 9px 12px; margin-top: 8px;
  font-size: 12px; font-weight: 700;
}

/* ---- Información de contacto (solo lectura) ---- */
.profile-info {
  background: var(--card); border: 1px solid var(--line);
  border-radius: 14px; padding: 4px 14px; margin-bottom: 8px;
}
.pi-row {
  display: flex; justify-content: space-between; gap: 12px;
  padding: 10px 0; border-bottom: 1px solid var(--line); font-size: 13px;
}
.pi-row:last-of-type { border-bottom: none; }
.pi-k { color: var(--muted); font-weight: 700; }
.pi-v { color: var(--ink); text-align: right; word-break: break-word; }
.edit-info-btn {
  width: 100%; background: var(--accent-soft); color: var(--accent);
  border: none; border-radius: 10px; padding: 11px; margin: 6px 0 10px;
  font-size: 14px; font-weight: 700; cursor: pointer; font-family: inherit;
}
.pf-actions { display: flex; gap: 8px; }
.pf-actions .save-btn, .pf-actions .ret-cancel { flex: 1; margin-top: 0; }

/* ---- Donar ropa ---- */
.donate-card {
  display: flex; align-items: center; gap: 12px; width: 100%;
  background: var(--accent-soft); border: 2px solid var(--accent); border-radius: 16px;
  padding: 14px; margin-bottom: 12px;
  cursor: pointer; font-family: inherit; text-align: left;
  box-shadow: 0 4px 14px rgba(63,125,58,.18);
}
.donate-card:active { transform: scale(.99); }
.dc-icon { display: flex; align-items: center; color: var(--accent); flex: 0 0 auto; }
.dc-text { flex: 1; min-width: 0; }
.dc-title { font-size: 15px; font-weight: 800; color: var(--accent); }
.dc-desc { font-size: 11px; color: var(--muted); margin-top: 2px; line-height: 1.35; }
/* El disco centra un SVG, no un glifo: place-items centraba la caja de línea
   del "→" y la flecha quedaba visiblemente alta dentro del círculo. */
.dc-cta {
  color: var(--on-accent); background: var(--accent);
  width: 30px; height: 30px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; flex: 0 0 auto;
}
.dc-cta .ico { vertical-align: 0; }

/* ---- Pon tu armario en alquiler (anuncio) ----
   Comparte la caja de .donate-card, pero en tono neutro y con borde punteado:
   la tarjeta activa (donar) no debe competir con una que aún no lleva a nada. */
.wardrobe-card {
  background: var(--card); border: 2px dashed var(--line);
  box-shadow: none;
}
.wardrobe-card .dc-icon { color: var(--ico-brown); }
.wardrobe-card .dc-title { color: var(--ink); display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.wardrobe-card .dc-cta { background: var(--muted); }
.soon-tag {
  font-size: 10px; font-weight: 800; letter-spacing: .3px; text-transform: uppercase;
  color: var(--accent); background: var(--accent-soft);
  padding: 3px 8px; border-radius: 20px; white-space: nowrap;
}
/* Contenido del diálogo "Muy pronto" */
.soon-text { font-size: 13px; color: var(--muted); line-height: 1.5; margin: 0 0 12px; text-align: center; }
.soon-list { display: flex; flex-direction: column; gap: 10px; margin-bottom: 12px; }
.soon-item {
  display: flex; align-items: center; gap: 10px;
  background: var(--bg); border-radius: 10px; padding: 10px 12px;
  font-size: 12.5px; color: var(--ink); text-align: left;
}
/* Disco de color por ítem: el mismo tamaño para los tres alinea el texto
   aunque los trazados de cada icono ocupen distinto alto. */
.si-icon {
  width: 34px; height: 34px; border-radius: 50%; flex: 0 0 auto;
  display: flex; align-items: center; justify-content: center;
  background: var(--card);
}
.soon-note { font-size: 11.5px; color: var(--muted); text-align: center; margin: 0; }

/* ---- Acentos de color de los iconos ----
   Los SVG heredan `currentColor`, así que basta con teñir el contenedor: un
   mismo icono sirve en verde, azul o dorado sin duplicar el trazado. Se
   aplican solo a los iconos que IDENTIFICAN algo (una opción de envío, un
   premio, una ventaja); las flechas, checks y equis siguen heredando el color
   del texto, que es lo que las mantiene legibles como parte de la interfaz. */
.ico-sky    { color: var(--ico-sky); }
.ico-violet { color: var(--ico-violet); }
.ico-gold   { color: var(--ico-gold); }
.ico-rose   { color: var(--ico-rose); }
.ico-teal   { color: var(--ico-teal); }

/* Entrega y devolución, un color por opción. Los cuatro comparten los mismos
   dos iconos (camión y local), así que si el color también se repitiera, las
   dos preguntas del checkout se verían idénticas y sería fácil creer que ya
   contestaste la de abajo. Se seleccionan por data-action/data-value porque el
   marcado reutiliza la clase .delivery-opt para entrega, devolución y pago. */
[data-action="setDelivery"][data-value="ship"]   .do-icon { color: var(--ico-sky); }
[data-action="setDelivery"][data-value="pickup"] .do-icon { color: var(--accent); }
[data-action="setReturn"][data-value="store"]    .do-icon { color: var(--ico-brown); }
[data-action="setReturn"][data-value="home"]     .do-icon { color: var(--ico-violet); }

/* Métodos de pago: efectivo en dorado, tarjetas en violeta. */
[data-action="setPay"][data-value="cash"]   .do-icon { color: var(--ico-gold); }
[data-action="setPay"][data-value="credit"] .do-icon,
[data-action="setPay"][data-value="debit"]  .do-icon { color: var(--ico-violet); }

/* Premios: cada uno con el color de lo que entrega (envío, días, %, premium). */
.reward[data-reward="1"] .rw-icon { color: var(--ico-sky); }
.reward[data-reward="2"] .rw-icon { color: var(--ico-rose); }
.reward[data-reward="3"] .rw-icon { color: var(--ico-gold); }
.reward[data-reward="4"] .rw-icon { color: var(--ico-violet); }
/* Un premio bloqueado no debe gritar más que uno disponible. */
.reward.locked .rw-icon { color: var(--muted); }

/* El agua ahorrada ya va en azul; su icono acompaña al bloque, no al texto. */
.water-saved .ico { color: var(--ico-teal); }

.donate-intro {
  font-size: 13px; color: var(--ink); line-height: 1.5;
  background: var(--accent-soft); border-radius: 12px; padding: 12px 14px; margin: 0 0 6px;
}
.donate-rules {
  list-style: none; margin: 0 0 10px; padding: 0;
  font-size: 12px; color: var(--ink); line-height: 1.5;
}
.donate-rules li { padding: 2px 0; }
.donate-input {
  width: 100%; border: 1px solid var(--line); border-radius: 10px;
  padding: 11px 12px; font-size: 14px; font-family: inherit; color: var(--ink); margin-bottom: 2px;
}
.donate-input:focus { outline: none; border-color: var(--accent); }
.don-date-label { display: block; font-size: 12px; font-weight: 700; color: var(--ink); margin-top: 8px; }
.don-date-label input {
  display: block; width: 100%; margin-top: 5px;
  border: 1px solid var(--line); border-radius: 8px; padding: 9px 10px;
  font-size: 13px; font-family: inherit; color: var(--ink);
}
.don-date-label input:focus { outline: none; border-color: var(--accent); }

.donation-item {
  display: flex; align-items: flex-start; gap: 12px;
  background: var(--card); border: 1px solid var(--line); border-radius: 14px;
  padding: 10px 12px; margin-bottom: 10px;
}
.di-info { flex: 1; min-width: 0; }
.di-name { font-size: 14px; font-weight: 700; color: var(--ink); }
.di-meta { font-size: 11px; color: var(--muted); margin-top: 2px; }
.di-points { font-size: 11px; color: var(--accent); font-weight: 700; margin-top: 2px; }
.di-status {
  font-size: 10px; font-weight: 700; color: var(--accent);
  background: var(--accent-soft); padding: 4px 9px; border-radius: 20px;
  flex: 0 0 auto; white-space: nowrap;
}

/* ---- Premios ---- */
.reward {
  display: flex; align-items: center; gap: 12px;
  background: var(--card); border: 1px solid var(--line);
  border-radius: 14px; padding: 12px; margin-bottom: 10px;
}
.reward.locked { opacity: .6; }
.rw-icon { display: flex; align-items: center; color: var(--accent); flex: 0 0 auto; }
.rw-info { flex: 1; min-width: 0; }
.rw-name { font-size: 14px; font-weight: 700; color: var(--ink); }
.rw-desc { font-size: 11px; color: var(--muted); margin: 2px 0; line-height: 1.35; }
.rw-cost { font-size: 12px; font-weight: 800; color: var(--accent); }
.rw-btn {
  flex: 0 0 auto; align-self: center;
  background: linear-gradient(135deg, var(--cta), var(--cta-strong)); color: #fff;
  border: none; border-radius: 10px;
  padding: 9px 12px; font-size: 13px; font-weight: 700; cursor: pointer; font-family: inherit;
  box-shadow: 0 4px 12px var(--cta-glow);
}
.rw-btn:disabled { background: var(--disabled-bg); color: var(--disabled-ink); box-shadow: none; cursor: not-allowed; font-size: 11px; }
.redeemed-item {
  display: flex; justify-content: space-between; gap: 10px;
  font-size: 12px; color: var(--ink); padding: 7px 2px;
}
.redeemed-item span { color: var(--muted); }
/* Un premio ya gastado no compite por atención con los que aún sirven. */
.redeemed-item.used { opacity: .6; }

/* ---- Premios aplicables en el checkout ----
   Comparten la caja de .delivery-opt (misma decisión: elegir una opción de una
   lista), con el candado para los que no aplican a este pedido. */
.coupon-opts { display: flex; flex-direction: column; gap: 10px; margin-bottom: 6px; }
.coupon-opt {
  border: 2px solid var(--line);
  background: var(--card);
  border-radius: 14px;
  padding: 12px 14px;
  cursor: pointer;
  display: flex;
  gap: 12px;
  align-items: flex-start;
}
.coupon-opt.active { border-color: var(--accent); background: var(--accent-soft); }
.coupon-opt.active .do-radio { border-color: var(--accent); }
.coupon-opt.active .do-radio::after {
  content: ""; width: 10px; height: 10px; border-radius: 50%; background: var(--accent);
}
/* No aplica a este pedido: se muestra igualmente, con el motivo, para que el
   cliente no crea que perdió el canje. */
.coupon-opt.locked { opacity: .55; cursor: not-allowed; border-style: dashed; }
.coupon-opt.locked .do-desc { color: var(--danger); }
.link-btn {
  background: none; border: none; padding: 4px 2px; margin-bottom: 6px;
  color: var(--muted); font-size: 12px; font-family: inherit;
  text-decoration: underline; cursor: pointer;
}
/* Descuento en el resumen: en verde, como el único importe que resta. */
.summary-row.discount { color: var(--ok); font-weight: 700; }
/* Premio aplicado (confirmación) */
.coupon-used {
  background: var(--accent-soft); color: var(--accent);
  border-radius: 12px; padding: 12px; margin-top: 10px;
  font-size: 14px; font-weight: 700; text-align: center;
}

/* ---- Dirección fijada por el mapa (sin campo de texto) ---- */
.addr-picked {
  background: var(--card); border: 1px solid var(--line);
  border-radius: 12px; padding: 10px 12px; margin-top: 6px;
}
.ap-text { font-size: 14px; font-weight: 600; color: var(--ink); line-height: 1.35; }
.ap-coords { font-size: 11px; color: var(--ok); margin-top: 4px; font-weight: 700; }
/* Sin punto todavía: caja punteada, para que se lea como un hueco por llenar
   y no como un dato ya resuelto. */
.addr-empty {
  border: 1px dashed var(--line); border-radius: 12px;
  padding: 10px 12px; margin-top: 6px;
  font-size: 12.5px; color: var(--muted); line-height: 1.4;
}

/* ---- Puntos ganados (confirmación) ---- */
.earned-points {
  background: var(--accent-soft); color: var(--accent);
  border-radius: 12px; padding: 12px; margin-top: 14px;
  font-size: 14px; font-weight: 700; text-align: center;
}
/* Pedido pendiente (efectivo): los puntos aún no se acreditan → tono neutro. */
.earned-points.pending { background: var(--bg); color: var(--muted); }
/* Agua ahorrada (confirmación) */
.water-saved {
  background: var(--water-soft); color: var(--water);
  border-radius: 12px; padding: 12px; margin-top: 10px;
  font-size: 14px; font-weight: 700; text-align: center;
}

.profile-form { display: flex; flex-direction: column; gap: 12px; margin-bottom: 8px; }
.pf-fld { display: block; font-size: 12px; font-weight: 700; color: var(--ink); }
.pf-fld input {
  display: block; width: 100%; margin-top: 5px;
  border: 1px solid var(--line); border-radius: 10px;
  padding: 11px 12px; font-size: 14px; font-family: inherit; color: var(--ink);
}
.pf-fld input:focus { outline: none; border-color: var(--accent); }
.save-btn {
  background: var(--accent-soft); color: var(--accent);
  border: none; border-radius: 12px; padding: 12px;
  font-size: 14px; font-weight: 700; cursor: pointer; margin-top: 2px;
}
.save-btn:active { transform: scale(.99); }

.pf-error { display: block; color: var(--danger); font-size: 11px; margin: -6px 0 2px; }
/* Pista permanente bajo el campo: dice la regla ANTES de escribir. El error
   llega tarde y culpa; la pista llega a tiempo y solo informa. */
.pf-hint {
  display: flex; align-items: center; gap: 5px;
  color: var(--muted); font-size: 11px; font-weight: 500; margin: -8px 0 0;
}
.pf-hint svg { flex: none; }

/* Campo bloqueado (nombre en enfriamiento, correo de Google). Se ve inerte pero
   sigue siendo enfocable y seleccionable: el usuario debe poder copiar su
   correo aunque no pueda editarlo. */
.pf-fld input.is-locked {
  background: var(--disabled-bg);
  color: var(--disabled-ink); cursor: not-allowed;
}
.pf-fld input.is-locked:focus { border-color: var(--line); }

/* Celular: el +593 es texto fijo dentro del mismo marco que el input, para que
   se lea como un solo número y no como dos campos independientes. */
.pf-phone {
  display: flex; align-items: stretch; margin-top: 5px;
  border: 1px solid var(--line); border-radius: 10px; overflow: hidden;
}
.pf-phone:focus-within { border-color: var(--accent); }
.pf-cc {
  display: flex; align-items: center; padding: 0 10px;
  background: var(--neutral-bg); color: var(--neutral-ink);
  font-size: 14px; font-weight: 700; border-right: 1px solid var(--line);
}
.pf-phone input { margin-top: 0; border: none; border-radius: 0; }
.pf-phone input:focus { border-color: transparent; }

.pf-verify { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: -4px; }
.pf-vbadge {
  display: inline-flex; align-items: center; gap: 4px;
  background: var(--warn-bg); color: var(--warn-ink);
  border-radius: 999px; padding: 4px 9px; font-size: 11px; font-weight: 700;
}
.pf-vbtn {
  display: inline-flex; align-items: center; gap: 5px;
  background: var(--accent-soft); color: var(--accent);
  border: none; border-radius: 999px; padding: 6px 12px;
  font-size: 12px; font-weight: 700; font-family: inherit; cursor: pointer;
}
.pf-vbtn:active { transform: scale(.98); }

.cart-item.rental { align-items: flex-start; }
.ci-ret { font-size: 11px; color: var(--muted); margin-top: 3px; }
.ret-addr { color: var(--ink); }
.ret-edit {
  background: none; border: none; color: var(--accent);
  font-size: 11px; font-weight: 700; cursor: pointer; padding: 4px 0 0; text-decoration: underline;
  display: inline-block;
}
/* Nota pasiva en un pedido en efectivo pendiente: informa los puntos
   reservados. NO es una acción: el cliente no confirma su propio pago. */
.points-pending {
  margin: 8px 0 2px; padding: 8px 10px;
  background: var(--bg); border-radius: 10px;
  font-size: 12px; font-weight: 700; color: var(--muted);
}
/* Litros que el pedido aporta a las metas de agua. Comparte caja con los puntos
   pendientes (se leen como una sola ficha), pero tiñe el dato en el azul del
   agua para separar de un vistazo el impacto de la recompensa. */
.water-pending {
  margin: 2px 0; padding: 8px 10px;
  background: var(--bg); border-radius: 10px;
  font-size: 12px; font-weight: 700; color: var(--muted);
}
.water-pending svg { color: var(--ico-sky); vertical-align: -2px; }
.water-pending b { color: var(--ico-sky); }

/* ---- Editor del modo de devolución (dentro de #retOverlay) ---- */
.ret-editor {
  display: flex; flex-direction: column; gap: 8px;
  text-align: left;   /* el .modal centra su contenido; aquí es un formulario */
}
/* Este pop-up es el ÚNICO que puede tener otro diálogo encima: cambiar de modo
   abre la confirmación del cargo. Con el z-index de .modal-overlay (90) los dos
   empataban y mandaba el orden del DOM, así que la confirmación quedaba DEBAJO
   y no se podía ni aceptar ni cancelar: la app parecía colgada. Va por debajo
   del modal (90) y también del toast (85), que es como avisa de sus propios
   errores ("marca la ubicación en el mapa"). */
#retOverlay { z-index: 84; }
/* El pop-up es más alto que el modal de confirmar: lleva dos opciones, la ficha
   del local o el mapa, y los botones. Se le deja crecer y desplazarse dentro en
   vez de desbordar la pantalla del teléfono. */
.ret-modal {
  max-width: 330px;
  max-height: 100%;
  overflow-y: auto;
}
.ret-editor-title { font-size: 12px; font-weight: 700; color: var(--ink); }
.ret-opt {
  display: flex; flex-direction: column; gap: 3px;
  border: 2px solid var(--line); background: var(--card);
  border-radius: 10px; padding: 9px 11px; cursor: pointer;
  font-family: inherit; text-align: left; width: 100%;
}
.ret-opt.active { border-color: var(--accent); background: var(--accent-soft); }
.ro-head { display: flex; justify-content: space-between; align-items: center; font-size: 13px; font-weight: 700; color: var(--ink); }
.ro-desc { font-size: 11px; color: var(--muted); }
.ro-tag { font-size: 11px; font-weight: 700; }
.ro-tag.free { color: var(--ok); }
.ro-tag.fee { color: var(--accent); }
.ret-editor-actions { display: flex; gap: 8px; }
.ret-cancel, .ret-save {
  flex: 1; border: none; border-radius: 10px; padding: 9px;
  font-size: 13px; font-weight: 700; cursor: pointer; font-family: inherit;
}
.ret-cancel { background: var(--accent-soft); color: var(--accent); }
.ret-save { background: linear-gradient(135deg, var(--cta), var(--cta-strong)); color: #fff; }

.rent-tag {
  font-size: 10px; font-weight: 700; text-transform: uppercase;
  background: var(--accent-soft); color: var(--accent);
  padding: 4px 9px; border-radius: 20px; flex: 0 0 auto; align-self: flex-start;
}

/* ---- Prenda vencida (devolución pasada) ---- */
.cart-item.late { border: 1.5px solid var(--danger); }
.rent-tag.late { background: #f6e1d8; color: var(--danger); }
.late-info-btn {
  background: none; border: none; color: var(--danger);
  font-size: 11px; font-weight: 700; cursor: pointer; padding: 5px 0 0;
}
.late-info {
  display: none; font-size: 11px; line-height: 1.45; color: var(--ink);
  background: var(--danger-soft); border: 1px solid var(--danger-line); border-radius: 8px;
  padding: 8px 10px; margin-top: 6px;
}
.late-info.show { display: block; }
.late-info b { color: var(--danger); }

/* ---- Pedidos del perfil (orders) ---- */
.order {
  background: var(--card); border: 1px solid var(--line);
  border-radius: 16px; padding: 12px 14px; margin-bottom: 12px;
}
.order.late { border: 1.5px solid var(--danger); }
.order-head {
  display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; flex-wrap: wrap;
}
.order-id { font-size: 14px; font-weight: 800; color: var(--ink); }
.order-date { font-size: 11px; color: var(--muted); margin-top: 2px; }
.order-badges { display: flex; flex-direction: column; align-items: flex-end; gap: 6px; flex: 0 0 auto; }
.pay-status {
  font-size: 10px; font-weight: 700; text-transform: uppercase;
  padding: 4px 9px; border-radius: 20px; white-space: nowrap;
}
.pay-status.settled { background: var(--accent-soft); color: var(--accent); }
.pay-status.pending { background: var(--warn-bg); color: var(--warn-ink); }
/* Anulado: gris neutro. NO usa el rojo de --danger porque anular es una acción
   normal del cliente, no un error ni un atraso. */
.pay-status.cancelled { background: var(--neutral-bg); color: var(--neutral-ink); }

.order-item {
  display: flex; gap: 10px; align-items: center;
  padding: 8px 0; border-bottom: 1px solid var(--line);
}
.order-item:first-of-type { border-top: 1px solid var(--line); margin-top: 8px; }
.order-item:last-of-type { border-bottom: none; }
.oi-info { flex: 1; min-width: 0; }
.oi-name { font-size: 13px; font-weight: 700; color: var(--ink); }
.oi-meta { font-size: 11px; color: var(--muted); }

.order-period { font-size: 11px; color: var(--muted); margin: 6px 0 0; }
.order-charge {
  display: flex; justify-content: space-between; align-items: center;
  margin-top: 8px; padding-top: 8px; border-top: 1px dashed var(--line);
  font-size: 13px; color: var(--ink); font-weight: 700;
}
.order-charge b { font-size: 16px; font-weight: 800; color: var(--accent); }

/* ---- Fila de depósito ---- */
.summary-row.deposit span:first-child { display: flex; align-items: center; gap: 4px; }
.refund-tag {
  font-size: 9px; background: var(--accent-soft); color: var(--accent);
  padding: 1px 6px; border-radius: 8px; font-weight: 700; text-transform: uppercase;
}

/* ---- Mobile-first: cabecera del pedido ---- */
.order-head-main { flex: 1; min-width: 0; }
.order-date { word-break: break-word; }

/* ---- Alquileres anteriores (desplegable) ---- */
.past-orders-section { margin-top: 4px; }

.past-orders-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  list-style: none;
  padding: 12px 14px;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 14px;
  font-size: 14px;
  font-weight: 700;
  color: var(--ink);
  user-select: none;
  width: 100%;
}
.past-orders-toggle::-webkit-details-marker { display: none; }
.past-orders-toggle > span:first-child { flex: 1; }
.past-orders-toggle::after {
  content: "▾";
  font-size: 14px;
  color: var(--muted);
  transition: transform .22s ease;
  flex: 0 0 auto;
}
.past-orders-section[open] > .past-orders-toggle::after { transform: rotate(-180deg); }
.past-orders-section[open] > .past-orders-toggle { border-radius: 14px 14px 0 0; }

.past-count {
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 11px;
  font-weight: 700;
  padding: 3px 9px;
  border-radius: 20px;
  flex: 0 0 auto;
}

.past-orders-body {
  border: 1px solid var(--line);
  border-top: none;
  border-radius: 0 0 14px 14px;
  padding: 10px 10px 4px;
  background: var(--bg);
}

.order.archived {
  opacity: .8;
  border-style: dashed;
}

/* ---- Anular pedido ---- */
.order-cancel {
  background: none; border: none; color: var(--danger);
  font-size: 11px; font-weight: 700; cursor: pointer;
  padding: 6px 0 0; text-decoration: underline;
  display: block;
}
.rent-tag.void { background: var(--neutral-bg); color: var(--neutral-ink); }
/* El pedido anulado sigue listado (historial), pero atenuado y tachado en su
   total para que no se confunda con uno vigente. */
.order.cancelled { opacity: .75; }
.order.cancelled .order-charge b { text-decoration: line-through; color: var(--muted); }

/* ============================================================
   Responsive mobile — ajustes para pantallas pequeñas y el
   sheet en modo web-hosted (no solo file://).
   ============================================================ */

/* El sheet usa position:absolute relativo al .phone, lo que ya
   funciona en el mockup. Al ser position:fixed en móvil, el sheet
   debe apoyarse contra el fondo REAL de la pantalla. */
@media (max-width: 600px) {
  /* Más espacio en el catálogo para el sheet sin pisarlo */
  main { padding-bottom: 120px; }

  /* Header más compacto: libera espacio de contenido */
  header { padding-left: 16px; padding-right: 16px; padding-bottom: 10px; }

  /* Botones de marca ligeramente más pequeños */
  .icon-btn, .cart-btn { width: 42px; height: 42px; }

  /* Grid: reduce gap y thumb para pantallas pequeñas */
  .grid { gap: 10px; }
  .thumb { height: 120px; }
  .card-body { padding: 8px 10px 10px; }
  .card-name { font-size: 13px; }
}

/* Teléfonos muy angostos (<360 px, ej. iPhone SE, Galaxy A01) */
@media (max-width: 360px) {
  .brand h1 { font-size: 19px; }
  .brand-logo img { height: 32px; }
  .brand-actions { gap: 7px; }
  .grid { grid-template-columns: 1fr 1fr; gap: 8px; }
  .thumb { height: 108px; }
  .sheet-body { padding: 12px 14px; }
  .order { padding: 10px 12px; }
}

/* ---- Selector de ubicación en el mapa ----
   Se superpone al marco del teléfono a pantalla completa: elegir un punto
   necesita todo el espacio disponible, y un mapa de 200px no permite afinar. */
.map-pick-btn {
  width: 100%; margin-top: 8px;
  background: var(--accent-soft); color: var(--accent);
  border: 1px dashed var(--accent); border-radius: 10px;
  padding: 10px; font-size: 13px; font-weight: 700;
  font-family: inherit; cursor: pointer;
}
.map-pick-btn:active { transform: scale(.99); }
.map-coords {
  margin-top: 6px; font-size: 11.5px; font-weight: 700; color: var(--ok);
}

.map-overlay {
  position: absolute; inset: 0; z-index: 120;
  background: rgba(0,0,0,.45);
  display: none; align-items: flex-end;
}
.map-overlay.show { display: flex; }
.map-sheet {
  background: var(--bg); width: 100%; height: 100%;
  display: flex; flex-direction: column;
}
.map-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 18px; border-bottom: 1px solid var(--line);
  font-size: 16px; color: var(--ink); flex: 0 0 auto;
}
.map-close {
  background: none; border: none; color: var(--muted);
  font-size: 20px; cursor: pointer; line-height: 1; padding: 4px 6px;
}
/* El mapa ocupa todo el hueco libre; el pie mantiene su alto natural. */
.map-canvas-wrap { position: relative; flex: 1; min-height: 0; }
.map-canvas { position: absolute; inset: 0; background: var(--card); }
/* Pin fijo al centro. El translate lo sube media altura para que la PUNTA
   —y no el centro del dibujo— caiga sobre el punto que el mapa reporta. */
.map-pin {
  position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -100%);
  font-size: 32px; pointer-events: none; line-height: 1;
  filter: drop-shadow(0 3px 4px rgba(0,0,0,.35));
}
.map-locate {
  position: absolute; right: 14px; bottom: 14px;
  width: 42px; height: 42px; border-radius: 50%;
  background: var(--card); border: 1px solid var(--line); color: var(--accent);
  font-size: 19px; cursor: pointer; box-shadow: 0 3px 10px rgba(0,0,0,.18);
}
.map-locate:disabled { opacity: .5; cursor: progress; }
.map-foot {
  flex: 0 0 auto; padding: 14px 18px 18px;
  border-top: 1px solid var(--line); background: var(--bg);
}
.map-hint { font-size: 11.5px; color: var(--muted); font-weight: 700; }
.map-address {
  font-size: 13px; color: var(--ink); line-height: 1.4;
  margin: 6px 0 12px; min-height: 36px;
}

/* ============================================================
   Ajustes (tema y accesibilidad)
   ============================================================ */
.settings-intro {
  font-size: 12.5px; color: var(--muted); line-height: 1.5;
  margin: 0 0 14px; text-align: center;
}
.settings-card .dc-title { color: var(--ink); }

.pref-row {
  background: var(--card); border: 1px solid var(--line);
  border-radius: 14px; padding: 14px; margin-bottom: 12px;
}
.pref-head { display: flex; align-items: center; gap: 12px; }
.pref-icon {
  width: 36px; height: 36px; border-radius: 50%; flex: 0 0 auto;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg);
}
.pref-head > div:not(.pref-icon) { flex: 1; min-width: 0; }
/* Baja de cuenta: única fila destructiva de Ajustes. Se separa del resto y se
   tiñe entera porque es la que no tiene deshacer — mezclada con los toggles de
   tema se pulsaría por inercia. */
.danger-row {
  border-color: var(--danger-line); background: var(--danger-soft);
  margin-top: 22px;
}
.ico-danger { color: var(--danger); }
.danger-row .ico-danger { background: var(--card); }
.danger-btn {
  width: 100%; margin-top: 12px;
  background: none; border: 1px solid var(--danger); color: var(--danger);
  border-radius: 12px; padding: 11px;
  font-family: inherit; font-size: 13.5px; font-weight: 700; cursor: pointer;
}
.danger-btn:active { transform: scale(.99); }
.pref-name { font-size: 14px; font-weight: 700; color: var(--ink); }
.pref-desc { font-size: 11.5px; color: var(--muted); margin-top: 2px; line-height: 1.35; }

/* Opciones excluyentes: se ven como un segmentado, no como botones sueltos,
   para que se lea que eligen UNA cosa entre varias. */
.pref-opts { display: flex; gap: 6px; margin-top: 12px; }
.pref-opt {
  flex: 1; padding: 9px 6px;
  background: var(--bg); color: var(--muted);
  border: 1px solid var(--line); border-radius: 10px;
  font-size: 12.5px; font-weight: 700; font-family: inherit; cursor: pointer;
}
.pref-opt.active {
  background: var(--accent-soft); color: var(--accent); border-color: var(--accent);
}
.pref-opt:active { transform: scale(.97); }

/* Interruptor. El foco se marca sobre el riel completo porque el pulgar es
   demasiado pequeño para que el anillo se vea. */
.pref-switch {
  flex: 0 0 auto; width: 46px; height: 27px; padding: 3px;
  background: var(--line); border: none; border-radius: 20px;
  cursor: pointer; transition: background .18s ease;
  display: flex; align-items: center;
}
.pref-switch.on { background: var(--cta); }
.ps-knob {
  width: 21px; height: 21px; border-radius: 50%;
  background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.3);
  transition: transform .18s ease;
}
.pref-switch.on .ps-knob { transform: translateX(19px); }
.pref-switch:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }


/* ============================================================
   Campos de formulario en ambos temas
   No fijaban `background` ni `color`: heredaban el estilo del navegador, que
   con el tema oscuro dejaba el valor y el texto de ayuda ilegibles. Se listan
   juntos para que ningún campo nuevo se quede fuera por olvido.
   ============================================================ */
.ship-detail input,
.fld input,
.date-field input,
.donate-input,
.don-date-label input,
.pf-fld input,
.addr-picked {
  background: var(--field);
  color: var(--ink);
}
.ship-detail input::placeholder,
.fld input::placeholder,
.donate-input::placeholder,
.pf-fld input::placeholder,
.search input::placeholder {
  color: var(--muted);
  opacity: 1;              /* Firefox lo aclara por su cuenta y lo vuelve ilegible */
}

/* El logo es un PNG de trazo oscuro sobre fondo transparente: en el tema
   oscuro se pierde contra el fondo. Se le da una base clara en vez de
   invertirlo, que le cambiaría el color de marca. */
:root[data-theme="dark"] .brand-logo {
  background: var(--logo-plate);
  border-radius: 10px;
  padding: 3px 5px;
}
/* El sello de la bienvenida lleva el mismo tratamiento: es el mismo PNG y se
   pierde igual contra el fondo oscuro. */
:root[data-theme="dark"] .login-mark {
  background: var(--logo-plate);
}

/* ---- Reseñas de clientes ----
   Aquí SÍ van estrellas: son la valoración de la gente, que es lo que una
   estrella significa para cualquiera. La calidad de la prenda usa su medidor
   propio (.qmeter) precisamente para que estas dos no se confundan. */
.reviews { margin-top: 18px; border-top: 1px solid var(--line); padding-top: 14px; }
.rev-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.rev-head h3 { margin: 0; font-size: 15px; }
.rev-avg { color: var(--star); font-size: 13px; letter-spacing: 1px; }
.rev-avg b { color: var(--ink); margin-left: 4px; letter-spacing: 0; }
.rev-avg small { color: var(--muted); letter-spacing: 0; }
.rev-empty { color: var(--muted); font-size: 12px; margin: 8px 0 0; }
.review { padding: 12px 0; border-bottom: 1px solid var(--line); }
.review:last-child { border-bottom: none; padding-bottom: 0; }
.rev-top { display: flex; justify-content: space-between; gap: 8px; font-size: 12px; }
.rev-author { font-weight: 700; }
.rev-date { color: var(--muted); }
.rev-stars { color: var(--star); font-size: 12px; letter-spacing: 1px; margin-top: 2px; }
.rev-text { margin: 6px 0 0; font-size: 13px; line-height: 1.45; }
.rev-photo { margin-top: 8px; max-width: 160px; width: 100%; border-radius: 10px; display: block; }

/* ---- Formulario de reseña ---- */
.rev-add-btn {
  width: 100%; margin-top: 8px; padding: 9px;
  border: 1px solid var(--line); border-radius: 10px;
  background: none; color: var(--ink);
  font-size: 12px; font-weight: 700; cursor: pointer;
  display: flex; align-items: center; justify-content: center; gap: 6px;
}
.rev-add-btn:hover { border-color: var(--accent); color: var(--accent); }
.rev-section { margin-bottom: 16px; }
.rev-label { font-size: 12px; font-weight: 700; margin-bottom: 7px; }
.rev-opt { color: var(--muted); font-weight: 400; }
.rev-picks { display: flex; flex-direction: column; gap: 8px; }
.rev-pick {
  display: flex; align-items: center; gap: 10px;
  padding: 8px; border: 1px solid var(--line); border-radius: 12px; cursor: pointer;
}
.rev-pick.on { border-color: var(--accent); background: var(--accent-soft, transparent); }
.rev-pick .ci-thumb { width: 44px; height: 56px; flex: none; }
/* Las estrellas del formulario son botones grandes: puntuar es la única acción
   obligatoria de la pantalla y con el pulgar hay que acertarlas a la primera. */
.rev-stars-input { display: flex; gap: 4px; }
.rev-star {
  border: none; background: none; cursor: pointer;
  font-size: 30px; line-height: 1; padding: 2px 4px;
  color: var(--line);
}
.rev-star.on { color: var(--star); }
.rev-textarea {
  width: 100%; resize: vertical;
  padding: 10px; border: 1px solid var(--line); border-radius: 10px;
  background: var(--card); color: var(--ink);
  font: inherit; font-size: 13px;
}
.rev-photo-pick {
  display: flex; align-items: center; justify-content: center; gap: 7px;
  padding: 12px; border: 1px dashed var(--line); border-radius: 12px;
  color: var(--muted); font-size: 12px; font-weight: 700; cursor: pointer;
}
.rev-photo-pick:hover { border-color: var(--accent); color: var(--accent); }
.rev-photo-wrap { display: flex; align-items: flex-start; gap: 10px; }
.rev-photo-del {
  display: flex; align-items: center; gap: 5px;
  border: none; background: none; cursor: pointer;
  color: var(--muted); font-size: 12px; font-weight: 700;
}
.rev-photo-del:hover { color: var(--danger, #b3261e); }
