{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "header",
"type": "registry:block",
"title": "header",
"description": "Bloque Concorde header — incluye sus 1 componentes.",
"dependencies": [
"react"
],
"registryDependencies": [],
"files": [
{
"path": "bloques/header/desktop/dimensions.ts",
"type": "registry:file",
"target": "bloques/header/desktop/dimensions.ts",
"content": "/**\n * Dimensiones del bloque Header — módulo PLANO (sin \"use client\") para que los\n * Server Components (catálogo /blocks, páginas de bloque) puedan importar estas\n * constantes sin que se evalúen a undefined → NaN en los cálculos de escala.\n */\n\nexport const HEADER_WIDTH = 798;\nexport const HEADER_HEIGHT = 64;\n"
},
{
"path": "bloques/header/desktop/Header.tsx",
"type": "registry:file",
"target": "bloques/header/desktop/Header.tsx",
"content": "/**\n * Header — Bloque de Concorde (Voyager DS)\n *\n * Barra superior 798 × 64 con fondo vault (#2E0F70). A la derecha lleva el\n * Button «Ingresa» (variante sm-guest, con UserIcon), a 16px del borde y\n * centrado verticalmente — igual que el export de Figma (1312:4674).\n *\n * Si se pasa `username`, el CTA cambia a la variante logueada: «Bienvenido,\n * {username}» (Button sm-logged-in) — usado p.ej. en la Zona de usuario.\n */\n\n\"use client\";\n\nimport type { JSX, ReactNode } from \"react\";\nimport Button, { UserIcon } from \"../../../components/Button\";\nimport { HEADER_WIDTH, HEADER_HEIGHT } from \"./dimensions\";\n\nexport interface HeaderProps {\n /** Ancho de la barra. Por defecto HEADER_WIDTH (798, desktop); 420 en mobile. */\n width?: number | string;\n /** Logo a la izquierda (slot). En desktop no se usa (el logo va en el Sidebar);\n * en mobile se pasa el logo de la marca. */\n logo?: ReactNode;\n /** Usuario logueado. Si se pasa, el CTA muestra «Bienvenido, {username}»\n * (variante sm-logged-in) en vez de «Ingresa» (sm-guest). */\n username?: string;\n /** En mobile el ancho es 420 y el botón «Bienvenido, {username}» no entra junto\n * al logo+hamburguesa: con `compact` se muestra solo el ícono de usuario. */\n compact?: boolean;\n className?: string;\n}\n\nexport default function Header({ width = HEADER_WIDTH, logo, username, compact = false, className = \"\" }: HeaderProps): JSX.Element {\n return (\n \n {logo}\n {username && compact ? (\n // Solo el ícono circular (mobile) — el botón con texto no entra en 420px.\n \n \n \n ) : username ? (\n } />\n ) : (\n }>\n Ingresa\n \n )}\n \n );\n}\n"
},
{
"path": "components/Button.tsx",
"type": "registry:file",
"target": "components/Button.tsx",
"content": "// Button.tsx — Generado por Concorde\r\n// Fuente: https://voyager-ds.vercel.app/preview/components/pase1\r\n// Generado: 2026-05-25\r\n// EDITAR LIBREMENTE después de generar\r\n\r\n\"use client\";\r\n\r\nimport { forwardRef } from \"react\";\r\nimport type { ButtonHTMLAttributes, JSX, ReactNode } from \"react\";\r\n\r\nexport type ButtonVariant =\r\n | \"primary\"\r\n | \"negotiable\"\r\n | \"secondary\"\r\n | \"secondary-sm\"\r\n | \"ghost\"\r\n | \"outline\"\r\n | \"sm-guest\"\r\n | \"sm-logged-in\";\r\n\r\n/**\r\n * Hereda todos los atributos nativos de (type, name, className, style,\r\n * onMouseEnter, data-*, etc.) — basta con props, no hace falta editar el archivo.\r\n */\r\nexport interface ButtonProps extends ButtonHTMLAttributes {\r\n /** Estilo visual del botón. */\r\n variant?: ButtonVariant;\r\n /** Ícono opcional en el slot circular (variantes sm-guest, secondary-sm, sm-logged-in). */\r\n icon?: ReactNode;\r\n /** Nombre de usuario — usado cuando variant=\"sm-logged-in\". */\r\n username?: string;\r\n}\r\n\r\n// ── CSS self-contained ────────────────────────────────────────────────────\r\n\r\nconst BUTTON_STYLES = `\r\n@property --vbtn-angle { syntax: \"\"; inherits: false; initial-value: 135deg; }\r\n@property --vbtn-stop-a { syntax: \"\"; inherits: false; initial-value: oklch(0.72 0.16 55); }\r\n@property --vbtn-stop-b { syntax: \"\"; inherits: false; initial-value: oklch(0.55 0.22 285); }\r\n@property --vsec-angle { syntax: \"\"; inherits: false; initial-value: 160deg; }\r\n@property --vsec-stop-a { syntax: \"\"; inherits: false; initial-value: oklch(0.38 0.20 285); }\r\n@property --vsec-stop-b { syntax: \"\"; inherits: false; initial-value: oklch(0.28 0.18 285); }\r\n@property --vneg-angle { syntax: \"\"; inherits: false; initial-value: 135deg; }\r\n@property --vneg-stop-a { syntax: \"\"; inherits: false; initial-value: #00aeb1; }\r\n@property --vneg-stop-b { syntax: \"\"; inherits: false; initial-value: #8460e5; }\r\n@property --vss-angle { syntax: \"\"; inherits: false; initial-value: 160deg; }\r\n@property --vss-stop-a { syntax: \"\"; inherits: false; initial-value: #8460e5; }\r\n@property --vss-stop-b { syntax: \"\"; inherits: false; initial-value: #3b1782; }\r\n\r\n/* ── primary ─────────────────────────────────────────────────────────── */\r\n.pvbtn {\r\n --vbtn-stop-a: var(--vmc-color-orange-600, #ed8936);\r\n --vbtn-stop-b: var(--vmc-color-vault-500, #8460e5);\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n height: 48px;\r\n padding: 0 56px;\r\n border-radius: var(--vmc-radius-full, 9999px);\r\n /* Borde GRADIENTE de Figma (1130:1778): white → #FBC47D 25% → #AE8EFF 75% → white */\r\n border: 2px solid transparent;\r\n cursor: pointer;\r\n position: relative;\r\n overflow: hidden;\r\n font-family: var(--vmc-font-display, \"Plus Jakarta Sans\", sans-serif);\r\n font-size: 16px;\r\n line-height: 20px;\r\n font-weight: 600;\r\n color: var(--vmc-color-base-white, #ffffff);\r\n text-shadow: rgba(0,0,0,0.25) 0 1px 3px;\r\n background-image:\r\n linear-gradient(var(--vbtn-angle), var(--vbtn-stop-a) 0%, var(--vbtn-stop-a) 40%, var(--vbtn-stop-b) 100%),\r\n linear-gradient(135deg, #ffffff 0%, #fbc47d 25%, #ae8eff 75%, #ffffff 100%);\r\n background-origin: padding-box, border-box;\r\n background-clip: padding-box, border-box;\r\n box-shadow: rgba(255,255,255,0.28) 0 1px 0 2px inset, rgba(237,137,54,0.3) 0 2px 6px;\r\n transition:\r\n --vbtn-angle 0.4s cubic-bezier(0.25, 0.8, 0.25, 1),\r\n --vbtn-stop-a 0.35s,\r\n --vbtn-stop-b 0.35s,\r\n transform 0.2s cubic-bezier(0.25, 0.8, 0.25, 1),\r\n box-shadow 0.25s;\r\n transform: translateZ(0);\r\n}\r\n.pvbtn::before {\r\n content: \"\";\r\n position: absolute;\r\n inset: 0;\r\n border-radius: var(--vmc-radius-full, 9999px);\r\n background: linear-gradient(rgba(255,255,255,0.17) 0%, transparent 55%);\r\n pointer-events: none;\r\n z-index: 1;\r\n}\r\n.pvbtn::after {\r\n content: \"\";\r\n position: absolute;\r\n inset: -4px;\r\n border-radius: var(--vmc-radius-full, 9999px);\r\n background: linear-gradient(135deg,\r\n var(--vmc-color-orange-600, oklch(0.72 0.16 55)),\r\n var(--vmc-color-vault-500, oklch(0.55 0.22 285))\r\n );\r\n filter: blur(14px);\r\n opacity: 0;\r\n z-index: -1;\r\n transition: opacity 0.3s, filter 0.3s;\r\n}\r\n.pvbtn:hover {\r\n --vbtn-angle: 220deg;\r\n --vbtn-stop-a: var(--vmc-color-orange-400, #fbc47d);\r\n --vbtn-stop-b: var(--vmc-color-vault-400, #ae8eff);\r\n transform: translateY(-2px) scale(1.02);\r\n box-shadow: rgba(255,255,255,0.22) 0 1px 0 2px inset, rgba(132,96,229,0.35) 0 8px 24px, rgba(237,137,54,0.4) 0 4px 10px;\r\n}\r\n.pvbtn:hover::after { opacity: 0.45; filter: blur(18px); }\r\n.pvbtn:active {\r\n --vbtn-angle: 135deg;\r\n --vbtn-stop-a: var(--vmc-color-orange-700, #d46e20);\r\n --vbtn-stop-b: var(--vmc-color-vault-600, #5a35c2);\r\n color: #d1d5dc;\r\n transform: scale(0.97) translateY(1px);\r\n box-shadow: rgba(0,0,0,0.22) 0 2px 5px 2px inset, rgba(0,0,0,0.12) 0 1px 3px;\r\n}\r\n.pvbtn:active::after { opacity: 0; }\r\n.pvbtn:disabled {\r\n background-image: none;\r\n background-color: var(--vmc-color-background-disabled, #e1e3e2);\r\n color: var(--vmc-color-neutral-700, #99a1af);\r\n text-shadow: none;\r\n box-shadow: none;\r\n cursor: not-allowed;\r\n transform: none;\r\n border-color: transparent;\r\n}\r\n.pvbtn:disabled::after { display: none; }\r\n.pvbtn:focus-visible {\r\n outline: transparent solid 3px;\r\n outline-offset: 4px;\r\n transform: scale(0.98);\r\n box-shadow:\r\n 0 0 0 2px var(--vmc-color-base-white, #fff),\r\n 0 0 0 5px var(--vmc-color-vault-500, oklch(0.55 0.22 285)),\r\n 0 8px 16px -4px rgb(51.76% 37.65% 89.8% / 0.30);\r\n}\r\n\r\n/* ── secondary ───────────────────────────────────────────────────────── */\r\n.psec {\r\n --vsec-stop-a: var(--vmc-color-vault-500, #8460e5);\r\n --vsec-stop-b: var(--vmc-color-vault-700, #3b1782);\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n height: 48px;\r\n padding: 0 56px;\r\n border-radius: var(--vmc-radius-full, 9999px);\r\n /* Borde GRADIENTE lila de Figma (1133:2294): #CFBAFF → white 35% → #AE8EFF 65% → #CFBAFF */\r\n border: 2px solid transparent;\r\n cursor: pointer;\r\n position: relative;\r\n overflow: hidden;\r\n font-family: var(--vmc-font-display, \"Plus Jakarta Sans\", sans-serif);\r\n font-size: 16px;\r\n line-height: 20px;\r\n font-weight: 600;\r\n color: var(--vmc-color-base-white, #ffffff);\r\n text-shadow: rgba(0,0,0,0.3) 0 1px 3px;\r\n background-image:\r\n linear-gradient(var(--vsec-angle), var(--vsec-stop-a) 0%, var(--vsec-stop-b) 100%),\r\n linear-gradient(135deg, #cfbaff 0%, #ffffff 35%, #ae8eff 65%, #cfbaff 100%);\r\n background-origin: padding-box, border-box;\r\n background-clip: padding-box, border-box;\r\n box-shadow: rgba(255,255,255,0.22) 0 1px 0 2px inset, rgba(132,96,229,0.3) 0 2px 8px;\r\n transition:\r\n --vsec-angle 0.4s cubic-bezier(0.25, 0.8, 0.25, 1),\r\n --vsec-stop-a 0.35s,\r\n --vsec-stop-b 0.35s,\r\n transform 0.2s cubic-bezier(0.25, 0.8, 0.25, 1),\r\n box-shadow 0.25s;\r\n transform: translateZ(0);\r\n}\r\n.psec::before {\r\n content: \"\";\r\n position: absolute;\r\n inset: 0;\r\n border-radius: var(--vmc-radius-full, 9999px);\r\n background: linear-gradient(rgba(255,255,255,0.15) 0%, transparent 55%);\r\n pointer-events: none;\r\n z-index: 1;\r\n}\r\n.psec::after {\r\n content: \"\";\r\n position: absolute;\r\n inset: -4px;\r\n border-radius: var(--vmc-radius-full, 9999px);\r\n background: linear-gradient(135deg,\r\n var(--vmc-color-vault-500, oklch(0.55 0.22 285)),\r\n var(--vmc-color-vault-700, oklch(0.38 0.20 285))\r\n );\r\n filter: blur(14px);\r\n opacity: 0;\r\n z-index: -1;\r\n transition: opacity 0.3s, filter 0.3s;\r\n}\r\n.psec:hover {\r\n --vsec-angle: 219deg;\r\n --vsec-stop-a: var(--vmc-color-vault-400, #ae8eff);\r\n --vsec-stop-b: var(--vmc-color-vault-600, #5a35c2);\r\n transform: translateY(-2px) scale(1.02);\r\n box-shadow: rgba(255,255,255,0.2) 0 1px 0 2px inset, rgba(132,96,229,0.4) 0 8px 24px, rgba(132,96,229,0.25) 0 4px 10px;\r\n}\r\n.psec:hover::after { opacity: 0.45; filter: blur(18px); }\r\n.psec:active {\r\n --vsec-angle: 160deg;\r\n --vsec-stop-a: var(--vmc-color-vault-700, #3b1782);\r\n --vsec-stop-b: var(--vmc-color-vault-900, #22005c);\r\n color: #d1d5dc;\r\n transform: scale(0.97) translateY(1px);\r\n box-shadow: rgba(0,0,0,0.28) 0 2px 5px 2px inset, rgba(0,0,0,0.14) 0 1px 3px;\r\n}\r\n.psec:active::after { opacity: 0; }\r\n.psec:disabled {\r\n background-image: none;\r\n background-color: var(--vmc-color-background-disabled, #e1e3e2);\r\n color: var(--vmc-color-neutral-700, #99a1af);\r\n text-shadow: none;\r\n box-shadow: none;\r\n cursor: not-allowed;\r\n transform: none;\r\n border-color: transparent;\r\n}\r\n.psec:disabled::after { display: none; }\r\n.psec:focus-visible {\r\n outline: transparent solid 3px;\r\n outline-offset: 4px;\r\n transform: scale(0.98);\r\n box-shadow:\r\n 0 0 0 2px var(--vmc-color-base-white, #fff),\r\n 0 0 0 5px var(--vmc-color-vault-500, oklch(0.55 0.22 285)),\r\n 0 8px 16px -4px rgb(51.76% 37.65% 89.8% / 0.30);\r\n}\r\n\r\n/* ── ghost · \"Ver Ofertas relacionadas\" ─────────────────────────────────\r\n Sync SVG Figma (1143:1709/1885/1909): frame 215×48 con texto casi al\r\n borde → padding 12px (antes 28px). Estados ya coincidían exacto. */\r\n.pghost {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n height: 48px;\r\n padding: 0 12px;\r\n border-radius: var(--vmc-radius-full, 9999px);\r\n border: 2px solid rgba(255,255,255,0.75);\r\n cursor: pointer;\r\n position: relative;\r\n overflow: hidden;\r\n font-family: var(--vmc-font-display, \"Plus Jakarta Sans\", sans-serif);\r\n font-size: 16px;\r\n line-height: 20px;\r\n font-weight: 600;\r\n color: var(--vmc-color-base-white, #ffffff);\r\n background: transparent;\r\n text-shadow: rgba(0,0,0,0.18) 0 1px 3px;\r\n box-shadow: rgba(255,255,255,0.2) 0 1px 0 2px inset, rgba(255,255,255,0.15) 0 0 0 1px;\r\n transition:\r\n background 0.25s,\r\n border-color 0.25s,\r\n color 0.25s,\r\n transform 0.2s cubic-bezier(0.25, 0.8, 0.25, 1),\r\n box-shadow 0.25s;\r\n transform: translateZ(0);\r\n}\r\n.pghost::before {\r\n content: \"\";\r\n position: absolute;\r\n inset: 0;\r\n border-radius: var(--vmc-radius-full, 9999px);\r\n background: linear-gradient(rgba(255,255,255,0.1) 0%, transparent 55%);\r\n pointer-events: none;\r\n z-index: 1;\r\n}\r\n.pghost::after {\r\n content: \"\";\r\n position: absolute;\r\n inset: -4px;\r\n border-radius: var(--vmc-radius-full, 9999px);\r\n background: linear-gradient(135deg,\r\n var(--vmc-color-orange-600, oklch(0.72 0.16 55)),\r\n var(--vmc-color-vault-500, oklch(0.55 0.22 285))\r\n );\r\n filter: blur(16px);\r\n opacity: 0;\r\n z-index: -1;\r\n transition: opacity 0.3s, filter 0.3s;\r\n}\r\n.pghost:hover {\r\n background: linear-gradient(146.64deg, #fff 0%, rgb(255,240,226) 100%);\r\n border-color: #fff;\r\n color: #ed8936;\r\n text-shadow: rgba(0,0,0,0.25) 0 1px 3px;\r\n transform: translateY(-2px) scale(1.02);\r\n box-shadow: rgba(255,255,255,0.5) 0 1px 0 2px inset, rgba(0,0,0,0.2) 0 6px 20px;\r\n}\r\n.pghost:hover::after { opacity: 0.4; filter: blur(18px); }\r\n.pghost:active {\r\n background: linear-gradient(146.56deg, rgb(212,110,32) 0%, rgb(183,55,0) 100%);\r\n border-color: #d46e20;\r\n color: var(--vmc-color-icon-disabled, #e1e3e2);\r\n text-shadow: rgba(0,0,0,0.25) 0 1px 3px;\r\n transform: scale(0.97) translateY(1px);\r\n box-shadow: rgba(0,0,0,0.22) 0 2px 5px 2px inset;\r\n}\r\n.pghost:active::after { opacity: 0; }\r\n.pghost:disabled {\r\n /* SVG Ghost/Disabled (1153:2443): borde white 0.3, glass white 0.1→transparent, texto white 0.35 */\r\n background: linear-gradient(rgba(255,255,255,0.1) 0%, transparent 55%);\r\n border: 2px solid rgba(255,255,255,0.3);\r\n color: rgba(255,255,255,0.35);\r\n text-shadow: none;\r\n box-shadow: none;\r\n cursor: not-allowed;\r\n transform: none;\r\n}\r\n.pghost:focus-visible {\r\n outline: transparent solid 3px;\r\n outline-offset: 4px;\r\n transform: scale(0.98);\r\n box-shadow:\r\n 0 0 0 2px var(--vmc-color-base-white, #fff),\r\n 0 0 0 5px var(--vmc-color-vault-500, oklch(0.55 0.22 285)),\r\n 0 8px 16px -4px rgb(51.76% 37.65% 89.8% / 0.30);\r\n}\r\n\r\n/* ── sm-guest ─────────────────────────────────────────────────────────── */\r\n.pvbtn-sm {\r\n --vbtn-stop-a: var(--vmc-color-orange-600, #ed8936);\r\n --vbtn-stop-b: var(--vmc-color-vault-500, #8460e5);\r\n display: inline-flex;\r\n align-items: center;\r\n gap: 8px;\r\n height: 40px;\r\n min-width: 116px;\r\n padding: 0 16px 0 4px;\r\n border-radius: var(--vmc-radius-full, 9999px);\r\n /* Borde GRADIENTE de Figma (1159:4466): white → #FBC47D 25% → #AE8EFF 75% → white */\r\n border: 2px solid transparent;\r\n cursor: pointer;\r\n position: relative;\r\n overflow: hidden;\r\n font-family: var(--vmc-font-display, \"Plus Jakarta Sans\", sans-serif);\r\n font-size: 14px;\r\n line-height: 16px;\r\n font-weight: 600;\r\n color: var(--vmc-color-base-white, #ffffff);\r\n text-shadow: rgba(0,0,0,0.2) 0 1px 2px;\r\n background-image:\r\n linear-gradient(var(--vbtn-angle), var(--vbtn-stop-a) 0%, var(--vbtn-stop-a) 40%, var(--vbtn-stop-b) 100%),\r\n linear-gradient(135deg, #ffffff 0%, #fbc47d 25%, #ae8eff 75%, #ffffff 100%);\r\n background-origin: padding-box, border-box;\r\n background-clip: padding-box, border-box;\r\n box-shadow: rgba(255,255,255,0.25) 0 1px 0 2px inset, rgba(237,137,54,0.25) 0 2px 6px;\r\n transition:\r\n --vbtn-angle 0.4s cubic-bezier(0.25, 0.8, 0.25, 1),\r\n --vbtn-stop-a 0.35s,\r\n --vbtn-stop-b 0.35s,\r\n transform 0.2s cubic-bezier(0.25, 0.8, 0.25, 1),\r\n box-shadow 0.25s;\r\n transform: translateZ(0);\r\n}\r\n.pvbtn-sm::before {\r\n content: \"\";\r\n position: absolute;\r\n inset: 0;\r\n border-radius: var(--vmc-radius-full, 9999px);\r\n background: linear-gradient(rgba(255,255,255,0.15) 0%, transparent 55%);\r\n pointer-events: none;\r\n z-index: 1;\r\n}\r\n.pvbtn-sm:hover {\r\n --vbtn-angle: 220deg;\r\n --vbtn-stop-a: var(--vmc-color-orange-400, #fbc47d);\r\n --vbtn-stop-b: var(--vmc-color-vault-400, #ae8eff);\r\n transform: translateY(-1px) scale(1.02);\r\n box-shadow: rgba(255,255,255,0.2) 0 1px 0 2px inset, rgba(132,96,229,0.3) 0 6px 18px, rgba(237,137,54,0.35) 0 3px 8px;\r\n}\r\n.pvbtn-sm:active {\r\n --vbtn-angle: 135deg;\r\n --vbtn-stop-a: var(--vmc-color-orange-700, #d46e20);\r\n --vbtn-stop-b: var(--vmc-color-vault-600, #5a35c2);\r\n color: #d1d5dc;\r\n transform: scale(0.97) translateY(1px);\r\n box-shadow: rgba(0,0,0,0.22) 0 2px 4px 2px inset, rgba(255,255,255,0.28) 0 1px 0 inset, rgba(0,0,0,0.1) 0 1px 2px;\r\n}\r\n.pvbtn-sm:disabled {\r\n background-image: none;\r\n background-color: var(--vmc-color-background-disabled, #e1e3e2);\r\n color: var(--vmc-color-neutral-700, #99a1af);\r\n text-shadow: none;\r\n box-shadow: none;\r\n cursor: not-allowed;\r\n transform: none;\r\n}\r\n.pvbtn-sm:focus-visible {\r\n outline: transparent solid 2px;\r\n outline-offset: 3px;\r\n box-shadow:\r\n 0 0 0 2px var(--vmc-color-base-white, #fff),\r\n 0 0 0 4px var(--vmc-color-vault-500, oklch(0.55 0.22 285));\r\n}\r\n.pvbtn-icon {\r\n width: 32px;\r\n height: 32px;\r\n border-radius: 50%;\r\n /* Figma SVG 1159:4466: círculo blanco translúcido (no oscuro) */\r\n background: rgba(255,255,255,0.2);\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n flex-shrink: 0;\r\n position: relative;\r\n z-index: 2;\r\n}\r\n\r\n/* ── sm-logged-in ─────────────────────────────────────────────────────── */\r\n.pvbtn-auth-d {\r\n display: inline-flex;\r\n align-items: center;\r\n gap: 8px;\r\n height: 40px;\r\n padding: 0 16px 0 4px;\r\n border-radius: var(--vmc-radius-full, 9999px);\r\n border: 2px solid rgba(255,255,255,0.7);\r\n cursor: pointer;\r\n position: relative;\r\n overflow: hidden;\r\n font-family: var(--vmc-font-display, \"Plus Jakarta Sans\", sans-serif);\r\n font-size: 14px;\r\n line-height: 16px;\r\n font-weight: 600;\r\n color: var(--vmc-color-base-white, #ffffff);\r\n text-shadow: rgba(0,0,0,0.22) 0 1px 2px;\r\n background-image: linear-gradient(var(--vbtn-angle), var(--vbtn-stop-a) 0%, var(--vbtn-stop-a) 40%, var(--vbtn-stop-b) 100%);\r\n box-shadow: rgba(255,255,255,0.28) 0 1px 0 2px inset, rgba(237,137,54,0.3) 0 2px 6px;\r\n transition:\r\n --vbtn-angle 0.4s cubic-bezier(0.25, 0.8, 0.25, 1),\r\n --vbtn-stop-a 0.35s,\r\n --vbtn-stop-b 0.35s,\r\n transform 0.2s cubic-bezier(0.25, 0.8, 0.25, 1),\r\n box-shadow 0.25s;\r\n transform: translateZ(0);\r\n}\r\n.pvbtn-auth-d:hover {\r\n --vbtn-angle: 220deg;\r\n --vbtn-stop-a: var(--vmc-color-orange-400, #fbc47d);\r\n --vbtn-stop-b: var(--vmc-color-vault-400, #ae8eff);\r\n transform: translateY(-2px) scale(1.02);\r\n box-shadow: rgba(255,255,255,0.22) 0 1px 0 2px inset, rgba(132,96,229,0.35) 0 8px 24px, rgba(237,137,54,0.4) 0 4px 10px;\r\n}\r\n.pvbtn-auth-d:active {\r\n --vbtn-angle: 135deg;\r\n --vbtn-stop-a: var(--vmc-color-orange-700, #d46e20);\r\n --vbtn-stop-b: var(--vmc-color-vault-600, #5a35c2);\r\n color: #d1d5dc;\r\n transform: scale(0.97) translateY(1px);\r\n box-shadow: rgba(0,0,0,0.22) 0 2px 5px 2px inset, rgba(0,0,0,0.12) 0 1px 3px;\r\n}\r\n.pvbtn-auth-d:disabled {\r\n background-image: none;\r\n background-color: var(--vmc-color-background-disabled, #e1e3e2);\r\n color: var(--vmc-color-neutral-700, #99a1af);\r\n text-shadow: none;\r\n box-shadow: none;\r\n cursor: not-allowed;\r\n transform: none;\r\n}\r\n.pvbtn-auth-d:focus-visible {\r\n outline: transparent solid 3px;\r\n outline-offset: 4px;\r\n transform: scale(0.98);\r\n box-shadow:\r\n 0 0 0 2px var(--vmc-color-base-white, #fff),\r\n 0 0 0 5px var(--vmc-color-vault-500, oklch(0.55 0.22 285)),\r\n 0 8px 16px -4px rgb(51.76% 37.65% 89.8% / 0.30);\r\n}\r\n.pvbtn-auth-d-icon {\r\n width: 32px;\r\n height: 32px;\r\n border-radius: 50%;\r\n background: rgba(0,0,0,0.18);\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n flex-shrink: 0;\r\n position: relative;\r\n z-index: 2;\r\n}\r\n.pvbtn-auth-d-username {\r\n font-weight: 700;\r\n opacity: 0.92;\r\n}\r\n\r\n/* ── prefers-reduced-motion ──────────────────────────────────────────── */\r\n/* ── negotiable (teal → vault) · sync EXACTO del SVG export de Figma ────\r\n Nodos 1807:14907/14943/14957 · 200×48 FIJO · borde gradiente teal→vault\r\n Spec: .claude/concorde/inbox/figma-ButtonNegotiable-svg-export.json */\r\n.pneg {\r\n --vneg-stop-a: var(--vmc-color-teal-500, #00aeb1);\r\n --vneg-stop-b: var(--vmc-color-vault-500, #8460e5);\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n height: 48px;\r\n min-width: 200px;\r\n padding: 0 24px;\r\n border-radius: var(--vmc-radius-full, 9999px);\r\n /* Borde GRADIENTE de Figma (no blanco sólido): capa border-box bajo el fill */\r\n border: 2px solid transparent;\r\n cursor: pointer;\r\n position: relative;\r\n overflow: hidden;\r\n font-family: var(--vmc-font-display, \"Plus Jakarta Sans\", sans-serif);\r\n font-size: 16px;\r\n line-height: 20px;\r\n font-weight: 600;\r\n color: var(--vmc-color-base-white, #ffffff);\r\n text-shadow: rgba(0,0,0,0.25) 0 1px 3px;\r\n background-image:\r\n linear-gradient(var(--vneg-angle), var(--vneg-stop-a) 0%, var(--vneg-stop-a) 40%, var(--vneg-stop-b) 100%),\r\n linear-gradient(135deg, #ffffff 0%, #4ddcdc 25%, #6445df 75%, #ffffff 100%);\r\n background-origin: padding-box, border-box;\r\n background-clip: padding-box, border-box;\r\n box-shadow: rgba(255,255,255,0.28) 0 1px 0 2px inset, rgba(0,174,177,0.35) 0 2px 6px;\r\n transition:\r\n --vneg-angle 0.4s cubic-bezier(0.25, 0.8, 0.25, 1),\r\n --vneg-stop-a 0.35s,\r\n --vneg-stop-b 0.35s,\r\n transform 0.2s cubic-bezier(0.25, 0.8, 0.25, 1),\r\n box-shadow 0.25s;\r\n transform: translateZ(0);\r\n}\r\n.pneg::before {\r\n content: \"\";\r\n position: absolute;\r\n inset: 0;\r\n border-radius: var(--vmc-radius-full, 9999px);\r\n background: linear-gradient(rgba(255,255,255,0.17) 0%, transparent 55%);\r\n pointer-events: none;\r\n z-index: 1;\r\n}\r\n.pneg::after {\r\n content: \"\";\r\n position: absolute;\r\n inset: -4px;\r\n border-radius: var(--vmc-radius-full, 9999px);\r\n background: linear-gradient(135deg,\r\n var(--vmc-color-teal-500, #00aeb1),\r\n var(--vmc-color-vault-500, #8460e5)\r\n );\r\n filter: blur(14px);\r\n opacity: 0;\r\n z-index: -1;\r\n transition: opacity 0.3s, filter 0.3s;\r\n}\r\n.pneg:hover {\r\n --vneg-angle: 220deg;\r\n --vneg-stop-a: var(--vmc-color-teal-400, #00cccc);\r\n --vneg-stop-b: var(--vmc-color-vault-400, #ae8eff);\r\n transform: translateY(-2px) scale(1.02);\r\n /* Sombras exactas del SVG hover: teal cercana + glow púrpura #6445DF */\r\n box-shadow: rgba(255,255,255,0.22) 0 1px 0 2px inset, rgba(0,174,177,0.4) 0 4px 10px, rgba(100,69,223,0.35) 0 8px 24px;\r\n}\r\n.pneg:hover::after { opacity: 0.45; filter: blur(18px); }\r\n.pneg:active {\r\n --vneg-angle: 135deg;\r\n --vneg-stop-a: var(--vmc-color-teal-600, #009095);\r\n --vneg-stop-b: var(--vmc-color-vault-600, #5a35c2);\r\n color: #d1d5dc; /* exacto del SVG pressed */\r\n transform: scale(0.97) translateY(1px);\r\n box-shadow: rgba(0,0,0,0.22) 0 2px 5px 2px inset, rgba(0,0,0,0.12) 0 1px 3px;\r\n}\r\n.pneg:active::after { opacity: 0; }\r\n.pneg:disabled {\r\n background-image: none;\r\n background-color: var(--vmc-color-background-disabled, #e1e3e2);\r\n color: var(--vmc-color-neutral-700, #99a1af);\r\n text-shadow: none;\r\n box-shadow: none;\r\n cursor: not-allowed;\r\n transform: none;\r\n border-color: transparent;\r\n}\r\n.pneg:disabled::after { display: none; }\r\n.pneg:focus-visible {\r\n outline: transparent solid 3px;\r\n outline-offset: 4px;\r\n transform: scale(0.98);\r\n box-shadow:\r\n 0 0 0 2px var(--vmc-color-base-white, #fff),\r\n 0 0 0 5px var(--vmc-color-teal-500, #00aeb1),\r\n 0 8px 16px -4px rgba(0,174,177,0.3);\r\n}\r\n\r\n/* ── outline · \"Regístrate\" — RECONSTRUIDO desde cero con SVGs de Figma ──\r\n Default 1932:10613 · Hover 1934:10627 · Pressed 1935:10631 (215×48, radius full)\r\n 3 capas Figma por estado: relleno (paint0) + borde 1px gradiente (stroke) + glass white 0.1 (paint2)\r\n Borde = STROKE de 1px (sin stroke-width = 1px), NO 2px. Glass presente en TODOS los estados. */\r\n.poutline {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n height: 48px;\r\n padding: 0 56px;\r\n border-radius: var(--vmc-radius-full, 9999px);\r\n border: none;\r\n cursor: pointer;\r\n position: relative;\r\n font-family: var(--vmc-font-display, \"Plus Jakarta Sans\", sans-serif);\r\n font-size: 16px;\r\n line-height: 20px;\r\n font-weight: 600;\r\n color: var(--vmc-color-orange-600, #ed8936);\r\n /* Default: relleno transparente + glass white 0.1 → transparent 55% (paint1) */\r\n background-image: linear-gradient(180deg, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0) 55%);\r\n box-shadow: none;\r\n transition:\r\n background 0.25s,\r\n color 0.25s,\r\n transform 0.2s cubic-bezier(0.25, 0.8, 0.25, 1),\r\n box-shadow 0.25s;\r\n transform: translateZ(0);\r\n}\r\n/* Borde = anillo gradiente de 1px (centro 100% transparente, sin doble borde) — mask trick.\r\n Default/Hover: naranja diagonal #FF9639 → #EF852E 50% → #BE3D00 (vector ~144deg) */\r\n.poutline::before {\r\n content: \"\";\r\n position: absolute;\r\n inset: 0;\r\n border-radius: inherit;\r\n padding: 1px;\r\n background: linear-gradient(144deg, #ff9639 0%, #ef852e 50%, #be3d00 100%);\r\n -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);\r\n -webkit-mask-composite: xor;\r\n mask-composite: exclude;\r\n pointer-events: none;\r\n z-index: 1;\r\n transition: background 0.25s;\r\n}\r\n/* Glow exterior — interacción Concorde (no existe en Figma estático) */\r\n.poutline::after {\r\n content: \"\";\r\n position: absolute;\r\n inset: -4px;\r\n border-radius: inherit;\r\n background: linear-gradient(144deg,\r\n var(--vmc-color-orange-600, #ed8936),\r\n var(--vmc-color-orange-tint, #fff0e2)\r\n );\r\n filter: blur(16px);\r\n opacity: 0;\r\n z-index: -1;\r\n transition: opacity 0.3s, filter 0.3s;\r\n}\r\n.poutline:hover {\r\n /* Hover 1934:10627: relleno white→#FFF0E2 horizontal (paint0) + glass (paint2). Un solo borde 1px */\r\n background-image:\r\n linear-gradient(180deg, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0) 55%),\r\n linear-gradient(90deg, #ffffff 0%, var(--vmc-color-orange-tint, #fff0e2) 100%);\r\n color: var(--vmc-color-orange-600, #ed8936);\r\n text-shadow: rgba(0,0,0,0.08) 0 1px 2px;\r\n transform: translateY(-2px) scale(1.02);\r\n box-shadow: rgba(190,61,0,0.18) 0 6px 18px -4px;\r\n}\r\n.poutline:hover::after { opacity: 0.35; filter: blur(18px); }\r\n.poutline:active {\r\n /* Pressed 1935:10631: relleno #D46E20→#B73700 (paint0 ~156deg) + glass. Borde oscuro vertical */\r\n background-image:\r\n linear-gradient(180deg, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0) 55%),\r\n linear-gradient(156deg, #d46e20 0%, #b73700 100%);\r\n color: var(--vmc-color-base-white, #fff);\r\n text-shadow: rgba(0,0,0,0.22) 0 1px 2px;\r\n transform: scale(0.97) translateY(1px);\r\n box-shadow: rgba(0,0,0,0.16) 0 1px 3px;\r\n}\r\n/* Pressed: anillo oscuro #B25614 → #93420A VERTICAL (paint1 vector 180deg) */\r\n.poutline:active::before { background: linear-gradient(180deg, #b25614 0%, #93420a 100%); }\r\n.poutline:active::after { opacity: 0; }\r\n.poutline:disabled {\r\n background-image: linear-gradient(180deg, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0) 55%);\r\n color: rgba(237,137,54,0.4);\r\n box-shadow: none;\r\n cursor: not-allowed;\r\n transform: none;\r\n}\r\n.poutline:disabled::before { background: rgba(237,137,54,0.3); }\r\n.poutline:disabled::after { opacity: 0; }\r\n.poutline:focus-visible {\r\n outline: transparent solid 3px;\r\n outline-offset: 4px;\r\n transform: scale(0.98);\r\n box-shadow:\r\n 0 0 0 2px var(--vmc-color-base-white, #fff),\r\n 0 0 0 5px var(--vmc-color-orange-600, #ed8936);\r\n}\r\n\r\n/* ── secondary-sm · \"Agenda tu visita\" ──────────────────────────────────\r\n Sync EXACTO del SVG export de Figma (Variant=Secondary, Size=Small)\r\n Nodos 1442:10976 / 1464:19933 / 1464:20511 · 160×40 fijo · ícono calendario\r\n Spec: .claude/concorde/inbox/figma-ButtonGhost-SecondarySm-svg-export.json */\r\n.psec-sm {\r\n --vss-stop-a: var(--vmc-color-vault-500, #8460e5);\r\n --vss-stop-b: var(--vmc-color-vault-700, #3b1782);\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 4px;\r\n height: 40px;\r\n min-width: 160px;\r\n padding: 0 12px 0 4px;\r\n border-radius: var(--vmc-radius-full, 9999px);\r\n /* Borde GRADIENTE lila de Figma (constante en los 3 estados) */\r\n border: 2px solid transparent;\r\n cursor: pointer;\r\n position: relative;\r\n overflow: hidden;\r\n font-family: var(--vmc-font-display, \"Plus Jakarta Sans\", sans-serif);\r\n font-size: 14px;\r\n line-height: 16px;\r\n font-weight: 600;\r\n color: var(--vmc-color-base-white, #ffffff);\r\n text-shadow: rgba(0,0,0,0.25) 0 1px 3px;\r\n background-image:\r\n linear-gradient(var(--vss-angle), var(--vss-stop-a) 0%, var(--vss-stop-b) 100%),\r\n linear-gradient(135deg, #cfbaff 0%, #ffffff 35%, #ae8eff 65%, #cfbaff 100%);\r\n background-origin: padding-box, border-box;\r\n background-clip: padding-box, border-box;\r\n box-shadow: rgba(255,255,255,0.22) 0 1px 0 2px inset, rgba(132,96,229,0.3) 0 2px 8px;\r\n transition:\r\n --vss-angle 0.4s cubic-bezier(0.25, 0.8, 0.25, 1),\r\n --vss-stop-a 0.35s,\r\n --vss-stop-b 0.35s,\r\n transform 0.2s cubic-bezier(0.25, 0.8, 0.25, 1),\r\n box-shadow 0.25s;\r\n transform: translateZ(0);\r\n}\r\n.psec-sm::before {\r\n content: \"\";\r\n position: absolute;\r\n inset: 0;\r\n border-radius: var(--vmc-radius-full, 9999px);\r\n background: linear-gradient(rgba(255,255,255,0.16) 0%, transparent 55%);\r\n pointer-events: none;\r\n z-index: 1;\r\n}\r\n.psec-sm:hover {\r\n --vss-angle: 219deg;\r\n --vss-stop-a: var(--vmc-color-vault-400, #ae8eff);\r\n --vss-stop-b: var(--vmc-color-vault-600, #5a35c2);\r\n transform: translateY(-1px) scale(1.02);\r\n box-shadow: rgba(255,255,255,0.2) 0 1px 0 2px inset, rgba(132,96,229,0.25) 0 4px 10px, rgba(132,96,229,0.4) 0 8px 24px;\r\n}\r\n.psec-sm:active {\r\n --vss-angle: 160deg;\r\n --vss-stop-a: var(--vmc-color-vault-700, #3b1782);\r\n --vss-stop-b: var(--vmc-color-vault-900, #22005c);\r\n color: #d1d5dc;\r\n transform: scale(0.97) translateY(1px);\r\n box-shadow: rgba(0,0,0,0.28) 0 2px 5px 2px inset, rgba(0,0,0,0.14) 0 1px 3px;\r\n}\r\n.psec-sm:disabled {\r\n background-image: none;\r\n background-color: var(--vmc-color-background-disabled, #e1e3e2);\r\n color: var(--vmc-color-neutral-700, #99a1af);\r\n text-shadow: none;\r\n box-shadow: none;\r\n cursor: not-allowed;\r\n transform: none;\r\n border-color: transparent;\r\n}\r\n.psec-sm:focus-visible {\r\n outline: transparent solid 2px;\r\n outline-offset: 3px;\r\n box-shadow:\r\n 0 0 0 2px var(--vmc-color-base-white, #fff),\r\n 0 0 0 4px var(--vmc-color-vault-500, #8460e5);\r\n}\r\n.psec-sm-icon {\r\n width: 32px;\r\n height: 32px;\r\n border-radius: 50%;\r\n background: rgba(255,255,255,0.2);\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n flex-shrink: 0;\r\n position: relative;\r\n z-index: 2;\r\n}\r\n\r\n/* ── prefers-reduced-motion ──────────────────────────────────────────── */\r\n@media (prefers-reduced-motion: reduce) {\r\n .pvbtn, .psec, .psec-sm, .pneg, .pghost, .poutline, .pvbtn-sm, .pvbtn-auth-d {\r\n transition: none;\r\n }\r\n .pvbtn::after, .psec::after, .pneg::after, .pghost::after, .poutline::after {\r\n transition: none;\r\n }\r\n}\r\n`;\r\n\r\n// ── Style injection ───────────────────────────────────────────────────────\r\n\r\nconst STYLE_ID = \"concorde-button-styles\";\r\nlet stylesInjected = false;\r\n\r\nfunction injectStyles(): void {\r\n if (typeof document === \"undefined\" || stylesInjected) return;\r\n if (!document.getElementById(STYLE_ID)) {\r\n const el = document.createElement(\"style\");\r\n el.id = STYLE_ID;\r\n el.textContent = BUTTON_STYLES;\r\n document.head.appendChild(el);\r\n }\r\n stylesInjected = true;\r\n}\r\n\r\n// ── Icon ─────────────────────────────────────────────────────────────────\r\n\r\n// Ícono \"user\" — path EXACTO del SVG export de Figma (Primary/Small \"Ingresa\",\r\n// nodo 1159:4466). Cabeza circular + cuerpo (hombros) rellenos. 24px dentro del\r\n// círculo de 32px (igual que Figma). fill=currentColor → en pressed hereda #E1E3E2.\r\nexport function UserIcon(): JSX.Element {\r\n return (\r\n \r\n \r\n \r\n );\r\n}\r\n\r\n// Ícono calendario — paths EXACTOS del SVG de Figma (Secondary/Small \"Agenda tu visita\").\r\n// stroke currentColor → en pressed hereda #e1e3e2 igual que en Figma.\r\nexport function CalendarIcon(): JSX.Element {\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n );\r\n}\r\n\r\n// ── Variant → class map ───────────────────────────────────────────────────\r\n\r\nconst VARIANT_CLASS: Record = {\r\n primary: \"pvbtn\",\r\n negotiable: \"pneg\",\r\n secondary: \"psec\",\r\n \"secondary-sm\": \"psec-sm\",\r\n ghost: \"pghost\",\r\n outline: \"poutline\",\r\n \"sm-guest\": \"pvbtn-sm\",\r\n \"sm-logged-in\": \"pvbtn-auth-d\",\r\n};\r\n\r\n// ── Component ─────────────────────────────────────────────────────────────\r\n\r\nconst Button = forwardRef(function Button(\r\n { variant = \"primary\", icon, username, className, type = \"button\", children, ...rest },\r\n ref,\r\n) {\r\n injectStyles();\r\n\r\n const cls = VARIANT_CLASS[variant];\r\n\r\n let content: ReactNode;\r\n if (variant === \"sm-guest\") {\r\n content = (\r\n <>\r\n {icon ? {icon} : null}\r\n {children}\r\n >\r\n );\r\n } else if (variant === \"secondary-sm\") {\r\n content = (\r\n <>\r\n {icon ? {icon} : null}\r\n {children}\r\n >\r\n );\r\n } else if (variant === \"sm-logged-in\") {\r\n content = (\r\n <>\r\n {icon ? {icon} : null}\r\n Bienvenido,{\" \"}\r\n {username ?? children} \r\n >\r\n );\r\n } else {\r\n content = children;\r\n }\r\n\r\n return (\r\n <>\r\n \r\n \r\n {content}\r\n \r\n >\r\n );\r\n});\r\n\r\nexport default Button;\r\n"
}
]
}