/* ======================================================================
     SISTEMA "NIVEL" — segunda generación de diseño (sep 2026).
     Amarillo señal + Big Shoulders Display/Instrument Sans, en vez del
     turquesa/Montserrat original. Ver DESIGN.md para el porqué completo.
  ====================================================================== */
  :root {
    --ink: #121212;
    --white: #FFFFFF;
    --gray-50: #F6F5F1;
    --gray-100: #EFEDE7;
    --gray-200: #E2DFD6;
    --gray-400: #A6A296;
    --gray-600: #66625A;
    --accent: #F2C200; /* 11,1:1 sobre --ink (uso libre ahí); 1,7:1 sobre blanco — SOLO decorativo/no-texto sobre fondos claros */
    --accent-text: #6B4E00; /* variante AA-safe (7,7:1 sobre blanco) para texto normal, botones y labels sobre fondo claro */
    --accent-pale: #FBF3D6;
    --green: #1C6143;
    --green-pale: #E1EEE7;
    --amber: #A8480A; /* naranja quemado: alerta semántica, deliberadamente distinta del amarillo de marca para no confundir "atención" con "es de Ponele Precio" */
    --amber-pale: #F7E4D6;
    --red: #B3261E;
    --red-pale: #F6E1DF;

    --radius-sm: 8px;
    --radius: 12px;
    --radius-pill: 999px;
    --shadow: 0 1px 2px rgba(17,17,17,0.04), 0 8px 24px rgba(17,17,17,0.06);
    --font-display: 'Big Shoulders Display', 'Arial Narrow', sans-serif; /* titulares, números protagonistas — nunca body */
    --font-body: 'Instrument Sans', -apple-system, sans-serif;
    --font-mono: var(--font-body); /* sin tipografía monoespaciada — pedido explícito de Flor. Se mantiene el nombre de variable por compatibilidad con .mono (solo activa tabular-nums), no carga ninguna fuente mono. */
  }

  * { box-sizing: border-box; }
  html, body { margin: 0; padding: 0; }
  body {
    background: var(--white);
    color: var(--ink);
    font-family: var(--font-body);
    font-weight: 500; /* piso de peso tipográfico — nada de regular/light, pedido explícito de Flor */
    -webkit-font-smoothing: antialiased;
    font-size: 16px;
    line-height: 1.5;
  }
  .mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
  button, input, select { font-family: inherit; }
  input[type="text"], input[type="number"] {
    font-size: 1rem; /* evita auto-zoom iOS */
  }

  .wrap { max-width: 1180px; margin: 0 auto; padding: 0 20px; }

  /* ---------- topbar ---------- */
  .topbar {
    border-bottom: 1px solid var(--gray-200);
    padding: 16px 0;
    position: sticky; top: 0; background: var(--white); z-index: 40;
  }
  .topbar-inner { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
  .brand {
    font-family: var(--font-display); font-weight: 800; font-size: 1.25rem; text-transform: uppercase;
    letter-spacing: 0.01em; display: flex; align-items: center; gap: 8px; min-width: 0;
  }
  .brand .dot { color: var(--accent-text); }
  .brand-icon { display: none; flex-shrink: 0; color: var(--accent-text); }
  .brand-icon svg { width: 26px; height: 26px; display: block; }
  /* En mobile el wordmark se pisaba con "Mi negocio": queda solo el ícono,
     pero el texto sigue en el DOM (oculto a la vista, no al lector de pantalla). */
  @media (max-width: 560px) {
    .brand-icon { display: block; }
    .brand-text {
      position: absolute; width: 1px; height: 1px; margin: -1px;
      padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
    }
  }
  .topbar-actions { display: flex; gap: 8px; }
  .btn-negocio {
    display: flex; align-items: center; gap: 6px; white-space: nowrap; flex-shrink: 0;
    border: 1.5px solid var(--ink); background: transparent; color: var(--ink);
    font-weight: 700; font-size: 0.875rem; padding: 9px 14px; border-radius: var(--radius-pill);
    min-height: 44px; cursor: pointer;
  }
  @media (max-width: 380px) { .btn-negocio { padding: 9px 12px; } }
  .btn-negocio:hover { background: var(--ink); color: var(--white); }
  .btn-negocio svg { width: 15px; height: 15px; }
  /* En el paso 1 ya estás en "Tu negocio": el botón no tiene a dónde llevarte
     y quedaba raro poder clickearlo sin que pase nada. Se apaga en vez de
     desaparecer, para que el header no salte de ancho al cambiar de paso. */
  .btn-negocio:disabled { opacity: 0.4; cursor: not-allowed; }
  .btn-negocio:disabled:hover { background: transparent; color: var(--ink); }

  /* ---------- buttons ---------- */
  .btn { font-family: inherit; font-weight: 700; font-size: 0.9rem; padding: 13px 22px; border-radius: var(--radius-sm); cursor: pointer; border: none; display: inline-flex; align-items: center; justify-content: center; gap: 8px; min-height: 48px; }
  /* Pedido explícito de Flor: el botón principal es el amarillo de marca a
     pleno (--accent), con texto en tinta — no la variante mostaza que se usa
     para texto sobre blanco. 11,1:1 de contraste, de sobra para AA. */
  .btn-primary { background: var(--accent); color: var(--ink); }
  .btn-primary:hover { background: #D5AB00; }
  .btn-primary:disabled { background: var(--gray-400); color: var(--ink); cursor: not-allowed; }
  .btn-secondary { background: transparent; color: var(--ink); border: 1.5px solid var(--ink); }
  .btn-secondary:hover { background: var(--gray-100); }
  .btn-danger-ghost { background: transparent; color: var(--red); border: none; font-size: 0.875rem; font-weight: 700; padding: 6px 8px; cursor: pointer; }
  /* "Empezar de nuevo": antes era un link subrayado casi invisible al pie.
     Ahora tiene el mismo peso visual que un botón secundario, con ícono, para
     que se note que es una acción real (borra el producto actual) y no un
     detalle menor. */
  .btn-restart { background: var(--gray-50); color: var(--ink); border: 1.5px solid var(--ink); }
  .btn-restart:hover { background: var(--ink); color: #fff; }
  .btn-block { width: 100%; }
  .btn-sm { padding: 9px 14px; font-size: 0.875rem; min-height: 40px; }
  /* Sin esto, tabular con el teclado hacía aparecer el anillo azul por default
     del navegador — el único lugar de toda la app donde asoma un color que no
     es de acá. Mismo --accent-text que ya usan los inputs al enfocar. */
  .btn:focus-visible, .btn-negocio:focus-visible, .modal-close-btn:focus-visible, .btn-link-sm:focus-visible {
    outline: 2px solid var(--accent-text); outline-offset: 2px;
  }
  .radio-pill:has(input:focus-visible) { outline: 2px solid var(--accent-text); outline-offset: 2px; }

  /* ---------- steps ---------- */
  .steps-nav { padding: 24px 0 8px; }
  .steps-dots { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
  .step-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--gray-200); flex-shrink: 0; }
  .step-dot.done { background: var(--ink); }
  .step-dot.active { background: var(--accent); width: 22px; border-radius: 4px; }
  .step-label { font-family: var(--font-mono); font-size: 0.875rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--gray-600); }

  .layout { display: grid; grid-template-columns: 1.5fr 1fr; gap: 32px; padding: 24px 0 32px; align-items: start; }
  @media (max-width: 860px) { .layout { grid-template-columns: 1fr; } }

  .panel { min-width: 0; }
  .step { display: none; }
  .step.active { display: block; animation: fadein .25s ease; }
  @keyframes fadein { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }

  /* ---------- "Mi negocio" como modal ----------
     El paso 1 (Tu negocio) es la MISMA marca de HTML tanto para el onboarding
     (primer ingreso, dentro del wizard) como para el botón "Mi negocio" desde
     cualquier otro paso — así no hay dos copias de los mismos campos con el
     mismo id. La clase .as-modal solo cambia cómo se POSICIONA ese paso, saca
     el goTo() del medio: no se pierde en qué paso del producto estabas. */
  .negocio-modal-bar { display: none; }
  .negocio-modal-footer { display: none; } /* mismo criterio: solo existe dentro del modal */
  .negocio-scroll { display: contents; } /* fuera del modal: no hace nada, el contenido sigue en flujo normal */
  /* Antes el header era `position: sticky` DENTRO del mismo contenedor que
     scrollea (el fondo oscuro completo). En desktop ese contenedor tiene
     padding para centrar la card, así que el header "sticky" terminaba
     pegado al borde del VIEWPORT, no al borde de la card — al scrollear
     hacia arriba quedaba un hueco entre el header y el resto de la placa.
     Ahora la card es un contenedor flex de alto fijo: el header es un item
     que nunca scrollea (flex-shrink: 0) y solo `.negocio-scroll` scrollea
     puertas adentro. El resto de la interfaz queda congelado igual que antes
     (el fondo oscuro no tiene scroll propio). */
  .step[data-step="1"].as-modal {
    display: flex; align-items: center; justify-content: center;
    position: fixed; inset: 0; z-index: 300;
    background: rgba(17,17,17,0.55);
    padding: 0; animation: fadein .2s ease;
  }
  .step[data-step="1"].as-modal .negocio-inner {
    display: flex; flex-direction: column;
    width: 100%; height: 100%;
    background: var(--white);
  }
  .step[data-step="1"].as-modal .negocio-modal-bar {
    display: flex; align-items: center; justify-content: space-between;
    flex-shrink: 0;
    padding: 18px 20px;
    background: var(--white); border-bottom: 1px solid var(--gray-200);
    font-weight: 800; font-size: 1rem;
  }
  .step[data-step="1"].as-modal .negocio-scroll {
    display: block; flex: 1 1 auto; min-height: 0; /* min-height:0 es lo que deja que un hijo flex scrollee en vez de estirar el padre */
    overflow-y: auto; -webkit-overflow-scrolling: touch;
    padding: 20px 20px 40px;
  }
  /* Footer fijo del modal: mismo trato que el header, un item de flex que
     nunca scrollea. Vive fuera de .negocio-scroll a propósito. */
  .step[data-step="1"].as-modal .negocio-modal-footer {
    display: flex; flex-shrink: 0;
    padding: 16px 20px calc(16px + env(safe-area-inset-bottom, 0px));
    background: var(--white); border-top: 1px solid var(--gray-200);
  }
  .step[data-step="1"].as-modal .negocio-modal-footer .btn { width: 100%; }
  .modal-close-btn {
    background: var(--gray-100); border: none; width: 44px; height: 44px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center; cursor: pointer; color: var(--ink); flex-shrink: 0;
  }
  .modal-close-btn svg { width: 17px; height: 17px; }
  .modal-close-btn:hover { background: var(--gray-200); }
  @media (min-width: 640px) {
    /* 90% de alto, con aire arriba y abajo: nunca toca los bordes del navegador. */
    .step[data-step="1"].as-modal { padding: 5vh 20px; }
    .step[data-step="1"].as-modal .negocio-inner {
      width: 100%; max-width: 640px; height: 90vh;
      border-radius: var(--radius); box-shadow: 0 20px 60px rgba(17,17,17,0.35);
      overflow: hidden; /* recorta las esquinas del header/scroll al radio redondeado */
    }
    .step[data-step="1"].as-modal .negocio-modal-bar { padding: 20px 28px; }
    .step[data-step="1"].as-modal .negocio-scroll { padding: 20px 28px 32px; }
    .step[data-step="1"].as-modal .negocio-modal-footer { padding: 16px 28px; }
    .step[data-step="1"].as-modal .negocio-modal-footer .btn { width: auto; margin-left: auto; }
  }

  .step-eyebrow { font-size: 0.875rem; text-transform: uppercase; letter-spacing: 0.1em; color: var(--accent-text); font-weight: 700; margin: 0 0 10px; }
  h1 {
    font-family: var(--font-display); font-size: clamp(2.4rem, 5.2vw, 3.4rem); font-weight: 900;
    letter-spacing: -0.01em; line-height: 0.96; margin: 0 0 10px; text-wrap: balance;
  }
  .step-sub { color: var(--gray-600); font-size: 1rem; margin: 0 0 28px; max-width: 480px; line-height: 1.55; }

  .card { background: #fff; border: 1px solid var(--gray-200); border-radius: var(--radius); padding: 22px; margin-bottom: 16px; box-shadow: var(--shadow); position: relative; }
  .card.example {
    box-shadow: none; background: var(--gray-50);
    border: 2px dashed var(--gray-400);
  }
  .card-title { font-size: 1.0625rem; font-weight: 800; margin: 0 0 4px; letter-spacing: -0.01em; }
  .card-sub { font-size: 0.9375rem; color: var(--gray-600); margin: 0 0 16px; line-height: 1.5; }
  .card-title + .radio-group, .card-title + .field { margin-top: 14px; }
  /* Separa visualmente las dos partes de cargar un material: lo que compraste
     vs. lo que usaste en una pieza. Sin esto se lee como una lista de campos
     sueltos y no queda claro que el precio es del paquete entero. */
  .mat-step-lbl {
    font-size: 0.875rem; font-weight: 800; letter-spacing: 0.04em; text-transform: uppercase;
    color: var(--accent-text); margin: 20px 0 12px; padding-top: 16px; border-top: 1px dashed var(--gray-200);
  }
  .field-hint { font-size: 0.875rem; color: var(--gray-600); line-height: 1.45; }
  /* Aviso de "consultá con tu contador": alerta semántica (--amber), informativo,
     no alarma. A propósito NO usa el amarillo de marca (--accent) — si usara el
     mismo amarillo, se leería como "esto es de Ponele Precio" en vez de "prestale
     atención a esto". Va con ícono para que se lea distinto del resto de las
     ayudas grises. */
  .nota-contador {
    display: flex; align-items: flex-start; gap: 11px;
    background: var(--amber-pale); border: 1px solid #E8C1A3; border-radius: var(--radius-sm);
    padding: 13px 15px; margin-top: 14px;
  }
  .nota-contador-ico { flex-shrink: 0; color: var(--amber); line-height: 0; margin-top: 1px; }
  .nota-contador-ico svg { width: 19px; height: 19px; }
  .nota-contador p { margin: 0; font-size: 0.9375rem; line-height: 1.5; color: var(--ink); }
  .nota-contador b { color: var(--ink); font-weight: 800; }

  .check-row {
    display: flex; align-items: flex-start; gap: 10px; cursor: pointer;
    margin-top: 16px; font-size: 0.9375rem; font-weight: 600; line-height: 1.45;
  }
  .check-row input { width: 22px; height: 22px; flex-shrink: 0; accent-color: var(--accent-text); margin: 0; cursor: pointer; }
  .check-row input:focus-visible { outline: 2px solid var(--accent-text); outline-offset: 2px; }
  .inp-sufijo { position: absolute; right: 12px; font-size: 0.9375rem; font-weight: 700; color: var(--gray-600); pointer-events: none; }
  .inp-wrap input.has-sufijo { padding-right: 32px; }
  .example-tag {
    font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.03em;
    color: var(--ink); background: var(--accent);
    padding: 5px 10px; border-radius: 6px; display: inline-block;
    margin: -6px 0 14px 2px;
  }

  .card-head { display: flex; align-items: flex-start; gap: 10px; margin-bottom: 18px; }
  .item-title-wrap { flex: 1; min-width: 0; }
  .item-name-input {
    font-weight: 700; font-size: 0.9375rem; width: 100%;
    padding: 11px 12px; min-height: 48px;
    border: 1.5px solid var(--gray-200); border-radius: var(--radius-sm); background: var(--white); color: var(--ink);
  }
  .item-name-input::placeholder { font-weight: 500; color: var(--gray-600); }
  /* --accent (amarillo puro) da 1,68:1 sobre blanco: no llega al 3:1 mínimo de
     WCAG para indicadores de foco. --accent-text sí (7,74:1). Se suma un halo
     sutil para que el foco se note incluso a simple vista, no solo en el borde. */
  .item-name-input:focus { outline: none; border-color: var(--accent-text); box-shadow: 0 0 0 3px rgba(107,78,0,0.15); }

  .field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
  .field-row.three { grid-template-columns: 1fr 1fr 1fr; }
  @media (max-width: 480px) { .field-row, .field-row.three { grid-template-columns: 1fr; } }
  .field { display: flex; flex-direction: column; gap: 6px; }
  .field label { font-size: 0.875rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--gray-600); }
  .inp-wrap { position: relative; display: flex; align-items: center; }
  .inp-prefix { position: absolute; left: 12px; font-family: var(--font-mono); font-size: 0.9375rem; color: var(--gray-600); pointer-events: none; }
  .inp-wrap input, .inp-wrap select {
    width: 100%; font-family: var(--font-mono); font-size: 0.95rem; padding: 11px 12px;
    border: 1.5px solid var(--gray-200); border-radius: var(--radius-sm); background: var(--white); color: var(--ink);
    min-height: 48px;
  }
  .inp-wrap input.has-prefix { padding-left: 26px; }
  /* La flechita nativa del navegador no sigue el sistema (grosor de trazo,
     color de tinta): se reemplaza por una propia, mismo lenguaje que el resto
     de los íconos de línea del proyecto. */
  .inp-wrap select {
    appearance: none; -webkit-appearance: none; -moz-appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23121212' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat; background-position: right 12px center; background-size: 16px;
    padding-right: 36px; cursor: pointer;
  }
  .inp-wrap input:focus, .inp-wrap select:focus, .type-select:focus { outline: none; border-color: var(--accent-text); box-shadow: 0 0 0 3px rgba(107,78,0,0.15); }
  .type-select { font-family: inherit; font-size: 0.9375rem; font-weight: 700; padding: 8px 10px; border: 1.5px solid var(--gray-200); border-radius: var(--radius-pill); background: var(--gray-50); }

  .item-cost { font-family: var(--font-mono); font-size: 0.9375rem; color: var(--gray-600); margin-top: 12px; padding-top: 12px; border-top: 1px dashed var(--gray-200); display: flex; justify-content: space-between; gap: 10px; }
  /* Sin white-space/flex-shrink acá, con una etiqueta larga ("Total de gastos
     fijos por mes") en 320px el monto se aprieta y el "$ 0" se corta en dos
     líneas ($ arriba, 0 abajo). Que la etiqueta envuelva, no el monto. */
  .item-cost b { color: var(--ink); font-weight: 500; white-space: nowrap; flex-shrink: 0; }

  .add-row { display: flex; gap: 10px; margin-top: 8px; flex-wrap: wrap; }
  /* "+ Servicio"/"+ Otro gasto fijo"/"+ Herramienta o máquina" quedaban chicos
     (94×40px) al lado de inputs full-width en la misma card. En mobile pasan
     a ocupar todo el ancho, como ya hace "+ Agregar material". */
  @media (max-width: 640px) { .add-row .btn { flex: 1 1 100%; } }

  .helper-hint { font-size: 0.875rem; color: var(--gray-600); background: var(--gray-50); border-radius: var(--radius-sm); padding: 14px 16px; margin-top: 10px; line-height: 1.6; }
  .helper-hint b { color: var(--ink); }
  /* Ejemplo del paso 2: era un párrafo corrido con 5 valores en bold seguidos
     — se leía, pero costaba separar "esto es lo que compraste" de "esto es lo
     que usaste". Ahora cada valor es su propio campito, como una previsualización
     de los inputs de abajo, para que el ejemplo se vea como se va a completar. */
  .helper-example { position: relative; padding-right: 48px; }
  .helper-example p { margin: 0 0 8px; }
  .helper-example p:last-of-type { margin-top: 4px; }
  .helper-example-close { position: absolute; top: 10px; right: 10px; width: 28px; height: 28px; }
  .helper-example-close svg { width: 14px; height: 14px; }
  .example-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0 0 12px; }
  .example-chips:last-child { margin-bottom: 0; }
  .example-chip {
    display: flex; flex-direction: column; gap: 2px; min-width: 74px;
    background: var(--white); border: 1px solid var(--gray-200); border-radius: var(--radius-sm);
    padding: 6px 12px;
  }
  .example-chip-lbl { font-size: 0.6875rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--gray-600); }
  .example-chip-val { font-family: var(--font-mono); font-weight: 700; font-size: 0.9375rem; color: var(--ink); }
  .example-chip-result { background: var(--accent-pale); border-color: transparent; }
  .example-chip-result .example-chip-val { color: var(--accent-text); }
  .example-arrow { color: var(--gray-400); font-weight: 700; font-size: 1.125rem; }

  /* ---------- slider ---------- */
  .slider-block { margin-top: 22px; padding-top: 20px; border-top: 1px solid var(--gray-200); }
  .slider-label-row { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 10px; }
  .slider-label-row label { font-size: 0.875rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--gray-600); }
  .slider-value { font-size: 1.375rem; font-weight: 800; color: var(--accent-text); font-variant-numeric: tabular-nums; }
  input[type="range"] {
    -webkit-appearance: none; appearance: none;
    width: 100%; height: 6px; border-radius: 3px;
    background: var(--gray-200); outline: none; margin: 6px 0;
  }
  input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none; appearance: none;
    width: 26px; height: 26px; border-radius: 50%;
    background: var(--accent-text); border: 3px solid #fff;
    box-shadow: 0 1px 5px rgba(17,17,17,0.28); cursor: pointer;
  }
  input[type="range"]::-moz-range-thumb {
    width: 26px; height: 26px; border-radius: 50%;
    background: var(--accent-text); border: 3px solid #fff;
    box-shadow: 0 1px 5px rgba(17,17,17,0.28); cursor: pointer;
  }
  input[type="range"]:focus-visible { outline: 2px solid var(--accent-text); outline-offset: 4px; }
  .slider-ticks { display: flex; justify-content: space-between; font-size: 0.875rem; font-weight: 600; color: var(--gray-600); margin-top: 2px; }
  .slider-hint { font-size: 0.9375rem; font-weight: 600; color: var(--ink); margin: 12px 0 0; }

  /* Salud del margen: mide el multiplicador sobre el costo variable (materiales
     + tiempo), NO si el negocio en conjunto anda bien — para eso está el punto
     de equilibrio del paso siguiente, que sí conoce los gastos fijos. Por eso
     el badge siempre lleva la aclaración de scope debajo, no solo el color. */
  .margen-salud { display: flex; align-items: center; gap: 10px; margin-top: 16px; flex-wrap: wrap; }
  .margen-salud-badge {
    display: inline-flex; align-items: center; gap: 6px;
    font-size: 0.875rem; font-weight: 800; padding: 6px 12px; border-radius: var(--radius-pill);
  }
  .margen-salud-badge .dot { width: 8px; height: 8px; border-radius: 50%; background: currentColor; }
  .margen-salud-badge.rojo { background: var(--red-pale); color: var(--red); }
  .margen-salud-badge.ambar { background: var(--amber-pale); color: var(--amber); }
  .margen-salud-badge.verde { background: var(--green-pale); color: var(--green); }
  .margen-salud-nota { font-size: 0.875rem; color: var(--gray-600); }

  /* ---------- summary sidebar: PLACA — chapa de instrumento, no otra card gris.
     Antes era un ticket de papel (fondo claro, zigzag de borde rasgado). Ahora
     es la chapa metálica de una herramienta: fondo oscuro, remaches en las
     cuatro esquinas, un filo de línea grabada por dentro, y el número
     protagonista en el amarillo de marca (11:1 de contraste sobre esta base,
     ver :root — es justo el fondo donde ESE amarillo funciona como texto). */
  .summary-wrap { position: sticky; top: 88px; }
  @media (max-width: 860px) { .summary-wrap { position: static; margin-top: 8px; } }
  .summary {
    position: relative;
    background: var(--ink); color: #fff;
    padding: 26px 22px 24px;
    border-radius: var(--radius-sm);
    box-shadow: 0 14px 30px rgba(18,18,18,0.22), 0 2px 6px rgba(18,18,18,0.16);
    transition: opacity .2s ease;
  }
  /* Sin materiales ni tiempo cargados todavía no hay precio real: se atenúa
     para que se note de un vistazo que es una placa vacía, no la final. */
  .summary.is-empty { opacity: 0.55; }
  .summary::before {
    content: ""; position: absolute; inset: 9px; border: 1px dashed rgba(255,255,255,0.16);
    border-radius: 4px; pointer-events: none;
  }
  .plate-rivets span { position: absolute; width: 6px; height: 6px; border-radius: 50%; background: rgba(255,255,255,0.28); }
  .plate-rivets span:nth-child(1) { top: 11px; left: 11px; }
  .plate-rivets span:nth-child(2) { top: 11px; right: 11px; }
  .plate-rivets span:nth-child(3) { bottom: 11px; left: 11px; }
  .plate-rivets span:nth-child(4) { bottom: 11px; right: 11px; }

  .summary-label { font-size: 0.875rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.08em; color: rgba(255,255,255,0.6); margin: 0 0 18px; }

  .summary-line { display: flex; align-items: baseline; gap: 6px; padding: 8px 0; }
  .summary-line .lbl { font-size: 0.875rem; font-weight: 700; color: #fff; white-space: nowrap; }
  .summary-line .leader { flex: 1; min-width: 12px; border-bottom: 1.5px solid rgba(255,255,255,0.18); margin-bottom: 3px; }
  .summary-line .val { font-size: 0.9375rem; font-weight: 700; color: #fff; white-space: nowrap; }
  /* .summary-empty se reutiliza en 4 lugares con fondo claro (gastos, equipos,
     lista de plataformas) y solo UNO con fondo oscuro (#summaryLines, dentro
     de la placa) — el color base tiene que ser el de fondo claro; el oscuro
     es la excepción, no al revés. Quedó al revés durante el rediseño y el
     texto se volvió invisible en los otros tres lugares. */
  .summary-empty { font-size: 0.875rem; color: var(--gray-600); padding: 6px 0; }
  .summary .summary-empty { color: rgba(255,255,255,0.55); }

  .summary-total { margin-top: 14px; padding-top: 16px; border-top: 2px solid var(--accent); }
  .summary-total .lbl { font-size: 0.875rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.06em; color: rgba(255,255,255,0.6); margin-bottom: 4px; }
  .summary-total .price {
    font-family: var(--font-display); font-weight: 900; font-size: 3.1rem; line-height: 0.95;
    color: var(--accent); letter-spacing: -0.01em; display: flex; align-items: baseline; gap: 3px;
    font-variant-numeric: tabular-nums;
  }
  .summary-total .price .cur { font-size: 1.375rem; }
  .summary-total .price-sub { font-size: 0.875rem; color: rgba(255,255,255,0.55); margin-top: 6px; }

  /* Tira de escala: reemplaza el código de barras del ticket viejo. Dos
     densidades de marca (mayor/menor) como una regla, no como un ticket de compra. */
  .summary-barcode {
    margin-top: 22px; height: 20px;
    background:
      repeating-linear-gradient(90deg, rgba(255,255,255,0.85) 0 1.5px, transparent 1.5px 22px),
      repeating-linear-gradient(90deg, rgba(255,255,255,0.28) 0 1px, transparent 1px 7.333px);
  }

  .be-box { margin-top: 16px; background: rgba(242,194,0,0.14); border: none; border-radius: var(--radius-sm); padding: 13px 14px; font-size: 0.9375rem; line-height: 1.55; color: #fff; }
  .be-box b { font-weight: 800; color: var(--accent); }
  .be-box.warn { background: rgba(168,72,10,0.28); }
  .be-box.warn b { color: #FFB37A; }

  /* ---------- barra de acciones global (fija) ----------
     Reemplaza los .step-actions sueltos de cada paso: antes se perdían al
     hacer scroll, ahora "Atrás"/el botón principal están siempre a mano, en
     cualquier paso y cualquier ancho. En mobile incluye el precio en vivo
     (reemplaza a la vieja .price-bar, que aparecía/desaparecía con el scroll);
     en desktop no hace falta, la placa de resultado ya está siempre visible
     en el costado. */
  .action-bar {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 70;
    background: var(--white); border-top: 1px solid var(--gray-200);
  }
  .action-bar-inner { padding-top: 12px; padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px)); }
  .action-bar-price { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 10px; }
  .action-bar-price-lbl { font-size: 0.8125rem; font-weight: 600; color: var(--gray-600); }
  .action-bar-price-val { font-size: 1.0625rem; font-weight: 800; color: var(--ink); }
  .action-bar-price.is-incomplete .action-bar-price-val { color: var(--gray-400); }
  .action-bar-buttons { display: flex; gap: 10px; }
  .action-bar-buttons #actionBarBack { display: none; flex: 1 1 0; }
  .action-bar-buttons #actionBarBack.show { display: inline-flex; }
  .action-bar-buttons #actionBarPrimary { flex: 1.6 1 0; }
  /* Body deja lugar para la barra: dos alturas porque en mobile tiene además
     la fila de precio. Los valores son generosos a propósito, sobra antes
     que se coma el último renglón de contenido. */
  body { padding-bottom: 128px; }
  @media (min-width: 860px) {
    body { padding-bottom: 84px; }
    .action-bar-price { display: none; }
    .action-bar-inner { padding-top: 16px; padding-bottom: 16px; }
    /* flex-end (no space-between) + margin-left:auto en "Atrás": con
       space-between, en el paso 1 (sin "Atrás", display:none) el único
       botón que queda ("Siguiente") se pegaba a la IZQUIERDA — un elemento
       solo con justify-content:space-between se alinea al inicio. El botón
       principal tiene que quedar siempre en el mismo lugar (a la derecha) en
       los 6 pasos, para no reubicarse cada vez que cambia de paso. */
    .action-bar-buttons { justify-content: flex-end; }
    .action-bar-buttons #actionBarBack, .action-bar-buttons #actionBarPrimary { flex: 0 0 auto; }
    .action-bar-buttons #actionBarBack.show { margin-right: auto; }
  }

  /* ---------- platforms result ---------- */
  .platform-card { border: 1px solid var(--gray-200); border-radius: var(--radius); padding: 18px; margin-bottom: 12px; }
  .platform-card.direct { background: var(--gray-50); }
  /* Un porcentaje ≥100% (o una combinación de impuestos + comisión que ya
     se come el precio entero) no tiene una cuenta posible: se bloquea acá
     en vez de mostrar un precio inventado. Mismo rojo que el resto del
     sistema para errores (--red / --red-pale). */
  .platform-error { background: var(--red-pale); border-radius: var(--radius); padding: 16px 18px; color: var(--red); }
  .platform-error b { display: block; margin-bottom: 4px; font-size: 1rem; }
  .platform-error p { font-size: 0.9375rem; line-height: 1.5; color: var(--ink); }
  /* Antes name/precio iban con justify-content:space-between a secas: en
     tarjetas anchas (tablet, ~700-900px) eso dejaba un tramo de espacio vacío
     entre los dos. Se suma una línea guía (mismo recurso que ya usa la placa
     en .summary-line .leader) para que ese espacio se lea como diseñado, no
     como vacío sin terminar, sea cual sea el ancho de la card. */
  .platform-head { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; flex-wrap: wrap; }
  .platform-head .leader { flex: 1; min-width: 16px; border-bottom: 1.5px solid var(--gray-200); margin-bottom: 2px; }
  /* Pedido de Flor: el nombre de la plataforma es lo primero que se lee (más
     grande, más peso); el precio pasa a ser un badge, un dato de apoyo, no
     el elemento más grande de la card. */
  .platform-name { font-weight: 800; font-size: 1.1875rem; display: flex; align-items: center; gap: 8px; }
  .platform-name svg { width: 20px; height: 20px; flex-shrink: 0; color: var(--ink); }
  .platform-sub { font-size: 0.875rem; color: var(--gray-600); margin: 0 0 10px; }
  .platform-price {
    font-family: var(--font-mono); font-weight: 800; font-size: 1rem; white-space: nowrap;
    background: var(--accent-pale); border: 1px solid transparent; color: var(--accent-text);
    border-radius: var(--radius-pill); padding: 6px 14px;
  }
  .platform-price.is-range { font-size: 0.875rem; } /* el rango ($X–$Y) es más largo que un precio solo */
  .platform-comm { font-family: var(--font-mono); font-size: 0.875rem; color: var(--gray-600); }
  .platform-tip { font-size: 0.875rem; color: var(--gray-600); margin-top: 8px; padding-top: 8px; border-top: 1px dashed var(--gray-200); line-height: 1.5; }
  /* En mobile angosto (~320-360px) nombre + badge en la misma fila se pisan
     si el precio es un rango largo: se apilan en vez de achicarse más. */
  @media (max-width: 400px) {
    .platform-head { flex-direction: column; align-items: flex-start; gap: 8px; }
    .platform-head .leader { display: none; }
  }

  .ml-comision-edit {
    display: flex; align-items: flex-end; gap: 14px; flex-wrap: wrap;
    margin-top: 14px; padding-top: 14px; border-top: 1px dashed var(--gray-200);
  }
  /* En mobile el campo va compacto; en desktop hay mucho más ancho disponible
     en la card y el mismo tamaño se veía chico y desproporcionado. */
  /* Campos de porcentaje (IIBB, comisión de ML): el dato es corto, pero en
     mobile van al 100% igual que cualquier otro input, más fácil de tocar y
     sin la excepción rara de "este campo sí, el resto no". El ancho angosto
     es una decisión de desktop, donde 700px de "3%" sí se vería raro. */
  @media (min-width: 640px) { .ml-comision-field { max-width: 300px; } }
  @media (min-width: 640px) { .field-iibb-tasa { max-width: 200px; } }
  /* Mobile-first: sin límite (va al 100%, como el resto de los inputs del
     wizard). El límite de 360px es una decisión de desktop, no de mobile. */
  @media (min-width: 641px) { .field-product-name { max-width: 360px; } }
  .btn-link-sm {
    background: none; border: none; padding: 0; margin-bottom: 13px; cursor: pointer;
    color: var(--accent-text); font-weight: 700; font-size: 0.875rem; text-decoration: underline;
  }

  /* ---------- gastos del negocio (paso 1) ---------- */
  .gasto-row {
    display: grid; grid-template-columns: 1fr 130px auto; gap: 10px; align-items: end;
    padding: 14px 0; border-bottom: 1px dashed var(--gray-200);
  }
  .gasto-row--equipo { grid-template-columns: 1fr 120px 120px auto; }
  .gasto-row:first-child { padding-top: 0; }
  .gasto-field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
  .gasto-field label { font-size: 0.875rem; font-weight: 700; letter-spacing: 0.03em; text-transform: uppercase; color: var(--gray-600); }
  .gasto-row input { min-height: 48px; }
  .gasto-del { align-self: end; margin-bottom: 12px; white-space: nowrap; }
  .gasto-calc {
    grid-column: 1 / -1; margin: 4px 0 0;
    font-size: 0.9375rem; color: var(--gray-600);
  }
  .gasto-calc b { color: var(--accent-text); font-weight: 800; }
  .total-card { display: flex; align-items: center; }
  .total-card .item-cost { width: 100%; font-size: 1rem; }
  .total-card .item-cost b { font-size: 1.25rem; font-weight: 800; }
  /* Bajo 640px cada gasto se apila: si no, el input de monto se corta y el
     botón Quitar queda fuera de pantalla. */
  @media (max-width: 640px) {
    .gasto-row, .gasto-row--equipo { grid-template-columns: 1fr; gap: 12px; }
    .gasto-del { justify-self: start; margin-bottom: 0; padding-left: 0; }
  }

  .radio-group { display: flex; gap: 10px; flex-wrap: wrap; }
  .radio-pill { position: relative; border: 1.5px solid var(--gray-200); border-radius: var(--radius-pill); padding: 10px 16px; font-size: 0.9375rem; font-weight: 600; cursor: pointer; }
  /* Variante compacta: mismas reglas de accesibilidad (input oculto solo
     visualmente), pero para vivir DENTRO de una platform-card ya densa
     (opciones de cuotas de ML, timing de MercadoPago, plan de TiendaNube),
     donde el tamaño normal de .radio-pill se siente desproporcionado. */
  .radio-group-sm { gap: 8px; }
  .radio-group-sm .radio-pill { padding: 6px 12px; font-size: 0.8125rem; }
  /* Sub-bloque de opciones dentro de una platform-card (cuotas, costo por
     unidad, plan/medio de pago): mismo patrón visual que .ml-comision-edit
     (separador punteado arriba) pero apilado, no en fila, porque el label +
     los radios + un input condicional no entran cómodos en una sola línea. */
  .ml-sub-option {
    margin-top: 14px; padding-top: 14px; border-top: 1px dashed var(--gray-200);
    display: flex; flex-direction: column; gap: 10px;
  }
  .ml-sub-option > label { font-size: 0.875rem; font-weight: 700; letter-spacing: 0.03em; text-transform: uppercase; color: var(--gray-600); }
  /* Hallazgo al agregar el anillo de foco (Fase 3): con display:none el radio
     no solo queda invisible, queda AFUERA del tabulado — con teclado o lector
     de pantalla era imposible llegar a "Monotributo"/"Responsable Inscripto".
     Se oculta solo visualmente (mismo recurso que .brand-text), no del todo. */
  .radio-pill input {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
  }
  .radio-pill.checked { border-color: var(--ink); background: var(--ink); color: #fff; }

  .toast { position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); background: var(--ink); color: #fff; padding: 12px 20px; border-radius: var(--radius-pill); font-size: 0.9375rem; font-weight: 600; z-index: 200; opacity: 0; pointer-events: none; transition: opacity .2s ease, transform .2s ease; }

  .toast.show { opacity: 1; transform: translateX(-50%) translateY(-6px); }

  .device-note { font-size: 0.875rem; color: var(--gray-600); line-height: 1.5; background: var(--gray-50); border-radius: var(--radius-sm); padding: 10px 12px; margin-top: 4px; }

  footer { padding: 28px 0; text-align: center; border-top: 1px solid var(--gray-200); }
  footer p { font-size: 0.875rem; color: var(--gray-600); }
  /* Aclara el alcance de la tool antes de la firma: dispositivo único, sin
     historial. Que quede claro que esto calcula un precio, no organiza un
     negocio entero, para que nadie espere un sistema que no es. */
  .footer-scope {
    display: flex; align-items: flex-start; gap: 10px; text-align: left;
    max-width: 480px; margin: 0 auto 18px; padding: 14px 16px;
    background: var(--gray-50); border-radius: var(--radius-sm); line-height: 1.55;
  }
  .footer-scope svg { width: 20px; height: 20px; flex-shrink: 0; margin-top: 1px; color: var(--accent-text); }

  /* ======================================================================
     PDF / IMPRESIÓN — ficha de costos.
     Mismo lenguaje visual que la app (tinta + amarillo de marca + Big
     Shoulders Display/Instrument Sans) y la misma placa oscura para "Tu neto".
  ====================================================================== */
  #pdf-sheet { display: none; }

  /* Antes era una placa oscura como "Tu neto" más abajo — dos negros en una
     ficha que por lo demás es blanca pesan mucho al imprimir en papel de
     verdad (gasta tinta) y no hacía falta para que se lea como título: fondo
     blanco, texto bien bold, y una línea divisoria alcanza. */
  .pdf-head { background: #fff; color: var(--ink); padding: 0 0 18px; border-bottom: 2px solid var(--ink); }
  .pdf-brand { font-size: 14px; font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase; color: var(--gray-600); margin: 0 0 10px; }
  .pdf-brand .dot { color: var(--accent-text); }
  .pdf-title { font-family: var(--font-display); font-size: 32px; font-weight: 900; letter-spacing: -0.01em; line-height: 1.05; margin: 0; }
  .pdf-meta { font-size: 14px; color: var(--gray-600); margin: 8px 0 0; }

  .pdf-body { padding: 20px 0 0; }
  .pdf-sect { margin-bottom: 14px; }
  .pdf-sect-t {
    font-size: 13px; font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase;
    color: var(--accent-text); margin: 0 0 10px; padding-bottom: 6px;
    border-bottom: 1.5px solid var(--gray-200);
  }
  .pdf-row { display: flex; align-items: baseline; gap: 6px; padding: 4px 0; font-size: 14px; }
  .pdf-row .n { font-weight: 700; white-space: nowrap; }
  .pdf-row .d { flex: 1; border-bottom: 1.5px dotted var(--gray-400); margin-bottom: 3px; }
  .pdf-row .v { font-weight: 700; white-space: nowrap; font-variant-numeric: tabular-nums; }
  .pdf-row .sub { display: block; font-size: 13px; font-weight: 500; color: var(--gray-600); margin-top: 2px; }
  .pdf-row--sum { border-top: 1.5px solid var(--ink); margin-top: 6px; padding-top: 9px; }

  /* Esta sí sigue siendo la placa oscura: es EL resultado, el número
     protagonista de la ficha entera — mismo criterio que la pantalla
     ("no convertir la placa de resultado en una card gris genérica",
     ver DESIGN.md). El header de arriba no cumple esa función, por eso
     cambió y esta no. */
  .pdf-neto {
    background: var(--ink); color: #fff; border: none; border-radius: 8px;
    padding: 14px 18px; margin-bottom: 14px;
    display: flex; align-items: flex-end; justify-content: space-between; gap: 14px;
  }
  .pdf-neto-l { font-size: 13px; font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase; color: rgba(255,255,255,0.65); margin: 0 0 3px; }
  .pdf-neto-s { font-size: 13px; color: rgba(255,255,255,0.65); margin: 3px 0 0; }
  .pdf-neto-v { font-family: var(--font-display); font-size: 36px; font-weight: 900; color: var(--accent); letter-spacing: -0.01em; font-variant-numeric: tabular-nums; line-height: 1; }
  /* Distinta del neto de arriba a propósito: acá sí es la ganancia pura
     (Base − Costo variable), por eso lleva otro color (verde, mismo que usa
     la app en pantalla para plata que "queda limpia") y no comparte placa
     con "Tu neto" para no mezclar los dos conceptos en un mismo bloque visual. */
  .pdf-ganancia { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; padding: 10px 0 14px; font-size: 14px; border-bottom: 1px solid var(--gray-200); margin-bottom: 14px; }
  .pdf-ganancia i { font-style: normal; font-weight: 500; color: var(--gray-600); font-size: 13px; }
  .pdf-ganancia b { color: var(--green); font-weight: 800; font-variant-numeric: tabular-nums; white-space: nowrap; }

  .pdf-plat { width: 100%; border-collapse: collapse; font-size: 14px; }
  .pdf-plat td { padding: 7px 10px; border-bottom: 1px solid var(--gray-200); }
  .pdf-plat tr:nth-child(odd) td { background: var(--gray-50); }
  .pdf-plat td:last-child { text-align: right; font-weight: 800; font-variant-numeric: tabular-nums; white-space: nowrap; }
  .pdf-plat .psub { display: block; font-size: 13px; font-weight: 500; color: var(--gray-600); }

  .pdf-be { background: var(--accent-pale); border-radius: 8px; padding: 13px 16px; font-size: 14px; line-height: 1.5; }
  .pdf-be b { font-weight: 800; }

  .pdf-foot { margin-top: 14px; padding: 0 0 14px; }
  /* Tira de escala, misma lógica que la pantalla: dos densidades de marca. */
  .pdf-barcode {
    height: 12px; margin-bottom: 9px;
    background:
      repeating-linear-gradient(90deg, var(--ink) 0 1.3px, transparent 1.3px 18px),
      repeating-linear-gradient(90deg, rgba(18,18,18,0.32) 0 1px, transparent 1px 6px);
  }
  .pdf-foot p { font-size: 13px; color: var(--gray-600); margin: 0; display: flex; justify-content: space-between; gap: 12px; }
  .pdf-disclaimer { display: block !important; font-size: 13px; color: var(--ink); background: var(--amber-pale); border-radius: 6px; padding: 10px 13px; margin: 0 0 12px !important; }

  @media print {
    /* Más margen alrededor de toda la hoja (antes 10mm, apretado) y más aire
       a los costados adentro de la ficha (antes 22px, "muy finito"). */
    @page { size: A4; margin: 16mm 18mm; }
    /* El bug real de "3 páginas para una ficha casi vacía": `visibility:hidden`
       oculta el resto de la app pero NO le saca el lugar que ocupa en el
       documento — toda la calculadora (wizard, barra de acciones, etc.) seguía
       reservando su alto normal, invisible, empujando la ficha a compartir
       hoja con páginas 2 y 3 en blanco. `display:none` sí la saca del todo. */
    body > *:not(#pdf-sheet) { display: none !important; }
    #pdf-sheet {
      display: block; padding: 0; border: none;
    }
    /* Sin esto el navegador imprime en blanco las bandas y los fondos. */
    #pdf-sheet, #pdf-sheet * { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
    .pdf-sect, .pdf-neto, .pdf-be { break-inside: avoid; }
  }

  /* ======================================================================
     PANTALLA DE CONTRASEÑA — pedido explícito de Flor: no es seguridad real
     (la contraseña queda a la vista en el código fuente), es solo para que
     nadie llegue por casualidad al link antes del lanzamiento. Z-index por
     encima de todo lo demás en la app (el modal de "Mi negocio" usa 300).
  ====================================================================== */
  .pw-gate {
    position: fixed; inset: 0; z-index: 500;
    background: var(--ink);
    display: flex; align-items: center; justify-content: center;
    padding: 20px;
  }
  .pw-gate-card {
    background: #fff; border-radius: var(--radius); padding: 32px 26px;
    max-width: 360px; width: 100%; text-align: center; box-shadow: var(--shadow);
  }
  .pw-gate-brand { font-family: var(--font-display); font-weight: 800; font-size: 1.375rem; text-transform: uppercase; margin: 0 0 10px; }
  .pw-gate-brand .dot { color: var(--accent-text); }
  .pw-gate-sub { font-size: 0.9375rem; color: var(--gray-600); margin: 0 0 20px; line-height: 1.5; }
  .pw-gate-card .inp-wrap { margin-bottom: 14px; }
  .pw-gate-card .inp-wrap input { text-align: center; }
  .pw-gate-error { color: var(--red); font-size: 0.875rem; font-weight: 700; margin: 12px 0 0; }
  body.pw-gate-locked { overflow: hidden; }
