/* =========================================================================
   QUOMYA — DESIGN FOUNDATION V1
   Wave: S4.1 (design system foundation)
   Depends on: qy-tokens-v1.css (must load first)

   Typography classes, status semantics and the minimum set of primitives
   needed to VERIFY the token contract. Not a production component library --
   that is S4.2+ in src/js/ui/.

   CONTAINMENT RULES (why this file cannot regress a legacy screen):
     - every selector is class-scoped under the .qy- prefix;
     - no bare element selector, no *, no html/body rule;
     - nothing here is applied by any existing markup, so on an unmigrated
       page this stylesheet contributes zero matched rules.
   ========================================================================= */

/* =========================================================================
   TYPOGRAPHY
   ========================================================================= */

.qy-display-financial {
  font: var(--qy-text-headline-xl);
  letter-spacing: var(--qy-tracking-tight);
  font-variant-numeric: var(--qy-font-numeric);
  font-feature-settings: "tnum" 1;
  color: var(--qy-color-text-primary);
}

.qy-page-title {
  font: var(--qy-text-headline-lg);
  letter-spacing: var(--qy-tracking-tight);
  color: var(--qy-color-text-primary);
}

.qy-section-title {
  font: var(--qy-text-headline-md);
  color: var(--qy-color-text-primary);
}

.qy-body {
  font: var(--qy-text-body-lg);
  color: var(--qy-color-text-primary);
}

.qy-body-sm {
  font: var(--qy-text-body-md);
  color: var(--qy-color-text-secondary);
}

.qy-label {
  font: var(--qy-text-label-md);
  letter-spacing: var(--qy-tracking-label);
  text-transform: uppercase;
  color: var(--qy-color-text-secondary);
}

.qy-metadata {
  font: var(--qy-text-body-md);
  color: var(--qy-color-text-tertiary);
}

/* Financial figures. tabular-nums keeps digit columns aligned across rows,
   which is the whole point in a money table; font-feature-settings is the
   fallback for engines that ignore the high-level property. es-ES money is
   produced by the existing formatCurrency() in src/js/core/utils.js -- this
   class styles it, it never formats it. */
.qy-money {
  font: var(--qy-text-financial);
  font-variant-numeric: var(--qy-font-numeric);
  font-feature-settings: "tnum" 1;
  color: var(--qy-color-text-primary);
  white-space: nowrap;
}

.qy-money--projected {
  color: var(--qy-color-projected);
}

.qy-money--collected {
  color: var(--qy-color-collected-text);
}

.qy-money--pending {
  color: var(--qy-color-pending-text);
}

/* =========================================================================
   FOCUS

   :focus-visible only -- a mouse click on a button must not paint a ring,
   but every keyboard path must. The ring reads on both the dark ramp and on
   the legacy light surfaces, so it is safe to apply before migration.
   ========================================================================= */

.qy-focusable:focus-visible,
.qy-btn:focus-visible,
.qy-input:focus-visible,
.qy-card--interactive:focus-visible {
  outline: none;
  box-shadow: var(--qy-focus-ring);
}

/* Engines without :focus-visible fall back to :focus rather than to nothing. */
@supports not selector(:focus-visible) {
  .qy-focusable:focus,
  .qy-btn:focus,
  .qy-input:focus,
  .qy-card--interactive:focus {
    outline: none;
    box-shadow: var(--qy-focus-ring);
  }
}

/* =========================================================================
   SURFACE / CARD
   ========================================================================= */

.qy-surface {
  background: var(--qy-color-surface-1);
  border: 1px solid var(--qy-color-border);
  border-radius: var(--qy-radius-lg);
  color: var(--qy-color-text-primary);
}

.qy-surface--raised {
  background: var(--qy-color-surface-2);
}

.qy-card {
  padding: var(--qy-space-5);
  background: var(--qy-color-surface-1);
  border: 1px solid var(--qy-color-border);
  border-radius: var(--qy-radius-lg);
  box-shadow: var(--qy-elevation-card);
  color: var(--qy-color-text-primary);
}

.qy-card--interactive {
  cursor: pointer;
  transition: background var(--qy-motion-fast) var(--qy-motion-ease),
    border-color var(--qy-motion-fast) var(--qy-motion-ease);
}

.qy-card--interactive:hover {
  background: var(--qy-color-surface-2);
  border-color: var(--qy-color-border-strong);
}

.qy-card--interactive:active {
  background: var(--qy-color-surface-3);
}

/* =========================================================================
   BUTTON

   min-height/min-width hold the 48px touch baseline. Text on a brand fill is
   --qy-color-text-on-brand (7.07:1); white on brand would be 2.33:1.
   ========================================================================= */

.qy-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--qy-space-2);
  min-height: var(--qy-touch-min);
  padding: 0 var(--qy-space-5);
  font: var(--qy-text-body-md);
  font-weight: 600;
  border: 1px solid transparent;
  border-radius: var(--qy-radius-md);
  cursor: pointer;
  transition: background var(--qy-motion-fast) var(--qy-motion-ease),
    border-color var(--qy-motion-fast) var(--qy-motion-ease),
    color var(--qy-motion-fast) var(--qy-motion-ease);
}

.qy-btn--primary {
  background: var(--qy-color-brand);
  color: var(--qy-color-text-on-brand);
}

.qy-btn--primary:hover {
  background: var(--qy-color-brand-hover);
}

.qy-btn--primary:active {
  background: var(--qy-color-brand-deep);
}

.qy-btn--secondary {
  background: transparent;
  border-color: var(--qy-color-border-interactive);
  color: var(--qy-color-text-primary);
}

.qy-btn--secondary:hover {
  background: var(--qy-color-hover);
}

.qy-btn--secondary:active {
  background: var(--qy-color-active);
}

.qy-btn--ghost {
  background: transparent;
  color: var(--qy-color-text-secondary);
}

.qy-btn--ghost:hover {
  background: var(--qy-color-hover);
  color: var(--qy-color-text-primary);
}

.qy-btn--danger {
  background: var(--qy-color-cancelled);
  color: var(--qy-color-text-primary);
}

.qy-btn[disabled],
.qy-btn[aria-disabled="true"] {
  cursor: not-allowed;
  opacity: 0.55;
  color: var(--qy-color-disabled-text);
}

/* =========================================================================
   FORM INPUT

   The border is the only boundary indication, so it uses
   --qy-color-border-interactive (>= 3:1 on every surface, WCAG 1.4.11).
   ========================================================================= */

.qy-field {
  display: flex;
  flex-direction: column;
  gap: var(--qy-space-2);
}

.qy-field__label {
  font: var(--qy-text-label-md);
  letter-spacing: var(--qy-tracking-label);
  text-transform: uppercase;
  color: var(--qy-color-text-secondary);
}

.qy-input {
  min-height: var(--qy-touch-min);
  padding: 0 var(--qy-space-4);
  font: var(--qy-text-body-lg);
  color: var(--qy-color-text-primary);
  background: var(--qy-color-surface-2);
  border: 1px solid var(--qy-color-border-interactive);
  border-radius: var(--qy-radius-md);
  transition: border-color var(--qy-motion-fast) var(--qy-motion-ease);
}

.qy-input::placeholder {
  color: var(--qy-color-text-tertiary);
}

.qy-input:hover {
  border-color: var(--qy-color-text-tertiary);
}

.qy-input[aria-invalid="true"] {
  border-color: var(--qy-color-cancelled);
}

/*
   RECUPERACIÓN DEL BORDE INTERACTIVO (S4.11A, fase 16).

   `compact-visual-v15-14-2.css` declara
   `.form-field input { border: 1px solid var(--rt-border) !important }`.
   `--rt-border` resuelve a `--qy-color-border`, que es un separador
   DECORATIVO y está exento de 1.4.11 precisamente porque no llega a 3:1.

   Como esa regla lleva `!important` y (0,1,1) de especificidad, ganaba a
   `.qy-input`, que es (0,1,0): todo campo de Registro y de Nueva Venta que
   viviera dentro de un `.form-field` perdía su borde accesible y se quedaba
   en 1.17:1 en oscuro y 1.26:1 en claro. Lo detectó la auditoría de
   contraste de S4.11A, no la vista: el borde se ve, simplemente no se ve lo
   suficiente.

   Se recupera repitiendo la clase: `.qy-input.qy-input` es (0,2,0) y gana a
   (0,1,1) por peso de clase, sin recurrir a un selector de elemento -- que
   esta hoja tiene PROHIBIDO usar, porque un selector de elemento aquí
   alcanzaría el marcado heredado que aún no ha migrado (invariante E3 de
   S4.1). Se toca EXCLUSIVAMENTE `border-color`: el
   grosor, el radio, el relleno y la altura los sigue fijando quien los fija
   hoy, así que no se mueve un solo pixel de maquetación.

   Las variantes se reafirman por el mismo motivo: sin ellas, la declaración
   de arriba ganaría también al hover y al estado inválido.
*/
.qy-input.qy-input {
  border-color: var(--qy-color-border-interactive) !important;
}

.qy-input.qy-input:hover {
  border-color: var(--qy-color-text-tertiary) !important;
}

.qy-input.qy-input[aria-invalid="true"] {
  border-color: var(--qy-color-cancelled) !important;
}

.qy-input--money {
  font-variant-numeric: var(--qy-font-numeric);
  font-feature-settings: "tnum" 1;
  text-align: right;
}

.qy-field__error {
  font: var(--qy-text-body-md);
  color: var(--qy-color-cancelled-text);
}

/* =========================================================================
   STATUS SEMANTICS

   INVARIANT 1 -- CERRADO is not COBRADO.
     PAYMENT_STATUS  (pending | partial | paid | cancelled)  and
     CLOSING_STATUS  (open | closed | completed | not_required)
     are two orthogonal axes in src/js/core/saleEngine.js. They get two
     SEPARATE badge families with two different SHAPES, so the axes stay
     distinguishable even in a monochrome rendering:
       payment axis -> fully rounded pill   (--qy-radius-pill)
       closing axis -> squared tag          (--qy-radius-sm)
     They must never be merged into one "completed" badge.

   INVARIANT 2 -- colour is never the whole state.
     .qy-badge composes three slots: __icon, __label and the shape itself.
     .qy-badge__label is required and must carry real text. Consumers must
     also set an accessible name; the icon is decorative and is hidden from
     assistive technology by aria-hidden at the call site.

     Required markup shape:
       <span class="qy-badge qy-badge--payment qy-badge--paid"
             role="status" aria-label="Estado de cobro: cobrado">
         <span class="qy-badge__icon" aria-hidden="true">&#10003;</span>
         <span class="qy-badge__label">Cobrado</span>
       </span>
   ========================================================================= */

.qy-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--qy-space-2);
  padding: var(--qy-space-1) var(--qy-space-3);
  font: var(--qy-text-label-md);
  letter-spacing: var(--qy-tracking-label);
  border: 1px solid currentColor;
  white-space: nowrap;
}

.qy-badge__icon {
  display: inline-flex;
  flex: none;
  line-height: 1;
}

.qy-badge__label {
  font: inherit;
  letter-spacing: inherit;
}

/* ---- payment axis: pill shape --------------------------------------- */
.qy-badge--payment {
  border-radius: var(--qy-radius-pill);
}

.qy-badge--paid {
  color: var(--qy-color-collected-text);
  background: var(--qy-color-collected-soft);
}

.qy-badge--partial {
  color: var(--qy-color-pending-text);
  background: var(--qy-color-pending-soft);
}

.qy-badge--pending {
  color: var(--qy-color-pending-text);
  background: var(--qy-color-pending-soft);
}

.qy-badge--cancelled {
  color: var(--qy-color-cancelled-text);
  background: var(--qy-color-cancelled-soft);
}

/* partial and pending share the amber semantic, so the shape carries the
   distinction: a partial payment is dashed, a pending one is solid. */
.qy-badge--partial {
  border-style: dashed;
}

/* ---- closing axis: squared tag shape --------------------------------- */
.qy-badge--closing {
  border-radius: var(--qy-radius-sm);
}

.qy-badge--closed,
.qy-badge--completed {
  color: var(--qy-color-closure-text);
  background: var(--qy-color-closure-soft);
}

.qy-badge--open {
  color: var(--qy-color-text-secondary);
  background: var(--qy-color-hover);
}

.qy-badge--not-required {
  color: var(--qy-color-text-tertiary);
  background: transparent;
  border-style: dotted;
}

/* A closing badge that is also COMPLETED gets a second visual stop so that
   closed and completed remain separable without reading the label colour. */
.qy-badge--completed {
  border-width: 2px;
}

/* ---- status dot: for dense rows where a full badge does not fit -------
   A dot alone is colour-only and therefore never sufficient. It must be
   paired with a text label in the same cell; .qy-status-dot has no
   standalone accessible meaning and carries aria-hidden at the call site. */
.qy-status-dot {
  display: inline-block;
  flex: none;
  width: var(--qy-space-2);
  height: var(--qy-space-2);
  border-radius: var(--qy-radius-pill);
  background: currentColor;
}

.qy-status--collected {
  color: var(--qy-color-collected);
}

.qy-status--pending {
  color: var(--qy-color-pending);
}

.qy-status--closure {
  color: var(--qy-color-closure);
}

.qy-status--cancelled {
  color: var(--qy-color-cancelled);
}

/* =========================================================================
   UTILITY
   ========================================================================= */

.qy-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

@media (prefers-reduced-motion: reduce) {
  .qy-btn,
  .qy-input,
  .qy-card--interactive {
    transition: none;
  }
}
