{
  "openapi": "3.1.0",
  "info": {
    "title": "Paleta API",
    "version": "1.7.0",
    "description": "Generador determinista de design systems con teoria del color: paleta verificada WCAG (AA/AAA con ajuste garantizado), tokens de 14 estilos UI, tipografia sugerida, chequeo de daltonismo, rampas tonales 50-900, par de temas claro/oscuro y exports para CSS, SCSS, Tailwind v4 y W3C Design Tokens. Misma semilla + mismos parametros = misma salida (dentro de cada version)."
  },
  "servers": [
    {
      "url": "./",
      "description": "Mismo origen que este documento"
    }
  ],
  "paths": {
    "/paleta.php": {
      "get": {
        "operationId": "generarPaleta",
        "summary": "Genera una paleta y su design system",
        "description": "Todos los parametros son opcionales. Con seed explicita la respuesta es cacheable (Cache-Control: public, max-age=86400); sin seed es aleatoria (no-store). Los parametros tambien se aceptan via PATH: /paleta.php/seed/VX-2741/estilo/glass.",
        "parameters": [
          {
            "name": "seed",
            "in": "query",
            "description": "Semilla determinista (maximo 64 caracteres). Default: aleatoria.",
            "schema": {
              "type": "string",
              "maxLength": 64
            },
            "example": "VX-2741"
          },
          {
            "name": "armonia",
            "in": "query",
            "description": "Esquema de hues derivados del hue base.",
            "schema": {
              "type": "string",
              "enum": [
                "auto",
                "monocromatica",
                "analoga",
                "complementaria",
                "split",
                "triadica",
                "tetradica"
              ],
              "default": "auto"
            }
          },
          {
            "name": "registro",
            "in": "query",
            "description": "Receta tonal (S/L por rol). En auto se sortea solo entre los compatibles con el estilo. registro=neobrutal ademas activa estilo=neobrutal (alias v1.0).",
            "schema": {
              "type": "string",
              "enum": [
                "auto",
                "profundo",
                "claro",
                "pastel",
                "oscuro",
                "desaturado",
                "neobrutal"
              ],
              "default": "auto"
            }
          },
          {
            "name": "estilo",
            "in": "query",
            "description": "Lenguaje visual: define los 14 tokens de superficie.",
            "schema": {
              "type": "string",
              "enum": [
                "auto",
                "minimal",
                "maximal",
                "glass",
                "liquid",
                "clay",
                "neobrutal",
                "espacial",
                "neumo",
                "skeu",
                "y2k",
                "flat",
                "aurora",
                "ilustrativo",
                "doodle"
              ],
              "default": "auto"
            }
          },
          {
            "name": "layout",
            "in": "query",
            "description": "Sugerencia de layout para el consumidor.",
            "schema": {
              "type": "string",
              "enum": [
                "classic",
                "bento",
                "auto"
              ],
              "default": "classic"
            }
          },
          {
            "name": "modo",
            "in": "query",
            "description": "Con par agrega temas.claro, temas.oscuro y css_par (mismos hues; cada tema con su propia garantia de contraste). No consume RNG.",
            "schema": {
              "type": "string",
              "enum": [
                "uno",
                "par"
              ],
              "default": "uno"
            }
          },
          {
            "name": "nivel",
            "in": "query",
            "description": "Objetivos de contraste. aaa: texto 4.5 -> 7.0, UI 3.0 -> 4.5.",
            "schema": {
              "type": "string",
              "enum": [
                "aa",
                "aaa"
              ],
              "default": "aa"
            }
          },
          {
            "name": "ajuste_aa",
            "in": "query",
            "description": "Con 1 ajusta la luminosidad hasta cumplir cada objetivo; con 0 solo reporta.",
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "0"
              ],
              "default": "1"
            }
          },
          {
            "name": "excluir",
            "in": "query",
            "description": "Hues ya usados, CSV (ej. 210,175,42). Con 2+ el hue base sale del hueco mas ancho; con 1, del opuesto.",
            "schema": {
              "type": "string",
              "pattern": "^\\s*\\d+(\\s*,\\s*\\d+)*\\s*$"
            },
            "example": "210,175,42,229"
          },
          {
            "name": "pretty",
            "in": "query",
            "description": "Con 0 el JSON sale compacto (sin saltos de linea).",
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "0"
              ],
              "default": "1"
            }
          },
          {
            "name": "mood",
            "in": "query",
            "description": "Mood generativo: fija el hue base dentro del rango del mood; si registro viene en auto, aplica su registro y limita el pool de estilos a los compatibles.",
            "schema": {
              "type": "string",
              "enum": [
                "pastel",
                "vintage",
                "neon",
                "calido",
                "frio",
                "otono",
                "invierno",
                "primavera",
                "verano",
                "naturaleza",
                "cafe",
                "atardecer",
                "mar",
                "dorado"
              ]
            }
          },
          {
            "name": "hue",
            "in": "query",
            "description": "Fija el hue base manualmente (0-359).",
            "schema": {
              "type": "number",
              "minimum": 0,
              "maximum": 359
            }
          },
          {
            "name": "marca",
            "in": "query",
            "description": "Hex RRGGBB (con o sin #) del color de marca; ancla el hue base. Prioridad: marca > hue > mood > excluir.",
            "schema": {
              "type": "string",
              "pattern": "^#?[0-9A-Fa-f]{6}$"
            },
            "example": "DB4361"
          },
          {
            "name": "lote",
            "in": "query",
            "description": "Devuelve N paletas ligeras (semillas seed-1..N) en una sola peticion (cuenta como 1 para el rate limit). La respuesta usa el esquema LoteRespuesta.",
            "schema": {
              "type": "integer",
              "minimum": 2,
              "maximum": 24
            }
          },
          {
            "name": "imagen",
            "in": "query",
            "description": "Con 1, la respuesta es una tarjeta PNG 1200x630 del tema principal (image/png). Requiere GD; ignora modo=par y lote.",
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Design system generado (JSON), lote de paletas ligeras (JSON con lote=2..24) o tarjeta PNG (imagen=1).",
            "headers": {
              "Cache-Control": {
                "description": "public, max-age=86400 con seed explicita; no-store sin seed.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/PaletaRespuesta"
                    },
                    {
                      "$ref": "#/components/schemas/LoteRespuesta"
                    }
                  ]
                }
              },
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit alcanzado (60 peticiones por minuto por IP).",
            "headers": {
              "Retry-After": {
                "description": "Segundos hasta la siguiente ventana.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorRateLimit"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Hex": {
        "type": "string",
        "pattern": "^#[0-9A-F]{6}$",
        "examples": [
          "#7841C8"
        ]
      },
      "Colores": {
        "type": "object",
        "description": "12 roles de color. Los sobre_* son texto con contraste AA garantizado encima de cada rol cromatico.",
        "properties": {
          "fondo": {
            "$ref": "#/components/schemas/Hex"
          },
          "superficie": {
            "$ref": "#/components/schemas/Hex"
          },
          "primario": {
            "$ref": "#/components/schemas/Hex"
          },
          "secundario": {
            "$ref": "#/components/schemas/Hex"
          },
          "acento": {
            "$ref": "#/components/schemas/Hex"
          },
          "acento_suave": {
            "$ref": "#/components/schemas/Hex"
          },
          "texto": {
            "$ref": "#/components/schemas/Hex"
          },
          "texto_muted": {
            "$ref": "#/components/schemas/Hex"
          },
          "sobre_primario": {
            "$ref": "#/components/schemas/Hex"
          },
          "sobre_secundario": {
            "$ref": "#/components/schemas/Hex"
          },
          "sobre_acento": {
            "$ref": "#/components/schemas/Hex"
          },
          "sobre_acento_suave": {
            "$ref": "#/components/schemas/Hex"
          }
        },
        "required": [
          "fondo",
          "superficie",
          "primario",
          "secundario",
          "acento",
          "acento_suave",
          "texto",
          "texto_muted"
        ]
      },
      "ParWcag": {
        "type": "object",
        "properties": {
          "par": {
            "type": "string",
            "examples": [
              "texto / fondo"
            ]
          },
          "ratio": {
            "type": "number"
          },
          "objetivo": {
            "type": "number",
            "description": "4.5/3.0 en nivel aa; 7.0/4.5 en aaa."
          },
          "aa": {
            "type": "boolean"
          },
          "aa_grande": {
            "type": "boolean"
          }
        }
      },
      "Tokens": {
        "type": "object",
        "description": "14 tokens uniformes en todos los estilos, mapeables 1:1 a custom properties.",
        "properties": {
          "radius": {
            "type": "string"
          },
          "radius_control": {
            "type": "string"
          },
          "borde": {
            "type": "string"
          },
          "sombra": {
            "type": "string"
          },
          "sombra_elevada": {
            "type": "string"
          },
          "blur": {
            "type": "string"
          },
          "saturacion": {
            "type": "string"
          },
          "alpha_superficie": {
            "type": "number"
          },
          "superficie_translucida": {
            "type": "string"
          },
          "espaciado": {
            "type": "string"
          },
          "transicion": {
            "type": "string"
          },
          "highlight": {
            "type": "string"
          },
          "gradiente": {
            "type": "string"
          },
          "fondo_decorado": {
            "type": "string"
          }
        }
      },
      "Fuente": {
        "type": "object",
        "properties": {
          "familia": {
            "type": "string",
            "examples": [
              "Sora"
            ]
          },
          "pesos": {
            "type": "array",
            "items": {
              "type": "integer"
            }
          },
          "fallback": {
            "type": "string",
            "examples": [
              "system-ui, sans-serif"
            ]
          }
        }
      },
      "Tipografia": {
        "type": "object",
        "properties": {
          "display": {
            "$ref": "#/components/schemas/Fuente"
          },
          "cuerpo": {
            "$ref": "#/components/schemas/Fuente"
          },
          "google_fonts_url": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "Daltonismo": {
        "type": "object",
        "description": "Simulacion Machado et al. 2009 (RGB lineal) del trio primario/secundario/acento y Delta E CIE76 por par. Umbrales: ok >= 20, justo >= 10, riesgo < 10.",
        "properties": {
          "simulaciones": {
            "type": "object",
            "properties": {
              "protanopia": {
                "type": "object",
                "additionalProperties": {
                  "$ref": "#/components/schemas/Hex"
                }
              },
              "deuteranopia": {
                "type": "object",
                "additionalProperties": {
                  "$ref": "#/components/schemas/Hex"
                }
              },
              "tritanopia": {
                "type": "object",
                "additionalProperties": {
                  "$ref": "#/components/schemas/Hex"
                }
              }
            }
          },
          "pares": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "tipo": {
                  "type": "string",
                  "enum": [
                    "protanopia",
                    "deuteranopia",
                    "tritanopia"
                  ]
                },
                "par": {
                  "type": "string"
                },
                "delta_e": {
                  "type": "number"
                },
                "estado": {
                  "type": "string",
                  "enum": [
                    "ok",
                    "justo",
                    "riesgo"
                  ]
                }
              }
            }
          },
          "nota": {
            "type": "string"
          }
        }
      },
      "Rampa": {
        "type": "object",
        "description": "Escala tonal con claves 50,100,200...900.",
        "additionalProperties": {
          "$ref": "#/components/schemas/Hex"
        }
      },
      "Tema": {
        "type": "object",
        "properties": {
          "registro": {
            "type": "string"
          },
          "colores": {
            "$ref": "#/components/schemas/Colores"
          },
          "wcag": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ParWcag"
            }
          },
          "ajustes_aa": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "tokens": {
            "$ref": "#/components/schemas/Tokens"
          },
          "css_variables": {
            "type": "string"
          }
        }
      },
      "PaletaRespuesta": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true
          },
          "meta": {
            "type": "object",
            "properties": {
              "seed": {
                "type": "string"
              },
              "armonia": {
                "type": "string"
              },
              "registro": {
                "type": "string"
              },
              "estilo": {
                "type": "string"
              },
              "layout": {
                "type": "string"
              },
              "modo": {
                "type": "string"
              },
              "nivel": {
                "type": "string"
              },
              "tema_principal": {
                "type": "string",
                "enum": [
                  "claro",
                  "oscuro"
                ]
              },
              "hue_base": {
                "type": "number"
              },
              "hues": {
                "type": "array",
                "items": {
                  "type": "number"
                }
              },
              "excluidos": {
                "type": "array",
                "items": {
                  "type": "integer"
                }
              },
              "nota": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "regla": {
                "type": "string"
              },
              "version": {
                "type": "string"
              },
              "generado_en": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          "colores": {
            "$ref": "#/components/schemas/Colores"
          },
          "wcag": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ParWcag"
            }
          },
          "ajustes_aa": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "rol": {
                  "type": "string"
                },
                "antes": {
                  "$ref": "#/components/schemas/Hex"
                },
                "despues": {
                  "$ref": "#/components/schemas/Hex"
                }
              }
            }
          },
          "estilo": {
            "type": "object",
            "properties": {
              "nombre": {
                "type": "string"
              },
              "layout": {
                "type": "string"
              },
              "registros_recomendados": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "tokens": {
                "$ref": "#/components/schemas/Tokens"
              }
            }
          },
          "tipografia": {
            "$ref": "#/components/schemas/Tipografia"
          },
          "daltonismo": {
            "$ref": "#/components/schemas/Daltonismo"
          },
          "css_variables": {
            "type": "string"
          },
          "rampas": {
            "type": "object",
            "properties": {
              "primario": {
                "$ref": "#/components/schemas/Rampa"
              },
              "secundario": {
                "$ref": "#/components/schemas/Rampa"
              },
              "acento": {
                "$ref": "#/components/schemas/Rampa"
              },
              "neutro": {
                "$ref": "#/components/schemas/Rampa"
              }
            }
          },
          "exports": {
            "type": "object",
            "properties": {
              "scss": {
                "type": "string"
              },
              "tailwind": {
                "type": "string"
              },
              "tokens_w3c": {
                "type": "object"
              }
            }
          },
          "temas": {
            "type": "object",
            "description": "Solo con modo=par.",
            "properties": {
              "claro": {
                "$ref": "#/components/schemas/Tema"
              },
              "oscuro": {
                "$ref": "#/components/schemas/Tema"
              }
            }
          },
          "css_par": {
            "type": "string",
            "description": "Solo con modo=par."
          },
          "uso": {
            "type": "object"
          }
        },
        "required": [
          "ok",
          "meta",
          "colores",
          "wcag",
          "estilo",
          "css_variables"
        ]
      },
      "ErrorRateLimit": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean",
            "const": false
          },
          "error": {
            "type": "string",
            "const": "rate_limit"
          },
          "mensaje": {
            "type": "string"
          },
          "reintentar_en": {
            "type": "integer",
            "description": "Segundos hasta la siguiente ventana."
          }
        }
      },
      "PaletaLigera": {
        "type": "object",
        "properties": {
          "seed": {
            "type": "string"
          },
          "armonia": {
            "type": "string"
          },
          "registro": {
            "type": "string"
          },
          "estilo": {
            "type": "string"
          },
          "hue_base": {
            "type": "number"
          },
          "colores": {
            "type": "object",
            "description": "fondo, primario, secundario, acento, acento_suave, texto.",
            "additionalProperties": {
              "$ref": "#/components/schemas/Hex"
            }
          }
        }
      },
      "LoteRespuesta": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true
          },
          "meta": {
            "type": "object",
            "properties": {
              "modo": {
                "type": "string",
                "const": "lote"
              },
              "lote": {
                "type": "integer"
              },
              "seed": {
                "type": "string"
              },
              "mood": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "nivel": {
                "type": "string"
              },
              "version": {
                "type": "string"
              },
              "generado_en": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          "paletas": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PaletaLigera"
            }
          },
          "uso": {
            "type": "object"
          }
        },
        "required": [
          "ok",
          "meta",
          "paletas"
        ]
      }
    }
  }
}