secure-ui-components 0.2.5 → 0.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,384 @@
1
+ var c=Object.freeze({PUBLIC:"public",AUTHENTICATED:"authenticated",SENSITIVE:"sensitive",CRITICAL:"critical"}),S=Object.freeze({[c.PUBLIC]:Object.freeze({name:"Public",level:1,validation:Object.freeze({required:!1,strict:!1,maxLength:5e3,pattern:null,sanitizeHtml:!0}),masking:Object.freeze({enabled:!1,character:"\u2022",partial:!1}),storage:Object.freeze({allowAutocomplete:!0,allowCache:!0,allowHistory:!0}),audit:Object.freeze({logAccess:!1,logChanges:!1,logSubmission:!1,includeMetadata:!1}),rateLimit:Object.freeze({enabled:!1,maxAttempts:0,windowMs:0})}),[c.AUTHENTICATED]:Object.freeze({name:"Authenticated",level:2,validation:Object.freeze({required:!0,strict:!1,maxLength:1e3,pattern:null,sanitizeHtml:!0}),masking:Object.freeze({enabled:!1,character:"\u2022",partial:!1}),storage:Object.freeze({allowAutocomplete:!0,allowCache:!1,allowHistory:!1}),audit:Object.freeze({logAccess:!1,logChanges:!0,logSubmission:!0,includeMetadata:!0}),rateLimit:Object.freeze({enabled:!1,maxAttempts:0,windowMs:0})}),[c.SENSITIVE]:Object.freeze({name:"Sensitive",level:3,validation:Object.freeze({required:!0,strict:!0,maxLength:500,pattern:null,sanitizeHtml:!0}),masking:Object.freeze({enabled:!0,character:"\u2022",partial:!0}),storage:Object.freeze({allowAutocomplete:!1,allowCache:!1,allowHistory:!1}),audit:Object.freeze({logAccess:!0,logChanges:!0,logSubmission:!0,includeMetadata:!0}),rateLimit:Object.freeze({enabled:!0,maxAttempts:10,windowMs:6e4})}),[c.CRITICAL]:Object.freeze({name:"Critical",level:4,validation:Object.freeze({required:!0,strict:!0,maxLength:256,pattern:null,sanitizeHtml:!0}),masking:Object.freeze({enabled:!0,character:"\u2022",partial:!1}),storage:Object.freeze({allowAutocomplete:!1,allowCache:!1,allowHistory:!1}),audit:Object.freeze({logAccess:!0,logChanges:!0,logSubmission:!0,includeMetadata:!0}),rateLimit:Object.freeze({enabled:!0,maxAttempts:5,windowMs:6e4})})});function g(l){return!l||!S[l]?(console.warn(`Invalid security tier "${l}", defaulting to CRITICAL`),S[c.CRITICAL]):S[l]}function _(l){return Object.values(c).includes(l)}function O(l,e){let t=g(l),i=g(e);return Math.sign(t.level-i.level)}function W(l,e){return O(l,e)>=0?l:e}var Z=Object.freeze({[c.PUBLIC]:Object.freeze({"default-src":["'self'"],"script-src":["'self'"],"style-src":["'self'"]}),[c.AUTHENTICATED]:Object.freeze({"default-src":["'self'"],"script-src":["'self'"],"style-src":["'self'"],"form-action":["'self'"]}),[c.SENSITIVE]:Object.freeze({"default-src":["'self'"],"script-src":["'self'"],"style-src":["'self'"],"form-action":["'self'"],"frame-ancestors":["'none'"],"upgrade-insecure-requests":[]}),[c.CRITICAL]:Object.freeze({"default-src":["'self'"],"script-src":["'self'"],"style-src":["'self'"],"form-action":["'self'"],"frame-ancestors":["'none'"],"upgrade-insecure-requests":[],"block-all-mixed-content":[],"base-uri":["'none'"]})}),G=Object.freeze({"X-Content-Type-Options":"nosniff","X-Frame-Options":"DENY","X-XSS-Protection":"1; mode=block","Referrer-Policy":"strict-origin-when-cross-origin","Permissions-Policy":"geolocation=(), microphone=(), camera=()"});var p=class l extends HTMLElement{static#e=1e3;static#s={"script-tag":"Script injection blocked","js-protocol":"JavaScript protocol blocked","event-handler":"Event handler injection blocked","html-injection":"HTML element injection blocked","css-expression":"CSS expression injection blocked",vbscript:"VBScript injection blocked","data-uri-html":"Data URI injection blocked","template-syntax":"Template injection blocked"};static#i=[{id:"script-tag",pattern:/<script[\s>/]/i},{id:"js-protocol",pattern:/javascript\s*:/i},{id:"event-handler",pattern:/\bon\w+\s*=/i},{id:"html-injection",pattern:/<\s*(img|svg|iframe|object|embed|link|meta|base)[^>]*/i},{id:"css-expression",pattern:/expression\s*\(/i},{id:"vbscript",pattern:/vbscript\s*:/i},{id:"data-uri-html",pattern:/data:\s*text\/html/i},{id:"template-syntax",pattern:/\{\{[\s\S]*?\}\}/}];#r=c.CRITICAL;#t;#a;#n=[];#o={attempts:0,windowStart:Date.now()};#u=!1;#c={focusAt:null,firstKeystrokeAt:null,blurAt:null,keyCount:0,correctionCount:0,pasteDetected:!1,autofillDetected:!1,focusCount:0,blurWithoutChange:0,lastInputLength:0};constructor(){super(),this.#a=this.attachShadow({mode:"closed"}),this.#t=g(this.#r)}static get observedAttributes(){return["security-tier","disabled","readonly","threat-feedback"]}connectedCallback(){this.#u||(this.#h(),this.#u=!0)}#h(){this.initializeSecurity(),this.#d()}initializeSecurity(){let e=this.getAttribute("security-tier");e&&_(e)&&(this.#r=e),this.#t=g(this.#r),this.#l("component_initialized",{tier:this.#r,timestamp:new Date().toISOString()})}attributeChangedCallback(e,t,i){if(e==="security-tier"&&this.#u){console.warn(`Security tier cannot be changed after initialization. Attempted change from "${t}" to "${i}" blocked.`),t!==null&&this.setAttribute("security-tier",t);return}this.#u&&this.handleAttributeChange(e,t,i)}handleAttributeChange(e,t,i){}#d(){this.#a.innerHTML="",this.addComponentStyles(":host { display: block; box-sizing: border-box; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; font-size: 14px; line-height: 1.5; } :host([hidden]) { display: none; } * { box-sizing: border-box; } .hidden { display: none; } .security-badge { display: inline-block; padding: var(--secure-ui-badge-padding, 2px 6px); margin-left: var(--secure-ui-space-2, 0.5rem); font-size: var(--secure-ui-badge-font-size, 0.6875rem); font-weight: var(--secure-ui-font-weight-semibold, 600); border-radius: var(--secure-ui-badge-border-radius, 0.25rem); text-transform: uppercase; background-color: var(--secure-ui-color-bg-tertiary); color: var(--secure-ui-color-text-secondary); border: var(--secure-ui-border-width-thin, 1px) solid var(--secure-ui-color-border); }");let e=this.render();e&&this.#a.appendChild(e)}getBaseStylesheetUrl(){return":host { display: block; box-sizing: border-box; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; font-size: 14px; line-height: 1.5; } :host([hidden]) { display: none; } * { box-sizing: border-box; } .hidden { display: none; } .security-badge { display: inline-block; padding: var(--secure-ui-badge-padding, 2px 6px); margin-left: var(--secure-ui-space-2, 0.5rem); font-size: var(--secure-ui-badge-font-size, 0.6875rem); font-weight: var(--secure-ui-font-weight-semibold, 600); border-radius: var(--secure-ui-badge-border-radius, 0.25rem); text-transform: uppercase; background-color: var(--secure-ui-color-bg-tertiary); color: var(--secure-ui-color-text-secondary); border: var(--secure-ui-border-width-thin, 1px) solid var(--secure-ui-color-border); }"}addComponentStyles(e){if(e.includes("{")){let t=new CSSStyleSheet;t.replaceSync(e),this.#a.adoptedStyleSheets=[...this.#a.adoptedStyleSheets,t]}else{let t=document.createElement("link");t.rel="stylesheet",t.href=e,this.#a.appendChild(t)}}sanitizeValue(e){if(typeof e!="string")return"";let t=document.createElement("div");return t.textContent=e,t.innerHTML}validateInput(e,t={}){let i=[],r=this.#t;(t.required!==void 0?t.required:r.validation.required)&&(!e||e.trim().length===0)&&i.push("This field is required");let a=t.maxLength||r.validation.maxLength;e&&e.length>a&&i.push(`Value exceeds maximum length of ${a}`);let n=t.minLength||0;e&&e.length<n&&i.push(`Value must be at least ${n} characters`);let o=t.pattern||r.validation.pattern;return o&&e&&!o.test(e)&&i.push("Value does not match required format"),r.validation.strict&&i.length>0&&this.#l("validation_failed",{errors:i,valueLength:e?e.length:0}),{valid:i.length===0,errors:i}}checkRateLimit(){if(!this.#t.rateLimit.enabled)return{allowed:!0,retryAfter:0};let e=Date.now(),t=this.#t.rateLimit.windowMs;if(e-this.#o.windowStart>t&&(this.#o.attempts=0,this.#o.windowStart=e),this.#o.attempts>=this.#t.rateLimit.maxAttempts){let i=t-(e-this.#o.windowStart);return this.#l("rate_limit_exceeded",{attempts:this.#o.attempts,retryAfter:i}),{allowed:!1,retryAfter:i}}return this.#o.attempts++,{allowed:!0,retryAfter:0}}#l(e,t={}){let i=this.#t.audit;if(!(e.includes("access")&&i.logAccess||e.includes("change")&&i.logChanges||e.includes("submit")&&i.logSubmission||e.includes("initialized")||e.includes("rate_limit")||e.includes("validation")||e.includes("threat")))return;let s={event:e,tier:this.#r,timestamp:new Date().toISOString(),...t};i.includeMetadata&&(s.userAgent=navigator.userAgent,s.language=navigator.language),this.#n.length>=l.#e&&this.#n.shift(),this.#n.push(s),this.dispatchEvent(new CustomEvent("secure-audit",{detail:s,bubbles:!0,composed:!0}))}get shadowRoot(){return this.#a}get securityTier(){return this.#r}get config(){return this.#t}getAuditLog(){return[...this.#n]}clearAuditLog(){this.#n=[]}audit(e,t){this.#l(e,t)}detectInjection(e,t){for(let{id:i,pattern:r}of l.#i)if(r.test(e)){this.audit("threat_detected",{fieldName:t,patternId:i,threatType:"injection"}),this.dispatchEvent(new CustomEvent("secure-threat-detected",{detail:{fieldName:t,threatType:"injection",patternId:i,tier:this.securityTier,timestamp:Date.now()},bubbles:!0,composed:!0})),this.hasAttribute("threat-feedback")&&this.showThreatFeedback(i,this.securityTier);return}this.hasAttribute("threat-feedback")&&this.clearThreatFeedback()}showThreatFeedback(e,t){}clearThreatFeedback(){}getThreatLabel(e){return l.#s[e]??`Injection blocked: ${e}`}rerender(){this.#d()}recordTelemetryFocus(){let e=this.#c;e.focusAt=Date.now(),e.blurAt=null,e.focusCount++;let t=this.shadowRoot.querySelector('input:not([type="hidden"]), textarea, select');e.lastInputLength=t?t.value.length:0}recordTelemetryInput(e){let t=this.#c,i=Date.now();t.firstKeystrokeAt===null&&(t.firstKeystrokeAt=i);let s=e.inputType??"";s==="insertFromPaste"||s==="insertFromPasteAsQuotation"?t.pasteDetected=!0:s==="insertReplacementText"?t.autofillDetected=!0:s.startsWith("delete")||s==="historyUndo"||s==="historyRedo"?t.correctionCount++:t.keyCount++;let a=e.target;a&&(t.lastInputLength=a.value.length)}recordTelemetryBlur(){let e=this.#c;e.blurAt=Date.now();let t=this.shadowRoot.querySelector('input:not([type="hidden"]), textarea, select');(t?t.value.length:0)===e.lastInputLength&&e.keyCount===0&&!e.pasteDetected&&e.blurWithoutChange++}getFieldTelemetry(){let e=this.#c,t=e.focusAt??Date.now(),i=e.firstKeystrokeAt,r=e.blurAt??Date.now(),s=i!==null?i-t:0,a=i!==null?r-i:0,n=a/1e3,o=n>0?e.keyCount/n:0;return{dwell:s,completionTime:a,velocity:Math.round(o*100)/100,corrections:e.correctionCount,pasteDetected:e.pasteDetected,autofillDetected:e.autofillDetected,focusCount:e.focusCount,blurWithoutChange:e.blurWithoutChange}}#p(){this.#c={focusAt:null,firstKeystrokeAt:null,blurAt:null,keyCount:0,correctionCount:0,pasteDetected:!1,autofillDetected:!1,focusCount:0,blurWithoutChange:0,lastInputLength:0}}disconnectedCallback(){this.#o={attempts:0,windowStart:Date.now()},this.#p(),this.#t.audit.logAccess&&this.#l("component_disconnected",{timestamp:new Date().toISOString()})}};var k=class extends p{#e=null;#s=null;#i=null;#r=null;#t="";#a=!1;#n=null;#o=`secure-input-${Math.random().toString(36).substring(2,11)}`;static get observedAttributes(){return[...super.observedAttributes,"name","type","label","placeholder","required","pattern","minlength","maxlength","autocomplete","value"]}constructor(){super()}render(){let e=document.createDocumentFragment(),t=document.createElement("div");t.className="input-container",t.setAttribute("part","container");let i=this.getAttribute("label");i&&(this.#s=document.createElement("label"),this.#s.htmlFor=this.#o,this.#s.textContent=this.sanitizeValue(i),this.#s.setAttribute("part","label"),t.appendChild(this.#s));let r=document.createElement("div");return r.className="input-wrapper",r.setAttribute("part","wrapper"),this.#e=document.createElement("input"),this.#e.id=this.#o,this.#e.className="input-field",this.#e.setAttribute("part","input"),this.#d(),this.#l(),r.appendChild(this.#e),t.appendChild(r),this.#i=document.createElement("div"),this.#i.className="error-container hidden",this.#i.setAttribute("role","alert"),this.#i.setAttribute("part","error"),this.#i.id=`${this.#o}-error`,t.appendChild(this.#i),this.#r=document.createElement("div"),this.#r.className="threat-container hidden",this.#r.setAttribute("role","alert"),this.#r.setAttribute("part","threat"),this.#r.id=`${this.#o}-threat`,t.appendChild(this.#r),this.#u(),this.#h(),this.addComponentStyles(this.#x()),e.appendChild(t),e}#u(){let e=this.getAttribute("name");!e||this.closest("secure-form")||(this.#n=document.createElement("input"),this.#n.type="hidden",this.#n.name=e,this.#n.value=this.#t||"",this.appendChild(this.#n))}#c(){this.#n&&(this.#n.value=this.#t||"")}#h(){this.querySelectorAll("input, textarea, select").forEach(t=>{if(t===this.#n)return;let i=t;i.removeAttribute("required"),i.removeAttribute("name"),i.removeAttribute("minlength"),i.removeAttribute("maxlength"),i.removeAttribute("pattern"),i.setAttribute("tabindex","-1"),i.setAttribute("aria-hidden","true")})}#d(){let e=this.config,t=this.getAttribute("name");t&&(this.#e.name=this.sanitizeValue(t)),!this.getAttribute("label")&&t&&this.#e.setAttribute("aria-label",this.sanitizeValue(t)),this.#e.setAttribute("aria-describedby",`${this.#o}-error`);let i=this.getAttribute("type")||"text";this.#e.type=i;let r=this.getAttribute("placeholder");r&&(this.#e.placeholder=this.sanitizeValue(r)),(this.hasAttribute("required")||e.validation.required)&&(this.#e.required=!0,this.#e.setAttribute("aria-required","true"));let s=this.getAttribute("pattern");s&&(this.#e.pattern=s);let a=this.getAttribute("minlength");a&&(this.#e.minLength=parseInt(a,10));let n=this.getAttribute("maxlength")||e.validation.maxLength;if(n&&(this.#e.maxLength=parseInt(String(n),10)),e.storage.allowAutocomplete){let d=this.getAttribute("autocomplete")||"on";this.#e.autocomplete=d}else this.#e.autocomplete="off",this.#e.type==="password"&&(this.#e.autocomplete="new-password");this.hasAttribute("disabled")&&(this.#e.disabled=!0),this.hasAttribute("readonly")&&(this.#e.readOnly=!0);let o=this.getAttribute("value");o&&this.#E(o);let u=new Set(["email","url","tel"]);e.masking.enabled&&this.#e.type!=="password"&&!u.has(this.#e.type)&&(this.#a=!0)}#l(){this.#e.addEventListener("focus",()=>{this.recordTelemetryFocus(),this.audit("input_focused",{name:this.#e.name})}),this.#e.addEventListener("input",e=>{this.recordTelemetryInput(e),this.#p(e)}),this.#e.addEventListener("blur",()=>{this.recordTelemetryBlur(),this.#m(),this.audit("input_blurred",{name:this.#e.name,hasValue:this.#t.length>0})}),this.#e.addEventListener("change",()=>{this.audit("input_changed",{name:this.#e.name,valueLength:this.#t.length})})}#p(e){if(this.#a&&this.#e.type!=="password"){let t=e,i=t.inputType,r=t.data||"",s=this.#e.value,a=this.#e.selectionStart||0;if(i==="deleteContentBackward")a<this.#t.length&&(this.#t=this.#t.substring(0,a)+this.#t.substring(a+1));else if(i==="deleteContentForward")this.#t=this.#t.substring(0,a)+this.#t.substring(a+1);else if(i==="insertText")this.#t=this.#t.substring(0,a-r.length)+r+this.#t.substring(a-r.length);else if(i==="insertFromPaste")r&&(this.#t=this.#t.substring(0,a-r.length)+r+this.#t.substring(a-r.length));else{let o=this.#t.length,u=s.length;if(u>o){let d=u-o,h=a-d;this.#t=this.#t.substring(0,h)+s.substring(h,a)+this.#t.substring(h)}else u<o&&(this.#t=this.#t.substring(0,a)+this.#t.substring(a+(o-u)))}let n=this.#b(this.#t);this.#e.value=n,this.#e.setSelectionRange(a,a)}else this.#t=this.#e.value;this.detectInjection(this.#t,this.#e.name),this.#v(),this.#c(),this.dispatchEvent(new CustomEvent("secure-input",{detail:{name:this.#e.name,value:this.#t,masked:this.#a,tier:this.securityTier},bubbles:!0,composed:!0}))}#b(e){let t=this.config,i=t.masking.character;if(!t.masking.partial||this.securityTier===c.CRITICAL||e.length<=4)return i.repeat(e.length);let r=i.repeat(e.length-4),s=e.slice(-4);return r+s}#f(e){if(!this.#e||this.#e.type!=="password"||!e||e.length===0)return null;let t=this.securityTier;if(t==="critical"){if(e.length<8)return"Password must be at least 8 characters";if(!/[a-z]/.test(e))return"Password must include a lowercase letter";if(!/[A-Z]/.test(e))return"Password must include an uppercase letter";if(!/[0-9]/.test(e))return"Password must include a number";if(!/[^a-zA-Z0-9]/.test(e))return"Password must include a special character"}else if(t==="sensitive"){if(e.length<8)return"Password must be at least 8 characters";if(!/[a-z]/.test(e))return"Password must include a lowercase letter";if(!/[A-Z]/.test(e))return"Password must include an uppercase letter";if(!/[0-9]/.test(e))return"Password must include a number"}else if(t==="authenticated"&&e.length<6)return"Password must be at least 6 characters";return null}#y(e){if(!this.#e||this.#e.type!=="number"||!e||e.length===0)return null;let t=Number(e);if(!Number.isFinite(t))return"Value must be a valid number";if(!e.includes(".")&&!Number.isSafeInteger(t))return"Value exceeds safe integer range";let i=this.getAttribute("min"),r=this.getAttribute("max");if(i!==null){let s=Number(i);if(Number.isFinite(s)&&t<s)return`Value must be at least ${s}`}if(r!==null){let s=Number(r);if(Number.isFinite(s)&&t>s)return`Value must be at most ${s}`}return null}#m(){let e=this.checkRateLimit();if(!e.allowed){this.#g(`Too many attempts. Please wait ${Math.ceil(e.retryAfter/1e3)} seconds.`);return}let t=this.getAttribute("pattern"),i=this.getAttribute("minlength"),r=this.getAttribute("maxlength"),s=null;if(t)try{s=new RegExp(t)}catch{}let a=this.validateInput(this.#t,{required:this.hasAttribute("required")||this.config.validation.required,pattern:s,minLength:i?parseInt(i,10):0,maxLength:r?parseInt(r,10):this.config.validation.maxLength});if(!a.valid){this.#g(a.errors.join(", "));return}let n=this.#f(this.#t);if(n){this.#g(n);return}let o=this.#y(this.#t);if(o){this.#g(o);return}if(this.#e&&this.#t){let u,d;if(this.#a){let h=this.#e.value;this.#e.value=this.#t,u=this.#e.checkValidity(),d=this.#e.validationMessage,this.#e.value=h}else u=this.#e.checkValidity(),d=this.#e.validationMessage;if(!u){this.#g(d);return}}}#g(e){this.#i.textContent=e,this.#i.offsetHeight,this.#i.classList.remove("hidden"),this.#e.classList.add("error"),this.#e.setAttribute("aria-invalid","true")}#v(){this.#i.classList.add("hidden"),this.#i.addEventListener("transitionend",()=>{this.#i.classList.contains("hidden")&&(this.#i.textContent="")},{once:!0}),this.#e.classList.remove("error"),this.#e.removeAttribute("aria-invalid")}#E(e){this.#t=e,this.#a&&this.#e.type!=="password"?this.#e.value=this.#b(e):this.#e.value=e,this.#c()}#x(){return".input-container { margin-bottom: var(--secure-ui-form-gap); font-family: var(--secure-ui-font-family-base); } label { display: flex; align-items: flex-end; margin-bottom: var(--secure-ui-form-label-margin-bottom); font-size: var(--secure-ui-label-font-size); font-weight: var(--secure-ui-label-font-weight); color: var(--secure-ui-label-color); } .label-suffix { font-weight: var(--secure-ui-font-weight-normal); color: var(--secure-ui-color-text-secondary); font-size: var(--secure-ui-font-size-xs); margin-left: var(--secure-ui-space-1); } .security-badge { display: inline-block; padding: var(--secure-ui-badge-padding); margin-left: var(--secure-ui-space-2); font-size: var(--secure-ui-badge-font-size); font-weight: var(--secure-ui-font-weight-semibold); border-radius: var(--secure-ui-badge-border-radius); text-transform: uppercase; background-color: var(--secure-ui-color-bg-tertiary); color: var(--secure-ui-color-text-secondary); border: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); } .input-wrapper { position: relative; } .input-field { width: 100%; height: var(--secure-ui-input-height); padding: var(--secure-ui-input-padding-y) var(--secure-ui-input-padding-x); font-family: var(--secure-ui-font-family-base); font-size: var(--secure-ui-input-font-size); line-height: var(--secure-ui-line-height-normal); color: var(--secure-ui-input-text-color); background-color: var(--secure-ui-input-bg); border: var(--secure-ui-input-border-width) solid var(--secure-ui-input-border-color); border-radius: var(--secure-ui-input-border-radius); transition: all var(--secure-ui-transition-base) var(--secure-ui-transition-ease-in-out); box-sizing: border-box; } .input-field::placeholder { color: var(--secure-ui-input-placeholder-color); } .input-field:hover:not(:disabled) { border-color: var(--secure-ui-input-border-color-hover); } .input-field:focus { outline: none; border-color: var(--secure-ui-input-border-color-focus); box-shadow: var(--secure-ui-shadow-focus); } .input-field.error { border-color: var(--secure-ui-color-error) !important; } .input-field.error:focus { box-shadow: var(--secure-ui-shadow-focus-error); } .input-field:disabled { background-color: var(--secure-ui-input-disabled-bg); cursor: not-allowed; opacity: var(--secure-ui-input-disabled-opacity); } .input-field:read-only:not(:disabled) { background-color: var(--secure-ui-color-bg-secondary); cursor: default; } .error-container { position: absolute; margin-top: var(--secure-ui-form-error-margin-top); font-size: var(--secure-ui-error-font-size); color: var(--secure-ui-error-color); line-height: var(--secure-ui-line-height-normal); overflow: hidden; max-height: 40px; opacity: 1; transform: translateY(0); transition: all 0.5s ease-in-out; } .error-container.hidden { max-height: 0; opacity: 0; transform: translateY(-4px); margin-top: 0; transition: all 0.2s ease-in-out; } @media (prefers-reduced-motion: reduce) { .input-field, .error-container, .threat-container { transition: none !important; } } .threat-container { margin-top: var(--secure-ui-form-error-margin-top); font-size: var(--secure-ui-error-font-size); color: var(--secure-ui-color-warning); line-height: var(--secure-ui-line-height-normal); overflow: hidden; max-height: 40px; opacity: 1; transform: translateY(0); transition: all 0.5s ease-in-out; display: flex; align-items: center; gap: var(--secure-ui-space-1, 4px); flex-wrap: wrap; } .threat-container.hidden { max-height: 0; opacity: 0; transform: translateY(-4px); margin-top: 0; transition: all 0.2s ease-in-out; } .threat-message { flex: 1; min-width: 0; } .threat-badge { display: inline-block; padding: var(--secure-ui-badge-padding); font-size: var(--secure-ui-badge-font-size); font-weight: var(--secure-ui-font-weight-semibold); border-radius: var(--secure-ui-badge-border-radius); background-color: color-mix(in srgb, var(--secure-ui-color-warning) 12%, transparent); color: var(--secure-ui-color-warning); border: var(--secure-ui-border-width-thin) solid currentColor; font-family: var(--secure-ui-font-family-mono, monospace); white-space: nowrap; } .threat-tier { display: inline-block; padding: var(--secure-ui-badge-padding); font-size: var(--secure-ui-badge-font-size); font-weight: var(--secure-ui-font-weight-semibold); border-radius: var(--secure-ui-badge-border-radius); background-color: var(--secure-ui-color-bg-tertiary); color: var(--secure-ui-color-text-secondary); border: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); text-transform: uppercase; white-space: nowrap; } .input-field.threat { border-color: var(--secure-ui-color-warning) !important; } .input-field.threat:focus { box-shadow: 0 0 0 3px color-mix(in srgb, var(--secure-ui-color-warning) 25%, transparent); } .input-field:-webkit-autofill { -webkit-box-shadow: 0 0 0 1000px var(--secure-ui-input-bg) inset; -webkit-text-fill-color: var(--secure-ui-input-text-color); }"}handleAttributeChange(e,t,i){if(this.#e)switch(e){case"disabled":this.#e.disabled=this.hasAttribute("disabled");break;case"readonly":this.#e.readOnly=this.hasAttribute("readonly");break;case"value":i!==this.#t&&this.#E(i||"");break}}get value(){return this.#t}set value(e){this.#E(e||"")}get name(){return this.#e?this.#e.name:""}get valid(){let e=this.getAttribute("pattern"),t=this.getAttribute("minlength"),i=this.getAttribute("maxlength"),r=null;if(e)try{r=new RegExp(e)}catch{}if(!this.validateInput(this.#t,{required:this.hasAttribute("required")||this.config.validation.required,pattern:r,minLength:t?parseInt(t,10):0,maxLength:i?parseInt(i,10):this.config.validation.maxLength}).valid||this.#f(this.#t)!==null||this.#y(this.#t)!==null)return!1;if(this.#e&&this.#t){let a;if(this.#a){let n=this.#e.value;this.#e.value=this.#t,a=this.#e.checkValidity(),this.#e.value=n}else a=this.#e.checkValidity();if(!a)return!1}return!0}focus(){this.#e&&this.#e.focus()}blur(){this.#e&&this.#e.blur()}showThreatFeedback(e,t){if(!this.#r||!this.#e)return;this.#r.textContent="";let i=document.createElement("span");i.className="threat-message",i.textContent=this.getThreatLabel(e);let r=document.createElement("span");r.className="threat-badge",r.textContent=e;let s=document.createElement("span");s.className=`threat-tier threat-tier--${t}`,s.textContent=t,this.#r.appendChild(i),this.#r.appendChild(r),this.#r.appendChild(s),this.#r.offsetHeight,this.#r.classList.remove("hidden"),this.#e.classList.add("threat"),this.#e.setAttribute("aria-invalid","true")}clearThreatFeedback(){!this.#r||!this.#e||(this.#r.classList.add("hidden"),this.#r.addEventListener("transitionend",()=>{this.#r.classList.contains("hidden")&&(this.#r.textContent="")},{once:!0}),this.#e.classList.remove("threat"),this.#e.removeAttribute("aria-invalid"))}disconnectedCallback(){super.disconnectedCallback(),this.#t="",this.#e&&(this.#e.value="")}};customElements.define("secure-input",k);var z=class extends p{#e=null;#s=null;#i=null;#r=null;#t=null;#a=`secure-textarea-${Math.random().toString(36).substring(2,11)}`;static get observedAttributes(){return[...super.observedAttributes,"name","label","placeholder","required","minlength","maxlength","rows","cols","wrap","value"]}constructor(){super()}render(){let e=document.createDocumentFragment(),t=document.createElement("div");t.className="textarea-container",t.setAttribute("part","container");let i=this.getAttribute("label");i&&(this.#s=document.createElement("label"),this.#s.htmlFor=this.#a,this.#s.textContent=this.sanitizeValue(i),this.#s.setAttribute("part","label"),t.appendChild(this.#s));let r=document.createElement("div");return r.className="textarea-wrapper",r.setAttribute("part","wrapper"),this.#e=document.createElement("textarea"),this.#e.id=this.#a,this.#e.className="textarea-field",this.#e.setAttribute("part","textarea"),this.#n(),this.#o(),r.appendChild(this.#e),t.appendChild(r),this.#t=document.createElement("span"),this.#t.className="char-count",this.#c(),t.appendChild(this.#t),this.#i=document.createElement("div"),this.#i.className="error-container hidden",this.#i.setAttribute("role","alert"),this.#i.setAttribute("part","error"),this.#i.id=`${this.#a}-error`,t.appendChild(this.#i),this.#r=document.createElement("div"),this.#r.className="threat-container hidden",this.#r.setAttribute("role","alert"),this.#r.setAttribute("part","threat"),this.#r.id=`${this.#a}-threat`,t.appendChild(this.#r),this.addComponentStyles(this.#p()),e.appendChild(t),e}#n(){let e=this.config,t=this.getAttribute("name");t&&(this.#e.name=this.sanitizeValue(t)),!this.getAttribute("label")&&t&&this.#e.setAttribute("aria-label",this.sanitizeValue(t)),this.#e.setAttribute("aria-describedby",`${this.#a}-error`);let i=this.getAttribute("placeholder");i&&(this.#e.placeholder=this.sanitizeValue(i)),(this.hasAttribute("required")||e.validation.required)&&(this.#e.required=!0,this.#e.setAttribute("aria-required","true"));let r=this.getAttribute("minlength");r&&(this.#e.minLength=parseInt(r,10));let s=this.getAttribute("maxlength")||e.validation.maxLength;s&&(this.#e.maxLength=parseInt(String(s),10));let a=this.getAttribute("rows")||3;this.#e.rows=parseInt(String(a),10);let n=this.getAttribute("cols");n&&(this.#e.cols=parseInt(n,10));let o=this.getAttribute("wrap")||"soft";if(this.#e.wrap=o,e.storage.allowAutocomplete){let d=this.getAttribute("autocomplete")||"on";this.#e.autocomplete=d}else this.#e.autocomplete="off";this.hasAttribute("disabled")&&(this.#e.disabled=!0),this.hasAttribute("readonly")&&(this.#e.readOnly=!0);let u=this.getAttribute("value");u&&(this.#e.value=u)}#o(){this.#e.addEventListener("focus",()=>{this.recordTelemetryFocus(),this.audit("textarea_focused",{name:this.#e.name})}),this.#e.addEventListener("input",e=>{this.recordTelemetryInput(e),this.#u(e)}),this.#e.addEventListener("blur",()=>{this.recordTelemetryBlur(),this.#h(),this.audit("textarea_blurred",{name:this.#e.name,hasValue:this.#e.value.length>0})}),this.#e.addEventListener("change",()=>{this.audit("textarea_changed",{name:this.#e.name,valueLength:this.#e.value.length})})}#u(e){this.detectInjection(this.#e.value,this.#e.name),this.#c(),this.#l(),this.dispatchEvent(new CustomEvent("secure-textarea",{detail:{name:this.#e.name,value:this.#e.value,tier:this.securityTier},bubbles:!0,composed:!0}))}#c(){let e=this.#e.value.length,t=this.#e.maxLength;t>0?(this.#t.textContent=`${e} / ${t}`,e>t*.9?this.#t.classList.add("warning"):this.#t.classList.remove("warning")):this.#t.textContent=`${e}`}#h(){let e=this.checkRateLimit();if(!e.allowed){this.#d(`Too many attempts. Please wait ${Math.ceil(e.retryAfter/1e3)} seconds.`);return}let t=this.getAttribute("minlength"),i=this.getAttribute("maxlength"),r=this.validateInput(this.#e.value,{required:this.hasAttribute("required")||this.config.validation.required,minLength:t?parseInt(t,10):0,maxLength:i?parseInt(i,10):this.config.validation.maxLength});r.valid||this.#d(r.errors.join(", "))}#d(e){this.#i.textContent=e,this.#i.offsetHeight,this.#i.classList.remove("hidden"),this.#e.classList.add("error"),this.#e.setAttribute("aria-invalid","true")}#l(){this.#i.classList.add("hidden"),this.#i.addEventListener("transitionend",()=>{this.#i.classList.contains("hidden")&&(this.#i.textContent="")},{once:!0}),this.#e.classList.remove("error"),this.#e.removeAttribute("aria-invalid")}#p(){return'.textarea-container { margin-bottom: var(--secure-ui-form-gap); font-family: var(--secure-ui-font-family-base); } label { display: block; margin-bottom: var(--secure-ui-form-label-margin-bottom); font-size: var(--secure-ui-label-font-size); font-weight: var(--secure-ui-label-font-weight); color: var(--secure-ui-label-color); } .label-suffix { font-weight: var(--secure-ui-font-weight-normal); color: var(--secure-ui-color-text-secondary); font-size: var(--secure-ui-font-size-xs); margin-left: var(--secure-ui-space-1); } .security-badge { display: inline-block; padding: var(--secure-ui-badge-padding); margin-left: var(--secure-ui-space-2); font-size: var(--secure-ui-badge-font-size); font-weight: var(--secure-ui-font-weight-semibold); border-radius: var(--secure-ui-badge-border-radius); text-transform: uppercase; background-color: var(--secure-ui-color-bg-tertiary); color: var(--secure-ui-color-text-secondary); border: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); } .textarea-wrapper { position: relative; } .textarea-field { width: 100%; min-height: var(--secure-ui-textarea-min-height); padding: var(--secure-ui-textarea-padding); font-family: var(--secure-ui-font-family-base); font-size: var(--secure-ui-input-font-size); line-height: var(--secure-ui-line-height-normal); color: var(--secure-ui-input-text-color); background-color: var(--secure-ui-input-bg); border: var(--secure-ui-input-border-width) solid var(--secure-ui-input-border-color); border-radius: var(--secure-ui-input-border-radius); transition: all var(--secure-ui-transition-base) var(--secure-ui-transition-ease-in-out); resize: vertical; box-sizing: border-box; } .textarea-field::placeholder { color: var(--secure-ui-input-placeholder-color); } .textarea-field:hover:not(:disabled) { border-color: var(--secure-ui-input-border-color-hover); } .textarea-field:focus { outline: none; border-color: var(--secure-ui-input-border-color-focus); box-shadow: var(--secure-ui-shadow-focus); } .textarea-field.error { border-color: var(--secure-ui-color-error); } .textarea-field.error:focus { box-shadow: var(--secure-ui-shadow-focus-error); } .textarea-field:read-only:not(:disabled) { background-color: var(--secure-ui-color-bg-secondary); cursor: default; resize: none; } .textarea-field:disabled { background-color: var(--secure-ui-input-disabled-bg); cursor: not-allowed; opacity: var(--secure-ui-input-disabled-opacity); } .char-count { display: block; margin-top: var(--secure-ui-space-1); font-size: var(--secure-ui-font-size-xs); color: var(--secure-ui-color-text-secondary); text-align: right; } .char-count.warning { color: var(--secure-ui-color-warning); font-weight: var(--secure-ui-font-weight-medium); } .error-container { margin-top: var(--secure-ui-form-error-margin-top); font-size: var(--secure-ui-error-font-size); color: var(--secure-ui-error-color); line-height: var(--secure-ui-line-height-normal); overflow: hidden; max-height: 40px; opacity: 1; transform: translateY(0); transition: opacity 0.2s ease-out, transform 0.2s ease-out, max-height 0.2s ease-out, margin-top 0.2s ease-out; } .error-container.hidden { max-height: 0; opacity: 0; transform: translateY(-4px); margin-top: 0; } @media (prefers-reduced-motion: reduce) { .textarea-field, .error-container, .threat-container { transition: none !important; } } .threat-container { margin-top: var(--secure-ui-form-error-margin-top); font-size: var(--secure-ui-error-font-size); color: var(--secure-ui-color-warning); line-height: var(--secure-ui-line-height-normal); overflow: hidden; max-height: 40px; opacity: 1; transform: translateY(0); transition: opacity 0.2s ease-out, transform 0.2s ease-out, max-height 0.2s ease-out, margin-top 0.2s ease-out; display: flex; align-items: center; gap: var(--secure-ui-space-1, 4px); flex-wrap: wrap; } .threat-container.hidden { max-height: 0; opacity: 0; transform: translateY(-4px); margin-top: 0; } .threat-message { flex: 1; min-width: 0; } .threat-badge { display: inline-block; padding: var(--secure-ui-badge-padding); font-size: var(--secure-ui-badge-font-size); font-weight: var(--secure-ui-font-weight-semibold); border-radius: var(--secure-ui-badge-border-radius); background-color: color-mix(in srgb, var(--secure-ui-color-warning) 12%, transparent); color: var(--secure-ui-color-warning); border: var(--secure-ui-border-width-thin) solid currentColor; font-family: var(--secure-ui-font-family-mono, monospace); white-space: nowrap; } .threat-tier { display: inline-block; padding: var(--secure-ui-badge-padding); font-size: var(--secure-ui-badge-font-size); font-weight: var(--secure-ui-font-weight-semibold); border-radius: var(--secure-ui-badge-border-radius); background-color: var(--secure-ui-color-bg-tertiary); color: var(--secure-ui-color-text-secondary); border: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); text-transform: uppercase; white-space: nowrap; } .textarea-field.threat { border-color: var(--secure-ui-color-warning) !important; } .textarea-field.threat:focus { box-shadow: 0 0 0 3px color-mix(in srgb, var(--secure-ui-color-warning) 25%, transparent); } :host([security-tier="authenticated"]) .textarea-field { border-color: var(--secure-ui-tier-authenticated); } :host([security-tier="sensitive"]) .textarea-field { border-color: var(--secure-ui-tier-sensitive); } :host([security-tier="critical"]) .textarea-field { border-color: var(--secure-ui-tier-critical); }'}handleAttributeChange(e,t,i){if(this.#e)switch(e){case"disabled":this.#e.disabled=this.hasAttribute("disabled");break;case"readonly":this.#e.readOnly=this.hasAttribute("readonly");break;case"value":i!==this.#e.value&&(this.#e.value=i||"",this.#c());break}}get value(){return this.#e?this.#e.value:""}set value(e){this.#e&&(this.#e.value=e||"",this.#c())}get name(){return this.#e?this.#e.name:""}get valid(){let e=this.getAttribute("minlength"),t=this.getAttribute("maxlength");return this.validateInput(this.#e.value,{required:this.hasAttribute("required")||this.config.validation.required,minLength:e?parseInt(e,10):0,maxLength:t?parseInt(t,10):this.config.validation.maxLength}).valid}focus(){this.#e&&this.#e.focus()}blur(){this.#e&&this.#e.blur()}showThreatFeedback(e,t){if(!this.#r||!this.#e)return;this.#r.textContent="";let i=document.createElement("span");i.className="threat-message",i.textContent=this.getThreatLabel(e);let r=document.createElement("span");r.className="threat-badge",r.textContent=e;let s=document.createElement("span");s.className=`threat-tier threat-tier--${t}`,s.textContent=t,this.#r.appendChild(i),this.#r.appendChild(r),this.#r.appendChild(s),this.#r.offsetHeight,this.#r.classList.remove("hidden"),this.#e.classList.add("threat"),this.#e.setAttribute("aria-invalid","true")}clearThreatFeedback(){!this.#r||!this.#e||(this.#r.classList.add("hidden"),this.#r.addEventListener("transitionend",()=>{this.#r.classList.contains("hidden")&&(this.#r.textContent="")},{once:!0}),this.#e.classList.remove("threat"),this.#e.removeAttribute("aria-invalid"))}disconnectedCallback(){super.disconnectedCallback(),this.#e&&(this.#e.value="")}};customElements.define("secure-textarea",z);var I=class extends p{#e=null;#s=null;#i=null;#r=`secure-select-${Math.random().toString(36).substring(2,11)}`;#t=new Set;#a=!1;#n=!1;static get observedAttributes(){return[...super.observedAttributes,"name","label","required","multiple","size","value"]}constructor(){super()}render(){let e=document.createDocumentFragment(),t=document.createElement("div");t.className="select-container",t.setAttribute("part","container"),this.#n=this.hasAttribute("multiple");let i=this.getAttribute("label");i&&(this.#s=document.createElement("label"),this.#s.htmlFor=this.#r,this.#s.textContent=this.sanitizeValue(i),this.#s.setAttribute("part","label"),t.appendChild(this.#s));let r=document.createElement("div");return r.className="select-wrapper",r.setAttribute("part","wrapper"),this.#e=document.createElement("select"),this.#e.id=this.#r,this.#e.className="select-field",this.#e.setAttribute("part","select"),this.#o(),this.#c(),queueMicrotask(()=>{this.#u()}),r.appendChild(this.#e),t.appendChild(r),this.#i=document.createElement("div"),this.#i.className="error-container hidden",this.#i.setAttribute("role","alert"),this.#i.setAttribute("part","error"),this.#i.id=`${this.#r}-error`,t.appendChild(this.#i),this.addComponentStyles(this.#b()),e.appendChild(t),e}#o(){let e=this.config,t=this.getAttribute("name");t&&(this.#e.name=this.sanitizeValue(t)),!this.getAttribute("label")&&t&&this.#e.setAttribute("aria-label",this.sanitizeValue(t)),this.#e.setAttribute("aria-describedby",`${this.#r}-error`),(this.hasAttribute("required")||e.validation.required)&&(this.#e.required=!0,this.#e.setAttribute("aria-required","true")),this.hasAttribute("multiple")&&(this.#e.multiple=!0);let i=this.getAttribute("size");i&&(this.#e.size=parseInt(i,10)),this.hasAttribute("disabled")&&(this.#e.disabled=!0),e.storage.allowAutocomplete||(this.#e.autocomplete="off")}#u(){if(this.#a)return;this.#a=!0;let e=Array.from(this.querySelectorAll("option"));if(e.length===0)return;let t=[];if(e.forEach(i=>{let r=document.createElement("option"),s=i.getAttribute("value")||"";r.value=this.sanitizeValue(s),this.#t.add(r.value),r.textContent=this.sanitizeValue(i.textContent||""),i.hasAttribute("selected")&&(r.selected=!0,t.push(r.value)),i.hasAttribute("disabled")&&(r.disabled=!0),this.#e.appendChild(r)}),!this.#n){let i=this.getAttribute("value");i?this.#e.value=i:t.length>0&&(this.#e.value=t[0])}}#c(){this.#e.addEventListener("focus",()=>{this.recordTelemetryFocus(),this.audit("select_focused",{name:this.#e.name})}),this.#e.addEventListener("change",e=>{this.recordTelemetryInput(e),this.#h(e)}),this.#e.addEventListener("blur",()=>{this.recordTelemetryBlur(),this.#d(),this.audit("select_blurred",{name:this.#e.name,hasValue:this.#n?this.#e.selectedOptions.length>0:this.#e.value.length>0})})}#h(e){if(this.#n){let t=Array.from(this.#e.selectedOptions).map(r=>r.value),i=t.filter(r=>r&&!this.#t.has(r));if(i.length>0){this.#l("Invalid option selected"),this.audit("invalid_option_detected",{name:this.#e.name,attemptedValues:i});return}this.#p(),this.audit("select_changed",{name:this.#e.name,values:t}),this.dispatchEvent(new CustomEvent("secure-select",{detail:{name:this.#e.name,value:t,tier:this.securityTier},bubbles:!0,composed:!0}))}else{let t=this.#e.value;if(t&&!this.#t.has(t)){this.#l("Invalid option selected"),this.audit("invalid_option_detected",{name:this.#e.name,attemptedValue:t}),this.#e.value="";return}this.#p(),this.audit("select_changed",{name:this.#e.name,value:t}),this.dispatchEvent(new CustomEvent("secure-select",{detail:{name:this.#e.name,value:t,tier:this.securityTier},bubbles:!0,composed:!0}))}}#d(){let e=this.checkRateLimit();if(!e.allowed){this.#l(`Too many attempts. Please wait ${Math.ceil(e.retryAfter/1e3)} seconds.`);return}let t=this.hasAttribute("required")||this.config.validation.required;if(this.#n){let i=Array.from(this.#e.selectedOptions).map(s=>s.value).filter(s=>s!=="");if(t&&i.length===0){this.#l("Please select at least one option");return}if(i.filter(s=>!this.#t.has(s)).length>0){this.#l("Invalid option selected");return}}else{if(t&&!this.#e.value){this.#l("Please select an option");return}let i=this.#e.value;if(i&&!this.#t.has(i)){this.#l("Invalid option selected");return}}}#l(e){this.#i.textContent=e,this.#i.offsetHeight,this.#i.classList.remove("hidden"),this.#e.classList.add("error"),this.#e.setAttribute("aria-invalid","true")}#p(){this.#i.classList.add("hidden"),this.#i.addEventListener("transitionend",()=>{this.#i.classList.contains("hidden")&&(this.#i.textContent="")},{once:!0}),this.#e.classList.remove("error"),this.#e.removeAttribute("aria-invalid")}#b(){return'.select-container { margin-bottom: var(--secure-ui-form-gap); font-family: var(--secure-ui-font-family-base); } label { display: block; margin-bottom: var(--secure-ui-form-label-margin-bottom); font-size: var(--secure-ui-label-font-size); font-weight: var(--secure-ui-label-font-weight); color: var(--secure-ui-label-color); } .label-suffix { font-weight: var(--secure-ui-font-weight-normal); color: var(--secure-ui-color-text-secondary); font-size: var(--secure-ui-font-size-xs); margin-left: var(--secure-ui-space-1); } .security-badge { display: inline-block; padding: var(--secure-ui-badge-padding); margin-left: var(--secure-ui-space-2); font-size: var(--secure-ui-badge-font-size); font-weight: var(--secure-ui-font-weight-semibold); border-radius: var(--secure-ui-badge-border-radius); text-transform: uppercase; background-color: var(--secure-ui-color-bg-tertiary); color: var(--secure-ui-color-text-secondary); border: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); } .select-wrapper { position: relative; } .select-field { width: 100%; height: var(--secure-ui-select-height); padding: var(--secure-ui-select-padding); font-family: var(--secure-ui-font-family-base); font-size: var(--secure-ui-input-font-size); line-height: var(--secure-ui-line-height-normal); color: var(--secure-ui-select-color); background-color: var(--secure-ui-select-background-color); border: var(--secure-ui-input-border-width) solid var(--secure-ui-input-border-color); border-radius: var(--secure-ui-input-border-radius); transition: all var(--secure-ui-transition-base) var(--secure-ui-transition-ease-in-out); cursor: pointer; box-sizing: border-box; } .select-field, ::picker(select) { appearance: base-select; border-radius: .25rem; } .select-field::picker-icon { color: #999999; transition: 0.2s rotate; } .select-field:open::picker-icon { rotate: 180deg; } .select-field option { display: flex; justify-content: flex-start; color: var(--secure-ui-select-color); background-color: var(--secure-ui-select-background-color); padding: .5rem; } .select-field option:hover { box-shadow: 0px 0px 4px 0px var(--secure-ui-input-border-color) inset; transition: all 0.2s ease-in-out; } .select-field option:first-of-type { border-top-left-radius: none; border-top-right-radius: none; } .select-field option:last-of-type { border-bottom-left-radius: none; border-bottom-right-radius: none; } .select-field option:nth-of-type(odd) { } .select-field option:checked { font-weight: bold; } .select-field option::checkmark { order: 1; margin-left: auto; content: "\u2713"; } .select-field option + option { border-top: 1px solid var(--secure-ui-input-border-color); } .select-field:hover:not(:disabled) { border-color: var(--secure-ui-input-border-color-hover); } .select-field:focus { outline: none; border-color: var(--secure-ui-input-border-color-focus); box-shadow: var(--secure-ui-shadow-focus); } .select-field.error { border-color: var(--secure-ui-color-error); } .select-field.error:focus { box-shadow: var(--secure-ui-shadow-focus-error); } .select-field:disabled { background-color: var(--secure-ui-input-disabled-bg); cursor: not-allowed; opacity: var(--secure-ui-input-disabled-opacity); } .select-field[multiple] { height: auto; min-height: calc(var(--secure-ui-select-height) * 2); padding: var(--secure-ui-space-2); } .error-container { position: absolute; margin-top: var(--secure-ui-form-error-margin-top); font-size: var(--secure-ui-error-font-size); color: var(--secure-ui-error-color); line-height: var(--secure-ui-line-height-normal); overflow: hidden; max-height: 40px; opacity: 1; transform: translateY(0); transition: opacity 0.2s ease-out, transform 0.2s ease-out, max-height 0.2s ease-out, margin-top 0.2s ease-out; } .error-container.hidden { max-height: 0; opacity: 0; transform: translateY(-4px); margin-top: 0; } @media (prefers-reduced-motion: reduce) { .select-field, .error-container { transition: none !important; } }'}handleAttributeChange(e,t,i){if(this.#e)switch(e){case"disabled":this.#e.disabled=this.hasAttribute("disabled");break;case"value":i!==this.#e.value&&(this.#e.value=i||"");break}}get value(){return this.#e?this.#n?Array.from(this.#e.selectedOptions).map(e=>e.value).filter(e=>e!=="").join(", "):this.#e.value:""}set value(e){if(this.#e)if(this.#n){let t=e.split(",").map(i=>i.trim()).filter(i=>i!=="");Array.from(this.#e.options).forEach(i=>{i.selected=!1}),t.forEach(i=>{if(this.#t.has(i)){let r=Array.from(this.#e.options).find(s=>s.value===i);r&&(r.selected=!0)}})}else this.#t.has(e)&&(this.#e.value=e)}get name(){return this.#e?this.#e.name:""}get selectedOptions(){return this.#e?Array.from(this.#e.selectedOptions).map(e=>e.value):[]}get valid(){let e=this.hasAttribute("required")||this.config.validation.required;if(this.#n){let i=Array.from(this.#e.selectedOptions).map(r=>r.value).filter(r=>r!=="");return e&&i.length===0?!1:i.every(r=>this.#t.has(r))}if(e&&!this.#e.value)return!1;let t=this.#e.value;return!(t&&!this.#t.has(t))}focus(){this.#e&&this.#e.focus()}blur(){this.#e&&this.#e.blur()}addOption(e,t,i=!1){if(!this.#e)return;let r=document.createElement("option");r.value=this.sanitizeValue(e),r.textContent=this.sanitizeValue(t),r.selected=i,this.#t.add(r.value),this.#e.appendChild(r)}removeOption(e){if(!this.#e)return;let i=Array.from(this.#e.options).find(r=>r.value===e);i&&(this.#e.removeChild(i),this.#t.delete(e))}clearOptions(){this.#e&&(this.#e.innerHTML="",this.#t.clear())}disconnectedCallback(){super.disconnectedCallback()}};customElements.define("secure-select",I);var M=class l extends HTMLElement{static __stylesAdded=!1;#e=null;#s=null;#i=null;#r=!1;#t=Date.now();#a=`secure-form-${Math.random().toString(36).substring(2,11)}`;#n=c.PUBLIC;static get observedAttributes(){return["security-tier","action","method","enctype","csrf-token","csrf-header-name","csrf-field-name","novalidate"]}constructor(){super()}connectedCallback(){if(this.#e)return;this.#t=Date.now();let e=this.getAttribute("security-tier");e&&(this.#n=e);let t=this.querySelector("form");if(t){this.#e=t,this.#e.id=this.#a,this.#e.classList.contains("secure-form")||this.#e.classList.add("secure-form"),this.#u();let i=this.getAttribute("csrf-field-name")||"csrf_token",r=t.querySelector(`input[name="${i}"]`);if(r){this.#s=r;let s=this.getAttribute("csrf-token");s&&r.value!==s&&(r.value=s)}else this.#c()}else{for(this.#e=document.createElement("form"),this.#e.id=this.#a,this.#e.className="secure-form",this.#u(),this.#c();this.firstChild;)this.#e.appendChild(this.firstChild);this.appendChild(this.#e)}this.#i=document.createElement("div"),this.#i.className="form-status form-status-hidden",this.#i.setAttribute("role","status"),this.#i.setAttribute("aria-live","polite"),this.#e.insertBefore(this.#i,this.#e.firstChild),this.#o(),this.#h(),this.audit("form_initialized",{formId:this.#a,action:this.#e.action,method:this.#e.method})}#o(){if(!l.__stylesAdded){let e='secure-form { display: block; } secure-form .secure-form { padding: 16px; border: 2px solid #e0e0e0; border-radius: 8px; background-color: transparent; } secure-form[security-tier="critical"] .secure-form { padding: 20px; } secure-form[security-tier="public"] .secure-form { border: none; } secure-form .form-status { padding: 12px; margin-bottom: 16px; border-radius: 4px; font-size: 14px; } secure-form .form-status-hidden { display: none; } secure-form .form-status-info { display: block; background-color: #E3F2FD; color: #1976D2; border: 1px solid #1976D2; } secure-form .form-status-success { display: block; background-color: #E8F5E9; color: #388E3C; border: 1px solid #388E3C; } secure-form .form-status-error { display: block; background-color: #FFEBEE; color: #D32F2F; border: 1px solid #D32F2F; }';if(e.includes("{")){let t=new CSSStyleSheet;t.replaceSync(e),document.adoptedStyleSheets=[...document.adoptedStyleSheets,t]}else{let t=document.createElement("link");t.rel="stylesheet",t.href=e,document.head.appendChild(t)}l.__stylesAdded=!0}}#u(){let e=this.getAttribute("action");e&&(this.#e.action=e);let t=this.getAttribute("method")||"POST";this.#e.method=t.toUpperCase();let i=this.getAttribute("enctype")||"application/x-www-form-urlencoded";this.#e.enctype=i,this.hasAttribute("novalidate")&&(this.#e.noValidate=!0),(this.#n===c.SENSITIVE||this.#n===c.CRITICAL)&&(this.#e.autocomplete="off")}#c(){let e=this.getAttribute("csrf-token");if(e){this.#s=document.createElement("input"),this.#s.type="hidden";let t=this.getAttribute("csrf-field-name")||"csrf_token";this.#s.name=t,this.#s.value=e,this.#e.appendChild(this.#s),this.audit("csrf_token_injected",{formId:this.#a,fieldName:t})}else(this.securityTier===c.SENSITIVE||this.securityTier===c.CRITICAL)&&console.warn("CSRF token not provided for SENSITIVE/CRITICAL tier form")}#h(){this.#e.addEventListener("submit",e=>{this.#l(e)}),this.addEventListener("secure-input",e=>{this.#d(e)}),this.addEventListener("secure-textarea",e=>{this.#d(e)}),this.addEventListener("secure-select",e=>{this.#d(e)})}#d(e){this.#E()}async#l(e){let t=this.hasAttribute("enhance");if(this.#r){e.preventDefault();return}(this.#n===c.SENSITIVE||this.#n===c.CRITICAL)&&!this.#s?.value&&this.dispatchEvent(new CustomEvent("secure-threat-detected",{detail:{fieldName:this.#a,threatType:"csrf-token-absent",patternId:"csrf-token-absent",tier:this.#n,timestamp:Date.now()},bubbles:!0,composed:!0}));let i=this.checkRateLimit();if(!i.allowed){e.preventDefault(),this.#v(`Too many submission attempts. Please wait ${Math.ceil(i.retryAfter/1e3)} seconds.`,"error"),this.audit("form_rate_limited",{formId:this.#a,retryAfter:i.retryAfter});return}let r=this.#b();if(!r.valid){e.preventDefault(),this.#v(r.errors.join(", "),"error"),this.audit("form_validation_failed",{formId:this.#a,errors:r.errors});return}if(!t){this.#p(),this.audit("form_submitted_native",{formId:this.#a,action:this.#e.action,method:this.#e.method});return}e.preventDefault(),this.#r=!0,this.#v("Submitting...","info"),this.#m();let s=this.#f(),a=this.#x();this.audit("form_submitted_enhanced",{formId:this.#a,action:this.#e.action,method:this.#e.method,fieldCount:Object.keys(s).length,riskScore:a.riskScore,riskSignals:a.riskSignals});let n=new CustomEvent("secure-form-submit",{detail:{formData:s,formElement:this.#e,telemetry:a,preventDefault:()=>{this.#r=!1,this.#g()}},bubbles:!0,composed:!0,cancelable:!0});if(!this.dispatchEvent(n)){this.#r=!1,this.#g();return}try{await this.#y(s,a)}catch(u){this.#v("Submission failed. Please try again.","error"),this.audit("form_submission_error",{formId:this.#a,error:u.message})}finally{this.#r=!1,this.#g()}}#p(){this.#e.querySelectorAll("secure-input, secure-textarea, secure-select, secure-datetime, secure-file-upload").forEach(t=>{let i=t.getAttribute("name");if(!i)return;t.querySelectorAll(`input[name="${i}"], textarea[name="${i}"], select[name="${i}"]`).forEach(a=>{a.removeAttribute("name")});let s=this.#e.querySelector(`input[type="hidden"][data-secure-input="${i}"]`);s||(s=document.createElement("input"),s.type="hidden",s.setAttribute("data-secure-input",i),s.name=i,this.#e.appendChild(s)),s.value=t.value||""})}#b(){let e=[];return this.#e.querySelectorAll("secure-input, secure-textarea, secure-select, secure-datetime, secure-file-upload").forEach(i=>{if(typeof i.valid=="boolean"&&!i.valid){let r=i.getAttribute("label")||i.getAttribute("name")||"Field";e.push(`${r} is invalid`)}}),{valid:e.length===0,errors:e}}#f(){let e=Object.create(null);return this.#e.querySelectorAll("secure-input, secure-textarea, secure-select, secure-datetime, secure-file-upload").forEach(r=>{let s=r;s.name&&(e[s.name]=s.value)}),this.#e.querySelectorAll('input:not([type="hidden"]), textarea:not(.textarea-field), select:not(.select-field)').forEach(r=>{let s=r;s.name&&(e[s.name]=this.sanitizeValue(s.value))}),this.#s&&(e[this.#s.name]=this.#s.value),e}async#y(e,t){let i=this.#e.action,r=this.#e.method,s={"Content-Type":"application/json"},a=this.getAttribute("csrf-header-name");a&&this.#s&&(s[a]=this.#s.value);let n={...e,_telemetry:t},o=await fetch(i,{method:r,headers:s,body:JSON.stringify(n),credentials:"same-origin",mode:"cors",cache:"no-cache",redirect:"follow"});if(!o.ok)throw new Error(`HTTP ${o.status}: ${o.statusText}`);return this.#v("Form submitted successfully!","success"),this.dispatchEvent(new CustomEvent("secure-form-success",{detail:{formData:e,response:o,telemetry:t},bubbles:!0,composed:!0})),o}#m(){this.#e.querySelectorAll("input, textarea, select, button").forEach(i=>{i.disabled=!0}),this.querySelectorAll("secure-input, secure-textarea, secure-select, secure-datetime, secure-file-upload").forEach(i=>{i.setAttribute("disabled","")})}#g(){this.#e.querySelectorAll("input, textarea, select, button").forEach(i=>{i.disabled=!1}),this.querySelectorAll("secure-input, secure-textarea, secure-select, secure-datetime, secure-file-upload").forEach(i=>{i.removeAttribute("disabled")})}#v(e,t="info"){this.#i.textContent=e,this.#i.className=`form-status form-status-${t}`}#E(){this.#i.textContent="",this.#i.className="form-status form-status-hidden"}#x(){let t=this.querySelectorAll("secure-input, secure-textarea, secure-select, secure-datetime, secure-card"),i=[];t.forEach(n=>{let o=n;if(typeof o.getFieldTelemetry!="function")return;let u=n.getAttribute("name")??n.tagName.toLowerCase(),d={...o.getFieldTelemetry(),fieldName:u,fieldType:n.tagName.toLowerCase()};i.push(d)});let r=Date.now()-this.#t,{riskScore:s,riskSignals:a}=this.#w(i,r);return{sessionDuration:r,fieldCount:i.length,fields:i,riskScore:s,riskSignals:a,submittedAt:new Date().toISOString()}}#w(e,t){let i=[],r=0;if(t<3e3?(r+=30,i.push("session_too_fast")):t<8e3&&(r+=10,i.push("session_fast")),e.length===0)return{riskScore:Math.min(r,100),riskSignals:i};e.every(h=>h.pasteDetected&&h.velocity===0)&&(r+=25,i.push("all_fields_pasted")),e.some(h=>h.velocity>15)&&(r+=15,i.push("high_velocity_typing")),e.some(h=>h.focusCount===0)&&(r+=15,i.push("field_filled_without_focus")),e.some(h=>h.focusCount>1&&h.blurWithoutChange>1)&&(r+=10,i.push("form_probing")),e.some(h=>h.corrections>5)&&(r+=5,i.push("high_correction_count"));let d=e.filter(h=>h.autofillDetected);return d.length>0&&d.length===e.length&&(r-=10,i.push("autofill_detected")),{riskScore:Math.max(0,Math.min(r,100)),riskSignals:i}}getData(){return this.#f()}reset(){this.#e&&(this.#e.reset(),this.#E(),this.audit("form_reset",{formId:this.#a}))}submit(){this.#e&&this.#e.dispatchEvent(new Event("submit",{bubbles:!0,cancelable:!0}))}get valid(){return this.#b().valid}disconnectedCallback(){this.#e&&this.#e.reset()}attributeChangedCallback(e,t,i){if(this.#e)switch(e){case"security-tier":this.#n=i||c.PUBLIC;break;case"action":this.#e.action=i;break;case"method":this.#e.method=i;break;case"csrf-token":this.#s&&(this.#s.value=i);break}}get securityTier(){return this.#n}sanitizeValue(e){if(typeof e!="string")return"";let t=document.createElement("div");return t.textContent=e,t.innerHTML}audit(e,t){console.debug&&console.debug(`[secure-form] ${e}`,t)}checkRateLimit(){return{allowed:!0,retryAfter:0}}};customElements.define("secure-form",M);var D=class extends p{#e=null;#s=null;#i=null;#r=null;#t=null;#a=null;#n=null;#o=`secure-file-upload-${Math.random().toString(36).substring(2,11)}`;#u=new Set;#c=5*1024*1024;#h=null;#d=!1;static get observedAttributes(){return[...super.observedAttributes,"name","label","accept","max-size","multiple","required","capture"]}constructor(){super()}render(){let e=document.createDocumentFragment(),t=document.createElement("div");t.className="file-upload-container",t.setAttribute("part","container");let i=this.getAttribute("label");i&&(this.#s=document.createElement("label"),this.#s.htmlFor=this.#o,this.#s.textContent=this.sanitizeValue(i),this.#s.setAttribute("part","label"),t.appendChild(this.#s)),this.#t=document.createElement("div"),this.#t.className="drop-zone",this.#t.setAttribute("part","wrapper"),this.#e=document.createElement("input"),this.#e.type="file",this.#e.id=this.#o,this.#e.className="file-input",this.#e.setAttribute("part","input"),this.#l(),this.#g();let r=document.createElement("div");r.className="drop-zone-content has-name";let s=document.createElement("span");s.className="file-cta";let a=document.createElement("span");a.className="drop-icon";let n=document.createElementNS("http://www.w3.org/2000/svg","svg");n.setAttribute("width","16"),n.setAttribute("height","16"),n.setAttribute("viewBox","0 0 24 24"),n.setAttribute("fill","none"),n.setAttribute("stroke","currentColor"),n.setAttribute("stroke-width","2"),n.setAttribute("stroke-linecap","round"),n.setAttribute("stroke-linejoin","round"),n.setAttribute("aria-hidden","true"),n.setAttribute("focusable","false");let o=document.createElementNS("http://www.w3.org/2000/svg","path");o.setAttribute("d","M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4");let u=document.createElementNS("http://www.w3.org/2000/svg","polyline");u.setAttribute("points","17 8 12 3 7 8");let d=document.createElementNS("http://www.w3.org/2000/svg","line");d.setAttribute("x1","12"),d.setAttribute("y1","3"),d.setAttribute("x2","12"),d.setAttribute("y2","15"),n.appendChild(o),n.appendChild(u),n.appendChild(d),a.appendChild(n),s.appendChild(a);let h=document.createElement("span");h.className="drop-text",h.textContent="Choose a file\u2026",s.appendChild(h),r.appendChild(s),this.#a=document.createElement("span"),this.#a.className="file-name-display",this.#a.textContent="No file selected",r.appendChild(this.#a),this.#t.appendChild(this.#e),this.#t.appendChild(r),t.appendChild(this.#t);let f=document.createElement("div");return f.className="drop-hint",f.textContent=this.#m(),t.appendChild(f),this.#r=document.createElement("div"),this.#r.className="preview-container",t.appendChild(this.#r),this.#i=document.createElement("div"),this.#i.className="error-container hidden",this.#i.setAttribute("role","alert"),this.#i.setAttribute("part","error"),this.#i.id=`${this.#o}-error`,t.appendChild(this.#i),this.#e.setAttribute("aria-describedby",`${this.#o}-error`),this.addComponentStyles(this.#V()),e.appendChild(t),e}#l(){let e=this.config,t=this.getAttribute("name");t&&(this.#e.name=this.sanitizeValue(t));let i=this.getAttribute("accept");if(i)this.#e.accept=i,this.#p(i);else{let a=this.#f();this.#e.accept=a,this.#p(a)}let r=this.getAttribute("max-size");r?this.#c=parseInt(r,10):this.#c=this.#y(),this.hasAttribute("multiple")&&(this.#e.multiple=!0),(this.hasAttribute("required")||e.validation.required)&&(this.#e.required=!0);let s=this.getAttribute("capture");s&&(this.#e.capture=s),this.hasAttribute("disabled")&&(this.#e.disabled=!0)}#p(e){this.#u.clear(),e.split(",").map(i=>i.trim()).forEach(i=>{if(i.startsWith(".")){let r=this.#b(i);r&&this.#u.add(r)}else this.#u.add(i)})}#b(e){return{".pdf":"application/pdf",".doc":"application/msword",".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document",".xls":"application/vnd.ms-excel",".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",".ppt":"application/vnd.ms-powerpoint",".pptx":"application/vnd.openxmlformats-officedocument.presentationml.presentation",".txt":"text/plain",".csv":"text/csv",".jpg":"image/jpeg",".jpeg":"image/jpeg",".png":"image/png",".gif":"image/gif",".svg":"image/svg+xml",".zip":"application/zip",".json":"application/json"}[e.toLowerCase()]||null}#f(){switch(this.securityTier){case c.CRITICAL:return".pdf,.txt";case c.SENSITIVE:return".pdf,.doc,.docx,.txt,.jpg,.jpeg,.png";case c.AUTHENTICATED:return".pdf,.doc,.docx,.xls,.xlsx,.txt,.csv,.jpg,.jpeg,.png,.gif";case c.PUBLIC:default:return".pdf,.doc,.docx,.xls,.xlsx,.txt,.csv,.jpg,.jpeg,.png,.gif,.zip"}}#y(){switch(this.securityTier){case c.CRITICAL:return 2*1024*1024;case c.SENSITIVE:return 5*1024*1024;case c.AUTHENTICATED:return 10*1024*1024;case c.PUBLIC:default:return 20*1024*1024}}#m(){let e=(this.#c/1048576).toFixed(1);return`Accepted: ${this.#e.accept||"all files"} (max ${e}MB)`}#g(){this.#e.addEventListener("change",e=>{this.#v(e)}),this.#t.addEventListener("dragover",e=>{e.preventDefault(),e.stopPropagation(),this.#t.classList.add("drag-over")}),this.#t.addEventListener("dragleave",e=>{e.preventDefault(),e.stopPropagation(),this.#t.classList.remove("drag-over")}),this.#t.addEventListener("drop",e=>{e.preventDefault(),e.stopPropagation(),this.#t.classList.remove("drag-over");let t=e;if(!t.dataTransfer)return;let i=t.dataTransfer.files;i.length>0&&(this.#e.files=i,this.#v({target:this.#e}))})}async#v(e){let t=e.target.files;if(!t||t.length===0)return;let i=this.checkRateLimit();if(!i.allowed){this.#D(`Too many upload attempts. Please wait ${Math.ceil(i.retryAfter/1e3)} seconds.`),this.#e.value="";return}this.#H();let r=await this.#E(t);if(!r.valid){this.#D(r.errors.join(", ")),this.#e.value="",this.#n=null;return}this.#n=t,this.#I(t),this.#$(t),this.audit("files_selected",{name:this.#e.name,fileCount:t.length,totalSize:Array.from(t).reduce((s,a)=>s+a.size,0)}),this.dispatchEvent(new CustomEvent("secure-file-upload",{detail:{name:this.#e.name,files:Array.from(t),tier:this.securityTier},bubbles:!0,composed:!0}))}async#E(e){let t=[];!this.#e.multiple&&e.length>1&&t.push("Only one file is allowed");for(let i=0;i<e.length;i++){let r=e[i];if(r.size>this.#c){let s=(this.#c/1048576).toFixed(1);t.push(`${r.name}: File size exceeds ${s}MB`);continue}if(this.#u.size>0&&!this.#x(r)){t.push(`${r.name}: File type not allowed`);continue}if(this.#w(r.name)){t.push(`${r.name}: Invalid file name`);continue}if(this.securityTier===c.CRITICAL){let s=await this.#z(r);if(!s.valid){t.push(`${r.name}: ${s.error}`);continue}}if(this.#h){let s=await this.#C(r);if(!s.valid){t.push(`${r.name}: ${s.reason||"Rejected by scan"}`);continue}}}return{valid:t.length===0,errors:t}}#x(e){if(this.#u.has(e.type))return!0;for(let t of this.#u)if(t.endsWith("/*")){let i=t.slice(0,-2);if(e.type.startsWith(i))return!0}return!1}#w(e){return!!(e.includes("..")||e.includes("/")||e.includes("\\")||["web.config",".htaccess",".env","config.php"].includes(e.toLowerCase()))}async#C(e){this.#d=!0,this.#S(e.name),this.audit("scan_started",{name:this.#e?.name??"",fileName:e.name,fileSize:e.size});try{let t=await this.#h(e);return this.audit(t.valid?"scan_passed":"scan_rejected",{name:this.#e?.name??"",fileName:e.name,reason:t.reason??""}),t}catch(t){let i=t instanceof Error?t.message:"Scan failed";return this.audit("scan_error",{name:this.#e?.name??"",fileName:e.name,error:i}),{valid:!1,reason:`Scan error: ${i}`}}finally{this.#d=!1,this.#k()}}#S(e){this.#t&&this.#t.classList.add("scanning"),this.#e&&(this.#e.disabled=!0),this.#a&&(this.#a.textContent=`Scanning ${e}\u2026`)}#k(){this.#t&&this.#t.classList.remove("scanning"),this.#e&&!this.hasAttribute("disabled")&&(this.#e.disabled=!1)}async#z(e){try{let t=await e.slice(0,4).arrayBuffer(),i=new Uint8Array(t),r={"application/pdf":[37,80,68,70],"image/jpeg":[255,216,255],"image/png":[137,80,78,71]};return r[e.type]&&!r[e.type].every((n,o)=>i[o]===n)?{valid:!1,error:"File content does not match declared type"}:{valid:!0}}catch{return{valid:!1,error:"Failed to validate file content"}}}#I(e){this.#a&&(!e||e.length===0?(this.#a.textContent="No file selected",this.#a.classList.remove("has-file")):e.length===1?(this.#a.textContent=e[0].name,this.#a.classList.add("has-file")):(this.#a.textContent=`${e.length} files selected`,this.#a.classList.add("has-file")))}#$(e){this.#r.innerHTML="",Array.from(e).forEach(t=>{let i=document.createElement("div");i.className="file-preview";let r=document.createElement("div");r.className="file-name",r.textContent=t.name;let s=document.createElement("div");s.className="file-size",s.textContent=this.#R(t.size);let a=document.createElement("button");a.className="remove-file",a.textContent="\u2715",a.type="button",a.onclick=()=>{this.#M()},i.appendChild(r),i.appendChild(s),i.appendChild(a),this.#r.appendChild(i)})}#R(e){return e<1024?e+" B":e<1024*1024?(e/1024).toFixed(1)+" KB":(e/(1024*1024)).toFixed(1)+" MB"}#M(){this.#e.value="",this.#n=null,this.#r.innerHTML="",this.#I(null),this.#H(),this.audit("file_removed",{name:this.#e.name})}#D(e){this.#i.textContent=e,this.#i.classList.remove("hidden"),this.#t.classList.add("error")}#H(){this.#i.textContent="",this.#i.classList.add("hidden"),this.#t.classList.remove("error")}#V(){return".file-upload-container { position: relative; margin-bottom: var(--secure-ui-form-gap); font-family: var(--secure-ui-font-family-base); } label { display: block; margin-bottom: var(--secure-ui-form-label-margin-bottom); font-size: var(--secure-ui-label-font-size); font-weight: var(--secure-ui-label-font-weight); color: var(--secure-ui-label-color); } .label-suffix { font-weight: var(--secure-ui-font-weight-normal); color: var(--secure-ui-color-text-secondary); font-size: var(--secure-ui-font-size-xs); margin-left: var(--secure-ui-space-1); } .security-badge { display: inline-block; padding: var(--secure-ui-badge-padding); margin-left: var(--secure-ui-space-2); font-size: var(--secure-ui-badge-font-size); font-weight: var(--secure-ui-font-weight-semibold); border-radius: var(--secure-ui-badge-border-radius); text-transform: uppercase; background-color: var(--secure-ui-color-bg-tertiary); color: var(--secure-ui-color-text-secondary); border: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); } .drop-zone { position: relative; display: inline-flex; align-items: stretch; justify-content: flex-start; border-radius: var(--secure-ui-input-border-radius); cursor: pointer; width: 100%; } .drop-zone.drag-over { transform: scale(1.01); } .drop-zone.error .file-cta { border-color: var(--secure-ui-color-error); color: var(--secure-ui-color-error); } .file-input { position: absolute; top: 0; left: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; z-index: 1; } .file-input:focus { outline: none; } .drop-zone:focus-within .file-cta { outline: 2px solid var(--secure-ui-color-border-focus); outline-offset: 2px; box-shadow: var(--secure-ui-shadow-focus); } @media (forced-colors: active) { .drop-zone:focus-within .file-cta { outline: 2px solid ButtonText; box-shadow: none; } } .drop-zone-content { display: flex; align-items: stretch; width: 100%; pointer-events: none; } .file-cta { display: flex; align-items: center; justify-content: center; padding: var(--secure-ui-input-padding-y) var(--secure-ui-input-padding-x); background-color: var(--secure-ui-color-bg-secondary); border: var(--secure-ui-input-border-width) solid var(--secure-ui-input-border-color); border-radius: var(--secure-ui-input-border-radius); color: var(--secure-ui-color-text-primary); font-size: var(--secure-ui-input-font-size); font-weight: var(--secure-ui-font-weight-medium); white-space: nowrap; transition: all var(--secure-ui-transition-base) var(--secure-ui-transition-ease-in-out); } .drop-zone:hover .file-cta { background-color: var(--secure-ui-color-bg-tertiary); border-color: var(--secure-ui-input-border-color-hover); } .drop-zone:active .file-cta { background-color: var(--secure-ui-color-bg-tertiary); } .drop-zone.drag-over .file-cta { background-color: var(--secure-ui-color-primary-light, rgba(102, 126, 234, 0.1)); border-color: var(--secure-ui-color-primary); color: var(--secure-ui-color-primary); } .drop-icon { font-size: var(--secure-ui-font-size-base); margin-right: var(--secure-ui-space-2); display: flex; align-items: center; } .drop-text { font-size: var(--secure-ui-font-size-base); } .file-name-display { display: flex; align-items: center; flex: 1; padding: var(--secure-ui-input-padding-y) var(--secure-ui-input-padding-x); border: var(--secure-ui-input-border-width) solid var(--secure-ui-input-border-color); border-left: none; border-radius: 0 var(--secure-ui-input-border-radius) var(--secure-ui-input-border-radius) 0; background-color: var(--secure-ui-input-bg); color: var(--secure-ui-input-placeholder-color); font-size: var(--secure-ui-input-font-size); max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .file-name-display.has-file { color: var(--secure-ui-input-text-color); } .drop-zone-content.has-name .file-cta { border-radius: var(--secure-ui-input-border-radius) 0 0 var(--secure-ui-input-border-radius); border-right: none; } .drop-hint { display: block; text-align: right; margin-top: var(--secure-ui-space-1); font-size: var(--secure-ui-font-size-xs); color: var(--secure-ui-color-text-secondary); } .preview-container { margin-top: var(--secure-ui-space-3); } .file-preview { display: flex; align-items: center; padding: var(--secure-ui-space-3); background-color: var(--secure-ui-color-bg-secondary); border: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); border-radius: var(--secure-ui-input-border-radius); margin-bottom: var(--secure-ui-space-2); } .file-name { flex: 1; font-size: var(--secure-ui-font-size-sm); color: var(--secure-ui-color-text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .file-size { font-size: var(--secure-ui-font-size-xs); color: var(--secure-ui-color-text-secondary); margin-left: var(--secure-ui-space-3); white-space: nowrap; } .remove-file { background: none; border: none; color: var(--secure-ui-color-error); font-size: var(--secure-ui-font-size-base); cursor: pointer; padding: var(--secure-ui-space-1) var(--secure-ui-space-2); margin-left: var(--secure-ui-space-2); border-radius: var(--secure-ui-border-radius-sm); transition: background-color var(--secure-ui-transition-base) var(--secure-ui-transition-ease-in-out); pointer-events: auto; } .remove-file:hover { background-color: var(--secure-ui-color-error-light, rgba(239, 68, 68, 0.1)); } .error-container { position: absolute; bottom: -1rem; left: 0; display: var(--error-display); margin-top: var(--secure-ui-form-error-margin-top); padding: var(--secure-ui-space-2) var(--secure-ui-space-3); background-color: var(--secure-ui-color-error-light, rgba(239, 68, 68, 0.1)); border-radius: var(--secure-ui-border-radius-sm); color: var(--secure-ui-color-error); font-size: var(--secure-ui-error-font-size); } .error-container.hidden { max-height: 0; opacity: 0; transform: translateY(-4px); margin-top: 0; } .drop-zone.disabled { opacity: var(--secure-ui-input-disabled-opacity); cursor: not-allowed; } .drop-zone.disabled .file-cta { background-color: var(--secure-ui-input-disabled-bg); } .drop-zone.scanning { pointer-events: none; opacity: 0.7; } .drop-zone.scanning .file-cta { border-color: var(--secure-ui-color-primary); } .drop-zone.scanning .file-name-display { color: var(--secure-ui-color-primary); animation: scanning-pulse 1.2s ease-in-out infinite; } @keyframes scanning-pulse { 0%, 100% { opacity: 0.5; } 50% { opacity: 1; } }"}handleAttributeChange(e,t,i){if(this.#e)switch(e){case"disabled":this.#e.disabled=this.hasAttribute("disabled");break;case"accept":this.#e.accept=i,this.#p(i);break}}get files(){return this.#n}get name(){return this.#e?this.#e.name:""}get valid(){return!((this.hasAttribute("required")||this.config.validation.required)&&(!this.#n||this.#n.length===0))}clear(){this.#M()}setScanHook(e){if(typeof e!="function")throw new TypeError("setScanHook expects a function");this.#h=e,this.audit("scan_hook_registered",{name:this.#e?.name??""})}get hasScanHook(){return this.#h!==null}get scanning(){return this.#d}disconnectedCallback(){super.disconnectedCallback(),this.#n=null,this.#e&&(this.#e.value="")}};customElements.define("secure-file-upload",D);var H=class extends p{#e=null;#s=null;#i=null;#r=null;#t=`secure-datetime-${Math.random().toString(36).substring(2,11)}`;static get observedAttributes(){return[...super.observedAttributes,"name","type","label","required","min","max","step","value","show-timezone"]}constructor(){super()}render(){let e=document.createDocumentFragment(),t=document.createElement("div");t.className="datetime-container",t.setAttribute("part","container");let i=this.getAttribute("label");i&&(this.#s=document.createElement("label"),this.#s.htmlFor=this.#t,this.#s.textContent=this.sanitizeValue(i),this.#s.setAttribute("part","label"),t.appendChild(this.#s));let r=document.createElement("div");return r.className="input-wrapper",r.setAttribute("part","wrapper"),this.#e=document.createElement("input"),this.#e.id=this.#t,this.#e.className="datetime-field",this.#e.setAttribute("part","input"),this.#a(),this.#u(),r.appendChild(this.#e),this.hasAttribute("show-timezone")&&(this.#r=document.createElement("span"),this.#r.className="timezone-display",this.#r.textContent=this.#o(),r.appendChild(this.#r)),t.appendChild(r),this.#i=document.createElement("div"),this.#i.className="error-container hidden",this.#i.setAttribute("role","alert"),this.#i.setAttribute("part","error"),this.#i.id=`${this.#t}-error`,t.appendChild(this.#i),this.addComponentStyles(this.#f()),e.appendChild(t),e}#a(){let e=this.config,t=this.getAttribute("name");t&&(this.#e.name=this.sanitizeValue(t)),!this.getAttribute("label")&&t&&this.#e.setAttribute("aria-label",this.sanitizeValue(t)),this.#e.setAttribute("aria-describedby",`${this.#t}-error`),this.#r&&this.#r.setAttribute("aria-label",`Timezone: ${this.#o()}`);let i=this.getAttribute("type")||"date";["date","time","datetime-local","month","week"].includes(i)?this.#e.type=i:(console.warn(`Invalid datetime type "${i}", defaulting to "date"`),this.#e.type="date"),(this.hasAttribute("required")||e.validation.required)&&(this.#e.required=!0,this.#e.setAttribute("aria-required","true"));let s=this.getAttribute("min");s&&(this.#e.min=this.#n(s));let a=this.getAttribute("max");a&&(this.#e.max=this.#n(a));let n=this.getAttribute("step");n&&(this.#e.step=n),this.hasAttribute("disabled")&&(this.#e.disabled=!0),this.hasAttribute("readonly")&&(this.#e.readOnly=!0),e.storage.allowAutocomplete||(this.#e.autocomplete="off");let o=this.getAttribute("value");o&&(this.#e.value=this.#n(o))}#n(e){if(!e)return"";let t=this.#e?.type||this.getAttribute("type")||"date",i={date:/^\d{4}-\d{2}-\d{2}$/,time:/^\d{2}:\d{2}(:\d{2})?$/,"datetime-local":/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2})?$/,month:/^\d{4}-\d{2}$/,week:/^\d{4}-W\d{2}$/},r=Object.hasOwn(i,t)?i[t]:void 0;return r&&!r.test(e)?(console.warn(`Invalid ${t} format: ${e}`),""):e}#o(){let e=new Date().getTimezoneOffset(),t=Math.abs(Math.floor(e/60)),i=Math.abs(e%60);return`UTC${e<=0?"+":"-"}${t.toString().padStart(2,"0")}:${i.toString().padStart(2,"0")}`}#u(){this.#e.addEventListener("focus",()=>{this.recordTelemetryFocus(),this.audit("datetime_focused",{name:this.#e.name,type:this.#e.type})}),this.#e.addEventListener("input",e=>{this.recordTelemetryInput(e),this.#c(e)}),this.#e.addEventListener("change",e=>{this.#h(e)}),this.#e.addEventListener("blur",()=>{this.recordTelemetryBlur(),this.#d(),this.audit("datetime_blurred",{name:this.#e.name,hasValue:this.#e.value.length>0})})}#c(e){this.#b(),this.dispatchEvent(new CustomEvent("secure-datetime",{detail:{name:this.#e.name,value:this.#e.value,type:this.#e.type,tier:this.securityTier},bubbles:!0,composed:!0}))}#h(e){let t=this.#e.value;if(!this.#n(t)&&t){this.#p("Invalid date/time format");return}this.#b(),this.audit("datetime_changed",{name:this.#e.name,type:this.#e.type,value:t})}#d(){let e=this.checkRateLimit();if(!e.allowed){this.#p(`Too many attempts. Please wait ${Math.ceil(e.retryAfter/1e3)} seconds.`);return}let t=this.#e.value;if(this.#e.required&&!t){this.#p("This field is required");return}if(t){if(this.#e.min&&t<this.#e.min){this.#p(`Value must be after ${this.#l(this.#e.min)}`);return}if(this.#e.max&&t>this.#e.max){this.#p(`Value must be before ${this.#l(this.#e.max)}`);return}}if(this.securityTier===c.CRITICAL&&t){let i=new Date(t);if(isNaN(i.getTime())){this.#p("Invalid date/time");return}let r=i.getFullYear();if(r<1900||r>2100){this.#p("Date must be between 1900 and 2100");return}}}#l(e){try{return new Date(e).toLocaleString()}catch{return e}}#p(e){this.#i.textContent=e,this.#i.offsetHeight,this.#i.classList.remove("hidden"),this.#e.classList.add("error"),this.#e.setAttribute("aria-invalid","true")}#b(){this.#i.classList.add("hidden"),this.#i.addEventListener("transitionend",()=>{this.#i.classList.contains("hidden")&&(this.#i.textContent="")},{once:!0}),this.#e.classList.remove("error"),this.#e.removeAttribute("aria-invalid")}#f(){return`.datetime-container { margin-bottom: var(--secure-ui-form-gap); font-family: var(--secure-ui-font-family-base); } label { display: block; margin-bottom: var(--secure-ui-form-label-margin-bottom); font-size: var(--secure-ui-label-font-size); font-weight: var(--secure-ui-label-font-weight); color: var(--secure-ui-label-color); } .label-suffix { font-weight: var(--secure-ui-font-weight-normal); color: var(--secure-ui-color-text-secondary); font-size: var(--secure-ui-font-size-xs); margin-left: var(--secure-ui-space-1); } .security-badge { display: inline-block; padding: var(--secure-ui-badge-padding); margin-left: var(--secure-ui-space-2); font-size: var(--secure-ui-badge-font-size); font-weight: var(--secure-ui-font-weight-semibold); border-radius: var(--secure-ui-badge-border-radius); text-transform: uppercase; background-color: var(--secure-ui-color-bg-tertiary); color: var(--secure-ui-color-text-secondary); border: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); } .input-wrapper { position: relative; } .datetime-field { width: 100%; height: var(--secure-ui-input-height); padding: var(--secure-ui-input-padding-y) var(--secure-ui-input-padding-x); font-family: var(--secure-ui-font-family-base); font-size: var(--secure-ui-input-font-size); line-height: var(--secure-ui-line-height-normal); color: var(--secure-ui-input-text-color); background-color: var(--secure-ui-input-bg); border: var(--secure-ui-input-border-width) solid var(--secure-ui-input-border-color); border-radius: var(--secure-ui-input-border-radius); transition: all var(--secure-ui-transition-base) var(--secure-ui-transition-ease-in-out); cursor: pointer; box-sizing: border-box; } .datetime-field::placeholder { color: var(--secure-ui-input-placeholder-color); } .datetime-field:hover:not(:disabled):not([readonly]) { border-color: var(--secure-ui-input-border-color-hover); } .datetime-field:focus { outline: none; border-color: var(--secure-ui-input-border-color-focus); box-shadow: var(--secure-ui-shadow-focus); } .datetime-field.error { border-color: var(--secure-ui-color-error); } .datetime-field.error:focus { box-shadow: var(--secure-ui-shadow-focus-error); } .datetime-field:disabled { background-color: var(--secure-ui-input-disabled-bg); cursor: not-allowed; opacity: var(--secure-ui-input-disabled-opacity); } .datetime-field[readonly] { background-color: var(--secure-ui-color-bg-secondary); cursor: default; } .input-wrapper::after { content: '\u{1F4C5}' / ''; position: absolute; right: var(--secure-ui-space-3); top: 50%; transform: translateY(-50%); pointer-events: none; font-size: var(--secure-ui-font-size-lg); color: var(--secure-ui-color-text-secondary); } .input-wrapper[data-type="time"]::after { content: '\u{1F550}' / ''; } .input-wrapper[data-type="datetime-local"]::after { content: '\u{1F4C5}' / ''; } .input-wrapper[data-type="month"]::after { content: '\u{1F4C6}' / ''; } .input-wrapper[data-type="week"]::after { content: '\u{1F4C5}' / ''; } .input-wrapper .timezone-display { position: absolute; right: 0; bottom: -1.25rem; } .range-display { display: none; margin-top: var(--secure-ui-space-2); padding: var(--secure-ui-space-2) var(--secure-ui-space-3); background-color: var(--secure-ui-color-bg-secondary); border-radius: var(--secure-ui-border-radius-sm); font-size: var(--secure-ui-font-size-xs); color: var(--secure-ui-color-text-secondary); } .range-display.visible { display: block; } .range-item { margin-bottom: var(--secure-ui-space-1); } .range-item:last-child { margin-bottom: 0; } .range-label { font-weight: var(--secure-ui-font-weight-medium); margin-right: var(--secure-ui-space-1); } .helper-text { margin-top: var(--secure-ui-space-2); font-size: var(--secure-ui-font-size-xs); color: var(--secure-ui-color-text-secondary); line-height: var(--secure-ui-line-height-normal); } .error-container { position: absolute; margin-top: var(--secure-ui-form-error-margin-top); font-size: var(--secure-ui-error-font-size); color: var(--secure-ui-error-color); line-height: var(--secure-ui-line-height-normal); overflow: hidden; max-height: 40px; opacity: 1; transform: translateY(0); transition: opacity 0.2s ease-out, transform 0.2s ease-out, max-height 0.2s ease-out, margin-top 0.2s ease-out; } .error-container.hidden { max-height: 0; opacity: 0; transform: translateY(-4px); margin-top: 0; } @media (prefers-reduced-motion: reduce) { .datetime-field, .error-container { transition: none !important; } } .datetime-field::-webkit-calendar-picker-indicator { display: inline-block; cursor: pointer; opacity: 1; padding: 4px; margin-left: 4px; } .datetime-field:disabled::-webkit-calendar-picker-indicator { cursor: not-allowed; opacity: 0.3; } .datetime-field::-webkit-inner-spin-button { height: auto; opacity: 0.6; cursor: pointer; } .datetime-field:valid:not(:placeholder-shown):not(:focus) { border-color: var(--secure-ui-color-success); } .datetime-field:invalid:not(:placeholder-shown):not(:focus) { border-color: var(--secure-ui-color-error); } .datetime-container:focus-within label { color: var(--secure-ui-color-primary); } .datetime-container.disabled { opacity: var(--secure-ui-input-disabled-opacity); } .datetime-container.disabled label { color: var(--secure-ui-color-text-disabled); } label .required { color: var(--secure-ui-color-error); margin-left: var(--secure-ui-space-1); }`}handleAttributeChange(e,t,i){if(this.#e)switch(e){case"disabled":this.#e.disabled=this.hasAttribute("disabled");break;case"readonly":this.#e.readOnly=this.hasAttribute("readonly");break;case"value":i!==this.#e.value&&(this.#e.value=this.#n(i||""));break;case"min":this.#e.min=this.#n(i||"");break;case"max":this.#e.max=this.#n(i||"");break}}get value(){return this.#e?this.#e.value:""}set value(e){this.#e&&(this.#e.value=this.#n(e||""))}get name(){return this.#e?this.#e.name:""}getValueAsDate(){if(!this.#e||!this.#e.value)return null;try{let e=new Date(this.#e.value);return isNaN(e.getTime())?null:e}catch{return null}}setValueFromDate(e){if(!this.#e||!(e instanceof Date))return;let t=this.#e.type,i="";switch(t){case"date":i=e.toISOString().split("T")[0];break;case"time":i=e.toTimeString().slice(0,5);break;case"datetime-local":i=e.toISOString().slice(0,16);break;case"month":i=e.toISOString().slice(0,7);break;case"week":let r=new Date(e);r.setHours(0,0,0,0),r.setDate(r.getDate()+4-(r.getDay()||7));let s=new Date(r.getFullYear(),0,1),a=Math.ceil(((r.getTime()-s.getTime())/864e5+1)/7);i=`${r.getFullYear()}-W${a.toString().padStart(2,"0")}`;break}this.#e.value=i}get valid(){let e=this.hasAttribute("required")||this.config.validation.required,t=this.#e?this.#e.value:"";return!(e&&!t||t&&!this.#n(t)||this.#e&&(this.#e.min&&t<this.#e.min||this.#e.max&&t>this.#e.max))}focus(){this.#e&&this.#e.focus()}blur(){this.#e&&this.#e.blur()}disconnectedCallback(){super.disconnectedCallback(),this.#e&&(this.#e.value="")}};customElements.define("secure-datetime",H);var N=class extends p{#e=[];#s=[];#i=[];#r="";#t={column:null,direction:"asc"};#a={currentPage:1,pageSize:10};#n=!1;constructor(){super()}render(){return null}connectedCallback(){this.initializeSecurity();let e=this.querySelector('table[slot="table"]'),t=this.#o();t&&(this.#n=!0,this.#s=t.columns,this.#e=t.data,this.#i=[...t.data],e&&e.remove()),this.#y(),this.audit("table_mounted",{rowCount:this.#e.length,columnCount:this.#s.length,usingSlottedContent:this.#n})}#o(){let e=this.querySelector('table[slot="table"]');if(!e)return null;try{let t=e.querySelectorAll("thead th");if(t.length===0)return null;let i=Array.from(t).map(a=>({key:a.getAttribute("data-key")||a.textContent.trim().toLowerCase().replace(/\s+/g,"_"),label:a.textContent.trim().replace(/\s+$/,""),sortable:a.hasAttribute("data-sortable")?a.getAttribute("data-sortable")!=="false":!0,filterable:a.hasAttribute("data-filterable")?a.getAttribute("data-filterable")!=="false":void 0,tier:a.getAttribute("data-tier")||void 0,width:a.getAttribute("data-width")||void 0,render:a.hasAttribute("data-render-html")?this.#u(a):void 0})),r=e.querySelectorAll("tbody tr"),s=Array.from(r).map((a,n)=>{let o=a.querySelectorAll("td"),u=Object.create(null);return o.forEach((d,h)=>{if(h<i.length){let f=i[h],b=d.getAttribute("data-key")||f.key;if(b==="__proto__"||b==="constructor"||b==="prototype")return;d.innerHTML.trim().includes("<")?(u[b]=d.textContent?.trim()??"",u[`${b}_html`]=d.innerHTML.trim()):u[b]=d.textContent?.trim()??""}}),u});return{columns:i,data:s}}catch(t){return console.error("SecureTable: Error parsing slotted table",t),null}}#u(e){return(t,i,r)=>{let s=`${r}_html`;return(Object.hasOwn(i,s)?i[s]:null)||this.#l(t)}}set data(e){Array.isArray(e)&&(this.#e=e,this.#i=[...e],this.#y())}get data(){return this.#e}set columns(e){Array.isArray(e)&&(this.#s=e,this.#y())}get columns(){return this.#s}#c(e){this.#r=e.toLowerCase(),this.#r?this.#i=this.#e.filter(t=>this.#s.some(i=>i.filterable===!1?!1:String(t[i.key]??"").toLowerCase().includes(this.#r))):this.#i=[...this.#e],this.#a.currentPage=1,this.#m(),this.audit("table_filtered",{filterTerm:e,resultCount:this.#i.length})}#h(e){this.#t.column===e?this.#t.direction=this.#t.direction==="asc"?"desc":"asc":(this.#t.column=e,this.#t.direction="asc"),this.#i.sort((t,i)=>{let r=Object.hasOwn(t,e)?t[e]:void 0,s=Object.hasOwn(i,e)?i[e]:void 0,a=0;return r>s&&(a=1),r<s&&(a=-1),this.#t.direction==="asc"?a:-a}),this.#m(),this.audit("table_sorted",{column:e,direction:this.#t.direction})}#d(e){let t=Math.ceil(this.#i.length/this.#a.pageSize);e<1||e>t||(this.#a.currentPage=e,this.#m())}#l(e){return e==null||e===""?"":String(e).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#x27;")}#p(e,t){if(e==null||e==="")return"-";let i=String(e);return t===c.SENSITIVE&&i.length>4?"\u2022".repeat(i.length-4)+i.slice(-4):t===c.CRITICAL?"\u2022".repeat(i.length):this.#l(i)}#b(e,t,i){if(typeof i.render=="function")return i.render(e,t,i.key);let r=`${i.key}_html`;return Object.hasOwn(t,r)&&t[r]?t[r]:this.#p(e,i.tier)}#f(){let e=Math.ceil(this.#i.length/this.#a.pageSize),t=(this.#a.currentPage-1)*this.#a.pageSize,i=t+this.#a.pageSize,r=this.#i.slice(t,i),s,a;if(r.length===0||this.#s.length===0){let n=this.#s.length===0?"No columns configured":"No results found",o=this.#s.length===0?"Set the columns property to configure the table":"Try adjusting your search term";s=`
2
+ <div class="empty-state">
3
+ <div class="empty-state-icon" aria-hidden="true">\u{1F50D}</div>
4
+ <h3>${this.#l(n)}</h3>
5
+ <p>${this.#l(o)}</p>
6
+ </div>`,a=""}else s=`
7
+ <div class="table-wrapper">
8
+ <table class="data-table">
9
+ <thead>
10
+ <tr>
11
+ ${this.#s.map(n=>{let o=this.#t.column===n.key,u=o?this.#t.direction==="asc"?"\u25B2":"\u25BC":"\u25B2",d=n.sortable!==!1?`aria-sort="${o?this.#t.direction==="asc"?"ascending":"descending":"none"}"`:"";return`
12
+ <th
13
+ class="${n.sortable!==!1?"sortable":""} ${o?"sorted":""}"
14
+ data-column="${this.#l(n.key)}"
15
+ ${d}
16
+ >
17
+ ${this.#l(n.label)}
18
+ ${n.sortable!==!1?`<span class="sort-indicator" aria-hidden="true">${u}</span>`:""}
19
+ ${n.tier?`<span class="security-badge" aria-hidden="true">${this.#l(n.tier)}</span>`:""}
20
+ </th>`}).join("")}
21
+ </tr>
22
+ </thead>
23
+ <tbody>
24
+ ${r.map(n=>`
25
+ <tr>
26
+ ${this.#s.map(o=>`
27
+ <td>${this.#b(n[o.key],n,o)}</td>
28
+ `).join("")}
29
+ </tr>
30
+ `).join("")}
31
+ </tbody>
32
+ </table>
33
+ </div>`,a=e>1?`
34
+ <div class="pagination">
35
+ <div class="pagination-info">
36
+ Showing ${t+1}-${Math.min(i,this.#i.length)} of ${this.#i.length} results
37
+ </div>
38
+ <div class="pagination-controls">
39
+ <button class="pagination-button" id="prevBtn" ${this.#a.currentPage===1?"disabled":""}>
40
+ \u2190 Previous
41
+ </button>
42
+ ${this.#g(e)}
43
+ <button class="pagination-button" id="nextBtn" ${this.#a.currentPage===e?"disabled":""}>
44
+ Next \u2192
45
+ </button>
46
+ </div>
47
+ </div>`:"";return{tableHtml:s,paginationHtml:a}}#y(){if(!this.shadowRoot)return;let{tableHtml:e,paginationHtml:t}=this.#f();this.shadowRoot.innerHTML="",this.addComponentStyles(this.getBaseStylesheetUrl()),this.addComponentStyles(':host { display: block; font-family: var(--secure-ui-font-family-base); } .table-container { background: var(--secure-ui-color-bg-primary); border-radius: var(--secure-ui-border-radius-lg); border: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); overflow: hidden; } .table-header { display: flex; justify-content: space-between; align-items: center; padding: var(--secure-ui-space-4); background-color: var(--secure-ui-color-bg-secondary); border-bottom: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); gap: var(--secure-ui-space-3); flex-wrap: wrap; } .table-title { font-size: var(--secure-ui-font-size-lg); font-weight: var(--secure-ui-font-weight-semibold); color: var(--secure-ui-color-text-primary); margin: 0; } .table-controls { display: flex; gap: var(--secure-ui-space-3); align-items: center; } .search-input { padding: var(--secure-ui-space-2) var(--secure-ui-space-3); border: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); border-radius: var(--secure-ui-border-radius-base); font-size: var(--secure-ui-font-size-sm); font-family: var(--secure-ui-font-family-base); color: var(--secure-ui-color-text-primary); background-color: var(--secure-ui-color-bg-primary); min-width: 200px; transition: all var(--secure-ui-transition-base) var(--secure-ui-transition-ease-in-out); } .search-input:focus { outline: none; border-color: var(--secure-ui-color-primary); box-shadow: var(--secure-ui-shadow-focus); } .search-input::placeholder { color: var(--secure-ui-color-text-secondary); } .table-wrapper { overflow-x: auto; overflow-y: visible; } .data-table { width: 100%; border-collapse: collapse; font-size: var(--secure-ui-font-size-sm); color: var(--secure-ui-table-font-color); } .data-table thead { background-color: var(--secure-ui-color-bg-tertiary); border-bottom: var(--secure-ui-border-width-base) solid var(--secure-ui-color-border); } .data-table th { padding: var(--secure-ui-space-3) var(--secure-ui-space-4); text-align: left; font-weight: var(--secure-ui-font-weight-semibold); color: var(--secure-ui-color-text-primary); white-space: nowrap; position: relative; } .data-table th.sortable { cursor: pointer; user-select: none; transition: background-color var(--secure-ui-transition-fast) var(--secure-ui-transition-ease-in-out); } .data-table th.sortable:hover { background-color: var(--secure-ui-color-bg-secondary); } .data-table th.sorted { color: var(--secure-ui-color-primary); } .sort-indicator { display: inline-block; margin-left: var(--secure-ui-space-1); font-size: var(--secure-ui-font-size-xs); opacity: 0.5; transition: opacity var(--secure-ui-transition-fast) var(--secure-ui-transition-ease-in-out); } .data-table th.sorted .sort-indicator { opacity: 1; } .data-table tbody tr { border-bottom: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); transition: background-color var(--secure-ui-transition-fast) var(--secure-ui-transition-ease-in-out); } .data-table tbody tr:hover { background-color: var(--secure-ui-color-bg-secondary); } .data-table tbody tr:last-child { border-bottom: none; } .data-table td { padding: var(--secure-ui-space-3) var(--secure-ui-space-4); color: var(--secure-ui-color-text-primary); vertical-align: middle; } .masked-cell { font-family: var(--secure-ui-font-family-mono); color: var(--secure-ui-color-text-secondary); letter-spacing: 0.1em; } .empty-state { padding: var(--secure-ui-space-8) var(--secure-ui-space-4); text-align: center; color: var(--secure-ui-color-text-secondary); } .empty-state-icon { font-size: var(--secure-ui-font-size-3xl); margin-bottom: var(--secure-ui-space-2); } .empty-state-text { font-size: var(--secure-ui-font-size-base); margin: 0; } .pagination { display: flex; justify-content: space-between; align-items: center; padding: var(--secure-ui-space-4); background-color: var(--secure-ui-color-bg-secondary); border-top: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); gap: var(--secure-ui-space-3); flex-wrap: wrap; } .pagination-info { font-size: var(--secure-ui-font-size-sm); color: var(--secure-ui-color-text-secondary); } .pagination-controls { display: flex; gap: var(--secure-ui-space-2); } .pagination-button { padding: var(--secure-ui-space-2) var(--secure-ui-space-3); border: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); border-radius: var(--secure-ui-border-radius-base); background-color: var(--secure-ui-color-bg-primary); color: var(--secure-ui-color-text-primary); font-size: var(--secure-ui-font-size-sm); font-family: var(--secure-ui-font-family-base); cursor: pointer; transition: all var(--secure-ui-transition-base) var(--secure-ui-transition-ease-in-out); } .pagination-button:hover:not(:disabled) { background-color: var(--secure-ui-color-primary); color: var(--secure-ui-color-text-inverse); border-color: var(--secure-ui-color-primary); } .pagination-button:disabled { opacity: var(--secure-ui-input-disabled-opacity); cursor: not-allowed; } .pagination-button.active { background-color: var(--secure-ui-color-primary); color: var(--secure-ui-color-text-inverse); border-color: var(--secure-ui-color-primary); } .page-size-selector { display: flex; align-items: center; gap: var(--secure-ui-space-2); font-size: var(--secure-ui-font-size-sm); color: var(--secure-ui-color-text-secondary); } .page-size-select { padding: var(--secure-ui-space-1) var(--secure-ui-space-2); border: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); border-radius: var(--secure-ui-border-radius-base); background-color: var(--secure-ui-color-bg-primary); color: var(--secure-ui-color-text-primary); font-size: var(--secure-ui-font-size-sm); font-family: var(--secure-ui-font-family-base); cursor: pointer; } .loading-overlay { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(255, 255, 255, 0.8); display: flex; justify-content: center; align-items: center; z-index: var(--secure-ui-z-sticky); } .loading-spinner { width: 40px; height: 40px; border: 4px solid var(--secure-ui-color-border); border-top-color: var(--secure-ui-color-primary); border-radius: 50%; animation: spin 0.8s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } :host([security-tier="authenticated"]) .table-container { border-top: var(--secure-ui-border-width-thick) solid var(--secure-ui-tier-authenticated); } :host([security-tier="sensitive"]) .table-container { border-top: var(--secure-ui-border-width-thick) solid var(--secure-ui-tier-sensitive); } :host([security-tier="critical"]) .table-container { border-top: var(--secure-ui-border-width-thick) solid var(--secure-ui-tier-critical); } .security-badge { display: inline-block; padding: var(--secure-ui-badge-padding); margin-left: var(--secure-ui-space-2); font-size: var(--secure-ui-badge-font-size); font-weight: var(--secure-ui-font-weight-semibold); border-radius: var(--secure-ui-badge-border-radius); text-transform: uppercase; background-color: var(--secure-ui-color-bg-tertiary); color: var(--secure-ui-color-text-secondary); border: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border); } @media (max-width: 768px) { .table-header { flex-direction: column; align-items: stretch; } .table-controls { flex-direction: column; width: 100%; } .search-input { width: 100%; min-width: auto; } .pagination { flex-direction: column; align-items: stretch; } .pagination-controls { justify-content: center; } .table-wrapper { position: relative; background: linear-gradient(to right, var(--secure-ui-color-bg-primary) 0%, transparent 100%) left, linear-gradient(to left, var(--secure-ui-color-bg-primary) 0%, transparent 100%) right, radial-gradient(farthest-side at 0 50%, rgba(0,0,0,.12), transparent) left, radial-gradient(farthest-side at 100% 50%, rgba(0,0,0,.12), transparent) right; background-repeat: no-repeat; background-size: 32px 100%, 32px 100%, 10px 100%, 10px 100%; background-attachment: local, local, scroll, scroll; } } .data-table tbody tr:nth-child(even) { background-color: rgba(0, 0, 0, 0.01); } .data-table tbody tr:nth-child(even):hover { background-color: var(--secure-ui-color-bg-secondary); }');let i=document.createElement("slot");i.name="table",this.shadowRoot.appendChild(i);let r=document.createElement("div");r.className="table-container",r.innerHTML=`
48
+ <div class="table-header">
49
+ <input
50
+ type="search"
51
+ class="search-input"
52
+ placeholder="Search across all columns..."
53
+ value="${this.#l(this.#r)}"
54
+ id="searchInput"
55
+ />
56
+ </div>
57
+ <div id="tableContent">${e}</div>
58
+ <div id="paginationContent">${t}</div>
59
+ `,this.shadowRoot.appendChild(r),this.#v()}#m(){if(!this.shadowRoot)return;let e=this.shadowRoot.getElementById("tableContent"),t=this.shadowRoot.getElementById("paginationContent");if(!e){this.#y();return}let{tableHtml:i,paginationHtml:r}=this.#f();e.innerHTML=i,t&&(t.innerHTML=r),this.#E()}#g(e){let i=Math.max(1,this.#a.currentPage-Math.floor(2.5)),r=Math.min(e,i+5-1);r-i<4&&(i=Math.max(1,r-5+1));let s="";for(let a=i;a<=r;a++)s+=`
60
+ <button
61
+ class="pagination-button ${a===this.#a.currentPage?"active":""}"
62
+ data-page="${a}"
63
+ >
64
+ ${a}
65
+ </button>
66
+ `;return s}#v(){let e=this.shadowRoot.getElementById("searchInput");e&&e.addEventListener("input",t=>{this.#c(t.target.value)}),this.#E()}#E(){this.shadowRoot.querySelectorAll("th.sortable").forEach(a=>{a.addEventListener("click",()=>{let n=a.getAttribute("data-column");n&&this.#h(n)})});let t=this.shadowRoot.getElementById("prevBtn"),i=this.shadowRoot.getElementById("nextBtn");t&&t.addEventListener("click",()=>{this.#d(this.#a.currentPage-1)}),i&&i.addEventListener("click",()=>{this.#d(this.#a.currentPage+1)}),this.shadowRoot.querySelectorAll(".pagination-button[data-page]").forEach(a=>{a.addEventListener("click",()=>{let n=parseInt(a.getAttribute("data-page"),10);this.#d(n)})});let s=this.shadowRoot.getElementById("tableContent");s&&s.addEventListener("click",a=>{let n=a.target.closest("[data-action]");if(!n)return;let o=n.getAttribute("data-action"),u=Object.create(null);u.action=o;for(let d of Array.from(n.attributes))if(d.name.startsWith("data-")&&d.name!=="data-action"){let h=d.name.slice(5).replace(/-([a-z])/g,(f,b)=>b.toUpperCase());if(h==="__proto__"||h==="constructor"||h==="prototype")continue;u[h]=d.value}this.dispatchEvent(new CustomEvent("table-action",{bubbles:!0,composed:!0,detail:u})),this.audit("table_action",u)})}};customElements.define("secure-table",N);var F=class extends p{#e=null;#s=null;#i=null;#r=null;#t=!1;#a=!1;#n="critical";#o;#u=`secure-submit-button-${Math.random().toString(36).substring(2,11)}`;#c;#h;static get observedAttributes(){return[...super.observedAttributes,"label","loading-label","disabled"]}constructor(){super(),this.#o=g(this.#n),this.#c=this.#b.bind(this),this.#h=this.#g.bind(this)}connectedCallback(){super.connectedCallback(),queueMicrotask(()=>{this.#d(),this.#l(),this.#p(),this.#f(),this.audit("submit_button_initialized",{tier:this.#n,hasParentForm:!!this.#r})})}render(){let e=document.createDocumentFragment(),t=document.createElement("div");t.className="submit-container";let i=`${this.#u}-hint`,r=document.createElement("p");r.id=i,r.className="sr-only",r.textContent="Complete all required fields to enable this button",t.appendChild(r),this.#e=document.createElement("button"),this.#e.type="button",this.#e.className="submit-btn",this.#e.disabled=!0,this.#e.setAttribute("aria-disabled","true"),this.#e.setAttribute("aria-describedby",i),this.#s=document.createElement("span"),this.#s.className="btn-label",this.#s.textContent=this.sanitizeValue(this.getAttribute("label")||"Submit"),this.#i=document.createElement("span"),this.#i.className="btn-loading hidden",this.#i.setAttribute("aria-hidden","true");let s=document.createElement("span");s.className="spinner";let a=document.createElement("span");return a.textContent=this.sanitizeValue(this.getAttribute("loading-label")||"Submitting..."),this.#i.appendChild(s),this.#i.appendChild(a),this.#e.appendChild(this.#s),this.#e.appendChild(this.#i),this.#e.addEventListener("click",this.#h),t.appendChild(this.#e),e.appendChild(t),this.addComponentStyles(this.#E()),e}#d(){this.#r=this.closest("secure-form")}#l(){!this.getAttribute("security-tier")&&this.#r?this.#n=this.#r.securityTier:this.#n=this.securityTier,this.#o=g(this.#n)}#p(){let e=this.#r||this.parentElement;e&&(e.addEventListener("secure-input",this.#c),e.addEventListener("secure-textarea",this.#c),e.addEventListener("secure-select",this.#c),e.addEventListener("secure-datetime",this.#c))}#b(e){this.#f()}#f(){if(this.hasAttribute("disabled")){this.#m(!0);return}if(!this.#a){if(!this.#o.validation.required){this.#t=!0,this.#m(!1);return}this.#r&&typeof this.#r.valid=="boolean"?this.#t=this.#r.valid:this.#t=this.#y(),this.#m(!this.#t)}}#y(){let e=this.#r||this.parentElement;if(!e)return!1;let t=e.querySelectorAll("secure-input, secure-textarea, secure-select, secure-datetime, secure-file-upload");for(let i of t){let r=i;if(typeof r.valid=="boolean"&&!r.valid)return!1}return t.length>0}#m(e){this.#e&&(this.#e.disabled=e,this.#e.setAttribute("aria-disabled",String(e)))}#g(){if(this.#a||this.#e?.disabled)return;let e=this.checkRateLimit();if(!e.allowed){this.audit("submit_button_rate_limited",{retryAfter:e.retryAfter});return}this.audit("submit_button_clicked",{tier:this.#n,formValid:this.#t}),this.#v(!0),this.#r&&this.#r.submit(),this.#v(!1)}#v(e){this.#a=e,this.#e&&(this.#e.disabled=e,this.#e.setAttribute("aria-disabled",String(e))),this.#s&&this.#s.classList.toggle("hidden",e),this.#i&&(this.#i.classList.toggle("hidden",!e),this.#i.setAttribute("aria-hidden",String(!e)))}handleAttributeChange(e,t,i){switch(e){case"label":this.#s&&(this.#s.textContent=this.sanitizeValue(i||"Submit"));break;case"loading-label":if(this.#i){let r=this.#i.querySelector("span:last-child");r&&(r.textContent=this.sanitizeValue(i||"Submitting..."))}break;case"disabled":this.#f();break}}get disabled(){return this.#e?this.#e.disabled:!0}set disabled(e){e?this.setAttribute("disabled",""):this.removeAttribute("disabled"),this.#f()}get label(){return this.getAttribute("label")||"Submit"}set label(e){this.setAttribute("label",e)}#E(){return":host { display: inline-block; } .submit-container { margin-top: 8px; position: relative; } .submit-btn { display: inline-flex; align-items: center; justify-content: center; gap: var(--secure-ui-space-2); padding: var(--secure-ui-button-padding-y) var(--secure-ui-button-padding-x); min-height: var(--secure-ui-button-height); font-family: inherit; font-size: var(--secure-ui-font-size-sm); font-weight: var(--secure-ui-button-font-weight); line-height: 1; border-radius: var(--secure-ui-button-border-radius); border: var(--secure-ui-border-width-base) solid transparent; cursor: pointer; transition: background-color var(--secure-ui-transition-base) var(--secure-ui-transition-ease-out), border-color var(--secure-ui-transition-base) var(--secure-ui-transition-ease-out), opacity var(--secure-ui-transition-base) var(--secure-ui-transition-ease-out), box-shadow var(--secure-ui-transition-base) var(--secure-ui-transition-ease-out), color var(--secure-ui-transition-base) var(--secure-ui-transition-ease-out), transform var(--secure-ui-transition-fast) var(--secure-ui-transition-ease-out); background-color: var(--secure-ui-color-info); color: var(--secure-ui-color-text-inverse); user-select: none; } .submit-btn:hover:not(:disabled) { background-color: color-mix(in srgb, var(--secure-ui-color-info) 82%, black); transform: translateY(-1px); box-shadow: 0 2px 8px rgba(59, 130, 246, 0.25); } .submit-btn:focus-visible { outline: 2px solid var(--secure-ui-color-info); outline-offset: 2px; box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.3); } @media (forced-colors: active) { .submit-btn:focus-visible { outline: 2px solid ButtonText; box-shadow: none; } } .submit-btn:active:not(:disabled) { background-color: color-mix(in srgb, var(--secure-ui-color-info) 72%, black); transform: scale(0.98); box-shadow: none; } .submit-btn:disabled { background-color: var(--secure-ui-color-bg-disabled); color: var(--secure-ui-color-text-disabled); border-color: var(--secure-ui-color-border); cursor: not-allowed; opacity: 0.7; transform: none; box-shadow: none; } .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; } .btn-label, .btn-loading { display: inline-flex; align-items: center; gap: 8px; transition: opacity 0.2s ease-out; } .btn-label.hidden, .btn-loading.hidden { display: none; } .spinner { display: inline-block; width: 14px; height: 14px; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: spin 0.6s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } @media (prefers-reduced-motion: reduce) { .submit-btn { transition: none !important; } .btn-label, .btn-loading { transition: none !important; } .spinner { animation: none; border-right-color: currentColor; opacity: 0.5; } }"}disconnectedCallback(){super.disconnectedCallback();let e=this.#r||this.parentElement;e&&(e.removeEventListener("secure-input",this.#c),e.removeEventListener("secure-textarea",this.#c),e.removeEventListener("secure-select",this.#c),e.removeEventListener("secure-datetime",this.#c))}};customElements.define("secure-submit-button",F);var U=Object.freeze([{type:"amex",pattern:/^3[47]/,format:[4,6,5],cvcLength:4,lengths:[15],label:"Amex"},{type:"diners",pattern:/^3(?:0[0-5]|[68])/,format:[4,6,4],cvcLength:3,lengths:[14],label:"Diners"},{type:"discover",pattern:/^6(?:011|5[0-9]{2})/,format:[4,4,4,4],cvcLength:3,lengths:[16],label:"Discover"},{type:"jcb",pattern:/^(?:2131|1800|35\d{3})/,format:[4,4,4,4],cvcLength:3,lengths:[16],label:"JCB"},{type:"mastercard",pattern:/^(?:5[1-5]|2[2-7])/,format:[4,4,4,4],cvcLength:3,lengths:[16],label:"Mastercard"},{type:"visa",pattern:/^4/,format:[4,4,4,4],cvcLength:3,lengths:[13,16,19],label:"Visa"}]);function J(l){return l?U.find(e=>e.pattern.test(l))??null:null}function x(l,e){let t="",i=0;for(let r=0;r<e.length;r++){let s=l.slice(i,i+e[r]);if(!s)break;r>0&&(t+=" "),t+=s,i+=e[r]}return t}function X(l,e){let t=e.reduce((a,n)=>a+n,0);if(!l)return x("\u2022".repeat(t),e);let i=l.padEnd(t,"\u2022").slice(0,t),r=Math.max(0,i.length-4),s="\u2022".repeat(r)+i.slice(r);return x(s,e)}function B(l){if(!l||l.length<12)return!1;let e=0,t=!1;for(let i=l.length-1;i>=0;i--){let r=l[i];if(!r)return!1;let s=parseInt(r,10);if(isNaN(s))return!1;let a=s;t&&(a*=2,a>9&&(a-=9)),e+=a,t=!t}return e%10===0}function Y(l,e){let t=new Date,i=t.getFullYear()%100,r=t.getMonth()+1;return!(e<i||e===i&&l<r)}var Q=0,$=class extends p{#e=null;#s=null;#i=null;#r=null;#t=null;#a=null;#n=null;#o=null;#u=null;#c=null;#h=null;#d=null;#l=null;#p=null;#b=null;#f=null;#y=null;#m="";#g="";#v="";#E="";#x=null;#w;constructor(){super(),this.#w=`secure-card-${++Q}`}static get observedAttributes(){return[...super.observedAttributes,"name","label","show-name"]}render(){let e=document.createDocumentFragment(),t=this.hasAttribute("disabled"),i=this.hasAttribute("show-name"),r=this.getAttribute("label")??"",s=document.createElement("div");s.className="card-container",s.setAttribute("part","container");let a=document.createElement("div");a.className="card-scene",a.setAttribute("aria-hidden","true"),this.#t=document.createElement("div"),this.#t.className="card";let n=document.createElement("div");n.className="card-face card-front";let o=document.createElement("div");o.className="card-top-row";let u=document.createElement("div");u.className="card-chip",this.#u=document.createElement("div"),this.#u.className="card-type-label",o.appendChild(u),o.appendChild(this.#u),n.appendChild(o),this.#a=document.createElement("div"),this.#a.className="card-number-display",this.#a.textContent="\u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022",n.appendChild(this.#a);let d=document.createElement("div");d.className="card-bottom-row";let h=document.createElement("div");h.className="card-name-section";let f=document.createElement("div");f.className="card-field-label",f.textContent="Card holder",this.#o=document.createElement("div"),this.#o.className="card-name-display",this.#o.textContent="FULL NAME",h.appendChild(f),h.appendChild(this.#o);let b=document.createElement("div");b.className="card-expiry-section";let P=document.createElement("div");P.className="card-field-label",P.textContent="Expires",this.#n=document.createElement("div"),this.#n.className="card-expiry-display",this.#n.textContent="MM/YY",b.appendChild(P),b.appendChild(this.#n),d.appendChild(h),d.appendChild(b),n.appendChild(d);let w=document.createElement("div");w.className="card-face card-back";let j=document.createElement("div");j.className="card-strip";let E=document.createElement("div");E.className="card-cvc-area";let q=document.createElement("div");q.className="card-cvc-label",q.textContent="CVC",this.#c=document.createElement("div"),this.#c.className="card-cvc-display",this.#c.textContent="\u2022\u2022\u2022",E.appendChild(q),E.appendChild(this.#c),w.appendChild(j),w.appendChild(E),this.#t.appendChild(n),this.#t.appendChild(w),a.appendChild(this.#t);let v=document.createElement("div");if(v.className="card-fields",r){let m=document.createElement("div");m.className="card-legend",m.setAttribute("part","label"),m.textContent=this.sanitizeValue(r),v.appendChild(m)}let A=this.#C(`${this.#w}-number`),K=A.querySelector("label");K.textContent="Card number",this.#e=document.createElement("input"),this.#e.id=`${this.#w}-number`,this.#e.className="card-input card-number-input",this.#e.setAttribute("type","text"),this.#e.setAttribute("inputmode","numeric"),this.#e.setAttribute("autocomplete","cc-number"),this.#e.setAttribute("placeholder","0000 0000 0000 0000"),this.#e.setAttribute("maxlength","23"),this.#e.setAttribute("aria-required","true"),this.#e.setAttribute("aria-describedby",`${this.#w}-number-error`),this.#e.setAttribute("part","number-input"),t&&(this.#e.disabled=!0),this.#h=A.querySelector(".error-container"),this.#h.id=`${this.#w}-number-error`,A.querySelector(".input-wrapper").appendChild(this.#e),v.appendChild(A);let C=document.createElement("div");C.className="field-row";let T=this.#C(`${this.#w}-expiry`);T.querySelector("label").textContent="Expiry date",this.#s=document.createElement("input"),this.#s.id=`${this.#w}-expiry`,this.#s.className="card-input",this.#s.setAttribute("type","text"),this.#s.setAttribute("inputmode","numeric"),this.#s.setAttribute("autocomplete","cc-exp"),this.#s.setAttribute("placeholder","MM/YY"),this.#s.setAttribute("maxlength","5"),this.#s.setAttribute("aria-required","true"),this.#s.setAttribute("aria-describedby",`${this.#w}-expiry-error`),this.#s.setAttribute("part","expiry-input"),t&&(this.#s.disabled=!0),this.#d=T.querySelector(".error-container"),this.#d.id=`${this.#w}-expiry-error`,T.querySelector(".input-wrapper").appendChild(this.#s);let L=this.#C(`${this.#w}-cvc`);L.querySelector("label").textContent="Security code",this.#i=document.createElement("input"),this.#i.id=`${this.#w}-cvc`,this.#i.className="card-input cvc-input",this.#i.setAttribute("type","password"),this.#i.setAttribute("inputmode","numeric"),this.#i.setAttribute("autocomplete","cc-csc"),this.#i.setAttribute("placeholder","\u2022\u2022\u2022"),this.#i.setAttribute("maxlength","4"),this.#i.setAttribute("aria-required","true"),this.#i.setAttribute("aria-describedby",`${this.#w}-cvc-error`),this.#i.setAttribute("part","cvc-input"),t&&(this.#i.disabled=!0),this.#l=L.querySelector(".error-container"),this.#l.id=`${this.#w}-cvc-error`,L.querySelector(".input-wrapper").appendChild(this.#i),C.appendChild(T),C.appendChild(L),v.appendChild(C);let y=this.#C(`${this.#w}-name`);return y.id=`${this.#w}-name-group`,y.querySelector("label").textContent="Cardholder name",i||(y.hidden=!0),this.#r=document.createElement("input"),this.#r.id=`${this.#w}-name`,this.#r.className="card-input",this.#r.setAttribute("type","text"),this.#r.setAttribute("autocomplete","cc-name"),this.#r.setAttribute("placeholder","Name as it appears on card"),this.#r.setAttribute("spellcheck","false"),this.#r.setAttribute("aria-describedby",`${this.#w}-name-error`),this.#r.setAttribute("part","name-input"),t&&(this.#r.disabled=!0),this.#p=y.querySelector(".error-container"),this.#p.id=`${this.#w}-name-error`,y.querySelector(".input-wrapper").appendChild(this.#r),v.appendChild(y),s.appendChild(a),s.appendChild(v),this.#q(),this.addComponentStyles(":host { --secure-card-width: 340px; --secure-card-radius: 16px; --secure-card-font: var(--secure-ui-font-family-mono, 'Courier New', monospace); --secure-card-transition: transform 0.6s cubic-bezier(0.4, 0, 0.2, 1); --secure-card-gradient: linear-gradient(135deg, #1e2a4a 0%, #2d4a8a 100%); display: block; } .card-container { width: 100%; max-width: 480px; font-family: var(--secure-ui-font-family-sans, system-ui, sans-serif); } .card-scene { width: var(--secure-card-width); max-width: 100%; aspect-ratio: 85.6 / 54; perspective: 1000px; margin-inline: auto; margin-block-end: var(--secure-ui-space-6, 1.5rem); user-select: none; } .card { width: 100%; height: 100%; position: relative; transform-style: preserve-3d; transition: var(--secure-card-transition); border-radius: var(--secure-card-radius); filter: drop-shadow(0 8px 24px rgba(0, 0, 0, 0.35)); } .card.is-flipped { transform: rotateY(180deg); } .card-face { position: absolute; inset: 0; border-radius: var(--secure-card-radius); backface-visibility: hidden; -webkit-backface-visibility: hidden; background: var(--secure-card-gradient); color: #fff; overflow: hidden; } .card-face::before { content: ''; position: absolute; inset: 0; background: linear-gradient( 135deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0) 60% ); border-radius: inherit; pointer-events: none; } .card-back { transform: rotateY(180deg); } .card--visa { --secure-card-gradient: linear-gradient(135deg, #1a1f71 0%, #2563eb 100%); } .card--mastercard { --secure-card-gradient: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #e63946 100%); } .card--amex { --secure-card-gradient: linear-gradient(135deg, #007b5e 0%, #00b894 100%); } .card--discover { --secure-card-gradient: linear-gradient(135deg, #b34700 0%, #e65c00 50%, #f9a825 100%); } .card--diners { --secure-card-gradient: linear-gradient(135deg, #005c97 0%, #363795 100%); } .card--jcb { --secure-card-gradient: linear-gradient(135deg, #0e4c96 0%, #e63946 100%); } .card-front { display: flex; flex-direction: column; justify-content: space-between; padding: 20px 24px 18px; } .card-top-row { display: flex; align-items: center; justify-content: space-between; } .card-chip { width: 42px; height: 32px; background: linear-gradient(135deg, #c8a84b 0%, #f0d060 40%, #c8a84b 100%); border-radius: 5px; position: relative; flex-shrink: 0; } .card-chip::before { content: ''; position: absolute; inset: 9px 0; border-top: 1.5px solid rgba(0, 0, 0, 0.25); border-bottom: 1.5px solid rgba(0, 0, 0, 0.25); } .card-chip::after { content: ''; position: absolute; inset: 0 13px; border-left: 1.5px solid rgba(0, 0, 0, 0.2); border-right: 1.5px solid rgba(0, 0, 0, 0.2); border-radius: 2px; } .card-type-label { font-size: 1rem; font-weight: 700; letter-spacing: 0.06em; font-style: italic; opacity: 0.95; min-width: 52px; text-align: end; text-transform: uppercase; } .card--mastercard .card-type-label { position: relative; width: 52px; height: 32px; font-size: 0; } .card--mastercard .card-type-label::before, .card--mastercard .card-type-label::after { content: ''; position: absolute; top: 50%; transform: translateY(-50%); width: 28px; height: 28px; border-radius: 50%; } .card--mastercard .card-type-label::before { background: #eb001b; inset-inline-start: 0; } .card--mastercard .card-type-label::after { background: #f79e1b; inset-inline-start: 16px; mix-blend-mode: multiply; } .card-number-display { font-family: var(--secure-card-font); font-size: clamp(0.85rem, 2.5vw, 1.1rem); letter-spacing: 0.18em; text-shadow: 0 1px 3px rgba(0, 0, 0, 0.4); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .card-bottom-row { display: flex; justify-content: space-between; align-items: flex-end; gap: var(--secure-ui-space-3, 0.75rem); } .card-field-label { font-size: 0.6rem; text-transform: uppercase; letter-spacing: 0.12em; opacity: 0.7; margin-block-end: 2px; } .card-name-display { font-size: clamp(0.7rem, 2vw, 0.85rem); letter-spacing: 0.06em; font-weight: 500; text-transform: uppercase; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 160px; } .card-expiry-display { font-family: var(--secure-card-font); font-size: 0.85rem; letter-spacing: 0.1em; white-space: nowrap; } .card-back { display: flex; flex-direction: column; gap: var(--secure-ui-space-3, 0.75rem); } .card-strip { width: 100%; height: 40px; background: #1a1a1a; margin-block-start: 28px; flex-shrink: 0; } .card-cvc-area { display: flex; flex-direction: column; align-items: flex-end; padding-inline-end: 24px; gap: 4px; } .card-cvc-label { font-size: 0.6rem; text-transform: uppercase; letter-spacing: 0.1em; opacity: 0.7; } .card-cvc-display { background: #fff; color: #1a1a1a; font-family: var(--secure-card-font); font-size: 0.85rem; letter-spacing: 0.2em; padding: 4px 10px; border-radius: 3px; min-width: 52px; text-align: center; } .card-fields { display: flex; flex-direction: column; gap: var(--secure-ui-space-4, 1rem); } .card-legend { font-size: var(--secure-ui-font-size-sm, 0.875rem); font-weight: var(--secure-ui-font-weight-semibold, 600); color: var(--secure-ui-color-neutral-700, #374151); margin-block-end: var(--secure-ui-space-1, 0.25rem); } .field-row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--secure-ui-space-4, 1rem); } .field-group { display: flex; flex-direction: column; gap: var(--secure-ui-space-1, 0.25rem); position: relative; } .field-label { font-size: var(--secure-ui-font-size-sm, 0.875rem); font-weight: var(--secure-ui-font-weight-medium, 500); color: var(--secure-ui-color-neutral-700, #374151); line-height: var(--secure-ui-line-height-tight, 1.25); } .input-wrapper { position: relative; } .card-input { width: 100%; box-sizing: border-box; padding: var(--secure-ui-input-padding-y, 0.625rem) var(--secure-ui-input-padding-x, 0.75rem); font-family: var(--secure-ui-font-family-sans, system-ui, sans-serif); font-size: var(--secure-ui-font-size-base, 1rem); line-height: var(--secure-ui-line-height-normal, 1.5); color: var(--secure-ui-input-color, #111827); background: var(--secure-ui-input-bg, #fff); border: var(--secure-ui-border-width, 1px) solid var(--secure-ui-input-border-color, #d1d5db); border-radius: var(--secure-ui-input-border-radius, 6px); outline: none; transition: border-color var(--secure-ui-transition-fast, 150ms) ease, box-shadow var(--secure-ui-transition-fast, 150ms) ease; appearance: none; -webkit-appearance: none; } .card-input:focus { border-color: var(--secure-ui-color-primary-500, #6366f1); box-shadow: 0 0 0 3px var(--secure-ui-color-primary-100, rgba(99, 102, 241, 0.2)); } .card-input[aria-invalid='true'] { border-color: var(--secure-ui-color-error-500, #ef4444) !important; box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.15); } .card-input:disabled { background: var(--secure-ui-input-disabled-bg, #f3f4f6); color: var(--secure-ui-color-neutral-400, #9ca3af); cursor: not-allowed; } .card-number-input { font-family: var(--secure-card-font); letter-spacing: 0.06em; } .cvc-input::-ms-reveal, .cvc-input::-ms-clear { display: none; } .error-container { font-size: var(--secure-ui-font-size-xs, 0.75rem); color: var(--secure-ui-color-error-600, #dc2626); line-height: var(--secure-ui-line-height-tight, 1.25); min-height: 0; max-height: 3rem; overflow: hidden; transition: max-height var(--secure-ui-transition-normal, 250ms) ease, opacity var(--secure-ui-transition-fast, 150ms) ease; opacity: 1; } .error-container.hidden { max-height: 0; opacity: 0; } @media (prefers-color-scheme: dark) { .card-legend { color: var(--secure-ui-color-neutral-200, #e5e7eb); } .field-label { color: var(--secure-ui-color-neutral-200, #e5e7eb); } .card-input { color: var(--secure-ui-input-color, #f9fafb); background: var(--secure-ui-input-bg, #1f2937); border-color: var(--secure-ui-input-border-color, #374151); } .card-input:disabled { background: #111827; color: #6b7280; } .card-cvc-display { background: #f9fafb; color: #111827; } } @media (prefers-reduced-motion: reduce) { .card { transition: none; } .card-input { transition: none; } .error-container { transition: none; } } @media (max-width: 400px) { .field-row { grid-template-columns: 1fr; } }"),this.#e.addEventListener("input",m=>{this.recordTelemetryInput(m),this.#S(m)}),this.#e.addEventListener("focus",()=>{this.recordTelemetryFocus(),this.#k()}),this.#e.addEventListener("blur",()=>{this.recordTelemetryBlur(),this.#z()}),this.#s.addEventListener("input",m=>{this.recordTelemetryInput(m),this.#$(m)}),this.#s.addEventListener("focus",()=>{this.recordTelemetryFocus(),this.#L(!1)}),this.#s.addEventListener("blur",()=>{this.recordTelemetryBlur(),this.#R()}),this.#i.addEventListener("input",m=>{this.recordTelemetryInput(m),this.#M(m)}),this.#i.addEventListener("focus",()=>{this.recordTelemetryFocus(),this.#L(!0)}),this.#i.addEventListener("blur",()=>{this.recordTelemetryBlur(),this.#D()}),this.#r.addEventListener("input",m=>{this.recordTelemetryInput(m),this.#H(m)}),this.#r.addEventListener("focus",()=>{this.recordTelemetryFocus(),this.#L(!1)}),this.#r.addEventListener("blur",()=>{this.recordTelemetryBlur(),this.#V()}),e.appendChild(s),e}#C(e){let t=document.createElement("div");t.className="field-group";let i=document.createElement("label");i.htmlFor=e,i.className="field-label";let r=document.createElement("div");r.className="input-wrapper",r.setAttribute("part","wrapper");let s=document.createElement("div");return s.className="error-container hidden",s.setAttribute("role","alert"),s.setAttribute("part","error"),t.appendChild(i),t.appendChild(r),t.appendChild(s),t}handleAttributeChange(e,t,i){if(this.shadowRoot)switch(e){case"disabled":{let r=i!==null;this.#e&&(this.#e.disabled=r),this.#s&&(this.#s.disabled=r),this.#i&&(this.#i.disabled=r),this.#r&&(this.#r.disabled=r);break}case"show-name":{let r=this.shadowRoot.querySelector(`#${this.#w}-name-group`);r&&(r.hidden=i===null);break}}}#S(e){let t=e.target,i=t.value.replace(/\D/g,""),r=this.#x?.type;this.#x=J(i);let s=this.#x?.format??[4,4,4,4],a=s.reduce((n,o)=>n+o,0);if(this.#m=i.slice(0,a),t.value=x(this.#m,s),this.#x?.type!==r){let n=a+s.length-1;t.setAttribute("maxlength",String(n));let o=this.#x?.cvcLength??3;this.#i&&this.#i.setAttribute("maxlength",String(o)),this.#P()}this.#a&&(this.#a.textContent=t.value||x("\u2022".repeat(a),s)),this.#A(this.#h),this.#N(),this.#F()}#k(){if(this.#e&&this.#m){let e=this.#x?.format??[4,4,4,4],t=x(this.#m,e);this.#e.value=t,this.#a&&(this.#a.textContent=t)}this.#L(!1),this.#A(this.#h)}#z(){let e=this.checkRateLimit();if(!e.allowed){this.#T(this.#h,`Too many attempts. Try again in ${Math.ceil(e.retryAfter/1e3)}s.`);return}this.#m?B(this.#m)?(this.#A(this.#h),this.#e?.removeAttribute("aria-invalid")):(this.#T(this.#h,"Invalid card number"),this.#e?.setAttribute("aria-invalid","true")):(this.#T(this.#h,"Card number is required"),this.#e?.setAttribute("aria-invalid","true")),this.#I(),this.audit("card-number-blur",{cardType:this.#x?.type??"unknown"})}#I(){let e=this.#x?.format??[4,4,4,4],t=X(this.#m,e);this.#e&&(this.#e.value=t),this.#a&&(this.#a.textContent=t)}#$(e){let t=e.target,i=t.value.replace(/\D/g,"").slice(0,4),r=i.length>2?`${i.slice(0,2)}/${i.slice(2)}`:i;t.value=r,this.#v=r,this.#n&&(this.#n.textContent=r||"MM/YY"),this.#A(this.#d),this.#N(),this.#F()}#R(){let e=this.#v.split("/");if(!this.#v){this.#T(this.#d,"Expiry date is required"),this.#s?.setAttribute("aria-invalid","true");return}let t=parseInt(e[0]??"",10),i=parseInt(e[1]??"",10);isNaN(t)||isNaN(i)||t<1||t>12||(e[1]??"").length<2?(this.#T(this.#d,"Enter a valid expiry date (MM/YY)"),this.#s?.setAttribute("aria-invalid","true")):Y(t,i)?(this.#A(this.#d),this.#s?.removeAttribute("aria-invalid")):(this.#T(this.#d,"This card has expired"),this.#s?.setAttribute("aria-invalid","true")),this.audit("card-expiry-blur",{})}#M(e){let t=e.target,i=t.value.replace(/\D/g,""),r=this.#x?.cvcLength??3;this.#g=i.slice(0,r),t.value=this.#g,this.#c&&(this.#c.textContent=this.#g.length>0?"\u2022".repeat(this.#g.length):"\u2022\u2022\u2022"),this.#A(this.#l),this.#F()}#D(){let e=this.#x?.cvcLength??3;this.#g?this.#g.length<e?(this.#T(this.#l,`Security code must be ${e} digits`),this.#i?.setAttribute("aria-invalid","true")):(this.#A(this.#l),this.#i?.removeAttribute("aria-invalid")):(this.#T(this.#l,"Security code is required"),this.#i?.setAttribute("aria-invalid","true")),this.#L(!1),this.audit("card-cvc-blur",{})}#H(e){let t=e.target,i=t.value.replace(/[^a-zA-Z\s\-']/g,"").slice(0,50);t.value=i,this.#E=i,this.#o&&(this.#o.textContent=i.toUpperCase()||"FULL NAME"),this.#A(this.#p),this.#N(),this.#F()}#V(){this.hasAttribute("show-name")&&(this.#E.trim()?(this.#A(this.#p),this.#r?.removeAttribute("aria-invalid")):(this.#T(this.#p,"Cardholder name is required"),this.#r?.setAttribute("aria-invalid","true")))}#L(e){this.#t?.classList.toggle("is-flipped",e)}#P(){if(!this.#t)return;for(let t of U)this.#t.classList.remove(`card--${t.type}`);let e=this.#x?.type;e&&this.#t.classList.add(`card--${e}`),this.#u&&(this.#u.textContent=this.#x?.label??"")}#T(e,t){if(!e)return;e.textContent="";let i=document.createElement("span");i.textContent=t,e.appendChild(i),e.classList.remove("hidden")}#A(e){e&&(e.textContent="",e.classList.add("hidden"))}#q(){let e=this.getAttribute("name");e&&(this.#b=document.createElement("input"),this.#b.type="hidden",this.#b.name=e,this.appendChild(this.#b),this.#f=document.createElement("input"),this.#f.type="hidden",this.#f.name=`${e}-expiry`,this.appendChild(this.#f),this.#y=document.createElement("input"),this.#y.type="hidden",this.#y.name=`${e}-holder`,this.appendChild(this.#y))}#N(){this.#b&&(this.#b.value=this.#m.slice(-4)),this.#f&&(this.#f.value=this.#v),this.#y&&(this.#y.value=this.#E)}#F(){let[e,t]=this.#v.split("/");this.dispatchEvent(new CustomEvent("secure-card",{bubbles:!0,composed:!0,detail:{name:this.getAttribute("name")??"",cardType:this.#x?.type??"unknown",last4:this.#m.slice(-4),expiryMonth:parseInt(e??"0",10)||0,expiryYear:parseInt(t??"0",10)||0,cardholderName:this.#E,valid:this.valid,tier:this.securityTier}}))}disconnectedCallback(){this.#m="",this.#g="",this.#v="",this.#E="",this.#e&&(this.#e.value=""),this.#s&&(this.#s.value=""),this.#i&&(this.#i.value=""),this.#r&&(this.#r.value=""),this.#b&&(this.#b.value=""),this.#f&&(this.#f.value=""),this.#y&&(this.#y.value=""),super.disconnectedCallback()}get valid(){let e=this.#m.length>=12&&B(this.#m),[t,i]=this.#v.split("/"),r=parseInt(t??"",10),s=parseInt(i??"",10),a=!isNaN(r)&&!isNaN(s)&&r>=1&&r<=12&&(i??"").length>=2&&Y(r,s),n=this.#x?.cvcLength??3,o=this.#g.length===n,u=!this.hasAttribute("show-name")||this.#E.trim().length>0;return e&&a&&o&&u}get cardType(){return this.#x?.type??"unknown"}get last4(){return this.#m.slice(-4)}get name(){return this.getAttribute("name")??""}getCardData(){return this.valid?{number:this.#m,expiry:this.#v,cvc:this.#g,name:this.#E}:null}reset(){this.#m="",this.#g="",this.#v="",this.#E="",this.#x=null,this.#e&&(this.#e.value=""),this.#s&&(this.#s.value=""),this.#i&&(this.#i.value=""),this.#r&&(this.#r.value=""),this.#N(),this.#L(!1),this.#P();let e=[4,4,4,4];this.#a&&(this.#a.textContent=x("\u2022".repeat(16),e)),this.#n&&(this.#n.textContent="MM/YY"),this.#o&&(this.#o.textContent="FULL NAME"),this.#c&&(this.#c.textContent="\u2022\u2022\u2022"),this.#A(this.#h),this.#A(this.#d),this.#A(this.#l),this.#A(this.#p),this.audit("card-reset",{})}focus(){this.#e?.focus()}};customElements.define("secure-card",$);var R=class extends HTMLElement{static get observedAttributes(){return["signing-key"]}#e={mouseMovementDetected:!1,keyboardActivityDetected:!1,injectedScriptCount:0,domMutationDetected:!1,pointerType:"none",firstKeystrokeAt:-1,threatSignals:[]};#s=0;#i=null;#r=new Set;#t=null;#a="";#n=()=>{this.#e.mouseMovementDetected=!0};#o=()=>{this.#e.keyboardActivityDetected=!0,this.#e.firstKeystrokeAt<0&&(this.#e.firstKeystrokeAt=performance.now())};#u=e=>{this.#e.pointerType=e.pointerType};#c=e=>{this.#y(e)};#h=e=>{this.#e.threatSignals.push(e.detail)};connectedCallback(){this.#s=performance.now(),document.querySelectorAll("script").forEach(e=>this.#r.add(e)),this.#d(),this.#l()}disconnectedCallback(){this.#i?.disconnect(),this.#i=null,this.#p(),this.#t=null,this.#a=""}attributeChangedCallback(e,t,i){e==="signing-key"&&i!==this.#a&&(this.#t=null,this.#a="")}#d(){this.#i=new MutationObserver(e=>{for(let t of e)if(t.type==="childList")for(let i of Array.from(t.addedNodes))i.tagName==="SCRIPT"&&!this.#r.has(i)&&(this.#e.injectedScriptCount++,this.#e.domMutationDetected=!0,this.#r.add(i))}),this.#i.observe(document.documentElement,{childList:!0,subtree:!0})}#l(){document.addEventListener("mousemove",this.#n,{passive:!0}),document.addEventListener("keydown",this.#o,{passive:!0}),document.addEventListener("pointerdown",this.#u,{passive:!0}),this.addEventListener("secure-form-submit",this.#c),this.addEventListener("secure-threat-detected",this.#h)}#p(){document.removeEventListener("mousemove",this.#n),document.removeEventListener("keydown",this.#o),document.removeEventListener("pointerdown",this.#u),this.removeEventListener("secure-form-submit",this.#c),this.removeEventListener("secure-threat-detected",this.#h)}collectSignals(){let e=navigator,t=e.webdriver===!0||Object.prototype.hasOwnProperty.call(e,"webdriver"),i=navigator.userAgent,r=i.includes("HeadlessChrome")||i.includes("Headless")||typeof window.chrome>"u"&&i.includes("Chrome"),s=screen.width===0||screen.height===0||screen.width<100&&screen.height<100,a=performance.now(),n=this.#e.firstKeystrokeAt>=0?Math.round(this.#e.firstKeystrokeAt-this.#s):-1,o=Math.round(a-this.#s);return{webdriverDetected:t,headlessDetected:r,domMutationDetected:this.#e.domMutationDetected,injectedScriptCount:this.#e.injectedScriptCount,suspiciousScreenSize:s,pointerType:this.#e.pointerType,mouseMovementDetected:this.#e.mouseMovementDetected,keyboardActivityDetected:this.#e.keyboardActivityDetected,pageLoadToFirstKeystroke:n,loadToSubmit:o,threatSignals:this.#e.threatSignals.length>0?[...this.#e.threatSignals]:void 0}}async sign(e){let t=this.#b(),i=new Date().toISOString(),r=this.getAttribute("signing-key")??"",s=`${t}.${i}.${JSON.stringify(e)}`,a=await this.#f(r,s);return{nonce:t,issuedAt:i,environment:e,signature:a}}#b(){let e=new Uint8Array(16);return crypto.getRandomValues(e),Array.from(e,t=>t.toString(16).padStart(2,"0")).join("")}async#f(e,t){if(!crypto.subtle)return"";let i=new TextEncoder;(this.#t===null||this.#a!==e)&&(this.#t=await crypto.subtle.importKey("raw",i.encode(e),{name:"HMAC",hash:"SHA-256"},!1,["sign"]),this.#a=e);let r=await crypto.subtle.sign("HMAC",this.#t,i.encode(t));return Array.from(new Uint8Array(r),s=>s.toString(16).padStart(2,"0")).join("")}async#y(e){let t=e.detail;if(t?.telemetry)try{let i=this.collectSignals(),r=await this.sign(i);t.telemetry._env=r}catch{}}getEnvironmentalSignals(){return this.collectSignals()}};customElements.define("secure-telemetry-provider",R);var V=class extends p{#e=null;#s=null;#i=null;#r=null;#t=null;#a=null;#n=null;#o="";#u="";#c=!1;#h=!1;#d=!1;#l=null;#p=`secure-password-confirm-${Math.random().toString(36).substring(2,11)}`;connectedCallback(){this.removeAttribute("security-tier"),super.connectedCallback()}static get observedAttributes(){return[...super.observedAttributes,"name","label","password-label","confirm-label","required","minlength"]}render(){let e=document.createDocumentFragment(),t=document.createElement("div");t.className="container",t.setAttribute("part","container");let i=this.getAttribute("label");if(i){let n=document.createElement("div");n.className="group-label",n.textContent=this.sanitizeValue(i),t.appendChild(n)}let r=this.hasAttribute("required"),s=this.#b({inputPart:"password-input",wrapperPart:"password-wrapper",labelPart:"password-label",errorPart:"password-error",togglePart:"password-toggle",labelText:this.getAttribute("password-label")??"New Password",inputId:`${this.#p}-password`,errorId:`${this.#p}-password-error`,isRequired:r});this.#e=s.querySelector('[part="password-input"]'),this.#a=s.querySelector('[part="password-toggle"]'),this.#i=s.querySelector('[part="password-error"]');let a=this.#b({inputPart:"confirm-input",wrapperPart:"confirm-wrapper",labelPart:"confirm-label",errorPart:"confirm-error",togglePart:"confirm-toggle",labelText:this.getAttribute("confirm-label")??"Confirm Password",inputId:`${this.#p}-confirm`,errorId:`${this.#p}-confirm-error`,isRequired:r});return this.#s=a.querySelector('[part="confirm-input"]'),this.#n=a.querySelector('[part="confirm-toggle"]'),this.#r=a.querySelector('[part="confirm-error"]'),this.#t=document.createElement("div"),this.#t.setAttribute("part","match-indicator"),this.#t.className="match-indicator",this.#t.setAttribute("aria-hidden","true"),t.appendChild(s),t.appendChild(a),t.appendChild(this.#t),this.#f(),this.#y(),this.#m(),this.#k(),this.addComponentStyles('.container { display: flex; flex-direction: column; gap: var(--secure-ui-form-gap); font-family: var(--secure-ui-font-family-base); } .group-label { font-size: var(--secure-ui-label-font-size); font-weight: var(--secure-ui-label-font-weight); color: var(--secure-ui-label-color); margin-bottom: var(--secure-ui-space-1); } .field-section { display: flex; flex-direction: column; gap: var(--secure-ui-form-label-margin-bottom); } label { font-size: var(--secure-ui-label-font-size); font-weight: var(--secure-ui-label-font-weight); color: var(--secure-ui-label-color); } .input-wrapper { position: relative; display: flex; align-items: center; } input[type="password"], input[type="text"] { flex: 1; height: var(--secure-ui-input-height); padding: var(--secure-ui-input-padding-y) var(--secure-ui-input-padding-x); padding-inline-end: calc(var(--secure-ui-input-padding-x) * 3.5); font-family: var(--secure-ui-font-family-base); font-size: var(--secure-ui-input-font-size); color: var(--secure-ui-input-text-color); background-color: var(--secure-ui-input-bg); border: var(--secure-ui-input-border-width) solid var(--secure-ui-input-border-color); border-radius: var(--secure-ui-input-border-radius); box-sizing: border-box; transition: border-color var(--secure-ui-transition-base), box-shadow var(--secure-ui-transition-base); } input:hover:not(:disabled) { border-color: var(--secure-ui-input-border-color-hover); } input:focus { outline: none; border-color: var(--secure-ui-input-border-color-focus); box-shadow: var(--secure-ui-shadow-focus); } input[aria-invalid="true"] { border-color: var(--secure-ui-color-error) !important; } input[aria-invalid="true"]:focus { box-shadow: var(--secure-ui-shadow-focus-error); } .toggle-btn { position: absolute; inset-inline-end: var(--secure-ui-space-2); display: flex; align-items: center; justify-content: center; background: none; border: none; cursor: pointer; color: var(--secure-ui-color-text-secondary); padding: var(--secure-ui-space-1); border-radius: var(--secure-ui-border-radius-sm); line-height: 1; transition: color var(--secure-ui-transition-base); } .toggle-btn:hover { color: var(--secure-ui-color-text-primary); } .toggle-btn:focus-visible { outline: 2px solid var(--secure-ui-input-border-color-focus); outline-offset: 2px; } .toggle-btn:active .eye-icon { transform: scale(0.85); } .eye-icon { display: block; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; transition: transform 0.15s ease; overflow: visible; } .eye-outline { transition: d 0.2s ease; } .eye-pupil { transform-origin: 12px 12px; transition: opacity 0.2s ease, transform 0.2s ease; } .eye-slash { stroke-dasharray: 26; stroke-dashoffset: 26; transition: stroke-dashoffset 0.3s ease; } .toggle-btn.is-visible .eye-pupil { opacity: 0; transform: scale(0.2); } .toggle-btn.is-visible .eye-slash { stroke-dashoffset: 0; } .error-container { font-size: var(--secure-ui-error-font-size); color: var(--secure-ui-error-color); line-height: var(--secure-ui-line-height-normal); overflow: hidden; max-height: 40px; opacity: 1; transition: all 0.2s ease-in-out; } .error-container.hidden { max-height: 0; opacity: 0; pointer-events: none; } .match-indicator { font-size: var(--secure-ui-font-size-sm); line-height: var(--secure-ui-line-height-normal); min-height: 1.25em; } .match-indicator.matched { color: var(--secure-ui-color-success, #2e7d32); } .match-indicator.mismatched { color: var(--secure-ui-color-error); } @media (prefers-reduced-motion: reduce) { input, .error-container, .eye-icon, .eye-pupil, .eye-slash { transition: none !important; } }'),e.appendChild(t),e}#b(e){let t=document.createElement("div");t.className="field-section";let i=document.createElement("label");i.setAttribute("part",e.labelPart),i.htmlFor=e.inputId,i.textContent=this.sanitizeValue(e.labelText);let r=document.createElement("div");r.className="input-wrapper",r.setAttribute("part",e.wrapperPart);let s=document.createElement("input");s.id=e.inputId,s.type="password",s.autocomplete="new-password",s.setAttribute("part",e.inputPart),s.setAttribute("aria-describedby",e.errorId),e.isRequired&&(s.required=!0,s.setAttribute("aria-required","true"));let a=document.createElement("button");a.type="button",a.className="toggle-btn",a.setAttribute("part",e.togglePart),a.setAttribute("aria-label","Show password"),a.appendChild(this.#g()),r.appendChild(s),r.appendChild(a);let n=document.createElement("div");return n.id=e.errorId,n.setAttribute("part",e.errorPart),n.setAttribute("role","alert"),n.className="error-container hidden",t.appendChild(i),t.appendChild(r),t.appendChild(n),t}#f(){this.#e.addEventListener("focus",()=>{this.recordTelemetryFocus()}),this.#e.addEventListener("input",e=>{this.recordTelemetryInput(e),this.#o=this.#e.value,this.detectInjection(this.#o,this.getAttribute("name")??""),this.#c&&this.#x(),this.dispatchEvent(new CustomEvent("secure-input",{detail:{name:this.getAttribute("name")??"",field:"password"},bubbles:!0,composed:!0}))}),this.#e.addEventListener("blur",()=>{this.recordTelemetryBlur(),this.#v()})}#y(){this.#s.addEventListener("input",()=>{this.#u=this.#s.value,this.detectInjection(this.#u,this.getAttribute("name")??""),this.#c&&this.#x()}),this.#s.addEventListener("blur",()=>{this.#c=!0,this.#u=this.#s.value,this.#x()})}#m(){this.#a.addEventListener("click",()=>{this.#h=!this.#h,this.#e.type=this.#h?"text":"password",this.#a.classList.toggle("is-visible",this.#h),this.#a.setAttribute("aria-label",this.#h?"Hide password":"Show password")}),this.#n.addEventListener("click",()=>{this.#d=!this.#d,this.#s.type=this.#d?"text":"password",this.#n.classList.toggle("is-visible",this.#d),this.#n.setAttribute("aria-label",this.#d?"Hide confirm password":"Show confirm password")})}#g(){let e="http://www.w3.org/2000/svg",t=document.createElementNS(e,"svg");t.setAttribute("viewBox","0 0 24 24"),t.setAttribute("aria-hidden","true"),t.setAttribute("class","eye-icon"),t.setAttribute("width","18"),t.setAttribute("height","18");let i=document.createElementNS(e,"path");i.setAttribute("class","eye-outline"),i.setAttribute("d","M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z");let r=document.createElementNS(e,"circle");r.setAttribute("class","eye-pupil"),r.setAttribute("cx","12"),r.setAttribute("cy","12"),r.setAttribute("r","3");let s=document.createElementNS(e,"line");return s.setAttribute("class","eye-slash"),s.setAttribute("x1","3"),s.setAttribute("y1","3"),s.setAttribute("x2","21"),s.setAttribute("y2","21"),t.append(i,r,s),t}#v(){let e=this.#E(this.#o);e?this.#w(this.#i,this.#e,e):this.#C(this.#i,this.#e)}#E(e){return e?e.length<8?"Password must be at least 8 characters":/[a-z]/.test(e)?/[A-Z]/.test(e)?/[0-9]/.test(e)?/[^a-zA-Z0-9]/.test(e)?null:"Password must include a special character":"Password must include a number":"Password must include an uppercase letter":"Password must include a lowercase letter":null}#x(){let e=this.#o.length>0&&this.#o===this.#u;if(this.#z(e),this.#S(e),e)this.#C(this.#r,this.#s),this.dispatchEvent(new CustomEvent("secure-password-match",{detail:{name:this.getAttribute("name")??"",matched:!0},bubbles:!0,composed:!0}));else{let t=this.#u.length>0?"Passwords do not match":"Please confirm your password";this.#w(this.#r,this.#s,t),this.dispatchEvent(new CustomEvent("secure-password-mismatch",{detail:{name:this.getAttribute("name")??"",matched:!1},bubbles:!0,composed:!0}))}}#w(e,t,i){e.textContent=i,e.classList.remove("hidden"),t.setAttribute("aria-invalid","true")}#C(e,t){e.classList.add("hidden"),e.textContent="",t.removeAttribute("aria-invalid")}#S(e){this.#t&&(this.#t.className=`match-indicator ${e?"matched":"mismatched"}`,this.#t.textContent=e?"\u2713 Passwords match":"\u2717 Passwords do not match")}#k(){let e=this.getAttribute("name");!e||this.closest("secure-form")||(this.#l=document.createElement("input"),this.#l.type="hidden",this.#l.name=e,this.#l.value="",this.appendChild(this.#l))}#z(e){this.#l&&(this.#l.value=e?this.#o:"")}getPasswordValue(){return!this.#o||!this.#u||this.#o!==this.#u?null:this.#o}get valid(){return!this.#o||!this.#u||this.#o!==this.#u?!1:this.#E(this.#o)===null}get name(){return this.getAttribute("name")??""}disconnectedCallback(){super.disconnectedCallback(),this.#o="",this.#u="",this.#e&&(this.#e.value=""),this.#s&&(this.#s.value=""),this.#l&&(this.#l.value="")}};customElements.define("secure-password-confirm",V);export{Z as CSP_RECOMMENDATIONS,G as SECURITY_HEADERS,p as SecureBaseComponent,$ as SecureCard,H as SecureDateTime,D as SecureFileUpload,M as SecureForm,k as SecureInput,V as SecurePasswordConfirm,I as SecureSelect,F as SecureSubmitButton,N as SecureTable,R as SecureTelemetryProvider,z as SecureTextarea,c as SecurityTier,S as TIER_CONFIG,O as compareTiers,W as getMoreSecureTier,g as getTierConfig,_ as isValidTier};
67
+ /**
68
+ * @fileoverview Security Configuration and Tier Definitions
69
+ *
70
+ * This module defines the four security tiers that govern all component behavior
71
+ * in the Secure-UI library. Each tier represents a different level of data sensitivity
72
+ * and applies corresponding security controls.
73
+ *
74
+ * Security Philosophy:
75
+ * - Defense in depth: Multiple layers of protection at each tier
76
+ * - Fail secure: Default to highest security when tier is ambiguous
77
+ * - Progressive enhancement: All tiers work without JavaScript
78
+ * - Zero trust: Always validate, never assume data is safe
79
+ *
80
+ * @module security-config
81
+ * @license MIT
82
+ */
83
+ /**
84
+ * @fileoverview Base Component Class for Secure-UI
85
+ *
86
+ * This module provides the foundational class that all Secure-UI web components
87
+ * extend. It implements core security features, progressive enhancement,
88
+ * and standardized lifecycle management.
89
+ *
90
+ * Security Features:
91
+ * - Closed Shadow DOM (prevents external JavaScript access)
92
+ * - Automatic XSS sanitization
93
+ * - Security tier enforcement
94
+ * - Audit logging infrastructure
95
+ * - Rate limiting support
96
+ * - Progressive enhancement (works without JS)
97
+ *
98
+ * @module base-component
99
+ * @license MIT
100
+ */
101
+ /**
102
+ * @fileoverview Secure Input Component
103
+ *
104
+ * A security-first input field component that implements progressive enhancement,
105
+ * tier-based validation, masking, and audit logging.
106
+ *
107
+ * Progressive Enhancement Strategy:
108
+ * 1. Without JavaScript: Falls back to native HTML5 input with attributes
109
+ * 2. With JavaScript: Enhances with masking, real-time validation, rate limiting
110
+ *
111
+ * Usage:
112
+ * <secure-input
113
+ * security-tier="critical"
114
+ * name="password"
115
+ * label="Password"
116
+ * type="password"
117
+ * required
118
+ * ></secure-input>
119
+ *
120
+ * Security Features:
121
+ * - XSS prevention via sanitization
122
+ * - Configurable masking based on security tier
123
+ * - Rate limiting for sensitive/critical tiers
124
+ * - Autocomplete control based on tier
125
+ * - Comprehensive audit logging
126
+ * - Visual security indicators
127
+ *
128
+ * @module secure-input
129
+ * @license MIT
130
+ */
131
+ /**
132
+ * @fileoverview Secure Textarea Component
133
+ *
134
+ * A security-first textarea component that implements progressive enhancement,
135
+ * tier-based validation, character counting, and audit logging.
136
+ *
137
+ * Progressive Enhancement Strategy:
138
+ * 1. Without JavaScript: Falls back to native HTML5 textarea with attributes
139
+ * 2. With JavaScript: Enhances with real-time validation, character limits, rate limiting
140
+ *
141
+ * Usage:
142
+ * <secure-textarea
143
+ * security-tier="sensitive"
144
+ * name="bio"
145
+ * label="Biography"
146
+ * rows="5"
147
+ * required
148
+ * ></secure-textarea>
149
+ *
150
+ * Security Features:
151
+ * - XSS prevention via sanitization
152
+ * - Character counting and limits based on security tier
153
+ * - Rate limiting for sensitive/critical tiers
154
+ * - Autocomplete control based on tier
155
+ * - Comprehensive audit logging
156
+ * - Visual security indicators
157
+ *
158
+ * @module secure-textarea
159
+ * @license MIT
160
+ */
161
+ /**
162
+ * @fileoverview Secure Select Component
163
+ *
164
+ * A security-first select dropdown component that implements progressive enhancement,
165
+ * tier-based validation, and audit logging.
166
+ *
167
+ * Progressive Enhancement Strategy:
168
+ * 1. Without JavaScript: Falls back to native HTML5 select with options
169
+ * 2. With JavaScript: Enhances with validation, audit logging, rate limiting
170
+ *
171
+ * Usage:
172
+ * <secure-select
173
+ * security-tier="authenticated"
174
+ * name="country"
175
+ * label="Country"
176
+ * required
177
+ * >
178
+ * <option value="">Select a country</option>
179
+ * <option value="us">United States</option>
180
+ * <option value="uk">United Kingdom</option>
181
+ * </secure-select>
182
+ *
183
+ * Multiple selection:
184
+ * <secure-select label="Languages" name="langs" multiple size="4">
185
+ * <option value="en">English</option>
186
+ * <option value="es">Spanish</option>
187
+ * </secure-select>
188
+ *
189
+ * Security Features:
190
+ * - XSS prevention via sanitization
191
+ * - Option value validation
192
+ * - Rate limiting for sensitive/critical tiers
193
+ * - Comprehensive audit logging
194
+ * - Visual security indicators
195
+ *
196
+ * @module secure-select
197
+ * @license MIT
198
+ */
199
+ /**
200
+ * @fileoverview Secure Form Component
201
+ *
202
+ * A security-first form component that implements CSRF protection, automatic
203
+ * field collection, validation, and comprehensive audit logging.
204
+ *
205
+ * Progressive Enhancement Strategy:
206
+ * 1. Without JavaScript: Falls back to native HTML5 form submission
207
+ * 2. With JavaScript: Enhances with CSRF tokens, validation, secure submission
208
+ *
209
+ * Usage:
210
+ * <secure-form
211
+ * security-tier="sensitive"
212
+ * action="/api/submit"
213
+ * method="POST"
214
+ * csrf-token="your-csrf-token"
215
+ * >
216
+ * <secure-input name="email" label="Email" required></secure-input>
217
+ * <button type="submit">Submit</button>
218
+ * </secure-form>
219
+ *
220
+ * Security Features:
221
+ * - CSRF token injection and validation
222
+ * - Automatic secure field collection
223
+ * - XSS prevention via sanitization
224
+ * - Rate limiting on submission
225
+ * - Comprehensive audit logging
226
+ * - Secure headers for form submission
227
+ * - Double-submit cookie pattern support
228
+ *
229
+ * @module secure-form
230
+ * @license MIT
231
+ */
232
+ /**
233
+ * @fileoverview Secure File Upload Component
234
+ *
235
+ * A security-first file upload component that implements progressive enhancement,
236
+ * file type validation, size limits, scan hook integration, and audit logging.
237
+ *
238
+ * Progressive Enhancement Strategy:
239
+ * 1. Without JavaScript: Falls back to native HTML5 file input
240
+ * 2. With JavaScript: Enhances with validation, preview, drag-drop, security checks
241
+ *
242
+ * Usage:
243
+ * <secure-file-upload
244
+ * security-tier="sensitive"
245
+ * name="document"
246
+ * label="Upload Document"
247
+ * accept=".pdf,.doc,.docx"
248
+ * max-size="5242880"
249
+ * required
250
+ * ></secure-file-upload>
251
+ *
252
+ * Security Features:
253
+ * - File type validation (MIME type and extension)
254
+ * - File size limits based on security tier
255
+ * - Scan hook integration (e.g. server-side malware scanning)
256
+ * - Content validation before upload
257
+ * - Rate limiting on uploads
258
+ * - Comprehensive audit logging
259
+ * - Drag-and-drop with validation
260
+ * - Preview for safe file types
261
+ *
262
+ * @module secure-file-upload
263
+ * @license MIT
264
+ */
265
+ /**
266
+ * @fileoverview Secure Date/Time Picker Component
267
+ *
268
+ * A security-first date/time picker component that implements progressive enhancement,
269
+ * validation, and audit logging.
270
+ *
271
+ * Progressive Enhancement Strategy:
272
+ * 1. Without JavaScript: Falls back to native HTML5 date/time inputs
273
+ * 2. With JavaScript: Enhances with validation, range limits, audit logging
274
+ *
275
+ * Usage:
276
+ * <secure-datetime
277
+ * security-tier="authenticated"
278
+ * name="appointment"
279
+ * label="Appointment Date"
280
+ * type="datetime-local"
281
+ * min="2024-01-01T00:00"
282
+ * max="2024-12-31T23:59"
283
+ * required
284
+ * ></secure-datetime>
285
+ *
286
+ * Security Features:
287
+ * - Input sanitization and validation
288
+ * - Date range enforcement
289
+ * - Rate limiting for sensitive/critical tiers
290
+ * - Comprehensive audit logging
291
+ * - Timezone awareness
292
+ * - Format validation
293
+ *
294
+ * @module secure-datetime
295
+ * @license MIT
296
+ */
297
+ /**
298
+ * @fileoverview Secure Submit Button Component
299
+ *
300
+ * A security-aware form submit button that integrates with <secure-form>.
301
+ * The button's enabled/disabled state is driven by the parent form's security
302
+ * tier and field validation state.
303
+ *
304
+ * Tier behaviour:
305
+ * - public: Button enabled by default (validation.required = false)
306
+ * - authenticated: Button disabled until all required fields are valid
307
+ * - sensitive: Button disabled until all required fields are valid
308
+ * - critical: Button disabled until all required fields are valid
309
+ *
310
+ * Usage:
311
+ * <secure-form action="/api/data" method="POST" security-tier="sensitive">
312
+ * <secure-input label="Name" name="name" required></secure-input>
313
+ * <secure-submit-button label="Submit"></secure-submit-button>
314
+ * </secure-form>
315
+ *
316
+ * @module secure-submit-button
317
+ * @license MIT
318
+ */
319
+ /**
320
+ * @fileoverview SecureCard — composite credit card input Web Component
321
+ *
322
+ * Renders card number, expiry date, CVC, and optional cardholder name
323
+ * fields inside a closed Shadow DOM with a live 3D card preview.
324
+ *
325
+ * Security model:
326
+ * - Full PAN is never included in events, audit logs, or hidden inputs
327
+ * - CVC is never in events, hidden inputs, or audit logs
328
+ * - Card number masked to last-4 on blur
329
+ * - Security tier is locked to CRITICAL (immutable, fail-secure default)
330
+ * - Luhn validation on card number
331
+ * - Rate limiting and audit logging via SecureBaseComponent
332
+ * - All sensitive fields cleared on disconnectedCallback
333
+ *
334
+ * PCI note: These fields provide a secure UI layer only. Raw card data
335
+ * must be passed to a PCI-compliant payment processor's SDK — never to
336
+ * your own server. Use getCardData() exclusively for SDK tokenisation.
337
+ *
338
+ * @module secure-card
339
+ * @license MIT
340
+ */
341
+ /**
342
+ * @fileoverview Secure Telemetry Provider
343
+ *
344
+ * An optional overlay component that wraps a <secure-form> and enriches
345
+ * every submission with a signed environmental signals envelope.
346
+ *
347
+ * Architecture
348
+ * ────────────
349
+ * <secure-telemetry-provider signing-key="...">
350
+ * <secure-form ...>
351
+ * ...
352
+ * </secure-form>
353
+ * </secure-telemetry-provider>
354
+ *
355
+ * What it does
356
+ * ────────────
357
+ * 1. Detects automation / headless browser characteristics at page load.
358
+ * 2. Monitors the DOM for unexpected script injection via MutationObserver.
359
+ * 3. Records mouse movement, keyboard activity, and pointer type.
360
+ * 4. On `secure-form-submit`, generates a nonce-stamped envelope signed
361
+ * with the provided key using SubtleCrypto (HMAC-SHA-256).
362
+ * 5. Injects the envelope as `_env` on the event's telemetry payload so the
363
+ * server can verify it server-side.
364
+ *
365
+ * Security Notes
366
+ * ────────────
367
+ * - The signing key set via `signing-key` attribute is a *symmetric* secret
368
+ * that MUST be kept server-side as well; it is used here only as a weak
369
+ * integrity hint to detect casual forgery, not as a cryptographic proof.
370
+ * - For stronger guarantees, rotate the key per-session via a server nonce
371
+ * endpoint and inject it via script, not as a static HTML attribute.
372
+ * - All signals are heuristic — a sufficiently motivated attacker can spoof
373
+ * them. The value is raising the cost of scripted attacks, not guaranteeing
374
+ * detection.
375
+ *
376
+ * @module secure-telemetry-provider
377
+ * @license MIT
378
+ */
379
+ /**
380
+ * Secure-UI Component Library
381
+ *
382
+ * @module @anthropic/secure-ui-components
383
+ * @license MIT
384
+ */