tyrell-components 1.0.0-TC33 → 1.0.0-TC34

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.
package/dist/tyrell.js CHANGED
@@ -1,2 +1,2 @@
1
1
  /*! Tyrell Components | Components Only (NO Icons) | MIT License | https://github.com/gersak/tyrell */
2
- !function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((t="undefined"!=typeof globalThis?globalThis:t||self).Tyrell={})}(this,function(t){"use strict";class n{constructor(t){this.t=new Map,this.i=t,this.o()}o(){for(const[t,n]of Object.entries(this.i))void 0!==n.default&&this.t.set(t,n.default)}hasConfig(t){return t in this.i}updateProperty(t,n,e="property"){const i=this.i[t];if(!i)return null;const o=this.t.get(t),s=this.l(t,n,i);return this.h(t,s,i)?this.u(o,s)?null:(this.t.set(t,s),{name:t,oldValue:o,newValue:s,source:e}):null}l(t,n,e){if(e.coerce)return e.coerce(n);if(null==n)return e.default??null;switch(e.type){case"boolean":if("string"==typeof n){if(""===n)return!0;const t=n.toLowerCase().trim();return"false"!==t&&"0"!==t}return!!n;case"number":const t=+n;return isNaN(t)?e.default??0:t;case"string":return n+"";case"object":case"array":if("string"==typeof n)try{return JSON.parse(n)}catch{return e.default??("array"===e.type?[]:{})}return n;default:return n}}h(t,n,e){return!e.validate||e.validate(n)}u(t,n){if("object"!=typeof t||"object"!=typeof n)return t===n;if(null===t||null===n)return t===n;try{return JSON.stringify(t)===JSON.stringify(n)}catch{return!1}}get(t){return this.t.get(t)}getAll(){return Object.fromEntries(this.t)}getConfig(t){return this.i[t]}isVisual(t){return this.i[t]?.visual??!1}isFormValue(t){return this.i[t]?.formValue??!1}shouldEmitChange(t){return this.i[t]?.emitChange??!1}handleAlias(t,n){for(const[e,i]of Object.entries(this.i))if(i.aliases&&t in i.aliases)return this.updateProperty(e,i.aliases[t],"attribute");return null}}const e=class extends HTMLElement{constructor(){super(),this.p=!1,this.m=!1,this.props=new n(this.constructor.properties),this.v=this.attachInternals(),this.shadowRoot||this.attachShadow({mode:"open"})}static get observedAttributes(){const t=[];for(const[n,e]of Object.entries(this.properties))if(t.push(n.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase()),e.aliases)for(const i of Object.keys(e.aliases))t.push(i);return t}setProperty(t,n){const e=this.props.updateProperty(t,n,"property");e&&(this.k(e),this.$([e]))}getProperty(t){return this.props.get(t)}k(t){const{name:n,newValue:e}=t,i=this.props.getConfig(n);if(!i)return;const o=this.C(n);"boolean"===i.type?e?this.setAttribute(o,""):this.removeAttribute(o):null==e?this.removeAttribute(o):this.setAttribute(o,"object"==typeof e?JSON.stringify(e):e+"")}C(t){return t.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase()}S(t){return t.replace(/-([a-z])/g,(t,n)=>n.toUpperCase())}attributeChangedCallback(t,n,e){if(n===e)return;let i=this.props.handleAlias(t,e);if(!i){const n=this.S(t),o=this.props.hasConfig(t)?t:n;i=this.props.updateProperty(o,e,"attribute")}i&&this.$([i])}connectedCallback(){this.p=!0;const t=this.T();t.length>0&&this.$(t),this.onConnect(),this.m||(this.render(),this.m=!0)}disconnectedCallback(){this.p=!1,this.onDisconnect()}T(){const t=[],n=this.constructor;for(const e of Object.keys(n.properties)){const n=Object.getOwnPropertyDescriptor(this,e);if(n&&void 0!==n.value){const i=this.props.updateProperty(e,n.value,"property");i&&t.push(i)}}return t}$(t){0!==t.length&&(this.onPropertiesChanged(t),t.some(t=>this.props.isFormValue(t.name))&&this.updateFormValue(),t.some(t=>this.props.isVisual(t.name))&&this.p&&this.render(),this.M(t))}M(t){for(const n of t)this.props.shouldEmitChange(n.name)&&this.dispatchEvent(new CustomEvent("prop:change",{detail:{property:n.name,oldValue:n.oldValue,newValue:n.newValue},bubbles:!0,composed:!0}))}updateFormValue(){const t=this.getFormValue();this.v.setFormValue(t)}getFormValue(){return this.props.get("value")??null}onPropertiesChanged(t){}onConnect(){}onDisconnect(){}get form(){return this.v.form}applyLabelName(t){let n=Array.from(this.v.labels??[]).map(t=>t.textContent?.trim()).filter(Boolean).join(" ");if(!n){const t=this.closest("label");if(t){const e=t.cloneNode(!0);e.querySelectorAll(this.tagName.toLowerCase()).forEach(t=>t.remove()),n=e.textContent?.trim()??""}}n?t.setAttribute("aria-label",n):t.removeAttribute("aria-label")}formResetCallback(){const t=this.constructor.properties.value;t&&this.setProperty("value",t.default??""),this.onFormReset()}onFormReset(){}};e.formAssociated=!0,e.properties={};let i=e;const o=new Map;function s(t,n){const{css:e,id:i}=n;let s;i&&o.has(i)?s=o.get(i):(s=new CSSStyleSheet,s.replaceSync(e),i&&o.set(i,s));const r=t.adoptedStyleSheets||[];r.includes(s)||(t.adoptedStyleSheets=[...r,s])}const r=["primary","secondary","success","danger","warning","neutral"],a=(t,n,e,i)=>i?`var(${t}-${n}${e}, var(${t}-${i}${e}))`:`var(${t}-${n}${e})`,l=(t,n)=>{const e=e=>a("--ty-solid",t,e,n);return`\nbutton.solid.${t} { --_ring: ${a("--ty-color",t,"",n)}; background: var(--ty-button-bg, ${e("")}); color: var(--ty-button-color, ${e("-fg")}); }\nbutton.solid.${t}.tone-plus { background: var(--ty-button-bg, ${e("-strong")}); }\nbutton.solid.${t}.tone-minus { background: var(--ty-button-bg, ${e("-soft")}); }\nbutton.solid.${t}:hover:not(:disabled) { background: var(--ty-button-bg-hover, ${e("-hover")}); }\nbutton.solid.${t}:active:not(:disabled) { background: ${e("-active")}; }\n`},c=(t,n)=>{const e=e=>a("--ty-color",t,e,n);return`\nbutton.outlined.${t} {\n color: var(--ty-button-color, ${e("")});\n border-color: var(--ty-button-border, ${e("")});\n}\nbutton.outlined.${t}.tone-plus {\n color: var(--ty-button-color, ${e("-strong")});\n border-color: var(--ty-button-border, ${e("-strong")});\n}\nbutton.outlined.${t}.tone-minus {\n color: var(--ty-button-color, ${e("-soft")});\n border-color: var(--ty-button-border, ${e("-soft")});\n}\nbutton.outlined.${t}:hover:not(:disabled) {\n background: var(--ty-button-bg-hover, ${a("--ty-bg",t,"-soft",n)});\n}\n`},d=(t,n)=>{const e=e=>a("--ty-color",t,e,n);return`\nbutton.ghost.${t} { color: var(--ty-button-color, ${e("")}); }\nbutton.ghost.${t}.tone-plus { color: var(--ty-button-color, ${e("-strong")}); }\nbutton.ghost.${t}.tone-minus { color: var(--ty-button-color, ${e("-soft")}); }\nbutton.ghost.${t}:hover:not(:disabled) {\n background: var(--ty-button-bg-hover, ${a("--ty-bg",t,"-soft",n)});\n}\n`},h=`\n:host {\n display: inline-block;\n font-family: var(--ty-font-sans);\n}\n\n:host([wide]) {\n display: flex;\n flex-grow: 1;\n}\n\nbutton {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--ty-spacing-1);\n font-size: var(--ty-font-xs);\n line-height: var(--ty-leading-xs);\n letter-spacing: var(--ty-tracking-xs);\n font-weight: var(--ty-font-semibold);\n white-space: nowrap;\n cursor: pointer;\n user-select: none;\n transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;\n background: transparent;\n color: var(--ty-color-neutral);\n border: 1px solid transparent;\n}\n\nbutton:not(.action) {\n min-width: 4rem;\n}\n\nbutton:not(.pill) {\n border-radius: var(--ty-radius-md);\n}\n\nbutton.xs:not(.pill) { border-radius: var(--ty-button-radius-xs, var(--ty-radius-md)); }\nbutton.sm:not(.pill) { border-radius: var(--ty-button-radius-sm, var(--ty-radius-md)); }\nbutton.md:not(.pill) { border-radius: var(--ty-button-radius-md, var(--ty-radius-md)); }\nbutton.lg:not(.pill) { border-radius: var(--ty-button-radius-lg, var(--ty-radius-md)); }\nbutton.xl:not(.pill) { border-radius: var(--ty-button-radius-xl, var(--ty-radius-md)); }\n\nbutton:focus-visible {\n outline: none;\n}\n\nbutton:disabled {\n cursor: not-allowed;\n opacity: 0.6;\n}\n\n/* ===== LOADING STATE =====\n Spinner overlays the button center; original content kept in flow but\n hidden via visibility so width/height are preserved (no layout shift).\n*/\n.loader-icon {\n display: none;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: 1em;\n height: 1em;\n color: currentColor;\n}\n.loader-icon svg {\n width: 100%;\n height: 100%;\n}\nbutton.loading {\n cursor: wait;\n}\nbutton.loading > *:not(.loader-icon) {\n visibility: hidden;\n}\nbutton.loading > .loader-icon {\n display: inline-flex;\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n animation: ty-button-spin 0.7s linear infinite;\n}\n@keyframes ty-button-spin {\n to { transform: translate(-50%, -50%) rotate(360deg); }\n}\n@media (prefers-reduced-motion: reduce) {\n button.loading > .loader-icon {\n animation-duration: 1.6s;\n }\n}\n\n::slotted(*) {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n::slotted(ty-icon) {\n flex-shrink: 0;\n}\n\n:host([wide]) button {\n flex-grow: 1;\n}\n\n/* ===== SIZES =====\n Buttons run a 4px ladder (24-40px). Shared scale with fields\n (--ty-size-sm/md/lg — see tyrell.css): field sm = button md (32px),\n field md = button lg (36px), field lg = button xl (40px) — a button\n and a field of the paired size sit flush, same height, in a row. */\n\nbutton.xs {\n padding: 0 var(--ty-spacing-2);\n font-size: var(--ty-font-xs);\n line-height: var(--ty-leading-xs);\n letter-spacing: var(--ty-tracking-xs);\n gap: var(--ty-spacing-1);\n height: 1.5rem; /* 24px */\n}\n\nbutton.sm {\n padding: 0 var(--ty-spacing-2);\n font-size: var(--ty-font-xs);\n line-height: var(--ty-leading-xs);\n letter-spacing: var(--ty-tracking-xs);\n gap: var(--ty-spacing-1);\n height: 1.75rem; /* 28px */\n}\n\nbutton.md {\n padding: 0.375rem var(--ty-spacing-3);\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n gap: var(--ty-spacing-2);\n height: 2rem; /* 32px — matches field sm */\n}\n\nbutton.lg {\n padding: 0.375rem var(--ty-spacing-4);\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n gap: var(--ty-spacing-2);\n height: 2.25rem; /* 36px — matches field md */\n}\n\nbutton.xl {\n padding: var(--ty-spacing-2) var(--ty-spacing-6);\n font-size: var(--ty-font-base);\n line-height: var(--ty-leading-base);\n letter-spacing: var(--ty-tracking-base);\n gap: var(--ty-spacing-2);\n height: 2.5rem; /* 40px — matches field lg */\n}\n\n/* ===== ACTION (icon-only square) ===== */\n\nbutton.action {\n gap: 0px !important;\n height: 2rem;\n width: 2rem;\n padding: 0px !important;\n}\n\nbutton.action ::slotted(ty-icon) {\n height: 1rem;\n width: 1rem;\n}\n\nbutton.action.xs { height: 1.375rem; width: 1.375rem; }\nbutton.action.xs ::slotted(ty-icon) { height: 0.75rem; width: 0.75rem; }\n\nbutton.action.sm { height: 1.5rem; width: 1.5rem; }\nbutton.action.sm ::slotted(ty-icon) { height: 0.875rem; width: 0.875rem; }\n\nbutton.action.lg { height: 2.25rem; width: 2.25rem; }\nbutton.action.lg ::slotted(ty-icon) { height: 1.125rem; width: 1.125rem; }\n\nbutton.action.xl { height: 2.5rem; width: 2.5rem; }\nbutton.action.xl ::slotted(ty-icon) { height: 1.25rem; width: 1.25rem; }\n\n/* ===== PILL ===== */\n\nbutton.pill {\n border-radius: 9999px;\n padding-left: 1.25em;\n padding-right: 1.25em;\n}\n\nbutton.pill.xs { padding-left: 1em; padding-right: 1em; }\nbutton.pill.sm { padding-left: 1.125em; padding-right: 1.125em; }\nbutton.pill.lg { padding-left: 1.5em; padding-right: 1.5em; }\nbutton.pill.xl { padding-left: 1.75em; padding-right: 1.75em; }\n\nbutton.pill:has(ty-icon:only-child),\nbutton.pill:has(slot[name="start"]:only-child),\nbutton.pill:has(slot[name="end"]:only-child) {\n padding: 0;\n aspect-ratio: 1;\n min-width: var(--ty-size-md);\n}\n\nbutton.pill.xs:has(ty-icon:only-child) { min-width: 1.375rem; min-height: 1.375rem; }\nbutton.pill.sm:has(ty-icon:only-child) { min-width: 1.5rem; min-height: 1.5rem; }\nbutton.pill.md:has(ty-icon:only-child) { min-width: 2rem; min-height: 2rem; }\nbutton.pill.lg:has(ty-icon:only-child) { min-width: 2.25rem; min-height: 2.25rem; }\nbutton.pill.xl:has(ty-icon:only-child) { min-width: 2.5rem; min-height: 2.5rem; }\n\n/* ============================================================\n SOLID — flat: one variable per segment. No color math here; all the\n --ty-solid-{flavor}-{hover,active,strong,soft} tokens are DERIVED in\n tyrell-brand.css (OKLCH) or set literally in tyrell.css. Override any\n single token to recolor that one segment. Bare .solid = custom-flavor\n fallback, themable via --ty-button-{bg,bg-hover,color}.\n ============================================================ */\n\nbutton.solid {\n border: none;\n --_ring: var(--ty-color-neutral);\n background: var(--ty-button-bg, var(--ty-solid-neutral));\n color: var(--ty-button-color, var(--ty-solid-neutral-fg));\n}\nbutton.solid.tone-plus { background: var(--ty-button-bg, var(--ty-solid-neutral-strong)); }\nbutton.solid.tone-minus { background: var(--ty-button-bg, var(--ty-solid-neutral-soft)); }\nbutton.solid:hover:not(:disabled) { background: var(--ty-button-bg-hover, var(--ty-solid-neutral-hover)); }\nbutton.solid:active:not(:disabled) { background: var(--ty-solid-neutral-active); }\n\n${r.map(t=>l(t)).join("")}\nbutton.solid:focus-visible {\n box-shadow: 0 0 0 2px var(--ty-focus-ring-gap), 0 0 0 4px var(--_ring);\n}\n\n/* ============================================================\n OUTLINED — transparent bg, text === border (uses --ty-color-*)\n Bare .outlined rule = fallback for custom flavors. For outlined,\n text is bound to border color (the rule "text === border"), so the\n fallback chain prefers --ty-button-border, then --ty-button-color.\n ============================================================ */\n\nbutton.outlined {\n background: transparent;\n color: var(--ty-button-border, var(--ty-button-color, var(--ty-color-neutral)));\n border-color: var(--ty-button-border, var(--ty-button-color, var(--ty-color-neutral)));\n}\nbutton.outlined:hover:not(:disabled) {\n background: var(--ty-button-bg-hover, var(--ty-bg-neutral-soft));\n}\n\n${r.map(t=>c(t)).join("")}\n\n/* ============================================================\n GHOST — text only, hover bg (uses --ty-color-* + --ty-bg-*-soft)\n Bare .ghost rule = fallback for custom flavors.\n ============================================================ */\n\nbutton.ghost {\n background: transparent;\n border: none;\n color: var(--ty-button-color, var(--ty-color-neutral));\n}\nbutton.ghost:hover:not(:disabled) {\n background: var(--ty-button-bg-hover, var(--ty-bg-neutral-soft));\n}\n\n${r.map(t=>d(t)).join("")}`;function u(t,n,e,i){const o=(e||"")+"",s=o.replace(/[+-]$/,"");return r.includes(s)||!/^[A-Za-z][A-Za-z0-9_-]*$/.test(s)?(n&&(t.adoptedStyleSheets=t.adoptedStyleSheets.filter(t=>t!==n)),null):(n||(n=new CSSStyleSheet,t.adoptedStyleSheets=[...t.adoptedStyleSheets,n]),n.replaceSync(i({flavor:o,base:s,shade:o.slice(s.length)})),n)}let p=null;function b(t){p=t&&t.trim()?t:null}function g(){return p??'<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="3" stroke-opacity="0.25"/><path d="M22 12a10 10 0 0 1-10 10" stroke="currentColor" stroke-width="3" stroke-linecap="round"/></svg>'}function m(){p=null}const v=class extends i{constructor(){super(),this.A=!1,this.I=null,s(this.shadowRoot,{css:h,id:"ty-button"})}onConnect(){this.D()}onDisconnect(){}onPropertiesChanged(t){t.some(t=>"flavor"===t.name)&&this.D()}D(){const{base:t}=this.parseFlavor();this.I=u(this.shadowRoot,this.I,t,()=>(t=>l(t,"neutral")+c(t,"neutral")+d(t,"neutral"))(t))}get flavor(){return this.getProperty("flavor")}set flavor(t){this.setProperty("flavor",t)}get size(){return this.getProperty("size")}set size(t){this.setProperty("size",t)}get appearance(){return this.getProperty("appearance")}set appearance(t){this.setProperty("appearance",t)}get disabled(){return this.getProperty("disabled")}set disabled(t){this.setProperty("disabled",t)}get loading(){return this.getProperty("loading")}set loading(t){this.setProperty("loading",t)}get type(){return this.getProperty("type")}set type(t){this.setProperty("type",t)}get pill(){return this.getProperty("pill")}set pill(t){this.setProperty("pill",t)}get action(){return this.getProperty("action")}set action(t){this.setProperty("action",t)}get wide(){return this.getProperty("wide")}set wide(t){this.setProperty("wide",t)}get name(){return this.getProperty("name")}set name(t){this.setProperty("name",t)}get value(){return this.getProperty("value")}set value(t){this.setProperty("value",t)}parseFlavor(){const t=this.flavor||"";return t.length>1&&t.endsWith("+")?{base:t.slice(0,-1),tone:"+"}:t.length>1&&t.endsWith("-")?{base:t.slice(0,-1),tone:"-"}:{base:t,tone:""}}buildClasses(){const{base:t,tone:n}=this.parseFlavor();return function(...t){return t.filter(Boolean).join(" ")}(t,this.size,this.appearance,this.pill&&"pill",this.action&&"action","+"===n&&"tone-plus","-"===n&&"tone-minus")}handleFormAction(){const t=this.v.form;if(t)switch(this.type){case"submit":this.name&&this.value&&this.v.setFormValue(this.value),t.requestSubmit();break;case"reset":t.reset()}}initializeButtonStructure(){const t=this.shadowRoot,n=this.buildClasses(),e=document.createElement("button");e.disabled=this.disabled,e.className=n;const i=document.createElement("span");i.className="loader-icon",i.setAttribute("aria-hidden","true"),i.innerHTML=g();const o=document.createElement("slot");o.name="start",o.className="start";const s=document.createElement("slot"),r=document.createElement("slot");r.name="end",r.className="end",e.appendChild(i),e.appendChild(o),e.appendChild(s),e.appendChild(r),e.addEventListener("click",t=>{this.disabled||this.loading||(t.stopPropagation(),this.handleFormAction(),this.dispatchEvent(new CustomEvent("click",{bubbles:!0,composed:!0,detail:{originalEvent:t}})))}),this.applyLoadingState(e),t.appendChild(e),this.A=!0}applyLoadingState(t){const n=this.loading;if(t.classList.toggle("loading",n),n){t.setAttribute("aria-busy","true");const n=t.querySelector(".loader-icon");n&&(n.innerHTML=g())}else t.removeAttribute("aria-busy")}render(){const t=this.shadowRoot;if(!this.A)return void this.initializeButtonStructure();const n=this.buildClasses(),e=t.querySelector("button");e&&(e.disabled=this.disabled,e.className=n,this.applyLoadingState(e))}};v.formAssociated=!0,v.properties={flavor:{type:"string",visual:!0,default:"neutral"},size:{type:"string",visual:!0,default:"md",validate:t=>["xs","sm","md","lg","xl"].includes(t),coerce:t=>["xs","sm","md","lg","xl"].includes(t)?t:"md"},appearance:{type:"string",visual:!0,default:"solid",validate:t=>["solid","outlined","ghost"].includes(t),coerce:t=>["solid","outlined","ghost"].includes(t)?t:"solid"},disabled:{type:"boolean",visual:!0,default:!1},loading:{type:"boolean",visual:!0,default:!1},type:{type:"string",visual:!1,default:"submit"},pill:{type:"boolean",visual:!0,default:!1},action:{type:"boolean",visual:!0,default:!1},wide:{type:"boolean",visual:!1,default:!1},name:{type:"string",default:""},value:{type:"string",default:""}};let y=v;customElements.get("ty-button")||customElements.define("ty-button",y);const f="1.0.0-TC33",w=new Map,x=new Map,k=new Map;let z=null,$=null;const C="ty-icons-v"+f,S="https://ty-icons.local/",E=new Map;let T=!1;function M(t){const n=new Set;Object.entries(t).forEach(([t,e])=>{w.set(t,e),n.add(t)}),n.size>0&&N(n)}function A(t){return w.get(t)}function I(t){return w.has(t)}async function D(){const t=new Set(w.keys());if(w.clear(),"caches"in window)try{await caches.delete(C),T=!1}catch(n){}N(t)}function L(t,n,e){x.set(t,e),n&&k.set(t,n)}function O(t){x.delete(t),k.delete(t)}function N(t){z||(z=new Set),t.forEach(t=>z.add(t)),null!==$&&clearTimeout($);const n="undefined"!=typeof requestIdleCallback?requestIdleCallback:t=>setTimeout(t,0);$=n(()=>{const t=z;z=null,$=null,t&&t.size>0&&function(t){x.forEach((n,e)=>{const i=k.get(e);i?t.has(i)&&n(new Set([i])):n(t)})}(t)})}function R(){return Array.from(w.keys())}async function q(){const t={version:f,cacheName:C,available:"caches"in window};if(!t.available)return t;try{const n=await caches.open(C),e=(await n.keys()).filter(t=>t.url.startsWith(S));return{...t,iconCount:e.length}}catch(n){return t}}const V=Object.freeze(Object.defineProperty({__proto__:null,addWatcher:L,clearIcons:D,getCacheInfo:q,getCachedIcon:async function(t){const n=E.get(t);if(n)return n;const e=(async()=>{try{await async function(){if(!T&&"caches"in window){T=!0;try{const t=(await caches.keys()).filter(t=>t.startsWith("ty-icons-v")&&t!==C);await Promise.all(t.map(t=>caches.delete(t)))}catch(t){}}}();const n=await caches.open(C),e=await n.match(`${S}${t}`);if(e)return await e.text()}catch(n){}return null})();return E.set(t,e),e.finally(()=>{E.delete(t)}),e},getIcon:A,getIconNames:R,hasIcon:I,registerIcons:M,removeWatcher:O},Symbol.toStringTag,{value:"Module"}));let P=0;const F='<svg xmlns="http://www.w3.org/2000/svg"\n viewBox="0 0 512 512"\n fill="currentColor"\n opacity="0.2">\n <path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z"/>\n</svg>',H=class extends i{constructor(){super(),this.L=null,this.O="",this.N=null,s(this.shadowRoot,{css:"\n:host {\n /* Display & Layout - CRITICAL: No containment to prevent paint deferral */\n display: flex;\n align-items: center;\n justify-content: center;\n line-height: 0;\n \n /* Dimensions with CSS variable support for flexibility */\n width: var(--ty-icon-size, 1em);\n height: var(--ty-icon-size, 1em);\n \n /* Enforce square aspect ratio */\n aspect-ratio: 1 / 1;\n \n \n /* Color & Transitions */\n color: inherit;\n transition: color var(--ty-transition-fast);\n \n /* Flex Behavior */\n flex-shrink: 0;\n \n /* Visibility - Force immediate rendering */\n visibility: visible !important;\n opacity: 1;\n \n /* ANTI-FLICKER: Force browser to paint immediately */\n will-change: contents;\n \n /* Prevent any sub-pixel rendering issues */\n transform: translateZ(0);\n -webkit-font-smoothing: antialiased;\n}\n\n/* The SVG element inside shadow DOM (registry / fallback path) */\n:host svg {\n width: 100%;\n height: 100%;\n display: block;\n\n /* Force immediate SVG rendering */\n will-change: auto;\n transform: translateZ(0);\n}\n\n/* Slotted SVG (server-side path: <ty-icon><svg>...</svg></ty-icon>).\n ::slotted() targets light-DOM children so they fill the host the same way\n shadow-DOM SVG does. Color is inherited from :host via currentColor. */\n::slotted(svg),\n::slotted(img) {\n width: 100%;\n height: 100%;\n display: block;\n}\n\n/* When used in slots, ensure proper display */\n:host([slot]) {\n display: inline-flex;\n}\n\n/* Size variants via CSS classes on the host */\n:host(.icon-xs) {\n width: 0.75em;\n height: 0.75em;\n}\n\n:host(.icon-sm) {\n width: 0.875em;\n height: 0.875em;\n}\n\n:host(.icon-md) {\n width: 1em;\n height: 1em;\n}\n\n:host(.icon-lg) {\n width: 1.25em;\n height: 1.25em;\n}\n\n:host(.icon-xl) {\n width: 1.5em;\n height: 1.5em;\n}\n\n:host(.icon-2xl) {\n width: 2em;\n height: 2em;\n}\n\n/* Fixed pixel sizes */\n:host(.icon-12) {\n width: 12px;\n height: 12px;\n}\n\n:host(.icon-14) {\n width: 14px;\n height: 14px;\n}\n\n:host(.icon-16) {\n width: 16px;\n height: 16px;\n}\n\n:host(.icon-18) {\n width: 18px;\n height: 18px;\n}\n\n:host(.icon-20) {\n width: 20px;\n height: 20px;\n}\n\n:host(.icon-24) {\n width: 24px;\n height: 24px;\n}\n\n:host(.icon-32) {\n width: 32px;\n height: 32px;\n}\n\n:host(.icon-48) {\n width: 48px;\n height: 48px;\n}\n\n:host(.icon-64) {\n width: 64px;\n height: 64px;\n}\n\n:host(.icon-80) {\n width: 80px;\n height: 80px;\n}\n\n:host(.icon-96) {\n width: 96px;\n height: 96px;\n}\n\n/* Spinning animation - default tempo */\n:host(.icon-spin) {\n animation: icon-spin 1s linear infinite;\n}\n\n/* Spinning animation - slow tempo */\n:host(.icon-spin.icon-tempo-slow) {\n animation: icon-spin 2s linear infinite;\n}\n\n/* Spinning animation - fast tempo */\n:host(.icon-spin.icon-tempo-fast) {\n animation: icon-spin 0.5s linear infinite;\n}\n\n@keyframes icon-spin {\n from {\n transform: rotate(0deg);\n }\n\n to {\n transform: rotate(360deg);\n }\n}\n\n/* Pulse animation - default tempo */\n:host(.icon-pulse) {\n animation: icon-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;\n}\n\n/* Pulse animation - slow tempo */\n:host(.icon-pulse.icon-tempo-slow) {\n animation: icon-pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite;\n}\n\n/* Pulse animation - fast tempo */\n:host(.icon-pulse.icon-tempo-fast) {\n animation: icon-pulse 1s cubic-bezier(0.4, 0, 0.6, 1) infinite;\n}\n\n@keyframes icon-pulse {\n 0%,\n 100% {\n opacity: 1;\n }\n\n 50% {\n opacity: 0.5;\n }\n}\n\n/* Accessibility: ensure icons are not announced by screen readers by default */\n:host {\n -webkit-user-select: none;\n user-select: none;\n}\n\n/* Allow pointer events to pass through by default */\n:host(:not(.icon-clickable)) {\n pointer-events: none;\n}\n\n/* Clickable icons */\n:host(.icon-clickable) {\n cursor: pointer;\n pointer-events: auto;\n transition: color var(--ty-transition-fast), transform var(--ty-transition-fast);\n}\n\n:host(.icon-clickable:hover) {\n transform: scale(1.1);\n}\n\n:host(.icon-clickable:active) {\n transform: scale(0.95);\n}\n\n/* Disabled state */\n:host(.icon-disabled) {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n/* Block display variant */\n:host(.icon-block) {\n display: block;\n}\n",id:"ty-icon"}),this.N=document.createElement("slot"),this.N.innerHTML=F,this.O=F,this.shadowRoot.appendChild(this.N)}onConnect(){this.L="ty-icon-"+ ++P,this.name&&L(this.L,this.name,t=>{this.name&&t.has(this.name)&&this.render()}),this.updateClasses()}onDisconnect(){this.L&&(O(this.L),this.L=null)}onPropertiesChanged(t){for(const n of t)if("name"===n.name){this.L&&O(this.L);const t=n.newValue||"";t&&this.isConnected&&(this.L="ty-icon-"+ ++P,L(this.L,t,t=>{this.name&&t.has(this.name)&&this.render()}))}this.updateClasses()}get name(){return this.getProperty("name")}set name(t){this.setProperty("name",t)}get size(){return this.getProperty("size")||void 0}set size(t){this.setProperty("size",t||"")}get spin(){return this.getProperty("spin")}set spin(t){this.setProperty("spin",t)}get pulse(){return this.getProperty("pulse")}set pulse(t){this.setProperty("pulse",t)}get tempo(){return this.getProperty("tempo")||void 0}set tempo(t){this.setProperty("tempo",t||"")}buildClasses(){const t=[],n=this.getProperty("size");n&&t.push("icon-"+n),this.getProperty("spin")&&t.push("icon-spin"),this.getProperty("pulse")&&t.push("icon-pulse");const e=this.getProperty("tempo");e&&(this.getProperty("spin")||this.getProperty("pulse"))&&t.push("icon-tempo-"+e);const i=this.className.split(/\s+/).filter(t=>t&&!t.startsWith("icon-")&&"icon-spin"!==t&&"icon-pulse"!==t);return[...t,...i]}updateClasses(){const t=this.buildClasses().join(" ");this.className!==t&&(this.className=t)}render(){const t=this.getProperty("name");if(!t)return void this.renderSvg(F);const n=A(t);this.renderSvg(n||F)}renderSvg(t){this.O!==t&&this.N&&(this.N.innerHTML=t,this.O=t)}};H.formAssociated=!1,H.properties={name:{type:"string",visual:!0,default:""},size:{type:"string",visual:!0,default:""},spin:{type:"boolean",visual:!0,default:!1},pulse:{type:"boolean",visual:!0,default:!1},tempo:{type:"string",visual:!0,default:""}};let B=H;customElements.get("ty-icon")||customElements.define("ty-icon",B);const j=`\n/* Tag Component Styles using centralized ty.variables.css */\n\n/* Host element */\n\n/* Hidden attribute support */\n:host([hidden]) {\n display: none !important;\n}\n\n/* Main container */\n.tag-container {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--ty-spacing-1);\n /* Default pill shape - can be overridden */\n border-radius: var(--ty-radius-full);\n font-weight: var(--ty-font-medium);\n text-align: center;\n white-space: nowrap;\n user-select: none;\n box-sizing: border-box;\n\n /* Default MD size — anchor at 28px, even +4 steps for other sizes */\n padding: 0 0.625rem; /* 0 10px */\n font-size: var(--ty-font-xs); /* 14px */\n line-height: var(--ty-leading-xs); /* 21px */\n letter-spacing: var(--ty-tracking-xs); /* -0.013em */\n min-height: 28px;\n\n /* Transitions using centralized values */\n transition: var(--ty-transition-all);\n\n /* Colors via custom properties — override on :host for full control */\n background: var(--tag-bg, transparent);\n color: var(--tag-color, var(--ty-text));\n border: 1px solid;\n border-color: var(--tag-border-color, var(--ty-border));\n}\n\n/* Non-pill variant - rectangular with rounded corners */\n:host([pill="false"]) .tag-container,\n:host([not-pill]) .tag-container {\n border-radius: var(--ty-radius-md);\n /* 6px instead of full pill */\n}\n\n/* Tags with value attribute but NOT selected should be clickable */\n:host([value]:not([selected])) .tag-container:not([aria-disabled="true"]) {\n cursor: pointer;\n}\n\n:host([selected]) .tag-container:not([aria-disabled="true"]) {\n cursor: initial;\n}\n\n.tag-container[tabindex]:not([aria-disabled="true"]):hover {\n background: var(--ty-bg-neutral-soft);\n transform: translateY(-1px);\n box-shadow: var(--ty-shadow-sm);\n}\n\n.tag-container[tabindex]:not([aria-disabled="true"]):active {\n transform: translateY(0);\n box-shadow: var(--ty-shadow-sm);\n}\n\n.tag-container[tabindex]:focus {\n outline: none;\n}\n\n/* Disabled state */\n.tag-container[aria-disabled="true"] {\n opacity: 0.6;\n cursor: not-allowed;\n pointer-events: none;\n}\n\n/* Slot containers */\n.tag-start,\n.tag-content,\n.tag-end {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.tag-content {\n flex: 1;\n min-width: 0;\n}\n\n/* Dismiss button */\n.tag-dismiss {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n background: none;\n border: none;\n color: currentColor;\n cursor: pointer;\n border-radius: var(--ty-radius-full);\n transition: var(--ty-transition-all);\n opacity: 0.7;\n flex-shrink: 0;\n /* Default MD dismiss button size */\n width: var(--ty-spacing-4);\n /* 16px */\n height: var(--ty-spacing-4);\n}\n\n.tag-dismiss:hover {\n opacity: 1;\n background: rgba(0, 0, 0, 0.1);\n}\n\n.tag-dismiss svg {\n width: 100%;\n height: 100%;\n}\n\n/* Size variants - override defaults */\n:host([size="xs"]) .tag-container {\n padding: 0 0.375rem; /* 0 6px */\n font-size: var(--ty-font-xs); /* 12px */\n line-height: var(--ty-leading-xs);\n letter-spacing: var(--ty-tracking-xs);\n min-height: 20px;\n}\n\n:host([size="xs"]) .tag-dismiss {\n width: var(--ty-spacing-3);\n height: var(--ty-spacing-3);\n margin-left: var(--ty-spacing-2);\n}\n\n:host([size="sm"]) .tag-container {\n padding: 0 var(--ty-spacing-2); /* 0 8px */\n font-size: var(--ty-font-xs); /* 12px */\n line-height: var(--ty-leading-xs);\n letter-spacing: var(--ty-tracking-xs);\n min-height: 24px;\n}\n\n:host([size="sm"]) .tag-dismiss {\n width: var(--ty-spacing-3);\n height: var(--ty-spacing-3);\n margin-left: var(--ty-spacing-2);\n}\n\n/* MD is now the default - no need for explicit [size="md"] selector */\n/* All default styles above apply to MD size (min-height: 24px) */\n\n:host([size="lg"]) .tag-container {\n padding: 0 var(--ty-spacing-3); /* 0 12px */\n font-size: var(--ty-font-sm); /* 14px */\n line-height: var(--ty-leading-sm); /* 21px */\n letter-spacing: var(--ty-tracking-sm); /* -0.013em */\n min-height: 32px;\n}\n\n:host([size="lg"]) .tag-dismiss {\n width: var(--ty-spacing-5);\n height: var(--ty-spacing-5);\n margin-left: var(--ty-spacing-4);\n}\n\n:host([size="xl"]) .tag-container {\n padding: 0 0.875rem; /* 0 14px */\n font-size: var(--ty-font-sm); /* 14px */\n line-height: var(--ty-leading-sm); /* 21px */\n letter-spacing: var(--ty-tracking-sm); /* -0.013em */\n min-height: 36px;\n}\n\n:host([size="xl"]) .tag-dismiss {\n width: var(--ty-spacing-5);\n height: var(--ty-spacing-5);\n margin-left: var(--ty-spacing-4);\n}\n\n/* ===== FLAVOR VARIANTS =====\n Each flavor sets --tag-bg / --tag-color / --tag-border-color on :host.\n Append '+' to flavor for a stronger shade (mild background, strong color),\n or '-' for a softer shade (soft background, base color).\n Generated per flavor above; neutral diverges (text/border tokens) and\n stays hand-written below. */\n\n${r.filter(t=>"neutral"!==t).map(t=>`\n/* ----- ${t.toUpperCase()} ----- */\n:host([flavor="${t}"]) {\n --tag-bg: var(--ty-bg-${t});\n --tag-color: var(--ty-color-${t});\n --tag-border-color: var(--ty-border-${t});\n}\n:host([flavor="${t}+"]) {\n --tag-bg: var(--ty-bg-${t}-bold);\n --tag-color: var(--ty-color-${t}-strong);\n --tag-border-color: var(--ty-color-${t});\n}\n:host([flavor="${t}-"]) {\n --tag-bg: var(--ty-bg-${t}-soft);\n --tag-color: var(--ty-color-${t});\n --tag-border-color: var(--ty-border-${t});\n}\n:host([flavor="${t}"]) .tag-container[tabindex]:hover,\n:host([flavor="${t}+"]) .tag-container[tabindex]:hover,\n:host([flavor="${t}-"]) .tag-container[tabindex]:hover {\n background: var(--ty-bg-${t}-bold);\n}\n:host([flavor="${t}"]) .tag-container[tabindex]:focus,\n:host([flavor="${t}+"]) .tag-container[tabindex]:focus,\n:host([flavor="${t}-"]) .tag-container[tabindex]:focus {\n box-shadow: 0 0 0 3px var(--ty-color-${t}-faint);\n}\n`).join("")}\n/* ----- NEUTRAL ----- */\n:host([flavor="neutral"]) {\n --tag-color: var(--ty-text-bold);\n --tag-bg: var(--ty-bg-neutral-soft);\n --tag-border-color: var(--ty-border-bold);\n}\n\n:host([flavor="neutral+"]) {\n --tag-bg: var(--ty-bg-neutral-bold);\n --tag-color: var(--ty-text-bold);\n --tag-border-color: var(--ty-border-strong);\n}\n:host([flavor="neutral-"]) {\n --tag-bg: var(--ty-bg-neutral-soft);\n --tag-color: var(--ty-text-soft);\n --tag-border-color: var(--ty-border);\n}\n:host([flavor="neutral"]) .tag-container[tabindex]:hover,\n:host([flavor="neutral+"]) .tag-container[tabindex]:hover,\n:host([flavor="neutral-"]) .tag-container[tabindex]:hover {\n background: var(--ty-bg-neutral-soft);\n}\n:host([flavor="neutral"]) .tag-container[tabindex]:focus,\n:host([flavor="neutral+"]) .tag-container[tabindex]:focus,\n:host([flavor="neutral-"]) .tag-container[tabindex]:focus {\n box-shadow: 0 0 0 3px var(--ty-border-soft);\n}\n\n/* Slotted content styling */\n.tag-start ::slotted(*),\n.tag-content ::slotted(*),\n.tag-end ::slotted(*) {\n display: flex;\n align-items: center;\n}\n\n/* Icon sizing for slotted icons */\n.tag-start ::slotted(ty-icon),\n.tag-end ::slotted(ty-icon) {\n width: 1em;\n height: 1em;\n flex-shrink: 0;\n}\n\n/* Count/badge styling using centralized spacing */\n.tag-end ::slotted(.count) {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: var(--ty-spacing-6);\n /* 24px */\n height: var(--ty-spacing-5);\n /* 20px */\n padding: 0 var(--ty-spacing-2);\n /* 0 8px */\n background: rgba(0, 0, 0, 0.1);\n border-radius: var(--ty-radius-full);\n font-size: var(--ty-font-xs);\n font-weight: var(--ty-font-semibold);\n line-height: var(--ty-line-height-none);\n flex-shrink: 0;\n}\n\n/* Special handling for long text content */\n.tag-content {\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n:host([data-type="user"]) .tag-container {\n min-width: var(--ty-spacing-20);\n /* 80px for user tags */\n}\n\n/* Dark mode is handled automatically by the centralized variables */\n`,W=class extends i{constructor(){super(),this.R=null,this.I=null,this.handleClick=t=>{this.clickable&&!this.disabled&&(t.preventDefault(),t.stopPropagation(),this.dispatchTagEvent("click",{target:this}),this.dispatchTagEvent("pointerdown",{target:this}))},this.handleDismiss=t=>{this.dismissible&&!this.disabled&&(t.preventDefault(),t.stopPropagation(),this.dispatchTagEvent("dismiss",{target:this}))},this.handleKeydown=t=>{const n=t;if(!this.disabled)switch(n.keyCode){case 13:case 32:this.clickable&&(n.preventDefault(),this.dispatchTagEvent("click",{target:this}));break;case 8:case 46:this.dismissible&&(n.preventDefault(),this.dispatchTagEvent("dismiss",{target:this}))}},s(this.shadowRoot,{css:j,id:"ty-tag"})}onConnect(){this.D(),queueMicrotask(()=>{this.setupEventListeners()})}D(){this.I=u(this.shadowRoot,this.I,this.flavor,({flavor:t,base:n,shade:e})=>`\n:host([flavor="${t}"]) {\n --tag-bg: var(${"+"===e?`--ty-bg-${n}-bold`:"-"===e?`--ty-bg-${n}-soft`:"--ty-bg-"+n});\n --tag-color: var(${"+"===e?`--ty-color-${n}-strong`:"--ty-color-"+n});\n --tag-border-color: var(--ty-border-${n}, var(--ty-color-${n}));\n}\n:host([flavor="${t}"]) .tag-container[tabindex]:hover {\n background: var(--ty-bg-${n}-bold, var(--tag-bg));\n}\n:host([flavor="${t}"]) .tag-container[tabindex]:focus {\n box-shadow: 0 0 0 3px var(--ty-color-${n}-faint, var(--tag-color));\n}`)}onDisconnect(){this.cleanupEventListeners()}onPropertiesChanged(t){t.some(t=>"flavor"===t.name)&&this.D()}dispatchTagEvent(t,n){this.dispatchEvent(new CustomEvent(t,{detail:n,bubbles:!0,composed:!0,cancelable:!0}))}cleanupEventListeners(){this.R&&(this.R(),this.R=null)}setupEventListeners(){this.cleanupEventListeners();const t=this.shadowRoot,n=t.querySelector(".tag-container"),e=t.querySelector(".tag-dismiss");n&&(n.addEventListener("click",this.handleClick),n.addEventListener("keydown",this.handleKeydown),e&&e.addEventListener("click",this.handleDismiss),this.R=()=>{n.removeEventListener("click",this.handleClick),n.removeEventListener("keydown",this.handleKeydown),e&&e.removeEventListener("click",this.handleDismiss)})}render(){this.shadowRoot.innerHTML=`\n <div class="tag-container" part="container"${this.clickable?' tabindex="0"':""}${this.disabled?' aria-disabled="true"':""}${this.value?` data-value="${this.value}"`:""}>\n <div class="tag-start">\n <slot name="start" class="tag-start"></slot>\n </div>\n <div class="tag-content">\n <slot></slot>\n </div>\n <div class="tag-end">\n <slot name="end"></slot>\n ${this.dismissible?'\n <button class="tag-dismiss" type="button" aria-label="Remove tag">\n <svg viewBox="0 0 20 20" fill="currentColor">\n <path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd" />\n </svg>\n </button>\n ':""}\n </div>\n </div>\n `,this.p&&this.setupEventListeners()}get flavor(){return this.getProperty("flavor")}set flavor(t){this.setProperty("flavor",t)}get size(){return this.getProperty("size")}set size(t){this.setProperty("size",t)}get value(){return this.getProperty("value")}set value(t){this.setProperty("value",t)}get selected(){return this.getProperty("selected")}set selected(t){this.setProperty("selected",t)}get pill(){return this.getProperty("pill")}set pill(t){this.setProperty("pill",t)}get clickable(){return this.getProperty("clickable")}set clickable(t){this.setProperty("clickable",t)}get dismissible(){return this.getProperty("dismissible")}set dismissible(t){this.setProperty("dismissible",t)}get disabled(){return this.getProperty("disabled")}set disabled(t){this.setProperty("disabled",t)}};W.formAssociated=!0,W.properties={flavor:{type:"string",visual:!0,default:"neutral"},size:{type:"string",visual:!0,default:"md",validate:t=>["xs","sm","md","lg","xl"].includes(t),coerce:t=>["xs","sm","md","lg","xl"].includes(t)?t:"md"},value:{type:"string",visual:!0,default:""},selected:{type:"boolean",visual:!0,default:!1},pill:{type:"boolean",visual:!0,default:!0,aliases:{"not-pill":!1}},clickable:{type:"boolean",visual:!0,default:!1},dismissible:{type:"boolean",visual:!0,default:!1},disabled:{type:"boolean",visual:!0,default:!1}};let _=W;function Y(t=768){return window.matchMedia(`(pointer: coarse) and (max-width: ${t}px)`).matches}customElements.get("ty-tag")||customElements.define("ty-tag",_);const U='\n <svg class="option-check" viewBox="0 0 24 24" fill="none" stroke="currentColor"\n stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">\n <path d="M20 6 9 17l-5-5" />\n </svg>\n';class TyOption extends HTMLElement{constructor(){super(),this.q=void 0,this.V=!1,this.P=!1,this.F=!1,this.H=!1,this.B=null,this.j=Y(),s(this.attachShadow({mode:"open"}),{css:"\n/* Ty Option Component Styles */\n\n.option-content {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--ty-spacing-2);\n box-sizing: border-box;\n width: 100%;\n\n /* Ensure content is clickable */\n cursor: pointer;\n user-select: none;\n\n /* Smooth transitions */\n transition: var(--ty-transition-all);\n\n /* Text styling — Linear-paired typography */\n color: var(--ty-text);\n font-family: var(--ty-font-sans);\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n padding: var(--ty-spacing-2) var(--ty-spacing-3);\n border-radius: var(--ty-radius-md);\n}\n\n:host([cloned]) .option-content {\n padding: 0px;\n background: transparent;\n}\n\n.option-content:hover {\n background: var(--ty-bg-neutral-soft);\n}\n\n.option-content[highlighted] {\n background: var(--ty-bg-neutral-soft);\n color: var(--ty-text-strong);\n font-weight: var(--ty-font-semibold);\n}\n\n/* Selected: quiet — bolder text color only, no background slab, no weight change */\n.option-content[selected] {\n background: transparent;\n color: var(--ty-text-bold);\n}\n\n/* Lucide check — right-aligned, visible only on selected options */\n.option-check {\n display: none;\n flex-shrink: 0;\n width: 14px;\n height: 14px;\n margin-left: auto;\n color: var(--ty-color-primary);\n}\n\n.option-content[selected] .option-check {\n display: block;\n}\n\n/* Never show the check on the copy cloned into the select's trigger field */\n:host([cloned]) .option-check {\n display: none;\n}\n\n.option-content[selected]:hover {\n background: var(--ty-bg-neutral-soft);\n}\n\n.option-text {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.option-clear-btn {\n flex-shrink: 0;\n width: 28px;\n height: 28px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(0, 0, 0, 0.5);\n border: none;\n border-radius: 50%;\n cursor: pointer;\n padding: 0;\n transition: all 150ms ease;\n opacity: 0.9;\n}\n\n.option-clear-btn:hover {\n background: rgba(0, 0, 0, 0.7);\n opacity: 1;\n transform: scale(1.05);\n}\n\n.option-clear-btn:active {\n background: rgba(0, 0, 0, 0.85);\n transform: scale(0.95);\n}\n\n.option-clear-btn svg {\n width: 16px;\n height: 16px;\n color: #ffffff;\n stroke-width: 2.5;\n}\n\n.option-content[disabled] {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.option-content[hidden] {}\n\n/* Ensure nested elements inherit proper styling */\n.option-content * {\n pointer-events: none;\n}\n\n/* CRITICAL: Re-enable pointer events on clear button */\n.option-clear-btn {\n pointer-events: auto !important;\n}\n\n.option-clear-btn * {\n pointer-events: none;\n}\n",id:"ty-option"}),this.render()}static get observedAttributes(){return["value","disabled","selected","highlighted","hidden"]}connectedCallback(){const t=Object.getOwnPropertyDescriptor(this,"value");t&&void 0!==t.value&&(this.q=t.value,delete this.value),this.render()}disconnectedCallback(){this.removeClearButtonListener()}attributeChangedCallback(t,n,e){if(n!==e){switch(t){case"value":this.q=e||void 0;break;case"selected":this.V=null!==e;break;case"disabled":this.P=null!==e;break;case"highlighted":this.F=null!==e;break;case"hidden":this.H=null!==e}this.render()}}getOptionValue(){if(void 0!==this.q)return this.q;const t=this.getAttribute("value");return null!==t?t:this.textContent?.trim()||""}get value(){return this.getOptionValue()}set value(t){this.q!==t&&(this.q=t,void 0!==t?this.setAttribute("value",t):this.removeAttribute("value"),this.render())}get selected(){return this.V}set selected(t){this.V!==t&&(this.V=t,t?this.setAttribute("selected",""):this.removeAttribute("selected"),this.render())}get disabled(){return this.P}set disabled(t){this.P!==t&&(this.P=t,t?this.setAttribute("disabled",""):this.removeAttribute("disabled"),this.render())}get highlighted(){return this.F}set highlighted(t){this.F!==t&&(this.F=t,t?this.setAttribute("highlighted",""):this.removeAttribute("highlighted"),this.render())}get hidden(){return this.H}set hidden(t){this.H!==t&&(this.H=t,t?this.setAttribute("hidden",""):this.removeAttribute("hidden"),this.render())}removeClearButtonListener(){if(this.B){const t=this.shadowRoot?.querySelector(".option-clear-btn");t&&t.removeEventListener("click",this.B),this.B=null}}addClearButtonListener(t){this.removeClearButtonListener(),this.B=t=>{t.preventDefault(),t.stopPropagation(),this.dispatchEvent(new CustomEvent("clear-selection",{bubbles:!0,composed:!0,detail:{value:this.q}}))},t.addEventListener("click",this.B)}render(){const t=this.shadowRoot;if(this.getOptionValue(),t.querySelector(".option-content")){const n=this.V&&this.j,e=t.querySelector(".option-clear-btn");if(n&&!e){const n=t.querySelector(".option-content");if(n){const t=n.querySelector("slot");if(t&&!t.parentElement?.classList.contains("option-text")){const n=document.createElement("span");n.className="option-text",t.parentNode?.insertBefore(n,t),n.appendChild(t)}const e=document.createElement("button");e.className="option-clear-btn",e.type="button",e.setAttribute("aria-label","Clear selection"),e.innerHTML='\n <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <line x1="18" y1="6" x2="6" y2="18"></line>\n <line x1="6" y1="6" x2="18" y2="18"></line>\n </svg>\n ',this.addClearButtonListener(e),n.appendChild(e)}}else!n&&e&&(e.remove(),this.removeClearButtonListener())}else if(this.V&&this.j){t.innerHTML=`\n <div class="option-content">\n <span class="option-text"><slot></slot></span>\n ${U}\n <button class="option-clear-btn" type="button" aria-label="Clear selection">\n <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <line x1="18" y1="6" x2="6" y2="18"></line>\n <line x1="6" y1="6" x2="18" y2="18"></line>\n </svg>\n </button>\n </div>\n `;const n=t.querySelector(".option-clear-btn");n&&this.addClearButtonListener(n)}else t.innerHTML=`<div class="option-content"><slot></slot>${U}</div>`;const n=t.querySelector(".option-content");n&&(this.P?n.setAttribute("disabled",""):n.removeAttribute("disabled"),this.V?n.setAttribute("selected",""):n.removeAttribute("selected"),this.F?n.setAttribute("highlighted",""):n.removeAttribute("highlighted"),this.H?n.setAttribute("hidden",""):n.removeAttribute("hidden"))}}customElements.get("ty-option")||customElements.define("ty-option",TyOption);const G=(t,n)=>{const e=e=>n?e?`var(--ty-color-${t}${e}, var(--ty-color-${t}, var(--ty-color-${n}${e})))`:`var(--ty-color-${t}, var(--ty-color-${n}))`:e?`var(--ty-color-${t}${e}, var(--ty-color-${t}))`:`var(--ty-color-${t})`;return`\n:host([flavor="${t}"]) {\n --input-accent: var(--ty-input-${t}-border, ${e("-soft")});\n --input-accent-bold: ${e("")};\n --input-ring: color-mix(in oklab, ${e("")} 15%, transparent);\n}\n:host([flavor="${t}+"]) {\n --input-accent: ${e("")};\n --input-accent-bold: ${e("-strong")};\n --input-ring: color-mix(in oklab, ${e("-strong")} 15%, transparent);\n}\n:host([flavor="${t}-"]) {\n --input-accent: ${e("-faint")};\n --input-accent-bold: ${e("-soft")};\n --input-ring: color-mix(in oklab, ${e("-soft")} 15%, transparent);\n}\n`},Z=`\n:host {\n display: block;\n font-family: var(--ty-font-sans);\n width: 100%;\n}\n\n:host([size="sm"]) {\n font-size: 14px;\n}\n\n:host([size="lg"]) {\n font-size: 18px;\n}\n\n.input-container {\n display: flex;\n flex-direction: column;\n width: 100%;\n box-sizing: border-box;\n}\n\n/* ===== LABEL STYLING ===== */\n\n.ty-field-label {\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n font-weight: var(--ty-font-medium);\n color: var(--ty-label-color);\n margin-bottom: 6px;\n padding-left: 12px;\n display: flex;\n align-items: center;\n}\n\n/* Required indicator - using SVG icon */\n.required-icon {\n display: inline-flex;\n align-items: center;\n color: var(--ty-color-danger);\n width: 12px;\n height: 12px;\n margin-left: 4px;\n vertical-align: middle;\n}\n\n.required-icon svg {\n width: 100%;\n height: 100%;\n}\n\n/* ===== INPUT WRAPPER WITH SLOTS ===== */\n\n.input-wrapper {\n display: flex;\n align-items: center;\n gap: 0.5rem; /* No gap by default */\n width: 100%;\n box-sizing: border-box;\n border: 1px solid var(--input-accent, var(--input-border, var(--ty-input-border)));\n border-radius: var(--ty-radius-base);\n background: var(--input-bg, var(--input-bg, var(--ty-input-bg)));\n transition: all 0.15s ease-in-out;\n \n /* Default size (md) */\n min-height: var(--ty-size-md);\n padding: 0 12px;\n}\n\n/* Wrapper states — --input-accent* are set by the flavor rules below;\n without a flavor attribute they're unset and the default chrome chain\n (per-instance --input-* var, then --ty-input-* token) applies. */\n.input-wrapper:hover:not(.disabled) {\n border-color: var(--input-accent-bold, var(--input-border-hover, var(--ty-input-border-hover)));\n}\n\n.input-wrapper.focused {\n border-color: var(--input-accent-bold, var(--input-border-focus, var(--ty-input-border-focus)));\n box-shadow: 0 0 0 3px var(--input-ring, var(--input-shadow-focus, var(--ty-input-shadow-focus)));\n}\n\n.input-wrapper.disabled {\n cursor: not-allowed;\n opacity: 0.5;\n background: var(--input-disabled-bg, var(--ty-input-disabled-bg));\n border-color: var(--input-disabled-border, var(--ty-input-disabled-border));\n}\n\n/* ===== SLOT STYLING ===== */\n\n/* Style slotted content directly (no wrappers needed) */\n::slotted([slot="start"]),\n::slotted([slot="end"]) {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n color: var(--ty-color-text-soft);\n}\n\n/* Password reveal toggle (rendered for type="password") */\n.password-toggle {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: 1.25rem;\n height: 1.25rem;\n padding: 0;\n border: none;\n background: none;\n cursor: pointer;\n color: var(--input-placeholder, var(--ty-input-placeholder));\n transition: color 0.15s ease-in-out;\n}\n.password-toggle:hover {\n color: var(--input-color, var(--ty-input-color));\n}\n.password-toggle:focus-visible {\n outline: 2px solid var(--input-accent, var(--ty-color-primary));\n outline-offset: 2px;\n border-radius: 2px;\n}\n.password-toggle svg {\n width: 1rem;\n height: 1rem;\n}\n\n/* Icon sizing for slotted icons */\n::slotted(ty-icon) {\n width: 1em;\n height: 1em;\n flex-shrink: 0;\n}\n\n/* ===== ERROR MESSAGE STYLING ===== */\n\n.error-message {\n font-size: var(--ty-font-xs);\n line-height: var(--ty-leading-xs);\n letter-spacing: var(--ty-tracking-xs);\n color: var(--ty-color-danger);\n margin-top: 4px;\n padding-left: 12px;\n}\n\n/* Error state for wrapper */\n.input-wrapper.error {\n border-color: var(--ty-color-danger);\n background: var(--ty-bg-danger-soft);\n}\n\n.input-wrapper.error.focused {\n border-color: var(--ty-color-danger-bold);\n box-shadow: 0 0 0 3px var(--input-shadow-focus, var(--ty-input-shadow-focus));\n}\n\n/* ===== INPUT BASE STYLING ===== */\n\ninput {\n /* Reset and base styles — Linear-paired typography */\n flex: 1;\n min-width: 0;\n box-sizing: border-box;\n border: none;\n outline: none;\n background: transparent;\n color: var(--input-color, var(--ty-input-color));\n font-family: inherit;\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n font-weight: var(--ty-font-normal);\n padding: 0;\n margin: 0;\n}\n\n/* Remove number input spinner arrows */\ninput[type="number"]::-webkit-outer-spin-button,\ninput[type="number"]::-webkit-inner-spin-button {\n -webkit-appearance: none;\n margin: 0;\n}\n\ninput[type="number"] {\n -moz-appearance: textfield;\n}\n\n/* Disabled state */\ninput:disabled {\n cursor: not-allowed;\n color: var(--input-disabled-color, var(--ty-input-disabled-color));\n}\n\n/* Placeholder styling */\ninput::placeholder {\n color: var(--input-placeholder, var(--ty-input-placeholder));\n font-weight: 400;\n}\n\n/* ===== SIZE MODIFIERS ===== */\n\n/* Small */\n.input-wrapper.sm {\n min-height: var(--ty-size-sm);\n padding: 0 10px;\n border-radius: var(--ty-input-radius-sm, var(--ty-radius-base));\n}\n\n.input-wrapper.sm input {\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n}\n\n/* Medium (default) */\n.input-wrapper.md {\n min-height: var(--ty-size-md);\n padding: 0 12px;\n border-radius: var(--ty-input-radius-md, var(--ty-radius-base));\n}\n\n.input-wrapper.md input {\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n}\n\n/* Large */\n.input-wrapper.lg {\n min-height: var(--ty-size-lg);\n padding: 0 14px;\n border-radius: var(--ty-input-radius-lg, var(--ty-radius-base));\n}\n\n.input-wrapper.lg input {\n font-size: var(--ty-font-base);\n line-height: var(--ty-leading-base);\n letter-spacing: var(--ty-tracking-base);\n}\n\n/* ===== SEMANTIC FLAVOR MODIFIERS (set --input-accent*, consumed above) ===== */\n${r.filter(t=>"neutral"!==t).map(t=>G(t)).join("")}\n\n/* ===== ACCESSIBILITY ENHANCEMENTS ===== */\n\ninput:focus-visible {\n outline: none;\n}\n\n/* High contrast mode support */\n@media (prefers-contrast: high) {\n .input-wrapper {\n border-width: 2px;\n }\n}\n\n/* Reduced motion support */\n@media (prefers-reduced-motion: reduce) {\n .input-wrapper {\n transition: none;\n }\n}\n\n/* ===== RESPONSIVE BEHAVIOR ===== */\n\n@media (max-width: 640px) {\n .input-wrapper.lg {\n min-height: 40px;\n padding: 0 12px;\n }\n\n .input-wrapper.lg input {\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n }\n\n .input-wrapper.xl {\n min-height: 44px;\n padding: 0 14px;\n }\n\n .input-wrapper.xl input {\n font-size: var(--ty-font-base);\n line-height: var(--ty-leading-base);\n letter-spacing: var(--ty-tracking-base);\n }\n}\n\n@media (max-width: 480px) {\n .input-wrapper.xl {\n min-height: 40px;\n padding: 0 12px;\n }\n\n .input-wrapper.xl input {\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n }\n}\n`;function K(t){return["number","currency","percent","compact"].includes(t)}function X(t,n){if(n)return n;const e=t.closest("[lang]");if(e){const t=e.getAttribute("lang");if(t)return t}return document.documentElement.lang?document.documentElement.lang:navigator.language?navigator.language:"en-US"}function J(t,n){let e=X(t);const i=new MutationObserver(i=>{for(const o of i)if("attributes"===o.type&&"lang"===o.attributeName){const i=X(t);i!==e&&(e=i,n(i))}});return i.observe(document.documentElement,{attributes:!0,attributeFilter:["lang"],subtree:!0}),()=>i.disconnect()}const Q='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 6v12"/><path d="M17.196 9 6.804 15"/><path d="m6.804 9 10.392 6"/></svg>',tt='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0"/><circle cx="12" cy="12" r="3"/></svg>',nt=class extends i{constructor(){super(),this.W=null,this._=!1,this.Y=!1,this.U=!1,this.I=null,this.G=null,this.Z=null,this.K=null,this.X=null,this.J=null,this.tt=null,s(this.shadowRoot,{css:Z,id:"ty-input"})}onConnect(){this.initializeShadowValue(),this.nt=J(this,()=>{this.render()}),this.D()}D(){this.I=u(this.shadowRoot,this.I,this.flavor,({base:t})=>(t=>G(t,"neutral"))(t))}onDisconnect(){this.removeEventListeners(),this.nt&&(this.nt(),this.nt=void 0),null!==this.J&&(clearTimeout(this.J),this.J=null),null!==this.tt&&(clearTimeout(this.tt),this.tt=null)}onPropertiesChanged(t){for(const{name:n,newValue:e}of t)switch(n){case"flavor":this.D();break;case"value":this.W=this.parseShadowValue(e||"");break;case"type":const t=this.getProperty("value")||"";this.W=this.parseShadowValue(t);break;case"error":e?"neutral"===this.getProperty("flavor")&&(this.setProperty("flavor","danger"),this.U=!0):this.U&&("danger"===this.getProperty("flavor")&&this.setProperty("flavor","neutral"),this.U=!1)}}onFormReset(){this.W=null,this._=!1,null!==this.J&&(clearTimeout(this.J),this.J=null),null!==this.tt&&(clearTimeout(this.tt),this.tt=null),this.render()}getFormValue(){return null!==this.W?this.W+"":null}initializeShadowValue(){const t=this.getProperty("value");t&&(this.W=this.parseShadowValue(t),this.v.setFormValue(null!==this.W?this.W+"":null))}parseShadowValue(t){if(!t||"string"!=typeof t||""===t.trim())return null;if(K(this.type)){const n=function(t){if(!t||""===t.trim())return null;let n=t.replace(/[^\d.,-]/g,"").trim();if(""===n||"-"===n)return null;const e=n.lastIndexOf(","),i=n.lastIndexOf("."),o=Math.max(e,i);if(-1===o){const t=parseFloat(n);return isNaN(t)?null:t}const s=n.slice(0,o).replace(/[.,]/g,""),r=n.slice(o+1),a=parseFloat(s+"."+r);return isNaN(a)?null:a}(t);return null!==n&&0===this.precision?Math.round(n):n}return t}shouldFormat(){return K(this.type)&&!this._&&null!==this.W&&"number"==typeof this.W}getFormatConfig(){return{type:this.type,locale:this.locale,currency:this.currency,precision:this.precision}}getDisplayValue(){if(this.shouldFormat()){let t=this.W;return"percent"===this.type&&(t/=100),function(t,n){const{type:e,locale:i="en-US",currency:o="USD",precision:s}=n,r={};switch(void 0!==s&&(r.minimumFractionDigits=s,r.maximumFractionDigits=s),e){case"currency":r.style="currency",r.currency=o;break;case"percent":r.style="percent";break;case"compact":r.notation="compact",r.compactDisplay="short";break;default:r.style="decimal"}return new Intl.NumberFormat(i,r).format(t).replace(/\u202F/g," ").replace(/\u2009/g," ")}(t,this.getFormatConfig())}return null!==this.W?this.W+"":""}get type(){return this.getProperty("type")}set type(t){this.setProperty("type",t)}get value(){return null!==this.W?this.W+"":""}set value(t){this.setProperty("value",t)}get name(){return this.getProperty("name")}set name(t){this.setProperty("name",t)}get placeholder(){return this.getProperty("placeholder")}set placeholder(t){this.setProperty("placeholder",t)}get label(){return this.getProperty("label")}set label(t){this.setProperty("label",t)}get disabled(){return this.getProperty("disabled")}set disabled(t){this.setProperty("disabled",t)}get required(){return this.getProperty("required")}set required(t){this.setProperty("required",t)}get error(){return this.getProperty("error")}set error(t){this.setProperty("error",t)}get size(){return this.getProperty("size")}set size(t){this.setProperty("size",t)}get flavor(){return this.getProperty("flavor")}set flavor(t){this.setProperty("flavor",t)}get currency(){return this.getProperty("currency")}set currency(t){this.setProperty("currency",t)}get locale(){return X(this,this.getProperty("locale"))}set locale(t){this.setProperty("locale",t)}get precision(){return this.getProperty("precision")}set precision(t){this.setProperty("precision",t)}get debounce(){return this.getProperty("debounce")}set debounce(t){this.setProperty("debounce",t)}get form(){return this.v.form}buildClassList(){const t=[this.size];return this.disabled&&t.push("disabled"),this.required&&t.push("required"),this.error&&t.push("error"),t.join(" ")}dispatchInputEvent(t,n){this.dispatchEvent(new CustomEvent("input",{detail:{value:this.W,formattedValue:this.shouldFormat()?this.getDisplayValue():null,rawValue:t,originalEvent:n},bubbles:!0,composed:!0}))}dispatchChangeEvent(t,n){this.dispatchEvent(new CustomEvent("change",{detail:{value:this.W,formattedValue:this.shouldFormat()?this.getDisplayValue():null,rawValue:t,originalEvent:n},bubbles:!0,composed:!0}))}removeEventListeners(){if(!this.Y)return;const t=this.shadowRoot;if(!t)return;const n=t.querySelector("input");n&&(this.G&&(n.removeEventListener("input",this.G),this.G=null),this.Z&&(n.removeEventListener("change",this.Z),this.Z=null),this.K&&(n.removeEventListener("focus",this.K),this.K=null),this.X&&(n.removeEventListener("blur",this.X),this.X=null),this.Y=!1)}setupEventListeners(){if(this.Y)return;const t=this.shadowRoot,n=t.querySelector("input"),e=t.querySelector(".input-wrapper");n&&e&&(this.G=t=>{t.stopPropagation(),t.stopImmediatePropagation();const e=t.target.value;this.W=this.parseShadowValue(e),this.v.setFormValue(null!==this.W?this.W+"":null),this.updateValidity(),null!==this.J&&clearTimeout(this.J),this.debounce>0?this.J=window.setTimeout(()=>{this.dispatchInputEvent(n.value,t),this.J=null},this.debounce):this.dispatchInputEvent(e,t)},this.Z=t=>{t.stopPropagation(),t.stopImmediatePropagation();const e=t.target.value;this.W=this.parseShadowValue(e),this.v.setFormValue(null!==this.W?this.W+"":null),this.updateValidity(),null!==this.tt&&clearTimeout(this.tt),this.debounce>0?this.tt=window.setTimeout(()=>{this.dispatchChangeEvent(n.value,t),this.tt=null},this.debounce):this.dispatchChangeEvent(e,t)},this.K=t=>{this._=!0,e.classList.add("focused"),K(this.type)&&null!==this.W&&(n.value=this.W+""),this.dispatchEvent(new CustomEvent("focus",{detail:{originalEvent:t},bubbles:!0,composed:!0}))},this.X=t=>{const i=t.target.value;null!==this.J&&(clearTimeout(this.J),this.J=null,this.dispatchInputEvent(i,t)),null!==this.tt&&(clearTimeout(this.tt),this.tt=null,this.dispatchChangeEvent(i,t)),this._=!1,e.classList.remove("focused"),this.shouldFormat()&&(n.value=this.getDisplayValue()),this.dispatchEvent(new CustomEvent("blur",{detail:{originalEvent:t},bubbles:!0,composed:!0}))},n.addEventListener("input",this.G),n.addEventListener("change",this.Z),n.addEventListener("focus",this.K),n.addEventListener("blur",this.X),this.Y=!0)}render(){const t=this.shadowRoot,n=t.querySelector("input"),e=t.querySelector(".input-wrapper"),i=t.querySelector(".ty-field-label"),o=t.querySelector(".error-message"),s=this.buildClassList(),r=["password","email","tel","url"].includes(this.type)?this.type:"text",a=K(this.type)?"decimal":"email"===this.type?"email":"tel"===this.type?"tel":"url"===this.type?"url":void 0,l=this.getDisplayValue();if(n&&e){if(n.type=r,n.value=l,n.placeholder=this.placeholder,n.name=this.name,a?n.inputMode=a:n.removeAttribute("inputmode"),e.className="input-wrapper "+s,n.disabled=this.disabled,this.disabled?n.setAttribute("disabled",""):n.removeAttribute("disabled"),n.required=this.required,this.required?n.setAttribute("required",""):n.removeAttribute("required"),this.label?n.setAttribute("aria-label",this.label):n.removeAttribute("aria-label"),this.label)if(i)i.innerHTML=`${this.label}${this.required?`<span class="required-icon">${Q}</span>`:""}`,i.style.display="flex";else{const n=document.createElement("label");n.className="ty-field-label",n.innerHTML=`${this.label}${this.required?`<span class="required-icon">${Q}</span>`:""}`;const i=t.querySelector(".input-container");i&&i.insertBefore(n,e)}else i&&(i.style.display="none");if(this.error)if(o)o.textContent=this.error;else{const n=document.createElement("div");n.className="error-message",n.textContent=this.error,t.querySelector(".input-container")?.appendChild(n)}else o&&o.remove()}else{t.innerHTML=`\n <div class="input-container">\n ${this.label?`\n <label class="ty-field-label">\n ${this.label}\n ${this.required?`<span class="required-icon">${Q}</span>`:""}\n </label>\n `:""}\n <div class="input-wrapper ${s}">\n <slot name="start"></slot>\n <input\n type="${r}"\n value="${l}"\n placeholder="${this.placeholder}"\n name="${this.name}"\n ${a?`inputmode="${a}"`:""}\n />\n <slot name="end"></slot>\n ${"password"===r?`\n <button class="password-toggle" type="button"\n aria-label="Show password" aria-pressed="false">\n ${tt}\n </button>`:""}\n </div>\n ${this.error?`\n <div class="error-message">${this.error}</div>\n `:""}\n </div>\n `;const n=t.querySelector("input");n.disabled=this.disabled,n.required=this.required,this.label&&n.setAttribute("aria-label",this.label),this.setupPasswordToggle(),this.setupEventListeners()}this.updateValidity()}setupPasswordToggle(){const t=this.shadowRoot,n=t.querySelector(".password-toggle"),e=t.querySelector("input");n&&e&&(n.addEventListener("mousedown",t=>t.preventDefault()),n.addEventListener("click",()=>{const t="password"===e.type;e.type=t?"text":"password",n.innerHTML=t?'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49"/><path d="M14.084 14.158a3 3 0 0 1-4.242-4.242"/><path d="M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143"/><path d="m2 2 20 20"/></svg>':tt,n.setAttribute("aria-label",t?"Hide password":"Show password"),n.setAttribute("aria-pressed",t+"")}))}updateValidity(){const t=this.shadowRoot?.querySelector("input");if(this.disabled)return void this.v.setValidity({});const n=t?t.value:(this.getProperty("value")??"")+"";this.required&&""===n.trim()?this.v.setValidity({valueMissing:!0},"Please fill out this field",t??void 0):this.v.setValidity({})}};nt.formAssociated=!0,nt.properties={type:{type:"string",visual:!0,default:"text",validate:t=>["text","email","password","number","tel","url","currency","percent","compact"].includes(t),coerce:t=>["text","email","password","number","tel","url","currency","percent","compact"].includes(t)?t:"text"},value:{type:"string",visual:!0,formValue:!0,emitChange:!0,default:""},name:{type:"string",default:""},placeholder:{type:"string",visual:!0,default:""},label:{type:"string",visual:!0,default:""},disabled:{type:"boolean",visual:!0,default:!1},required:{type:"boolean",visual:!0,default:!1},error:{type:"string",visual:!0,default:""},size:{type:"string",visual:!0,default:"md",validate:t=>["sm","md","lg"].includes(t),coerce:t=>"xs"===t?"sm":"xl"===t?"lg":["sm","md","lg"].includes(t)?t:"md"},flavor:{type:"string",visual:!0,default:"neutral"},currency:{type:"string",visual:!0,default:"USD"},locale:{type:"string",visual:!0,default:"en-US"},precision:{type:"number",visual:!0,default:void 0,validate:t=>null==t||"number"==typeof t&&t>=0&&10>=t,coerce:t=>{if(null==t)return;const n=+t;return isNaN(n)?void 0:Math.max(0,Math.min(10,Math.floor(n)))}},debounce:{type:"number",default:0,validate:t=>{const n=+t;return!isNaN(n)&&n>=0&&5e3>=n},coerce:t=>{const n=+t;return isNaN(n)?0:Math.max(0,Math.min(5e3,Math.floor(n)))}}};let et=nt;customElements.get("ty-input")||customElements.define("ty-input",et);const it=(t,n)=>{const e=e=>n?`var(--ty-color-${t}${e}, var(--ty-color-${n}${e}))`:`var(--ty-color-${t}${e})`;return`\n:host([flavor="${t}"]) { --checkbox-color: ${e("")}; --checkbox-color-off: ${e("-soft")}; --checkbox-ring: color-mix(in oklab, ${e("")} 25%, transparent); }\n:host([flavor="${t}+"]) { --checkbox-color: ${e("-strong")}; --checkbox-color-off: ${e("-soft")}; --checkbox-ring: color-mix(in oklab, ${e("-strong")} 25%, transparent); }\n:host([flavor="${t}-"]) { --checkbox-color: ${e("-soft")}; --checkbox-color-off: ${e("-faint")}; --checkbox-ring: color-mix(in oklab, ${e("-soft")} 25%, transparent); }\n`},ot=`\n:host {\n display: inline-flex;\n width: auto;\n vertical-align: middle;\n}\n\n.checkbox-container {\n display: inline-flex;\n align-items: center;\n outline: none;\n transition: all 0.15s ease-in-out;\n user-select: none;\n cursor: pointer;\n border-radius: 6px;\n gap: var(--ty-spacing-1);\n /* Default (no flavor attribute) is neutral — defaults don't reflect to the\n host attribute, so the fallbacks here carry the default look. */\n color: var(--checkbox-color-off, var(--ty-color-neutral-soft));\n}\n\n.checkbox-container[aria-checked="true"] {\n color: var(--checkbox-color, var(--ty-color-neutral));\n}\n\n/* Visible focus ring (keyboard) — .focused is toggled by the component.\n Matches the checked-state color so a danger checkbox gets a red ring,\n not a fixed primary one. */\n.checkbox-container.focused,\n.checkbox-container:focus-visible {\n box-shadow: 0 0 0 3px var(--checkbox-ring, color-mix(in oklab, var(--ty-color-primary) 25%, transparent));\n}\n\n.checkbox-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n color: inherit;\n transition: color 0.15s ease-in-out;\n pointer-events: none;\n /* Let the container handle the click */\n}\n\n/* ===== SIZES ===== */\n\n.checkbox-container svg {\n width: 16px;\n height: 16px;\n}\n\n.checkbox-container.xs svg {\n width: 12px;\n height: 12px;\n}\n\n.checkbox-container.sm svg {\n width: 14px;\n height: 14px;\n}\n\n.checkbox-container.lg svg {\n width: 20px;\n height: 20px;\n}\n\n.checkbox-container.xl svg {\n width: 24px;\n height: 24px;\n}\n\n/* ===== SEMANTIC FLAVORS (set --checkbox-color[-off], consumed above) ===== */\n${r.map(t=>it(t)).join("")}\n\n/* ===== STATES ===== */\n\n/* Clean tick: no box outline, just the checkmark. Inactive = faint tick. */\n.checkbox-container:not([aria-checked="true"]) {\n opacity: 0.35;\n}\n\n/* Indeterminate (dash) sits between unchecked and checked */\n.checkbox-container[aria-checked="mixed"] {\n opacity: 0.7;\n}\n\n/* Disabled must stay distinguishable from merely-unchecked: grayscale kills\n the flavor color, and disabled-unchecked drops below the unchecked 0.35. */\n.checkbox-container.disabled {\n pointer-events: none;\n cursor: not-allowed;\n opacity: 0.5;\n filter: grayscale(1);\n}\n\n.checkbox-container.disabled:not([aria-checked="true"]) {\n opacity: 0.2;\n}\n\n/* Error state */\n.checkbox-container.error .checkbox-icon {\n color: var(--ty-color-danger);\n}\n\n.checkbox-container.error:focus {\n box-shadow: 0 0 0 3px color-mix(in oklab, var(--ty-color-danger) 15%, transparent);\n}\n`,st=class extends i{constructor(){super(),this.I=null,this.Y=!1,this.et=null,this.it=null,this.K=null,this.X=null,s(this.shadowRoot,{css:ot,id:"ty-checkbox"})}onConnect(){this.setupEventListeners(),this.D()}D(){this.I=u(this.shadowRoot,this.I,this.flavor,({base:t})=>(t=>it(t,"neutral"))(t))}onDisconnect(){this.removeEventListeners()}onPropertiesChanged(t){t.some(t=>"flavor"===t.name)&&this.D()}getFormValue(){return this.checked?this.value:null}buildClassList(){const t=[this.size];return this.disabled&&t.push("disabled"),this.required&&t.push("required"),t.join(" ")}handleCheckboxClick(t){if(this.disabled)return;const n=!!this.indeterminate||!this.checked;this.indeterminate&&(this.indeterminate=!1),this.checked=n,setTimeout(()=>{const e={value:n,checked:n,formValue:n?this.value:null,originalEvent:t};this.dispatchEvent(new CustomEvent("input",{detail:e,bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("change",{detail:e,bubbles:!0,composed:!0}))},0)}handleCheckboxKeydown(t){this.disabled||["Space"," ","Enter"].includes(t.key)&&(t.preventDefault(),t.stopPropagation(),this.handleCheckboxClick(t))}removeEventListeners(){if(!this.Y)return;this.et&&(this.removeEventListener("click",this.et),this.et=null);const t=this.shadowRoot;if(!t)return;const n=t.querySelector(".checkbox-container");n?(this.it&&(n.removeEventListener("keydown",this.it),this.it=null),this.K&&(n.removeEventListener("focus",this.K),this.K=null),this.X&&(n.removeEventListener("blur",this.X),this.X=null),this.Y=!1):this.Y=!1}setupEventListeners(){if(this.Y)return;const t=this.shadowRoot.querySelector(".checkbox-container");t&&(this.et=t=>{this.handleCheckboxClick(t)},this.it=t=>{this.handleCheckboxKeydown(t)},this.K=()=>{t.classList.add("focused")},this.X=()=>{t.classList.remove("focused")},this.addEventListener("click",this.et),t.addEventListener("keydown",this.it),t.addEventListener("focus",this.K),t.addEventListener("blur",this.X),this.Y=!0)}render(){const t=this.shadowRoot;let n=t.querySelector(".checkbox-container");const e=this.buildClassList(),i=this.indeterminate?"mixed":this.checked+"";if(n)n.className="checkbox-container "+e,n.tabIndex=this.disabled?-1:0,n.setAttribute("aria-checked",i),n.setAttribute("aria-disabled",this.disabled+""),n.setAttribute("aria-required",this.required+"");else{n=document.createElement("div"),n.className="checkbox-container "+e,n.tabIndex=this.disabled?-1:0,n.setAttribute("role","checkbox"),n.setAttribute("aria-checked",i),n.setAttribute("aria-disabled",this.disabled+""),n.setAttribute("aria-required",this.required+"");const o=document.createElement("div");o.className="checkbox-icon",n.appendChild(o),t.appendChild(n)}n.querySelector(".checkbox-icon").innerHTML=this.indeterminate?'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/></svg>':'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>',this.setupEventListeners(),this.applyLabelName(n),this.updateValidity()}updateValidity(){const t=this.shadowRoot?.querySelector(".checkbox-container");this.disabled?this.v.setValidity({}):this.required&&!this.checked?this.v.setValidity({valueMissing:!0},"Please check this box",t??void 0):this.v.setValidity({})}get checked(){return this.getProperty("checked")}set checked(t){this.setProperty("checked",t)}get indeterminate(){return this.getProperty("indeterminate")}set indeterminate(t){this.setProperty("indeterminate",t)}get value(){return this.getProperty("value")}set value(t){this.setProperty("value",t)}get name(){return this.getProperty("name")}set name(t){this.setProperty("name",t)}get disabled(){return this.getProperty("disabled")}set disabled(t){this.setProperty("disabled",t)}get required(){return this.getProperty("required")}set required(t){this.setProperty("required",t)}get size(){return this.getProperty("size")}set size(t){this.setProperty("size",t)}get flavor(){return this.getProperty("flavor")}set flavor(t){this.setProperty("flavor",t)}get form(){return this.v.form}};st.formAssociated=!0,st.properties={checked:{type:"boolean",visual:!0,formValue:!0,emitChange:!0,default:!1},indeterminate:{type:"boolean",visual:!0,default:!1},value:{type:"string",default:"on"},name:{type:"string",default:""},disabled:{type:"boolean",visual:!0,default:!1},required:{type:"boolean",visual:!0,default:!1},size:{type:"string",visual:!0,default:"md",validate:t=>["xs","sm","md","lg","xl"].includes(t),coerce:t=>["xs","sm","md","lg","xl"].includes(t)?t:"md"},flavor:{type:"string",visual:!0,default:"neutral"}};let rt=st;customElements.get("ty-checkbox")||customElements.define("ty-checkbox",rt);const at=(t,n)=>{const e=e=>n?`var(--ty-color-${t}${e}, var(--ty-color-${n}${e}))`:`var(--ty-color-${t}${e})`;return`\n:host([flavor="${t}"]) { --switch-track: ${e("")}; }\n:host([flavor="${t}+"]) { --switch-track: ${e("-strong")}; }\n:host([flavor="${t}-"]) { --switch-track: ${e("-soft")}; }\n`},lt=`\n${Z}\n\n/* Override input's :host so the switch sizes to its visual */\n:host {\n display: inline-flex;\n width: auto;\n vertical-align: middle;\n}\n\n/* ===== SWITCH CONTAINER (just the visual) ===== */\n.switch-container {\n display: inline-block;\n cursor: pointer;\n user-select: none;\n outline: none;\n vertical-align: middle;\n}\n\n.switch-container.disabled {\n cursor: not-allowed;\n opacity: 0.55;\n}\n\n.switch-container:focus-visible .switch-track,\n.switch-container.focused .switch-track {\n box-shadow: 0 0 0 3px var(--ty-input-shadow-focus);\n}\n\n/* ===== TRACK ===== */\n.switch-track {\n position: relative;\n flex-shrink: 0;\n width: 36px;\n height: 20px;\n border-radius: 999px;\n background: var(--ty-color-neutral-soft, var(--ty-input-border));\n transition: background-color 0.18s ease-in-out;\n box-sizing: border-box;\n}\n\n/* ===== THUMB ===== */\n.switch-thumb {\n position: absolute;\n top: 2px;\n left: 2px;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n background: white;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n transition: transform 0.18s ease-in-out, background-color 0.18s ease-in-out;\n}\n\n/* ===== CHECKED STATE ===== */\n/* Default (no flavor attribute) is primary — defaults don't reflect to the\n host attribute, so the base rule's fallback carries the default look. */\n.switch-container[aria-checked="true"] .switch-track {\n background: var(--switch-track, var(--ty-color-primary));\n}\n\n.switch-container[aria-checked="true"] .switch-thumb {\n transform: translateX(16px);\n}\n\n/* ===== SIZE VARIANTS ===== */\n.switch-container.xs .switch-track { width: 26px; height: 14px; }\n.switch-container.xs .switch-thumb { width: 10px; height: 10px; }\n.switch-container.xs[aria-checked="true"] .switch-thumb { transform: translateX(12px); }\n\n.switch-container.sm .switch-track { width: 30px; height: 16px; }\n.switch-container.sm .switch-thumb { width: 12px; height: 12px; }\n.switch-container.sm[aria-checked="true"] .switch-thumb { transform: translateX(14px); }\n\n/* md is default — already set above */\n\n.switch-container.lg .switch-track { width: 44px; height: 24px; }\n.switch-container.lg .switch-thumb { width: 20px; height: 20px; }\n.switch-container.lg[aria-checked="true"] .switch-thumb { transform: translateX(20px); }\n\n.switch-container.xl .switch-track { width: 52px; height: 28px; }\n.switch-container.xl .switch-thumb { width: 24px; height: 24px; }\n.switch-container.xl[aria-checked="true"] .switch-thumb { transform: translateX(24px); }\n\n/* ===== FLAVOR VARIANTS (set --switch-track, consumed above) ===== */\n${r.map(t=>at(t)).join("")}\n\n`,ct=class extends i{constructor(){super(),this.I=null,this.Y=!1,this.et=null,this.it=null,this.K=null,this.X=null,s(this.shadowRoot,{css:lt,id:"ty-switch"})}onConnect(){this.setupEventListeners(),this.D()}onDisconnect(){this.removeEventListeners()}onPropertiesChanged(t){t.some(t=>"flavor"===t.name)&&this.D()}D(){this.I=u(this.shadowRoot,this.I,this.flavor,({base:t})=>(t=>at(t,"neutral"))(t))}getFormValue(){return this.checked?this.value:null}buildClassList(){const t=[this.size];return this.disabled&&t.push("disabled"),this.required&&t.push("required"),t.join(" ")}handleSwitchClick(t){if(this.disabled)return;const n=!this.checked;this.checked=n,setTimeout(()=>{const e={value:n,checked:n,formValue:n?this.value:null,originalEvent:t};this.dispatchEvent(new CustomEvent("input",{detail:e,bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("change",{detail:e,bubbles:!0,composed:!0}))},0)}handleSwitchKeydown(t){this.disabled||["Space"," ","Enter"].includes(t.key)&&(t.preventDefault(),t.stopPropagation(),this.handleSwitchClick(t))}removeEventListeners(){if(!this.Y)return;this.et&&(this.removeEventListener("click",this.et),this.et=null);const t=this.shadowRoot;if(!t)return;const n=t.querySelector(".switch-container");n?(this.it&&(n.removeEventListener("keydown",this.it),this.it=null),this.K&&(n.removeEventListener("focus",this.K),this.K=null),this.X&&(n.removeEventListener("blur",this.X),this.X=null),this.Y=!1):this.Y=!1}setupEventListeners(){if(this.Y)return;const t=this.shadowRoot.querySelector(".switch-container");t&&(this.et=t=>this.handleSwitchClick(t),this.it=t=>this.handleSwitchKeydown(t),this.K=()=>t.classList.add("focused"),this.X=()=>t.classList.remove("focused"),this.addEventListener("click",this.et),t.addEventListener("keydown",this.it),t.addEventListener("focus",this.K),t.addEventListener("blur",this.X),this.Y=!0)}render(){const t=this.shadowRoot;let n=t.querySelector(".switch-container");const e=this.buildClassList();if(n)n.className="switch-container "+e,n.tabIndex=this.disabled?-1:0,n.setAttribute("aria-checked",this.checked?"true":"false"),n.setAttribute("aria-disabled",this.disabled?"true":"false"),n.setAttribute("aria-required",this.required?"true":"false");else{n=document.createElement("div"),n.className="switch-container "+e,n.tabIndex=this.disabled?-1:0,n.setAttribute("role","switch"),n.setAttribute("aria-checked",this.checked?"true":"false"),n.setAttribute("aria-disabled",this.disabled?"true":"false"),n.setAttribute("aria-required",this.required?"true":"false");const i=document.createElement("div");i.className="switch-track";const o=document.createElement("div");o.className="switch-thumb",i.appendChild(o),n.appendChild(i),t.appendChild(n)}this.setupEventListeners(),this.applyLabelName(n),this.updateValidity()}updateValidity(){const t=this.shadowRoot?.querySelector(".switch-container");this.disabled?this.v.setValidity({}):this.required&&!this.checked?this.v.setValidity({valueMissing:!0},"Please turn this on",t??void 0):this.v.setValidity({})}get checked(){return this.getProperty("checked")}set checked(t){this.setProperty("checked",t)}get value(){return this.getProperty("value")}set value(t){this.setProperty("value",t)}get name(){return this.getProperty("name")}set name(t){this.setProperty("name",t)}get disabled(){return this.getProperty("disabled")}set disabled(t){this.setProperty("disabled",t)}get required(){return this.getProperty("required")}set required(t){this.setProperty("required",t)}get size(){return this.getProperty("size")}set size(t){this.setProperty("size",t)}get flavor(){return this.getProperty("flavor")}set flavor(t){this.setProperty("flavor",t)}get form(){return this.v.form}};ct.formAssociated=!0,ct.properties={checked:{type:"boolean",visual:!0,formValue:!0,emitChange:!0,default:!1},value:{type:"string",default:"on"},name:{type:"string",default:""},disabled:{type:"boolean",visual:!0,default:!1},required:{type:"boolean",visual:!0,default:!1},size:{type:"string",visual:!0,default:"md",validate:t=>["xs","sm","md","lg","xl"].includes(t),coerce:t=>["xs","sm","md","lg","xl"].includes(t)?t:"md"},flavor:{type:"string",visual:!0,default:"primary"}};let dt=ct;customElements.get("ty-switch")||customElements.define("ty-switch",dt);const ht=(t,n)=>{const e=e=>n?`var(--ty-color-${t}${e}, var(--ty-color-${n}${e}))`:`var(--ty-color-${t}${e})`;return`\n:host([flavor="${t}"]) { --radio-color: ${e("")}; }\n:host([flavor="${t}+"]) { --radio-color: ${e("-strong")}; }\n:host([flavor="${t}-"]) { --radio-color: ${e("-soft")}; }\n`},ut=`\n${Z}\n\n/* Override input's :host. ty-radio is just the circle (inline);\n ty-radio-group is a form-field block. */\n:host(ty-radio) {\n display: inline-flex;\n width: auto;\n vertical-align: middle;\n}\n\n:host(ty-radio-group) {\n display: block;\n width: 100%;\n}\n\n/* ===== RADIO GROUP ===== */\n.radio-group-container {\n display: flex;\n flex-direction: column;\n gap: 0.4rem;\n font-family: var(--ty-font-sans);\n color: var(--ty-color-text);\n}\n\n.radio-group-label {\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n font-weight: var(--ty-font-medium);\n color: var(--ty-color-text);\n display: flex;\n align-items: center;\n gap: 0.25rem;\n}\n\n.radio-group-list {\n display: flex;\n gap: 0.6rem;\n align-items: flex-start;\n}\n\n.radio-group-list.vertical {\n flex-direction: column;\n align-items: flex-start;\n}\n\n.radio-group-list.horizontal {\n flex-direction: row;\n flex-wrap: wrap;\n align-items: center;\n}\n\n.radio-group-error {\n font-size: var(--ty-font-xs);\n line-height: var(--ty-leading-xs);\n color: var(--ty-color-danger);\n}\n\n.radio-group-container .required-icon {\n width: 0.65em;\n height: 0.65em;\n color: var(--ty-color-danger);\n}\n.radio-group-container .required-icon svg {\n width: 100%;\n height: 100%;\n}\n\n/* ===== RADIO ITEM (just the circle) ===== */\n.radio-container {\n display: inline-block;\n cursor: pointer;\n user-select: none;\n outline: none;\n vertical-align: middle;\n}\n\n.radio-container.disabled {\n cursor: not-allowed;\n opacity: 0.55;\n}\n\n.radio-container:focus-visible .radio-circle,\n.radio-container.focused .radio-circle {\n box-shadow: 0 0 0 3px var(--ty-input-shadow-focus);\n}\n\n.radio-circle {\n position: relative;\n flex-shrink: 0;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n border: 2px solid var(--ty-input-border);\n background: var(--ty-input-bg);\n box-sizing: border-box;\n transition: border-color 0.15s ease-in-out;\n}\n\n/* Default (no flavor attribute) is primary — defaults don't reflect to the\n host attribute, so the base rules' fallback carries the default look. */\n.radio-circle::after {\n content: "";\n position: absolute;\n top: 50%;\n left: 50%;\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: var(--radio-color, var(--ty-color-primary));\n transform: translate(-50%, -50%) scale(0);\n transition: transform 0.15s ease-in-out;\n}\n\n.radio-container[aria-checked="true"] .radio-circle {\n border-color: var(--radio-color, var(--ty-color-primary));\n}\n\n.radio-container[aria-checked="true"] .radio-circle::after {\n transform: translate(-50%, -50%) scale(1);\n}\n\n/* Size variants */\n.radio-container.xs .radio-circle { width: 14px; height: 14px; }\n.radio-container.xs .radio-circle::after { width: 6px; height: 6px; }\n\n.radio-container.sm .radio-circle { width: 16px; height: 16px; }\n.radio-container.sm .radio-circle::after { width: 7px; height: 7px; }\n\n.radio-container.lg .radio-circle { width: 22px; height: 22px; }\n.radio-container.lg .radio-circle::after { width: 10px; height: 10px; }\n\n.radio-container.xl .radio-circle { width: 26px; height: 26px; }\n.radio-container.xl .radio-circle::after { width: 12px; height: 12px; }\n\n/* Flavor variants — set --radio-color, consumed by the base rules above */\n${r.map(t=>ht(t)).join("")}\n`,pt=class extends i{constructor(){super(),this.I=null,this.Y=!1,this.et=null,this.K=null,this.X=null,s(this.shadowRoot,{css:ut,id:"ty-radio"})}onConnect(){this.setupEventListeners(),this.dispatchEvent(new CustomEvent("ty-radio-connected",{bubbles:!0})),this.D()}onDisconnect(){this.removeEventListeners()}onPropertiesChanged(t){t.some(t=>"flavor"===t.name)&&this.D()}D(){this.I=u(this.shadowRoot,this.I,this.flavor,({base:t})=>(t=>ht(t,"neutral"))(t))}buildClassList(){const t=[this.size];return this.disabled&&t.push("disabled"),t.join(" ")}handleClick(t){this.disabled||(t.stopPropagation(),this.dispatchEvent(new CustomEvent("ty-radio-select",{detail:{value:this.value},bubbles:!0,composed:!0})))}removeEventListeners(){if(!this.Y)return;this.et&&(this.removeEventListener("click",this.et),this.et=null);const t=this.shadowRoot?.querySelector(".radio-container");t?(this.K&&(t.removeEventListener("focus",this.K),this.K=null),this.X&&(t.removeEventListener("blur",this.X),this.X=null),this.Y=!1):this.Y=!1}setupEventListeners(){if(this.Y)return;const t=this.shadowRoot.querySelector(".radio-container");t&&(this.et=t=>this.handleClick(t),this.K=()=>t.classList.add("focused"),this.X=()=>t.classList.remove("focused"),this.addEventListener("click",this.et),t.addEventListener("focus",this.K),t.addEventListener("blur",this.X),this.Y=!0)}render(){const t=this.shadowRoot;let n=t.querySelector(".radio-container");const e=this.buildClassList();if(n)n.className="radio-container "+e,n.tabIndex=this.disabled?-1:0,n.setAttribute("aria-checked",this.checked+""),n.setAttribute("aria-disabled",this.disabled+"");else{n=document.createElement("div"),n.className="radio-container "+e,n.tabIndex=this.disabled?-1:0,n.setAttribute("role","radio"),n.setAttribute("aria-checked",this.checked+""),n.setAttribute("aria-disabled",this.disabled+"");const i=document.createElement("div");i.className="radio-circle",n.appendChild(i),t.appendChild(n)}this.setupEventListeners(),this.applyLabelName(n)}get value(){return this.getProperty("value")}set value(t){this.setProperty("value",t)}get checked(){return this.getProperty("checked")}set checked(t){this.setProperty("checked",t)}get disabled(){return this.getProperty("disabled")}set disabled(t){this.setProperty("disabled",t)}get size(){return this.getProperty("size")}set size(t){this.setProperty("size",t)}get flavor(){return this.getProperty("flavor")}set flavor(t){this.setProperty("flavor",t)}};pt.properties={value:{type:"string",default:""},checked:{type:"boolean",visual:!0,default:!1},disabled:{type:"boolean",visual:!0,default:!1},size:{type:"string",visual:!0,default:"md"},flavor:{type:"string",visual:!0,default:"primary"}};let bt=pt;customElements.get("ty-radio")||customElements.define("ty-radio",bt);const gt=class extends i{constructor(){super(),this.Y=!1,this.ot=null,this.it=null,this.st=null,s(this.shadowRoot,{css:ut,id:"ty-radio-group"})}onConnect(){this.setupEventListeners(),queueMicrotask(()=>this.syncChildren())}onDisconnect(){this.removeEventListeners()}onPropertiesChanged(t){t.some(t=>"value"===t.name||"size"===t.name||"flavor"===t.name||"disabled"===t.name)&&this.syncChildren()}getFormValue(){return this.value||null}getRadios(){return Array.from(this.querySelectorAll("ty-radio"))}syncChildren(){const t=this.getRadios();for(const n of t)n.checked=n.value===this.value,this.disabled&&(n.disabled=!0),n.size=this.size,n.flavor=this.flavor}handleRadioSelect(t){if(this.disabled)return;const n=t.detail,e=n?.value;"string"==typeof e&&e!==this.value&&(this.value=e,this.syncChildren(),setTimeout(()=>{const n={value:e,formValue:e,originalEvent:t};this.dispatchEvent(new CustomEvent("input",{detail:n,bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("change",{detail:n,bubbles:!0,composed:!0}))},0))}handleKeydown(t){if(this.disabled)return;const n=this.getRadios().filter(t=>!t.disabled);if(0===n.length)return;const e=document.activeElement,i=n.find(t=>t===e||t.contains(e));let o=-1;if(["ArrowDown","ArrowRight"].includes(t.key))t.preventDefault(),o=i?(n.indexOf(i)+1)%n.length:0;else{if(!["ArrowUp","ArrowLeft"].includes(t.key)){if(["Space"," ","Enter"].includes(t.key)){if(i){t.preventDefault(),this.value=i.value,this.syncChildren();const n={value:i.value,formValue:i.value,originalEvent:t};setTimeout(()=>{this.dispatchEvent(new CustomEvent("change",{detail:n,bubbles:!0,composed:!0}))},0)}return}return}t.preventDefault(),o=i?(n.indexOf(i)-1+n.length)%n.length:n.length-1}const s=n[o];if(s){s.focus(),this.value=s.value,this.syncChildren();const n={value:s.value,formValue:s.value,originalEvent:t};setTimeout(()=>{this.dispatchEvent(new CustomEvent("change",{detail:n,bubbles:!0,composed:!0}))},0)}}removeEventListeners(){this.Y&&(this.ot&&(this.removeEventListener("ty-radio-select",this.ot),this.ot=null),this.it&&(this.removeEventListener("keydown",this.it),this.it=null),this.st&&(this.removeEventListener("ty-radio-connected",this.st),this.st=null),this.Y=!1)}setupEventListeners(){this.Y||(this.ot=t=>this.handleRadioSelect(t),this.it=t=>this.handleKeydown(t),this.st=()=>this.syncChildren(),this.addEventListener("ty-radio-select",this.ot),this.addEventListener("keydown",this.it),this.addEventListener("ty-radio-connected",this.st),this.Y=!0)}render(){const t=this.shadowRoot;let n=t.querySelector(".radio-group-container");if(n){let t=n.querySelector(".radio-group-label");if(this.label)if(t||(t=document.createElement("div"),t.className="radio-group-label",n.insertBefore(t,n.firstChild)),t.textContent=this.label,this.required&&!t.querySelector(".required-icon")){const n=document.createElement("span");n.className="required-icon",n.innerHTML=Q,t.appendChild(n)}else this.required||t.querySelector(".required-icon")?.remove();else t&&t.remove();const e=n.querySelector(".radio-group-list");e&&(e.className="radio-group-list "+this.orientation);let i=n.querySelector(".radio-group-error");this.error?(i||(i=document.createElement("div"),i.className="radio-group-error",n.appendChild(i)),i.textContent=this.error):i&&i.remove(),n.setAttribute("aria-disabled",this.disabled+"")}else{if(n=document.createElement("div"),n.className="radio-group-container",n.setAttribute("role","radiogroup"),n.setAttribute("aria-disabled",this.disabled+""),this.label){const t=document.createElement("div");if(t.className="radio-group-label",t.textContent=this.label,this.required){const n=document.createElement("span");n.className="required-icon",n.innerHTML=Q,t.appendChild(n)}n.appendChild(t)}const e=document.createElement("div");e.className="radio-group-list "+this.orientation;const i=document.createElement("slot");if(e.appendChild(i),n.appendChild(e),this.error){const t=document.createElement("div");t.className="radio-group-error",t.textContent=this.error,n.appendChild(t)}t.appendChild(n),this.setupEventListeners()}this.syncChildren()}get value(){return this.getProperty("value")}set value(t){this.setProperty("value",t)}get name(){return this.getProperty("name")}set name(t){this.setProperty("name",t)}get label(){return this.getProperty("label")}set label(t){this.setProperty("label",t)}get disabled(){return this.getProperty("disabled")}set disabled(t){this.setProperty("disabled",t)}get required(){return this.getProperty("required")}set required(t){this.setProperty("required",t)}get error(){return this.getProperty("error")}set error(t){this.setProperty("error",t)}get orientation(){return this.getProperty("orientation")}set orientation(t){this.setProperty("orientation",t)}get size(){return this.getProperty("size")}set size(t){this.setProperty("size",t)}get flavor(){return this.getProperty("flavor")}set flavor(t){this.setProperty("flavor",t)}get form(){return this.v.form}};gt.formAssociated=!0,gt.properties={value:{type:"string",visual:!0,formValue:!0,emitChange:!0,default:""},name:{type:"string",default:""},label:{type:"string",visual:!0,default:""},disabled:{type:"boolean",visual:!0,default:!1},required:{type:"boolean",visual:!0,default:!1},error:{type:"string",visual:!0,default:""},orientation:{type:"string",visual:!0,default:"vertical"},size:{type:"string",visual:!0,default:"md"},flavor:{type:"string",visual:!0,default:"primary"}};let mt=gt;customElements.get("ty-radio-group")||customElements.define("ty-radio-group",mt);const vt=(t,n)=>{const e=e=>n?`var(--ty-color-${t}${e}, var(--ty-color-${n}${e}))`:`var(--ty-color-${t}${e})`,i=e=>n?`var(--ty-bg-${t}${e}, var(--ty-bg-${n}${e}))`:`var(--ty-bg-${t}${e})`;return`\n:host([flavor="${t}"]) { --copy-color: ${e("")}; --copy-color-hover: ${e("-strong")}; --copy-bg-hover: ${i("-soft")}; }\n:host([flavor="${t}+"]) { --copy-color: ${e("-strong")}; --copy-color-hover: ${e("-strong")}; --copy-bg-hover: ${i("-soft")}; }\n:host([flavor="${t}-"]) { --copy-color: ${e("-soft")}; --copy-color-hover: ${e("")}; --copy-bg-hover: ${i("-soft")}; }\n`},yt=`\n/* Copy field value display */\n.copy-field-value {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n user-select: none;\n padding: 0;\n margin: 0;\n background: transparent;\n border: none;\n color: inherit;\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\n/* Multiline variant */\n.copy-field-value.multiline {\n white-space: pre-wrap;\n word-break: break-word;\n max-height: 200px;\n overflow-y: auto;\n}\n\n/* Keep the copy button pinned to the top-right when content wraps to multiple lines */\n.input-wrapper:has(.copy-field-value.multiline) {\n align-items: flex-start;\n padding-top: 8px;\n padding-bottom: 8px;\n}\n\n/* Horizontal scroll variant - scroll long content instead of clipping with ellipsis */\n.copy-field-value.horizontal-scroll {\n overflow-x: auto;\n overflow-y: hidden;\n text-overflow: clip;\n white-space: nowrap;\n}\n\n/* Multiline + horizontal scroll (e.g. code blocks): preserve lines, scroll both axes */\n.copy-field-value.multiline.horizontal-scroll {\n white-space: pre;\n word-break: normal;\n overflow-y: auto;\n}\n\n/* Hide scrollbars on scrollable value - content still scrolls, chrome stays clean */\n.copy-field-value.multiline,\n.copy-field-value.horizontal-scroll {\n scrollbar-width: none; /* Firefox */\n}\n.copy-field-value.multiline::-webkit-scrollbar,\n.copy-field-value.horizontal-scroll::-webkit-scrollbar {\n display: none; /* Chrome/Safari */\n}\n\n/* Code format */\n.copy-field-value {\n font-size: 0.8em;\n}\n\n/* Hover state — flavor-soft background (primary by default) */\n.input-wrapper:not(.disabled):hover {\n background: var(--copy-bg-hover, var(--ty-bg-primary-soft));\n transition: background 0.2s ease;\n}\n\n/* Copy button */\n.copy-button {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n cursor: pointer;\n border: none;\n background: transparent;\n color: var(--copy-color, var(--ty-text-soft));\n transition: color 0.2s ease, transform 0.2s ease;\n padding: 0;\n margin: 0;\n}\n\n.copy-button:hover:not(.disabled) {\n color: var(--copy-color-hover, var(--ty-text));\n transform: scale(1.1);\n}\n\n.copy-button.success {\n color: var(--ty-color-success);\n animation: copy-feedback 0.3s ease;\n}\n\n.copy-button.error {\n color: var(--ty-color-danger);\n animation: copy-feedback 0.3s ease;\n}\n\n@keyframes copy-feedback {\n 0%, 100% { transform: scale(1); }\n 50% { transform: scale(1.2); }\n}\n\n.copy-button svg {\n width: 18px;\n height: 18px;\n}\n\n.input-wrapper.disabled .copy-button {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n.input-wrapper.disabled {\n cursor: not-allowed;\n}\n\n/* ===== SEMANTIC FLAVORS (set --copy-*, consumed above) ===== */\n${r.map(t=>vt(t)).join("")}\n`,ft='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>',wt='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>',xt=class extends i{constructor(){super(),this.rt=null,this.lt=!1,this.I=null,s(this.shadowRoot,{css:Z,id:"ty-input"}),s(this.shadowRoot,{css:yt,id:"ty-copy"})}onConnect(){this.D()}D(){this.I=u(this.shadowRoot,this.I,this.flavor,({base:t})=>(t=>vt(t,"neutral"))(t))}onDisconnect(){null!==this.rt&&(clearTimeout(this.rt),this.rt=null)}onPropertiesChanged(t){t.some(t=>"flavor"===t.name)&&this.D()}buildClassList(){const t=[this.size];return this.disabled&&t.push("disabled"),this.required&&t.push("required"),t.join(" ")}async copyToClipboard(){if(!this.disabled&&this.value){try{await navigator.clipboard.writeText(this.value),this.dispatchEvent(new CustomEvent("copy-success",{detail:{value:this.value},bubbles:!0,composed:!0}))}catch(t){try{const t=document.createElement("textarea");t.value=this.value,t.style.position="fixed",t.style.opacity="0",document.body.appendChild(t),t.select(),document.execCommand("copy"),document.body.removeChild(t),this.dispatchEvent(new CustomEvent("copy-success",{detail:{value:this.value},bubbles:!0,composed:!0}))}catch(n){return this.dispatchEvent(new CustomEvent("copy-error",{detail:{error:n},bubbles:!0,composed:!0})),void this.showCopyError()}}this.showCopySuccess()}}showCopySuccess(){null!==this.rt&&clearTimeout(this.rt),this.lt=!0;const t=this.shadowRoot.querySelector(".copy-button");t&&(t.classList.add("success"),t.innerHTML=wt,t.setAttribute("aria-label","Copied!")),this.rt=window.setTimeout(()=>{this.lt=!1;const t=this.shadowRoot.querySelector(".copy-button");t&&(t.classList.remove("success"),t.innerHTML=ft,t.setAttribute("aria-label","Copy to clipboard")),this.rt=null},2e3)}showCopyError(){null!==this.rt&&clearTimeout(this.rt),this.lt=!1;const t=this.shadowRoot.querySelector(".copy-button");t&&(t.classList.add("error"),t.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>',t.setAttribute("aria-label","Copy failed")),this.rt=window.setTimeout(()=>{const t=this.shadowRoot.querySelector(".copy-button");t&&(t.classList.remove("error"),t.innerHTML=ft,t.setAttribute("aria-label","Copy to clipboard")),this.rt=null},2e3)}setupEventListeners(){const t=this.shadowRoot,n=t.querySelector(".input-wrapper"),e=t.querySelector(".copy-button");if(n&&!this.disabled){const t=n;t.addEventListener("click",t=>{t.target===e||t.target.closest(".copy-button")||this.copyToClipboard()}),t.style.cursor="pointer"}e&&e.addEventListener("click",()=>{this.copyToClipboard()})}render(){const t=this.shadowRoot,n=this.buildClassList(),e=["copy-field-value",this.multiline?"multiline":"",this.horizontalScroll?"horizontal-scroll":""].filter(Boolean).join(" ");t.innerHTML=`\n <div class="input-container">\n ${this.label?`\n <label class="ty-field-label">\n ${this.label}\n ${this.required?`<span class="required-icon">${Q}</span>`:""}\n </label>\n `:""}\n <div class="input-wrapper ${n}">\n ${"code"===this.format?`<code class="${e}">${this.value||""}</code>`:`<div class="${e}">${this.value||""}</div>`}\n <button class="copy-button${this.lt?" success":""}" type="button" aria-label="${this.lt?"Copied!":"Copy to clipboard"}" ${this.disabled?"disabled":""}>\n ${this.lt?wt:ft}\n </button>\n </div>\n </div>\n `,this.setupEventListeners()}get value(){return this.getProperty("value")}set value(t){this.setProperty("value",t)}get label(){return this.getProperty("label")}set label(t){this.setProperty("label",t)}get size(){return this.getProperty("size")}set size(t){this.setProperty("size",t)}get flavor(){return this.getProperty("flavor")}set flavor(t){this.setProperty("flavor",t)}get format(){return this.getProperty("format")}set format(t){this.setProperty("format",t)}get multiline(){return this.getProperty("multiline")}set multiline(t){this.setProperty("multiline",t)}get horizontalScroll(){return this.getProperty("horizontalScroll")}set horizontalScroll(t){this.setProperty("horizontalScroll",t)}get disabled(){return this.getProperty("disabled")}set disabled(t){this.setProperty("disabled",t)}get required(){return this.getProperty("required")}set required(t){this.setProperty("required",t)}};xt.formAssociated=!0,xt.properties={value:{type:"string",visual:!0,formValue:!0,default:""},label:{type:"string",visual:!0,default:""},size:{type:"string",visual:!0,default:"md",validate:t=>["xs","sm","md","lg","xl"].includes(t),coerce:t=>["xs","sm","md","lg","xl"].includes(t)?t:"md"},flavor:{type:"string",visual:!0,default:"neutral"},format:{type:"string",visual:!0,default:"text",coerce:t=>"code"===t?"code":"text"},multiline:{type:"boolean",visual:!0,default:!1},horizontalScroll:{type:"boolean",visual:!0,default:!1},disabled:{type:"boolean",visual:!0,default:!1},required:{type:"boolean",visual:!0,default:!1}};let kt=xt;function zt(t){return 1024>t?t+" B":1048576>t?(t/1024).toFixed(1)+" KB":1073741824>t?(t/1024/1024).toFixed(1)+" MB":(t/1024/1024/1024).toFixed(1)+" GB"}customElements.get("ty-copy")||customElements.define("ty-copy",kt),customElements.get("ty-copy-field")||customElements.define("ty-copy-field",class extends kt{});const $t=class extends i{constructor(){super(),this.ct=[],this.dt=!1,this.Y=!1,this.ht=null,this.ut=null,this.bt=null,this.gt=null,this.vt=null,this.yt=null,this.ft=null,this.wt=null,s(this.shadowRoot,{css:"\n:host {\n display: block;\n font-family: var(--ty-font-sans);\n width: 100%;\n}\n\n.file-upload-container {\n display: flex;\n flex-direction: column;\n width: 100%;\n box-sizing: border-box;\n}\n\n/* ===== LABEL ===== */\n\n.upload-label {\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n font-weight: var(--ty-font-medium);\n color: var(--ty-label-color);\n margin-bottom: 6px;\n padding-left: 4px;\n display: flex;\n align-items: center;\n}\n\n.required-icon {\n color: var(--ty-color-danger);\n margin-left: 4px;\n font-size: 0.75rem;\n line-height: 1;\n}\n\n/* ===== DROP ZONE ===== */\n\n.drop-zone {\n border: 2px dashed var(--ty-border);\n border-radius: var(--ty-radius-base);\n padding: 2rem 1.5rem;\n text-align: center;\n cursor: pointer;\n transition: border-color 0.15s ease, background-color 0.15s ease, box-shadow 0.15s ease;\n outline: none;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n min-height: 140px;\n user-select: none;\n}\n\n.drop-zone:hover:not(.disabled) {\n border-color: var(--ty-input-border-hover);\n background: var(--ty-surface-content);\n}\n\n.drop-zone.focused {\n border-color: var(--ty-input-border-focus);\n box-shadow: 0 0 0 3px var(--ty-input-shadow-focus);\n}\n\n.drop-zone.drag-active {\n border-color: var(--ty-color-primary);\n border-style: solid;\n background: var(--ty-bg-primary-);\n}\n\n.drop-zone.drag-active .upload-icon {\n color: var(--ty-color-primary);\n transform: translateY(-2px);\n}\n\n.drop-zone.has-files {\n min-height: 80px;\n padding: 1.25rem 1.5rem;\n}\n\n.drop-zone.disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n}\n\n.drop-zone.error {\n border-color: var(--ty-color-danger);\n}\n\n.drop-zone.error:not(.disabled) {\n background: var(--ty-bg-danger-);\n}\n\n/* ===== UPLOAD ICON ===== */\n\n.upload-icon {\n color: var(--ty-text-faint);\n width: 2.5rem;\n height: 2.5rem;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: color 0.15s ease, transform 0.15s ease;\n pointer-events: none;\n}\n\n.upload-icon svg {\n width: 100%;\n height: 100%;\n}\n\n/* ===== HINT TEXT ===== */\n\n.upload-hint {\n color: var(--ty-text-soft);\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n pointer-events: none;\n}\n\n.browse-link {\n color: var(--ty-color-primary);\n font-weight: var(--ty-font-medium);\n}\n\n.upload-sub-hint {\n color: var(--ty-text-faint);\n font-size: var(--ty-font-xs);\n line-height: var(--ty-leading-xs);\n pointer-events: none;\n}\n\n/* ===== FILE LIST ===== */\n\n.file-list {\n display: flex;\n flex-direction: column;\n gap: 0.375rem;\n margin-top: 0.5rem;\n}\n\n.file-item {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.5rem 0.75rem;\n border-radius: var(--ty-radius-base);\n background: var(--ty-surface-content);\n border: 1px solid var(--ty-border-soft);\n}\n\n.file-icon {\n color: var(--ty-text-faint);\n flex-shrink: 0;\n width: 1rem;\n height: 1rem;\n display: flex;\n align-items: center;\n}\n\n.file-icon svg {\n width: 100%;\n height: 100%;\n}\n\n.file-name {\n flex: 1;\n font-size: var(--ty-font-sm);\n color: var(--ty-text);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n min-width: 0;\n}\n\n.file-size {\n font-size: var(--ty-font-xs);\n color: var(--ty-text-faint);\n flex-shrink: 0;\n font-variant-numeric: tabular-nums;\n}\n\n.file-remove {\n flex-shrink: 0;\n cursor: pointer;\n color: var(--ty-text-faint);\n width: 1.25rem;\n height: 1.25rem;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n transition: color 0.15s ease, background-color 0.15s ease;\n border: none;\n background: none;\n padding: 0;\n outline: none;\n}\n\n.file-remove:hover {\n color: var(--ty-color-danger);\n background: var(--ty-bg-danger-);\n}\n\n.file-remove:focus-visible {\n box-shadow: 0 0 0 2px var(--ty-color-danger);\n}\n\n.file-remove svg {\n width: 12px;\n height: 12px;\n}\n\n/* ===== ERROR MESSAGE ===== */\n\n.error-message {\n font-size: var(--ty-font-xs);\n line-height: var(--ty-leading-xs);\n color: var(--ty-color-danger);\n margin-top: 4px;\n padding-left: 4px;\n}\n\n/* ===== ACCESSIBILITY ===== */\n\n@media (prefers-reduced-motion: reduce) {\n .drop-zone,\n .upload-icon,\n .file-remove {\n transition: none;\n }\n}\n\n@media (prefers-contrast: high) {\n .drop-zone {\n border-width: 3px;\n }\n}\n",id:"ty-file-upload"})}onConnect(){}onDisconnect(){this.removeEventListeners()}onPropertiesChanged(t){}onFormReset(){this.ct=[],this.updateFormValue(),this.p&&this.render();const t=this.shadowRoot?.querySelector(".file-input");t&&(t.value="")}getFormValue(){if(0===this.ct.length)return null;const t=new FormData,n=this.name||"files";for(const e of this.ct)t.append(n,e);return t}get files(){return[...this.ct]}get multiple(){return this.getProperty("multiple")}set multiple(t){this.setProperty("multiple",t)}get accept(){return this.getProperty("accept")}set accept(t){this.setProperty("accept",t)}get name(){return this.getProperty("name")}set name(t){this.setProperty("name",t)}get disabled(){return this.getProperty("disabled")}set disabled(t){this.setProperty("disabled",t)}get required(){return this.getProperty("required")}set required(t){this.setProperty("required",t)}get label(){return this.getProperty("label")}set label(t){this.setProperty("label",t)}get placeholder(){return this.getProperty("placeholder")}set placeholder(t){this.setProperty("placeholder",t)}get error(){return this.getProperty("error")}set error(t){this.setProperty("error",t)}get form(){return this.v.form}setFiles(t){this.ct=this.multiple?t:t.slice(0,1),this.updateFormValue(),this.render();const n={value:this.ct,files:this.ct,names:this.ct.map(t=>t.name)};setTimeout(()=>{this.dispatchEvent(new CustomEvent("change",{detail:n,bubbles:!0,composed:!0}))},0)}removeFile(t){const n=[...this.ct];n.splice(t,1),this.setFiles(n);const e=this.shadowRoot?.querySelector(".file-input");e&&(e.value="")}setupEventListeners(){if(this.Y)return;const t=this.shadowRoot,n=t.querySelector(".drop-zone"),e=t.querySelector(".file-input");this.ht=t=>{this.disabled||t.target.closest(".file-remove")||e.click()},this.ut=t=>{this.disabled||"Enter"!==t.key&&" "!==t.key||(t.preventDefault(),e.click())},this.bt=()=>{n.classList.add("focused")},this.gt=()=>{n.classList.remove("focused")},this.vt=t=>{this.disabled||(t.preventDefault(),t.stopPropagation(),this.dt||(this.dt=!0,n.classList.add("drag-active")))},this.yt=t=>{n.contains(t.relatedTarget)||(this.dt=!1,n.classList.remove("drag-active"))},this.ft=t=>{if(this.disabled)return;t.preventDefault(),t.stopPropagation(),this.dt=!1,n.classList.remove("drag-active");const e=Array.from(t.dataTransfer?.files??[]);e.length>0&&this.setFiles(e)},this.wt=t=>{const n=t.target;n.files&&n.files.length>0&&this.setFiles(Array.from(n.files))},n.addEventListener("click",this.ht),n.addEventListener("keydown",this.ut),n.addEventListener("focus",this.bt),n.addEventListener("blur",this.gt),n.addEventListener("dragover",this.vt),n.addEventListener("dragleave",this.yt),n.addEventListener("drop",this.ft),e.addEventListener("change",this.wt),this.Y=!0}removeEventListeners(){if(!this.Y)return;const t=this.shadowRoot;if(!t)return;const n=t.querySelector(".drop-zone"),e=t.querySelector(".file-input");n&&e&&(this.ht&&n.removeEventListener("click",this.ht),this.ut&&n.removeEventListener("keydown",this.ut),this.bt&&n.removeEventListener("focus",this.bt),this.gt&&n.removeEventListener("blur",this.gt),this.vt&&n.removeEventListener("dragover",this.vt),this.yt&&n.removeEventListener("dragleave",this.yt),this.ft&&n.removeEventListener("drop",this.ft),this.wt&&e.removeEventListener("change",this.wt),this.Y=!1)}buildDropZoneClasses(){const t=["drop-zone"];return this.dt&&t.push("drag-active"),this.ct.length>0&&t.push("has-files"),this.disabled&&t.push("disabled"),this.error&&t.push("error"),t.join(" ")}renderFileList(t){t.innerHTML="";for(let n=0;this.ct.length>n;n++){const e=this.ct[n],i=document.createElement("div");i.className="file-item";const o=document.createElement("span");o.className="file-icon",o.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>';const s=document.createElement("span");s.className="file-name",s.textContent=e.name,s.title=e.name;const r=document.createElement("span");r.className="file-size",r.textContent=zt(e.size);const a=document.createElement("button");a.className="file-remove",a.type="button",a.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>',a.setAttribute("aria-label","Remove "+e.name);const l=n;a.addEventListener("click",t=>{t.stopPropagation(),this.removeFile(l)}),i.appendChild(o),i.appendChild(s),i.appendChild(r),i.appendChild(a),t.appendChild(i)}}render(){const t=this.shadowRoot;let n=t.querySelector(".file-upload-container");if(!n){n=document.createElement("div"),n.className="file-upload-container";const e=document.createElement("div");e.className="upload-label",n.appendChild(e);const i=document.createElement("div");i.className="drop-zone",i.setAttribute("role","button");const o=document.createElement("input");o.type="file",o.className="file-input",o.style.display="none",i.appendChild(o);const s=document.createElement("div");s.className="upload-icon",s.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>',i.appendChild(s);const r=document.createElement("div");r.className="upload-hint",i.appendChild(r);const a=document.createElement("div");a.className="upload-sub-hint",i.appendChild(a),n.appendChild(i);const l=document.createElement("div");l.className="file-list",n.appendChild(l);const c=document.createElement("div");c.className="error-message",n.appendChild(c),t.appendChild(n),this.setupEventListeners()}const e=n.querySelector(".upload-label");if(this.label){if(e.style.display="",e.innerHTML="",e.appendChild(document.createTextNode(this.label)),this.required){const t=document.createElement("span");t.className="required-icon",t.textContent="*",t.setAttribute("aria-hidden","true"),e.appendChild(t)}}else e.style.display="none";const i=n.querySelector(".drop-zone");i.className=this.buildDropZoneClasses(),i.tabIndex=this.disabled?-1:0,i.setAttribute("aria-disabled",this.disabled+""),i.setAttribute("aria-label",this.placeholder||"Upload files");const o=n.querySelector(".file-input");o.multiple=this.multiple,o.accept=this.accept,o.disabled=this.disabled,n.querySelector(".upload-icon").style.display=this.ct.length>0?"none":"",n.querySelector(".upload-hint").innerHTML=this.ct.length>0?`<strong>${this.ct.length} file${1!==this.ct.length?"s":""} selected</strong>`:'Drop files here or <span class="browse-link">click to browse</span>';const s=n.querySelector(".upload-sub-hint");this.accept&&0===this.ct.length?(s.textContent="Accepted: "+this.accept,s.style.display=""):s.style.display="none";const r=n.querySelector(".file-list");this.renderFileList(r);const a=n.querySelector(".error-message");a.textContent=this.error,a.style.display=this.error?"":"none"}};$t.formAssociated=!0,$t.properties={multiple:{type:"boolean",visual:!0,default:!1},accept:{type:"string",visual:!0,default:""},name:{type:"string",default:""},disabled:{type:"boolean",visual:!0,default:!1},required:{type:"boolean",visual:!0,default:!1},label:{type:"string",visual:!0,default:""},placeholder:{type:"string",visual:!0,default:"Drop files here or click to browse"},error:{type:"string",visual:!0,default:""}};let Ct=$t;function St(){return"native"!==document.documentElement.getAttribute("data-ty-scrollbar")}customElements.get("ty-file-upload")||customElements.define("ty-file-upload",Ct);class Et{constructor(t,n={}){this.trackY=null,this.thumbY=null,this.trackX=null,this.thumbX=null,this.dt=!1,this.xt="y",this.kt=0,this.zt=0,this.$t=null,this.Ct=null,this.St=null,this.Et=t,this.Tt=!1!==n.vertical,this.Mt=n.horizontal??!1,this.At=n.autoHideDelay??1e3,this.It=this.Dt.bind(this),this.Lt=this.Ot.bind(this),this.Nt=this.Rt.bind(this),this.qt=this.Vt.bind(this),this.Pt=this.Ft.bind(this),this.Ht=this.Bt.bind(this),this.jt=this.Wt.bind(this),this.Tt&&(this.trackY=this._t("y"),this.thumbY=this.Yt("y"),this.trackY.appendChild(this.thumbY)),this.Mt&&(this.trackX=this._t("x"),this.thumbX=this.Yt("x"),this.trackX.appendChild(this.thumbX)),this.Et.addEventListener("scroll",this.It,{passive:!0}),this.thumbY&&this.thumbY.addEventListener("pointerdown",this.Lt),this.trackY&&this.trackY.addEventListener("pointerdown",this.qt),this.thumbX&&this.thumbX.addEventListener("pointerdown",this.Nt),this.trackX&&this.trackX.addEventListener("pointerdown",this.Pt),this.St=new ResizeObserver(()=>this.update()),this.St.observe(this.Et),this.update()}_t(t){const n=document.createElement("div");return n.className="ty-scrollbar-track-"+t,n}Yt(t){const n=document.createElement("div");return n.className="ty-scrollbar-thumb-"+t,n}update(){this.Ut(),this.Gt()}scrollToTop(t=!1){this.Et.scrollTo({top:0,behavior:t?"smooth":"auto"})}scrollToBottom(t=!1){this.Et.scrollTo({top:this.Et.scrollHeight,behavior:t?"smooth":"auto"})}scrollToLeft(t=!1){this.Et.scrollTo({left:0,behavior:t?"smooth":"auto"})}scrollToRight(t=!1){this.Et.scrollTo({left:this.Et.scrollWidth,behavior:t?"smooth":"auto"})}destroy(){this.Et.removeEventListener("scroll",this.It),this.thumbY&&this.thumbY.removeEventListener("pointerdown",this.Lt),this.trackY&&this.trackY.removeEventListener("pointerdown",this.qt),this.thumbX&&this.thumbX.removeEventListener("pointerdown",this.Nt),this.trackX&&this.trackX.removeEventListener("pointerdown",this.Pt),this.St&&(this.St.disconnect(),this.St=null),null!==this.$t&&(cancelAnimationFrame(this.$t),this.$t=null),null!==this.Ct&&(clearTimeout(this.Ct),this.Ct=null)}Dt(){null===this.$t&&(this.$t=requestAnimationFrame(()=>{this.$t=null,this.Zt(),this.Kt()}))}Ut(){if(!this.trackY||!this.thumbY)return;const{scrollHeight:t,clientHeight:n}=this.Et,e=t>n+2;this.trackY.classList.toggle("has-overflow",e),e&&(this.thumbY.style.height=Math.max(n/t*100,0)+"%"),this.Xt()}Gt(){if(!this.trackX||!this.thumbX)return;const{scrollWidth:t,clientWidth:n}=this.Et,e=t>n+2;this.trackX.classList.toggle("has-overflow",e),e&&(this.thumbX.style.width=Math.max(n/t*100,0)+"%"),this.Jt()}Zt(){this.Xt(),this.Jt()}Xt(){if(!this.trackY||!this.thumbY)return;const{scrollTop:t,scrollHeight:n,clientHeight:e}=this.Et,i=n-e;i>0&&(this.thumbY.style.top=t/i*(this.trackY.clientHeight-this.thumbY.offsetHeight)+"px")}Jt(){if(!this.trackX||!this.thumbX)return;const{scrollLeft:t,scrollWidth:n,clientWidth:e}=this.Et,i=n-e;i>0&&(this.thumbX.style.left=t/i*(this.trackX.clientWidth-this.thumbX.offsetWidth)+"px")}Kt(){this.dt||(this.trackY?.classList.add("scrolling"),this.trackX?.classList.add("scrolling"),null!==this.Ct&&clearTimeout(this.Ct),this.Ct=setTimeout(()=>{this.trackY?.classList.remove("scrolling"),this.trackX?.classList.remove("scrolling"),this.Ct=null},this.At))}Ot(t){0===t.button&&(t.preventDefault(),t.stopPropagation(),this.dt=!0,this.xt="y",this.kt=t.clientY,this.zt=this.Et.scrollTop,this.thumbY.setPointerCapture(t.pointerId),this.trackY?.classList.add("dragging"),this.thumbY.addEventListener("pointermove",this.Ht),this.thumbY.addEventListener("pointerup",this.jt),this.thumbY.addEventListener("pointercancel",this.jt))}Rt(t){0===t.button&&(t.preventDefault(),t.stopPropagation(),this.dt=!0,this.xt="x",this.kt=t.clientX,this.zt=this.Et.scrollLeft,this.thumbX.setPointerCapture(t.pointerId),this.trackX?.classList.add("dragging"),this.thumbX.addEventListener("pointermove",this.Ht),this.thumbX.addEventListener("pointerup",this.jt),this.thumbX.addEventListener("pointercancel",this.jt))}Bt(t){if(this.dt)if("y"===this.xt){const n=t.clientY-this.kt,{scrollHeight:e,clientHeight:i}=this.Et,o=this.trackY.clientHeight-this.thumbY.offsetHeight;if(0>=o)return;this.Et.scrollTop=this.zt+n*((e-i)/o)}else{const n=t.clientX-this.kt,{scrollWidth:e,clientWidth:i}=this.Et,o=this.trackX.clientWidth-this.thumbX.offsetWidth;if(0>=o)return;this.Et.scrollLeft=this.zt+n*((e-i)/o)}}Wt(t){const n="y"===this.xt?this.thumbY:this.thumbX,e="y"===this.xt?this.trackY:this.trackX;this.dt=!1,n.releasePointerCapture(t.pointerId),e?.classList.remove("dragging"),n.removeEventListener("pointermove",this.Ht),n.removeEventListener("pointerup",this.jt),n.removeEventListener("pointercancel",this.jt),this.Kt()}Vt(t){if(t.target===this.thumbY||0!==t.button)return;t.preventDefault();const n=this.trackY.getBoundingClientRect(),e=(t.clientY-n.top)/n.height,{scrollHeight:i,clientHeight:o}=this.Et;this.Et.scrollTo({top:e*(i-o),behavior:"smooth"})}Ft(t){if(t.target===this.thumbX||0!==t.button)return;t.preventDefault();const n=this.trackX.getBoundingClientRect(),e=(t.clientX-n.left)/n.width,{scrollWidth:i,clientWidth:o}=this.Et;this.Et.scrollTo({left:e*(i-o),behavior:"smooth"})}}const Tt="\n/* ===================================== */\n/* Custom Scrollbar - Vertical Track */\n/* ===================================== */\n\n.ty-scrollbar-track-y {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n width: var(--ty-scrollbar-width, 8px);\n z-index: 3;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.25s ease-out;\n cursor: pointer;\n}\n\n.ty-scrollbar-track-y.has-overflow {\n pointer-events: auto;\n}\n\n.ty-scrollbar-track-y.has-overflow:hover,\n.ty-scrollbar-track-y.has-overflow.scrolling,\n.ty-scrollbar-track-y.dragging {\n opacity: 1;\n}\n\n.ty-scrollbar-track-y::before {\n content: '';\n position: absolute;\n inset: 0;\n background: var(--ty-scrollbar-track, transparent);\n border-radius: var(--ty-scrollbar-radius, 4px);\n opacity: 0;\n transition: opacity 0.15s ease-out;\n}\n\n.ty-scrollbar-track-y:hover::before,\n.ty-scrollbar-track-y.dragging::before {\n opacity: 1;\n background: var(--ty-scrollbar-track-hover, color-mix(in oklab, var(--ty-color-neutral-bold) 8%, transparent));\n}\n\n.ty-scrollbar-thumb-y {\n position: absolute;\n right: 0;\n width: 100%;\n min-height: var(--ty-scrollbar-thumb-min-height, 30px);\n background: var(--ty-scrollbar-thumb, color-mix(in oklab, var(--ty-color-neutral-bold) 40%, transparent));\n border-radius: var(--ty-scrollbar-radius, 4px);\n transition: background 0.15s ease-out;\n box-sizing: border-box;\n border: 1px solid transparent;\n}\n\n.ty-scrollbar-thumb-y:hover,\n.ty-scrollbar-track-y.dragging .ty-scrollbar-thumb-y {\n background: var(--ty-scrollbar-thumb-hover, color-mix(in oklab, var(--ty-color-neutral-bold) 55%, transparent));\n}\n\n.ty-scrollbar-thumb-y:active,\n.ty-scrollbar-track-y.dragging .ty-scrollbar-thumb-y {\n background: var(--ty-scrollbar-thumb-active, color-mix(in oklab, var(--ty-color-neutral-bold) 70%, transparent));\n}\n\n/* ===================================== */\n/* Custom Scrollbar - Horizontal Track */\n/* ===================================== */\n\n.ty-scrollbar-track-x {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: var(--ty-scrollbar-width, 8px);\n z-index: 3;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.25s ease-out;\n cursor: pointer;\n}\n\n.ty-scrollbar-track-x.has-overflow {\n pointer-events: auto;\n}\n\n.ty-scrollbar-track-x.has-overflow:hover,\n.ty-scrollbar-track-x.has-overflow.scrolling,\n.ty-scrollbar-track-x.dragging {\n opacity: 1;\n}\n\n.ty-scrollbar-track-x::before {\n content: '';\n position: absolute;\n inset: 0;\n background: var(--ty-scrollbar-track, transparent);\n border-radius: var(--ty-scrollbar-radius, 4px);\n opacity: 0;\n transition: opacity 0.15s ease-out;\n}\n\n.ty-scrollbar-track-x:hover::before,\n.ty-scrollbar-track-x.dragging::before {\n opacity: 1;\n background: var(--ty-scrollbar-track-hover, color-mix(in oklab, var(--ty-color-neutral-bold) 8%, transparent));\n}\n\n.ty-scrollbar-thumb-x {\n position: absolute;\n bottom: 0;\n height: 100%;\n min-width: var(--ty-scrollbar-thumb-min-height, 30px);\n background: var(--ty-scrollbar-thumb, color-mix(in oklab, var(--ty-color-neutral-bold) 40%, transparent));\n border-radius: var(--ty-scrollbar-radius, 4px);\n transition: background 0.15s ease-out;\n box-sizing: border-box;\n border: 1px solid transparent;\n}\n\n.ty-scrollbar-thumb-x:hover,\n.ty-scrollbar-track-x.dragging .ty-scrollbar-thumb-x {\n background: var(--ty-scrollbar-thumb-hover, color-mix(in oklab, var(--ty-color-neutral-bold) 55%, transparent));\n}\n\n.ty-scrollbar-thumb-x:active,\n.ty-scrollbar-track-x.dragging .ty-scrollbar-thumb-x {\n background: var(--ty-scrollbar-thumb-active, color-mix(in oklab, var(--ty-color-neutral-bold) 70%, transparent));\n}\n\n/* ===================================== */\n/* Touch devices - hide custom scrollbar */\n/* ===================================== */\n\n@media (pointer: coarse) and (hover: none) {\n .ty-scrollbar-track-y,\n .ty-scrollbar-track-x {\n display: none !important;\n }\n}\n\n/* Respect reduced motion */\n@media (prefers-reduced-motion: reduce) {\n .ty-scrollbar-track-y,\n .ty-scrollbar-track-x,\n .ty-scrollbar-thumb-y,\n .ty-scrollbar-thumb-x {\n transition-duration: 0ms !important;\n }\n}\n",Mt='<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="12"></line><line x1="12" y1="16" x2="12.01" y2="16"></line></svg>',At=class extends i{constructor(){super(),this.Qt=null,this.tn=null,this.nn=null,this._=!1,this.handleInputEvent=t=>{this.value=t.target.value,this.Qt&&this.tn&&this.resizeTextarea(this.Qt,this.tn),this.emitValueEvents(t)},this.handleFocusEvent=()=>{this._=!0},this.handleBlurEvent=()=>{this._=!1};const t=this.shadowRoot;s(t,{css:"\n:host {\n display: block;\n font-family: var(--ty-font-sans);\n width: 100%;\n}\n\n.textarea-container {\n display: flex;\n flex-direction: column;\n width: 100%;\n box-sizing: border-box;\n position: relative;\n /* For absolute positioned dummy element */\n}\n\n/* Bordered container — owns the border + active state (composer layout):\n header (top slot) · textarea (borderless) · footer (bottom slot). */\n.textarea-wrapper {\n position: relative;\n width: 100%;\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n border: 1px solid var(--input-border, var(--ty-input-border));\n border-radius: var(--ty-radius-base);\n background: var(--input-bg, var(--ty-input-bg));\n transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n}\n\n/* Active ring tied to the TEXTAREA specifically (not :focus-within) so tabbing\n to a footer button doesn't make the whole field look focused. */\n.textarea-wrapper:has(textarea:focus) {\n border-color: var(--input-border-focus, var(--ty-input-border-focus));\n box-shadow: 0 0 0 3px var(--input-shadow-focus, var(--ty-input-shadow-focus));\n}\n\n/* Error + disabled reflected from the inner textarea (both in shadow DOM, so\n :has is reliable here — unlike slotted content). */\n.textarea-wrapper:has(textarea.error) {\n border-color: var(--ty-color-danger);\n background: var(--ty-bg-danger-soft);\n}\n.textarea-wrapper:has(textarea.error):has(textarea:focus) {\n border-color: var(--ty-color-danger-bold);\n}\n.textarea-wrapper:has(textarea:disabled) {\n opacity: 0.5;\n background: var(--input-disabled-bg, var(--ty-input-disabled-bg));\n border-color: var(--input-disabled-border, var(--ty-input-disabled-border));\n}\n\n/* Scroll region wraps just the textarea so the custom scrollbar never overlaps\n the header/footer. */\n.textarea-scroll {\n position: relative;\n flex: 1 1 auto;\n min-height: 0;\n display: flex;\n}\n\n/* Custom scrollbar track positioned to the scroll region (textarea edges) */\n.textarea-scroll .ty-scrollbar-track-y {\n top: 2px;\n right: 2px;\n bottom: 2px;\n border-radius: 0 4px 4px 0;\n}\n\n/* Header / footer slot regions — zero footprint until they have content\n (the component toggles .has-content via slotchange). footer defaults to\n space-between so \"tools … submit\" works; a single wide button fills it. */\n.textarea-header,\n.textarea-footer {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n.textarea-footer { justify-content: space-between; }\n.textarea-header.has-content {\n padding: 6px 10px;\n border-bottom: 1px solid var(--ty-textarea-divider, var(--input-border, var(--ty-input-border)));\n}\n.textarea-footer.has-content {\n padding: 6px 10px;\n border-top: 1px solid var(--ty-textarea-divider, var(--input-border, var(--ty-input-border)));\n}\n\n/* ===== LABEL STYLING ===== */\n\n.ty-field-label {\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n font-weight: var(--ty-font-medium);\n color: var(--ty-label-color);\n margin-bottom: 6px;\n padding-left: 12px;\n}\n\n/* Required indicator - using SVG icon instead of CSS */\n.required-icon {\n display: inline-flex;\n align-items: center;\n color: var(--ty-color-danger);\n width: 12px;\n height: 12px;\n vertical-align: middle;\n}\n\n/* ===== ERROR MESSAGE STYLING ===== */\n\n.error-message {\n font-size: var(--ty-font-xs);\n line-height: var(--ty-leading-xs);\n letter-spacing: var(--ty-tracking-xs);\n color: var(--ty-color-danger);\n margin-top: 4px;\n padding-left: 12px;\n}\n\n/* Error state is reflected on .textarea-wrapper (see above). */\n\n/* ===== TEXTAREA BASE STYLING ===== */\n\ntextarea {\n /* Borderless — the .textarea-wrapper owns the border/background now. */\n box-sizing: border-box;\n width: 100%;\n flex: 1 1 auto;\n border: none;\n background: transparent;\n color: var(--input-color, var(--ty-input-color));\n font-family: inherit;\n /* Linear-paired typography */\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n font-weight: var(--ty-font-normal);\n outline: none;\n\n /* Default size (md) - refined spacing */\n min-height: 80px;\n /* Larger than input for multiline */\n padding: 12px 12px;\n /* Slightly larger padding for text areas */\n\n /* Auto-resize specific styles */\n overflow: hidden;\n /* Hide scrollbars since we're auto-resizing */\n resize: none;\n /* Disable manual resize by default */\n\n /* Ensure consistent text wrapping */\n white-space: pre-wrap;\n word-wrap: break-word;\n}\n\n/* Hide native scrollbar for webkit when custom scrollbar is active\n (scrollbar-width: none handles Firefox; this handles Chrome/Safari) */\n:host([data-custom-scroll]) textarea::-webkit-scrollbar {\n display: none;\n}\n\n/* Disabled — visual state lives on the wrapper; just the cursor/text here. */\ntextarea:disabled {\n cursor: not-allowed;\n color: var(--input-disabled-color, var(--ty-input-disabled-color));\n}\n\n/* Placeholder styling - subtle and elegant */\ntextarea::placeholder {\n color: var(--input-placeholder, var(--ty-input-placeholder));\n font-weight: 400;\n}\n\n/* ===== RESIZE CONTROL OPTIONS ===== */\n\n/* Allow manual resizing */\ntextarea.resize-both {\n resize: both;\n}\n\ntextarea.resize-horizontal {\n resize: horizontal;\n}\n\ntextarea.resize-vertical {\n resize: vertical;\n}\n\ntextarea.resize-none {\n resize: none;\n}\n\n/* Auto-resize mode (default) disables manual resize */\ntextarea:not(.resize-both):not(.resize-horizontal):not(.resize-vertical) {\n resize: none;\n}\n\n/* ===== DUMMY ELEMENT FOR AUTO-RESIZE ===== */\n\n.textarea-dummy {\n /* Hidden element that measures text height */\n position: absolute !important;\n top: 0 !important;\n left: 0 !important;\n visibility: hidden !important;\n white-space: pre-wrap !important;\n word-break: break-word !important;\n box-sizing: border-box !important;\n overflow: hidden !important;\n pointer-events: none !important;\n z-index: -1 !important;\n\n /* Ensure it has the same text behavior as textarea */\n word-wrap: break-word !important;\n overflow-wrap: break-word !important;\n}\n\n/* ===== SIZE MODIFIERS ===== */\n\n/* Extra Small */\ntextarea.xs {\n min-height: 64px;\n padding: 8px 10px;\n font-size: var(--ty-font-xs);\n line-height: var(--ty-leading-xs);\n letter-spacing: var(--ty-tracking-xs);\n}\n\n/* Small */\ntextarea.sm {\n min-height: 72px;\n padding: 10px 10px;\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n}\n\n/* Medium (default) */\ntextarea.md {\n min-height: 80px;\n padding: 12px 12px;\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n}\n\n/* Large */\ntextarea.lg {\n min-height: 96px;\n padding: 14px 14px;\n font-size: var(--ty-font-base);\n line-height: var(--ty-leading-base);\n letter-spacing: var(--ty-tracking-base);\n}\n\n/* Extra Large */\ntextarea.xl {\n min-height: 112px;\n padding: 16px 16px;\n font-size: var(--ty-font-lg);\n line-height: var(--ty-leading-lg);\n letter-spacing: var(--ty-tracking-lg);\n}\n\n/* ===== ACCESSIBILITY ENHANCEMENTS ===== */\n\ntextarea:focus-visible {\n outline: none;\n /* We use box-shadow instead */\n}\n\n/* High contrast mode support */\n@media (prefers-contrast: high) {\n textarea {\n border-width: 2px;\n }\n}\n\n/* Reduced motion support */\n@media (prefers-reduced-motion: reduce) {\n textarea {\n transition: none;\n }\n\n .textarea-dummy {\n transition: none;\n }\n}\n\n/* ===== CONTAINER-AWARE RESPONSIVE BEHAVIOR ===== */\n\n/* Scale down on smaller containers using container queries */\n@container (max-width: 480px) {\n textarea.lg {\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n padding: 12px 12px;\n min-height: 80px;\n }\n\n textarea.xl {\n font-size: var(--ty-font-base);\n line-height: var(--ty-leading-base);\n letter-spacing: var(--ty-tracking-base);\n padding: 14px 14px;\n min-height: 96px;\n }\n}\n\n@container (max-width: 320px) {\n textarea.xl {\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n padding: 12px 12px;\n min-height: 80px;\n }\n}\n\n/* Fallback for browsers without container query support */\n@media (max-width: 640px) {\n textarea.lg {\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n padding: 12px 12px;\n min-height: 80px;\n }\n\n textarea.xl {\n font-size: var(--ty-font-base);\n line-height: var(--ty-leading-base);\n letter-spacing: var(--ty-tracking-base);\n padding: 14px 14px;\n min-height: 96px;\n }\n}\n\n@media (max-width: 480px) {\n textarea.xl {\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n padding: 12px 12px;\n min-height: 80px;\n }\n}\n\n/* ===== ANIMATION AND TRANSITIONS ===== */\n\n/* Smooth height transitions for auto-resize */\ntextarea {\n transition:\n border-color 0.15s ease-in-out,\n box-shadow 0.15s ease-in-out,\n background-color 0.15s ease-in-out,\n height 0.1s ease-out;\n /* Smooth height changes */\n}\n\n/* Disable height transition on focus to avoid jarring effect */\ntextarea:focus {\n transition:\n border-color 0.15s ease-in-out,\n box-shadow 0.15s ease-in-out,\n background-color 0.15s ease-in-out;\n}\n\n/* For users who prefer reduced motion, disable height transitions */\n@media (prefers-reduced-motion: reduce) {\n textarea {\n transition: none;\n }\n}\n",id:"ty-textarea"}),St()&&s(t,{css:Tt,id:"ty-custom-scrollbar"})}onConnect(){}onDisconnect(){if(this.en(),this.Qt){const t=this.Qt.cloneNode(!0);this.Qt.parentNode?.replaceChild(t,this.Qt),this.Qt=null}this.tn=null}onPropertiesChanged(t){}getFormValue(){return this.getProperty("value")||null}get value(){return this.getProperty("value")}set value(t){this.setProperty("value",t)}get name(){return this.getProperty("name")}set name(t){this.setProperty("name",t)}get placeholder(){return this.getProperty("placeholder")}set placeholder(t){this.setProperty("placeholder",t)}get label(){return this.getProperty("label")}set label(t){this.setProperty("label",t)}get disabled(){return this.getProperty("disabled")}set disabled(t){this.setProperty("disabled",t)}get required(){return this.getProperty("required")}set required(t){this.setProperty("required",t)}get error(){return this.getProperty("error")}set error(t){this.setProperty("error",t)}get size(){return this.getProperty("size")}set size(t){this.setProperty("size",t)}get rows(){return this.getProperty("rows")}set rows(t){this.setProperty("rows",t)}get cols(){return this.getProperty("cols")}set cols(t){this.setProperty("cols",t)}get resize(){return this.getProperty("resize")}set resize(t){this.setProperty("resize",t)}get minHeight(){return this.getProperty("minHeight")}set minHeight(t){this.setProperty("minHeight",t)}get maxHeight(){return this.getProperty("maxHeight")}set maxHeight(t){this.setProperty("maxHeight",t)}getFontStyle(t){const n=window.getComputedStyle(t);return{fontFamily:n.fontFamily,fontSize:n.fontSize,fontWeight:n.fontWeight,lineHeight:n.lineHeight,letterSpacing:n.letterSpacing,fontStyle:n.fontStyle}}getSpacingStyle(t){const n=window.getComputedStyle(t);return{padding:n.padding,paddingTop:n.paddingTop,paddingRight:n.paddingRight,paddingBottom:n.paddingBottom,paddingLeft:n.paddingLeft,margin:n.margin,borderWidth:n.borderWidth}}setupDummyElement(t){const n=this.shadowRoot,e=n.querySelector(".textarea-dummy");e&&e.remove();const i=document.createElement("pre"),o=this.getFontStyle(t),s=this.getSpacingStyle(t);i.className="textarea-dummy";const r=i.style;return r.position="absolute",r.top="0",r.left="0",r.visibility="hidden",r.whiteSpace="pre-wrap",r.wordBreak="break-word",r.boxSizing="border-box",r.overflow="hidden",r.pointerEvents="none",Object.entries(o).forEach(([t,n])=>{r[t]=n}),Object.entries(s).forEach(([t,n])=>{r[t]=n}),n.appendChild(i),this.tn=i,i}resizeTextarea(t,n){if(!t||!n)return;const e=this.value,i=this.placeholder,o=t.clientHeight;n.textContent=""===e&&i?i:e+" ",n.style.width=t.clientWidth+"px";const s=n.scrollHeight,r=this.minHeight?parseInt(this.minHeight.replace("px",""),10):null,a=this.maxHeight?parseInt(this.maxHeight.replace("px",""),10):null;let l=s;null!==r&&(l=Math.max(l,r)),null!==a&&(l=Math.min(l,a)),Math.abs(l-o)>2&&(t.style.height=l+"px",null===a||a>s?(t.style.overflowY="hidden",this.en()):(t.style.overflowY="auto",this.sn(t))),this.nn?.update()}sn(t){if(this.nn||!St())return;t.style.scrollbarWidth="none",this.setAttribute("data-custom-scroll",""),this.nn=new Et(t,{vertical:!0,horizontal:!1});const n=this.shadowRoot.querySelector(".textarea-scroll");n&&this.nn.trackY&&n.appendChild(this.nn.trackY)}en(){this.nn&&(this.nn.trackY?.remove(),this.nn.destroy(),this.nn=null,this.removeAttribute("data-custom-scroll"),this.Qt&&(this.Qt.style.scrollbarWidth=""))}emitValueEvents(t){const n=this.value;this.v.setFormValue(n||""),this.updateValidity();const e={bubbles:!0,composed:!0,detail:{value:n,originalEvent:t}};setTimeout(()=>{this.dispatchEvent(new CustomEvent("input",e)),this.dispatchEvent(new CustomEvent("change",e))},0)}buildClassList(){const t=[this.size];this.disabled&&t.push("disabled"),this.required&&t.push("required"),this.error&&t.push("error"),"none"!==this.resize&&t.push("resize-"+this.resize);const n=this.getAttribute("class");return n&&t.push(n),t.join(" ")}applyHeightConstraints(t){this.minHeight&&(t.style.minHeight=this.minHeight),this.maxHeight&&(t.style.maxHeight=this.maxHeight)}setupTextareaEvents(t){t.addEventListener("input",this.handleInputEvent),t.addEventListener("change",this.handleInputEvent),t.addEventListener("focus",this.handleFocusEvent),t.addEventListener("blur",this.handleBlurEvent)}render(){const t=this.shadowRoot,n=t.querySelector(".textarea-container"),e=t.querySelector("label"),i=t.querySelector("textarea"),o=t.querySelector(".error-message");if(n&&i){if(this.label?e&&(e.innerHTML=this.label+(this.required?` <span class="required-icon">${Mt}</span>`:""),e.style.display="block"):e&&(e.style.display="none"),i.value=this.value||"",i.placeholder=this.placeholder||"",i.disabled=this.disabled,i.required=this.required,i.className=this.buildClassList(),this.label?i.setAttribute("aria-label",this.label):i.removeAttribute("aria-label"),this.name?i.setAttribute("name",this.name):i.removeAttribute("name"),this.rows&&i.setAttribute("rows",this.rows),this.cols&&i.setAttribute("cols",this.cols),this.applyHeightConstraints(i),this.error){if(!o){const t=document.createElement("div");t.className="error-message",n.appendChild(t)}const e=t.querySelector(".error-message");e&&(e.textContent=this.error)}else o&&o.remove();const s=this.setupDummyElement(i);setTimeout(()=>this.resizeTextarea(i,s),0),this.Qt=i}else{const n=document.createElement("div");n.className="textarea-container";const e=document.createElement("label");e.className="ty-field-label",this.label?(e.innerHTML=this.label+(this.required?` <span class="required-icon">${Mt}</span>`:""),e.style.display="block"):e.style.display="none";const i=document.createElement("textarea");i.value=this.value||"",i.placeholder=this.placeholder||"",i.disabled=this.disabled,i.required=this.required,i.className=this.buildClassList(),this.label&&i.setAttribute("aria-label",this.label),this.name&&i.setAttribute("name",this.name),i.setAttribute("rows",this.rows||"3"),this.cols&&i.setAttribute("cols",this.cols),this.applyHeightConstraints(i),this.setupTextareaEvents(i);const o=document.createElement("div");o.className="textarea-wrapper";const s=document.createElement("div");s.className="textarea-header";const r=document.createElement("slot");r.setAttribute("name","header"),s.appendChild(r);const a=document.createElement("div");a.className="textarea-scroll",a.appendChild(i);const l=document.createElement("div");l.className="textarea-footer";const c=document.createElement("slot");c.setAttribute("name","footer"),l.appendChild(c),o.appendChild(s),o.appendChild(a),o.appendChild(l);const d=(t,n)=>{const e=()=>n.classList.toggle("has-content",t.assignedNodes({flatten:!0}).length>0);t.addEventListener("slotchange",e),e()};if(d(r,s),d(c,l),n.appendChild(e),n.appendChild(o),this.error){const t=document.createElement("div");t.className="error-message",t.textContent=this.error,n.appendChild(t)}t.appendChild(n);const h=this.setupDummyElement(i);setTimeout(()=>this.resizeTextarea(i,h),0),this.Qt=i}this.updateValidity()}updateValidity(){const t=this.shadowRoot?.querySelector("textarea");this.disabled?this.v.setValidity({}):this.required&&""===(t?t.value:(this.value??"")+"").trim()?this.v.setValidity({valueMissing:!0},"Please fill out this field",t??void 0):this.v.setValidity({})}};At.formAssociated=!0,At.properties={value:{type:"string",visual:!0,formValue:!0,emitChange:!0,default:""},name:{type:"string",default:""},placeholder:{type:"string",visual:!0,default:""},label:{type:"string",visual:!0,default:""},disabled:{type:"boolean",visual:!0,default:!1},required:{type:"boolean",visual:!0,default:!1},error:{type:"string",visual:!0,default:""},size:{type:"string",visual:!0,default:"md",validate:t=>["xs","sm","md","lg","xl"].includes(t),coerce:t=>["xs","sm","md","lg","xl"].includes(t)?t:"md"},rows:{type:"string",visual:!0,default:"3",coerce:t=>t+""},cols:{type:"string",visual:!0,default:"",coerce:t=>t?t+"":""},resize:{type:"string",visual:!0,default:"none",validate:t=>["none","both","horizontal","vertical"].includes(t),coerce:t=>["none","both","horizontal","vertical"].includes(t)?t:"none"},minHeight:{type:"string",visual:!0,default:""},maxHeight:{type:"string",visual:!0,default:""}};let It=At;customElements.get("ty-textarea")||customElements.define("ty-textarea",It);const Dt={"top-start":{vertical:"top",horizontal:"start"},top:{vertical:"top",horizontal:"center"},"top-end":{vertical:"top",horizontal:"end"},"right-start":{vertical:"center",horizontal:"end",orientation:"vertical"},right:{vertical:"center",horizontal:"end",orientation:"vertical"},"right-end":{vertical:"end",horizontal:"end",orientation:"vertical"},"bottom-start":{vertical:"bottom",horizontal:"start"},bottom:{vertical:"bottom",horizontal:"center"},"bottom-end":{vertical:"bottom",horizontal:"end"},"left-start":{vertical:"center",horizontal:"start",orientation:"vertical"},left:{vertical:"center",horizontal:"start",orientation:"vertical"},"left-end":{vertical:"end",horizontal:"start",orientation:"vertical"}},Lt={default:["bottom-start","bottom-end","top-start","top-end","bottom","top","left","right"],tooltip:["top","bottom","left","right","top-start","top-end","bottom-start","bottom-end"]};function Ot(t){const n=t.getBoundingClientRect();return{top:n.top,left:n.left,right:n.right,bottom:n.bottom,width:n.width,height:n.height,centerX:n.left+n.width/2,centerY:n.top+n.height/2}}function Nt(t){const{targetEl:n,floatingEl:e,preferences:i=Lt.default,offset:o=8,padding:s=8,containerPadding:r=0}=t,a=Ot(n),l=Ot(e),c=i.map(t=>function(t){const{targetRect:n,floatingRect:e,placement:i,offset:o,padding:s,scrollbarWidth:r,containerPadding:a}=t,l=Dt[i],{vertical:c,horizontal:d,orientation:h}=l,u=window.innerWidth,p=window.innerHeight;let b,g;window,window,b="vertical"===h?"start"===d?n.left-e.width-o+a:n.right+o-a:"start"===d?n.left:"center"===d?n.centerX-e.width/2:n.right-e.width,g="vertical"===h?"center"===c?n.centerY-e.height/2:"end"===c?n.bottom-e.height-a:n.top:"top"===c?n.top-e.height-o+a:n.bottom+o-a;const m={top:Math.min(0,g-s),left:Math.min(0,b-s),bottom:Math.min(0,p-(g+e.height+s)),right:Math.min(0,u-(b+e.width+s+r))},v=Object.values(m).reduce((t,n)=>t+Math.abs(n),0);return{x:Math.round(b),y:Math.round(g),placement:i,overflow:m,overflowAmount:v,fits:0===v}}({targetRect:a,floatingRect:l,placement:t,offset:o,padding:s,containerPadding:r,scrollbarWidth:15})),d=c.find(t=>t.fits)||c.reduce((t,n)=>t.overflowAmount>n.overflowAmount?n:t);return 0>d.overflow.right&&(d.x+=d.overflow.right),d}function Rt(t){const n=t.gap??4,e=t.padding??8,i=window.innerWidth,o=window.innerHeight,s=o-t.anchorRect.bottom,r=s>=t.popupHeight+n+e||s>=t.anchorRect.top;return{x:Math.max(e,Math.min(t.anchorRect.left,i-t.popupWidth-e)),topY:t.anchorRect.bottom+n,bottomY:o-t.anchorRect.top+n,below:r}}const qt={id:"ty-tooltip",css:"\n/* Tooltip host element - display contents to not affect layout */\n:host {\n display: contents;\n}\n"},Vt=new WeakMap,Pt=new WeakMap,Ft=new WeakMap,Ht=new WeakMap,Bt=new WeakMap;function jt(t){const n=t||"dark",e=n.replace(/[+-]$/,"");return/^[A-Za-z][A-Za-z0-9_-]*$/.test(e)?n:"dark"}function Wt(t){let n=Ft.get(t);return n||(n={showTimeout:null,hideTimeout:null},Ft.set(t,n)),n}function _t(t,n){return t.hasAttribute(n)}function Yt(t,n,e){const i=t.getAttribute(n);if(null===i)return e;const o=parseInt(i,10);return isNaN(o)?e:o}function Ut(t){return{placement:t.getAttribute("placement")||"top",offset:Yt(t,"offset",8),delay:Yt(t,"delay",600),disabled:_t(t,"disabled"),flavor:jt(t.getAttribute("flavor"))}}function Gt(t){return t.parentElement}function Zt(t){let n=Ht.get(t);if(!n){n=document.createElement("div"),n.id="ty-tooltip-"+Math.random().toString(36).slice(2,11),n.setAttribute("popover","manual"),n.setAttribute("role","tooltip"),n.className="ty-tooltip-popover",n.style.cssText="\n position: fixed;\n margin: 0;\n padding: 8px 12px;\n background: var(--ty-tooltip-bg, #262626);\n color: var(--ty-tooltip-color, #f5f5f5);\n border: none;\n border-radius: 6px;\n font-size: var(--ty-font-xs, 12px);\n font-weight: var(--ty-font-semibold, 600);\n line-height: 1.5;\n max-width: 250px;\n text-align: center;\n box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.2), 0 4px 6px -4px rgba(0, 0, 0, 0.1);\n user-select: none;\n pointer-events: none;\n ",document.body.appendChild(n),Ht.set(t,n);const e=Bt.get(t);e&&function(t,n){const e=(t.getAttribute("aria-describedby")||"").split(/\s+/).filter(Boolean);e.includes(n)||(e.push(n),t.setAttribute("aria-describedby",e.join(" ")))}(e,n.id)}const{flavor:e}=Ut(t);return n.setAttribute("data-flavor",e),n.innerHTML=t.innerHTML,Kt(n,e),n}function Kt(t,n){switch(t.style.removeProperty("background"),t.style.removeProperty("color"),t.style.removeProperty("border-color"),n){case"dark":t.style.background="var(--ty-tooltip-bg, #262626)",t.style.color="var(--ty-tooltip-color, #f5f5f5)",t.style.borderColor="var(--ty-tooltip-border, #404040)";break;case"light":t.style.background="var(--ty-surface-elevated, #ffffff)",t.style.color="var(--ty-text-strong, #111827)",t.style.borderColor="var(--ty-border, #e5e7eb)";break;case"info":t.style.background="var(--ty-bg-info, #06b6d4)",t.style.color="var(--ty-text-strong, #f0f9ff)",t.style.borderColor="var(--ty-border-info, #22d3ee)";break;default:{const e=n.replace(/[+-]$/,""),i=n.slice(e.length);t.style.background=`var(--ty-bg-${e}${"+"===i?"-bold":"-"===i?"-soft":""}, var(--ty-bg-neutral))`,t.style.color=`var(--ty-color-${e}-strong, var(--ty-color-neutral-strong))`,t.style.borderColor=`var(--ty-border-${e}, var(--ty-color-${e}))`;break}}}function Xt(t){const{placement:n,offset:e}=Ut(t),i=Gt(t),o=Ht.get(t);if(!i||!o)return;const s=Nt({targetEl:i,floatingEl:o,preferences:"top"===n?Lt.tooltip:"bottom"===n?["bottom","top","left","right"]:"left"===n?["left","right","top","bottom"]:"right"===n?["right","left","top","bottom"]:Lt.tooltip,offset:e});o.style.left=s.x+"px",o.style.top=s.y+"px"}function Jt(t){const n=Vt.get(t);n&&(n(),Vt.delete(t))}function Qt(t){const n=Wt(t);null!==n.showTimeout&&(clearTimeout(n.showTimeout),n.showTimeout=null),null!==n.hideTimeout&&(clearTimeout(n.hideTimeout),n.hideTimeout=null)}function tn(t){const n=Ht.get(t);if(n)try{n.hidePopover(),t.rn=!1,Jt(t)}catch(e){}}function nn(t){const n=Wt(t),{delay:e}=Ut(t);Qt(t),n.showTimeout=window.setTimeout(()=>function(t){const{disabled:n}=Ut(t);if(n)return;const e=Zt(t);try{e.showPopover(),t.rn=!0,Xt(t),function(t){const n=Gt(t),e=Ht.get(t);if(!n||!e)return;let i=null;const o=()=>{null!==i&&clearTimeout(i),i=window.setTimeout(()=>{i=null,Xt(t)},10)},s=new ResizeObserver(o);s.observe(n),s.observe(e);let r=null;const a=()=>{null===r&&(r=requestAnimationFrame(()=>{r=null,Xt(t)}))};window.addEventListener("scroll",a,!0),window.addEventListener("resize",o),Vt.set(t,()=>{s.disconnect(),window.removeEventListener("scroll",a,!0),window.removeEventListener("resize",o),null!==i&&clearTimeout(i),null!==r&&cancelAnimationFrame(r)})}(t)}catch(i){}}(t),e)}function en(t){const n=Wt(t);Qt(t),n.hideTimeout=window.setTimeout(()=>tn(t),200)}class TyTooltip extends HTMLElement{constructor(){super(),this.rn=!1,this.attachShadow({mode:"open"})}static get observedAttributes(){return["placement","offset","delay","disabled","flavor"]}connectedCallback(){this.rn=!1,s(this.shadowRoot,qt),function(t){const n=Gt(t);if(!n)return;Bt.set(t,n);const e=()=>nn(t),i=()=>en(t),o=()=>nn(t),s=()=>en(t);n.addEventListener("mouseenter",e),n.addEventListener("mouseleave",i),n.addEventListener("focusin",o),n.addEventListener("focusout",s),Pt.set(t,()=>{n.removeEventListener("mouseenter",e),n.removeEventListener("mouseleave",i),n.removeEventListener("focusin",o),n.removeEventListener("focusout",s)})}(this),Zt(this)}disconnectedCallback(){!function(t){Qt(t),Jt(t);const n=Pt.get(t);n&&(n(),Pt.delete(t));const e=Ht.get(t),i=Bt.get(t);e&&i&&function(t,n){const e=(t.getAttribute("aria-describedby")||"").split(/\s+/).filter(t=>t&&t!==n);e.length>0?t.setAttribute("aria-describedby",e.join(" ")):t.removeAttribute("aria-describedby")}(i,e.id),e&&(e.remove(),Ht.delete(t)),Bt.delete(t),Ft.delete(t)}(this)}attributeChangedCallback(t,n,e){if("flavor"===t){const t=Ht.get(this);t&&Kt(t,jt(e))}"disabled"===t&&null!==e&&tn(this)}}customElements.get("ty-tooltip")||customElements.define("ty-tooltip",TyTooltip);const on={locked:!1,scrollY:0,activeLocks:new Set};function sn(){return document.documentElement}function rn(){if(!on.locked)return;const t=sn();window,t.classList.remove("ty-scroll-locked"),t.style.overflow="",t.style.paddingRight="",on.locked=!1}function an(t){on.activeLocks.has(t)||(on.activeLocks.add(t),1===on.activeLocks.size&&function(){if(on.locked)return;const t=window.innerWidth-sn().clientWidth,n=sn();window,on.scrollY=window.scrollY||sn().scrollTop||0,on.locked=!0,n.style.overflow="hidden",t>0&&(n.style.paddingRight=t+"px"),n.classList.add("ty-scroll-locked")}())}function ln(t){on.activeLocks.has(t)&&(on.activeLocks.delete(t),0===on.activeLocks.size&&rn())}const cn=new WeakMap,dn=new WeakMap,hn=new WeakMap,un=new WeakMap,pn=new WeakMap;function bn(t,n){return t.hasAttribute(n)}function gn(t,n,e){const i=t.getAttribute(n);if(null===i)return e;const o=parseInt(i,10);return isNaN(o)?e:o}function mn(t){return{manual:bn(t,"manual"),disableClose:bn(t,"disable-close"),placement:t.getAttribute("placement")||"bottom",offset:gn(t,"offset",8)}}function vn(t){return t.parentElement}function yn(t){return t.querySelector(".popup-dialog")}function fn(t){let n=pn.get(t);return n||(n="popup-"+(t.id||Math.random().toString(36).substr(2,9)),pn.set(t,n)),n}function wn(t,n=!1){const{disableClose:e}=mn(t);if(!n&&e)return;const i=t.shadowRoot,o=i?yn(i):null;if(!o)return;o.classList.remove("open"),o.classList.remove("preparing-animation");const s=vn(t);s?.hasAttribute("aria-haspopup")&&s.setAttribute("aria-expanded","false"),setTimeout(()=>{o.classList.remove("position-calculated"),o.close()},150),t.dispatchEvent(new CustomEvent("close",{bubbles:!0}))}function xn(t){an(fn(t));const n=t.shadowRoot,e=n?yn(n):null;if(!e)return;e.showModal();const i=vn(t);i?.hasAttribute("aria-haspopup")&&i.setAttribute("aria-expanded","true"),requestAnimationFrame(()=>{!function(t){const{placement:n,offset:e}=mn(t),i=t.shadowRoot,o=vn(t),s=i?yn(i):null;if(!o||!s)return;const r=Nt({targetEl:o,floatingEl:s,preferences:"top"===n?["top","bottom","left","right"]:"bottom"===n?["bottom","top","left","right"]:"left"===n?["left","right","top","bottom"]:"right"===n?["right","left","top","bottom"]:["bottom","top","right","left"],offset:e,padding:8,containerPadding:16});t.style.setProperty("--popup-x",r.x+"px"),t.style.setProperty("--popup-y",r.y+"px"),s.classList.add("position-calculated")}(t),e.classList.add("preparing-animation"),requestAnimationFrame(()=>{e.classList.add("open"),t.dispatchEvent(new CustomEvent("open",{bubbles:!0}))})})}function kn(t){const n=t.shadowRoot,e=n?yn(n):null;e&&(e.classList.contains("open")?wn(t):xn(t))}function zn(t){const{manual:n}=mn(t),e=vn(t);if(!e||n)return;e.setAttribute("aria-haspopup","dialog"),e.hasAttribute("aria-expanded")||e.setAttribute("aria-expanded","false");const i=cn.get(t);i&&e.removeEventListener("pointerdown",i);const o=n=>function(t,n){n.preventDefault(),n.stopPropagation(),kn(t)}(t,n);cn.set(t,o),e.addEventListener("pointerdown",o)}function $n(t){const n=vn(t),e=cn.get(t);n&&e&&(n.removeEventListener("pointerdown",e),cn.delete(t)),n?.removeAttribute("aria-haspopup"),n?.removeAttribute("aria-expanded")}function Cn(t){const n=t.shadowRoot;if(!n)return;const e=yn(n);if(s(n,{css:"\n/* Popup component with dropdown-like behavior and tooltip positioning */\n/* Uses dialog element for top layer rendering like dropdown and date-picker */\n\n.popup-dialog {\n position: fixed;\n top: 0;\n left: 0;\n\n /* Reset dialog defaults */\n margin: 0;\n border: none;\n background: transparent;\n max-width: none;\n max-height: none;\n\n /* Shadow infrastructure - provide space for user shadows */\n padding: var(--popup-padding, 16px);\n\n /* Hidden by default - even when [open] (for positioning phase) */\n visibility: hidden;\n opacity: 0;\n /* NO TRANSFORM here - apply only when animating to avoid measurement errors! */\n\n /* Smooth transitions */\n transition:\n opacity 150ms ease-out,\n visibility 150ms ease-out,\n transform 150ms ease-out;\n\n /* Prevent interactions when hidden */\n pointer-events: none;\n}\n\n/* Apply position variables only when position is calculated (like dropdown) */\n.popup-dialog.position-calculated {\n top: var(--popup-y, 0px);\n left: var(--popup-x, 0px);\n}\n\n/* Apply scale for entrance animation (right before .open) */\n.popup-dialog.preparing-animation {\n transform: scale(0.95);\n}\n\n/* When open - smooth entrance animation */\n.popup-dialog.open {\n visibility: visible;\n opacity: 1;\n transform: scale(1);\n pointer-events: auto;\n}\n\n/* Make dialog backdrop transparent like dropdown/date-picker */\n.popup-dialog::backdrop {\n background: transparent;\n}\n\n/* Inner container - neutral structural container */\n.popup-container {\n /* No default styling - just provides structure */\n /* Users control all visual aspects via slotted content */\n display: contents;\n}\n\n/* Content slot styling */\n#popup-content {\n /* Allow slotted content to define its own styling */\n display: contents;\n}\n\n/* Remove default styling from slotted content - users have full control */\n#popup-content ::slotted(*) {\n /* Remove default styling that conflicts with user styling */\n /* Users now have complete control over popup appearance */\n /* background: unset; */\n /* border: unset; */\n /* box-shadow: unset; */\n\n /* Only maintain essential positioning */\n position: relative;\n\n /* Prevent content from being too wide - still helpful */\n max-width: min(400px, 90vw);\n max-height: min(500px, 80vh);\n overflow: auto;\n}\n",id:"ty-popup"}),!e){const e=document.createElement("dialog"),i=document.createElement("div"),o=document.createElement("slot");e.className="popup-dialog",i.className="popup-container",o.id="popup-content",n.appendChild(e),e.appendChild(i),i.appendChild(o),t.style.setProperty("--popup-x","0px"),t.style.setProperty("--popup-y","0px");const s=n=>function(t,n){n.stopPropagation();const e=t.shadowRoot,i=e?yn(e):null;i&&n.target===i&&(n.preventDefault(),wn(t))}(t,n);dn.set(t,s),e.addEventListener("pointerdown",s);const r=n=>function(t,n){if(n.stopPropagation(),"Escape"===n.key){const{disableClose:e}=mn(t);e?n.preventDefault():wn(t)}}(t,n);hn.set(t,r),t.addEventListener("keydown",r),e.addEventListener("close",()=>{ln(fn(t)),e.classList.remove("open"),e.classList.remove("preparing-animation"),t.dispatchEvent(new CustomEvent("close",{bubbles:!0}))})}t.closePopup=()=>wn(t,!0),t.openPopup=()=>xn(t),t.togglePopup=()=>kn(t);const i=n=>function(t,n){n.stopPropagation(),wn(t,!0)}(t,n);un.set(t,i),t.addEventListener("ty:close-popup",i),zn(t)}class TyPopup extends HTMLElement{static get observedAttributes(){return["manual","disable-close","placement","offset"]}constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){Cn(this)}disconnectedCallback(){!function(t){const n=pn.get(t);n&&(ln(n),pn.delete(t)),$n(t);const e=t.shadowRoot,i=e?yn(e):null;if(i){const n=dn.get(t);n&&(i.removeEventListener("pointerdown",n),dn.delete(t))}const o=hn.get(t);o&&(t.removeEventListener("keydown",o),hn.delete(t));const s=un.get(t);s&&(t.removeEventListener("ty:close-popup",s),un.delete(t))}(this)}attributeChangedCallback(t,n,e){switch(Cn(this),t){case"placement":case"offset":Cn(this);break;case"manual":case"disable-close":$n(this),zn(this)}}}customElements.get("ty-popup")||customElements.define("ty-popup",TyPopup);const Sn=new WeakMap,En=new WeakMap,Tn=new WeakMap,Mn=new WeakMap,An=new WeakMap,In=new WeakMap;function Dn(t,n){if(!t.hasAttribute(n))return!1;const e=t.getAttribute(n);return null===e||"false"!==e.toLowerCase()}function Ln(t){return t.querySelector(".ty-modal-dialog")}function On(t,n,e){const i=new CustomEvent(n,{detail:e,bubbles:!0,cancelable:!0});t.dispatchEvent(i)}function Nn(t,n="programmatic",e){const i=t.shadowRoot,o=i?Ln(i):null;if(o&&o.open){if(!e?.force){const e=new CustomEvent("beforeclose",{detail:{reason:n},bubbles:!0,composed:!0,cancelable:!0});if(t.dispatchEvent(e),e.defaultPrevented)return}t.removeAttribute("open")}}function Rn(t){const n=t.shadowRoot;if(!n)return;const e=function(t){return{open:Dn(t,"open"),backdrop:!t.hasAttribute("backdrop")||Dn(t,"backdrop"),closeOnOutsideClick:!t.hasAttribute("close-on-outside-click")||Dn(t,"close-on-outside-click"),closeOnEscape:!t.hasAttribute("close-on-escape")||Dn(t,"close-on-escape")}}(t),i=function(t){let n=Ln(t);if(!n){n=document.createElement("dialog");const e=document.createElement("button"),i=document.createElement("div"),o=document.createElement("slot");n.className="ty-modal-dialog",e.className="close-button",e.type="button",e.setAttribute("aria-label","Close modal"),e.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-x-icon lucide-x"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>',i.className="modal-content",i.appendChild(o),n.appendChild(e),n.appendChild(i),t.appendChild(n)}return n}(n),o=function(t){let n=In.get(t);return n||(n="modal-"+(t.id||Math.random().toString(36).slice(2,11)),In.set(t,n)),n}(t);s(n,{css:"\n/* Modal Host Styling */\n:host {\n display: contents;\n /* Don't interfere with layout */\n /* CSS variables are now auto-generated via the with-vars? option */\n}\n\n/* ===== CLOSE BUTTON STYLING ===== */\n/* This is part of the modal wrapper functionality, not user content styling */\n\n.close-button {\n position: absolute;\n top: -8px;\n right: -8px;\n background: transparent;\n border: none;\n cursor: pointer;\n padding: 4px;\n border-radius: 4px;\n transition: var(--ty-transition-colors);\n z-index: 1;\n color: #d8d8d8;\n\n /* Remove all default browser styling that could cause outlines/borders */\n outline: none;\n box-shadow: none;\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n\n /* Remove mobile tap highlights and focus rings */\n -webkit-tap-highlight-color: transparent;\n -webkit-touch-callout: none;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n}\n\n.close-button:hover {\n color: white;\n}\n\n/* Explicitly remove focus and active states for all interaction modes */\n.close-button:focus,\n.close-button:focus-visible,\n.close-button:focus-within,\n.close-button:active {\n outline: none !important;\n box-shadow: none !important;\n border: none !important;\n background: transparent !important;\n}\n\n/* Override hover color even in focus/active states */\n.close-button:hover,\n.close-button:focus:hover,\n.close-button:active:hover {\n color: white;\n}\n\n.close-button.hide {\n visibility: hidden;\n}\n\n/* ===== DIALOG ELEMENT - PURE WRAPPER ===== */\n/* Modal dialog - provides only essential modal functionality without styling user content */\n\n.ty-modal-dialog {\n /* Reset default dialog styles */\n padding: 18px;\n border: none;\n margin: 0;\n background: transparent;\n\n /* Modal positioning - centered */\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n\n /* Layer management */\n z-index: 1000;\n overflow: hidden;\n\n /* No sizing - let user content determine size */\n max-width: 85vw;\n max-height: 90vh;\n\n outline: none;\n}\n\n/* ===== BACKDROP STYLING ===== */\n/* Backdrop is part of modal functionality, not user content */\n\n.ty-modal-dialog::backdrop {\n background: var(--ty-modal-backdrop, rgba(0, 0, 0, 0.5));\n backdrop-filter: var(--ty-modal-backdrop-blur, blur(2px));\n animation: ty-modal-backdrop-enter var(--ty-modal-duration, 200ms) ease-out;\n}\n\n/* When backdrop is disabled */\n.ty-modal-dialog:not([data-backdrop])::backdrop {\n background: transparent;\n backdrop-filter: none;\n}\n\n/* ===== MODAL CONTENT CONTAINER ===== */\n/* Minimal container - no styling imposed on user content */\n\n.modal-content {\n color: var(--ty-text);\n}\n\n/* ===== ANIMATION KEYFRAMES ===== */\n\n@keyframes ty-modal-backdrop-enter {\n from {\n opacity: 0;\n }\n\n to {\n opacity: 1;\n }\n}\n",id:"ty-modal"}),i.className="ty-modal-dialog",e.backdrop?i.setAttribute("data-backdrop","true"):i.removeAttribute("data-backdrop");const r=t.getAttribute("label");r?i.setAttribute("aria-label",r):i.removeAttribute("aria-label"),function(t,n,e){const i=Sn.get(t);if(i&&(n.removeEventListener("click",i),Sn.delete(t)),e){const e=n=>function(t,n){n.stopPropagation();const e=t.shadowRoot,i=e?Ln(e):null;i&&n.target===i&&(n.preventDefault(),Nn(t,"backdrop"))}(t,n);Sn.set(t,e),n.addEventListener("click",e)}}(t,i,e.closeOnOutsideClick),function(t,n,e){const i=En.get(t);if(i&&(n.removeEventListener("keydown",i),En.delete(t)),e){const e=n=>function(t,n){n.stopPropagation(),"Escape"===n.key&&(n.preventDefault(),Nn(t,"escape"))}(t,n);En.set(t,e),n.addEventListener("keydown",e)}}(t,i,e.closeOnEscape),function(t,n,e){const i=n.querySelector(".close-button");if(!i)return;i.style.display=e?"":"none";const o=Tn.get(t);if(o&&(i.removeEventListener("click",o),Tn.delete(t)),e){const n=n=>function(t,n){n.preventDefault(),n.stopPropagation(),Nn(t,"close-button")}(t,n);Tn.set(t,n),i.addEventListener("click",n)}}(t,i,e.closeOnOutsideClick),function(t,n){const e=n.querySelector(".modal-content");if(!e)return;const i=Mn.get(t),o=An.get(t);if(i&&(e.removeEventListener("mouseenter",i),Mn.delete(t)),o&&(e.removeEventListener("mouseleave",o),An.delete(t)),window.innerWidth>=768&&0>=navigator.maxTouchPoints){const n=t=>function(t,n){const e=n.currentTarget.closest(".ty-modal-dialog");if(e){const t=e.querySelector(".close-button");t&&t.classList.add("hide")}}(0,t),i=t=>function(t,n){const e=n.currentTarget.closest(".ty-modal-dialog");if(e){const t=e.querySelector(".close-button");t&&t.classList.remove("hide")}}(0,t);Mn.set(t,n),An.set(t,i),e.addEventListener("mouseenter",n),e.addEventListener("mouseleave",i)}}(t,i),e.open?i.open||(an(o),e.backdrop?i.showModal():i.show(),On(t,"open",{})):i.open&&(ln(o),i.close(),On(t,"close",{reason:"programmatic"})),i.onclose=n=>{n.target===i&&(ln(o),t.hasAttribute("open")&&(t.removeAttribute("open"),On(t,"close",{reason:"native",returnValue:i.returnValue||void 0})))}}class TyModal extends HTMLElement{static get observedAttributes(){return["open","backdrop","close-on-outside-click","close-on-escape","label"]}constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){Rn(this),this.show=()=>{this.setAttribute("open","true")},this.hide=t=>Nn(this,"programmatic",t)}disconnectedCallback(){!function(t){const n=In.get(t),e=t.shadowRoot,i=e?Ln(e):null;if(n&&(ln(n),In.delete(t)),!i)return;const o=Sn.get(t);o&&(i.removeEventListener("click",o),Sn.delete(t));const s=En.get(t);s&&(i.removeEventListener("keydown",s),En.delete(t));const r=i.querySelector(".close-button");if(r){const n=Tn.get(t);n&&(r.removeEventListener("click",n),Tn.delete(t))}const a=i.querySelector(".modal-content");if(a){const n=Mn.get(t),e=An.get(t);n&&(a.removeEventListener("mouseenter",n),Mn.delete(t)),e&&(a.removeEventListener("mouseleave",e),An.delete(t))}}(this)}attributeChangedCallback(t,n,e){this.isConnected&&Rn(this)}}customElements.get("ty-modal")||customElements.define("ty-modal",TyModal),customElements.get("ty-dialog")||customElements.define("ty-dialog",class extends TyModal{});const qn=(t,n)=>{const e=e=>n?e?`var(--ty-color-${t}${e}, var(--ty-color-${t}, var(--ty-color-${n}${e})))`:`var(--ty-color-${t}, var(--ty-color-${n}))`:e?`var(--ty-color-${t}${e}, var(--ty-color-${t}))`:`var(--ty-color-${t})`;return`\n:host([flavor="${t}"]) {\n --select-accent: var(--ty-input-${t}-border, ${e("-soft")});\n --select-accent-bold: ${e("")};\n --select-ring: color-mix(in oklab, ${e("")} 15%, transparent);\n}\n:host([flavor="${t}+"]) {\n --select-accent: ${e("")};\n --select-accent-bold: ${e("-strong")};\n --select-ring: color-mix(in oklab, ${e("-strong")} 15%, transparent);\n}\n:host([flavor="${t}-"]) {\n --select-accent: ${e("-faint")};\n --select-accent-bold: ${e("-soft")};\n --select-ring: color-mix(in oklab, ${e("-soft")} 15%, transparent);\n}\n`},Vn=`\n/* Select-field-specific styles extending dropdown base styles */\n\n:host {\n font-family: var(--ty-font-sans);\n --mobile-border-color: var(--ty-border, #5858587d);\n}\n\n/* ===== DIALOG POSITIONING SUPPORT ===== */\n\n.dropdown-dialog {\n position: fixed;\n width: var(--dropdown-width, 200px);\n max-width: 100vw;\n margin: 0;\n padding: 0;\n border: none;\n background: transparent;\n box-sizing: border-box;\n padding: var(--dropdown-padding, 20px);\n /* Modal handles z-index automatically */\n\n /* Hidden by default */\n opacity: 0;\n transition: opacity 400ms ease;\n\n transform: translate(var(--dropdown-offset-x, 0px), var(--dropdown-offset-y, 0px));\n top: -1000px;\n left: -1000px;\n}\n\n/* When opened via showModal(), apply flex layout and direction */\n.dropdown-dialog[open] {\n display: flex;\n flex-direction: column;\n}\n\n/* Direction-based positioning with CSS classes */\n.dropdown-dialog.position-below {\n left: var(--dropdown-x);\n top: var(--dropdown-y);\n}\n\n.dropdown-dialog.position-above {\n left: var(--dropdown-x);\n bottom: var(--dropdown-y);\n top: auto;\n flex-direction: column-reverse;\n}\n\n.dropdown-dialog.position-above .dropdown-header {\n margin-top: 4px;\n}\n\n.dropdown-dialog.position-below .dropdown-header {\n margin-bottom: 4px;\n}\n\n.dropdown-dialog.position-below .dropdown-options {\n /* Optional: Add upward-pointing shadow for below positioning */\n box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1), var(--ty-shadow-md);\n}\n\n/* Animate when .open class is added */\n.dropdown-dialog.open {\n opacity: 1;\n}\n\n.dropdown-dialog.open .dropdown-options {\n opacity: 1;\n transform: translateY(0) scale(1);\n}\n\n.dropdown-dialog::backdrop {\n background: transparent;\n}\n\n/* ===== DIALOG HEADER ===== */\n\n.dropdown-header {\n display: flex;\n align-items: center;\n gap: var(--ty-spacing-2);\n position: relative;\n}\n\n.dropdown-search-input {\n width: 100%;\n min-width: 0;\n box-sizing: border-box;\n background: var(--input-bg, var(--ty-input-bg));\n color: var(--input-color, var(--ty-input-color));\n border: 1px solid var(--input-border, var(--ty-input-border));\n border-radius: var(--ty-radius-md);\n font-family: var(--ty-font-sans);\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n font-weight: var(--ty-font-normal);\n min-height: var(--ty-size-md);\n padding: var(--ty-spacing-2) var(--ty-spacing-3);\n padding-right: calc(var(--ty-spacing-3) + 1rem + var(--ty-spacing-2));\n transition: var(--ty-transition-all);\n outline: none;\n}\n\n.dropdown-search-input:focus {\n border-color: var(--input-border-focus, var(--ty-input-border-focus));\n box-shadow: 0 0 0 3px var(--input-shadow-focus, var(--ty-input-shadow-focus));\n}\n\n.dropdown-search-input:disabled {\n background-color: var(--input-disabled-bg, var(--ty-input-disabled-bg));\n color: var(--input-disabled-color, var(--ty-input-disabled-color));\n cursor: not-allowed;\n opacity: 0.6;\n}\n\n.dropdown-search-input::placeholder {\n color: var(--input-placeholder, var(--ty-input-placeholder));\n}\n\n.dropdown-search-chevron {\n position: absolute;\n top: 50%;\n right: var(--ty-spacing-3);\n transform: translateY(-50%);\n width: 1rem;\n height: 1rem;\n color: var(--input-placeholder, var(--ty-input-placeholder));\n transition: var(--ty-transition-transform);\n pointer-events: none;\n}\n\n.dropdown-search-chevron.open {\n transform: translateY(-50%) rotate(180deg);\n}\n\n.dropdown-search-chevron svg {\n width: 100%;\n height: 100%;\n}\n\n/* ===== SELECT FIELD-SPECIFIC STYLES ===== */\n\n/* Select stub modifications */\n.select-stub {\n min-height: var(--ty-size-md);\n display: flex;\n flex-wrap: wrap;\n gap: 0.25rem;\n align-items: center;\n padding: 0 2.5rem 0 0.75rem;\n /* Transitions - includes opacity for open state */\n transition: var(--ty-transition-all), opacity 0.2s ease;\n outline: none;\n background: var(--input-bg, var(--ty-input-bg));\n color: var(--input-color, var(--ty-input-color));\n border: 1px solid var(--select-accent, var(--input-border, var(--ty-input-border)));\n border-radius: var(--ty-radius-md);\n font-family: var(--ty-font-sans);\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n cursor: pointer;\n position: relative;\n width: 100%;\n box-sizing: border-box;\n}\n\n/* ===== SIZE MODIFIERS =====\n buildStubClasses() always stamps exactly one size class on .select-stub.\n min-height comes from the shared --ty-size-* tokens (same ones ty-input\n and ty-date-picker consume) so a given size is the same height on every\n field. Right padding stays 2.5rem for chevron room. Zero vertical\n padding — same fix as ty-input: with align-items:center on a flex\n container, ANY vertical padding adds on top of min-height instead of\n being absorbed by it, so a padded stub silently overflows past the\n shared field height (measured +3px at sm/md before this was zeroed).\n min-height + centering alone gets the exact height. */\n.select-stub.sm {\n min-height: var(--ty-size-sm);\n padding: 0 2.5rem 0 0.625rem;\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n}\n\n/* md matches the base rule; listed for parity/overrides */\n.select-stub.md {\n min-height: var(--ty-size-md);\n padding: 0 2.5rem 0 0.75rem;\n}\n\n.select-stub.lg {\n min-height: var(--ty-size-lg);\n padding: 0 2.5rem 0 0.875rem;\n font-size: var(--ty-font-base);\n line-height: var(--ty-leading-base);\n letter-spacing: var(--ty-tracking-base);\n}\n\n.select-stub:hover {\n border-color: var(--select-accent-bold, var(--input-border-hover, var(--ty-input-border-hover)));\n}\n\n.select-stub[disabled] {\n background-color: var(--input-disabled-bg, var(--ty-input-disabled-bg));\n color: var(--input-disabled-color, var(--ty-input-disabled-color));\n cursor: not-allowed;\n opacity: 0.6;\n}\n\n/* Hide stub when dropdown is open */\n.dropdown-wrapper:has(.dropdown-chevron.open) .select-stub {\n opacity: 0;\n pointer-events: none;\n}\n\n/* Open state — same escalation as ty-input's .focused: bolder border + ring.\n Applies whenever the stub stays visible while open (field skin without\n the opacity-hide above kicking in — e.g. single-select with no tags). */\n.dropdown-wrapper:has(.dropdown-chevron.open) .select-stub,\n.select-stub:focus,\n.select-stub:focus-visible {\n border-color: var(--select-accent-bold, var(--input-border-focus, var(--ty-input-border-focus)));\n box-shadow: 0 0 0 3px var(--select-ring, var(--input-shadow-focus, var(--ty-input-shadow-focus)));\n}\n\n/* Custom trigger (slot="trigger"): setupTriggerSlot() toggles this class when\n the consumer assigns their own content — the slot's fallback (start/selected/\n placeholder/end/chevron, i.e. the whole default field skin) is entirely\n replaced at that point, so the wrapping .select-stub itself must go bare.\n Without this, the stub's own border/background/padding and the open/focus\n ring above still wrapped the custom content in a second, unwanted outline. */\n.select-stub.custom-trigger {\n min-height: 0;\n padding: 0;\n border: none;\n background: transparent;\n}\n.select-stub.custom-trigger:hover,\n.dropdown-wrapper:has(.dropdown-chevron.open) .select-stub.custom-trigger,\n.select-stub.custom-trigger:focus,\n.select-stub.custom-trigger:focus-visible {\n border-color: transparent;\n box-shadow: none;\n}\n\n/* Hide stub chips when mobile dialog is open (let modal show them) */\n.dropdown-mode-mobile .dropdown-wrapper:has(.mobile-dialog[open]) .select-chips {\n display: none;\n}\n\n/* When tags are present, reduce padding to make room */\n.select-stub.has-tags {\n padding: 0.25rem 2.5rem 0.25rem 0.5rem;\n width: 100%;\n}\n\n.select-stub.has-tags slot[name="selected"] {\n display: flex;\n flex-wrap: wrap;\n gap: 0.25rem;\n}\n\n/* ===== CHEVRON INDICATOR ===== */\n\n.dropdown-chevron {\n position: absolute;\n top: 50%;\n right: var(--ty-spacing-3);\n transform: translateY(-50%);\n width: 1rem;\n height: 1rem;\n color: var(--input-placeholder, var(--ty-input-placeholder));\n transition: var(--ty-transition-transform);\n pointer-events: none;\n}\n\n.dropdown-chevron.open {\n transform: translateY(-50%) rotate(180deg);\n}\n\n.dropdown-chevron svg {\n width: 100%;\n height: 100%;\n}\n\n\n/* Tags container */\n.select-chips {\n display: flex;\n flex-wrap: wrap;\n gap: 0.5rem;\n align-items: center;\n min-width: 0;\n}\n\n.dropdown-placeholder {\n flex-grow: 1;\n color: var(--input-placeholder, var(--ty-input-placeholder, #9ca3af));\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n font-weight: var(--ty-font-light);\n font-style: italic;\n}\n\n/* Placeholder styling when tags are present */\n.dropdown-placeholder.hidden {\n display: none;\n}\n\n/* Options area styling - Override for select */\n.dropdown-options {\n opacity: 0;\n background: var(--input-bg, var(--ty-input-bg));\n border: 1px solid var(--input-border, var(--ty-input-border));\n border-radius: var(--ty-radius-lg);\n max-height: 16rem;\n width: 100%;\n max-width: 100%;\n overflow-x: hidden;\n overflow-y: auto;\n scroll-behavior: smooth;\n box-sizing: border-box;\n position: relative;\n box-shadow:\n 0 20px 25px -5px rgba(0, 0, 0, 0.1),\n 0 10px 10px -5px rgba(0, 0, 0, 0.04);\n\n /* Animation properties */\n transform: translateY(-8px) scale(0.95);\n transition:\n opacity 200ms cubic-bezier(0.16, 1, 0.3, 1),\n transform 200ms cubic-bezier(0.16, 1, 0.3, 1);\n\n /* Select-specific: flex wrap for tags */\n display: flex;\n flex-wrap: wrap;\n padding: 0.5rem;\n gap: 0.5rem;\n\n}\n\n/* Hide native scrollbar only when custom scrollbar is active */\n.dropdown-options.ty-custom-scroll {\n scrollbar-width: none;\n -ms-overflow-style: none;\n}\n\n.dropdown-options.ty-custom-scroll::-webkit-scrollbar {\n display: none;\n}\n\n/* Options wrapper - positioned container for scrollbar track */\n.dropdown-options-wrapper {\n position: relative;\n}\n\n/* Show custom scrollbar on hover */\n.dropdown-options-wrapper:hover .ty-scrollbar-track-y.has-overflow {\n opacity: 1;\n}\n\n/* Make ty-tags in dropdown clickable with pointer cursor */\n.dropdown-options ty-tag {\n user-select: none;\n transition: transform 0.1s ease;\n}\n\n.dropdown-options ty-tag:hover {\n transform: scale(1.02);\n}\n\n.dropdown-options ty-tag:active {\n transform: scale(0.98);\n}\n\n/* Visual feedback for selected tags in options */\n.dropdown-options ty-tag[selected] {\n opacity: 0.5;\n}\n\n/* Ensure ty-tag components in the select field have proper sizing */\n.select-chips ty-tag {\n max-width: 150px;\n}\n\n/* Responsive adjustments */\n@media (max-width: 640px) {\n .select-chips ty-tag {\n max-width: 100px;\n }\n}\n\n\n/* Ensure proper spacing in container layouts */\n.select-container {\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n}\n\n/* ===== DROPDOWN WRAPPER & LABEL ===== */\n\n.dropdown-wrapper {\n position: relative;\n display: block;\n width: 100%;\n}\n\n.ty-field-label {\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n font-weight: var(--ty-font-medium);\n color: var(--ty-label-color);\n margin-bottom: 6px;\n padding-left: 12px;\n display: flex;\n align-items: center;\n}\n\n/* Required indicator - using SVG icon */\n.required-icon {\n display: inline-flex;\n align-items: center;\n color: #ef4444;\n width: 12px;\n height: 12px;\n vertical-align: middle;\n margin-left: 4px;\n}\n\n.required-icon svg {\n width: 100%;\n height: 100%;\n}\n\n:host([disabled]) .select-container {\n pointer-events: none;\n}\n\n/* ============================================================================\n MOBILE MODAL STYLES\n ============================================================================ */\n\n.dropdown-mode-mobile .mobile-dialog {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n width: 100vw;\n height: 100vh;\n max-width: 100vw;\n max-height: 100vh;\n margin: 0;\n padding: 0;\n padding-top: 10vh; /* Position content from top */\n border: none;\n background: transparent; /* Backdrop handles background */\n /* Note: Don't set display - browser controls <dialog> visibility */\n align-items: flex-start;\n justify-content: center;\n opacity: 0;\n transition: opacity 300ms ease;\n}\n\n/* When opened via showModal(), add flex layout */\n.dropdown-mode-mobile .mobile-dialog[open] {\n display: flex;\n}\n\n.dropdown-mode-mobile .mobile-dialog.open {\n opacity: 1;\n}\n\n/* Native dialog backdrop with blur */\n.dropdown-mode-mobile .mobile-dialog::backdrop {\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n}\n\n.dropdown-mode-mobile .mobile-dialog-content {\n position: relative;\n display: flex;\n flex-direction: column;\n width: calc(100% - 32px); /* Side margins */\n max-width: 400px; /* Constrained width like dropdown */\n min-height: 200px;\n max-height: calc(90vh - 10vh);\n opacity: 0;\n transform: scale(0.95);\n transition: \n opacity 300ms cubic-bezier(0.16, 1, 0.3, 1),\n transform 300ms cubic-bezier(0.16, 1, 0.3, 1);\n}\n\n.dropdown-mode-mobile .mobile-dialog.open .mobile-dialog-content {\n opacity: 1;\n transform: scale(1);\n}\n\n.dropdown-mode-mobile .mobile-search-input:focus {\n border-color: var(--ty-border);\n}\n\n/* Mobile search header - label floats above, search + close below */\n.dropdown-mode-mobile .mobile-search-header {\n flex-shrink: 0;\n display: flex;\n flex-direction: column;\n margin-bottom: 16px;\n padding: 0;\n background: transparent;\n position: relative;\n}\n\n.dropdown-mode-mobile .mobile-header-content {\n display: flex;\n align-items: center;\n gap: 12px;\n width: 100%;\n}\n\n/* Header for non-searchable (label + close button) */\n.dropdown-mode-mobile .mobile-header-nosearch {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: flex-end;\n margin-bottom: 16px;\n padding: 0;\n background: transparent;\n position: relative;\n min-height: 40px;\n}\n\n.dropdown-mode-mobile .mobile-header-label {\n position: absolute;\n bottom: 100%;\n left: 6px;\n margin-bottom: 4px;\n font-size: var(--ty-font-lg);\n line-height: var(--ty-leading-lg);\n letter-spacing: var(--ty-tracking-lg);\n font-weight: 700;\n color: var(--ty-color-neutral);\n pointer-events: none;\n}\n\n/* Close button - circular with border (matches dropdown.ts) */\n.dropdown-mode-mobile .mobile-close-button {\n flex-shrink: 0;\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--ty-surface-floating);\n border: 2px solid var(--mobile-border-color);\n border-radius: 50%;\n color: var(--ty-text-strong);\n cursor: pointer;\n transition: var(--ty-transition-all);\n padding: 0;\n}\n\n.dropdown-mode-mobile .mobile-close-button:hover {\n background: var(--ty-bg-neutral);\n border-color: var(--ty-border);\n color: var(--ty-text-strong);\n}\n\n.dropdown-mode-mobile .mobile-close-button:active {\n transform: scale(0.9);\n}\n\n.dropdown-mode-mobile .mobile-close-button svg {\n width: 24px;\n height: 24px;\n}\n\n/* Mobile search input (matches dropdown.ts) */\n.dropdown-mode-mobile .mobile-search-input {\n flex: 1;\n min-width: 0;\n box-sizing: border-box;\n background: var(--ty-surface-floating);\n color: var(--ty-text);\n border: 2px solid;\n border-color: var(--mobile-border-color);\n border-radius: var(--ty-radius-md);\n font-family: var(--ty-font-sans);\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n font-weight: var(--ty-font-normal);\n padding: var(--ty-spacing-2) var(--ty-spacing-3);\n height: 40px;\n transition: var(--ty-transition-all);\n outline: none;\n}\n\n.dropdown-mode-mobile .mobile-search-input::placeholder {\n color: var(--ty-text-faint);\n}\n\n.dropdown-mode-mobile .mobile-search-input:focus {\n border-color: var(--ty-border);\n}\n\n/* ============================================================================\n MOBILE BODY & SECTIONS - UPDATED STRUCTURE\n ============================================================================ */\n\n/* Mobile body - contains both sections */\n.dropdown-mode-mobile .mobile-body {\n position: relative;\n display: flex;\n flex-direction: column;\n height: var(--body-height, 350px);\n max-height: 350px;\n overflow: hidden;\n background: var(--ty-surface-floating);\n border-radius: var(--ty-radius-lg);\n box-shadow: \n 0 20px 25px -5px rgba(0, 0, 0, 0.1),\n 0 10px 10px -5px rgba(0, 0, 0, 0.04);\n border: 2px solid;\n border-color: var(--mobile-border-color);\n}\n\n/* ===== SECTION HEADERS - Labels, not buttons ===== */\n\n.dropdown-mode-mobile .section-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n height: 36px;\n flex-shrink: 0;\n padding: 0 16px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--ty-text-bold);\n background: transparent;\n cursor: default;\n user-select: none;\n}\n\n.dropdown-mode-mobile .section-header .section-title {\n flex: 1;\n}\n\n.dropdown-mode-mobile .section-header .section-count {\n font-weight: 500;\n color: var(--ty-text-faint);\n margin-left: 0.25rem;\n}\n\n/* ===== SELECTED STRIP - pinned, capped height, collapses when empty ===== */\n\n.dropdown-mode-mobile .mobile-selected-section {\n display: flex;\n flex-direction: column;\n background: var(--ty-input-bg);\n overflow: hidden;\n flex: 0 0 auto;\n max-height: 40%;\n transition: max-height 200ms cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n/* Empty: collapse to header only */\n.dropdown-mode-mobile .mobile-selected-section[data-empty="true"] {\n max-height: 36px;\n flex: 0 0 36px;\n}\n\n.dropdown-mode-mobile .mobile-selected-section .section-content {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n padding: 0.75rem 1rem;\n display: flex;\n flex-wrap: wrap;\n gap: 0.5rem;\n align-content: flex-start;\n /* Soft fade at bottom edge — hints at scrollable overflow */\n -webkit-mask-image: linear-gradient(to bottom, black calc(100% - 12px), transparent);\n mask-image: linear-gradient(to bottom, black calc(100% - 12px), transparent);\n}\n\n/* ===== AVAILABLE LIST - takes remaining space ===== */\n\n.dropdown-mode-mobile .mobile-available-section {\n display: flex;\n flex-direction: column;\n background: var(--ty-input-bg);\n overflow: hidden;\n flex: 1 1 auto;\n min-height: 0;\n}\n\n.dropdown-mode-mobile .mobile-available-section .section-content {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n padding: 0.75rem 1rem;\n display: flex;\n flex-wrap: wrap;\n gap: 0.5rem;\n align-content: flex-start;\n}\n\n/* ===== EMPTY STATES =====\n Selected strip collapses (no text needed).\n Available shows the empty message only when there are zero tags total. */\n\n.dropdown-mode-mobile .empty-state {\n display: none;\n width: 100%;\n padding: 2rem 1rem;\n text-align: center;\n color: var(--ty-text-faint);\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n font-style: italic;\n}\n\n.dropdown-mode-mobile .mobile-available-section[data-empty="true"] .empty-state {\n display: block;\n}\n\n.dropdown-mode-mobile .mobile-selected-section[data-empty="true"] .section-content,\n.dropdown-mode-mobile .mobile-available-section[data-empty="true"] slot {\n display: none;\n}\n\n/* ===== TAG STYLING IN MOBILE ===== */\n\n.dropdown-mode-mobile .section-content ::slotted(ty-tag) {\n cursor: pointer;\n user-select: none;\n transition: transform 0.1s ease;\n margin: 2px 0; /* Vertical spacing like dropdown options */\n /* Fade + scale entry — replays on each (re)insertion when a tag moves\n between selected and available slots */\n animation: ty-select-tag-enter 180ms cubic-bezier(0.16, 1, 0.3, 1);\n}\n\n@media (hover: hover) {\n .dropdown-mode-mobile .section-content ::slotted(ty-tag:hover) {\n transform: scale(1.02);\n }\n}\n\n.dropdown-mode-mobile .section-content ::slotted(ty-tag:active) {\n transform: scale(0.96);\n}\n\n/* Dimmed appearance for hidden filtered tags */\n.dropdown-mode-mobile .section-content ::slotted(ty-tag[hidden]) {\n display: none !important;\n}\n\n@keyframes ty-select-tag-enter {\n from { opacity: 0; transform: scale(0.85); }\n to { opacity: 1; transform: scale(1); }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .dropdown-mode-mobile .section-content ::slotted(ty-tag) {\n animation: none;\n }\n}\n\n/* ==================== LOADING STATE ====================\n Spinner overlay shown inside the options area while the parent\n (external-search mode) is fetching. Search input stays usable.\n\n Carries its own surface so it stays visible even when the host\n has restyled the popup with a transparent or unusual background.\n Override with --ty-loader-bg / --ty-loader-radius / --ty-loader-border.\n*/\n.dropdown-loading {\n display: none;\n align-items: center;\n justify-content: center;\n gap: var(--ty-spacing-2);\n padding: var(--ty-spacing-4) var(--ty-spacing-3);\n color: var(--ty-text-soft);\n font-size: var(--ty-font-sm);\n min-height: 4rem;\n /* Match the .dropdown-options popup look — same background, border, radius, shadow */\n background: var(--ty-loader-bg, var(--input-bg, var(--ty-input-bg)));\n border: 1px solid var(--ty-loader-border, var(--input-border, var(--ty-input-border)));\n border-radius: var(--ty-loader-radius, var(--ty-radius-lg));\n box-shadow: var(--ty-loader-shadow, 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04));\n box-sizing: border-box;\n}\n\n.dropdown-options-wrapper.loading .dropdown-loading {\n display: flex;\n}\n\n/* Slot is transparent for layout — fallback (spinner + text) and user-provided\n slotted content both act as direct flex children of .dropdown-loading. */\n.dropdown-loading > slot[name="loading"] {\n display: contents;\n}\n\n/* Mobile: full-screen dialog is the surface — drop the card chrome,\n stack vertically, scale up so it feels native to a fullscreen view.\n Slotted content adapts automatically since the slot is display:contents. */\n.dropdown-mode-mobile .dropdown-loading {\n background: transparent;\n border: none;\n box-shadow: none;\n flex: 1;\n flex-direction: column;\n gap: var(--ty-spacing-3);\n padding: var(--ty-spacing-8) var(--ty-spacing-4);\n min-height: 12rem;\n}\n\n.dropdown-mode-mobile .dropdown-loading-spinner {\n width: 2rem;\n height: 2rem;\n}\n\n.dropdown-mode-mobile .dropdown-loading-text {\n font-size: var(--ty-font-base);\n}\n\n.dropdown-options-wrapper.loading .dropdown-options,\n.dropdown-options-wrapper.loading > slot#options-slot,\n.dropdown-options-wrapper.loading .empty-state {\n display: none;\n}\n\n.dropdown-loading-spinner {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1.125rem;\n height: 1.125rem;\n flex-shrink: 0;\n animation: ty-select-spin 0.7s linear infinite;\n /* Active-state indicator — full accent, not the soft resting shade */\n color: var(--select-accent-bold, var(--ty-color-primary));\n}\n\n.dropdown-loading-spinner svg {\n width: 100%;\n height: 100%;\n}\n\n.dropdown-loading-text {\n color: var(--ty-text-soft);\n}\n\n@keyframes ty-select-spin {\n to { transform: rotate(360deg); }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .dropdown-loading-spinner {\n animation-duration: 1.6s;\n }\n}\n\n/* Custom scrollbar styles */\n${Tt}\n\n/* ===== FLAVOR VARIANTS (set --select-accent*, consumed above) ===== */\n${r.filter(t=>"neutral"!==t).map(t=>qn(t)).join("")}\n`;let Pn=0;const Fn=new WeakMap;function Hn(t){let n=Fn.get(t);return void 0===n&&(n=++Pn,Fn.set(t,n)),n}const Bn='<svg viewBox="0 0 20 20" fill="currentColor">\n <path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" />\n</svg>',jn='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">\n <circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/>\n</svg>',Wn=class extends i{constructor(){super(),this.an="",this.ln=!1,this.cn=!1,this.dn="Select...",this.hn="",this.P=!1,this.un=!1,this.pn=!1,this.bn=!1,this.gn=!1,this.mn="none",this.vn="auto",this.yn=!1,this.fn=null,this.wn="md",this.xn="Available",this.kn="No options available",this.zn={open:!1,search:"",highlightedIndex:-1,filteredTags:[],selectedValues:[],mode:"desktop"},this.$n=null,this.Cn=null,this.Sn=null,this.En=null,this.Tn=null,this.Mn=0,this.An=null,this.In=null,this.Dn=null,this.Ln=null,this.I=null;const t=this.shadowRoot;s(t,{css:Vn,id:"ty-select-base"}),s(t,{css:'\n/* ===== COMPACT skin: hugs content (field skin = base styles) ===== */\n.select-stub.compact {\n display: inline-flex;\n flex-wrap: nowrap;\n width: auto;\n gap: 0.5rem;\n /* extra right padding = room for the absolutely-positioned chevron */\n padding: 0.5rem 2.25rem 0.5rem 0.875rem;\n}\n\n/* Consumer-provided trigger (slot="trigger"): no chrome at all */\n.select-stub.custom-trigger {\n display: inline-block;\n border: none;\n background: none;\n padding: 0;\n min-height: 0;\n border-radius: 0;\n}\n.select-stub.custom-trigger:hover {\n border: none;\n}\n\n.select-count {\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 1.25rem;\n height: 1.25rem;\n padding: 0 0.375rem;\n border-radius: 9999px;\n /* --ty-text-primary never existed as a token — this silently fell back\n to inherited/unset color. Now follows the select\'s own flavor. */\n background: color-mix(in oklab, var(--select-accent, var(--ty-color-primary)) 15%, transparent);\n color: var(--select-accent-bold, var(--ty-color-primary-strong));\n font-size: var(--ty-font-xs);\n font-weight: var(--ty-font-semibold);\n font-style: normal;\n}\n.select-count[hidden] {\n display: none;\n}\n/* Selection text (field skin): single line, ellipsis, input colors */\n.select-stub .dropdown-placeholder {\n font-style: normal;\n flex: 1 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: var(--input-color, var(--ty-input-color));\n}\n\n/* Empty state: muted placeholder color */\n.select-stub .dropdown-placeholder.placeholder-shown {\n color: var(--input-placeholder, var(--ty-input-placeholder));\n}\n.select-stub .dropdown-placeholder[hidden] {\n display: none;\n}\n\n/* Single-select display clone (slot="selected"): the selected ty-option\n projected into the stub — its own :host([cloned]) styling strips the\n list-row chrome; here it just takes the text\'s flex slot. */\n.select-stub slot[name="selected"] {\n display: none;\n}\n.select-stub.has-clone slot[name="selected"] {\n display: block;\n flex: 1 1 auto;\n min-width: 0;\n overflow: hidden;\n}\n.select-stub.compact.has-clone slot[name="selected"] {\n flex: 0 1 auto;\n}\n\n/* start/end slot content (icons etc.) — spacing comes from the stub\'s flex\n gap; muted like ty-input adornments. end sits before the chevron. */\n.select-stub ::slotted([slot="start"]),\n.select-stub ::slotted([slot="end"]) {\n flex-shrink: 0;\n color: var(--ty-text-soft);\n}\n\n/* Compact skin: the text IS the trigger label — no grow, regular text color */\n.select-stub.compact .dropdown-placeholder {\n flex-grow: 0;\n color: var(--ty-text);\n}\n\n/* Trigger stays visible while the popup is open (the popup hides it) */\n.dropdown-wrapper:has(.dropdown-chevron.open) .select-stub {\n opacity: 1;\n pointer-events: auto;\n}\n\n/* ===== One-panel popup: search header fused with the options list ===== */\n\n/* Single unified shadow around the whole panel (header + list as one silhouette) */\n.dropdown-dialog.open {\n filter: drop-shadow(0 12px 24px rgba(0, 0, 0, 0.14)) drop-shadow(0 2px 6px rgba(0, 0, 0, 0.08));\n}\n\n/* Card-style header: the search input keeps its own bordered-field look\n (base styles) and sits inset in the panel, TagPicker-style — no divider,\n whitespace separates it from the list. */\n.dropdown-header {\n background: var(--input-bg, var(--ty-input-bg));\n border: 1px solid var(--input-border, var(--ty-input-border));\n border-bottom: none;\n border-radius: var(--ty-radius-lg) var(--ty-radius-lg) 0 0;\n padding: var(--ty-spacing-2) var(--ty-spacing-2) var(--ty-spacing-1);\n}\n.dropdown-dialog.position-below .dropdown-header {\n margin-bottom: 0;\n}\n.dropdown-dialog.position-above .dropdown-header {\n margin-top: 0;\n border-top: none;\n border-bottom: 1px solid var(--input-border, var(--ty-input-border));\n border-radius: 0 0 var(--ty-radius-lg) var(--ty-radius-lg);\n padding: var(--ty-spacing-1) var(--ty-spacing-2) var(--ty-spacing-2);\n}\n\n/* Magnifier adornment inside the search field (header padding + field inset) */\n.dropdown-search-icon {\n position: absolute;\n top: 50%;\n left: calc(var(--ty-spacing-2) + var(--ty-spacing-3));\n transform: translateY(-50%);\n width: 1rem;\n height: 1rem;\n color: var(--input-placeholder, var(--ty-input-placeholder));\n pointer-events: none;\n}\n.dropdown-search-icon svg {\n width: 100%;\n height: 100%;\n}\n\n/* Mobile header: flex row, icon flows inline before the input */\n.dropdown-mode-mobile .mobile-header-content .dropdown-search-icon {\n position: static;\n transform: none;\n flex-shrink: 0;\n}\n\n/* Search input: bordered field from base styles; just size + icon room */\n.dropdown-search-input {\n min-height: 2.25rem;\n padding-right: var(--ty-spacing-2);\n /* room for the magnifier adornment */\n padding-left: calc(var(--ty-spacing-3) + 1rem + var(--ty-spacing-2));\n}\n/* Trigger already has a chevron - no second one inside the search row */\n.dropdown-search-chevron {\n display: none;\n}\n\n/* With the search row hidden nothing inside is focusable, so the <dialog>\n itself receives focus on open — suppress its UA focus ring */\n.dropdown-dialog:focus,\n.dropdown-dialog:focus-visible {\n outline: none;\n}\n\n/* Search row hidden (\'auto\' below threshold / searchable="false"):\n the options panel owns the whole silhouette */\n.dropdown-header[hidden] {\n display: none;\n}\n.dropdown-header[hidden] ~ .dropdown-options-wrapper .dropdown-options {\n border-top: 1px solid var(--input-border, var(--ty-input-border));\n border-radius: var(--ty-radius-lg);\n}\n.mobile-search-input[hidden],\n.mobile-header-content .dropdown-search-icon[hidden] {\n display: none;\n}\n\n/* Options: vertical list rows fused under the search header.\n No own shadow/animation - the panel appears as one via dialog opacity. */\n.dropdown-options {\n flex-direction: column;\n flex-wrap: nowrap;\n align-items: stretch;\n gap: 0;\n /* Card-style list: rounded rows sit inset from the panel edges */\n padding: var(--ty-spacing-1);\n border-top: none;\n border-radius: 0 0 var(--ty-radius-lg) var(--ty-radius-lg);\n box-shadow: none;\n transform: none;\n transition: none;\n /* ~9-10 visible rows before scrolling (custom scrollbar, native hidden) */\n max-height: 24rem;\n}\n.dropdown-dialog.position-below .dropdown-options {\n box-shadow: none;\n}\n.dropdown-dialog.position-above .dropdown-options {\n border-top: 1px solid var(--input-border, var(--ty-input-border));\n border-bottom: none;\n border-radius: var(--ty-radius-lg) var(--ty-radius-lg) 0 0;\n}\n\n/* Loading panel continues the fused silhouette exactly like .dropdown-options —\n the base layer styles it as a floating card (radius + shadow), which left a\n see-through gap under the search header while loading. */\n.dropdown-loading {\n border-top: none;\n border-radius: 0 0 var(--ty-radius-lg) var(--ty-radius-lg);\n box-shadow: none;\n}\n.dropdown-dialog.position-above .dropdown-loading {\n border-top: 1px solid var(--input-border, var(--ty-input-border));\n border-bottom: none;\n border-radius: var(--ty-radius-lg) var(--ty-radius-lg) 0 0;\n}\n\n/* Selection tick lives inside ty-option (lucide check on [selected]) */\n\n/* Mobile modal: same vertical list */\n.dropdown-mode-mobile .section-content ::slotted(ty-option) {\n display: block;\n width: 100%;\n}\n',id:"ty-select"})}onConnect(){this.shadowRoot.querySelectorAll("dialog").forEach(t=>{t.open&&t.close()}),this.render(),requestAnimationFrame(()=>{this.initializeState()}),this.Dn=new MutationObserver(()=>{this.ensureOptionRoles(),this.zn.selectedValues.length>0&&this.syncSelectedTags(this.zn.selectedValues),this.updateSearchVisibility(),this.updateSelectionDisplay()}),this.Dn.observe(this,{childList:!0}),this.ensureOptionRoles(),this.D()}D(){this.I=u(this.shadowRoot,this.I,this.getProperty("flavor"),({base:t})=>(t=>qn(t,"neutral"))(t))}onDisconnect(){this.shadowRoot.querySelectorAll("dialog").forEach(t=>{t.open&&t.close()}),this.Tn&&(document.removeEventListener("keydown",this.Tn),this.Tn=null),null!==this.An&&(clearTimeout(this.An),this.An=null),this.On(),this.Dn&&(this.Dn.disconnect(),this.Dn=null)}onPropertiesChanged(t){for(const{name:n,newValue:e}of t)switch(n){case"value":const t=this.parseValue(e);this.zn.selectedValues=t,this.isConnected&&this.shadowRoot&&(this.syncSelectedTags(t),this.updateSelectionDisplay(),this.updateMobileSelectedState());break;case"name":this.an=e||"";break;case"flavor":this.D();break;case"multiple":this.ln=e,!e&&this.zn.selectedValues.length>1&&this.updateComponentValue([this.zn.selectedValues[0]],!1,"set",null);break;case"compact":this.cn=e;break;case"placeholder":this.dn=e||"Select...",this.isConnected&&this.shadowRoot&&this.updateSelectionDisplay();break;case"label":this.hn=e||"";break;case"disabled":this.P=e;break;case"readonly":this.un=e;break;case"required":this.pn=e;break;case"externalSearch":this.bn=e;break;case"searchable":this.vn=e,this.isConnected&&this.shadowRoot&&this.updateSearchVisibility();break;case"allowCreate":this.gn=e,this.isConnected&&this.shadowRoot&&this.updateSearchVisibility();break;case"createTransform":this.mn=e;break;case"size":this.wn=e;break;case"debounce":this.Mn=e;break;case"available-label":this.xn=e||"Available";break;case"no-options-message":this.kn=e||"No options available";break;case"loading":this.yn=e,this.applyLoadingState()}}applyLoadingState(){const t=this.shadowRoot;if(!t)return;const n=this.yn?g():null;t.querySelectorAll(".dropdown-options-wrapper").forEach(t=>{if(t.classList.toggle("loading",this.yn),this.yn){t.setAttribute("aria-busy","true");const e=t.querySelector(".dropdown-loading-spinner");e&&n&&(e.innerHTML=n)}else t.removeAttribute("aria-busy")})}getFormValue(){const t=this.zn.selectedValues;if(this.an&&t.length>0){if(!this.ln)return t[0];const n=new FormData;return t.forEach(t=>{n.append(this.an,t)}),n}return null}parseValue(t){return t&&"string"==typeof t&&""!==t.trim()?t.split(",").map(t=>t.trim()).filter(t=>""!==t):[]}initializeState(){const t=this.getProperty("value")||"";if(t){const n=this.parseValue(t);this.zn.selectedValues=n,this.syncSelectedTags(n),this.updateSelectionDisplay(),this.updateMobileSelectedState()}else{const t=this.getTagElements().filter(t=>t.hasAttribute("selected")).map(t=>this.getTagData(t).value);t.length>0&&this.updateComponentValue(t,!1)}}getTagElements(){return Array.from(this.querySelectorAll("ty-option:not([cloned]), ty-tag:not([cloned])"))}getTagData(t){return{value:t.value||t.getAttribute("value")||t.textContent||"",text:t.getAttribute("label")||t.textContent||"",element:t}}selectTag(t){t.setAttribute("selected","")}deselectTag(t){t.removeAttribute("selected")}getSelectedValues(){return this.getTagElements().filter(t=>t.hasAttribute("selected")).map(t=>this.getTagData(t).value).filter(t=>""!==t)}syncSelectedTags(t){const n=new Set(t);this.getTagElements().forEach(t=>{const e=this.getTagData(t).value,i=n.has(e),o=t.hasAttribute("selected");i&&!o?this.selectTag(t):!i&&o&&this.deselectTag(t),t.setAttribute("aria-selected",i+"")})}ensureOptionRoles(){this.getTagElements().forEach(t=>{t.hasAttribute("role")||t.setAttribute("role","option"),t.hasAttribute("aria-selected")||t.setAttribute("aria-selected","false")})}updateComponentValue(t,n=!1,e="set",i=null){const o=this.getSelectedValues(),s=t.join(",");JSON.stringify(t.sort())!==JSON.stringify(o.sort())&&(this.setProperty("value",s),n&&this.dispatchChangeEvent({value:this.ln?[...t]:t[0]??null,values:t,items:this.getSelectedItems(t),action:e,item:i}))}getSelectedItems(t){const n=new Map(this.getTagElements().map(t=>[this.getTagData(t).value,t]));return t.map(t=>{const e=n.get(t);return{value:t,label:e?.getAttribute("label")||e?.textContent?.trim()||t,flavor:e?.getAttribute("flavor")??null}})}calculatePosition(){const t=this.shadowRoot,n=t.querySelector(".select-stub"),e=t.querySelector(".dropdown-dialog");if(!n||!e)return;const i=n.getBoundingClientRect(),o=e.getBoundingClientRect(),s=Math.min(o.height||200,440),r=parseFloat(getComputedStyle(this).getPropertyValue("--ty-select-popup-width")),a=isNaN(r)?Math.max(i.width,320):r,l=Rt({anchorRect:i,popupWidth:a,popupHeight:s}),c=l.below,d=(c?l.topY:l.bottomY)-20,h=a+20+20;this.style.setProperty("--dropdown-x",l.x-20+"px"),this.style.setProperty("--dropdown-y",d+"px"),this.style.setProperty("--dropdown-width",h+"px"),this.style.setProperty("--dropdown-offset-x","0px"),this.style.setProperty("--dropdown-offset-y","0px"),this.style.setProperty("--dropdown-padding","20px"),c?(e.classList.add("position-below"),e.classList.remove("position-above")):(e.classList.add("position-above"),e.classList.remove("position-below")),this.style.setProperty("--dropdown-direction",c?"below":"above")}Nn(){if(!St())return;const t=this.shadowRoot,n=t.querySelector(".dropdown-options"),e=t.querySelector(".dropdown-options-wrapper");n&&e&&(this.On(),n.classList.add("ty-custom-scroll"),this.In=new Et(n,{vertical:!0}),this.In.trackY&&e.appendChild(this.In.trackY))}On(){this.In&&(this.In.trackY?.remove(),this.In.destroy(),this.In=null)}openDropdown(){const t=this.shadowRoot,n=t.querySelector(".dropdown-dialog");if(!n)return;const e=t.querySelector(".select-stub");e&&e.setAttribute("aria-expanded","true");const i=`select-${this.id||"anon"}-${Hn(this)}`;this.fn=i,an(i),n.showModal(),n.classList.add("open"),this.calculatePosition(),this.zn.open=!0;const o=t.querySelector(".dropdown-chevron");o&&o.classList.add("open");const s=t.querySelector(".dropdown-search-chevron");s&&s.classList.add("open");const r=this.getTagElements().map(t=>this.getTagData(t));this.zn.filteredTags=r,this.zn.highlightedIndex=-1,this.updateOptionsVisibility(!0),this.Nn();const a=t.querySelector(".dropdown-search-input");a&&this.shouldShowSearch()&&setTimeout(()=>a.focus(),100),this.fireOpenEvent()}closeDropdown(){const t=this.shadowRoot,n=t.querySelector(".dropdown-dialog");if(!n)return;const e=t.querySelector(".select-stub");e&&e.setAttribute("aria-expanded","false"),this.On(),n.classList.remove("open"),n.classList.remove("position-above"),n.classList.remove("position-below"),n.close(),this.fn&&(ln(this.fn),this.fn=null),this.zn.open=!1,this.zn.highlightedIndex=-1;const i=t.querySelector(".dropdown-chevron");i&&i.classList.remove("open");const o=t.querySelector(".dropdown-search-chevron");o&&o.classList.remove("open");const s=""!==this.zn.search;this.zn.search="";const r=t.querySelector(".dropdown-search-input");if(r&&(r.value=""),this.bn)s&&(null!==this.An&&(clearTimeout(this.An),this.An=null),this.fireSearchEvent(""));else{const t=this.getTagElements().map(t=>this.getTagData(t));this.zn.filteredTags=t,this.updateTagVisibility(t,t),this.clearHighlights(t)}this.fireCloseEvent()}openMobileModal(){const t=this.shadowRoot,n=t.querySelector(".mobile-dialog");if(!n)return;const e=t.querySelector(".select-stub");e&&e.setAttribute("aria-expanded","true");const i=`select-${this.id||"anon"}-${Hn(this)}`;this.fn=i,an(i),n.showModal(),n.classList.add("open"),this.zn.open=!0;const o=this.getTagElements().map(t=>this.getTagData(t));this.zn.filteredTags=o;const s=t.querySelector(".mobile-search-input");s&&this.shouldShowSearch()&&setTimeout(()=>s.focus(),100),requestAnimationFrame(()=>{this.updateMobileSelectedState()}),this.fireOpenEvent()}closeMobileModal(){const t=this.shadowRoot,n=t.querySelector(".mobile-dialog");if(!n)return;const e=t.querySelector(".select-stub");e&&e.setAttribute("aria-expanded","false"),n.classList.remove("open"),n.close(),this.fn&&(ln(this.fn),this.fn=null),this.zn.open=!1,this.zn.highlightedIndex=-1;const i=""!==this.zn.search;this.zn.search="";const o=t.querySelector(".mobile-search-input");o&&(o.value=""),this.bn?i&&(null!==this.An&&(clearTimeout(this.An),this.An=null),this.fireSearchEvent("")):this.getTagElements().forEach(t=>t.removeAttribute("hidden")),this.fireCloseEvent()}handleStubClick(t){t.preventDefault(),t.stopPropagation(),this.P||this.un||this.openDropdown()}handleStubKeydown(t){this.P||this.un||this.zn.open||"Enter"!==t.key&&" "!==t.key&&"ArrowDown"!==t.key||(t.preventDefault(),this.openDropdown())}handleTagClick(t){const n=t.target.closest("ty-option, ty-tag");n&&!n.hasAttribute("disabled")&&(t.preventDefault(),t.stopPropagation(),this.selectByTag(n))}selectByTag(t){const n=this.getTagData(t).value,e=this.getSelectedValues();if(!this.ln)return this.updateComponentValue([n],!0,"set",n),void("mobile"===this.zn.mode?this.closeMobileModal():this.closeDropdown());if(t.hasAttribute("selected")){const t=e.filter(t=>t!==n);this.updateComponentValue(t,!0,"remove",n)}else this.updateComponentValue([...e,n],!0,"add",n)}tryCreateFromSearch(){if(!this.gn)return!1;const t=(this.zn.search||"").trim();if(!t)return!1;const n=t.toLowerCase(),e=this.getTagElements().map(t=>this.getTagData(t)).find(t=>t.value.toLowerCase()===n||t.text.toLowerCase()===n);if(e)return this.selectByTag(e.element),!0;const i=t,o="slug"===this.mn?i.trim().toLowerCase().replace(/\s+/g,"_").replace(/[^a-z0-9_]/g,"").replace(/_+/g,"_").replace(/^_|_$/g,""):i;if(!o)return!0;const s={value:o,label:i},r=new CustomEvent("create",{detail:s,bubbles:!0,composed:!0,cancelable:!0});if(this.dispatchEvent(r),r.defaultPrevented)return!0;const a=s.value,l=document.createElement("ty-option");if(l.setAttribute("value",a),l.textContent=i,this.appendChild(l),!this.ln)return this.updateComponentValue([a],!0,"create",a),"mobile"===this.zn.mode?this.closeMobileModal():this.closeDropdown(),!0;const c=this.getSelectedValues();return this.updateComponentValue([...c,a],!0,"create",a),this.clearSearchAfterCreate(),!0}clearSearchAfterCreate(){this.zn.search="",this.zn.highlightedIndex=-1;const t=this.shadowRoot;if(!t)return;const n=t.querySelector(".dropdown-search-input"),e=t.querySelector(".mobile-search-input");n&&(n.value=""),e&&(e.value="");const i=this.getTagElements().map(t=>this.getTagData(t));this.zn.filteredTags=i,this.updateTagVisibility(i,i),this.updateOptionsVisibility(!0),this.clearHighlights(i),this.updateMobileSelectedState(),(n??e)?.focus()}blockSearchClick(t){t.stopPropagation(),t.preventDefault()}handleSearchInput(t){const n=t.target.value;if(this.zn.search=n,this.bn)return void this.dispatchSearchEvent(n);const e=this.getTagElements().map(t=>this.getTagData(t)),i=this.filterTags(e,n);this.zn.filteredTags=i,this.zn.highlightedIndex=-1,this.updateTagVisibility(i,e),this.updateOptionsVisibility(i.length>0),this.updateMobileSelectedState(),this.clearHighlights(e)}handleKeyboard(t){if(!this.zn.open)return;const n=this.shadowRoot.querySelector(".dropdown-search-input");if(t.target!==n&&document.activeElement===n)return;const e=this.zn.filteredTags,i=e.length,o=this.zn.highlightedIndex;switch(t.key){case"Escape":t.preventDefault(),t.stopPropagation(),this.closeDropdown();break;case"Enter":t.preventDefault(),t.stopPropagation(),o>=0&&i>o?this.selectByTag(e[o].element):this.tryCreateFromSearch();break;case"ArrowUp":let n;t.preventDefault(),t.stopPropagation(),n=0===i?-1:-1===o||0===o?i-1:o-1,this.zn.highlightedIndex=n,this.highlightTag(e,n);break;case"ArrowDown":let s;t.preventDefault(),t.stopPropagation(),s=0===i?-1:-1===o||o===i-1?0:o+1,this.zn.highlightedIndex=s,this.highlightTag(e,s)}}filterTags(t,n){if(!n||""===n.trim())return t;const e=n.toLowerCase();return t.filter(({text:t})=>t.toLowerCase().includes(e))}updateTagVisibility(t,n){const e=new Set(t.map(t=>t.value));n.forEach(({value:t,element:n})=>{e.has(t)?n.removeAttribute("hidden"):n.setAttribute("hidden","")})}updateOptionsVisibility(t){const n=this.shadowRoot.querySelector(".dropdown-options");n&&(n.style.display=t?"":"none")}clearHighlights(t){t.forEach(({element:t})=>{t.removeAttribute("highlighted")})}highlightTag(t,n){if(this.clearHighlights(t),n>=0&&t.length>n){const{element:e}=t[n];e.setAttribute("highlighted",""),e.scrollIntoView({behavior:"smooth",block:"nearest",inline:"nearest"})}}dispatchSearchEvent(t){null!==this.An&&(clearTimeout(this.An),this.An=null),this.Mn>0?this.An=window.setTimeout(()=>{this.fireSearchEvent(t),this.An=null},this.Mn):this.fireSearchEvent(t)}fireSearchEvent(t){this.dispatchEvent(new CustomEvent("search",{detail:{query:t,element:this},bubbles:!0,composed:!0}))}fireOpenEvent(){this.dispatchEvent(new CustomEvent("open",{detail:{mode:this.zn.mode,element:this},bubbles:!0,composed:!0})),this.bn&&this.fireSearchEvent("")}fireCloseEvent(){this.dispatchEvent(new CustomEvent("close",{detail:{mode:this.zn.mode,element:this},bubbles:!0,composed:!0}))}dispatchChangeEvent(t){this.dispatchEvent(new CustomEvent("change",{detail:t,bubbles:!0,cancelable:!0}))}render(){this.zn.mode=Y()?"mobile":"desktop","mobile"===this.zn.mode?this.renderMobile():this.renderDesktop(),this.updateSearchVisibility(),this.applyLoadingState()}setupTriggerSlot(){const t=this.shadowRoot,n=t.querySelector(".select-stub"),e=t.querySelector('slot[name="trigger"]');if(!n||!e)return;const i=()=>n.classList.toggle("custom-trigger",e.assignedElements().length>0);e.addEventListener("slotchange",i),i()}setupEventListeners(){const t=this.shadowRoot,n=t.querySelector(".select-stub"),e=t.querySelector("#options-slot"),i=t.querySelector(".dropdown-search-input");n&&(this.$n=this.handleStubClick.bind(this),n.addEventListener("click",this.$n),n.addEventListener("keydown",this.handleStubKeydown.bind(this))),this.setupTriggerSlot(),e&&(this.Cn=this.handleTagClick.bind(this),e.addEventListener("click",this.Cn)),i&&(this.Sn=this.handleSearchInput.bind(this),this.En=this.blockSearchClick.bind(this),i.addEventListener("input",this.Sn),i.addEventListener("click",this.En));const o=t.querySelector(".dropdown-dialog");o&&o.addEventListener("click",t=>{t.target===o&&this.closeDropdown()}),this.Tn=this.handleKeyboard.bind(this),document.addEventListener("keydown",this.Tn)}buildStubClasses(){const t=[this.wn];return this.P&&t.push("disabled"),this.cn&&t.push("compact"),t.join(" ")}renderDesktop(){const t=this.shadowRoot;if(!t.querySelector(".select-container")){const n=this.buildStubClasses(),e="select-listbox-"+Hn(this),i="select-label-"+Hn(this);t.innerHTML=`\n <div class="select-container dropdown-mode-desktop">\n ${this.hn?`\n <label class="ty-field-label" id="${i}">\n ${this.hn}\n ${this.pn?`<span class="required-icon">${Q}</span>`:""}\n </label>\n `:""}\n <div class="dropdown-wrapper">\n <div class="dropdown-stub select-stub ${n}"\n role="combobox"\n aria-haspopup="listbox"\n aria-expanded="false"\n aria-controls="${e}"\n ${this.hn?`aria-labelledby="${i}"`:""}\n tabindex="${this.P?"-1":"0"}"\n ${this.P?'disabled aria-disabled="true"':""}>\n <slot name="trigger">\n <slot name="start"></slot>\n <slot name="selected"></slot>\n <span class="dropdown-placeholder">${this.dn}</span>\n <span class="select-count" hidden></span>\n <slot name="end"></slot>\n <div class="dropdown-chevron">\n ${Bn}\n </div>\n </slot>\n </div>\n <dialog class="dropdown-dialog">\n <div class="dropdown-header">\n <div class="dropdown-search-icon" aria-hidden="true">\n ${jn}\n </div>\n <input\n class="dropdown-search-input ${this.wn}"\n type="text"\n placeholder="Search..."\n ${this.P?"disabled":""}\n />\n <div class="dropdown-search-chevron">\n ${Bn}\n </div>\n </div>\n <div class="dropdown-options-wrapper">\n <div class="dropdown-options" id="${e}" role="listbox" ${this.ln?'aria-multiselectable="true"':""}>\n <slot id="options-slot"></slot>\n </div>\n <div class="dropdown-loading" aria-hidden="true">\n <slot name="loading">\n <span class="dropdown-loading-spinner"></span>\n <span class="dropdown-loading-text">Searching…</span>\n </slot>\n </div>\n </div>\n </dialog>\n </div>\n </div>\n `,this.setupEventListeners()}this.updateSelectionDisplay()}renderMobile(){const t=this.shadowRoot;if(!t.querySelector(".select-container")){const n=this.buildStubClasses(),e="select-listbox-"+Hn(this),i="select-label-"+Hn(this);t.innerHTML=`\n <div class="select-container dropdown-mode-mobile">\n ${this.hn?`\n <label class="ty-field-label" id="${i}">\n ${this.hn}\n ${this.pn?`<span class="required-icon">${Q}</span>`:""}\n </label>\n `:""}\n <div class="dropdown-wrapper">\n <div class="dropdown-stub select-stub ${n}"\n role="combobox"\n aria-haspopup="listbox"\n aria-expanded="false"\n aria-controls="${e}"\n ${this.hn?`aria-labelledby="${i}"`:""}\n tabindex="${this.P?"-1":"0"}"\n ${this.P?'disabled aria-disabled="true"':""}>\n <slot name="trigger">\n <slot name="start"></slot>\n <slot name="selected"></slot>\n <span class="dropdown-placeholder">${this.dn}</span>\n <span class="select-count" hidden></span>\n <slot name="end"></slot>\n <div class="dropdown-chevron">\n ${Bn}\n </div>\n </slot>\n </div>\n\n <dialog class="mobile-dialog">\n <div class="mobile-dialog-content">\n\n \x3c!-- HEADER (matches dropdown.ts) --\x3e\n \n <div class="mobile-search-header">\n ${this.hn?`<span class="mobile-header-label">${this.hn}</span>`:""}\n <div class="mobile-header-content">\n <div class="dropdown-search-icon" aria-hidden="true">\n ${jn}\n </div>\n <input\n class="mobile-search-input ${this.wn}"\n type="text"\n placeholder="${this.hn?`Search ${this.hn}...`:"Search..."}"\n ${this.P?"disabled":""}\n />\n <button class="mobile-close-button" type="button" aria-label="Close">\n <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">\n <line x1="18" y1="6" x2="6" y2="18"></line>\n <line x1="6" y1="6" x2="18" y2="18"></line>\n </svg>\n </button>\n </div>\n </div>\n \n\n \x3c!-- BODY: options list with toggleable selected state --\x3e\n <div class="mobile-body">\n\n \x3c!-- AVAILABLE LIST (always visible, takes remaining space) --\x3e\n <div class="mobile-available-section" data-empty="false">\n <div class="section-header">\n <span class="section-title">${this.xn}</span>\n </div>\n <div class="section-content dropdown-options-wrapper" id="${e}" role="listbox" ${this.ln?'aria-multiselectable="true"':""}>\n <slot id="options-slot"></slot>\n <div class="empty-state">${this.kn}</div>\n <div class="dropdown-loading" aria-hidden="true">\n <slot name="loading">\n <span class="dropdown-loading-spinner"></span>\n <span class="dropdown-loading-text">Searching…</span>\n </slot>\n </div>\n </div>\n </div>\n\n </div>\n </div>\n </dialog>\n </div>\n </div>\n `,this.setupMobileEventListeners()}this.updateSelectionDisplay()}setupMobileEventListeners(){const t=this.shadowRoot,n=t.querySelector(".select-stub"),e=t.querySelector("#options-slot"),i=t.querySelector(".mobile-search-input"),o=t.querySelector(".mobile-close-button"),s=t.querySelector(".mobile-dialog");n&&(n.addEventListener("click",t=>this.handleMobileStubClick(t)),n.addEventListener("keydown",t=>this.handleMobileStubKeydown(t))),this.setupTriggerSlot(),e&&e.addEventListener("click",t=>this.handleMobileTagClick(t)),i&&i.addEventListener("input",t=>this.handleSearchInput(t)),o&&o.addEventListener("click",()=>this.closeMobileModal()),s&&(s.addEventListener("click",t=>{t.target===s&&this.closeMobileModal()}),s.addEventListener("cancel",t=>{t.preventDefault(),this.closeMobileModal()}))}handleMobileStubClick(t){t.preventDefault(),t.stopPropagation(),this.P||this.un||this.openMobileModal()}handleMobileStubKeydown(t){this.P||this.un||this.zn.open||"Enter"!==t.key&&" "!==t.key&&"ArrowDown"!==t.key||(t.preventDefault(),this.openMobileModal())}handleMobileTagClick(t){this.handleTagClick(t)}updateMobileSelectedState(){if("mobile"!==this.zn.mode)return;const t=this.shadowRoot,n=t.querySelector(".mobile-available-section");if(n){const e=this.getTagElements().filter(t=>!t.hasAttribute("hidden")).length;n.setAttribute("data-empty",(0===e)+"");const i=t.querySelector(".mobile-available-section .section-title");i&&(i.textContent=`${this.xn} (${e})`)}}shouldShowSearch(){return!!this.bn||!!this.gn||"always"===this.vn||"never"!==this.vn&&this.getTagElements().length>7}updateSearchVisibility(){const t=this.shadowRoot;if(!t)return;const n=this.shouldShowSearch(),e=t.querySelector(".dropdown-header");e&&(e.hidden=!n);const i=t.querySelector(".mobile-search-input");i&&(i.hidden=!n);const o=t.querySelector(".mobile-header-content .dropdown-search-icon");o&&(o.hidden=!n)}updateSelectionDisplay(){const t=this.shadowRoot.querySelector(".select-stub");if(!t)return;const n=this.zn.selectedValues,e=n.length;t.classList.toggle("has-selection",e>0),t.classList.toggle("compact",this.cn);const i=t.querySelector(".select-count");i&&(i.textContent=e+"",i.hidden=0===e||!this.ln||!this.cn);const o=!this.ln&&e>0?n[0]:null;this.syncSelectedClone(o),t.classList.toggle("has-clone",null!==o);const s=t.querySelector(".dropdown-placeholder");s&&(s.hidden=null!==o,e>0&&this.ln&&!this.cn?(s.textContent=this.getSelectedItems(n).map(t=>t.label).join(", "),s.classList.remove("placeholder-shown")):(s.textContent=this.dn,s.classList.add("placeholder-shown")))}syncSelectedClone(t){const n=this.querySelector(':scope > [cloned][slot="selected"]');if(n?.getAttribute("value")===t)return void(this.Ln=n);if(n?.remove(),null===t)return void(this.Ln=null);const e=this.getTagElements().find(n=>this.getTagData(n).value===t);if(e){const t=e.cloneNode(!0);t.removeAttribute("selected"),t.setAttribute("slot","selected"),t.setAttribute("cloned","true"),this.appendChild(t),this.Ln=t}else if(this.Ln?.getAttribute("value")===t){const t=this.Ln.cloneNode(!0);this.appendChild(t),this.Ln=t}}deselectValue(t){const n=this.getSelectedValues();n.includes(t)&&this.updateComponentValue(n.filter(n=>n!==t),!0,"remove",t)}get value(){return this.getSelectedValues().join(",")}set value(t){this.setProperty("value",t)}get name(){return this.getProperty("name")}set name(t){this.setProperty("name",t)}get multiple(){return this.getProperty("multiple")}set multiple(t){this.setProperty("multiple",t)}get compact(){return this.getProperty("compact")}set compact(t){this.setProperty("compact",t)}get placeholder(){return this.getProperty("placeholder")}set placeholder(t){this.setProperty("placeholder",t)}get label(){return this.getProperty("label")}set label(t){this.setProperty("label",t)}get disabled(){return this.getProperty("disabled")}set disabled(t){this.setProperty("disabled",t)}get loading(){return this.getProperty("loading")}set loading(t){this.setProperty("loading",t)}get readonly(){return this.getProperty("readonly")}set readonly(t){this.setProperty("readonly",t)}get required(){return this.getProperty("required")}set required(t){this.setProperty("required",t)}get searchable(){return this.getProperty("searchable")}set searchable(t){this.setProperty("searchable",t)}get externalSearch(){return this.getProperty("externalSearch")}set externalSearch(t){this.setProperty("externalSearch",t)}get debounce(){return this.getProperty("debounce")}set debounce(t){this.setProperty("debounce","string"==typeof t?parseInt(t,10):t)}get size(){return this.getProperty("size")}set size(t){this.setProperty("size",t)}get flavor(){return this.getProperty("flavor")}set flavor(t){this.setProperty("flavor",t)}get form(){return this.v.form}};Wn.properties={value:{type:"string",visual:!0,formValue:!0,emitChange:!1,default:"",coerce:t=>Array.isArray(t)?t.join(","):null==t?"":t+""},name:{type:"string",default:""},multiple:{type:"boolean",visual:!0,default:!1},compact:{type:"boolean",visual:!0,default:!1},placeholder:{type:"string",visual:!0,default:"Select..."},label:{type:"string",visual:!0,default:""},disabled:{type:"boolean",visual:!0,default:!1},readonly:{type:"boolean",visual:!0,default:!1},required:{type:"boolean",visual:!0,default:!1},externalSearch:{type:"boolean",visual:!0,default:!1,aliases:{"external-search":!0}},allowCreate:{type:"boolean",visual:!0,default:!1,aliases:{"allow-create":!0}},createTransform:{type:"string",visual:!1,default:"none",aliases:{"create-transform":!0},coerce:t=>"slug"===t?"slug":"none"},searchable:{type:"string",visual:!0,default:"auto",coerce:t=>!0===t||""===t||"true"===t?"always":!1===t||"false"===t?"never":"auto"},size:{type:"string",visual:!0,default:"md",validate:t=>["sm","md","lg"].includes(t),coerce:t=>"xs"===t?"sm":"xl"===t?"lg":["sm","md","lg"].includes(t)?t:"md"},debounce:{type:"number",default:0,validate:t=>t>=0&&5e3>=t,coerce:t=>{const n=+t;return isNaN(n)?0:Math.max(0,Math.min(5e3,n))}},"available-label":{type:"string",visual:!0,default:"Available"},"no-options-message":{type:"string",visual:!0,default:"No options available"},loading:{type:"boolean",visual:!0,default:!1},flavor:{type:"string",visual:!0,default:"neutral"}};let _n=Wn;function Yn(t,n){return t.replace(/\{([\w-]+)\}/g,(t,e)=>n[e]??t)}customElements.get("ty-select")||customElements.define("ty-select",_n);class TySelectedTags extends HTMLElement{constructor(){super(...arguments),this.Rn=null,this.qn=()=>this.renderChips(),this.Dn=null,this.Vn=null,this.Pn=null}static get observedAttributes(){return["for"]}connectedCallback(){this.style.display||(this.style.display="contents"),this.bind(),this.renderChips(),this.Dn=new MutationObserver(()=>{this.template()!==this.Pn&&this.renderChips()}),this.Dn.observe(this,{childList:!0})}disconnectedCallback(){this.unbind(),this.Dn?.disconnect(),this.Dn=null}attributeChangedCallback(){this.isConnected&&(this.bind(),this.renderChips())}resolvePicker(){const t=this.getAttribute("for");return(t?document.getElementById(t):this.previousElementSibling)??null}bind(){const t=this.resolvePicker();t!==this.Rn&&(this.unbind(),this.Rn=t,this.Rn?.addEventListener("change",this.qn),this.Rn&&(this.Vn=new MutationObserver(()=>this.renderChips()),this.Vn.observe(this.Rn,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["selected"]})))}unbind(){this.Rn?.removeEventListener("change",this.qn),this.Vn?.disconnect(),this.Vn=null,this.Rn=null}values(){return(this.Rn?.value??"").split(",").map(t=>t.trim()).filter(Boolean)}template(){return this.querySelector(":scope > template")}context(t){const n=this.Rn?.querySelector(`[value="${CSS.escape(t)}"]`),e={value:t,label:n?.getAttribute("label")||n?.textContent?.trim()||t,flavor:n?.getAttribute("flavor")??""};if(n)for(const i of Array.from(n.attributes))i.name.startsWith("data-")&&(e[i.name]=i.value);return e}templateSource(t){if(t.content.firstElementChild)return t.content;const n=document.createDocumentFragment();return t.childNodes.forEach(t=>n.appendChild(t.cloneNode(!0))),n}stampTemplate(t,n){const e=this.context(n),i=this.templateSource(t).cloneNode(!0),o=document.createTreeWalker(i,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_TEXT);for(let s=o.nextNode();s;s=o.nextNode())if(s.nodeType===Node.TEXT_NODE)s.textContent?.includes("{")&&(s.textContent=Yn(s.textContent,e));else{const t=s;for(const n of Array.from(t.attributes)){if(!n.value.includes("{"))continue;const i=Yn(n.value,e);!/^\{[\w-]+\}$/.test(n.value)||""!==i&&i!==n.value?t.setAttribute(n.name,i):t.removeAttribute(n.name)}}for(const s of Array.from(i.children))s.addEventListener("dismiss",t=>{t.stopPropagation(),this.deselect(n)});return i}defaultChip(t){const n=this.context(t),e=document.createElement("ty-tag");return e.setAttribute("value",t),e.setAttribute("dismissible","true"),n.flavor&&e.setAttribute("flavor",n.flavor),e.textContent=n.label,e.addEventListener("dismiss",()=>this.deselect(t)),e}renderChips(){const t=this.template();if(this.Pn=t,!this.Rn)return void this.replaceChildren(...t?[t]:[]);const n=document.createDocumentFragment();t&&n.appendChild(t);for(const e of this.values())n.appendChild(t?this.stampTemplate(t,e):this.defaultChip(e));this.replaceChildren(n)}deselect(t){if(!this.Rn)return;const n=this.Rn;"function"==typeof n.deselectValue?n.deselectValue(t):(n.value=this.values().filter(n=>n!==t).join(","),this.renderChips())}}customElements.get("ty-selected-tags")||customElements.define("ty-selected-tags",TySelectedTags);const Un=new WeakMap,Gn=new WeakMap;function Zn(t){return{width:t.getAttribute("width")||"100%",height:t.getAttribute("height")||"400px",active:t.getAttribute("active"),placement:t.getAttribute("placement")||"top"}}function Kn(t){return Array.from(t.querySelectorAll("ty-tab"))}function Xn(t){return t.getAttribute("id")}function Jn(t,n){const e=Xn(n);return e&&function(t,n){return null!==t.querySelector(`[slot='label-${n}']`)}(t,e)?"slot":"text"}function Qn(t){return t.hasAttribute("disabled")}function te(t,n){const e=t.findIndex(t=>Xn(t)===n);return 0>e?void 0:e}function ne(t,n){const e=t.getAttribute("active");return e&&void 0!==te(n,e)?e:n.length>0?Xn(n[0]):null}function ee(t){const n=Un.get(t);if(!n)return;const e=t.shadowRoot;e&&(n.tabClickHandlers.forEach((t,n)=>{const i=e.querySelector(`[data-tab-id='${n}']`);i&&i.removeEventListener("pointerdown",t)}),n.tabClickHandlers.clear())}function ie(t,n,e){ee(t);const i={tabClickHandlers:new Map};e.forEach(e=>{const o=Xn(e);if(!o)return;const s=n.querySelector(`[data-tab-id='${o}']`);if(s){const n=n=>function(t,n,e){e.preventDefault(),e.stopPropagation(),function(t,n){t.setAttribute("active",n)}(t,n)}(t,o,n);s.addEventListener("pointerdown",n),i.tabClickHandlers.set(o,n)}}),Un.set(t,i)}function oe(t,n){const e=t.shadowRoot;if(!e)return;const i=e.querySelector(".panels-wrapper");i&&(i.style.transform=`translateX(-${n*t.offsetWidth}px)`)}function se(t,n,e){Kn(t).forEach(i=>{const o=Xn(i);if(!o)return;const s=n.querySelector(`[data-tab-id='${o}']`),r=o===e;if(s){s.setAttribute("aria-selected",r+""),s.setAttribute("tabindex",r?"0":"-1"),s.setAttribute("data-active",r+"");const n=t.querySelector(`[slot='label-${o}']`);n&&n.setAttribute("data-active",r+"")}})}function re(t,n){Kn(t).forEach(t=>{const e=Xn(t);if(!e)return;const i=e===n;t.setAttribute("data-active",i+""),i?(t.style.pointerEvents="auto",t.style.opacity="1"):(t.style.pointerEvents="none",t.style.opacity="0")})}function ae(t,n){const e=t.shadowRoot;if(!e)return;const i=e.querySelector(".marker-wrapper");if(!i)return;const o=function(t,n,e){const i=n.querySelector(`[data-tab-id='${e}']`),o=n.querySelector(".tab-buttons");if(!i||!o)return null;const s=i.getBoundingClientRect();return{left:i.offsetLeft,top:i.offsetTop,width:s.width,height:s.height}}(0,e,n);if(!o)return;const s=!i.style.left||0===i.offsetWidth;s&&(i.style.transition="none"),i.style.left=o.left+"px",i.style.top=o.top+"px",i.style.width=o.width+"px",i.style.height=o.height+"px",s&&(i.style.transition="")}function le(t){const n=t.shadowRoot;if(!n)return;const{width:e,height:i,placement:o}=Zn(t),r=Kn(t),a=ne(t,r),l=a?te(r,a)??0:0;r.forEach(t=>{const n=Xn(t);n&&(t.setAttribute("role","tabpanel"),t.setAttribute("aria-labelledby","tab-"+n),t.setAttribute("tabindex","0"))});const c=n.querySelector(".tabs-container"),d=n.querySelector(".tab-buttons"),h=n.querySelector(".panels-viewport");if(s(n,{css:'\n:host {\n display: block;\n width: var(--tabs-width, 100%);\n height: var(--tabs-height, 400px);\n box-sizing: border-box;\n}\n\n.tabs-container {\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n position: relative;\n box-sizing: border-box;\n}\n\n/* Bottom placement reverses the order */\n.tabs-container[data-placement="bottom"] {\n flex-direction: column-reverse;\n}\n\n/* ===================================== */\n/* Tab Buttons Container */\n/* Expose as CSS Part for full styling control */\n/* ===================================== */\n\n.tab-buttons {\n display: flex;\n gap: 0;\n flex-shrink: 0;\n position: relative;\n /* For absolute positioned marker */\n \n /* Default minimal styling - customize via ::part(buttons-container) */\n border-bottom: 1px solid var(--ty-border);\n background: transparent;\n}\n\n/* Bottom placement moves border to top */\n.tabs-container[data-placement="bottom"] .tab-buttons {\n border-bottom: none;\n border-top: 1px solid var(--ty-border);\n}\n\n/* ===================================== */\n/* Marker Wrapper */\n/* Expose as CSS Part for custom marker styling */\n/* ===================================== */\n\n.marker-wrapper {\n position: absolute;\n z-index: 0;\n /* Behind buttons */\n pointer-events: none;\n /* Don\'t block clicks */\n transition: left var(--transition-duration, 300ms) var(--transition-easing, ease-in-out),\n width var(--transition-duration, 300ms) var(--transition-easing, ease-in-out),\n height var(--transition-duration, 300ms) var(--transition-easing, ease-in-out),\n top var(--transition-duration, 300ms) var(--transition-easing, ease-in-out);\n}\n\n/* Default marker - simple underline */\n.default-marker {\n position: absolute;\n bottom: 0;\n left: 0;\n height: 2px;\n width: 100%;\n background: var(--ty-color-primary);\n pointer-events: none;\n}\n\n/* Hide default marker when custom marker is slotted */\n.marker-wrapper:has(::slotted([slot="marker"])) .default-marker {\n display: none;\n}\n\n/* User\'s marker element fills the wrapper */\n::slotted([slot="marker"]) {\n display: block;\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n}\n\n/* ===================================== */\n/* Tab Buttons */\n/* ===================================== */\n\n.tab-button {\n min-width: 120px;\n padding: 6px 12px;\n border: none;\n background: transparent;\n cursor: pointer;\n font: inherit;\n color: var(--ty-text-soft);\n transition: color 200ms, background-color 200ms;\n white-space: nowrap;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n font-weight: var(--ty-font-bold);\n font-size: var(--ty-font-sm);\n position: relative;\n /* Establish stacking context */\n z-index: 10;\n /* Above marker */\n}\n\n.tab-button[aria-selected=true] {\n color: var(--ty-text-strong);\n}\n\n.tab-button[disabled] {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n}\n\n.tab-button:focus-visible {\n outline: 2px solid var(--ty-color-primary);\n outline-offset: -2px;\n}\n\n/* ===================================== */\n/* Panels Viewport */\n/* Expose as CSS Part for panels container styling */\n/* ===================================== */\n\n.panels-viewport {\n position: relative;\n flex: 1;\n overflow: hidden;\n /* Critical: hides off-screen panels */\n min-height: 0;\n /* Allows flex child to shrink */\n}\n\n/* ===================================== */\n/* Panels Wrapper (slides horizontally) */\n/* ===================================== */\n\n.panels-wrapper {\n display: flex;\n height: 100%;\n transition: transform var(--transition-duration, 300ms) var(--transition-easing, ease-in-out);\n}\n\n/* Respect user\'s motion preferences */\n@media (prefers-reduced-motion: reduce) {\n .panels-wrapper {\n transition-duration: 0ms !important;\n }\n\n .marker-wrapper {\n transition-duration: 0ms !important;\n }\n}\n\n/* ===================================== */\n/* Slotted Tab Panels */\n/* ===================================== */\n\n::slotted(ty-tab) {\n width: var(--tabs-width, 100%);\n height: 100%;\n flex-shrink: 0;\n}\n',id:"ty-tabs"}),t.style.setProperty("--tabs-width",e.includes("%")?"100%":e),t.style.setProperty("--tabs-height",i),t.style.setProperty("--active-index",l+""),c&&d&&h){c.setAttribute("data-placement",o),d.querySelectorAll(".tab-button").forEach(t=>t.remove());const e=function(t,n,e){return n.map(n=>{const i=Xn(n);if(!i)return"";const o=Jn(t,n),s="text"===o?n.getAttribute("label")||"Tab":"",r=Qn(n),a=i===e;return`<button\n class="tab-button"\n role="tab"\n data-tab-id="${i}"\n id="tab-${i}"\n aria-selected="${a}"\n tabindex="${a?"0":"-1"}"\n data-active="${a}"\n ${r?'disabled aria-disabled="true"':""}\n >\n ${"slot"===o?`<slot name="label-${i}"></slot>`:s}\n </button>`}).join("")}(t,r,a),i=document.createElement("div");i.innerHTML=e,Array.from(i.children).forEach(t=>{d.appendChild(t)}),ie(t,n,r),se(t,n,a||""),requestAnimationFrame(()=>{const e=n.querySelector(".tab-buttons");e&&t.style.setProperty("--buttons-height",e.offsetHeight+"px"),oe(t,l),a&&ae(t,a)}),a&&re(t,a)}else{n.innerHTML=`\n <div class="tabs-container" data-placement="${o}">\n ${function(t,n,e){const i=n.map(n=>{const i=Xn(n);if(!i)return"";const o=Jn(t,n),s="text"===o?n.getAttribute("label")||"Tab":"",r=Qn(n),a=i===e;return`<button\n class="tab-button"\n role="tab"\n data-tab-id="${i}"\n id="tab-${i}"\n aria-selected="${a}"\n tabindex="${a?"0":"-1"}"\n data-active="${a}"\n ${r?'disabled aria-disabled="true"':""}\n >\n ${"slot"===o?`<slot name="label-${i}"></slot>`:s}\n </button>`}).join("");return`\n <div class="tab-buttons" role="tablist" part="buttons-container">\n <div class="marker-wrapper" part="marker-wrapper">\n ${o=t,null===o.querySelector('[slot="marker"]')?'<div class="default-marker"></div>':""}\n <slot name="marker"></slot>\n </div>\n ${i}\n </div>\n `;var o}(t,r,a)}\n <div class="panels-viewport" part="panels-container">\n <div class="panels-wrapper">\n <slot></slot>\n </div>\n </div>\n </div>\n `,requestAnimationFrame(()=>{const e=n.querySelector(".tab-buttons");e&&t.style.setProperty("--buttons-height",e.offsetHeight+"px"),oe(t,l),a&&ae(t,a)}),ie(t,n,r),se(t,n,a||""),function(t){const n=Gn.get(t);n&&n.disconnect();const{width:e}=Zn(t);if(e.includes("%")){const n=new ResizeObserver(n=>{const e=n[0].contentRect.width,i=Kn(t),o=ne(t,i),s=o?te(i,o):0;t.style.setProperty("--tabs-width",e+"px"),void 0!==s&&oe(t,s),o&&ae(t,o)});n.observe(t),Gn.set(t,n)}}(t),a&&re(t,a);const e=n.querySelector('slot[name="marker"]');if(e){const t=()=>{const t=n.querySelector(".default-marker");if(t){const n=e.assignedElements().length>0;t.style.display=n?"none":""}};e.addEventListener("slotchange",t),t()}}}class TyTabs extends HTMLElement{static get observedAttributes(){return["width","height","active","placement"]}constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){le(this)}disconnectedCallback(){ee(this),function(t){const n=Gn.get(t);n&&(n.disconnect(),Gn.delete(t))}(this)}attributeChangedCallback(t,n,e){"active"===t?(e&&function(t,n,e){const i=Kn(t),o=t.shadowRoot;if(!o)return;const s=e?te(i,e):void 0,r=te(i,n);if(e===n||void 0===r)return;t.style.setProperty("--active-index",r+""),oe(t,r),se(t,o,n),re(t,n),ae(t,n);const a=i[r];a?.resetScroll&&a.resetScroll(),function(t,n,e,i,o){const s=new CustomEvent("ty-tab-change",{detail:{activeId:n,activeIndex:e,previousId:i,previousIndex:o},bubbles:!0,cancelable:!1});t.dispatchEvent(s)}(t,n,r,e,s??null)}(this,e,n),le(this)):le(this)}}customElements.get("ty-tabs")||customElements.define("ty-tabs",TyTabs);const ce=`\n:host {\n width: var(--tabs-width, 100%);\n height: calc(var(--tabs-height, 400px) - var(--buttons-height, 48px));\n display: block;\n box-sizing: border-box;\n flex-shrink: 0;\n transition: opacity var(--transition-duration, 400ms) var(--transition-easing, ease-in-out);\n}\n\n@media (prefers-reduced-motion: reduce) {\n :host {\n transition-duration: 0ms !important;\n }\n}\n\n.tab-wrapper {\n width: 100%;\n height: 100%;\n position: relative;\n overflow: hidden;\n}\n\n.tab-panel {\n width: 100%;\n height: 100%;\n overflow: auto;\n box-sizing: border-box;\n}\n\n.tab-panel.ty-custom-scroll {\n scrollbar-width: none;\n -ms-overflow-style: none;\n}\n\n.tab-panel.ty-custom-scroll::-webkit-scrollbar {\n display: none;\n}\n\n/* Show scrollbar on hover */\n.tab-wrapper:hover .ty-scrollbar-track-y.has-overflow {\n opacity: 1;\n}\n\n${Tt}\n`;class TyTab extends HTMLElement{constructor(){super(),this.nn=null,this.attachShadow({mode:"open"})}static get observedAttributes(){return["id","label","disabled"]}connectedCallback(){this.Fn()}disconnectedCallback(){this.en()}attributeChangedCallback(t,n,e){this.Fn()}Fn(){const t=this.shadowRoot;if(!t)return;const n=this.getAttribute("id");t.querySelector(".tab-wrapper")||(s(t,{css:ce,id:"ty-tab"}),t.innerHTML=`\n <div class="tab-wrapper"\n role="tabpanel"\n ${n?`id="panel-${n}"`:""}\n ${n?`aria-labelledby="tab-${n}"`:""}\n >\n <div class="tab-panel">\n <slot></slot>\n </div>\n </div>\n `,this.sn())}sn(){const t=this.shadowRoot?.querySelector(".tab-panel"),n=this.shadowRoot?.querySelector(".tab-wrapper");t&&n&&St()&&(t.classList.add("ty-custom-scroll"),this.nn=new Et(t,{vertical:!0}),this.nn.trackY&&n.appendChild(this.nn.trackY))}en(){this.nn&&(this.nn.trackY?.remove(),this.nn.destroy(),this.nn=null)}resetScroll(){this.nn?.scrollToTop(!1)}}customElements.get("ty-tab")||customElements.define("ty-tab",TyTab);const de=new WeakMap,he=new WeakMap;function ue(t){return{width:t.getAttribute("width")||"100%",height:t.getAttribute("height")||"700px",active:t.getAttribute("active"),completed:t.getAttribute("completed")||"",orientation:t.getAttribute("orientation")||"horizontal"}}function pe(t){return Array.from(t.querySelectorAll("ty-step"))}function be(t){return t.getAttribute("id")}function ge(t){const n=t.getAttribute("completed")||"";return n.trim()?new Set(n.split(",").map(t=>t.trim()).filter(Boolean)):new Set}function me(t,n){const e=t.findIndex(t=>be(t)===n);return 0>e?void 0:e}function ve(t,n){const e=t.getAttribute("active");return e&&void 0!==me(n,e)?e:n.length>0?be(n[0]):null}function ye(t,n){return t.length>1&&n?t.findIndex(t=>be(t)===n)/(t.length-1)*100:0}function fe(t){const n=de.get(t);if(!n)return;const e=t.shadowRoot;e&&(n.stepClickHandlers.forEach((t,n)=>{const i=e.querySelector(`[data-step-id='${n}']`);i&&i.removeEventListener("pointerdown",t)}),n.stepClickHandlers.clear())}function we(t,n,e){fe(t);const i={stepClickHandlers:new Map};e.forEach(e=>{const o=be(e);if(!o)return;const s=n.querySelector(`[data-step-id='${o}']`);if(s){const n=n=>function(t,n,e){e.preventDefault(),e.stopPropagation();const i=pe(t),o=i.findIndex(t=>be(t)===n);if(0>o)return;const s=ve(t,i),r=s?me(i,s)??null:null,a=new CustomEvent("ty-wizard-step-change",{detail:{activeId:n,activeIndex:o,previousId:s,previousIndex:r,direction:null===r?"none":o>r?"forward":r>o?"backward":"none"},bubbles:!0,cancelable:!1});t.dispatchEvent(a)}(t,o,n);s.addEventListener("pointerdown",n),i.stepClickHandlers.set(o,n)}}),de.set(t,i)}function xe(t,n){const e=t.shadowRoot;if(!e)return;const i=e.querySelector(".panels-wrapper");i&&(i.style.transform=`translateX(-${n*t.offsetWidth}px)`)}function ke(t){const n=t.shadowRoot;if(!n)return;const e=n.querySelector(".progress-overlay");if(!e)return;const i=pe(t),o=ve(t,i);ge(t);const s=ye(i,o);e.style.width=s+"%"}function ze(t,n,e){const i=pe(t),o=ge(t);e&&i.findIndex(t=>be(t)===e),i.forEach(i=>{const s=be(i);if(!s)return;const r=n.querySelector(`[data-step-id='${s}']`),a=n.querySelector(`[data-step-id='${s}'] .step-circle`),l=s===e;if(r&&(r.setAttribute("aria-selected",l+""),r.setAttribute("tabindex",l?"0":"-1"),r.setAttribute("data-active",l+"")),a){const t=Ce(i,s,e,o);a.setAttribute("data-state",t)}const c=t.querySelector(`[slot='indicator-${s}']`);c&&c.setAttribute("data-active",l+"")})}function $e(t,n){pe(t).forEach(t=>{const e=be(t);if(!e)return;const i=e===n;t.setAttribute("data-active",i+""),i?(t.style.pointerEvents="auto",t.style.opacity="1"):(t.style.pointerEvents="none",t.style.opacity="0")})}function Ce(t,n,e,i){const o=t.getAttribute("status");if(o&&["completed","active","pending","error"].includes(o))return o;const s=n===e;return i.has(n)?"completed":s?"active":"pending"}function Se(t,n,e,i){e&&n.findIndex(t=>be(t)===e);const o=n.map((n,o)=>{const s=be(n);if(!s)return"";const r=n.getAttribute("label")||"Step "+(o+1),a=n.getAttribute("description")||"",l=function(t){return t.hasAttribute("disabled")}(n),c=s===e,d=function(t,n){return null!==t.querySelector(`[slot='indicator-${n}']`)}(t,s),h=Ce(n,s,e,i);let u="";return u=d?`<slot name="indicator-${s}"></slot>`:"completed"===h?'<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg>':"error"===h?'<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>':`<span style="font-size: 12px; font-weight: 700;">${o+1}</span>`,`<button\n class="step-indicator"\n role="tab"\n data-step-id="${s}"\n id="step-${s}"\n aria-selected="${c}"\n tabindex="${c?"0":"-1"}"\n data-active="${c}"\n ${l?'disabled aria-disabled="true"':""}\n >\n <div class="step-circle" data-state="${h}" part="step-circle">\n ${u}\n </div>\n <div class="step-text">\n <span class="step-label">${r}</span>\n ${a?`<span class="step-description">${a}</span>`:""}\n </div>\n </button>`}).join(""),s=ye(n,e);return`\n <div class="step-indicators-wrapper" part="indicators-wrapper">\n <div class="step-indicators" style="--ty-wizard-step-count: ${n.length}">\n <div class="progress-line" part="progress-line" role="progressbar" aria-label="Wizard progress" aria-valuenow="${Math.round(s)}" aria-valuemin="0" aria-valuemax="100">\n <div class="progress-overlay" style="width: ${s}%"></div>\n </div>\n <div class="step-tablist" role="tablist" style="display: contents;">\n ${o}\n </div>\n </div>\n </div>\n `}function Ee(t){const n=t.shadowRoot;if(!n)return;const{width:e,height:i}=ue(t),o=pe(t),r=ve(t,o),a=r?me(o,r)??0:0,l=ge(t);o.forEach(t=>{const n=be(t);n&&(t.setAttribute("role","tabpanel"),t.setAttribute("aria-labelledby","step-"+n),t.setAttribute("tabindex","0"))});const c=n.querySelector(".wizard-container"),d=n.querySelector(".step-indicators-wrapper"),h=n.querySelector(".panels-viewport");if(s(n,{css:'\n/* ============================================================================\n Theming Tokens — see file header for the override surface.\n Every default chains back to the brand layer / global scale tokens.\n ============================================================================ */\n\n:host {\n display: block;\n width: var(--ty-wizard-width, 100%); /* set by width attribute — not a public token */\n height: var(--ty-wizard-height, 700px); /* set by height attribute — not a public token */\n box-sizing: border-box;\n\n /* State accents — the primary override surface. One variable retints the\n * matching circle background, border, and glow. */\n --ty-wizard-active-accent: var(--ty-color-primary);\n --ty-wizard-completed-accent: var(--ty-color-success);\n --ty-wizard-error-accent: var(--ty-color-danger);\n --ty-wizard-pending-accent: var(--ty-color-neutral);\n\n /* Container chrome — routes through global scales. Override --ty-radius-lg\n * or --ty-shadow-md app-wide and the wizard follows; override these locally\n * to give the wizard a distinct look. */\n --ty-wizard-bg: var(--ty-surface-floating);\n --ty-wizard-border: var(--ty-border);\n --ty-wizard-radius: var(--ty-radius-lg, 12px);\n --ty-wizard-shadow: var(--ty-shadow-md, 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1));\n\n /* Header strip */\n --ty-wizard-header-bg: var(--ty-surface-content);\n --ty-wizard-header-border: var(--ty-border-soft, var(--ty-border));\n --ty-wizard-header-padding: 24px 24px 16px;\n\n /* Progress line */\n --ty-wizard-progress-track: var(--ty-border);\n --ty-wizard-progress-fill: var(--ty-wizard-completed-accent);\n --ty-wizard-progress-height: 2px;\n\n /* Motion — routes through global motion tokens if defined. */\n --ty-wizard-transition-duration: var(--ty-transition-duration, 300ms);\n --ty-wizard-transition-easing: var(--ty-transition-easing, ease-in-out);\n\n /* Circle geometry */\n --ty-wizard-circle-size: 32px;\n --ty-wizard-circle-border-width: 2px;\n\n /* Panels viewport */\n --ty-wizard-panels-bg: var(--ty-surface-elevated);\n\n /* Focus */\n --ty-wizard-focus-outline: var(--ty-wizard-active-accent);\n}\n\n.wizard-container {\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n position: relative;\n box-sizing: border-box;\n border-radius: var(--ty-wizard-radius);\n border: 1px solid var(--ty-wizard-border);\n background: var(--ty-wizard-bg);\n box-shadow: var(--ty-wizard-shadow);\n overflow: hidden;\n}\n\n/* ===================================== */\n/* Step Indicators Wrapper */\n/* ===================================== */\n\n.step-indicators-wrapper {\n display: flex;\n flex-direction: column;\n flex-shrink: 0;\n position: relative;\n padding: var(--ty-wizard-header-padding);\n border-bottom: 1px solid var(--ty-wizard-header-border);\n background: var(--ty-wizard-header-bg);\n}\n\n/* ===================================== */\n/* Progress Line (behind step circles) */\n/* ===================================== */\n\n.progress-line {\n position: absolute;\n /*\n * With equal-width indicators (flex: 1), each takes 100%/N of the width.\n * Circle centers sit at 50%/N from the left edge of each indicator.\n * Inset = 50% / step-count from each side keeps the line between circle centres.\n */\n left: calc(50% / var(--ty-wizard-step-count, 4));\n right: calc(50% / var(--ty-wizard-step-count, 4));\n top: calc(var(--ty-wizard-circle-size, 32px) / 2 - 1px);\n height: var(--ty-wizard-progress-height);\n background: var(--ty-wizard-progress-track);\n z-index: 0;\n pointer-events: none;\n transition: opacity var(--ty-wizard-transition-duration) var(--ty-wizard-transition-easing);\n}\n\n.progress-overlay {\n position: absolute;\n left: 0;\n top: 0;\n height: 100%;\n background: var(--ty-wizard-progress-fill);\n transition: width var(--ty-wizard-transition-duration) var(--ty-wizard-transition-easing);\n will-change: width;\n}\n\n/* ===================================== */\n/* Step Indicators Container */\n/* ===================================== */\n\n.step-indicators {\n display: flex;\n align-items: flex-start;\n position: relative;\n}\n\n/* ===================================== */\n/* Individual Step Indicator */\n/* ===================================== */\n\n.step-indicator {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n cursor: pointer;\n background: transparent;\n border: none;\n padding: 0;\n font: inherit;\n transition: opacity 200ms;\n flex: 1;\n min-width: 0;\n}\n\n.step-indicator[aria-disabled="true"] {\n opacity: 0.4;\n cursor: not-allowed;\n pointer-events: none;\n}\n\n.step-indicator:focus-visible {\n outline: 2px solid var(--ty-wizard-focus-outline);\n outline-offset: 4px;\n border-radius: 50%;\n}\n\n/* ===================================== */\n/* Step Circle */\n/* ===================================== */\n\n.step-circle {\n width: var(--ty-wizard-circle-size);\n height: var(--ty-wizard-circle-size);\n border-radius: 50%;\n border: var(--ty-wizard-circle-border-width) solid;\n display: flex;\n align-items: center;\n justify-content: center;\n position: relative;\n z-index: 10;\n transition: all var(--ty-wizard-transition-duration) var(--ty-wizard-transition-easing);\n box-sizing: border-box;\n flex-shrink: 0;\n}\n\n.step-circle[data-state="completed"] {\n background: var(--ty-wizard-completed-accent);\n border-color: var(--ty-color-success-strong);\n color: var(--ty-solid-success-fg, white);\n box-shadow: 0 0 0 4px color-mix(in oklab, var(--ty-wizard-completed-accent) 12%, transparent);\n}\n\n.step-circle[data-state="active"] {\n background: var(--ty-wizard-active-accent);\n border-color: var(--ty-color-primary-strong);\n color: var(--ty-solid-primary-fg, white);\n box-shadow: 0 0 0 4px color-mix(in oklab, var(--ty-wizard-active-accent) 12%, transparent);\n}\n\n.step-circle[data-state="pending"] {\n background: var(--ty-surface-elevated);\n border-color: var(--ty-border);\n color: var(--ty-color-neutral);\n}\n\n.step-circle[data-state="error"] {\n background: var(--ty-wizard-error-accent);\n border-color: var(--ty-color-danger-strong);\n color: var(--ty-solid-danger-fg, white);\n box-shadow: 0 0 0 4px color-mix(in oklab, var(--ty-wizard-error-accent) 12%, transparent);\n}\n\n/* ===================================== */\n/* Step Text Container */\n/* ===================================== */\n\n.step-text {\n display: flex;\n flex-direction: column;\n gap: 2px;\n align-items: center;\n}\n\n/* ===================================== */\n/* Step Label */\n/* ===================================== */\n\n.step-label {\n font-size: var(--ty-font-sm, 14px);\n font-weight: var(--ty-font-semibold, 600);\n color: var(--ty-color-neutral);\n transition: color 200ms;\n}\n\n.step-indicator[aria-selected="true"] .step-label {\n color: var(--ty-color-neutral-strong);\n}\n\n.step-indicator[aria-selected="false"] .step-label {\n color: var(--ty-color-neutral);\n}\n\n/* ===================================== */\n/* Step Description */\n/* ===================================== */\n\n.step-description {\n font-size: var(--ty-font-xs, 12px);\n font-weight: var(--ty-font-normal, 400);\n color: var(--ty-color-neutral);\n transition: color 200ms;\n text-align: center;\n max-width: 120px;\n}\n\n.step-indicator[aria-selected="true"] .step-description {\n color: var(--ty-color-neutral-bold);\n}\n\n/* ===================================== */\n/* Custom Indicator Content via Slots */\n/* ===================================== */\n\n::slotted([slot^="indicator-"]) {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n}\n\n/* ===================================== */\n/* Panels Viewport */\n/* ===================================== */\n\n.panels-viewport {\n position: relative;\n flex: 1;\n overflow: hidden;\n min-height: 0;\n background: var(--ty-wizard-panels-bg);\n}\n\n/* ===================================== */\n/* Panels Wrapper (slides horizontally) */\n/* ===================================== */\n\n.panels-wrapper {\n display: flex;\n height: 100%;\n transition: transform var(--ty-wizard-transition-duration) var(--ty-wizard-transition-easing);\n will-change: transform;\n}\n\n/* ===================================== */\n/* Slotted Step Panels */\n/* ===================================== */\n\n::slotted(ty-step) {\n width: var(--ty-wizard-width, 100%);\n height: 100%;\n flex-shrink: 0;\n}\n\n/* ===================================== */\n/* Accessibility & Motion Preferences */\n/* ===================================== */\n\n@media (prefers-reduced-motion: reduce) {\n .panels-wrapper {\n transition-duration: 0ms !important;\n }\n\n .progress-overlay {\n transition-duration: 0ms !important;\n }\n\n .step-circle {\n transition-duration: 0ms !important;\n }\n\n .progress-line {\n transition-duration: 0ms !important;\n }\n}\n\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border-width: 0;\n}\n',id:"ty-wizard"}),t.style.setProperty("--ty-wizard-width",e.includes("%")?"100%":e),t.style.setProperty("--ty-wizard-height",i),t.style.setProperty("--ty-wizard-active-index",a+""),t.style.setProperty("--ty-wizard-step-count",o.length+""),c&&d&&h){d.remove();const e=Se(t,o,r,l),i=document.createElement("div");i.innerHTML=e,c.insertBefore(i.firstElementChild,h),we(t,n,o),ze(t,n,r||""),requestAnimationFrame(()=>{const e=n.querySelector(".step-indicators-wrapper");e&&t.style.setProperty("--ty-wizard-indicators-height",e.offsetHeight+"px"),xe(t,a),ke(t)}),r&&$e(t,r)}else n.innerHTML=`\n <div class="wizard-container">\n ${Se(t,o,r,l)}\n <div class="panels-viewport" part="panels-container">\n <div class="panels-wrapper">\n <slot></slot>\n </div>\n </div>\n </div>\n `,requestAnimationFrame(()=>{const e=n.querySelector(".step-indicators-wrapper");e&&t.style.setProperty("--ty-wizard-indicators-height",e.offsetHeight+"px"),xe(t,a),ke(t)}),we(t,n,o),ze(t,n,r||""),function(t){const n=he.get(t);n&&n.disconnect();const{width:e}=ue(t);if(e.includes("%")){const n=new ResizeObserver(n=>{const e=n[0].contentRect.width,i=pe(t),o=ve(t,i),s=o?me(i,o):0;t.style.setProperty("--ty-wizard-width",e+"px"),void 0!==s&&xe(t,s)});n.observe(t),he.set(t,n)}}(t),r&&$e(t,r)}class TyWizard extends HTMLElement{static get observedAttributes(){return["width","height","active","completed","orientation"]}constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){Ee(this)}disconnectedCallback(){fe(this),function(t){const n=he.get(t);n&&(n.disconnect(),he.delete(t))}(this)}attributeChangedCallback(t,n,e){"active"===t?(e&&function(t,n){const e=pe(t),i=t.shadowRoot;if(!i)return;const o=ve(t,e),s=o?me(e,o):void 0,r=me(e,n);if(o===n||void 0===r)return;t.style.setProperty("--ty-wizard-active-index",r+""),xe(t,r),ze(t,i,n),ke(t),$e(t,n);const a=e[r];a?.resetScroll&&a.resetScroll(),function(t,n,e,i,o){const s=new CustomEvent("ty-wizard-step-change",{detail:{activeId:n,activeIndex:e,previousId:i,previousIndex:o,direction:null===o?"none":e>o?"forward":o>e?"backward":"none"},bubbles:!0,cancelable:!1});t.dispatchEvent(s)}(t,n,r,o,s??null)}(this,e),Ee(this)):Ee(this)}}customElements.get("ty-wizard")||customElements.define("ty-wizard",TyWizard);const Te=`\n:host {\n width: var(--ty-wizard-width, 100%);\n height: calc(var(--ty-wizard-height, 700px) - var(--ty-wizard-indicators-height, 120px));\n display: block;\n box-sizing: border-box;\n flex-shrink: 0;\n transition: opacity var(--ty-wizard-transition-duration, 400ms) var(--ty-wizard-transition-easing, ease-in-out);\n}\n\n@media (prefers-reduced-motion: reduce) {\n :host {\n transition-duration: 0ms !important;\n }\n}\n\n.step-wrapper {\n width: 100%;\n height: 100%;\n position: relative;\n overflow: hidden;\n}\n\n.step-panel {\n width: 100%;\n height: 100%;\n overflow: auto;\n box-sizing: border-box;\n}\n\n.step-panel.ty-custom-scroll {\n scrollbar-width: none;\n -ms-overflow-style: none;\n}\n\n.step-panel.ty-custom-scroll::-webkit-scrollbar {\n display: none;\n}\n\n.step-wrapper:hover .ty-scrollbar-track-y.has-overflow {\n opacity: 1;\n}\n\n${Tt}\n`;class TyStep extends HTMLElement{constructor(){super(),this.nn=null,this.attachShadow({mode:"open"})}static get observedAttributes(){return["id","label","description","disabled","status"]}connectedCallback(){this.Fn()}disconnectedCallback(){this.en()}attributeChangedCallback(t,n,e){this.Fn()}Fn(){const t=this.shadowRoot;if(!t)return;const n=this.getAttribute("id");t.querySelector(".step-wrapper")||(s(t,{css:Te,id:"ty-step"}),t.innerHTML=`\n <div class="step-wrapper"\n role="tabpanel"\n ${n?`id="panel-${n}"`:""}\n ${n?`aria-labelledby="step-${n}"`:""}\n >\n <div class="step-panel">\n <slot></slot>\n </div>\n </div>\n `,this.sn())}sn(){const t=this.shadowRoot?.querySelector(".step-panel"),n=this.shadowRoot?.querySelector(".step-wrapper");t&&n&&St()&&(t.classList.add("ty-custom-scroll"),this.nn=new Et(t,{vertical:!0}),this.nn.trackY&&n.appendChild(this.nn.trackY))}en(){this.nn&&(this.nn.trackY?.remove(),this.nn.destroy(),this.nn=null)}resetScroll(){this.nn?.scrollToTop(!1)}}customElements.get("ty-step")||customElements.define("ty-step",TyStep);const Me=(t,n)=>{const e=e=>n?`var(--ty-color-${t}${e}, var(--ty-color-${n}${e}))`:`var(--ty-color-${t}${e})`,i=e=>n?`var(--ty-bg-${t}${e}, var(--ty-bg-${n}${e}))`:`var(--ty-bg-${t}${e})`;return`\n:host([flavor="${t}"]) {\n --calendar-month-accent: ${e("")};\n --calendar-month-selected-bg: ${i("")};\n --calendar-month-selected-color: ${e("-strong")};\n --calendar-month-selected-hover-bg: ${i("-bold")};\n}\n:host([flavor="${t}+"]) {\n --calendar-month-accent: ${e("-strong")};\n --calendar-month-selected-bg: ${i("-bold")};\n --calendar-month-selected-color: ${e("-strong")};\n --calendar-month-selected-hover-bg: ${i("-bold")};\n}\n:host([flavor="${t}-"]) {\n --calendar-month-accent: ${e("-soft")};\n --calendar-month-selected-bg: ${i("-soft")};\n --calendar-month-selected-color: ${e("")};\n --calendar-month-selected-hover-bg: ${i("")};\n}\n`},Ae=`\n/* ============================================================================\n Theming Tokens\n Override these to retheme the calendar without touching the global palette.\n Defaults chain back to the global --ty-color-* / --ty-bg-* / --ty-border tokens.\n ============================================================================ */\n\n/* Theming tokens are applied as var(--ty-calendar-*, <default>) at point\n of use (not declared on :host) so consumers can override any of them\n from outside the shadow root. The 3 accent aliases — --ty-calendar-accent,\n --ty-calendar-today-accent, --ty-calendar-muted — still cascade into the\n derived defaults, so overriding one retints the related cells. */\n\n/* ============================================================================\n Base Calendar Container\n ============================================================================ */\n\n.calendar-flex-container {\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n gap: 0;\n padding: 0.75rem;\n border-radius: var(--ty-radius-md);\n font-family: system-ui, sans-serif;\n user-select: none;\n width: var(--calendar-width, fit-content);\n min-width: 280px;\n max-width: var(--calendar-max-width, none);\n}\n\n/* ============================================================================\n Rows (Header + 6 Day Rows)\n ============================================================================ */\n\n.calendar-row {\n display: flex;\n flex: 1;\n min-height: 0;\n}\n\n.calendar-header-row {\n flex: 0 0 auto;\n color: var(--ty-calendar-header-color, var(--ty-color-neutral-soft));\n}\n\n.calendar-day-row {\n flex: 1;\n min-height: 2rem;\n margin-bottom: 0.125rem;\n}\n\n/* ============================================================================\n Base Cell Styles\n ============================================================================ */\n\n.calendar-cell {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n min-width: 0;\n position: relative;\n box-sizing: border-box;\n}\n\n/* ============================================================================\n Header Cells\n ============================================================================ */\n\n.calendar-header-cell {\n text-align: center;\n font-weight: 500;\n text-transform: uppercase;\n padding: 0.25rem;\n letter-spacing: 0.05em;\n}\n\n/* ============================================================================\n Day Cells - Square with Better Visual Hierarchy\n ============================================================================ */\n\n.calendar-day-cell {\n /* Square cells */\n aspect-ratio: 1;\n\n /* Layout */\n display: flex;\n align-items: center;\n justify-content: center;\n flex-direction: column;\n\n /* Spacing */\n margin: 0.125rem;\n\n /* Visual: ghost cells — no boxes; the border is a theming hook only */\n border-radius: var(--ty-calendar-day-radius, 0.5rem);\n border: 1px solid var(--ty-calendar-day-border, transparent);\n background-color: var(--ty-calendar-day-bg, transparent);\n color: var(--ty-calendar-day-color, var(--ty-calendar-muted, var(--ty-text)));\n cursor: pointer;\n transition: background-color 0.15s ease, color 0.15s ease;\n\n /* Typography */\n font-weight: 400;\n font-variant-numeric: tabular-nums;\n}\n\n/* Hover: soft rounded pill, no border flash */\n.calendar-day-cell:hover {\n color: var(--ty-calendar-day-hover-color, var(--ty-text-strong));\n background-color: var(--ty-calendar-day-hover-bg, var(--ty-bg-neutral-soft));\n border-color: var(--ty-calendar-day-hover-border, transparent);\n}\n\n/* Keyboard focus ring (roving tabindex — see calendar-month.ts's render()).\n :focus-visible, not :focus, so mouse/pointerdown activation doesn't flash\n a ring; only Tab-in / arrow-key navigation does. */\n.calendar-day-cell:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--calendar-month-accent, var(--ty-color-primary));\n}\n\n/* ============================================================================\n Day States\n ============================================================================ */\n\n/* Today: accent number, no slab — never collides with hover, and the\n selected pill wins when today is picked */\n.calendar-day-cell.today {\n background-color: var(--ty-calendar-today-bg, transparent);\n color: var(--ty-calendar-today-color, var(--ty-calendar-today-accent, var(--calendar-month-accent, var(--ty-color-primary))));\n border-color: var(--ty-calendar-today-border, transparent);\n font-weight: 600;\n}\n\n/* Weekend: no distinction by default (hook kept for theming) */\n.calendar-day-cell.weekend {\n color: var(--ty-calendar-weekend-color, var(--ty-calendar-day-color, var(--ty-text)));\n}\n\n/* Other Month - Muted.\n Was color: var(--ty-color-neutral-faint) at opacity 0.5 — -faint alone is\n only ~2.5:1 against the content surface (already under the 4.5:1 AA text\n minimum), and blending it toward the background via opacity made it\n worse (~1.5:1 in light mode). --ty-calendar-other-month-color is its own\n token (tyrell.css :root / html.dark) calibrated to actually pass, with\n opacity dropped rather than layered on top. */\n.calendar-day-cell.other-month {\n color: var(--ty-calendar-other-month-color, #6b7280);\n}\n\n.calendar-day-cell.other-month:hover { \n color: var(--ty-calendar-day-hover-color, var(--ty-color-neutral-strong));\n background-color: var(--ty-calendar-day-hover-bg, var(--ty-bg-neutral-soft));\n opacity: 0.7;\n}\n\n/* Disabled - outside min/max bounds */\n.calendar-day-cell.disabled {\n color: var(--ty-calendar-disabled-color, var(--ty-color-neutral-faint));\n opacity: var(--ty-calendar-disabled-opacity, 0.35);\n cursor: default;\n pointer-events: none;\n}\n\n/* Selected: the one strong element in the grid */\n.calendar-day-cell.selected {\n background-color: var(--ty-calendar-selected-bg, var(--calendar-month-selected-bg, var(--ty-bg-primary)));\n color: var(--ty-calendar-selected-color, var(--calendar-month-selected-color, var(--ty-color-primary-strong)));\n border-color: var(--ty-calendar-selected-border, var(--ty-calendar-accent, var(--calendar-month-accent, transparent)));\n font-weight: 600;\n}\n\n.calendar-day-cell.selected:hover {\n background-color: var(--ty-calendar-selected-hover-bg, var(--calendar-month-selected-hover-bg, var(--ty-bg-primary-bold)));\n border-color: var(--ty-calendar-selected-hover-border, transparent);\n}\n\n.calendar-day-cell.selected.other-month {\n opacity: 0.7;\n}\n\n/* ============================================================================\n Size Variants\n ============================================================================ */\n\n/* Small - Compact (240px min-width) */\n.calendar-size-sm {\n padding: 0.5rem;\n min-width: 240px;\n}\n\n.calendar-size-sm .calendar-header-cell {\n font-size: 0.625rem;\n padding: 0.125rem;\n}\n\n.calendar-size-sm .calendar-day-cell {\n font-size: 0.75rem;\n margin: 0.0625rem;\n}\n\n.calendar-size-sm .calendar-day-row {\n min-height: 1.5rem;\n}\n\n/* Medium - Default (280px min-width) */\n.calendar-size-md {\n padding: 0.75rem;\n min-width: 280px;\n}\n\n.calendar-size-md .calendar-header-cell {\n font-size: 0.6875rem;\n padding: 0.25rem;\n}\n\n.calendar-size-md .calendar-day-cell {\n font-size: 0.8125rem;\n margin: 0.125rem;\n}\n\n.calendar-size-md .calendar-day-row {\n min-height: 2rem;\n}\n\n/* Large - Spacious (360px min-width) */\n.calendar-size-lg {\n padding: 1rem;\n min-width: 360px;\n}\n\n.calendar-size-lg .calendar-header-cell {\n font-size: 0.75rem;\n padding: 0.375rem;\n}\n\n.calendar-size-lg .calendar-day-cell {\n font-size: 0.875rem;\n margin: 0.1875rem;\n}\n\n.calendar-size-lg .calendar-day-row {\n min-height: 2.5rem;\n}\n\n/* ============================================================================\n Backwards Compatibility\n ============================================================================ */\n\n.calendar-day {\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n}\n\n/* ============================================================================\n Flavor Variants (set --calendar-month-*, consumed above)\n ============================================================================ */\n${r.map(t=>Me(t)).join("")}\n`;function Ie(t){if(!Number.isInteger(t)||1>t||t>12)throw new RangeError(`Invalid month: ${t}. Must be an integer between 1 and 12.`)}function De(t,n,e,i){const o=t.getFullYear(),s=t.getMonth()+1,r=t.getDate(),a=t.getDay(),l=o!==n||s!==e;let c=!1,d=!1;l&&(n>o||o===n&&e>s?c=!0:d=!0);const h=(p=function(){const t=new Date;return new Date(t.getFullYear(),t.getMonth(),t.getDate(),0,0,0,0)}(),(u=t).getFullYear()===p.getFullYear()&&u.getMonth()===p.getMonth()&&u.getDate()===p.getDate());var u,p;const b=i?.year===o&&i?.month===s&&i?.day===r;return{value:Date.UTC(o,s-1,r,0,0,0,0),localValue:t.getTime(),year:o,month:s,dayInMonth:r,weekend:0===a||6===a,otherMonth:l,prevMonth:c,nextMonth:d,today:h,isSelected:b,selectedYear:i?.year,selectedMonth:i?.month,selectedDay:i?.day}}function Le(t,n){const e=new Date(t);return e.setDate(e.getDate()+n),e}function Oe(t){const n=t.match(/^(\d{4})-(\d{2})-(\d{2})$/);if(!n)return null;const e=parseInt(n[1],10),i=parseInt(n[2],10),o=parseInt(n[3],10);if(1>e||e>9999)return null;if(1>i||i>12)return null;if(1>o||o>31)return null;const s=new Date(e,i-1,o);return s.getFullYear()!==e||s.getMonth()!==i-1||s.getDate()!==o?null:{year:e,month:i,day:o}}function Ne(t){return t instanceof HTMLElement}function Re(t){if(!t)return null;const n=Oe(t);return n?Date.UTC(n.year,n.month-1,n.day):null}function qe(t){if(!t||""===t)return null;const n=t+"";return/^\d+(\.\d+)?$/.test(n)?n+"px":n}class TyCalendarMonth extends HTMLElement{constructor(){super(),this.Hn="en-US",this.wn="md",this.I=null,this.Bn=null,this.jn=[];const t=new Date;this.Wn=t.getFullYear(),this._n=t.getMonth()+1,this.attachShadow({mode:"open"})}static get observedAttributes(){return["locale","size","min","max","flavor"]}connectedCallback(){this._n||(this._n=(new Date).getMonth()+1),this.Wn||(this.Wn=(new Date).getFullYear()),this.Hn||(this.Hn=this.getAttribute("locale")||"en-US");const t=this.getAttribute("size");!t||"sm"!==t&&"md"!==t&&"lg"!==t||(this.wn=t);const n=this.dayContentFn;n&&!this.Yn&&(this.Yn=n,delete this.dayContentFn);const e=this.customCSS;e&&!this.Un&&(this.Un=e,delete this.customCSS),this.nt=J(this,()=>{this.render()}),this.D(),this.render()}disconnectedCallback(){this.nt&&(this.nt(),this.nt=void 0)}attributeChangedCallback(t,n,e){"locale"===t?(this.Hn=e||"en-US",this.render()):"size"===t?"sm"!==e&&"md"!==e&&"lg"!==e||(this.wn=e,this.render()):"min"===t||"max"===t?(this["min"===t?"Gn":"Zn"]=e??void 0,this.render()):"flavor"===t&&this.D()}D(){this.I=u(this.shadowRoot,this.I,this.getAttribute("flavor"),({base:t})=>(t=>Me(t,"neutral"))(t))}get displayYear(){return this.Wn}set displayYear(t){this.Wn!==t&&(this.Wn=t,this.Bn=null,this.render())}get displayMonth(){return this._n}set displayMonth(t){this._n!==t&&(this._n=t,this.Bn=null,this.render())}get locale(){return X(this,this.getAttribute("locale"))}set locale(t){this.Hn!==t&&(this.Hn=t,this.render())}get size(){return this.wn}set size(t){this.wn!==t&&(this.wn=t,this.render())}get flavor(){return this.getAttribute("flavor")||"primary"}set flavor(t){t?this.setAttribute("flavor",t):this.removeAttribute("flavor")}get width(){return this.Kn}set width(t){this.Kn!==t&&(this.Kn=t,this.applyWidthProperties())}get minWidth(){return this.Xn}set minWidth(t){this.Xn!==t&&(this.Xn=t,this.applyWidthProperties())}get maxWidth(){return this.Jn}set maxWidth(t){this.Jn!==t&&(this.Jn=t,this.applyWidthProperties())}get dayContentFn(){return this.Yn}set dayContentFn(t){this.Yn!==t&&(this.Yn=t,this.render())}get customCSS(){return this.Un}set customCSS(t){this.Un!==t&&(this.Un=t,this.applyCustomCSS())}get min(){return this.Gn}set min(t){this.Gn!==t&&(this.Gn=t,this.render())}get max(){return this.Zn}set max(t){this.Zn!==t&&(this.Zn=t,this.render())}get value(){return this.q}set value(t){const n=t??void 0;this.q!==n&&(this.q=n,this.render())}applyWidthProperties(){const t=qe(this.Kn),n=qe(this.Xn),e=qe(this.Jn);t?this.style.setProperty("--calendar-width",t):this.style.removeProperty("--calendar-width"),n?this.style.setProperty("--calendar-min-width",n):this.style.removeProperty("--calendar-min-width"),e?this.style.setProperty("--calendar-max-width",e):this.style.removeProperty("--calendar-max-width")}applyCustomCSS(){if(!this.Un||!this.shadowRoot)return;const t=this.shadowRoot.adoptedStyleSheets;t.includes(this.Un)||(this.shadowRoot.adoptedStyleSheets=[...t,this.Un])}refresh(){this.render()}dispatchDayClick(t,n){const e={dayContext:t,value:t.value,year:t.year,month:t.month,day:t.dayInMonth,isHoliday:t.holiday,isToday:t.today,isWeekend:t.weekend,isOtherMonth:t.otherMonth};for(const i of["day-click","day-select"]){const t=new CustomEvent(i,{detail:e,bubbles:!0,cancelable:!0});this.dispatchEvent(t)}}renderDayCell(t,n,e){const i=document.createElement("div"),o=this.Yn?this.Yn(t):function(t){return""+t.dayInMonth}(t);if(this.Yn&&o&&!Ne(o)&&"string"!=typeof o)throw Error(`Custom dayContentFn must return a DOM element or string, got: ${typeof o}. Use document.createElement() to create DOM elements.`);const s=function(t){const n=["calendar-day"];return t.today&&n.push("today"),t.weekend&&n.push("weekend"),t.otherMonth&&n.push("other-month"),t.isSelected&&n.push("selected"),n}(t);return n&&s.push("disabled"),i.className=s.join(" "),"string"==typeof o?i.textContent=o:Ne(o)&&i.appendChild(o),i.setAttribute("role","gridcell"),i.setAttribute("aria-label",new Intl.DateTimeFormat(this.Hn,{weekday:"long",year:"numeric",month:"long",day:"numeric"}).format(new Date(t.localValue))),i.setAttribute("aria-selected",!!t.isSelected+""),t.today&&i.setAttribute("aria-current","date"),n?(i.setAttribute("aria-disabled","true"),i.setAttribute("tabindex","-1")):(i.setAttribute("tabindex",e?"0":"-1"),i.addEventListener("pointerdown",n=>{n.preventDefault(),this.dispatchDayClick(t,n)}),i.addEventListener("keydown",n=>{"Enter"!==n.key&&" "!==n.key||(n.preventDefault(),this.dispatchDayClick(t,n))})),i}render(){const t=this.shadowRoot;if(!t)return;let n;if(s(t,{css:Ae,id:"ty-calendar-month"}),this.applyCustomCSS(),this.applyWidthProperties(),this.q){const t=new Date(this.q);n={year:t.getFullYear(),month:t.getMonth()+1,day:t.getDate()}}const e=function(t,n,e){return function(t){if(!Number.isInteger(t)||1>t||t>9999)throw new RangeError(`Invalid year: ${t}. Must be an integer between 1 and 9999.`)}(t),Ie(n),function(t,n,e,i,o){const s=[];for(let r=0;42>r;r++){const n=Le(t,r);s.push(De(n,e,i,o))}return s}(function(t,n){const e=function(t,n){return new Date(t,n-1,1,0,0,0,0)}(t,n);return function(t){const n=t.getDay(),e=0===n?6:n-1,i=new Date(t);return i.setDate(t.getDate()-e),i.setHours(0,0,0,0),i}(e)}(t,n),0,t,n,e)}(this.Wn,this._n,n),i=function(t,n="short"){const e=new Intl.DateTimeFormat(t,{weekday:n}),i=new Date(2024,0,7),o=Array.from({length:7},(t,n)=>{const o=Le(i,n);return e.format(o)}),[s,...r]=o;return[...r,s]}(this.Hn,"short");t.innerHTML="";const o=document.createElement("div");o.className="calendar-flex-container calendar-size-"+this.wn,o.setAttribute("role","grid"),o.setAttribute("aria-label",new Intl.DateTimeFormat(this.Hn,{month:"long",year:"numeric"}).format(new Date(this.Wn,this._n-1,1)));const r=document.createElement("div");r.className="calendar-row calendar-header-row",r.setAttribute("role","row"),i.forEach(t=>{const n=document.createElement("div");n.className="calendar-cell calendar-header-cell",n.setAttribute("role","columnheader"),n.textContent=t,r.appendChild(n)}),o.appendChild(r);const a=[];for(let s=0;42>s;s+=7)a.push(e.slice(s,s+7));const l=Re(this.Gn),c=Re(this.Zn),d=t=>{const n=e[t].value;return null!==l&&l>n||null!==c&&n>c};let h=e.findIndex(t=>t.isSelected);-1===h&&(h=e.findIndex(t=>t.today)),-1===h&&(h=0),(null===this.Bn||0>this.Bn||this.Bn>41||d(this.Bn))&&(this.Bn=h),this.jn=[];let u=0;a.forEach(t=>{const n=document.createElement("div");n.className="calendar-row calendar-day-row",n.setAttribute("role","row"),t.forEach(t=>{const e=this.renderDayCell(t,null!==l&&l>t.value||null!==c&&t.value>c,u===this.Bn);e.className=e.className+" calendar-cell calendar-day-cell",n.appendChild(e),this.jn[u]=e,u++}),o.appendChild(n)}),o.addEventListener("keydown",t=>{const n=t,e="ArrowLeft"===n.key?-1:"ArrowRight"===n.key?1:"ArrowUp"===n.key?-7:"ArrowDown"===n.key?7:0;if(0===e)return;const i=this.Bn??h,o=i+e;if(0>o||o>41||d(o))return;n.preventDefault(),this.jn[i]?.setAttribute("tabindex","-1"),this.Bn=o;const s=this.jn[o];s&&(s.setAttribute("tabindex","0"),s.focus())}),t.appendChild(o)}}customElements.get("ty-calendar-month")||customElements.define("ty-calendar-month",TyCalendarMonth);const Ve='\n/* ============================================================================\n Size Variants (CSS Custom Properties)\n ============================================================================ */\n\n/* Theming tokens applied as var(--ty-calendar-nav-*, <default>) at point of\n use (NOT on :host) so consumers can override them from outside — this\n component is nested inside ty-calendar\'s shadow, so a :host default would\n block inherited overrides. --ty-calendar-accent still cascades in. */\n\n:host([data-size="md"]) {\n --nav-btn-size: 2rem;\n --nav-btn-icon-size: 1.25rem;\n --nav-font-size: 1rem;\n --nav-padding: 0.5rem 0.75rem;\n --nav-default-width: 280px;\n}\n\n:host([data-size="sm"]) {\n --nav-btn-size: 1.5rem;\n --nav-btn-icon-size: 1rem;\n --nav-font-size: 0.875rem;\n --nav-padding: 0.375rem 0.5rem;\n --nav-default-width: 240px;\n}\n\n:host([data-size="lg"]) {\n --nav-btn-size: 2.5rem;\n --nav-btn-icon-size: 1.5rem;\n --nav-font-size: 1.125rem;\n --nav-padding: 0.625rem 1rem;\n --nav-default-width: 360px;\n}\n\n/* ============================================================================\n Main Navigation Header\n ============================================================================ */\n\n.calendar-navigation-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--nav-padding);\n font-family: system-ui, sans-serif;\n user-select: none;\n width: var(--nav-width, var(--nav-default-width));\n box-sizing: border-box;\n}\n\n/* ============================================================================\n Navigation Groups (Left, Center, Right)\n ============================================================================ */\n\n.nav-group {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n}\n\n.nav-group-left,\n.nav-group-right {\n flex: 0 0 auto;\n}\n\n.nav-group-center {\n flex: 1;\n justify-content: center;\n}\n\n/* ============================================================================\n Navigation Buttons\n ============================================================================ */\n\n.nav-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--nav-btn-size);\n height: var(--nav-btn-size);\n padding: 0;\n border: none;\n border-radius: var(--ty-radius-base);\n background-color: transparent;\n color: var(--ty-calendar-nav-color, var(--ty-color-neutral));\n cursor: pointer;\n transition: all 0.15s ease;\n outline: none;\n}\n\n.nav-btn:hover {\n background-color: var(--ty-calendar-nav-hover-bg, var(--ty-bg-neutral-soft));\n color: var(--ty-calendar-nav-hover-color, var(--ty-color-neutral-strong));\n}\n\n.nav-btn:active {\n background-color: var(--ty-calendar-nav-active-bg, var(--ty-bg-neutral));\n transform: scale(0.95);\n}\n\n.nav-btn:disabled {\n opacity: 0.35;\n cursor: default;\n pointer-events: none;\n}\n\n.nav-btn:focus-visible {\n outline: 2px solid var(--ty-calendar-nav-focus-outline, var(--ty-calendar-accent, var(--ty-color-primary)));\n outline-offset: 2px;\n}\n\n/* SVG sizing */\n.nav-btn svg {\n width: var(--nav-btn-icon-size);\n height: var(--nav-btn-icon-size);\n display: block;\n}\n\n/* ============================================================================\n Month/Year Display (Center)\n ============================================================================ */\n\n.month-year-display {\n font-size: var(--nav-font-size);\n font-weight: 600;\n color: var(--ty-calendar-nav-title-color, var(--ty-color-neutral-strong));\n text-align: center;\n white-space: nowrap;\n letter-spacing: -0.01em;\n}\n',Pe=class t extends i{constructor(){super();const t=new Date;this.zn={displayMonth:t.getMonth()+1,displayYear:t.getFullYear()},s(this.shadowRoot,{css:Ve,id:"ty-calendar-navigation"})}onConnect(){this.zn.displayMonth=this.displayMonth,this.zn.displayYear=this.displayYear,this.nt=J(this,()=>{this.render()}),this.render()}onDisconnect(){this.nt&&(this.nt(),this.nt=void 0)}onPropertiesChanged(t){for(const{name:n,newValue:e}of t)switch(n){case"display-month":this.zn.displayMonth=e;break;case"display-year":this.zn.displayYear=e}}get displayMonth(){return this.getProperty("display-month")}set displayMonth(t){this.setProperty("display-month",t)}get displayYear(){return this.getProperty("display-year")}set displayYear(t){this.setProperty("display-year",t)}get locale(){return X(this,this.getProperty("locale"))}set locale(t){this.setProperty("locale",t)}get size(){return this.getProperty("size")}set size(t){this.setProperty("size",t)}get width(){return this.getProperty("width")}set width(t){this.setProperty("width",t)}get min(){return this.getProperty("min")}set min(t){this.setProperty("min",t??"")}get max(){return this.getProperty("max")}set max(t){this.setProperty("max",t??"")}emitChangeEvent(t,n){const e=new CustomEvent("change",{detail:{month:t,year:n},bubbles:!0,cancelable:!0});this.dispatchEvent(e)}static monthIndex(t,n){return 12*t+(n-1)}boundIndices(){const n=Oe(this.min),e=Oe(this.max);return{minIdx:n?t.monthIndex(n.year,n.month):null,maxIdx:e?t.monthIndex(e.year,e.month):null}}clampIndex(t){const{minIdx:n,maxIdx:e}=this.boundIndices();return null!==n&&n>t?n:null!==e&&t>e?e:t}navigateBy(n){const e=t.monthIndex(this.zn.displayYear,this.zn.displayMonth),i=this.clampIndex(e+n);i!==e&&this.emitChangeEvent(i%12+1,Math.floor(i/12))}isNavDisabled(n){const e=t.monthIndex(this.zn.displayYear,this.zn.displayMonth);return this.clampIndex(e+n)===e}createButton(t,n,e,i,o=!1){const s=document.createElement("button");return s.className=t,s.title=n,s.innerHTML=e,s.disabled=o,s.addEventListener("click",i),s}render(){const t=this.shadowRoot;if(!t)return;s(t,{css:Ve,id:"ty-calendar-navigation"}),this.setAttribute("data-size",this.size);const n=this.width;n?this.style.setProperty("--nav-width",n):this.style.removeProperty("--nav-width");const e=function(t,n="en-US",e="long"){Ie(t);const i=new Date(2024,t-1,1);return new Intl.DateTimeFormat(n,{month:e}).format(i)}(this.zn.displayMonth,this.locale,"long");t.innerHTML="";const i=document.createElement("div");i.className="calendar-navigation-header";const o=document.createElement("div");o.className="nav-group nav-group-left",o.appendChild(this.createButton("nav-btn nav-year-prev","Previous year","<?xml version='1.0' encoding='UTF-8'?>\n<svg width='24' viewBox='0 0 24 24' height='24' enable-background='new 0 0 24 24' xmlns='http://www.w3.org/2000/svg' stroke-width='0' stroke='currentColor' fill='currentColor'>\n<g>\n<rect width='24' height='24' fill='none'/>\n</g>\n<g>\n<g>\n<polygon points='17.59,18 19,16.59 14.42,12 19,7.41 17.59,6 11.59,12'/>\n<polygon points='11,18 12.41,16.59 7.83,12 12.41,7.41 11,6 5,12'/>\n</g>\n</g>\n</svg>",()=>this.navigateBy(-12),this.isNavDisabled(-12))),o.appendChild(this.createButton("nav-btn nav-month-prev","Previous month","<?xml version='1.0' encoding='UTF-8'?>\n<svg width='24' viewBox='0 0 24 24' height='24' xmlns='http://www.w3.org/2000/svg' stroke-width='0' stroke='currentColor' fill='currentColor'>\n<path fill='none' d='M0 0h24v24H0V0z'/>\n<path d='M15.41 16.59L10.83 12l4.58-4.59L14 6l-6 6 6 6 1.41-1.41z'/>\n</svg>",()=>this.navigateBy(-1),this.isNavDisabled(-1)));const r=document.createElement("div");r.className="nav-group nav-group-center";const a=document.createElement("div");a.className="month-year-display",a.textContent=`${e} ${this.zn.displayYear}`,r.appendChild(a);const l=document.createElement("div");l.className="nav-group nav-group-right",l.appendChild(this.createButton("nav-btn nav-month-next","Next month","<?xml version='1.0' encoding='UTF-8'?>\n<svg width='24' viewBox='0 0 24 24' height='24' xmlns='http://www.w3.org/2000/svg' stroke-width='0' stroke='currentColor' fill='currentColor'>\n<path fill='none' d='M0 0h24v24H0V0z'/>\n<path d='M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z'/>\n</svg>",()=>this.navigateBy(1),this.isNavDisabled(1))),l.appendChild(this.createButton("nav-btn nav-year-next","Next year","<?xml version='1.0' encoding='UTF-8'?>\n<svg width='24' viewBox='0 0 24 24' height='24' enable-background='new 0 0 24 24' xmlns='http://www.w3.org/2000/svg' stroke-width='0' stroke='currentColor' fill='currentColor'>\n<g>\n<rect width='24' height='24' fill='none'/>\n</g>\n<g>\n<g>\n<polygon points='6.41,6 5,7.41 9.58,12 5,16.59 6.41,18 12.41,12'/>\n<polygon points='13,6 11.59,7.41 16.17,12 11.59,16.59 13,18 19,12'/>\n</g>\n</g>\n</svg>",()=>this.navigateBy(12),this.isNavDisabled(12))),i.appendChild(o),i.appendChild(r),i.appendChild(l),t.appendChild(i)}};Pe.properties={"display-month":{type:"number",visual:!0,default:()=>(new Date).getMonth()+1,validate:t=>{const n=+t;return Number.isInteger(n)&&n>=1&&12>=n},coerce:t=>{const n=+t;return isNaN(n)||1>n||n>12?(new Date).getMonth()+1:n}},"display-year":{type:"number",visual:!0,default:()=>(new Date).getFullYear(),validate:t=>{const n=+t;return Number.isInteger(n)&&n>=1&&9999>=n},coerce:t=>{const n=+t;return isNaN(n)||1>n||n>9999?(new Date).getFullYear():n}},locale:{type:"string",visual:!0,default:"en-US"},size:{type:"string",visual:!0,default:"md",validate:t=>["sm","md","lg"].includes(t),coerce:t=>["sm","md","lg"].includes(t)?t:"md"},width:{type:"string",visual:!0,default:""},min:{type:"string",visual:!0,default:""},max:{type:"string",visual:!0,default:""}};let Fe=Pe;function He(t){return t&&/^\d{4}$/.test(t)?parseInt(t,10):null}function Be(t){if(!t||!/^\d{1,2}$/.test(t))return null;const n=parseInt(t,10);return 1>n||n>12?null:n}function je(t,n,e){if(!t||!/^\d{1,2}$/.test(t))return null;const i=parseInt(t,10),o=new Date(n,e,0).getDate();return 1>i||i>o?null:i}function We(t,n,e){return`${t}-${(""+n).padStart(2,"0")}-${(""+e).padStart(2,"0")}`}customElements.get("ty-calendar-navigation")||customElements.define("ty-calendar-navigation",Fe);const _e=class extends HTMLElement{constructor(){super(),this.Qn=!0,this.te=!1,this.wn="md",this.ne="primary";const t=function(){const t=new Date;return{year:t.getFullYear(),month:t.getMonth()+1,day:t.getDate()}}();this.zn={displayYear:t.year,displayMonth:t.month},this.attachShadow({mode:"open"}),"attachInternals"in this&&(this.v=this.attachInternals())}static get observedAttributes(){return["year","month","day","show-navigation","stateless","locale","name","size","width","min","max","flavor"]}connectedCallback(){this.initializeFromAttributes();const t=this.dayContentFn;t&&!this.Yn&&(this.Yn=t,delete this.dayContentFn);const n=this.customCSS;n&&!this.Un&&(this.Un=n,delete this.customCSS);const e=this.value;if(e&&"string"==typeof e&&e!==this.value){const t=e.match(/^(\d{4})-(\d{2})-(\d{2})$/);if(t){const n=parseInt(t[1],10),e=parseInt(t[2],10),i=parseInt(t[3],10);this.zn.selectedYear=n,this.zn.selectedMonth=e,this.zn.selectedDay=i,this.zn.displayYear=n,this.zn.displayMonth=e,this.te||(this.setAttribute("year",""+n),this.setAttribute("month",""+e),this.setAttribute("day",""+i))}delete this.value}this.render(),this.updateFormValue(),this.nt=J(this,()=>{this.render()})}disconnectedCallback(){this.nt&&(this.nt(),this.nt=void 0),this.ee=void 0,this.ie=void 0}attributeChangedCallback(t,n,e){if(n!==e)switch(t){case"year":case"month":case"day":this.syncStateFromAttributes(),this.syncChildComponents(),this.updateFormValue();break;case"show-navigation":this.Qn="false"!==e,this.render();break;case"stateless":this.te=null!==e&&"false"!==e;break;case"locale":this.syncChildComponents();break;case"size":"sm"!==e&&"md"!==e&&"lg"!==e||(this.wn=e,this.Kn=void 0,this.removeAttribute("width"),this.syncChildComponents());break;case"width":this.Kn=e||void 0,e&&(this.wn="md",this.removeAttribute("size")),this.syncChildComponents();break;case"name":this.updateFormValue();break;case"min":case"max":this["min"===t?"Gn":"Zn"]=e||void 0,this.syncChildComponents(),this.updateValidity();break;case"flavor":this.ne=e||"primary",this.syncChildComponents()}}get min(){return this.Gn}set min(t){t?this.setAttribute("min",t):this.removeAttribute("min")}get max(){return this.Zn}set max(t){t?this.setAttribute("max",t):this.removeAttribute("max")}get flavor(){return this.ne}set flavor(t){t?this.setAttribute("flavor",t):this.removeAttribute("flavor")}get year(){return this.zn.selectedYear}set year(t){void 0!==t?this.te?(this.zn.displayYear=t,this.setAttribute("year",""+t)):(this.zn.selectedYear=t,this.zn.displayYear=t,this.setAttribute("year",""+t)):(this.te||delete this.zn.selectedYear,this.removeAttribute("year")),this.syncChildComponents(),this.te||this.updateFormValue()}get month(){return this.zn.selectedMonth}set month(t){void 0!==t?this.te?(this.zn.displayMonth=t,this.setAttribute("month",""+t)):(this.zn.selectedMonth=t,this.zn.displayMonth=t,this.setAttribute("month",""+t)):(this.te||delete this.zn.selectedMonth,this.removeAttribute("month")),this.syncChildComponents(),this.te||this.updateFormValue()}get day(){return this.zn.selectedDay}set day(t){void 0!==t?(this.zn.selectedDay=t,this.setAttribute("day",""+t)):(delete this.zn.selectedDay,this.removeAttribute("day")),this.syncChildComponents(),this.updateFormValue()}get locale(){return X(this,this.getAttribute("locale"))}set locale(t){this.setAttribute("locale",t)}get showNavigation(){return this.Qn}set showNavigation(t){this.Qn=t,this.setAttribute("show-navigation",""+t)}get stateless(){return this.te}set stateless(t){this.te=t,t?this.setAttribute("stateless",""):this.removeAttribute("stateless")}get size(){return this.wn}set size(t){this.wn!==t&&(this.wn=t,this.Kn=void 0,this.removeAttribute("width"),this.setAttribute("size",t),this.syncChildComponents())}get width(){return this.Kn}set width(t){this.Kn!==t&&(this.Kn=t,t?(this.wn="md",this.removeAttribute("size"),this.setAttribute("width",t)):this.removeAttribute("width"),this.syncChildComponents())}get dayContentFn(){return this.Yn}set dayContentFn(t){this.Yn=t,this.syncChildComponents()}get customCSS(){return this.Un}set customCSS(t){this.Un=t,this.syncChildComponents()}get value(){const{selectedYear:t,selectedMonth:n,selectedDay:e}=this.zn;return t&&n&&e?We(t,n,e):""}set value(t){if(t){const n=t.match(/^(\d{4})-(\d{2})-(\d{2})$/);if(n){const t=parseInt(n[1],10),e=parseInt(n[2],10),i=parseInt(n[3],10);this.zn.selectedYear=t,this.zn.selectedMonth=e,this.zn.selectedDay=i,this.zn.displayYear=t,this.zn.displayMonth=e,this.te||(this.setAttribute("year",""+t),this.setAttribute("month",""+e),this.setAttribute("day",""+i))}}else delete this.zn.selectedYear,delete this.zn.selectedMonth,delete this.zn.selectedDay,this.te||(this.removeAttribute("year"),this.removeAttribute("month"),this.removeAttribute("day"));this.syncChildComponents(),this.te||this.updateFormValue()}initializeFromAttributes(){const t=this.getAttribute("year"),n=this.getAttribute("month"),e=this.getAttribute("day"),i=this.getAttribute("show-navigation"),o=this.getAttribute("stateless"),s=this.getAttribute("size"),r=this.getAttribute("width");this.Gn=this.getAttribute("min")||void 0,this.Zn=this.getAttribute("max")||void 0;const a=He(t);a&&(this.zn.displayYear=a);const l=Be(n);if(l&&(this.zn.displayMonth=l),a&&l){const t=je(e,a,l);t&&(this.zn.selectedYear=a,this.zn.selectedMonth=l,this.zn.selectedDay=t)}i&&(this.Qn="false"!==i),null!==o&&(this.te="false"!==o),!s||"sm"!==s&&"md"!==s&&"lg"!==s||(this.wn=s),r&&(this.Kn=r)}syncStateFromAttributes(){const t=this.getAttribute("year"),n=this.getAttribute("month"),e=this.getAttribute("day"),i=He(t),o=Be(n);if(i&&(this.zn.displayYear=i),o&&(this.zn.displayMonth=o),i&&o){const t=je(e,i,o);t?(this.zn.selectedYear=i,this.zn.selectedMonth=o,this.zn.selectedDay=t):(delete this.zn.selectedYear,delete this.zn.selectedMonth,delete this.zn.selectedDay)}else delete this.zn.selectedYear,delete this.zn.selectedMonth,delete this.zn.selectedDay}syncChildComponents(){if(this.ee&&(this.ee.displayMonth=this.zn.displayMonth,this.ee.displayYear=this.zn.displayYear,this.ee.locale=this.locale,this.ee.size=this.wn,this.ee.min=this.Gn??"",this.ee.max=this.Zn??"",this.ee.width=this.Kn),this.ie){this.ie.displayMonth=this.zn.displayMonth,this.ie.displayYear=this.zn.displayYear,this.ie.locale=this.locale,this.ie.size=this.wn,this.ie.min=this.Gn,this.ie.max=this.Zn,this.ie.flavor=this.ne,this.ie.width=this.Kn,this.Yn&&(this.ie.dayContentFn=this.Yn),this.Un&&(this.ie.customCSS=this.Un);const{selectedYear:t,selectedMonth:n,selectedDay:e}=this.zn;this.ie.value=t&&n&&e?new Date(t,n-1,e).getTime():null}}updateFormValue(){if(this.te)return;if(!this.v)return;const t=this.getAttribute("name"),{selectedYear:n,selectedMonth:e,selectedDay:i}=this.zn;if(t&&n&&e&&i){const t=We(n,e,i);this.v.setFormValue(t)}else this.v.setFormValue("");this.updateValidity()}updateValidity(){if(!this.v)return;const{selectedYear:t,selectedMonth:n,selectedDay:e}=this.zn;if(t&&n&&e){const i=Date.UTC(t,n-1,e),o=this.Gn?Oe(this.Gn):null,s=this.Zn?Oe(this.Zn):null;if(o&&i<Date.UTC(o.year,o.month-1,o.day))return void this.v.setValidity({rangeUnderflow:!0},`Date must be ${this.Gn} or later`);if(s&&i>Date.UTC(s.year,s.month-1,s.day))return void this.v.setValidity({rangeOverflow:!0},`Date must be ${this.Zn} or earlier`)}this.v.setValidity({})}handleNavigationChange(t){t.preventDefault(),t.stopPropagation();const{month:n,year:e}=t.detail;this.zn.displayMonth=n,this.zn.displayYear=e,this.syncChildComponents(),this.dispatchEvent(new CustomEvent("navigate",{detail:{month:n,year:e,action:"navigate",source:"navigation"},bubbles:!0,composed:!0,cancelable:!1}))}handleDayClick(t){t.preventDefault(),t.stopPropagation();const{dayContext:n,year:e,month:i,day:o}=t.detail;this.te?this.dispatchEvent(new CustomEvent("day-click",{detail:t.detail,bubbles:!0,composed:!0,cancelable:!0})):(this.zn.selectedYear=e,this.zn.selectedMonth=i,this.zn.selectedDay=o,this.zn.displayYear=e,this.zn.displayMonth=i,this.setAttribute("year",""+e),this.setAttribute("month",""+i),this.setAttribute("day",""+o),this.updateFormValue(),this.syncChildComponents(),this.dispatchEvent(new CustomEvent("change",{detail:{year:e,month:i,day:o,action:"select",source:"day-click",dayContext:n},bubbles:!0,composed:!0,cancelable:!1})))}refresh(){this.syncChildComponents(),this.ie&&"function"==typeof this.ie.refresh&&this.ie.refresh()}createNavigation(){const t=document.createElement("ty-calendar-navigation");return t.displayMonth=this.zn.displayMonth,t.displayYear=this.zn.displayYear,t.locale=this.locale,t.size=this.wn,t.min=this.Gn??"",t.max=this.Zn??"",this.Kn&&(t.width=this.Kn),t.addEventListener("change",t=>this.handleNavigationChange(t)),this.ee=t,t}createMonthDisplay(){const t=document.createElement("ty-calendar-month");t.displayMonth=this.zn.displayMonth,t.displayYear=this.zn.displayYear,t.locale=this.locale,t.size=this.wn,t.min=this.Gn,t.max=this.Zn,t.flavor=this.ne,this.Kn&&(t.width=this.Kn);const{selectedYear:n,selectedMonth:e,selectedDay:i}=this.zn;return n&&e&&i&&(t.value=new Date(n,e-1,i).getTime()),this.Yn&&(t.dayContentFn=this.Yn),this.Un&&(t.customCSS=this.Un),t.addEventListener("day-click",t=>this.handleDayClick(t)),this.ie=t,t}render(){const t=this.shadowRoot;if(!t)return;s(t,{css:"\n/* ============================================================================\n Calendar Container\n ============================================================================ */\n\n.calendar-container {\n display: flex;\n flex-direction: column;\n gap: 0.125rem;\n box-sizing: border-box;\n font-family: system-ui, sans-serif;\n}\n\n/* ============================================================================\n Responsive Adjustments\n ============================================================================ */\n\n@media (max-width: 320px) {\n .calendar-container {\n gap: 0.375rem;\n }\n}\n",id:"ty-calendar"}),t.innerHTML="";const n=document.createElement("div");if(n.className="calendar-container",this.Qn){const t=this.createNavigation();n.appendChild(t)}const e=this.createMonthDisplay();n.appendChild(e),t.appendChild(n)}};_e.formAssociated=!0;let Ye=_e;customElements.get("ty-calendar")||customElements.define("ty-calendar",Ye);const Ue=(t,n)=>{const e=e=>n?e?`var(--ty-color-${t}${e}, var(--ty-color-${t}, var(--ty-color-${n}${e})))`:`var(--ty-color-${t}, var(--ty-color-${n}))`:e?`var(--ty-color-${t}${e}, var(--ty-color-${t}))`:`var(--ty-color-${t})`;return`\n:host([flavor="${t}"]) {\n --date-picker-accent: var(--ty-input-${t}-border, ${e("-soft")});\n --date-picker-accent-bold: ${e("")};\n --date-picker-ring: color-mix(in oklab, ${e("")} 15%, transparent);\n}\n:host([flavor="${t}+"]) {\n --date-picker-accent: ${e("")};\n --date-picker-accent-bold: ${e("-strong")};\n --date-picker-ring: color-mix(in oklab, ${e("-strong")} 15%, transparent);\n}\n:host([flavor="${t}-"]) {\n --date-picker-accent: ${e("-faint")};\n --date-picker-accent-bold: ${e("-soft")};\n --date-picker-ring: color-mix(in oklab, ${e("-soft")} 15%, transparent);\n}\n`},Ge=`\n/* Date Picker Component Styles */\n:host {\n display: block;\n width: auto;\n min-width: 200px;\n font-family: var(--ty-font-sans);\n\n /* ==========================================================================\n Theming Tokens — Date Picker Stub\n Thin shim over --ty-input-*. Override these to retheme just the date-picker\n trigger without affecting other inputs.\n ========================================================================== */\n --ty-date-picker-bg: var(--ty-input-bg);\n --ty-date-picker-color: var(--ty-input-color);\n --ty-date-picker-placeholder: var(--ty-input-placeholder);\n --ty-date-picker-border: var(--ty-input-border);\n --ty-date-picker-border-hover: var(--ty-input-border-hover);\n --ty-date-picker-border-focus: var(--ty-input-border-focus);\n --ty-date-picker-shadow-focus: var(--ty-input-shadow-focus);\n --ty-date-picker-disabled-bg: var(--ty-input-disabled-bg);\n --ty-date-picker-disabled-color: var(--ty-input-disabled-color);\n --ty-date-picker-radius: var(--ty-radius-md);\n\n /* ==========================================================================\n Theming Tokens — Calendar Popup Surface\n Shared with ty-calendar / ty-calendar-month theming.\n ========================================================================== */\n --ty-calendar-surface-bg: var(--ty-surface-floating);\n --ty-calendar-surface-border: var(--ty-input-border);\n --ty-calendar-surface-shadow: var(--ty-shadow-lg, 0 4px 20px rgba(0, 0, 0, 0.08), 0 1px 3px rgba(0, 0, 0, 0.1));\n --ty-calendar-surface-radius: var(--ty-radius-lg);\n\n /* ==========================================================================\n Theming Tokens — Time Section\n ========================================================================== */\n --ty-calendar-time-bg: transparent;\n --ty-calendar-time-border: var(--ty-border-faint);\n --ty-calendar-time-label-color: var(--ty-color-neutral);\n --ty-calendar-time-input-color: var(--ty-input-color);\n --ty-calendar-time-placeholder-color: var(--ty-input-placeholder);\n --ty-calendar-time-icon-color: var(--ty-color-neutral-soft);\n}\n\n/* Container structure (reuses dropdown patterns) */\n.dropdown-container {\n display: flex;\n flex-direction: column;\n width: 100%;\n box-sizing: border-box;\n}\n\n.ty-field-label {\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n font-weight: var(--ty-font-medium);\n color: var(--ty-label-color);\n margin-bottom: 6px;\n padding-left: 12px;\n display: flex;\n align-items: center;\n}\n\n.required-icon {\n display: inline-flex;\n align-items: center;\n color: #ef4444;\n width: 12px;\n height: 12px;\n vertical-align: middle;\n margin-left: 4px;\n}\n\n.dropdown-wrapper {\n position: relative;\n display: block;\n width: 100%;\n}\n\n/* Start-slot icon (leading content inside the date-picker stub) */\n.date-picker-stub ::slotted([slot="start"]) {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n margin-right: 0.5rem;\n color: var(--ty-color-text-soft);\n}\n\n.date-picker-stub ::slotted(ty-icon[slot="start"]) {\n width: 1em;\n height: 1em;\n}\n\n/* Date picker stub (styled like dropdown) */\n.date-picker-stub {\n width: 100%;\n cursor: pointer;\n box-sizing: border-box;\n position: relative;\n display: flex;\n align-items: center;\n background: var(--ty-date-picker-bg);\n color: var(--ty-date-picker-color);\n border: 1px solid var(--date-picker-accent, var(--ty-date-picker-border));\n border-radius: var(--ty-date-picker-radius);\n font-family: var(--ty-font-sans);\n font-size: var(--ty-font-sm);\n font-weight: var(--ty-font-normal);\n line-height: var(--ty-line-height-tight);\n min-height: var(--ty-size-md);\n padding: var(--ty-spacing-2) var(--ty-spacing-3);\n padding-right: calc(var(--ty-spacing-3) + 1rem + var(--ty-spacing-2));\n transition: var(--ty-transition-all), opacity 0.2s ease;\n outline: none;\n}\n\n.date-picker-stub:hover:not([disabled]):not(.open) {\n border-color: var(--date-picker-accent-bold, var(--ty-date-picker-border-hover));\n}\n\n.date-picker-stub[disabled] {\n background-color: var(--ty-date-picker-disabled-bg);\n color: var(--ty-date-picker-disabled-color);\n cursor: not-allowed;\n opacity: 0.6;\n}\n\n.date-picker-stub:focus,\n.date-picker-stub.open {\n border-color: var(--date-picker-accent-bold, var(--ty-date-picker-border-focus));\n box-shadow: 0 0 0 3px var(--date-picker-ring, var(--ty-date-picker-shadow-focus));\n}\n\n/* Size variants */\n.date-picker-stub.sm {\n min-height: var(--ty-size-sm);\n font-size: var(--ty-font-xs);\n padding: var(--ty-spacing-1) var(--ty-spacing-2);\n padding-right: calc(var(--ty-spacing-2) + 0.875rem + var(--ty-spacing-1));\n}\n\n.date-picker-stub.lg {\n min-height: var(--ty-size-lg);\n font-size: var(--ty-font-base);\n padding: var(--ty-spacing-2) var(--ty-spacing-4);\n padding-right: calc(var(--ty-spacing-4) + 1.125rem + var(--ty-spacing-2));\n}\n\n/* Flavor variants — set --date-picker-accent*, consumed by the stub rules above */\n${r.filter(t=>"neutral"!==t).map(t=>Ue(t)).join("")}\n\n/* Text content */\n.stub-text {\n flex: 1;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n user-select: none;\n color: inherit;\n pointer-events: none;\n}\n\n.stub-text.placeholder {\n color: var(--ty-date-picker-placeholder);\n}\n\n/* Icons */\n.stub-icons {\n display: flex;\n align-items: center;\n gap: var(--ty-spacing-1);\n position: absolute;\n right: var(--ty-spacing-3);\n top: 50%;\n transform: translateY(-50%);\n height: 1rem;\n pointer-events: none;\n z-index: 2;\n}\n\n.stub-clear {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 1rem;\n height: 1rem;\n padding: 0;\n border: none;\n background: none;\n color: var(--ty-color-neutral-soft);\n cursor: pointer;\n border-radius: var(--ty-radius-sm);\n transition: all 0.15s ease;\n pointer-events: auto;\n}\n\n.stub-clear:hover {\n /* Clear is a destructive utility action, not the field's semantic flavor\n — it stays neutral at rest and always warns danger-red on hover,\n regardless of the field's own flavor. (--ty-color-negative/\n --ty-bg-negative-faint used here previously don't exist as tokens —\n this silently fell back to unstyled inherited color.) */\n color: var(--ty-color-danger);\n background-color: var(--ty-bg-danger-soft);\n}\n\n.stub-arrow {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 1rem;\n height: 1rem;\n color: var(--date-picker-accent, var(--ty-color-neutral-soft));\n}\n\n.date-picker-stub:hover .stub-arrow {\n color: var(--date-picker-accent-bold, var(--ty-color-neutral));\n}\n\n.date-picker-stub:focus .stub-arrow,\n.date-picker-stub.open .stub-arrow {\n color: var(--date-picker-accent-bold, var(--ty-date-picker-border-focus));\n}\n\n/* Calendar dialog (showModal positioning system) */\n.calendar-dialog {\n position: fixed;\n flex-direction: column;\n max-width: 90vw;\n margin: 0;\n padding: 0;\n border: none;\n background: transparent;\n box-sizing: border-box;\n padding: var(--calendar-padding, 8px);\n\n /* Hidden by default */\n opacity: 0;\n transition: opacity 200ms ease;\n\n transform: translate(var(--calendar-offset-x, 0px), var(--calendar-offset-y, 0px));\n top: -1000px;\n left: -1000px;\n}\n\n/* Direction-based positioning with CSS classes */\n.calendar-dialog.position-below {\n left: var(--calendar-x);\n top: var(--calendar-y);\n}\n\n.calendar-dialog.position-above {\n left: var(--calendar-x);\n bottom: var(--calendar-y);\n top: auto;\n flex-direction: column-reverse;\n}\n\n.calendar-dialog.open {\n opacity: 1;\n}\n\n.calendar-dialog::backdrop {\n background: transparent\n}\n\n/* Calendar content container */\n.calendar-content {\n background-color: var(--ty-calendar-surface-bg);\n border: 1px solid var(--ty-calendar-surface-border);\n border-radius: var(--ty-calendar-surface-radius);\n box-shadow: var(--ty-calendar-surface-shadow);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n align-items: center;\n}\n\n/* Native date input for mobile */\n/* Native input is invisible — used only to trigger the OS picker */\n.native-date-input {\n position: absolute;\n inset: 0;\n opacity: 0;\n width: 100%;\n height: 100%;\n margin: 0;\n padding: 0;\n border: none;\n cursor: pointer;\n z-index: 1;\n}\n\n.native-date-input::-webkit-calendar-picker-indicator {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n margin: 0;\n padding: 0;\n cursor: pointer;\n}\n\n/* Time input section */\n.time-section {\n display: flex;\n min-height: 2.5rem;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n padding: 0.5rem 1rem;\n border-top: 1px solid var(--ty-calendar-time-border);\n background-color: var(--ty-calendar-time-bg);\n width: 100%;\n box-sizing: border-box;\n position: relative;\n}\n\n.time-label {\n font-size: var(--ty-font-sm);\n font-weight: 500;\n color: var(--ty-calendar-time-label-color);\n flex-shrink: 0;\n}\n\n.time-input {\n width: 3.5rem;\n border: 1px solid var(--ty-input-border);\n border-radius: var(--ty-radius-sm);\n background: var(--ty-input-bg);\n color: var(--ty-calendar-time-input-color);\n font-family: var(--ty-font-sans);\n font-size: var(--ty-font-sm);\n font-variant-numeric: tabular-nums;\n text-align: center;\n padding: 0.25rem 0.375rem;\n outline: none;\n transition: var(--ty-transition-all);\n}\n\n.time-input:focus {\n border-color: var(--ty-input-border-focus);\n box-shadow: 0 0 0 3px var(--ty-input-shadow-focus);\n}\n\n.time-input::placeholder {\n color: var(--ty-calendar-time-placeholder-color);\n}\n\n.time-icon {\n display: flex;\n align-items: center;\n color: var(--ty-calendar-time-icon-color);\n width: 1rem;\n height: 1rem;\n flex-shrink: 0;\n}\n`,Ze="<svg stroke='currentColor' fill='none' stroke-width='2' viewBox='0 0 24 24' width='16' height='16' xmlns='http://www.w3.org/2000/svg'><rect x='3' y='4' width='18' height='18' rx='2' ry='2'></rect><line x1='16' y1='2' x2='16' y2='6'></line><line x1='8' y1='2' x2='8' y2='6'></line><line x1='3' y1='10' x2='21' y2='10'></line></svg>",Ke="<svg stroke='currentColor' fill='none' stroke-width='2' viewBox='0 0 24 24' width='14' height='14' xmlns='http://www.w3.org/2000/svg'><line x1='18' y1='6' x2='6' y2='18'></line><line x1='6' y1='6' x2='18' y2='18'></line></svg>",Xe=new WeakMap;let Je=0;function Qe(t){let n=Xe.get(t);return void 0===n&&(n=++Je,Xe.set(t,n)),n}function ti(t,n){if(!t)return null;let e=null;if("string"==typeof t)if(/^\d{4}-\d{2}-\d{2}$/.test(t)){const[n,i,o]=t.split("-");e=new Date(parseInt(n,10),parseInt(i,10)-1,parseInt(o,10),0,0,0,0)}else e=new Date(t);else"number"==typeof t&&(e=new Date(t));return!e||isNaN(e.getTime())?null:{year:e.getFullYear(),month:e.getMonth()+1,day:e.getDate(),hour:n?e.getHours():0,minute:n?e.getMinutes():0}}function ni(t){const{year:n,month:e,day:i,hour:o,minute:s}=t;return n&&e&&i?new Date(n,e-1,i,o||0,s||0,0,0):null}function ei(t){if(!t.year||!t.month||!t.day)return null;const n=ni(t);return n?n.toISOString():null}function ii(t,n){if(!t.year||!t.month||!t.day)return null;const e=(""+t.year).padStart(4,"0"),i=(""+t.month).padStart(2,"0"),o=(""+t.day).padStart(2,"0");return n?`${e}-${i}-${o}T${(""+(t.hour||0)).padStart(2,"0")}:${(""+(t.minute||0)).padStart(2,"0")}`:`${e}-${i}-${o}`}function oi(t,n){return`${(""+t).padStart(2,"0")}:${(""+n).padStart(2,"0")}`}function si(t){switch(t){case 0:return 1;case 1:return 3;case 3:return 4;case 4:case 5:return 5;default:return t}}class ri{constructor(t,n,e=0,i=0){this.element=t,this.datePickerElement=n;const o=oi(e,i);this.state={hour:e,minute:i,caretPosition:0,displayValue:o,rawDigits:(""+e).padStart(2,"0")+(""+i).padStart(2,"0")},this.element.value=o,this.setupEventListeners()}setupEventListeners(){this.element.addEventListener("keydown",t=>this.handleKeyDown(t)),this.element.addEventListener("input",t=>this.handleInput(t)),this.element.addEventListener("click",()=>this.handleClick()),this.element.addEventListener("focus",()=>this.handleFocus())}handleKeyDown(t){const n=t.key;switch(n){case"ArrowRight":this.handleArrowRight(t);break;case"ArrowLeft":this.handleArrowLeft(t);break;case"Backspace":this.handleBackspace(t);break;case"Delete":this.handleDelete(t);break;case"Home":t.preventDefault(),this.updateState({caretPosition:0});break;case"End":t.preventDefault(),this.updateState({caretPosition:5});break;case"Tab":break;default:/^\d$/.test(n)&&this.handleDigitInput(t,parseInt(n,10))}}handleInput(t){t.preventDefault()}handleClick(){this.updateState({caretPosition:0})}handleFocus(){this.updateState({caretPosition:0})}handleArrowRight(t){t.preventDefault();const n=si(this.state.caretPosition);this.updateState({caretPosition:n})}handleArrowLeft(t){t.preventDefault();const n=function(t){switch(t){case 5:return 4;case 4:return 3;case 3:return 1;case 1:case 0:return 0;default:return t}}(this.state.caretPosition);this.updateState({caretPosition:n})}handleDigitInput(t,n){t.preventDefault();const e=this.state.caretPosition;if(![0,1,3,4].includes(e))return;if(!function(t,n,e){switch(n){case 0:return 2>=t;case 1:return 2!==parseInt(e[0],10)||3>=t;case 3:return 5>=t;case 4:return!0;default:return!1}}(n,e,this.state.rawDigits))return;const i=this.replaceDigitAtPosition(e,n);if(!i)return;const o=si(e);this.updateState({...i,caretPosition:o}),this.notifyTimeChange()}handleBackspace(t){t.preventDefault();const n=this.state.caretPosition;if(0===n)return;const e=1===n?0:3===n?1:4===n?3:5===n?4:0,i=this.zeroDigitAtPosition(e);i&&(this.updateState({...i,caretPosition:e}),this.notifyTimeChange())}handleDelete(t){t.preventDefault();const n=this.state.caretPosition;if(![0,1,3,4].includes(n))return;const e=this.zeroDigitAtPosition(n);e&&(this.updateState({...e,caretPosition:n}),this.notifyTimeChange())}replaceDigitAtPosition(t,n){const e=function(t){switch(t){case 0:default:return 0;case 1:return 1;case 3:return 2;case 4:return 3}}(t),i=this.state.rawDigits.split("");i[e]=""+n;const o=i.join(""),s=function(t){if(!t||4!==t.length)return null;const n=t.substring(0,2),e=t.substring(2,4),i=parseInt(n,10),o=parseInt(e,10);return 0>i||i>23||0>o||o>59?null:{hour:i,minute:o}}(o);return s?{rawDigits:o,hour:s.hour,minute:s.minute,displayValue:oi(s.hour,s.minute)}:null}zeroDigitAtPosition(t){return this.replaceDigitAtPosition(t,0)}updateState(t){this.state={...this.state,...t},this.element.value=this.state.displayValue;const n=this.state.caretPosition,e=0===n?0:1===n?1:2===n||3===n?3:4===n?4:5===n?5:n;this.element.setSelectionRange(e,e)}notifyTimeChange(){this.datePickerElement.handleTimeInputChange(this.state.hour,this.state.minute)}getTime(){return{hour:this.state.hour,minute:this.state.minute}}setTime(t,n){const e=oi(t,n);this.state={...this.state,hour:t,minute:n,displayValue:e,rawDigits:(""+t).padStart(2,"0")+(""+n).padStart(2,"0")},this.element.value=e}}const ai=class extends i{constructor(){super(),this.zn={withTime:!1,open:!1},this.oe=0,this.I=null,s(this.shadowRoot,{css:Ge,id:"ty-date-picker"})}onConnect(){this.initializeState(),this.render(),this.nt=J(this,()=>{this.render()}),this.D()}D(){this.I=u(this.shadowRoot,this.I,"default"===this.flavor?"neutral":this.flavor,({base:t})=>(t=>Ue(t,"neutral"))(t))}onDisconnect(){this.nt&&(this.nt(),this.nt=void 0),this.cleanup()}onPropertiesChanged(t){for(const{name:n,newValue:e}of t)switch(n){case"flavor":this.D();break;case"size":case"label":case"placeholder":case"required":case"disabled":case"clearable":case"format":case"locale":break;case"value":{const t=ti(e,this.zn.withTime);if(null===t){(void 0!==this.zn.year||void 0!==this.zn.month||void 0!==this.zn.day)&&(this.zn={withTime:this.zn.withTime,open:this.zn.open});break}const n={year:this.zn.year,month:this.zn.month,day:this.zn.day,hour:this.zn.hour,minute:this.zn.minute};(t?.year!==n.year||t?.month!==n.month||t?.day!==n.day||t?.hour!==n.hour||t?.minute!==n.minute)&&(this.zn={...this.zn,...t});break}case"with-time":e!==this.zn.withTime&&(this.zn.withTime=e,void 0!==this.zn.year&&void 0!==this.zn.month&&void 0!==this.zn.day&&this.syncFormValue())}}getFormValue(){return ei(this.getComponents())}getComponents(){return{year:this.zn.year,month:this.zn.month,day:this.zn.day,hour:this.zn.hour,minute:this.zn.minute}}hasDate(){return!!(this.zn.year&&this.zn.month&&this.zn.day)}getFormattedValue(t){const n=t||this.getComponents();return n.year&&n.month&&n.day?function(t,n,e,i){if(!t.year||!t.month||!t.day)return null;const o=ni(t);if(!o)return null;const s={dateStyle:n};return i&&(s.timeStyle="short"),new Intl.DateTimeFormat(e,s).format(o)}(n,this.getProperty("format")||"long",X(this,this.getProperty("locale")),this.zn.withTime):null}initializeState(){const t=this.getProperty("value"),n=this.getProperty("with-time"),e=ti(t,n);this.zn=null===e?{withTime:n,open:!1}:{...e,withTime:n,open:!1},this.syncFormValue()}updateState(t,n=!1){this.zn={...this.zn,...t},(n||!this.zn.open||!this.zn.withTime)&&this.syncFormValue()}syncFormValue(){const t=this.getFormValue();t!==this.getProperty("value")&&this.setProperty("value",t||null)}handleTimeInputChange(t,n){if(!this.hasDate())return;const e={...this.getComponents(),hour:t,minute:n};this.updateState(e,!0),this.emitChangeEvent(e,"time-change")}emitChangeEvent(t,n){const e=t?ei(t):null,i=t?ii(t,this.zn.withTime):null,o=t?ni(t)?.getTime()??null:null,s=t?this.getFormattedValue(t):null,r=new CustomEvent("change",{detail:{value:e,localValue:i,milliseconds:o,formatted:s,source:n},bubbles:!0,cancelable:!0});this.dispatchEvent(r)}get size(){return this.getProperty("size")}set size(t){this.setProperty("size",t)}get flavor(){return this.getProperty("flavor")}set flavor(t){this.setProperty("flavor",t)}get label(){return this.getProperty("label")}set label(t){this.setProperty("label",t)}get placeholder(){return this.getProperty("placeholder")}set placeholder(t){this.setProperty("placeholder",t)}get name(){return this.getProperty("name")}set name(t){this.setProperty("name",t)}get format(){return this.getProperty("format")}set format(t){this.setProperty("format",t)}get locale(){return this.getProperty("locale")}set locale(t){this.setProperty("locale",t)}get required(){return this.getProperty("required")}set required(t){this.setProperty("required",t)}get disabled(){return this.getProperty("disabled")}set disabled(t){this.setProperty("disabled",t)}get clearable(){return this.getProperty("clearable")}set clearable(t){this.setProperty("clearable",t)}get min(){return this.getProperty("min")}set min(t){this.setProperty("min",t??"")}get max(){return this.getProperty("max")}set max(t){this.setProperty("max",t??"")}get withTime(){return this.getProperty("with-time")}set withTime(t){this.setProperty("with-time",t)}get value(){return this.getProperty("value")||null}set value(t){if(null==t||""===t)this.setProperty("value",null);else{const n=t instanceof Date?t.toISOString():t;this.setProperty("value",n)}}buildStubClasses(){const t=["date-picker-stub"],n=this.getProperty("size")||"md";return t.push(n),this.getProperty("disabled")&&t.push("disabled"),this.getProperty("required")&&t.push("required"),this.zn.open&&t.push("open"),t.join(" ")}renderStub(){const t=document.createElement("div");t.className=this.buildStubClasses();const n=this.getProperty("disabled");n&&t.setAttribute("disabled","true"),t.setAttribute("role","button"),t.setAttribute("aria-haspopup","dialog"),t.setAttribute("aria-expanded",this.zn.open+""),t.setAttribute("tabindex",n?"-1":"0"),n&&t.setAttribute("aria-disabled","true"),this.getProperty("label")&&t.setAttribute("aria-labelledby","date-picker-label-"+Qe(this)),t.addEventListener("keydown",t=>{this.zn.open||"Enter"!==t.key&&" "!==t.key||(t.preventDefault(),this.handleStubClick(t))});const e=document.createElement("slot");e.name="start";const i=document.createElement("span");i.className="stub-text";const o=this.getFormattedValue(),s=this.getProperty("placeholder")||"Select date...";i.textContent=o||s,o||i.classList.add("placeholder");const r=document.createElement("div");if(r.className="stub-icons",this.getProperty("clearable")&&o&&!n){const t=document.createElement("button");t.className="stub-clear",t.type="button",t.innerHTML=Ke,t.addEventListener("click",t=>this.handleClearClick(t)),r.appendChild(t)}const a=document.createElement("span");return a.className="stub-arrow",a.innerHTML=Ze,r.appendChild(a),t.addEventListener("click",t=>this.handleStubClick(t)),t.appendChild(e),t.appendChild(i),t.appendChild(r),t}createTimeInputElement(){const t=document.createElement("input");return t.type="text",t.className="time-input",t.placeholder="HH:mm",t.autocomplete="off",t.maxLength=5,t}renderTimeSection(){const t=document.createElement("div");t.className="time-section";const n=document.createElement("label");n.className="time-label",n.textContent="Time:";const e=this.createTimeInputElement();this.se=new ri(e,this,this.zn.hour||0,this.zn.minute||0);const i=document.createElement("span");return i.className="time-icon",i.innerHTML="<svg stroke='currentColor' fill='none' stroke-width='2' viewBox='0 0 24 24' width='16' height='16' xmlns='http://www.w3.org/2000/svg'><circle cx='12' cy='12' r='10'></circle><polyline points='12,6 12,12 16,14'></polyline></svg>",t.appendChild(n),t.appendChild(e),t.appendChild(i),t}renderCalendarDropdown(){const t=document.createElement("dialog");t.className="calendar-dialog";const n=document.createElement("div");n.className="calendar-content";const e=document.createElement("ty-calendar");this.zn.year&&this.zn.month&&this.zn.day&&(e.setAttribute("year",""+this.zn.year),e.setAttribute("month",""+this.zn.month),e.setAttribute("day",""+this.zn.day));const i=X(this,this.getProperty("locale"));i&&e.setAttribute("locale",i);const o=this.getProperty("min"),s=this.getProperty("max");o&&e.setAttribute("min",o),s&&e.setAttribute("max",s);const r=this.getProperty("flavor");return r&&"default"!==r&&e.setAttribute("flavor",r),e.addEventListener("change",t=>this.handleCalendarChange(t)),n.appendChild(e),this.zn.withTime&&n.appendChild(this.renderTimeSection()),t.appendChild(n),t.addEventListener("close",()=>{this.updateState({open:!1})}),t}renderNativeInput(){const t=document.createElement("div");t.className="dropdown-wrapper";const n=document.createElement("div");n.className=this.buildStubClasses();const e=this.getProperty("disabled");e&&n.setAttribute("disabled","true");const i=document.createElement("input");i.className="native-date-input",i.type=this.zn.withTime?"datetime-local":"date",e&&(i.disabled=!0),this.getProperty("required")&&(i.required=!0);const o=this.getProperty("min"),s=this.getProperty("max");o&&(i.min=this.zn.withTime?o+"T00:00":o),s&&(i.max=this.zn.withTime?s+"T23:59":s);const r=ii(this.getComponents(),this.zn.withTime);r&&(i.value=r);const a=this.getProperty("placeholder")||"Select date...",l=this.getFormattedValue(),c=document.createElement("span");c.className="stub-text"+(l?"":" placeholder"),c.textContent=l||a,i.addEventListener("change",()=>{if(!i.value)return void this.clearValue();const t=ti(i.value,this.zn.withTime);t&&(this.updateState(t,!0),this.emitChangeEvent(t,"selection"))});const d=document.createElement("slot");d.name="start",n.appendChild(d),n.appendChild(i),n.appendChild(c);const h=document.createElement("div");if(h.className="stub-icons",this.getProperty("clearable")&&r&&!e){const t=document.createElement("button");t.className="stub-clear",t.type="button",t.innerHTML=Ke,t.addEventListener("click",t=>this.handleClearClick(t)),h.appendChild(t)}const u=document.createElement("span");return u.className="stub-arrow",u.innerHTML=Ze,h.appendChild(u),n.appendChild(h),t.appendChild(n),t}calculateCalendarPosition(){if(!this.shadowRoot)return;if(Y())return;const t=this.shadowRoot.querySelector(".date-picker-stub"),n=this.shadowRoot.querySelector(".calendar-dialog");if(!t||!n)return;const e=t.getBoundingClientRect(),i=n.getBoundingClientRect(),o=Rt({anchorRect:e,popupWidth:i.width||320,popupHeight:i.height||400,gap:0}),s=o.below,r=s?o.topY:o.bottomY;this.style.setProperty("--calendar-x",o.x-8+"px"),this.style.setProperty("--calendar-y",r+"px"),this.style.setProperty("--calendar-offset-x","0px"),this.style.setProperty("--calendar-offset-y","0px"),s?(n.classList.add("position-below"),n.classList.remove("position-above")):(n.classList.add("position-above"),n.classList.remove("position-below"))}renderContainer(){const t=document.createElement("div");t.className="dropdown-container";const n=this.getProperty("label");if(n){const e=document.createElement("label");e.className="ty-field-label",e.id="date-picker-label-"+Qe(this),e.innerHTML=n+(this.getProperty("required")?'<span class="required-icon">*</span>':""),t.appendChild(e)}return t}render(){if(!this.shadowRoot)return;if(s(this.shadowRoot,{css:Ge,id:"ty-date-picker"}),Y()){if(this.shadowRoot.querySelector(".native-date-input"))return void this.updateDisplay();this.shadowRoot.innerHTML="";const t=this.renderContainer();return t.appendChild(this.renderNativeInput()),void this.shadowRoot.appendChild(t)}const t=this.shadowRoot.querySelector(".calendar-dialog");if(t&&t.open&&this.zn.open)return this.updateDisplay(),void this.calculateCalendarPosition();this.shadowRoot.innerHTML="";const n=this.renderContainer(),e=document.createElement("div");e.className="dropdown-wrapper",e.appendChild(this.renderStub()),e.appendChild(this.renderCalendarDropdown()),n.appendChild(e),this.shadowRoot.appendChild(n),this.setupEventListeners()}updateDisplay(){if(!this.shadowRoot)return;const t=this.getFormattedValue(),n=this.getProperty("placeholder")||"Select date...",e=this.hasDate(),i=this.getProperty("clearable"),o=this.getProperty("disabled"),s=this.shadowRoot.querySelector(".stub-text");s&&(s.textContent=t||n,s.classList.toggle("placeholder",!t));const r=this.shadowRoot.querySelector(".stub-clear");if(r&&(r.style.display=i&&e&&!o?"":"none"),Y()){const t=this.shadowRoot.querySelector(".native-date-input");if(t){const n=ii(this.getComponents(),this.zn.withTime);t.value=n||""}return}const a=this.shadowRoot.querySelector("ty-calendar");if(a&&e&&(a.setAttribute("year",""+this.zn.year),a.setAttribute("month",""+this.zn.month),a.setAttribute("day",""+this.zn.day)),a){const t=this.getProperty("flavor");t&&"default"!==t?a.setAttribute("flavor",t):a.removeAttribute("flavor")}this.se&&void 0!==this.zn.hour&&void 0!==this.zn.minute&&this.se.setTime(this.zn.hour,this.zn.minute)}setupEventListeners(){this.re&&document.removeEventListener("click",this.re),this.ae&&document.removeEventListener("keydown",this.ae),this.re=t=>this.handleOutsideClick(t),this.ae=t=>this.handleEscapeKey(t),document.addEventListener("click",this.re),document.addEventListener("keydown",this.ae);const t=this.shadowRoot?.querySelector(".calendar-dialog");t&&(this.le=t=>this.handleDialogClick(t),t.addEventListener("click",this.le))}handleStubClick(t){t.preventDefault();const n=this.shadowRoot?.querySelector(".calendar-dialog");!this.zn.open||n&&n.open||(this.updateState({open:!1},!0),ln("date-picker-"+(this.id||""+this))),!this.getProperty("disabled")&&Date.now()-this.oe>300&&this.openDropdown()}clearValue(){this.updateState({year:void 0,month:void 0,day:void 0,hour:void 0,minute:void 0},!0),this.value=null,this.emitChangeEvent(null,"clear"),this.render()}handleClearClick(t){t.preventDefault(),t.stopPropagation(),this.clearValue()}handleCalendarChange(t){t.preventDefault(),t.stopPropagation();const n=t.detail.dayContext;if(!n)return;const e={year:n.year,month:n.month,day:n.dayInMonth,hour:this.zn.hour,minute:this.zn.minute};this.updateState(e,!0),this.emitChangeEvent(e,"selection"),this.zn.withTime?requestAnimationFrame(()=>{if(!this.shadowRoot)return;const t=this.shadowRoot.querySelector(".time-input");t&&t.focus()}):this.closeDropdown()}handleDialogClick(t){if(!this.shadowRoot)return;const n=this.shadowRoot.querySelector(".calendar-dialog"),e=this.shadowRoot.querySelector(".calendar-content");t.target===n&&this.zn.open&&e&&!e.contains(t.target)&&(t.preventDefault(),t.stopPropagation(),this.closeDropdown())}handleOutsideClick(t){if(!this.shadowRoot)return;const n=t.target,e=this.shadowRoot.querySelector(".calendar-dialog");this.zn.open&&e&&!this.contains(n)&&!e.contains(n)&&this.closeDropdown()}handleEscapeKey(t){"Escape"===t.key&&this.zn.open&&(t.preventDefault(),this.closeDropdown())}openDropdown(){this.zn.open||Y()||(this.updateState({open:!0}),this.dispatchEvent(new CustomEvent("open",{bubbles:!0,composed:!0})),this.render(),requestAnimationFrame(()=>{if(!this.shadowRoot)return;const t=this.shadowRoot.querySelector(".calendar-dialog");if(t){an("date-picker-"+(this.id||""+this)),t.showModal(),this.calculateCalendarPosition(),t.classList.add("open");const n=this.shadowRoot.querySelector(".date-picker-stub");n&&n.setAttribute("aria-expanded","true");const e=this.shadowRoot.activeElement;e&&e.blur()}}))}closeDropdown(){if(!this.zn.open)return;this.oe=Date.now();const t="date-picker-"+(this.id||""+this);if(this.updateState({open:!1},!0),ln(t),this.shadowRoot){const t=this.shadowRoot.querySelector(".calendar-dialog");t&&(t.classList.remove("position-above","position-below","open"),t.close());const n=this.shadowRoot.querySelector(".date-picker-stub");n&&n.setAttribute("aria-expanded","false")}this.dispatchEvent(new CustomEvent("close",{bubbles:!0,composed:!0})),this.render()}cleanup(){if(this.re&&document.removeEventListener("click",this.re),this.ae&&document.removeEventListener("keydown",this.ae),this.le&&this.shadowRoot){const t=this.shadowRoot.querySelector(".calendar-dialog");t&&t.removeEventListener("click",this.le)}this.zn.open&&ln("date-picker-"+(this.id||""+this)),this.re=void 0,this.ae=void 0,this.le=void 0,this.se=void 0}};ai.properties={size:{type:"string",visual:!0,default:"md",validate:t=>["sm","md","lg"].includes(t),coerce:t=>"xs"===t?"sm":"xl"===t?"lg":["sm","md","lg"].includes(t)?t:"md"},flavor:{type:"string",visual:!0,default:"default"},label:{type:"string",visual:!0,default:""},placeholder:{type:"string",visual:!0,default:"Select date..."},name:{type:"string",visual:!1,default:""},min:{type:"string",visual:!0,default:""},max:{type:"string",visual:!0,default:""},required:{type:"boolean",visual:!0,default:!1},disabled:{type:"boolean",visual:!0,default:!1},clearable:{type:"boolean",visual:!0,default:!0,aliases:{"not-clearable":!1}},format:{type:"string",visual:!0,default:"long",validate:t=>["short","medium","long","full"].includes(t),coerce:t=>["short","medium","long","full"].includes(t)?t:"long"},locale:{type:"string",visual:!0,default:""},value:{type:"string",visual:!0,formValue:!0,emitChange:!1,default:null},"with-time":{type:"boolean",visual:!0,default:!1}},ai.formAssociated=!0;let li=ai;customElements.get("ty-date-picker")||customElements.define("ty-date-picker",li);const ci=new Map,di=new Map;function hi(t){return ci.get(t)}function ui(t,n){di.has(t)||di.set(t,new Set),di.get(t).add(n);const e=ci.get(t);return e&&n(e),()=>{di.get(t)?.delete(n),0===di.get(t)?.size&&di.delete(t)}}function pi(){return Object.fromEntries(ci)}class TyResizeObserver extends HTMLElement{constructor(){super(),this.St=null,this.ce=null;const t=this.attachShadow({mode:"open"});s(t,{css:"\n:host {\n /* Default to block display, user can override */\n display: block;\n /* Ensure the component can participate in layout */\n position: relative;\n}\n\n/* Slot content styling */\n::slotted(*) {\n /* No default styling - preserve natural layout */\n}\n",id:"ty-resize-observer"}),t.innerHTML="<slot></slot>"}static get observedAttributes(){return["id","debounce"]}get debounce(){return parseInt(this.getAttribute("debounce")||"0")}set debounce(t){this.setAttribute("debounce",t+"")}connectedCallback(){this.setupObserver()}disconnectedCallback(){this.cleanup()}setupObserver(){this.St=new ResizeObserver(t=>{this.debounce>0?(this.ce&&clearTimeout(this.ce),this.ce=window.setTimeout(()=>{this.handleResize(t)},this.debounce)):this.handleResize(t)}),this.St.observe(this)}handleResize(t){const{width:n,height:e}=t[0].contentRect;this.id&&function(t,n,e){ci.set(t,{width:n,height:e});const i=di.get(t);if(i){const t={width:n,height:e};i.forEach(n=>n(t))}}(this.id,n,e)}cleanup(){var t;this.St&&(this.St.disconnect(),this.St=null),this.ce&&(clearTimeout(this.ce),this.ce=null),this.id&&(ci.delete(t=this.id),di.delete(t))}}customElements.define("ty-resize-observer",TyResizeObserver);const bi=`\n:host {\n display: block;\n position: relative;\n overflow: hidden;\n}\n\n.scroll-wrapper {\n width: 100%;\n height: 100%;\n overflow-y: auto;\n overflow-x: hidden;\n}\n\n/* Allow horizontal scrolling when enabled */\n:host([overflow-x]) .scroll-wrapper {\n overflow-x: auto;\n}\n\n:host([max-height]) .scroll-wrapper {\n max-height: var(--scroll-max-height);\n}\n\n/* ===================================== */\n/* hide-scrollbar: hides native, no custom */\n/* ===================================== */\n\n:host([hide-scrollbar]) .scroll-wrapper {\n scrollbar-width: none;\n -ms-overflow-style: none;\n}\n\n:host([hide-scrollbar]) .scroll-wrapper::-webkit-scrollbar {\n display: none;\n}\n\n/* scroll-anchoring: we manage scroll position in JS, so turn off the browser's\n native scroll anchoring to avoid double-compensation. */\n:host([scroll-anchoring]) .scroll-wrapper {\n overflow-anchor: none;\n}\n\n/* ===================================== */\n/* custom-scrollbar: hides native */\n/* ===================================== */\n\n:host([custom-scrollbar]) .scroll-wrapper {\n scrollbar-width: none;\n -ms-overflow-style: none;\n}\n\n:host([custom-scrollbar]) .scroll-wrapper::-webkit-scrollbar {\n display: none;\n}\n\n/* Show scrollbar tracks on host hover */\n:host([custom-scrollbar]:hover) .ty-scrollbar-track-y.has-overflow,\n:host([custom-scrollbar]:hover) .ty-scrollbar-track-x.has-overflow {\n opacity: 1;\n}\n\n/* Corner gap when both axes are present */\n:host([custom-scrollbar][overflow-x]) .ty-scrollbar-track-y {\n bottom: var(--ty-scrollbar-width, 8px);\n}\n\n:host([custom-scrollbar]) .ty-scrollbar-track-x {\n right: var(--ty-scrollbar-width, 8px);\n}\n\n/* ===================================== */\n/* Shadow Indicators */\n/* ===================================== */\n\n.shadow-overlay {\n position: absolute;\n inset: 0;\n pointer-events: none;\n z-index: 2;\n}\n\n.shadow-top,\n.shadow-bottom,\n.shadow-left,\n.shadow-right {\n position: absolute;\n opacity: 0;\n transition: var(--ty-scroll-shadow-transition, opacity 0.2s ease-out);\n pointer-events: none;\n}\n\n.shadow-top {\n top: -40px;\n left: 0;\n right: 0;\n height: 80px;\n background: var(--ty-scroll-shadow-top, radial-gradient(\n ellipse 100% 30% at center,\n color-mix(in oklab, var(--ty-color-neutral-bold) 12%, transparent),\n transparent,\n transparent\n ));\n clip-path: inset(50% 0 0 0);\n}\n\n.shadow-bottom {\n bottom: -30px;\n left: 0;\n right: 0;\n height: 60px;\n background: var(--ty-scroll-shadow-bottom, radial-gradient(\n ellipse 100% 20% at center,\n color-mix(in oklab, var(--ty-color-neutral-bold) 18%, transparent),\n transparent,\n transparent\n ));\n clip-path: inset(0 0 50% 0);\n}\n\n.shadow-left {\n left: -30px;\n top: 0;\n bottom: 0;\n width: 60px;\n background: var(--ty-scroll-shadow-left, radial-gradient(\n ellipse 30% 100% at center,\n color-mix(in oklab, var(--ty-color-neutral-bold) 12%, transparent),\n transparent,\n transparent\n ));\n clip-path: inset(0 0 0 50%);\n}\n\n.shadow-right {\n right: -30px;\n top: 0;\n bottom: 0;\n width: 60px;\n background: var(--ty-scroll-shadow-right, radial-gradient(\n ellipse 30% 100% at center,\n color-mix(in oklab, var(--ty-color-neutral-bold) 12%, transparent),\n transparent,\n transparent\n ));\n clip-path: inset(0 50% 0 0);\n}\n\n.shadow-left,\n.shadow-right {\n display: none;\n}\n\n:host([overflow-x]) .shadow-left,\n:host([overflow-x]) .shadow-right {\n display: block;\n}\n\n.shadow-top.visible,\n.shadow-bottom.visible,\n.shadow-left.visible,\n.shadow-right.visible {\n opacity: 1;\n}\n\n:host([shadow="false"]) .shadow-overlay {\n display: none;\n}\n\n/* Touch devices - restore native scrollbar */\n@media (pointer: coarse) and (hover: none) {\n :host([custom-scrollbar]) .scroll-wrapper {\n scrollbar-width: thin;\n scrollbar-color: var(--ty-border, color-mix(in oklab, var(--ty-color-neutral-bold) 25%, transparent)) transparent;\n }\n :host([custom-scrollbar]) .scroll-wrapper::-webkit-scrollbar {\n display: block;\n width: 4px;\n height: 4px;\n }\n :host([custom-scrollbar]) .scroll-wrapper::-webkit-scrollbar-thumb {\n background: var(--ty-border, color-mix(in oklab, var(--ty-color-neutral-bold) 25%, transparent));\n border-radius: 2px;\n }\n}\n\n/* Respect reduced motion */\n@media (prefers-reduced-motion: reduce) {\n .shadow-top,\n .shadow-bottom,\n .shadow-left,\n .shadow-right {\n transition-duration: 0ms !important;\n }\n}\n\n/* Shared scrollbar styles */\n${Tt}\n`;class TyScrollContainer extends HTMLElement{constructor(){super(),this.de=null,this.he=null,this.ue=null,this.pe=null,this.be=null,this.nn=null,this.St=null,this.ge=null,this.$t=null,this.me=!1,this.ve=!1,this.It=()=>{null===this.$t&&(this.$t=requestAnimationFrame(()=>{this.$t=null,this.ye()}))},this.fe=()=>{this.nn?.update(),this.ye()};const t=this.attachShadow({mode:"open"});s(t,{css:bi,id:"ty-scroll-container"}),t.innerHTML='\n <div class="scroll-wrapper">\n <slot></slot>\n </div>\n <div class="shadow-overlay">\n <div class="shadow-top"></div>\n <div class="shadow-bottom"></div>\n <div class="shadow-left"></div>\n <div class="shadow-right"></div>\n </div>\n ',this.de=t.querySelector(".scroll-wrapper"),this.he=t.querySelector(".shadow-top"),this.ue=t.querySelector(".shadow-bottom"),this.pe=t.querySelector(".shadow-left"),this.be=t.querySelector(".shadow-right")}static get observedAttributes(){return["shadow","max-height","hide-scrollbar","custom-scrollbar","overflow-x","scroll-anchoring"]}get shadow(){return"false"!==this.getAttribute("shadow")}set shadow(t){t?this.removeAttribute("shadow"):this.setAttribute("shadow","false")}get maxHeight(){return this.getAttribute("max-height")}set maxHeight(t){t?this.setAttribute("max-height",t):this.removeAttribute("max-height"),this.we()}get hideScrollbar(){return this.hasAttribute("hide-scrollbar")}set hideScrollbar(t){t?this.setAttribute("hide-scrollbar",""):this.removeAttribute("hide-scrollbar")}get customScrollbar(){return this.hasAttribute("custom-scrollbar")}set customScrollbar(t){t?this.setAttribute("custom-scrollbar",""):this.removeAttribute("custom-scrollbar")}get overflowX(){return this.hasAttribute("overflow-x")}set overflowX(t){t?this.setAttribute("overflow-x",""):this.removeAttribute("overflow-x")}get nearEdgeThreshold(){const t=parseInt(this.getAttribute("near-edge-threshold")||"",10);return Number.isFinite(t)?t:100}set nearEdgeThreshold(t){null==t?this.removeAttribute("near-edge-threshold"):this.setAttribute("near-edge-threshold",t+"")}get scrollAnchoring(){return this.hasAttribute("scroll-anchoring")}set scrollAnchoring(t){t?this.setAttribute("scroll-anchoring",""):this.removeAttribute("scroll-anchoring")}connectedCallback(){if(this.de?.addEventListener("scroll",this.It,{passive:!0}),this.St=new ResizeObserver(()=>{this.nn?.update(),this.ye()}),this.de){this.St.observe(this.de);const t=this.de.querySelector("slot");t&&t.addEventListener("slotchange",this.fe)}this.we(),this.ye(),this.sn(),this.xe()}disconnectedCallback(){this.de?.removeEventListener("scroll",this.It),this.en(),this.ke(),this.St&&(this.St.disconnect(),this.St=null),null!==this.$t&&(cancelAnimationFrame(this.$t),this.$t=null)}attributeChangedCallback(t,n,e){n!==e&&("max-height"===t&&(this.we(),this.ye(),this.nn?.update()),"custom-scrollbar"!==t&&"overflow-x"!==t||(this.en(),this.sn(),this.ye()),"scroll-anchoring"===t&&(this.ke(),this.xe()))}xe(){!this.ge&&this.scrollAnchoring&&(this.ge=new MutationObserver(t=>{const n=this.de;if(!n)return;const e=n.getBoundingClientRect().top;let i=0;for(const o of t)o.addedNodes.forEach(t=>{if(t.nodeType!==Node.ELEMENT_NODE)return;const n=t.getBoundingClientRect();n.bottom>e?e>n.top&&(i+=e-n.top):i+=n.height});i>0&&(n.scrollTop+=i,this.nn?.update())}),this.ge.observe(this,{childList:!0}))}ke(){this.ge?.disconnect(),this.ge=null}sn(){if(this.nn)return;if(!this.de||!this.customScrollbar)return;this.nn=new Et(this.de,{vertical:!0,horizontal:this.overflowX});const t=this.shadowRoot;this.nn.trackY&&t.appendChild(this.nn.trackY),this.nn.trackX&&t.appendChild(this.nn.trackX)}en(){this.nn&&(this.nn.trackY?.remove(),this.nn.trackX?.remove(),this.nn.destroy(),this.nn=null)}we(){if(this.de){const t=this.maxHeight;t?(this.de.style.setProperty("--scroll-max-height",t),this.de.style.maxHeight=t):(this.de.style.removeProperty("--scroll-max-height"),this.de.style.maxHeight="")}}ye(){if(!this.de)return;const{scrollTop:t,scrollLeft:n,scrollHeight:e,scrollWidth:i,clientHeight:o,clientWidth:s}=this.de;this.he&&this.he.classList.toggle("visible",t>2),this.ue&&this.ue.classList.toggle("visible",e-2>t+o),this.overflowX&&(this.pe&&this.pe.classList.toggle("visible",n>2),this.be&&this.be.classList.toggle("visible",i-2>n+s));const r=e-o;if(r>0){const n=this.nearEdgeThreshold,i=r-t;this.ve=this.ze("nearend",i,n,this.ve,{distance:i,scrollTop:t,scrollHeight:e,clientHeight:o}),this.me=this.ze("nearstart",t,n,this.me,{distance:t,scrollTop:t,scrollHeight:e,clientHeight:o})}else this.me=!1,this.ve=!1}ze(t,n,e,i,o){return e>=n&&(i||this.dispatchEvent(new CustomEvent(t,{detail:o,bubbles:!0,composed:!0})),!0)}updateShadows(){this.ye(),this.nn?.update()}scrollToTop(t=!0){this.de?.scrollTo({top:0,behavior:t?"smooth":"auto"})}scrollToBottom(t=!0){this.de&&this.de.scrollTo({top:this.de.scrollHeight,behavior:t?"smooth":"auto"})}scrollToLeft(t=!0){this.de?.scrollTo({left:0,behavior:t?"smooth":"auto"})}scrollToRight(t=!0){this.de&&this.de.scrollTo({left:this.de.scrollWidth,behavior:t?"smooth":"auto"})}scrollToElement(t,n=!0){const e="string"==typeof t?this.querySelector(t):t;e?.scrollIntoView({behavior:n?"smooth":"auto",block:"nearest"})}get scrollElement(){return this.de}}customElements.define("ty-scroll-container",TyScrollContainer),"undefined"!=typeof window&&(window.tyVersion=f,window.tyIcons={register:t=>{M(t)},get:t=>A(t),has:t=>I(t),list:()=>R(),cacheInfo:()=>q(),clearCache:()=>D()},window.tyResizeObserver={getSize:t=>hi(t),onResize:(t,n)=>ui(t,n),get sizes(){return pi()}},window.tyLoader={set:t=>b(t),get:()=>g(),reset:()=>m()}),t.IconRegistry=V,t.TyButton=y,t.TyCalendar=Ye,t.TyCalendarMonth=TyCalendarMonth,t.TyCalendarNavigation=Fe,t.TyCheckbox=rt,t.TyCopy=kt,t.TyDatePicker=li,t.TyFileUpload=Ct,t.TyIcon=B,t.TyInput=et,t.TyModal=TyModal,t.TyOption=TyOption,t.TyPopup=TyPopup,t.TyRadio=bt,t.TyRadioGroup=mt,t.TyResizeObserver=TyResizeObserver,t.TyScrollContainer=TyScrollContainer,t.TySelect=_n,t.TySelectedTags=TySelectedTags,t.TyStep=TyStep,t.TySwitch=dt,t.TyTab=TyTab,t.TyTabs=TyTabs,t.TyTag=_,t.TyTextarea=It,t.TyTooltip=TyTooltip,t.TyWizard=TyWizard,t.disableScrollLockDebug=function(){window.tyScrollDebug=!1},t.enableScrollLockDebug=function(){window.tyScrollDebug=!0},t.forceUnlockAll=function(){on.activeLocks.clear(),rn()},t.getActiveLocks=function(){return new Set(on.activeLocks)},t.getAllSizes=pi,t.getLoaderSvg=g,t.getLockState=function(){return{locked:on.locked,scrollY:on.scrollY,activeLocks:Array.from(on.activeLocks)}},t.getSize=hi,t.isLocked=function(){return on.locked},t.isLockedBy=function(t){return on.activeLocks.has(t)},t.lockScroll=an,t.onResize=ui,t.resetLoaderSvg=m,t.setLoaderSvg=b,t.unlockScroll=ln,Object.defineProperty(t,Symbol.toStringTag,{value:"Module"})});
2
+ !function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((t="undefined"!=typeof globalThis?globalThis:t||self).Tyrell={})}(this,function(t){"use strict";class n{constructor(t){this.t=new Map,this.i=t,this.o()}o(){for(const[t,n]of Object.entries(this.i))void 0!==n.default&&this.t.set(t,n.default)}hasConfig(t){return t in this.i}updateProperty(t,n,e="property"){const i=this.i[t];if(!i)return null;const o=this.t.get(t),s=this.l(t,n,i);return this.h(t,s,i)?this.u(o,s)?null:(this.t.set(t,s),{name:t,oldValue:o,newValue:s,source:e}):null}l(t,n,e){if(e.coerce)return e.coerce(n);if(null==n)return e.default??null;switch(e.type){case"boolean":if("string"==typeof n){if(""===n)return!0;const t=n.toLowerCase().trim();return"false"!==t&&"0"!==t}return!!n;case"number":const t=+n;return isNaN(t)?e.default??0:t;case"string":return n+"";case"object":case"array":if("string"==typeof n)try{return JSON.parse(n)}catch{return e.default??("array"===e.type?[]:{})}return n;default:return n}}h(t,n,e){return!e.validate||e.validate(n)}u(t,n){if("object"!=typeof t||"object"!=typeof n)return t===n;if(null===t||null===n)return t===n;try{return JSON.stringify(t)===JSON.stringify(n)}catch{return!1}}get(t){return this.t.get(t)}getAll(){return Object.fromEntries(this.t)}getConfig(t){return this.i[t]}isVisual(t){return this.i[t]?.visual??!1}isFormValue(t){return this.i[t]?.formValue??!1}shouldEmitChange(t){return this.i[t]?.emitChange??!1}handleAlias(t,n){for(const[e,i]of Object.entries(this.i))if(i.aliases&&t in i.aliases)return this.updateProperty(e,i.aliases[t],"attribute");return null}}const e=class extends HTMLElement{constructor(){super(),this.p=!1,this.m=!1,this.props=new n(this.constructor.properties),this.v=this.attachInternals(),this.shadowRoot||this.attachShadow({mode:"open"})}static get observedAttributes(){const t=[];for(const[n,e]of Object.entries(this.properties))if(t.push(n.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase()),e.aliases)for(const i of Object.keys(e.aliases))t.push(i);return t}setProperty(t,n){const e=this.props.updateProperty(t,n,"property");e&&(this.k(e),this.$([e]))}getProperty(t){return this.props.get(t)}k(t){const{name:n,newValue:e}=t,i=this.props.getConfig(n);if(!i)return;const o=this.C(n);"boolean"===i.type?e?this.setAttribute(o,""):this.removeAttribute(o):null==e?this.removeAttribute(o):this.setAttribute(o,"object"==typeof e?JSON.stringify(e):e+"")}C(t){return t.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase()}S(t){return t.replace(/-([a-z])/g,(t,n)=>n.toUpperCase())}attributeChangedCallback(t,n,e){if(n===e)return;let i=this.props.handleAlias(t,e);if(!i){const n=this.S(t),o=this.props.hasConfig(t)?t:n;i=this.props.updateProperty(o,e,"attribute")}i&&this.$([i])}connectedCallback(){this.p=!0;const t=this.T();t.length>0&&this.$(t),this.onConnect(),this.m||(this.render(),this.m=!0)}disconnectedCallback(){this.p=!1,this.onDisconnect()}T(){const t=[],n=this.constructor;for(const e of Object.keys(n.properties)){const n=Object.getOwnPropertyDescriptor(this,e);if(n&&void 0!==n.value){const i=this.props.updateProperty(e,n.value,"property");i&&t.push(i)}}return t}$(t){0!==t.length&&(this.onPropertiesChanged(t),t.some(t=>this.props.isFormValue(t.name))&&this.updateFormValue(),t.some(t=>this.props.isVisual(t.name))&&this.p&&this.render(),this.M(t))}M(t){for(const n of t)this.props.shouldEmitChange(n.name)&&this.dispatchEvent(new CustomEvent("prop:change",{detail:{property:n.name,oldValue:n.oldValue,newValue:n.newValue},bubbles:!0,composed:!0}))}updateFormValue(){const t=this.getFormValue();this.v.setFormValue(t)}getFormValue(){return this.props.get("value")??null}onPropertiesChanged(t){}onConnect(){}onDisconnect(){}get form(){return this.v.form}applyLabelName(t){let n=Array.from(this.v.labels??[]).map(t=>t.textContent?.trim()).filter(Boolean).join(" ");if(!n){const t=this.closest("label");if(t){const e=t.cloneNode(!0);e.querySelectorAll(this.tagName.toLowerCase()).forEach(t=>t.remove()),n=e.textContent?.trim()??""}}n?t.setAttribute("aria-label",n):t.removeAttribute("aria-label")}formResetCallback(){const t=this.constructor.properties.value;t&&this.setProperty("value",t.default??""),this.onFormReset()}onFormReset(){}};e.formAssociated=!0,e.properties={};let i=e;const o=new Map;function s(t,n){const{css:e,id:i}=n;let s;i&&o.has(i)?s=o.get(i):(s=new CSSStyleSheet,s.replaceSync(e),i&&o.set(i,s));const r=t.adoptedStyleSheets||[];r.includes(s)||(t.adoptedStyleSheets=[...r,s])}const r=["primary","secondary","success","danger","warning","neutral"],a=(t,n,e,i)=>i?`var(${t}-${n}${e}, var(${t}-${i}${e}))`:`var(${t}-${n}${e})`,l=(t,n)=>{const e=e=>a("--ty-solid",t,e,n);return`\nbutton.solid.${t} { --_ring: ${a("--ty-color",t,"",n)}; background: var(--ty-button-bg, ${e("")}); color: var(--ty-button-color, ${e("-fg")}); }\nbutton.solid.${t}.tone-plus { background: var(--ty-button-bg, ${e("-strong")}); }\nbutton.solid.${t}.tone-minus { background: var(--ty-button-bg, ${e("-soft")}); }\nbutton.solid.${t}:hover:not(:disabled) { background: var(--ty-button-bg-hover, ${e("-hover")}); }\nbutton.solid.${t}:active:not(:disabled) { background: ${e("-active")}; }\n`},c=(t,n)=>{const e=e=>a("--ty-color",t,e,n);return`\nbutton.outlined.${t} {\n color: var(--ty-button-color, ${e("")});\n border-color: var(--ty-button-border, ${e("")});\n}\nbutton.outlined.${t}.tone-plus {\n color: var(--ty-button-color, ${e("-strong")});\n border-color: var(--ty-button-border, ${e("-strong")});\n}\nbutton.outlined.${t}.tone-minus {\n color: var(--ty-button-color, ${e("-soft")});\n border-color: var(--ty-button-border, ${e("-soft")});\n}\nbutton.outlined.${t}:hover:not(:disabled) {\n background: var(--ty-button-bg-hover, ${a("--ty-bg",t,"-soft",n)});\n}\n`},d=(t,n)=>{const e=e=>a("--ty-color",t,e,n);return`\nbutton.ghost.${t} { color: var(--ty-button-color, ${e("")}); }\nbutton.ghost.${t}.tone-plus { color: var(--ty-button-color, ${e("-strong")}); }\nbutton.ghost.${t}.tone-minus { color: var(--ty-button-color, ${e("-soft")}); }\nbutton.ghost.${t}:hover:not(:disabled) {\n background: var(--ty-button-bg-hover, ${a("--ty-bg",t,"-soft",n)});\n}\n`},h=`\n:host {\n display: inline-block;\n font-family: var(--ty-font-sans);\n}\n\n:host([wide]) {\n display: flex;\n flex-grow: 1;\n}\n\nbutton {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--ty-spacing-1);\n font-size: var(--ty-font-xs);\n line-height: var(--ty-leading-xs);\n letter-spacing: var(--ty-tracking-xs);\n font-weight: var(--ty-font-semibold);\n white-space: nowrap;\n cursor: pointer;\n user-select: none;\n transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;\n background: transparent;\n color: var(--ty-color-neutral);\n border: 1px solid transparent;\n}\n\nbutton:not(.action) {\n min-width: 4rem;\n}\n\nbutton:not(.pill) {\n border-radius: var(--ty-radius-md);\n}\n\nbutton.xs:not(.pill) { border-radius: var(--ty-button-radius-xs, var(--ty-radius-md)); }\nbutton.sm:not(.pill) { border-radius: var(--ty-button-radius-sm, var(--ty-radius-md)); }\nbutton.md:not(.pill) { border-radius: var(--ty-button-radius-md, var(--ty-radius-md)); }\nbutton.lg:not(.pill) { border-radius: var(--ty-button-radius-lg, var(--ty-radius-md)); }\nbutton.xl:not(.pill) { border-radius: var(--ty-button-radius-xl, var(--ty-radius-md)); }\n\nbutton:focus-visible {\n outline: none;\n}\n\nbutton:disabled {\n cursor: not-allowed;\n opacity: 0.6;\n}\n\n/* ===== LOADING STATE =====\n Spinner overlays the button center; original content kept in flow but\n hidden via visibility so width/height are preserved (no layout shift).\n*/\n.loader-icon {\n display: none;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: 1em;\n height: 1em;\n color: currentColor;\n}\n.loader-icon svg {\n width: 100%;\n height: 100%;\n}\nbutton.loading {\n cursor: wait;\n}\nbutton.loading > *:not(.loader-icon) {\n visibility: hidden;\n}\nbutton.loading > .loader-icon {\n display: inline-flex;\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n animation: ty-button-spin 0.7s linear infinite;\n}\n@keyframes ty-button-spin {\n to { transform: translate(-50%, -50%) rotate(360deg); }\n}\n@media (prefers-reduced-motion: reduce) {\n button.loading > .loader-icon {\n animation-duration: 1.6s;\n }\n}\n\n::slotted(*) {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n::slotted(ty-icon) {\n flex-shrink: 0;\n}\n\n:host([wide]) button {\n flex-grow: 1;\n}\n\n/* ===== SIZES =====\n Buttons run a 4px ladder (24-40px). Shared scale with fields\n (--ty-size-sm/md/lg — see tyrell.css): field sm = button md (32px),\n field md = button lg (36px), field lg = button xl (40px) — a button\n and a field of the paired size sit flush, same height, in a row. */\n\nbutton.xs {\n padding: 0 var(--ty-spacing-2);\n font-size: var(--ty-font-xs);\n line-height: var(--ty-leading-xs);\n letter-spacing: var(--ty-tracking-xs);\n gap: var(--ty-spacing-1);\n height: 1.5rem; /* 24px */\n}\n\nbutton.sm {\n padding: 0 var(--ty-spacing-2);\n font-size: var(--ty-font-xs);\n line-height: var(--ty-leading-xs);\n letter-spacing: var(--ty-tracking-xs);\n gap: var(--ty-spacing-1);\n height: 1.75rem; /* 28px */\n}\n\nbutton.md {\n padding: 0.375rem var(--ty-spacing-3);\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n gap: var(--ty-spacing-2);\n height: 2rem; /* 32px — matches field sm */\n}\n\nbutton.lg {\n padding: 0.375rem var(--ty-spacing-4);\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n gap: var(--ty-spacing-2);\n height: 2.25rem; /* 36px — matches field md */\n}\n\nbutton.xl {\n padding: var(--ty-spacing-2) var(--ty-spacing-6);\n font-size: var(--ty-font-base);\n line-height: var(--ty-leading-base);\n letter-spacing: var(--ty-tracking-base);\n gap: var(--ty-spacing-2);\n height: 2.5rem; /* 40px — matches field lg */\n}\n\n/* ===== ACTION (icon-only square) ===== */\n\nbutton.action {\n gap: 0px !important;\n height: 2rem;\n width: 2rem;\n padding: 0px !important;\n}\n\nbutton.action ::slotted(ty-icon) {\n height: 1rem;\n width: 1rem;\n}\n\nbutton.action.xs { height: 1.375rem; width: 1.375rem; }\nbutton.action.xs ::slotted(ty-icon) { height: 0.75rem; width: 0.75rem; }\n\nbutton.action.sm { height: 1.5rem; width: 1.5rem; }\nbutton.action.sm ::slotted(ty-icon) { height: 0.875rem; width: 0.875rem; }\n\nbutton.action.lg { height: 2.25rem; width: 2.25rem; }\nbutton.action.lg ::slotted(ty-icon) { height: 1.125rem; width: 1.125rem; }\n\nbutton.action.xl { height: 2.5rem; width: 2.5rem; }\nbutton.action.xl ::slotted(ty-icon) { height: 1.25rem; width: 1.25rem; }\n\n/* ===== PILL ===== */\n\nbutton.pill {\n border-radius: 9999px;\n padding-left: 1.25em;\n padding-right: 1.25em;\n}\n\nbutton.pill.xs { padding-left: 1em; padding-right: 1em; }\nbutton.pill.sm { padding-left: 1.125em; padding-right: 1.125em; }\nbutton.pill.lg { padding-left: 1.5em; padding-right: 1.5em; }\nbutton.pill.xl { padding-left: 1.75em; padding-right: 1.75em; }\n\nbutton.pill:has(ty-icon:only-child),\nbutton.pill:has(slot[name="start"]:only-child),\nbutton.pill:has(slot[name="end"]:only-child) {\n padding: 0;\n aspect-ratio: 1;\n min-width: var(--ty-size-md);\n}\n\nbutton.pill.xs:has(ty-icon:only-child) { min-width: 1.375rem; min-height: 1.375rem; }\nbutton.pill.sm:has(ty-icon:only-child) { min-width: 1.5rem; min-height: 1.5rem; }\nbutton.pill.md:has(ty-icon:only-child) { min-width: 2rem; min-height: 2rem; }\nbutton.pill.lg:has(ty-icon:only-child) { min-width: 2.25rem; min-height: 2.25rem; }\nbutton.pill.xl:has(ty-icon:only-child) { min-width: 2.5rem; min-height: 2.5rem; }\n\n/* ============================================================\n SOLID — flat: one variable per segment. No color math here; all the\n --ty-solid-{flavor}-{hover,active,strong,soft} tokens are DERIVED in\n tyrell-brand.css (OKLCH) or set literally in tyrell.css. Override any\n single token to recolor that one segment. Bare .solid = custom-flavor\n fallback, themable via --ty-button-{bg,bg-hover,color}.\n ============================================================ */\n\nbutton.solid {\n border: none;\n --_ring: var(--ty-color-neutral);\n background: var(--ty-button-bg, var(--ty-solid-neutral));\n color: var(--ty-button-color, var(--ty-solid-neutral-fg));\n}\nbutton.solid.tone-plus { background: var(--ty-button-bg, var(--ty-solid-neutral-strong)); }\nbutton.solid.tone-minus { background: var(--ty-button-bg, var(--ty-solid-neutral-soft)); }\nbutton.solid:hover:not(:disabled) { background: var(--ty-button-bg-hover, var(--ty-solid-neutral-hover)); }\nbutton.solid:active:not(:disabled) { background: var(--ty-solid-neutral-active); }\n\n${r.map(t=>l(t)).join("")}\nbutton.solid:focus-visible {\n box-shadow: 0 0 0 2px var(--ty-focus-ring-gap), 0 0 0 4px var(--_ring);\n}\n\n/* ============================================================\n OUTLINED — transparent bg, text === border (uses --ty-color-*)\n Bare .outlined rule = fallback for custom flavors. For outlined,\n text is bound to border color (the rule "text === border"), so the\n fallback chain prefers --ty-button-border, then --ty-button-color.\n ============================================================ */\n\nbutton.outlined {\n background: transparent;\n color: var(--ty-button-border, var(--ty-button-color, var(--ty-color-neutral)));\n border-color: var(--ty-button-border, var(--ty-button-color, var(--ty-color-neutral)));\n}\nbutton.outlined:hover:not(:disabled) {\n background: var(--ty-button-bg-hover, var(--ty-bg-neutral-soft));\n}\n\n${r.map(t=>c(t)).join("")}\n\n/* ============================================================\n GHOST — text only, hover bg (uses --ty-color-* + --ty-bg-*-soft)\n Bare .ghost rule = fallback for custom flavors.\n ============================================================ */\n\nbutton.ghost {\n background: transparent;\n border: none;\n color: var(--ty-button-color, var(--ty-color-neutral));\n}\nbutton.ghost:hover:not(:disabled) {\n background: var(--ty-button-bg-hover, var(--ty-bg-neutral-soft));\n}\n\n${r.map(t=>d(t)).join("")}`;function u(t,n,e,i){const o=(e||"")+"",s=o.replace(/[+-]$/,"");return r.includes(s)||!/^[A-Za-z][A-Za-z0-9_-]*$/.test(s)?(n&&(t.adoptedStyleSheets=t.adoptedStyleSheets.filter(t=>t!==n)),null):(n||(n=new CSSStyleSheet,t.adoptedStyleSheets=[...t.adoptedStyleSheets,n]),n.replaceSync(i({flavor:o,base:s,shade:o.slice(s.length)})),n)}let p=null;function b(t){p=t&&t.trim()?t:null}function g(){return p??'<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="3" stroke-opacity="0.25"/><path d="M22 12a10 10 0 0 1-10 10" stroke="currentColor" stroke-width="3" stroke-linecap="round"/></svg>'}function m(){p=null}const v=class extends i{constructor(){super(),this.A=!1,this.I=null,s(this.shadowRoot,{css:h,id:"ty-button"})}onConnect(){this.D()}onDisconnect(){}onPropertiesChanged(t){t.some(t=>"flavor"===t.name)&&this.D()}D(){const{base:t}=this.parseFlavor();this.I=u(this.shadowRoot,this.I,t,()=>(t=>l(t,"neutral")+c(t,"neutral")+d(t,"neutral"))(t))}get flavor(){return this.getProperty("flavor")}set flavor(t){this.setProperty("flavor",t)}get size(){return this.getProperty("size")}set size(t){this.setProperty("size",t)}get appearance(){return this.getProperty("appearance")}set appearance(t){this.setProperty("appearance",t)}get disabled(){return this.getProperty("disabled")}set disabled(t){this.setProperty("disabled",t)}get loading(){return this.getProperty("loading")}set loading(t){this.setProperty("loading",t)}get type(){return this.getProperty("type")}set type(t){this.setProperty("type",t)}get pill(){return this.getProperty("pill")}set pill(t){this.setProperty("pill",t)}get action(){return this.getProperty("action")}set action(t){this.setProperty("action",t)}get wide(){return this.getProperty("wide")}set wide(t){this.setProperty("wide",t)}get name(){return this.getProperty("name")}set name(t){this.setProperty("name",t)}get value(){return this.getProperty("value")}set value(t){this.setProperty("value",t)}parseFlavor(){const t=this.flavor||"";return t.length>1&&t.endsWith("+")?{base:t.slice(0,-1),tone:"+"}:t.length>1&&t.endsWith("-")?{base:t.slice(0,-1),tone:"-"}:{base:t,tone:""}}buildClasses(){const{base:t,tone:n}=this.parseFlavor();return function(...t){return t.filter(Boolean).join(" ")}(t,this.size,this.appearance,this.pill&&"pill",this.action&&"action","+"===n&&"tone-plus","-"===n&&"tone-minus")}handleFormAction(){const t=this.v.form;if(t)switch(this.type){case"submit":this.name&&this.value&&this.v.setFormValue(this.value),t.requestSubmit();break;case"reset":t.reset()}}initializeButtonStructure(){const t=this.shadowRoot,n=this.buildClasses(),e=document.createElement("button");e.disabled=this.disabled,e.className=n;const i=document.createElement("span");i.className="loader-icon",i.setAttribute("aria-hidden","true"),i.innerHTML=g();const o=document.createElement("slot");o.name="start",o.className="start";const s=document.createElement("slot"),r=document.createElement("slot");r.name="end",r.className="end",e.appendChild(i),e.appendChild(o),e.appendChild(s),e.appendChild(r),e.addEventListener("click",t=>{this.disabled||this.loading||(t.stopPropagation(),this.handleFormAction(),this.dispatchEvent(new CustomEvent("click",{bubbles:!0,composed:!0,detail:{originalEvent:t}})))}),this.applyLoadingState(e),t.appendChild(e),this.A=!0}applyLoadingState(t){const n=this.loading;if(t.classList.toggle("loading",n),n){t.setAttribute("aria-busy","true");const n=t.querySelector(".loader-icon");n&&(n.innerHTML=g())}else t.removeAttribute("aria-busy")}render(){const t=this.shadowRoot;if(!this.A)return void this.initializeButtonStructure();const n=this.buildClasses(),e=t.querySelector("button");e&&(e.disabled=this.disabled,e.className=n,this.applyLoadingState(e))}};v.formAssociated=!0,v.properties={flavor:{type:"string",visual:!0,default:"neutral"},size:{type:"string",visual:!0,default:"md",validate:t=>["xs","sm","md","lg","xl"].includes(t),coerce:t=>["xs","sm","md","lg","xl"].includes(t)?t:"md"},appearance:{type:"string",visual:!0,default:"solid",validate:t=>["solid","outlined","ghost"].includes(t),coerce:t=>["solid","outlined","ghost"].includes(t)?t:"solid"},disabled:{type:"boolean",visual:!0,default:!1},loading:{type:"boolean",visual:!0,default:!1},type:{type:"string",visual:!1,default:"submit"},pill:{type:"boolean",visual:!0,default:!1},action:{type:"boolean",visual:!0,default:!1},wide:{type:"boolean",visual:!1,default:!1},name:{type:"string",default:""},value:{type:"string",default:""}};let f=v;customElements.get("ty-button")||customElements.define("ty-button",f);const y="1.0.0-TC34",w=new Map,x=new Map,k=new Map;let z=null,$=null;const C="ty-icons-v"+y,S="https://ty-icons.local/",E=new Map;let T=!1;function M(t){const n=new Set;Object.entries(t).forEach(([t,e])=>{w.set(t,e),n.add(t)}),n.size>0&&N(n)}function A(t){return w.get(t)}function I(t){return w.has(t)}async function D(){const t=new Set(w.keys());if(w.clear(),"caches"in window)try{await caches.delete(C),T=!1}catch(n){}N(t)}function L(t,n,e){x.set(t,e),n&&k.set(t,n)}function O(t){x.delete(t),k.delete(t)}function N(t){z||(z=new Set),t.forEach(t=>z.add(t)),null!==$&&clearTimeout($);const n="undefined"!=typeof requestIdleCallback?requestIdleCallback:t=>setTimeout(t,0);$=n(()=>{const t=z;z=null,$=null,t&&t.size>0&&function(t){x.forEach((n,e)=>{const i=k.get(e);i?t.has(i)&&n(new Set([i])):n(t)})}(t)})}function R(){return Array.from(w.keys())}async function q(){const t={version:y,cacheName:C,available:"caches"in window};if(!t.available)return t;try{const n=await caches.open(C),e=(await n.keys()).filter(t=>t.url.startsWith(S));return{...t,iconCount:e.length}}catch(n){return t}}const V=Object.freeze(Object.defineProperty({__proto__:null,addWatcher:L,clearIcons:D,getCacheInfo:q,getCachedIcon:async function(t){const n=E.get(t);if(n)return n;const e=(async()=>{try{await async function(){if(!T&&"caches"in window){T=!0;try{const t=(await caches.keys()).filter(t=>t.startsWith("ty-icons-v")&&t!==C);await Promise.all(t.map(t=>caches.delete(t)))}catch(t){}}}();const n=await caches.open(C),e=await n.match(`${S}${t}`);if(e)return await e.text()}catch(n){}return null})();return E.set(t,e),e.finally(()=>{E.delete(t)}),e},getIcon:A,getIconNames:R,hasIcon:I,registerIcons:M,removeWatcher:O},Symbol.toStringTag,{value:"Module"}));let F=0;const P='<svg xmlns="http://www.w3.org/2000/svg"\n viewBox="0 0 512 512"\n fill="currentColor"\n opacity="0.2">\n <path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z"/>\n</svg>',H=class extends i{constructor(){super(),this.L=null,this.O="",this.N=null,s(this.shadowRoot,{css:"\n:host {\n /* Display & Layout - CRITICAL: No containment to prevent paint deferral */\n display: flex;\n align-items: center;\n justify-content: center;\n line-height: 0;\n \n /* Dimensions with CSS variable support for flexibility */\n width: var(--ty-icon-size, 1em);\n height: var(--ty-icon-size, 1em);\n \n /* Enforce square aspect ratio */\n aspect-ratio: 1 / 1;\n \n \n /* Color & Transitions */\n color: inherit;\n transition: color var(--ty-transition-fast);\n \n /* Flex Behavior */\n flex-shrink: 0;\n \n /* Visibility - Force immediate rendering */\n visibility: visible !important;\n opacity: 1;\n \n /* ANTI-FLICKER: Force browser to paint immediately */\n will-change: contents;\n \n /* Prevent any sub-pixel rendering issues */\n transform: translateZ(0);\n -webkit-font-smoothing: antialiased;\n}\n\n/* The SVG element inside shadow DOM (registry / fallback path) */\n:host svg {\n width: 100%;\n height: 100%;\n display: block;\n\n /* Force immediate SVG rendering */\n will-change: auto;\n transform: translateZ(0);\n}\n\n/* Slotted SVG (server-side path: <ty-icon><svg>...</svg></ty-icon>).\n ::slotted() targets light-DOM children so they fill the host the same way\n shadow-DOM SVG does. Color is inherited from :host via currentColor. */\n::slotted(svg),\n::slotted(img) {\n width: 100%;\n height: 100%;\n display: block;\n}\n\n/* When used in slots, ensure proper display */\n:host([slot]) {\n display: inline-flex;\n}\n\n/* Size variants via CSS classes on the host */\n:host(.icon-xs) {\n width: 0.75em;\n height: 0.75em;\n}\n\n:host(.icon-sm) {\n width: 0.875em;\n height: 0.875em;\n}\n\n:host(.icon-md) {\n width: 1em;\n height: 1em;\n}\n\n:host(.icon-lg) {\n width: 1.25em;\n height: 1.25em;\n}\n\n:host(.icon-xl) {\n width: 1.5em;\n height: 1.5em;\n}\n\n:host(.icon-2xl) {\n width: 2em;\n height: 2em;\n}\n\n/* Fixed pixel sizes */\n:host(.icon-12) {\n width: 12px;\n height: 12px;\n}\n\n:host(.icon-14) {\n width: 14px;\n height: 14px;\n}\n\n:host(.icon-16) {\n width: 16px;\n height: 16px;\n}\n\n:host(.icon-18) {\n width: 18px;\n height: 18px;\n}\n\n:host(.icon-20) {\n width: 20px;\n height: 20px;\n}\n\n:host(.icon-24) {\n width: 24px;\n height: 24px;\n}\n\n:host(.icon-32) {\n width: 32px;\n height: 32px;\n}\n\n:host(.icon-48) {\n width: 48px;\n height: 48px;\n}\n\n:host(.icon-64) {\n width: 64px;\n height: 64px;\n}\n\n:host(.icon-80) {\n width: 80px;\n height: 80px;\n}\n\n:host(.icon-96) {\n width: 96px;\n height: 96px;\n}\n\n/* Spinning animation - default tempo */\n:host(.icon-spin) {\n animation: icon-spin 1s linear infinite;\n}\n\n/* Spinning animation - slow tempo */\n:host(.icon-spin.icon-tempo-slow) {\n animation: icon-spin 2s linear infinite;\n}\n\n/* Spinning animation - fast tempo */\n:host(.icon-spin.icon-tempo-fast) {\n animation: icon-spin 0.5s linear infinite;\n}\n\n@keyframes icon-spin {\n from {\n transform: rotate(0deg);\n }\n\n to {\n transform: rotate(360deg);\n }\n}\n\n/* Pulse animation - default tempo */\n:host(.icon-pulse) {\n animation: icon-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;\n}\n\n/* Pulse animation - slow tempo */\n:host(.icon-pulse.icon-tempo-slow) {\n animation: icon-pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite;\n}\n\n/* Pulse animation - fast tempo */\n:host(.icon-pulse.icon-tempo-fast) {\n animation: icon-pulse 1s cubic-bezier(0.4, 0, 0.6, 1) infinite;\n}\n\n@keyframes icon-pulse {\n 0%,\n 100% {\n opacity: 1;\n }\n\n 50% {\n opacity: 0.5;\n }\n}\n\n/* Accessibility: ensure icons are not announced by screen readers by default */\n:host {\n -webkit-user-select: none;\n user-select: none;\n}\n\n/* Allow pointer events to pass through by default */\n:host(:not(.icon-clickable)) {\n pointer-events: none;\n}\n\n/* Clickable icons */\n:host(.icon-clickable) {\n cursor: pointer;\n pointer-events: auto;\n transition: color var(--ty-transition-fast), transform var(--ty-transition-fast);\n}\n\n:host(.icon-clickable:hover) {\n transform: scale(1.1);\n}\n\n:host(.icon-clickable:active) {\n transform: scale(0.95);\n}\n\n/* Disabled state */\n:host(.icon-disabled) {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n/* Block display variant */\n:host(.icon-block) {\n display: block;\n}\n",id:"ty-icon"}),this.N=document.createElement("slot"),this.N.innerHTML=P,this.O=P,this.shadowRoot.appendChild(this.N)}onConnect(){this.L="ty-icon-"+ ++F,this.name&&L(this.L,this.name,t=>{this.name&&t.has(this.name)&&this.render()}),this.updateClasses()}onDisconnect(){this.L&&(O(this.L),this.L=null)}onPropertiesChanged(t){for(const n of t)if("name"===n.name){this.L&&O(this.L);const t=n.newValue||"";t&&this.isConnected&&(this.L="ty-icon-"+ ++F,L(this.L,t,t=>{this.name&&t.has(this.name)&&this.render()}))}this.updateClasses()}get name(){return this.getProperty("name")}set name(t){this.setProperty("name",t)}get size(){return this.getProperty("size")||void 0}set size(t){this.setProperty("size",t||"")}get spin(){return this.getProperty("spin")}set spin(t){this.setProperty("spin",t)}get pulse(){return this.getProperty("pulse")}set pulse(t){this.setProperty("pulse",t)}get tempo(){return this.getProperty("tempo")||void 0}set tempo(t){this.setProperty("tempo",t||"")}buildClasses(){const t=[],n=this.getProperty("size");n&&t.push("icon-"+n),this.getProperty("spin")&&t.push("icon-spin"),this.getProperty("pulse")&&t.push("icon-pulse");const e=this.getProperty("tempo");e&&(this.getProperty("spin")||this.getProperty("pulse"))&&t.push("icon-tempo-"+e);const i=this.className.split(/\s+/).filter(t=>t&&!t.startsWith("icon-")&&"icon-spin"!==t&&"icon-pulse"!==t);return[...t,...i]}updateClasses(){const t=this.buildClasses().join(" ");this.className!==t&&(this.className=t)}render(){const t=this.getProperty("name");if(!t)return void this.renderSvg(P);const n=A(t);this.renderSvg(n||P)}renderSvg(t){this.O!==t&&this.N&&(this.N.innerHTML=t,this.O=t)}};H.formAssociated=!1,H.properties={name:{type:"string",visual:!0,default:""},size:{type:"string",visual:!0,default:""},spin:{type:"boolean",visual:!0,default:!1},pulse:{type:"boolean",visual:!0,default:!1},tempo:{type:"string",visual:!0,default:""}};let j=H;customElements.get("ty-icon")||customElements.define("ty-icon",j);const B=`\n/* Tag Component Styles using centralized ty.variables.css */\n\n/* Host element */\n\n/* Hidden attribute support */\n:host([hidden]) {\n display: none !important;\n}\n\n/* Main container */\n.tag-container {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--ty-spacing-1);\n /* Default pill shape - can be overridden */\n border-radius: var(--ty-radius-full);\n font-weight: var(--ty-font-medium);\n text-align: center;\n white-space: nowrap;\n user-select: none;\n box-sizing: border-box;\n\n /* Default MD size — anchor at 28px, even +4 steps for other sizes */\n padding: 0 0.625rem; /* 0 10px */\n font-size: var(--ty-font-xs); /* 14px */\n line-height: var(--ty-leading-xs); /* 21px */\n letter-spacing: var(--ty-tracking-xs); /* -0.013em */\n min-height: 28px;\n\n /* Transitions using centralized values */\n transition: var(--ty-transition-all);\n\n /* Colors via custom properties — override on :host for full control */\n background: var(--tag-bg, transparent);\n color: var(--tag-color, var(--ty-text));\n border: 1px solid;\n border-color: var(--tag-border-color, var(--ty-border));\n}\n\n/* Non-pill variant - rectangular with rounded corners */\n:host([pill="false"]) .tag-container,\n:host([not-pill]) .tag-container {\n border-radius: var(--ty-radius-md);\n /* 6px instead of full pill */\n}\n\n/* Tags with value attribute but NOT selected should be clickable */\n:host([value]:not([selected])) .tag-container:not([aria-disabled="true"]) {\n cursor: pointer;\n}\n\n:host([selected]) .tag-container:not([aria-disabled="true"]) {\n cursor: initial;\n}\n\n.tag-container[tabindex]:not([aria-disabled="true"]):hover {\n background: var(--ty-bg-neutral-soft);\n transform: translateY(-1px);\n box-shadow: var(--ty-shadow-sm);\n}\n\n.tag-container[tabindex]:not([aria-disabled="true"]):active {\n transform: translateY(0);\n box-shadow: var(--ty-shadow-sm);\n}\n\n.tag-container[tabindex]:focus {\n outline: none;\n}\n\n/* Disabled state */\n.tag-container[aria-disabled="true"] {\n opacity: 0.6;\n cursor: not-allowed;\n pointer-events: none;\n}\n\n/* Slot containers */\n.tag-start,\n.tag-content,\n.tag-end {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.tag-content {\n flex: 1;\n min-width: 0;\n}\n\n/* Dismiss button */\n.tag-dismiss {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n background: none;\n border: none;\n color: currentColor;\n cursor: pointer;\n border-radius: var(--ty-radius-full);\n transition: var(--ty-transition-all);\n opacity: 0.7;\n flex-shrink: 0;\n /* Default MD dismiss button size */\n width: var(--ty-spacing-4);\n /* 16px */\n height: var(--ty-spacing-4);\n}\n\n.tag-dismiss:hover {\n opacity: 1;\n background: rgba(0, 0, 0, 0.1);\n}\n\n.tag-dismiss svg {\n width: 100%;\n height: 100%;\n}\n\n/* Size variants - override defaults */\n:host([size="xs"]) .tag-container {\n padding: 0 0.375rem; /* 0 6px */\n font-size: var(--ty-font-xs); /* 12px */\n line-height: var(--ty-leading-xs);\n letter-spacing: var(--ty-tracking-xs);\n min-height: 20px;\n}\n\n:host([size="xs"]) .tag-dismiss {\n width: var(--ty-spacing-3);\n height: var(--ty-spacing-3);\n margin-left: var(--ty-spacing-2);\n}\n\n:host([size="sm"]) .tag-container {\n padding: 0 var(--ty-spacing-2); /* 0 8px */\n font-size: var(--ty-font-xs); /* 12px */\n line-height: var(--ty-leading-xs);\n letter-spacing: var(--ty-tracking-xs);\n min-height: 24px;\n}\n\n:host([size="sm"]) .tag-dismiss {\n width: var(--ty-spacing-3);\n height: var(--ty-spacing-3);\n margin-left: var(--ty-spacing-2);\n}\n\n/* MD is now the default - no need for explicit [size="md"] selector */\n/* All default styles above apply to MD size (min-height: 24px) */\n\n:host([size="lg"]) .tag-container {\n padding: 0 var(--ty-spacing-3); /* 0 12px */\n font-size: var(--ty-font-sm); /* 14px */\n line-height: var(--ty-leading-sm); /* 21px */\n letter-spacing: var(--ty-tracking-sm); /* -0.013em */\n min-height: 32px;\n}\n\n:host([size="lg"]) .tag-dismiss {\n width: var(--ty-spacing-5);\n height: var(--ty-spacing-5);\n margin-left: var(--ty-spacing-4);\n}\n\n:host([size="xl"]) .tag-container {\n padding: 0 0.875rem; /* 0 14px */\n font-size: var(--ty-font-sm); /* 14px */\n line-height: var(--ty-leading-sm); /* 21px */\n letter-spacing: var(--ty-tracking-sm); /* -0.013em */\n min-height: 36px;\n}\n\n:host([size="xl"]) .tag-dismiss {\n width: var(--ty-spacing-5);\n height: var(--ty-spacing-5);\n margin-left: var(--ty-spacing-4);\n}\n\n/* ===== FLAVOR VARIANTS =====\n Each flavor sets --tag-bg / --tag-color / --tag-border-color on :host.\n Append '+' to flavor for a stronger shade (mild background, strong color),\n or '-' for a softer shade (soft background, base color).\n Generated per flavor above; neutral diverges (text/border tokens) and\n stays hand-written below. */\n\n${r.filter(t=>"neutral"!==t).map(t=>`\n/* ----- ${t.toUpperCase()} ----- */\n:host([flavor="${t}"]) {\n --tag-bg: var(--ty-bg-${t});\n --tag-color: var(--ty-color-${t});\n --tag-border-color: var(--ty-border-${t});\n}\n:host([flavor="${t}+"]) {\n --tag-bg: var(--ty-bg-${t}-bold);\n --tag-color: var(--ty-color-${t}-strong);\n --tag-border-color: var(--ty-color-${t});\n}\n:host([flavor="${t}-"]) {\n --tag-bg: var(--ty-bg-${t}-soft);\n --tag-color: var(--ty-color-${t});\n --tag-border-color: var(--ty-border-${t});\n}\n:host([flavor="${t}"]) .tag-container[tabindex]:hover,\n:host([flavor="${t}+"]) .tag-container[tabindex]:hover,\n:host([flavor="${t}-"]) .tag-container[tabindex]:hover {\n background: var(--ty-bg-${t}-bold);\n}\n:host([flavor="${t}"]) .tag-container[tabindex]:focus,\n:host([flavor="${t}+"]) .tag-container[tabindex]:focus,\n:host([flavor="${t}-"]) .tag-container[tabindex]:focus {\n box-shadow: 0 0 0 3px var(--ty-color-${t}-faint);\n}\n`).join("")}\n/* ----- NEUTRAL ----- */\n:host([flavor="neutral"]) {\n --tag-color: var(--ty-text-bold);\n --tag-bg: var(--ty-bg-neutral-soft);\n --tag-border-color: var(--ty-border-bold);\n}\n\n:host([flavor="neutral+"]) {\n --tag-bg: var(--ty-bg-neutral-bold);\n --tag-color: var(--ty-text-bold);\n --tag-border-color: var(--ty-border-strong);\n}\n:host([flavor="neutral-"]) {\n --tag-bg: var(--ty-bg-neutral-soft);\n --tag-color: var(--ty-text-soft);\n --tag-border-color: var(--ty-border);\n}\n:host([flavor="neutral"]) .tag-container[tabindex]:hover,\n:host([flavor="neutral+"]) .tag-container[tabindex]:hover,\n:host([flavor="neutral-"]) .tag-container[tabindex]:hover {\n background: var(--ty-bg-neutral-soft);\n}\n:host([flavor="neutral"]) .tag-container[tabindex]:focus,\n:host([flavor="neutral+"]) .tag-container[tabindex]:focus,\n:host([flavor="neutral-"]) .tag-container[tabindex]:focus {\n box-shadow: 0 0 0 3px var(--ty-border-soft);\n}\n\n/* Slotted content styling */\n.tag-start ::slotted(*),\n.tag-content ::slotted(*),\n.tag-end ::slotted(*) {\n display: flex;\n align-items: center;\n}\n\n/* Icon sizing for slotted icons */\n.tag-start ::slotted(ty-icon),\n.tag-end ::slotted(ty-icon) {\n width: 1em;\n height: 1em;\n flex-shrink: 0;\n}\n\n/* Count/badge styling using centralized spacing */\n.tag-end ::slotted(.count) {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: var(--ty-spacing-6);\n /* 24px */\n height: var(--ty-spacing-5);\n /* 20px */\n padding: 0 var(--ty-spacing-2);\n /* 0 8px */\n background: rgba(0, 0, 0, 0.1);\n border-radius: var(--ty-radius-full);\n font-size: var(--ty-font-xs);\n font-weight: var(--ty-font-semibold);\n line-height: var(--ty-line-height-none);\n flex-shrink: 0;\n}\n\n/* Special handling for long text content */\n.tag-content {\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n:host([data-type="user"]) .tag-container {\n min-width: var(--ty-spacing-20);\n /* 80px for user tags */\n}\n\n/* Dark mode is handled automatically by the centralized variables */\n`,W=class extends i{constructor(){super(),this.R=null,this.I=null,this.handleClick=t=>{this.clickable&&!this.disabled&&(t.preventDefault(),t.stopPropagation(),this.dispatchTagEvent("click",{target:this}),this.dispatchTagEvent("pointerdown",{target:this}))},this.handleDismiss=t=>{this.dismissible&&!this.disabled&&(t.preventDefault(),t.stopPropagation(),this.dispatchTagEvent("dismiss",{target:this}))},this.handleKeydown=t=>{const n=t;if(!this.disabled)switch(n.keyCode){case 13:case 32:this.clickable&&(n.preventDefault(),this.dispatchTagEvent("click",{target:this}));break;case 8:case 46:this.dismissible&&(n.preventDefault(),this.dispatchTagEvent("dismiss",{target:this}))}},s(this.shadowRoot,{css:B,id:"ty-tag"})}onConnect(){this.D(),queueMicrotask(()=>{this.setupEventListeners()})}D(){this.I=u(this.shadowRoot,this.I,this.flavor,({flavor:t,base:n,shade:e})=>`\n:host([flavor="${t}"]) {\n --tag-bg: var(${"+"===e?`--ty-bg-${n}-bold`:"-"===e?`--ty-bg-${n}-soft`:"--ty-bg-"+n});\n --tag-color: var(${"+"===e?`--ty-color-${n}-strong`:"--ty-color-"+n});\n --tag-border-color: var(--ty-border-${n}, var(--ty-color-${n}));\n}\n:host([flavor="${t}"]) .tag-container[tabindex]:hover {\n background: var(--ty-bg-${n}-bold, var(--tag-bg));\n}\n:host([flavor="${t}"]) .tag-container[tabindex]:focus {\n box-shadow: 0 0 0 3px var(--ty-color-${n}-faint, var(--tag-color));\n}`)}onDisconnect(){this.cleanupEventListeners()}onPropertiesChanged(t){t.some(t=>"flavor"===t.name)&&this.D()}dispatchTagEvent(t,n){this.dispatchEvent(new CustomEvent(t,{detail:n,bubbles:!0,composed:!0,cancelable:!0}))}cleanupEventListeners(){this.R&&(this.R(),this.R=null)}setupEventListeners(){this.cleanupEventListeners();const t=this.shadowRoot,n=t.querySelector(".tag-container"),e=t.querySelector(".tag-dismiss");n&&(n.addEventListener("click",this.handleClick),n.addEventListener("keydown",this.handleKeydown),e&&e.addEventListener("click",this.handleDismiss),this.R=()=>{n.removeEventListener("click",this.handleClick),n.removeEventListener("keydown",this.handleKeydown),e&&e.removeEventListener("click",this.handleDismiss)})}render(){this.shadowRoot.innerHTML=`\n <div class="tag-container" part="container"${this.clickable?' tabindex="0"':""}${this.disabled?' aria-disabled="true"':""}${this.value?` data-value="${this.value}"`:""}>\n <div class="tag-start">\n <slot name="start" class="tag-start"></slot>\n </div>\n <div class="tag-content">\n <slot></slot>\n </div>\n <div class="tag-end">\n <slot name="end"></slot>\n ${this.dismissible?'\n <button class="tag-dismiss" type="button" aria-label="Remove tag">\n <svg viewBox="0 0 20 20" fill="currentColor">\n <path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd" />\n </svg>\n </button>\n ':""}\n </div>\n </div>\n `,this.p&&this.setupEventListeners()}get flavor(){return this.getProperty("flavor")}set flavor(t){this.setProperty("flavor",t)}get size(){return this.getProperty("size")}set size(t){this.setProperty("size",t)}get value(){return this.getProperty("value")}set value(t){this.setProperty("value",t)}get selected(){return this.getProperty("selected")}set selected(t){this.setProperty("selected",t)}get pill(){return this.getProperty("pill")}set pill(t){this.setProperty("pill",t)}get clickable(){return this.getProperty("clickable")}set clickable(t){this.setProperty("clickable",t)}get dismissible(){return this.getProperty("dismissible")}set dismissible(t){this.setProperty("dismissible",t)}get disabled(){return this.getProperty("disabled")}set disabled(t){this.setProperty("disabled",t)}};W.formAssociated=!0,W.properties={flavor:{type:"string",visual:!0,default:"neutral"},size:{type:"string",visual:!0,default:"md",validate:t=>["xs","sm","md","lg","xl"].includes(t),coerce:t=>["xs","sm","md","lg","xl"].includes(t)?t:"md"},value:{type:"string",visual:!0,default:""},selected:{type:"boolean",visual:!0,default:!1},pill:{type:"boolean",visual:!0,default:!0,aliases:{"not-pill":!1}},clickable:{type:"boolean",visual:!0,default:!1},dismissible:{type:"boolean",visual:!0,default:!1},disabled:{type:"boolean",visual:!0,default:!1}};let _=W;customElements.get("ty-tag")||customElements.define("ty-tag",_);class TyOption extends HTMLElement{constructor(){super(),this.q=void 0,this.V=!1,this.F=!1,this.P=!1,this.H=!1,s(this.attachShadow({mode:"open"}),{css:"\n/* Ty Option Component Styles */\n\n.option-content {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--ty-spacing-2);\n box-sizing: border-box;\n width: 100%;\n\n /* Ensure content is clickable */\n cursor: pointer;\n user-select: none;\n\n /* Smooth transitions */\n transition: var(--ty-transition-all);\n\n /* Text styling — Linear-paired typography */\n color: var(--ty-text);\n font-family: var(--ty-font-sans);\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n padding: var(--ty-spacing-2) var(--ty-spacing-3);\n border-radius: var(--ty-radius-md);\n}\n\n:host([cloned]) .option-content {\n padding: 0px;\n background: transparent;\n}\n\n.option-content:hover {\n background: var(--ty-bg-neutral-soft);\n}\n\n.option-content[highlighted] {\n background: var(--ty-bg-neutral-soft);\n color: var(--ty-text-strong);\n font-weight: var(--ty-font-semibold);\n}\n\n/* Selected: quiet — bolder text color only, no background slab, no weight change */\n.option-content[selected] {\n background: transparent;\n color: var(--ty-text-bold);\n}\n\n/* Lucide check — right-aligned, visible only on selected options */\n.option-check {\n display: none;\n flex-shrink: 0;\n width: 14px;\n height: 14px;\n margin-left: auto;\n color: var(--ty-color-primary);\n}\n\n.option-content[selected] .option-check {\n display: block;\n}\n\n/* Never show the check on the copy cloned into the select's trigger field */\n:host([cloned]) .option-check {\n display: none;\n}\n\n.option-content[selected]:hover {\n background: var(--ty-bg-neutral-soft);\n}\n\n.option-content[disabled] {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.option-content[hidden] {}\n\n/* Ensure nested elements inherit proper styling */\n.option-content * {\n pointer-events: none;\n}\n",id:"ty-option"}),this.render()}static get observedAttributes(){return["value","disabled","selected","highlighted","hidden"]}connectedCallback(){const t=Object.getOwnPropertyDescriptor(this,"value");t&&void 0!==t.value&&(this.q=t.value,delete this.value),this.render()}attributeChangedCallback(t,n,e){if(n!==e){switch(t){case"value":this.q=e||void 0;break;case"selected":this.V=null!==e;break;case"disabled":this.F=null!==e;break;case"highlighted":this.P=null!==e;break;case"hidden":this.H=null!==e}this.render()}}getOptionValue(){if(void 0!==this.q)return this.q;const t=this.getAttribute("value");return null!==t?t:this.textContent?.trim()||""}get value(){return this.getOptionValue()}set value(t){this.q!==t&&(this.q=t,void 0!==t?this.setAttribute("value",t):this.removeAttribute("value"),this.render())}get selected(){return this.V}set selected(t){this.V!==t&&(this.V=t,t?this.setAttribute("selected",""):this.removeAttribute("selected"),this.render())}get disabled(){return this.F}set disabled(t){this.F!==t&&(this.F=t,t?this.setAttribute("disabled",""):this.removeAttribute("disabled"),this.render())}get highlighted(){return this.P}set highlighted(t){this.P!==t&&(this.P=t,t?this.setAttribute("highlighted",""):this.removeAttribute("highlighted"),this.render())}get hidden(){return this.H}set hidden(t){this.H!==t&&(this.H=t,t?this.setAttribute("hidden",""):this.removeAttribute("hidden"),this.render())}render(){const t=this.shadowRoot;t.querySelector(".option-content")||(t.innerHTML='<div class="option-content"><slot></slot>\n <svg class="option-check" viewBox="0 0 24 24" fill="none" stroke="currentColor"\n stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">\n <path d="M20 6 9 17l-5-5" />\n </svg>\n</div>');const n=t.querySelector(".option-content");n&&(this.F?n.setAttribute("disabled",""):n.removeAttribute("disabled"),this.V?n.setAttribute("selected",""):n.removeAttribute("selected"),this.P?n.setAttribute("highlighted",""):n.removeAttribute("highlighted"),this.H?n.setAttribute("hidden",""):n.removeAttribute("hidden"))}}customElements.get("ty-option")||customElements.define("ty-option",TyOption);const Y=(t,n)=>{const e=e=>n?e?`var(--ty-color-${t}${e}, var(--ty-color-${t}, var(--ty-color-${n}${e})))`:`var(--ty-color-${t}, var(--ty-color-${n}))`:e?`var(--ty-color-${t}${e}, var(--ty-color-${t}))`:`var(--ty-color-${t})`;return`\n:host([flavor="${t}"]) {\n --input-accent: var(--ty-input-${t}-border, ${e("-soft")});\n --input-accent-bold: ${e("")};\n --input-ring: color-mix(in oklab, ${e("")} 15%, transparent);\n}\n:host([flavor="${t}+"]) {\n --input-accent: ${e("")};\n --input-accent-bold: ${e("-strong")};\n --input-ring: color-mix(in oklab, ${e("-strong")} 15%, transparent);\n}\n:host([flavor="${t}-"]) {\n --input-accent: ${e("-faint")};\n --input-accent-bold: ${e("-soft")};\n --input-ring: color-mix(in oklab, ${e("-soft")} 15%, transparent);\n}\n`},U=`\n:host {\n display: block;\n font-family: var(--ty-font-sans);\n width: 100%;\n}\n\n:host([size="sm"]) {\n font-size: 14px;\n}\n\n:host([size="lg"]) {\n font-size: 18px;\n}\n\n.input-container {\n display: flex;\n flex-direction: column;\n width: 100%;\n box-sizing: border-box;\n}\n\n/* ===== LABEL STYLING ===== */\n\n.ty-field-label {\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n font-weight: var(--ty-font-medium);\n color: var(--ty-label-color);\n margin-bottom: 6px;\n padding-left: 12px;\n display: flex;\n align-items: center;\n}\n\n/* Required indicator - using SVG icon */\n.required-icon {\n display: inline-flex;\n align-items: center;\n color: var(--ty-color-danger);\n width: 12px;\n height: 12px;\n margin-left: 4px;\n vertical-align: middle;\n}\n\n.required-icon svg {\n width: 100%;\n height: 100%;\n}\n\n/* ===== INPUT WRAPPER WITH SLOTS ===== */\n\n.input-wrapper {\n display: flex;\n align-items: center;\n gap: 0.5rem; /* No gap by default */\n width: 100%;\n box-sizing: border-box;\n border: 1px solid var(--input-accent, var(--input-border, var(--ty-input-border)));\n border-radius: var(--ty-radius-base);\n background: var(--input-bg, var(--input-bg, var(--ty-input-bg)));\n transition: all 0.15s ease-in-out;\n \n /* Default size (md) */\n min-height: var(--ty-size-md);\n padding: 0 12px;\n}\n\n/* Wrapper states — --input-accent* are set by the flavor rules below;\n without a flavor attribute they're unset and the default chrome chain\n (per-instance --input-* var, then --ty-input-* token) applies. */\n.input-wrapper:hover:not(.disabled) {\n border-color: var(--input-accent-bold, var(--input-border-hover, var(--ty-input-border-hover)));\n}\n\n.input-wrapper.focused {\n border-color: var(--input-accent-bold, var(--input-border-focus, var(--ty-input-border-focus)));\n box-shadow: 0 0 0 3px var(--input-ring, var(--input-shadow-focus, var(--ty-input-shadow-focus)));\n}\n\n.input-wrapper.disabled {\n cursor: not-allowed;\n opacity: 0.5;\n background: var(--input-disabled-bg, var(--ty-input-disabled-bg));\n border-color: var(--input-disabled-border, var(--ty-input-disabled-border));\n}\n\n/* ===== SLOT STYLING ===== */\n\n/* Style slotted content directly (no wrappers needed) */\n::slotted([slot="start"]),\n::slotted([slot="end"]) {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n color: var(--ty-color-text-soft);\n}\n\n/* Password reveal toggle (rendered for type="password") */\n.password-toggle {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: 1.25rem;\n height: 1.25rem;\n padding: 0;\n border: none;\n background: none;\n cursor: pointer;\n color: var(--input-placeholder, var(--ty-input-placeholder));\n transition: color 0.15s ease-in-out;\n}\n.password-toggle:hover {\n color: var(--input-color, var(--ty-input-color));\n}\n.password-toggle:focus-visible {\n outline: 2px solid var(--input-accent, var(--ty-color-primary));\n outline-offset: 2px;\n border-radius: 2px;\n}\n.password-toggle svg {\n width: 1rem;\n height: 1rem;\n}\n\n/* Icon sizing for slotted icons */\n::slotted(ty-icon) {\n width: 1em;\n height: 1em;\n flex-shrink: 0;\n}\n\n/* ===== ERROR MESSAGE STYLING ===== */\n\n.error-message {\n font-size: var(--ty-font-xs);\n line-height: var(--ty-leading-xs);\n letter-spacing: var(--ty-tracking-xs);\n color: var(--ty-color-danger);\n margin-top: 4px;\n padding-left: 12px;\n}\n\n/* Error state for wrapper */\n.input-wrapper.error {\n border-color: var(--ty-color-danger);\n background: var(--ty-bg-danger-soft);\n}\n\n.input-wrapper.error.focused {\n border-color: var(--ty-color-danger-bold);\n box-shadow: 0 0 0 3px var(--input-shadow-focus, var(--ty-input-shadow-focus));\n}\n\n/* ===== INPUT BASE STYLING ===== */\n\ninput {\n /* Reset and base styles — Linear-paired typography */\n flex: 1;\n min-width: 0;\n box-sizing: border-box;\n border: none;\n outline: none;\n background: transparent;\n color: var(--input-color, var(--ty-input-color));\n font-family: inherit;\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n font-weight: var(--ty-font-normal);\n padding: 0;\n margin: 0;\n}\n\n/* Remove number input spinner arrows */\ninput[type="number"]::-webkit-outer-spin-button,\ninput[type="number"]::-webkit-inner-spin-button {\n -webkit-appearance: none;\n margin: 0;\n}\n\ninput[type="number"] {\n -moz-appearance: textfield;\n}\n\n/* Disabled state */\ninput:disabled {\n cursor: not-allowed;\n color: var(--input-disabled-color, var(--ty-input-disabled-color));\n}\n\n/* Placeholder styling */\ninput::placeholder {\n color: var(--input-placeholder, var(--ty-input-placeholder));\n font-weight: 400;\n}\n\n/* ===== SIZE MODIFIERS ===== */\n\n/* Small */\n.input-wrapper.sm {\n min-height: var(--ty-size-sm);\n padding: 0 10px;\n border-radius: var(--ty-input-radius-sm, var(--ty-radius-base));\n}\n\n.input-wrapper.sm input {\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n}\n\n/* Medium (default) */\n.input-wrapper.md {\n min-height: var(--ty-size-md);\n padding: 0 12px;\n border-radius: var(--ty-input-radius-md, var(--ty-radius-base));\n}\n\n.input-wrapper.md input {\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n}\n\n/* Large */\n.input-wrapper.lg {\n min-height: var(--ty-size-lg);\n padding: 0 14px;\n border-radius: var(--ty-input-radius-lg, var(--ty-radius-base));\n}\n\n.input-wrapper.lg input {\n font-size: var(--ty-font-base);\n line-height: var(--ty-leading-base);\n letter-spacing: var(--ty-tracking-base);\n}\n\n/* ===== SEMANTIC FLAVOR MODIFIERS (set --input-accent*, consumed above) ===== */\n${r.filter(t=>"neutral"!==t).map(t=>Y(t)).join("")}\n\n/* ===== ACCESSIBILITY ENHANCEMENTS ===== */\n\ninput:focus-visible {\n outline: none;\n}\n\n/* High contrast mode support */\n@media (prefers-contrast: high) {\n .input-wrapper {\n border-width: 2px;\n }\n}\n\n/* Reduced motion support */\n@media (prefers-reduced-motion: reduce) {\n .input-wrapper {\n transition: none;\n }\n}\n\n/* ===== RESPONSIVE BEHAVIOR ===== */\n\n@media (max-width: 640px) {\n .input-wrapper.lg {\n min-height: 40px;\n padding: 0 12px;\n }\n\n .input-wrapper.lg input {\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n }\n\n .input-wrapper.xl {\n min-height: 44px;\n padding: 0 14px;\n }\n\n .input-wrapper.xl input {\n font-size: var(--ty-font-base);\n line-height: var(--ty-leading-base);\n letter-spacing: var(--ty-tracking-base);\n }\n}\n\n@media (max-width: 480px) {\n .input-wrapper.xl {\n min-height: 40px;\n padding: 0 12px;\n }\n\n .input-wrapper.xl input {\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n }\n}\n`;function G(t){return["number","currency","percent","compact"].includes(t)}function K(t,n){if(n)return n;const e=t.closest("[lang]");if(e){const t=e.getAttribute("lang");if(t)return t}return document.documentElement.lang?document.documentElement.lang:navigator.language?navigator.language:"en-US"}function Z(t,n){let e=K(t);const i=new MutationObserver(i=>{for(const o of i)if("attributes"===o.type&&"lang"===o.attributeName){const i=K(t);i!==e&&(e=i,n(i))}});return i.observe(document.documentElement,{attributes:!0,attributeFilter:["lang"],subtree:!0}),()=>i.disconnect()}const X='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 6v12"/><path d="M17.196 9 6.804 15"/><path d="m6.804 9 10.392 6"/></svg>',J='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0"/><circle cx="12" cy="12" r="3"/></svg>',Q=class extends i{constructor(){super(),this.j=null,this.B=!1,this.W=!1,this._=!1,this.I=null,this.Y=null,this.U=null,this.G=null,this.K=null,this.Z=null,this.X=null,s(this.shadowRoot,{css:U,id:"ty-input"})}onConnect(){this.initializeShadowValue(),this.J=Z(this,()=>{this.render()}),this.D()}D(){this.I=u(this.shadowRoot,this.I,this.flavor,({base:t})=>(t=>Y(t,"neutral"))(t))}onDisconnect(){this.removeEventListeners(),this.J&&(this.J(),this.J=void 0),null!==this.Z&&(clearTimeout(this.Z),this.Z=null),null!==this.X&&(clearTimeout(this.X),this.X=null)}onPropertiesChanged(t){for(const{name:n,newValue:e}of t)switch(n){case"flavor":this.D();break;case"value":this.j=this.parseShadowValue(e||"");break;case"type":const t=this.getProperty("value")||"";this.j=this.parseShadowValue(t);break;case"error":e?"neutral"===this.getProperty("flavor")&&(this.setProperty("flavor","danger"),this._=!0):this._&&("danger"===this.getProperty("flavor")&&this.setProperty("flavor","neutral"),this._=!1)}}onFormReset(){this.j=null,this.B=!1,null!==this.Z&&(clearTimeout(this.Z),this.Z=null),null!==this.X&&(clearTimeout(this.X),this.X=null),this.render()}getFormValue(){return null!==this.j?this.j+"":null}initializeShadowValue(){const t=this.getProperty("value");t&&(this.j=this.parseShadowValue(t),this.v.setFormValue(null!==this.j?this.j+"":null))}parseShadowValue(t){if(!t||"string"!=typeof t||""===t.trim())return null;if(G(this.type)){const n=function(t){if(!t||""===t.trim())return null;let n=t.replace(/[^\d.,-]/g,"").trim();if(""===n||"-"===n)return null;const e=n.lastIndexOf(","),i=n.lastIndexOf("."),o=Math.max(e,i);if(-1===o){const t=parseFloat(n);return isNaN(t)?null:t}const s=n.slice(0,o).replace(/[.,]/g,""),r=n.slice(o+1),a=parseFloat(s+"."+r);return isNaN(a)?null:a}(t);return null!==n&&0===this.precision?Math.round(n):n}return t}shouldFormat(){return G(this.type)&&!this.B&&null!==this.j&&"number"==typeof this.j}getFormatConfig(){return{type:this.type,locale:this.locale,currency:this.currency,precision:this.precision}}getDisplayValue(){if(this.shouldFormat()){let t=this.j;return"percent"===this.type&&(t/=100),function(t,n){const{type:e,locale:i="en-US",currency:o="USD",precision:s}=n,r={};switch(void 0!==s&&(r.minimumFractionDigits=s,r.maximumFractionDigits=s),e){case"currency":r.style="currency",r.currency=o;break;case"percent":r.style="percent";break;case"compact":r.notation="compact",r.compactDisplay="short";break;default:r.style="decimal"}return new Intl.NumberFormat(i,r).format(t).replace(/\u202F/g," ").replace(/\u2009/g," ")}(t,this.getFormatConfig())}return null!==this.j?this.j+"":""}get type(){return this.getProperty("type")}set type(t){this.setProperty("type",t)}get value(){return null!==this.j?this.j+"":""}set value(t){this.setProperty("value",t)}get name(){return this.getProperty("name")}set name(t){this.setProperty("name",t)}get placeholder(){return this.getProperty("placeholder")}set placeholder(t){this.setProperty("placeholder",t)}get label(){return this.getProperty("label")}set label(t){this.setProperty("label",t)}get disabled(){return this.getProperty("disabled")}set disabled(t){this.setProperty("disabled",t)}get required(){return this.getProperty("required")}set required(t){this.setProperty("required",t)}get error(){return this.getProperty("error")}set error(t){this.setProperty("error",t)}get size(){return this.getProperty("size")}set size(t){this.setProperty("size",t)}get flavor(){return this.getProperty("flavor")}set flavor(t){this.setProperty("flavor",t)}get currency(){return this.getProperty("currency")}set currency(t){this.setProperty("currency",t)}get locale(){return K(this,this.getProperty("locale"))}set locale(t){this.setProperty("locale",t)}get precision(){return this.getProperty("precision")}set precision(t){this.setProperty("precision",t)}get debounce(){return this.getProperty("debounce")}set debounce(t){this.setProperty("debounce",t)}get form(){return this.v.form}buildClassList(){const t=[this.size];return this.disabled&&t.push("disabled"),this.required&&t.push("required"),this.error&&t.push("error"),t.join(" ")}dispatchInputEvent(t,n){this.dispatchEvent(new CustomEvent("input",{detail:{value:this.j,formattedValue:this.shouldFormat()?this.getDisplayValue():null,rawValue:t,originalEvent:n},bubbles:!0,composed:!0}))}dispatchChangeEvent(t,n){this.dispatchEvent(new CustomEvent("change",{detail:{value:this.j,formattedValue:this.shouldFormat()?this.getDisplayValue():null,rawValue:t,originalEvent:n},bubbles:!0,composed:!0}))}removeEventListeners(){if(!this.W)return;const t=this.shadowRoot;if(!t)return;const n=t.querySelector("input");n&&(this.Y&&(n.removeEventListener("input",this.Y),this.Y=null),this.U&&(n.removeEventListener("change",this.U),this.U=null),this.G&&(n.removeEventListener("focus",this.G),this.G=null),this.K&&(n.removeEventListener("blur",this.K),this.K=null),this.W=!1)}setupEventListeners(){if(this.W)return;const t=this.shadowRoot,n=t.querySelector("input"),e=t.querySelector(".input-wrapper");n&&e&&(this.Y=t=>{t.stopPropagation(),t.stopImmediatePropagation();const e=t.target.value;this.j=this.parseShadowValue(e),this.v.setFormValue(null!==this.j?this.j+"":null),this.updateValidity(),null!==this.Z&&clearTimeout(this.Z),this.debounce>0?this.Z=window.setTimeout(()=>{this.dispatchInputEvent(n.value,t),this.Z=null},this.debounce):this.dispatchInputEvent(e,t)},this.U=t=>{t.stopPropagation(),t.stopImmediatePropagation();const e=t.target.value;this.j=this.parseShadowValue(e),this.v.setFormValue(null!==this.j?this.j+"":null),this.updateValidity(),null!==this.X&&clearTimeout(this.X),this.debounce>0?this.X=window.setTimeout(()=>{this.dispatchChangeEvent(n.value,t),this.X=null},this.debounce):this.dispatchChangeEvent(e,t)},this.G=t=>{this.B=!0,e.classList.add("focused"),G(this.type)&&null!==this.j&&(n.value=this.j+""),this.dispatchEvent(new CustomEvent("focus",{detail:{originalEvent:t},bubbles:!0,composed:!0}))},this.K=t=>{const i=t.target.value;null!==this.Z&&(clearTimeout(this.Z),this.Z=null,this.dispatchInputEvent(i,t)),null!==this.X&&(clearTimeout(this.X),this.X=null,this.dispatchChangeEvent(i,t)),this.B=!1,e.classList.remove("focused"),this.shouldFormat()&&(n.value=this.getDisplayValue()),this.dispatchEvent(new CustomEvent("blur",{detail:{originalEvent:t},bubbles:!0,composed:!0}))},n.addEventListener("input",this.Y),n.addEventListener("change",this.U),n.addEventListener("focus",this.G),n.addEventListener("blur",this.K),this.W=!0)}render(){const t=this.shadowRoot,n=t.querySelector("input"),e=t.querySelector(".input-wrapper"),i=t.querySelector(".ty-field-label"),o=t.querySelector(".error-message"),s=this.buildClassList(),r=["password","email","tel","url"].includes(this.type)?this.type:"text",a=G(this.type)?"decimal":"email"===this.type?"email":"tel"===this.type?"tel":"url"===this.type?"url":void 0,l=this.getDisplayValue();if(n&&e){if(n.type=r,n.value=l,n.placeholder=this.placeholder,n.name=this.name,a?n.inputMode=a:n.removeAttribute("inputmode"),e.className="input-wrapper "+s,n.disabled=this.disabled,this.disabled?n.setAttribute("disabled",""):n.removeAttribute("disabled"),n.required=this.required,this.required?n.setAttribute("required",""):n.removeAttribute("required"),this.label?n.setAttribute("aria-label",this.label):n.removeAttribute("aria-label"),this.label)if(i)i.innerHTML=`${this.label}${this.required?`<span class="required-icon">${X}</span>`:""}`,i.style.display="flex";else{const n=document.createElement("label");n.className="ty-field-label",n.innerHTML=`${this.label}${this.required?`<span class="required-icon">${X}</span>`:""}`;const i=t.querySelector(".input-container");i&&i.insertBefore(n,e)}else i&&(i.style.display="none");if(this.error)if(o)o.textContent=this.error;else{const n=document.createElement("div");n.className="error-message",n.textContent=this.error,t.querySelector(".input-container")?.appendChild(n)}else o&&o.remove()}else{t.innerHTML=`\n <div class="input-container">\n ${this.label?`\n <label class="ty-field-label">\n ${this.label}\n ${this.required?`<span class="required-icon">${X}</span>`:""}\n </label>\n `:""}\n <div class="input-wrapper ${s}">\n <slot name="start"></slot>\n <input\n type="${r}"\n value="${l}"\n placeholder="${this.placeholder}"\n name="${this.name}"\n ${a?`inputmode="${a}"`:""}\n />\n <slot name="end"></slot>\n ${"password"===r?`\n <button class="password-toggle" type="button"\n aria-label="Show password" aria-pressed="false">\n ${J}\n </button>`:""}\n </div>\n ${this.error?`\n <div class="error-message">${this.error}</div>\n `:""}\n </div>\n `;const n=t.querySelector("input");n.disabled=this.disabled,n.required=this.required,this.label&&n.setAttribute("aria-label",this.label),this.setupPasswordToggle(),this.setupEventListeners()}this.updateValidity()}setupPasswordToggle(){const t=this.shadowRoot,n=t.querySelector(".password-toggle"),e=t.querySelector("input");n&&e&&(n.addEventListener("mousedown",t=>t.preventDefault()),n.addEventListener("click",()=>{const t="password"===e.type;e.type=t?"text":"password",n.innerHTML=t?'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49"/><path d="M14.084 14.158a3 3 0 0 1-4.242-4.242"/><path d="M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143"/><path d="m2 2 20 20"/></svg>':J,n.setAttribute("aria-label",t?"Hide password":"Show password"),n.setAttribute("aria-pressed",t+"")}))}updateValidity(){const t=this.shadowRoot?.querySelector("input");if(this.disabled)return void this.v.setValidity({});const n=t?t.value:(this.getProperty("value")??"")+"";this.required&&""===n.trim()?this.v.setValidity({valueMissing:!0},"Please fill out this field",t??void 0):this.v.setValidity({})}};Q.formAssociated=!0,Q.properties={type:{type:"string",visual:!0,default:"text",validate:t=>["text","email","password","number","tel","url","currency","percent","compact"].includes(t),coerce:t=>["text","email","password","number","tel","url","currency","percent","compact"].includes(t)?t:"text"},value:{type:"string",visual:!0,formValue:!0,emitChange:!0,default:""},name:{type:"string",default:""},placeholder:{type:"string",visual:!0,default:""},label:{type:"string",visual:!0,default:""},disabled:{type:"boolean",visual:!0,default:!1},required:{type:"boolean",visual:!0,default:!1},error:{type:"string",visual:!0,default:""},size:{type:"string",visual:!0,default:"md",validate:t=>["sm","md","lg"].includes(t),coerce:t=>"xs"===t?"sm":"xl"===t?"lg":["sm","md","lg"].includes(t)?t:"md"},flavor:{type:"string",visual:!0,default:"neutral"},currency:{type:"string",visual:!0,default:"USD"},locale:{type:"string",visual:!0,default:"en-US"},precision:{type:"number",visual:!0,default:void 0,validate:t=>null==t||"number"==typeof t&&t>=0&&10>=t,coerce:t=>{if(null==t)return;const n=+t;return isNaN(n)?void 0:Math.max(0,Math.min(10,Math.floor(n)))}},debounce:{type:"number",default:0,validate:t=>{const n=+t;return!isNaN(n)&&n>=0&&5e3>=n},coerce:t=>{const n=+t;return isNaN(n)?0:Math.max(0,Math.min(5e3,Math.floor(n)))}}};let tt=Q;customElements.get("ty-input")||customElements.define("ty-input",tt);const nt=(t,n)=>{const e=e=>n?`var(--ty-color-${t}${e}, var(--ty-color-${n}${e}))`:`var(--ty-color-${t}${e})`;return`\n:host([flavor="${t}"]) { --checkbox-color: ${e("")}; --checkbox-color-off: ${e("-soft")}; --checkbox-ring: color-mix(in oklab, ${e("")} 25%, transparent); }\n:host([flavor="${t}+"]) { --checkbox-color: ${e("-strong")}; --checkbox-color-off: ${e("-soft")}; --checkbox-ring: color-mix(in oklab, ${e("-strong")} 25%, transparent); }\n:host([flavor="${t}-"]) { --checkbox-color: ${e("-soft")}; --checkbox-color-off: ${e("-faint")}; --checkbox-ring: color-mix(in oklab, ${e("-soft")} 25%, transparent); }\n`},et=`\n:host {\n display: inline-flex;\n width: auto;\n vertical-align: middle;\n}\n\n.checkbox-container {\n display: inline-flex;\n align-items: center;\n outline: none;\n transition: all 0.15s ease-in-out;\n user-select: none;\n cursor: pointer;\n border-radius: 6px;\n gap: var(--ty-spacing-1);\n /* Default (no flavor attribute) is neutral — defaults don't reflect to the\n host attribute, so the fallbacks here carry the default look. */\n color: var(--checkbox-color-off, var(--ty-color-neutral-soft));\n}\n\n.checkbox-container[aria-checked="true"] {\n color: var(--checkbox-color, var(--ty-color-neutral));\n}\n\n/* Visible focus ring (keyboard) — .focused is toggled by the component.\n Matches the checked-state color so a danger checkbox gets a red ring,\n not a fixed primary one. */\n.checkbox-container.focused,\n.checkbox-container:focus-visible {\n box-shadow: 0 0 0 3px var(--checkbox-ring, color-mix(in oklab, var(--ty-color-primary) 25%, transparent));\n}\n\n.checkbox-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n color: inherit;\n transition: color 0.15s ease-in-out;\n pointer-events: none;\n /* Let the container handle the click */\n}\n\n/* ===== SIZES ===== */\n\n.checkbox-container svg {\n width: 16px;\n height: 16px;\n}\n\n.checkbox-container.xs svg {\n width: 12px;\n height: 12px;\n}\n\n.checkbox-container.sm svg {\n width: 14px;\n height: 14px;\n}\n\n.checkbox-container.lg svg {\n width: 20px;\n height: 20px;\n}\n\n.checkbox-container.xl svg {\n width: 24px;\n height: 24px;\n}\n\n/* ===== SEMANTIC FLAVORS (set --checkbox-color[-off], consumed above) ===== */\n${r.map(t=>nt(t)).join("")}\n\n/* ===== STATES ===== */\n\n/* Clean tick: no box outline, just the checkmark. Inactive = faint tick. */\n.checkbox-container:not([aria-checked="true"]) {\n opacity: 0.35;\n}\n\n/* Indeterminate (dash) sits between unchecked and checked */\n.checkbox-container[aria-checked="mixed"] {\n opacity: 0.7;\n}\n\n/* Disabled must stay distinguishable from merely-unchecked: grayscale kills\n the flavor color, and disabled-unchecked drops below the unchecked 0.35. */\n.checkbox-container.disabled {\n pointer-events: none;\n cursor: not-allowed;\n opacity: 0.5;\n filter: grayscale(1);\n}\n\n.checkbox-container.disabled:not([aria-checked="true"]) {\n opacity: 0.2;\n}\n\n/* Error state */\n.checkbox-container.error .checkbox-icon {\n color: var(--ty-color-danger);\n}\n\n.checkbox-container.error:focus {\n box-shadow: 0 0 0 3px color-mix(in oklab, var(--ty-color-danger) 15%, transparent);\n}\n`,it=class extends i{constructor(){super(),this.I=null,this.W=!1,this.tt=null,this.nt=null,this.G=null,this.K=null,s(this.shadowRoot,{css:et,id:"ty-checkbox"})}onConnect(){this.setupEventListeners(),this.D()}D(){this.I=u(this.shadowRoot,this.I,this.flavor,({base:t})=>(t=>nt(t,"neutral"))(t))}onDisconnect(){this.removeEventListeners()}onPropertiesChanged(t){t.some(t=>"flavor"===t.name)&&this.D()}getFormValue(){return this.checked?this.value:null}buildClassList(){const t=[this.size];return this.disabled&&t.push("disabled"),this.required&&t.push("required"),t.join(" ")}handleCheckboxClick(t){if(this.disabled)return;const n=!!this.indeterminate||!this.checked;this.indeterminate&&(this.indeterminate=!1),this.checked=n,setTimeout(()=>{const e={value:n,checked:n,formValue:n?this.value:null,originalEvent:t};this.dispatchEvent(new CustomEvent("input",{detail:e,bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("change",{detail:e,bubbles:!0,composed:!0}))},0)}handleCheckboxKeydown(t){this.disabled||["Space"," ","Enter"].includes(t.key)&&(t.preventDefault(),t.stopPropagation(),this.handleCheckboxClick(t))}removeEventListeners(){if(!this.W)return;this.tt&&(this.removeEventListener("click",this.tt),this.tt=null);const t=this.shadowRoot;if(!t)return;const n=t.querySelector(".checkbox-container");n?(this.nt&&(n.removeEventListener("keydown",this.nt),this.nt=null),this.G&&(n.removeEventListener("focus",this.G),this.G=null),this.K&&(n.removeEventListener("blur",this.K),this.K=null),this.W=!1):this.W=!1}setupEventListeners(){if(this.W)return;const t=this.shadowRoot.querySelector(".checkbox-container");t&&(this.tt=t=>{this.handleCheckboxClick(t)},this.nt=t=>{this.handleCheckboxKeydown(t)},this.G=()=>{t.classList.add("focused")},this.K=()=>{t.classList.remove("focused")},this.addEventListener("click",this.tt),t.addEventListener("keydown",this.nt),t.addEventListener("focus",this.G),t.addEventListener("blur",this.K),this.W=!0)}render(){const t=this.shadowRoot;let n=t.querySelector(".checkbox-container");const e=this.buildClassList(),i=this.indeterminate?"mixed":this.checked+"";if(n)n.className="checkbox-container "+e,n.tabIndex=this.disabled?-1:0,n.setAttribute("aria-checked",i),n.setAttribute("aria-disabled",this.disabled+""),n.setAttribute("aria-required",this.required+"");else{n=document.createElement("div"),n.className="checkbox-container "+e,n.tabIndex=this.disabled?-1:0,n.setAttribute("role","checkbox"),n.setAttribute("aria-checked",i),n.setAttribute("aria-disabled",this.disabled+""),n.setAttribute("aria-required",this.required+"");const o=document.createElement("div");o.className="checkbox-icon",n.appendChild(o),t.appendChild(n)}n.querySelector(".checkbox-icon").innerHTML=this.indeterminate?'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/></svg>':'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>',this.setupEventListeners(),this.applyLabelName(n),this.updateValidity()}updateValidity(){const t=this.shadowRoot?.querySelector(".checkbox-container");this.disabled?this.v.setValidity({}):this.required&&!this.checked?this.v.setValidity({valueMissing:!0},"Please check this box",t??void 0):this.v.setValidity({})}get checked(){return this.getProperty("checked")}set checked(t){this.setProperty("checked",t)}get indeterminate(){return this.getProperty("indeterminate")}set indeterminate(t){this.setProperty("indeterminate",t)}get value(){return this.getProperty("value")}set value(t){this.setProperty("value",t)}get name(){return this.getProperty("name")}set name(t){this.setProperty("name",t)}get disabled(){return this.getProperty("disabled")}set disabled(t){this.setProperty("disabled",t)}get required(){return this.getProperty("required")}set required(t){this.setProperty("required",t)}get size(){return this.getProperty("size")}set size(t){this.setProperty("size",t)}get flavor(){return this.getProperty("flavor")}set flavor(t){this.setProperty("flavor",t)}get form(){return this.v.form}};it.formAssociated=!0,it.properties={checked:{type:"boolean",visual:!0,formValue:!0,emitChange:!0,default:!1},indeterminate:{type:"boolean",visual:!0,default:!1},value:{type:"string",default:"on"},name:{type:"string",default:""},disabled:{type:"boolean",visual:!0,default:!1},required:{type:"boolean",visual:!0,default:!1},size:{type:"string",visual:!0,default:"md",validate:t=>["xs","sm","md","lg","xl"].includes(t),coerce:t=>["xs","sm","md","lg","xl"].includes(t)?t:"md"},flavor:{type:"string",visual:!0,default:"neutral"}};let ot=it;customElements.get("ty-checkbox")||customElements.define("ty-checkbox",ot);const st=(t,n)=>{const e=e=>n?`var(--ty-color-${t}${e}, var(--ty-color-${n}${e}))`:`var(--ty-color-${t}${e})`;return`\n:host([flavor="${t}"]) { --switch-track: ${e("")}; }\n:host([flavor="${t}+"]) { --switch-track: ${e("-strong")}; }\n:host([flavor="${t}-"]) { --switch-track: ${e("-soft")}; }\n`},rt=`\n${U}\n\n/* Override input's :host so the switch sizes to its visual */\n:host {\n display: inline-flex;\n width: auto;\n vertical-align: middle;\n}\n\n/* ===== SWITCH CONTAINER (just the visual) ===== */\n.switch-container {\n display: inline-block;\n cursor: pointer;\n user-select: none;\n outline: none;\n vertical-align: middle;\n}\n\n.switch-container.disabled {\n cursor: not-allowed;\n opacity: 0.55;\n}\n\n.switch-container:focus-visible .switch-track,\n.switch-container.focused .switch-track {\n box-shadow: 0 0 0 3px var(--ty-input-shadow-focus);\n}\n\n/* ===== TRACK ===== */\n.switch-track {\n position: relative;\n flex-shrink: 0;\n width: 36px;\n height: 20px;\n border-radius: 999px;\n background: var(--ty-color-neutral-soft, var(--ty-input-border));\n transition: background-color 0.18s ease-in-out;\n box-sizing: border-box;\n}\n\n/* ===== THUMB ===== */\n.switch-thumb {\n position: absolute;\n top: 2px;\n left: 2px;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n background: white;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n transition: transform 0.18s ease-in-out, background-color 0.18s ease-in-out;\n}\n\n/* ===== CHECKED STATE ===== */\n/* Default (no flavor attribute) is primary — defaults don't reflect to the\n host attribute, so the base rule's fallback carries the default look. */\n.switch-container[aria-checked="true"] .switch-track {\n background: var(--switch-track, var(--ty-color-primary));\n}\n\n.switch-container[aria-checked="true"] .switch-thumb {\n transform: translateX(16px);\n}\n\n/* ===== SIZE VARIANTS ===== */\n.switch-container.xs .switch-track { width: 26px; height: 14px; }\n.switch-container.xs .switch-thumb { width: 10px; height: 10px; }\n.switch-container.xs[aria-checked="true"] .switch-thumb { transform: translateX(12px); }\n\n.switch-container.sm .switch-track { width: 30px; height: 16px; }\n.switch-container.sm .switch-thumb { width: 12px; height: 12px; }\n.switch-container.sm[aria-checked="true"] .switch-thumb { transform: translateX(14px); }\n\n/* md is default — already set above */\n\n.switch-container.lg .switch-track { width: 44px; height: 24px; }\n.switch-container.lg .switch-thumb { width: 20px; height: 20px; }\n.switch-container.lg[aria-checked="true"] .switch-thumb { transform: translateX(20px); }\n\n.switch-container.xl .switch-track { width: 52px; height: 28px; }\n.switch-container.xl .switch-thumb { width: 24px; height: 24px; }\n.switch-container.xl[aria-checked="true"] .switch-thumb { transform: translateX(24px); }\n\n/* ===== FLAVOR VARIANTS (set --switch-track, consumed above) ===== */\n${r.map(t=>st(t)).join("")}\n\n`,at=class extends i{constructor(){super(),this.I=null,this.W=!1,this.tt=null,this.nt=null,this.G=null,this.K=null,s(this.shadowRoot,{css:rt,id:"ty-switch"})}onConnect(){this.setupEventListeners(),this.D()}onDisconnect(){this.removeEventListeners()}onPropertiesChanged(t){t.some(t=>"flavor"===t.name)&&this.D()}D(){this.I=u(this.shadowRoot,this.I,this.flavor,({base:t})=>(t=>st(t,"neutral"))(t))}getFormValue(){return this.checked?this.value:null}buildClassList(){const t=[this.size];return this.disabled&&t.push("disabled"),this.required&&t.push("required"),t.join(" ")}handleSwitchClick(t){if(this.disabled)return;const n=!this.checked;this.checked=n,setTimeout(()=>{const e={value:n,checked:n,formValue:n?this.value:null,originalEvent:t};this.dispatchEvent(new CustomEvent("input",{detail:e,bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("change",{detail:e,bubbles:!0,composed:!0}))},0)}handleSwitchKeydown(t){this.disabled||["Space"," ","Enter"].includes(t.key)&&(t.preventDefault(),t.stopPropagation(),this.handleSwitchClick(t))}removeEventListeners(){if(!this.W)return;this.tt&&(this.removeEventListener("click",this.tt),this.tt=null);const t=this.shadowRoot;if(!t)return;const n=t.querySelector(".switch-container");n?(this.nt&&(n.removeEventListener("keydown",this.nt),this.nt=null),this.G&&(n.removeEventListener("focus",this.G),this.G=null),this.K&&(n.removeEventListener("blur",this.K),this.K=null),this.W=!1):this.W=!1}setupEventListeners(){if(this.W)return;const t=this.shadowRoot.querySelector(".switch-container");t&&(this.tt=t=>this.handleSwitchClick(t),this.nt=t=>this.handleSwitchKeydown(t),this.G=()=>t.classList.add("focused"),this.K=()=>t.classList.remove("focused"),this.addEventListener("click",this.tt),t.addEventListener("keydown",this.nt),t.addEventListener("focus",this.G),t.addEventListener("blur",this.K),this.W=!0)}render(){const t=this.shadowRoot;let n=t.querySelector(".switch-container");const e=this.buildClassList();if(n)n.className="switch-container "+e,n.tabIndex=this.disabled?-1:0,n.setAttribute("aria-checked",this.checked?"true":"false"),n.setAttribute("aria-disabled",this.disabled?"true":"false"),n.setAttribute("aria-required",this.required?"true":"false");else{n=document.createElement("div"),n.className="switch-container "+e,n.tabIndex=this.disabled?-1:0,n.setAttribute("role","switch"),n.setAttribute("aria-checked",this.checked?"true":"false"),n.setAttribute("aria-disabled",this.disabled?"true":"false"),n.setAttribute("aria-required",this.required?"true":"false");const i=document.createElement("div");i.className="switch-track";const o=document.createElement("div");o.className="switch-thumb",i.appendChild(o),n.appendChild(i),t.appendChild(n)}this.setupEventListeners(),this.applyLabelName(n),this.updateValidity()}updateValidity(){const t=this.shadowRoot?.querySelector(".switch-container");this.disabled?this.v.setValidity({}):this.required&&!this.checked?this.v.setValidity({valueMissing:!0},"Please turn this on",t??void 0):this.v.setValidity({})}get checked(){return this.getProperty("checked")}set checked(t){this.setProperty("checked",t)}get value(){return this.getProperty("value")}set value(t){this.setProperty("value",t)}get name(){return this.getProperty("name")}set name(t){this.setProperty("name",t)}get disabled(){return this.getProperty("disabled")}set disabled(t){this.setProperty("disabled",t)}get required(){return this.getProperty("required")}set required(t){this.setProperty("required",t)}get size(){return this.getProperty("size")}set size(t){this.setProperty("size",t)}get flavor(){return this.getProperty("flavor")}set flavor(t){this.setProperty("flavor",t)}get form(){return this.v.form}};at.formAssociated=!0,at.properties={checked:{type:"boolean",visual:!0,formValue:!0,emitChange:!0,default:!1},value:{type:"string",default:"on"},name:{type:"string",default:""},disabled:{type:"boolean",visual:!0,default:!1},required:{type:"boolean",visual:!0,default:!1},size:{type:"string",visual:!0,default:"md",validate:t=>["xs","sm","md","lg","xl"].includes(t),coerce:t=>["xs","sm","md","lg","xl"].includes(t)?t:"md"},flavor:{type:"string",visual:!0,default:"primary"}};let lt=at;customElements.get("ty-switch")||customElements.define("ty-switch",lt);const ct=(t,n)=>{const e=e=>n?`var(--ty-color-${t}${e}, var(--ty-color-${n}${e}))`:`var(--ty-color-${t}${e})`;return`\n:host([flavor="${t}"]) { --radio-color: ${e("")}; }\n:host([flavor="${t}+"]) { --radio-color: ${e("-strong")}; }\n:host([flavor="${t}-"]) { --radio-color: ${e("-soft")}; }\n`},dt=`\n${U}\n\n/* Override input's :host. ty-radio is just the circle (inline);\n ty-radio-group is a form-field block. */\n:host(ty-radio) {\n display: inline-flex;\n width: auto;\n vertical-align: middle;\n}\n\n:host(ty-radio-group) {\n display: block;\n width: 100%;\n}\n\n/* ===== RADIO GROUP ===== */\n.radio-group-container {\n display: flex;\n flex-direction: column;\n gap: 0.4rem;\n font-family: var(--ty-font-sans);\n color: var(--ty-color-text);\n}\n\n.radio-group-label {\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n font-weight: var(--ty-font-medium);\n color: var(--ty-color-text);\n display: flex;\n align-items: center;\n gap: 0.25rem;\n}\n\n.radio-group-list {\n display: flex;\n gap: 0.6rem;\n align-items: flex-start;\n}\n\n.radio-group-list.vertical {\n flex-direction: column;\n align-items: flex-start;\n}\n\n.radio-group-list.horizontal {\n flex-direction: row;\n flex-wrap: wrap;\n align-items: center;\n}\n\n.radio-group-error {\n font-size: var(--ty-font-xs);\n line-height: var(--ty-leading-xs);\n color: var(--ty-color-danger);\n}\n\n.radio-group-container .required-icon {\n width: 0.65em;\n height: 0.65em;\n color: var(--ty-color-danger);\n}\n.radio-group-container .required-icon svg {\n width: 100%;\n height: 100%;\n}\n\n/* ===== RADIO ITEM (just the circle) ===== */\n.radio-container {\n display: inline-block;\n cursor: pointer;\n user-select: none;\n outline: none;\n vertical-align: middle;\n}\n\n.radio-container.disabled {\n cursor: not-allowed;\n opacity: 0.55;\n}\n\n.radio-container:focus-visible .radio-circle,\n.radio-container.focused .radio-circle {\n box-shadow: 0 0 0 3px var(--ty-input-shadow-focus);\n}\n\n.radio-circle {\n position: relative;\n flex-shrink: 0;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n border: 2px solid var(--ty-input-border);\n background: var(--ty-input-bg);\n box-sizing: border-box;\n transition: border-color 0.15s ease-in-out;\n}\n\n/* Default (no flavor attribute) is primary — defaults don't reflect to the\n host attribute, so the base rules' fallback carries the default look. */\n.radio-circle::after {\n content: "";\n position: absolute;\n top: 50%;\n left: 50%;\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: var(--radio-color, var(--ty-color-primary));\n transform: translate(-50%, -50%) scale(0);\n transition: transform 0.15s ease-in-out;\n}\n\n.radio-container[aria-checked="true"] .radio-circle {\n border-color: var(--radio-color, var(--ty-color-primary));\n}\n\n.radio-container[aria-checked="true"] .radio-circle::after {\n transform: translate(-50%, -50%) scale(1);\n}\n\n/* Size variants */\n.radio-container.xs .radio-circle { width: 14px; height: 14px; }\n.radio-container.xs .radio-circle::after { width: 6px; height: 6px; }\n\n.radio-container.sm .radio-circle { width: 16px; height: 16px; }\n.radio-container.sm .radio-circle::after { width: 7px; height: 7px; }\n\n.radio-container.lg .radio-circle { width: 22px; height: 22px; }\n.radio-container.lg .radio-circle::after { width: 10px; height: 10px; }\n\n.radio-container.xl .radio-circle { width: 26px; height: 26px; }\n.radio-container.xl .radio-circle::after { width: 12px; height: 12px; }\n\n/* Flavor variants — set --radio-color, consumed by the base rules above */\n${r.map(t=>ct(t)).join("")}\n`,ht=class extends i{constructor(){super(),this.I=null,this.W=!1,this.tt=null,this.G=null,this.K=null,s(this.shadowRoot,{css:dt,id:"ty-radio"})}onConnect(){this.setupEventListeners(),this.dispatchEvent(new CustomEvent("ty-radio-connected",{bubbles:!0})),this.D()}onDisconnect(){this.removeEventListeners()}onPropertiesChanged(t){t.some(t=>"flavor"===t.name)&&this.D()}D(){this.I=u(this.shadowRoot,this.I,this.flavor,({base:t})=>(t=>ct(t,"neutral"))(t))}buildClassList(){const t=[this.size];return this.disabled&&t.push("disabled"),t.join(" ")}handleClick(t){this.disabled||(t.stopPropagation(),this.dispatchEvent(new CustomEvent("ty-radio-select",{detail:{value:this.value},bubbles:!0,composed:!0})))}removeEventListeners(){if(!this.W)return;this.tt&&(this.removeEventListener("click",this.tt),this.tt=null);const t=this.shadowRoot?.querySelector(".radio-container");t?(this.G&&(t.removeEventListener("focus",this.G),this.G=null),this.K&&(t.removeEventListener("blur",this.K),this.K=null),this.W=!1):this.W=!1}setupEventListeners(){if(this.W)return;const t=this.shadowRoot.querySelector(".radio-container");t&&(this.tt=t=>this.handleClick(t),this.G=()=>t.classList.add("focused"),this.K=()=>t.classList.remove("focused"),this.addEventListener("click",this.tt),t.addEventListener("focus",this.G),t.addEventListener("blur",this.K),this.W=!0)}render(){const t=this.shadowRoot;let n=t.querySelector(".radio-container");const e=this.buildClassList();if(n)n.className="radio-container "+e,n.tabIndex=this.disabled?-1:0,n.setAttribute("aria-checked",this.checked+""),n.setAttribute("aria-disabled",this.disabled+"");else{n=document.createElement("div"),n.className="radio-container "+e,n.tabIndex=this.disabled?-1:0,n.setAttribute("role","radio"),n.setAttribute("aria-checked",this.checked+""),n.setAttribute("aria-disabled",this.disabled+"");const i=document.createElement("div");i.className="radio-circle",n.appendChild(i),t.appendChild(n)}this.setupEventListeners(),this.applyLabelName(n)}get value(){return this.getProperty("value")}set value(t){this.setProperty("value",t)}get checked(){return this.getProperty("checked")}set checked(t){this.setProperty("checked",t)}get disabled(){return this.getProperty("disabled")}set disabled(t){this.setProperty("disabled",t)}get size(){return this.getProperty("size")}set size(t){this.setProperty("size",t)}get flavor(){return this.getProperty("flavor")}set flavor(t){this.setProperty("flavor",t)}};ht.properties={value:{type:"string",default:""},checked:{type:"boolean",visual:!0,default:!1},disabled:{type:"boolean",visual:!0,default:!1},size:{type:"string",visual:!0,default:"md"},flavor:{type:"string",visual:!0,default:"primary"}};let ut=ht;customElements.get("ty-radio")||customElements.define("ty-radio",ut);const pt=class extends i{constructor(){super(),this.W=!1,this.et=null,this.nt=null,this.it=null,s(this.shadowRoot,{css:dt,id:"ty-radio-group"})}onConnect(){this.setupEventListeners(),queueMicrotask(()=>this.syncChildren())}onDisconnect(){this.removeEventListeners()}onPropertiesChanged(t){t.some(t=>"value"===t.name||"size"===t.name||"flavor"===t.name||"disabled"===t.name)&&this.syncChildren()}getFormValue(){return this.value||null}getRadios(){return Array.from(this.querySelectorAll("ty-radio"))}syncChildren(){const t=this.getRadios();for(const n of t)n.checked=n.value===this.value,this.disabled&&(n.disabled=!0),n.size=this.size,n.flavor=this.flavor}handleRadioSelect(t){if(this.disabled)return;const n=t.detail,e=n?.value;"string"==typeof e&&e!==this.value&&(this.value=e,this.syncChildren(),setTimeout(()=>{const n={value:e,formValue:e,originalEvent:t};this.dispatchEvent(new CustomEvent("input",{detail:n,bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("change",{detail:n,bubbles:!0,composed:!0}))},0))}handleKeydown(t){if(this.disabled)return;const n=this.getRadios().filter(t=>!t.disabled);if(0===n.length)return;const e=document.activeElement,i=n.find(t=>t===e||t.contains(e));let o=-1;if(["ArrowDown","ArrowRight"].includes(t.key))t.preventDefault(),o=i?(n.indexOf(i)+1)%n.length:0;else{if(!["ArrowUp","ArrowLeft"].includes(t.key)){if(["Space"," ","Enter"].includes(t.key)){if(i){t.preventDefault(),this.value=i.value,this.syncChildren();const n={value:i.value,formValue:i.value,originalEvent:t};setTimeout(()=>{this.dispatchEvent(new CustomEvent("change",{detail:n,bubbles:!0,composed:!0}))},0)}return}return}t.preventDefault(),o=i?(n.indexOf(i)-1+n.length)%n.length:n.length-1}const s=n[o];if(s){s.focus(),this.value=s.value,this.syncChildren();const n={value:s.value,formValue:s.value,originalEvent:t};setTimeout(()=>{this.dispatchEvent(new CustomEvent("change",{detail:n,bubbles:!0,composed:!0}))},0)}}removeEventListeners(){this.W&&(this.et&&(this.removeEventListener("ty-radio-select",this.et),this.et=null),this.nt&&(this.removeEventListener("keydown",this.nt),this.nt=null),this.it&&(this.removeEventListener("ty-radio-connected",this.it),this.it=null),this.W=!1)}setupEventListeners(){this.W||(this.et=t=>this.handleRadioSelect(t),this.nt=t=>this.handleKeydown(t),this.it=()=>this.syncChildren(),this.addEventListener("ty-radio-select",this.et),this.addEventListener("keydown",this.nt),this.addEventListener("ty-radio-connected",this.it),this.W=!0)}render(){const t=this.shadowRoot;let n=t.querySelector(".radio-group-container");if(n){let t=n.querySelector(".radio-group-label");if(this.label)if(t||(t=document.createElement("div"),t.className="radio-group-label",n.insertBefore(t,n.firstChild)),t.textContent=this.label,this.required&&!t.querySelector(".required-icon")){const n=document.createElement("span");n.className="required-icon",n.innerHTML=X,t.appendChild(n)}else this.required||t.querySelector(".required-icon")?.remove();else t&&t.remove();const e=n.querySelector(".radio-group-list");e&&(e.className="radio-group-list "+this.orientation);let i=n.querySelector(".radio-group-error");this.error?(i||(i=document.createElement("div"),i.className="radio-group-error",n.appendChild(i)),i.textContent=this.error):i&&i.remove(),n.setAttribute("aria-disabled",this.disabled+"")}else{if(n=document.createElement("div"),n.className="radio-group-container",n.setAttribute("role","radiogroup"),n.setAttribute("aria-disabled",this.disabled+""),this.label){const t=document.createElement("div");if(t.className="radio-group-label",t.textContent=this.label,this.required){const n=document.createElement("span");n.className="required-icon",n.innerHTML=X,t.appendChild(n)}n.appendChild(t)}const e=document.createElement("div");e.className="radio-group-list "+this.orientation;const i=document.createElement("slot");if(e.appendChild(i),n.appendChild(e),this.error){const t=document.createElement("div");t.className="radio-group-error",t.textContent=this.error,n.appendChild(t)}t.appendChild(n),this.setupEventListeners()}this.syncChildren()}get value(){return this.getProperty("value")}set value(t){this.setProperty("value",t)}get name(){return this.getProperty("name")}set name(t){this.setProperty("name",t)}get label(){return this.getProperty("label")}set label(t){this.setProperty("label",t)}get disabled(){return this.getProperty("disabled")}set disabled(t){this.setProperty("disabled",t)}get required(){return this.getProperty("required")}set required(t){this.setProperty("required",t)}get error(){return this.getProperty("error")}set error(t){this.setProperty("error",t)}get orientation(){return this.getProperty("orientation")}set orientation(t){this.setProperty("orientation",t)}get size(){return this.getProperty("size")}set size(t){this.setProperty("size",t)}get flavor(){return this.getProperty("flavor")}set flavor(t){this.setProperty("flavor",t)}get form(){return this.v.form}};pt.formAssociated=!0,pt.properties={value:{type:"string",visual:!0,formValue:!0,emitChange:!0,default:""},name:{type:"string",default:""},label:{type:"string",visual:!0,default:""},disabled:{type:"boolean",visual:!0,default:!1},required:{type:"boolean",visual:!0,default:!1},error:{type:"string",visual:!0,default:""},orientation:{type:"string",visual:!0,default:"vertical"},size:{type:"string",visual:!0,default:"md"},flavor:{type:"string",visual:!0,default:"primary"}};let bt=pt;customElements.get("ty-radio-group")||customElements.define("ty-radio-group",bt);const gt=(t,n)=>{const e=e=>n?`var(--ty-color-${t}${e}, var(--ty-color-${n}${e}))`:`var(--ty-color-${t}${e})`,i=e=>n?`var(--ty-bg-${t}${e}, var(--ty-bg-${n}${e}))`:`var(--ty-bg-${t}${e})`;return`\n:host([flavor="${t}"]) { --copy-color: ${e("")}; --copy-color-hover: ${e("-strong")}; --copy-bg-hover: ${i("-soft")}; }\n:host([flavor="${t}+"]) { --copy-color: ${e("-strong")}; --copy-color-hover: ${e("-strong")}; --copy-bg-hover: ${i("-soft")}; }\n:host([flavor="${t}-"]) { --copy-color: ${e("-soft")}; --copy-color-hover: ${e("")}; --copy-bg-hover: ${i("-soft")}; }\n`},mt=`\n/* Copy field value display */\n.copy-field-value {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n user-select: none;\n padding: 0;\n margin: 0;\n background: transparent;\n border: none;\n color: inherit;\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\n/* Multiline variant */\n.copy-field-value.multiline {\n white-space: pre-wrap;\n word-break: break-word;\n max-height: 200px;\n overflow-y: auto;\n}\n\n/* Keep the copy button pinned to the top-right when content wraps to multiple lines */\n.input-wrapper:has(.copy-field-value.multiline) {\n align-items: flex-start;\n padding-top: 8px;\n padding-bottom: 8px;\n}\n\n/* Horizontal scroll variant - scroll long content instead of clipping with ellipsis */\n.copy-field-value.horizontal-scroll {\n overflow-x: auto;\n overflow-y: hidden;\n text-overflow: clip;\n white-space: nowrap;\n}\n\n/* Multiline + horizontal scroll (e.g. code blocks): preserve lines, scroll both axes */\n.copy-field-value.multiline.horizontal-scroll {\n white-space: pre;\n word-break: normal;\n overflow-y: auto;\n}\n\n/* Hide scrollbars on scrollable value - content still scrolls, chrome stays clean */\n.copy-field-value.multiline,\n.copy-field-value.horizontal-scroll {\n scrollbar-width: none; /* Firefox */\n}\n.copy-field-value.multiline::-webkit-scrollbar,\n.copy-field-value.horizontal-scroll::-webkit-scrollbar {\n display: none; /* Chrome/Safari */\n}\n\n/* Code format */\n.copy-field-value {\n font-size: 0.8em;\n}\n\n/* Hover state — flavor-soft background (primary by default) */\n.input-wrapper:not(.disabled):hover {\n background: var(--copy-bg-hover, var(--ty-bg-primary-soft));\n transition: background 0.2s ease;\n}\n\n/* Copy button */\n.copy-button {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n cursor: pointer;\n border: none;\n background: transparent;\n color: var(--copy-color, var(--ty-text-soft));\n transition: color 0.2s ease, transform 0.2s ease;\n padding: 0;\n margin: 0;\n}\n\n.copy-button:hover:not(.disabled) {\n color: var(--copy-color-hover, var(--ty-text));\n transform: scale(1.1);\n}\n\n.copy-button.success {\n color: var(--ty-color-success);\n animation: copy-feedback 0.3s ease;\n}\n\n.copy-button.error {\n color: var(--ty-color-danger);\n animation: copy-feedback 0.3s ease;\n}\n\n@keyframes copy-feedback {\n 0%, 100% { transform: scale(1); }\n 50% { transform: scale(1.2); }\n}\n\n.copy-button svg {\n width: 18px;\n height: 18px;\n}\n\n.input-wrapper.disabled .copy-button {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n.input-wrapper.disabled {\n cursor: not-allowed;\n}\n\n/* ===== SEMANTIC FLAVORS (set --copy-*, consumed above) ===== */\n${r.map(t=>gt(t)).join("")}\n`,vt='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>',ft='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>',yt=class extends i{constructor(){super(),this.ot=null,this.st=!1,this.I=null,s(this.shadowRoot,{css:U,id:"ty-input"}),s(this.shadowRoot,{css:mt,id:"ty-copy"})}onConnect(){this.D()}D(){this.I=u(this.shadowRoot,this.I,this.flavor,({base:t})=>(t=>gt(t,"neutral"))(t))}onDisconnect(){null!==this.ot&&(clearTimeout(this.ot),this.ot=null)}onPropertiesChanged(t){t.some(t=>"flavor"===t.name)&&this.D()}buildClassList(){const t=[this.size];return this.disabled&&t.push("disabled"),this.required&&t.push("required"),t.join(" ")}async copyToClipboard(){if(!this.disabled&&this.value){try{await navigator.clipboard.writeText(this.value),this.dispatchEvent(new CustomEvent("copy-success",{detail:{value:this.value},bubbles:!0,composed:!0}))}catch(t){try{const t=document.createElement("textarea");t.value=this.value,t.style.position="fixed",t.style.opacity="0",document.body.appendChild(t),t.select(),document.execCommand("copy"),document.body.removeChild(t),this.dispatchEvent(new CustomEvent("copy-success",{detail:{value:this.value},bubbles:!0,composed:!0}))}catch(n){return this.dispatchEvent(new CustomEvent("copy-error",{detail:{error:n},bubbles:!0,composed:!0})),void this.showCopyError()}}this.showCopySuccess()}}showCopySuccess(){null!==this.ot&&clearTimeout(this.ot),this.st=!0;const t=this.shadowRoot.querySelector(".copy-button");t&&(t.classList.add("success"),t.innerHTML=ft,t.setAttribute("aria-label","Copied!")),this.ot=window.setTimeout(()=>{this.st=!1;const t=this.shadowRoot.querySelector(".copy-button");t&&(t.classList.remove("success"),t.innerHTML=vt,t.setAttribute("aria-label","Copy to clipboard")),this.ot=null},2e3)}showCopyError(){null!==this.ot&&clearTimeout(this.ot),this.st=!1;const t=this.shadowRoot.querySelector(".copy-button");t&&(t.classList.add("error"),t.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>',t.setAttribute("aria-label","Copy failed")),this.ot=window.setTimeout(()=>{const t=this.shadowRoot.querySelector(".copy-button");t&&(t.classList.remove("error"),t.innerHTML=vt,t.setAttribute("aria-label","Copy to clipboard")),this.ot=null},2e3)}setupEventListeners(){const t=this.shadowRoot,n=t.querySelector(".input-wrapper"),e=t.querySelector(".copy-button");if(n&&!this.disabled){const t=n;t.addEventListener("click",t=>{t.target===e||t.target.closest(".copy-button")||this.copyToClipboard()}),t.style.cursor="pointer"}e&&e.addEventListener("click",()=>{this.copyToClipboard()})}render(){const t=this.shadowRoot,n=this.buildClassList(),e=["copy-field-value",this.multiline?"multiline":"",this.horizontalScroll?"horizontal-scroll":""].filter(Boolean).join(" ");t.innerHTML=`\n <div class="input-container">\n ${this.label?`\n <label class="ty-field-label">\n ${this.label}\n ${this.required?`<span class="required-icon">${X}</span>`:""}\n </label>\n `:""}\n <div class="input-wrapper ${n}">\n ${"code"===this.format?`<code class="${e}">${this.value||""}</code>`:`<div class="${e}">${this.value||""}</div>`}\n <button class="copy-button${this.st?" success":""}" type="button" aria-label="${this.st?"Copied!":"Copy to clipboard"}" ${this.disabled?"disabled":""}>\n ${this.st?ft:vt}\n </button>\n </div>\n </div>\n `,this.setupEventListeners()}get value(){return this.getProperty("value")}set value(t){this.setProperty("value",t)}get label(){return this.getProperty("label")}set label(t){this.setProperty("label",t)}get size(){return this.getProperty("size")}set size(t){this.setProperty("size",t)}get flavor(){return this.getProperty("flavor")}set flavor(t){this.setProperty("flavor",t)}get format(){return this.getProperty("format")}set format(t){this.setProperty("format",t)}get multiline(){return this.getProperty("multiline")}set multiline(t){this.setProperty("multiline",t)}get horizontalScroll(){return this.getProperty("horizontalScroll")}set horizontalScroll(t){this.setProperty("horizontalScroll",t)}get disabled(){return this.getProperty("disabled")}set disabled(t){this.setProperty("disabled",t)}get required(){return this.getProperty("required")}set required(t){this.setProperty("required",t)}};yt.formAssociated=!0,yt.properties={value:{type:"string",visual:!0,formValue:!0,default:""},label:{type:"string",visual:!0,default:""},size:{type:"string",visual:!0,default:"md",validate:t=>["xs","sm","md","lg","xl"].includes(t),coerce:t=>["xs","sm","md","lg","xl"].includes(t)?t:"md"},flavor:{type:"string",visual:!0,default:"neutral"},format:{type:"string",visual:!0,default:"text",coerce:t=>"code"===t?"code":"text"},multiline:{type:"boolean",visual:!0,default:!1},horizontalScroll:{type:"boolean",visual:!0,default:!1},disabled:{type:"boolean",visual:!0,default:!1},required:{type:"boolean",visual:!0,default:!1}};let wt=yt;function xt(t){return 1024>t?t+" B":1048576>t?(t/1024).toFixed(1)+" KB":1073741824>t?(t/1024/1024).toFixed(1)+" MB":(t/1024/1024/1024).toFixed(1)+" GB"}customElements.get("ty-copy")||customElements.define("ty-copy",wt),customElements.get("ty-copy-field")||customElements.define("ty-copy-field",class extends wt{});const kt=class extends i{constructor(){super(),this.rt=[],this.lt=!1,this.W=!1,this.ct=null,this.dt=null,this.ht=null,this.ut=null,this.bt=null,this.gt=null,this.vt=null,this.ft=null,s(this.shadowRoot,{css:"\n:host {\n display: block;\n font-family: var(--ty-font-sans);\n width: 100%;\n}\n\n.file-upload-container {\n display: flex;\n flex-direction: column;\n width: 100%;\n box-sizing: border-box;\n}\n\n/* ===== LABEL ===== */\n\n.upload-label {\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n font-weight: var(--ty-font-medium);\n color: var(--ty-label-color);\n margin-bottom: 6px;\n padding-left: 4px;\n display: flex;\n align-items: center;\n}\n\n.required-icon {\n color: var(--ty-color-danger);\n margin-left: 4px;\n font-size: 0.75rem;\n line-height: 1;\n}\n\n/* ===== DROP ZONE ===== */\n\n.drop-zone {\n border: 2px dashed var(--ty-border);\n border-radius: var(--ty-radius-base);\n padding: 2rem 1.5rem;\n text-align: center;\n cursor: pointer;\n transition: border-color 0.15s ease, background-color 0.15s ease, box-shadow 0.15s ease;\n outline: none;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n min-height: 140px;\n user-select: none;\n}\n\n.drop-zone:hover:not(.disabled) {\n border-color: var(--ty-input-border-hover);\n background: var(--ty-surface-content);\n}\n\n.drop-zone.focused {\n border-color: var(--ty-input-border-focus);\n box-shadow: 0 0 0 3px var(--ty-input-shadow-focus);\n}\n\n.drop-zone.drag-active {\n border-color: var(--ty-color-primary);\n border-style: solid;\n background: var(--ty-bg-primary-);\n}\n\n.drop-zone.drag-active .upload-icon {\n color: var(--ty-color-primary);\n transform: translateY(-2px);\n}\n\n.drop-zone.has-files {\n min-height: 80px;\n padding: 1.25rem 1.5rem;\n}\n\n.drop-zone.disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n}\n\n.drop-zone.error {\n border-color: var(--ty-color-danger);\n}\n\n.drop-zone.error:not(.disabled) {\n background: var(--ty-bg-danger-);\n}\n\n/* ===== UPLOAD ICON ===== */\n\n.upload-icon {\n color: var(--ty-text-faint);\n width: 2.5rem;\n height: 2.5rem;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: color 0.15s ease, transform 0.15s ease;\n pointer-events: none;\n}\n\n.upload-icon svg {\n width: 100%;\n height: 100%;\n}\n\n/* ===== HINT TEXT ===== */\n\n.upload-hint {\n color: var(--ty-text-soft);\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n pointer-events: none;\n}\n\n.browse-link {\n color: var(--ty-color-primary);\n font-weight: var(--ty-font-medium);\n}\n\n.upload-sub-hint {\n color: var(--ty-text-faint);\n font-size: var(--ty-font-xs);\n line-height: var(--ty-leading-xs);\n pointer-events: none;\n}\n\n/* ===== FILE LIST ===== */\n\n.file-list {\n display: flex;\n flex-direction: column;\n gap: 0.375rem;\n margin-top: 0.5rem;\n}\n\n.file-item {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.5rem 0.75rem;\n border-radius: var(--ty-radius-base);\n background: var(--ty-surface-content);\n border: 1px solid var(--ty-border-soft);\n}\n\n.file-icon {\n color: var(--ty-text-faint);\n flex-shrink: 0;\n width: 1rem;\n height: 1rem;\n display: flex;\n align-items: center;\n}\n\n.file-icon svg {\n width: 100%;\n height: 100%;\n}\n\n.file-name {\n flex: 1;\n font-size: var(--ty-font-sm);\n color: var(--ty-text);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n min-width: 0;\n}\n\n.file-size {\n font-size: var(--ty-font-xs);\n color: var(--ty-text-faint);\n flex-shrink: 0;\n font-variant-numeric: tabular-nums;\n}\n\n.file-remove {\n flex-shrink: 0;\n cursor: pointer;\n color: var(--ty-text-faint);\n width: 1.25rem;\n height: 1.25rem;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n transition: color 0.15s ease, background-color 0.15s ease;\n border: none;\n background: none;\n padding: 0;\n outline: none;\n}\n\n.file-remove:hover {\n color: var(--ty-color-danger);\n background: var(--ty-bg-danger-);\n}\n\n.file-remove:focus-visible {\n box-shadow: 0 0 0 2px var(--ty-color-danger);\n}\n\n.file-remove svg {\n width: 12px;\n height: 12px;\n}\n\n/* ===== ERROR MESSAGE ===== */\n\n.error-message {\n font-size: var(--ty-font-xs);\n line-height: var(--ty-leading-xs);\n color: var(--ty-color-danger);\n margin-top: 4px;\n padding-left: 4px;\n}\n\n/* ===== ACCESSIBILITY ===== */\n\n@media (prefers-reduced-motion: reduce) {\n .drop-zone,\n .upload-icon,\n .file-remove {\n transition: none;\n }\n}\n\n@media (prefers-contrast: high) {\n .drop-zone {\n border-width: 3px;\n }\n}\n",id:"ty-file-upload"})}onConnect(){}onDisconnect(){this.removeEventListeners()}onPropertiesChanged(t){}onFormReset(){this.rt=[],this.updateFormValue(),this.p&&this.render();const t=this.shadowRoot?.querySelector(".file-input");t&&(t.value="")}getFormValue(){if(0===this.rt.length)return null;const t=new FormData,n=this.name||"files";for(const e of this.rt)t.append(n,e);return t}get files(){return[...this.rt]}get multiple(){return this.getProperty("multiple")}set multiple(t){this.setProperty("multiple",t)}get accept(){return this.getProperty("accept")}set accept(t){this.setProperty("accept",t)}get name(){return this.getProperty("name")}set name(t){this.setProperty("name",t)}get disabled(){return this.getProperty("disabled")}set disabled(t){this.setProperty("disabled",t)}get required(){return this.getProperty("required")}set required(t){this.setProperty("required",t)}get label(){return this.getProperty("label")}set label(t){this.setProperty("label",t)}get placeholder(){return this.getProperty("placeholder")}set placeholder(t){this.setProperty("placeholder",t)}get error(){return this.getProperty("error")}set error(t){this.setProperty("error",t)}get form(){return this.v.form}setFiles(t){this.rt=this.multiple?t:t.slice(0,1),this.updateFormValue(),this.render();const n={value:this.rt,files:this.rt,names:this.rt.map(t=>t.name)};setTimeout(()=>{this.dispatchEvent(new CustomEvent("change",{detail:n,bubbles:!0,composed:!0}))},0)}removeFile(t){const n=[...this.rt];n.splice(t,1),this.setFiles(n);const e=this.shadowRoot?.querySelector(".file-input");e&&(e.value="")}setupEventListeners(){if(this.W)return;const t=this.shadowRoot,n=t.querySelector(".drop-zone"),e=t.querySelector(".file-input");this.ct=t=>{this.disabled||t.target.closest(".file-remove")||e.click()},this.dt=t=>{this.disabled||"Enter"!==t.key&&" "!==t.key||(t.preventDefault(),e.click())},this.ht=()=>{n.classList.add("focused")},this.ut=()=>{n.classList.remove("focused")},this.bt=t=>{this.disabled||(t.preventDefault(),t.stopPropagation(),this.lt||(this.lt=!0,n.classList.add("drag-active")))},this.gt=t=>{n.contains(t.relatedTarget)||(this.lt=!1,n.classList.remove("drag-active"))},this.vt=t=>{if(this.disabled)return;t.preventDefault(),t.stopPropagation(),this.lt=!1,n.classList.remove("drag-active");const e=Array.from(t.dataTransfer?.files??[]);e.length>0&&this.setFiles(e)},this.ft=t=>{const n=t.target;n.files&&n.files.length>0&&this.setFiles(Array.from(n.files))},n.addEventListener("click",this.ct),n.addEventListener("keydown",this.dt),n.addEventListener("focus",this.ht),n.addEventListener("blur",this.ut),n.addEventListener("dragover",this.bt),n.addEventListener("dragleave",this.gt),n.addEventListener("drop",this.vt),e.addEventListener("change",this.ft),this.W=!0}removeEventListeners(){if(!this.W)return;const t=this.shadowRoot;if(!t)return;const n=t.querySelector(".drop-zone"),e=t.querySelector(".file-input");n&&e&&(this.ct&&n.removeEventListener("click",this.ct),this.dt&&n.removeEventListener("keydown",this.dt),this.ht&&n.removeEventListener("focus",this.ht),this.ut&&n.removeEventListener("blur",this.ut),this.bt&&n.removeEventListener("dragover",this.bt),this.gt&&n.removeEventListener("dragleave",this.gt),this.vt&&n.removeEventListener("drop",this.vt),this.ft&&e.removeEventListener("change",this.ft),this.W=!1)}buildDropZoneClasses(){const t=["drop-zone"];return this.lt&&t.push("drag-active"),this.rt.length>0&&t.push("has-files"),this.disabled&&t.push("disabled"),this.error&&t.push("error"),t.join(" ")}renderFileList(t){t.innerHTML="";for(let n=0;this.rt.length>n;n++){const e=this.rt[n],i=document.createElement("div");i.className="file-item";const o=document.createElement("span");o.className="file-icon",o.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>';const s=document.createElement("span");s.className="file-name",s.textContent=e.name,s.title=e.name;const r=document.createElement("span");r.className="file-size",r.textContent=xt(e.size);const a=document.createElement("button");a.className="file-remove",a.type="button",a.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>',a.setAttribute("aria-label","Remove "+e.name);const l=n;a.addEventListener("click",t=>{t.stopPropagation(),this.removeFile(l)}),i.appendChild(o),i.appendChild(s),i.appendChild(r),i.appendChild(a),t.appendChild(i)}}render(){const t=this.shadowRoot;let n=t.querySelector(".file-upload-container");if(!n){n=document.createElement("div"),n.className="file-upload-container";const e=document.createElement("div");e.className="upload-label",n.appendChild(e);const i=document.createElement("div");i.className="drop-zone",i.setAttribute("role","button");const o=document.createElement("input");o.type="file",o.className="file-input",o.style.display="none",i.appendChild(o);const s=document.createElement("div");s.className="upload-icon",s.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>',i.appendChild(s);const r=document.createElement("div");r.className="upload-hint",i.appendChild(r);const a=document.createElement("div");a.className="upload-sub-hint",i.appendChild(a),n.appendChild(i);const l=document.createElement("div");l.className="file-list",n.appendChild(l);const c=document.createElement("div");c.className="error-message",n.appendChild(c),t.appendChild(n),this.setupEventListeners()}const e=n.querySelector(".upload-label");if(this.label){if(e.style.display="",e.innerHTML="",e.appendChild(document.createTextNode(this.label)),this.required){const t=document.createElement("span");t.className="required-icon",t.textContent="*",t.setAttribute("aria-hidden","true"),e.appendChild(t)}}else e.style.display="none";const i=n.querySelector(".drop-zone");i.className=this.buildDropZoneClasses(),i.tabIndex=this.disabled?-1:0,i.setAttribute("aria-disabled",this.disabled+""),i.setAttribute("aria-label",this.placeholder||"Upload files");const o=n.querySelector(".file-input");o.multiple=this.multiple,o.accept=this.accept,o.disabled=this.disabled,n.querySelector(".upload-icon").style.display=this.rt.length>0?"none":"",n.querySelector(".upload-hint").innerHTML=this.rt.length>0?`<strong>${this.rt.length} file${1!==this.rt.length?"s":""} selected</strong>`:'Drop files here or <span class="browse-link">click to browse</span>';const s=n.querySelector(".upload-sub-hint");this.accept&&0===this.rt.length?(s.textContent="Accepted: "+this.accept,s.style.display=""):s.style.display="none";const r=n.querySelector(".file-list");this.renderFileList(r);const a=n.querySelector(".error-message");a.textContent=this.error,a.style.display=this.error?"":"none"}};kt.formAssociated=!0,kt.properties={multiple:{type:"boolean",visual:!0,default:!1},accept:{type:"string",visual:!0,default:""},name:{type:"string",default:""},disabled:{type:"boolean",visual:!0,default:!1},required:{type:"boolean",visual:!0,default:!1},label:{type:"string",visual:!0,default:""},placeholder:{type:"string",visual:!0,default:"Drop files here or click to browse"},error:{type:"string",visual:!0,default:""}};let zt=kt;function $t(){return"native"!==document.documentElement.getAttribute("data-ty-scrollbar")}customElements.get("ty-file-upload")||customElements.define("ty-file-upload",zt);class Ct{constructor(t,n={}){this.trackY=null,this.thumbY=null,this.trackX=null,this.thumbX=null,this.lt=!1,this.yt="y",this.wt=0,this.xt=0,this.kt=null,this.zt=null,this.$t=null,this.Ct=t,this.St=!1!==n.vertical,this.Et=n.horizontal??!1,this.Tt=n.autoHideDelay??1e3,this.Mt=this.At.bind(this),this.It=this.Dt.bind(this),this.Lt=this.Ot.bind(this),this.Nt=this.Rt.bind(this),this.qt=this.Vt.bind(this),this.Ft=this.Pt.bind(this),this.Ht=this.jt.bind(this),this.St&&(this.trackY=this.Bt("y"),this.thumbY=this.Wt("y"),this.trackY.appendChild(this.thumbY)),this.Et&&(this.trackX=this.Bt("x"),this.thumbX=this.Wt("x"),this.trackX.appendChild(this.thumbX)),this.Ct.addEventListener("scroll",this.Mt,{passive:!0}),this.thumbY&&this.thumbY.addEventListener("pointerdown",this.It),this.trackY&&this.trackY.addEventListener("pointerdown",this.Nt),this.thumbX&&this.thumbX.addEventListener("pointerdown",this.Lt),this.trackX&&this.trackX.addEventListener("pointerdown",this.qt),this.$t=new ResizeObserver(()=>this.update()),this.$t.observe(this.Ct),this.update()}Bt(t){const n=document.createElement("div");return n.className="ty-scrollbar-track-"+t,n}Wt(t){const n=document.createElement("div");return n.className="ty-scrollbar-thumb-"+t,n}update(){this._t(),this.Yt()}scrollToTop(t=!1){this.Ct.scrollTo({top:0,behavior:t?"smooth":"auto"})}scrollToBottom(t=!1){this.Ct.scrollTo({top:this.Ct.scrollHeight,behavior:t?"smooth":"auto"})}scrollToLeft(t=!1){this.Ct.scrollTo({left:0,behavior:t?"smooth":"auto"})}scrollToRight(t=!1){this.Ct.scrollTo({left:this.Ct.scrollWidth,behavior:t?"smooth":"auto"})}destroy(){this.Ct.removeEventListener("scroll",this.Mt),this.thumbY&&this.thumbY.removeEventListener("pointerdown",this.It),this.trackY&&this.trackY.removeEventListener("pointerdown",this.Nt),this.thumbX&&this.thumbX.removeEventListener("pointerdown",this.Lt),this.trackX&&this.trackX.removeEventListener("pointerdown",this.qt),this.$t&&(this.$t.disconnect(),this.$t=null),null!==this.kt&&(cancelAnimationFrame(this.kt),this.kt=null),null!==this.zt&&(clearTimeout(this.zt),this.zt=null)}At(){null===this.kt&&(this.kt=requestAnimationFrame(()=>{this.kt=null,this.Ut(),this.Gt()}))}_t(){if(!this.trackY||!this.thumbY)return;const{scrollHeight:t,clientHeight:n}=this.Ct,e=t>n+2;this.trackY.classList.toggle("has-overflow",e),e&&(this.thumbY.style.height=Math.max(n/t*100,0)+"%"),this.Kt()}Yt(){if(!this.trackX||!this.thumbX)return;const{scrollWidth:t,clientWidth:n}=this.Ct,e=t>n+2;this.trackX.classList.toggle("has-overflow",e),e&&(this.thumbX.style.width=Math.max(n/t*100,0)+"%"),this.Zt()}Ut(){this.Kt(),this.Zt()}Kt(){if(!this.trackY||!this.thumbY)return;const{scrollTop:t,scrollHeight:n,clientHeight:e}=this.Ct,i=n-e;i>0&&(this.thumbY.style.top=t/i*(this.trackY.clientHeight-this.thumbY.offsetHeight)+"px")}Zt(){if(!this.trackX||!this.thumbX)return;const{scrollLeft:t,scrollWidth:n,clientWidth:e}=this.Ct,i=n-e;i>0&&(this.thumbX.style.left=t/i*(this.trackX.clientWidth-this.thumbX.offsetWidth)+"px")}Gt(){this.lt||(this.trackY?.classList.add("scrolling"),this.trackX?.classList.add("scrolling"),null!==this.zt&&clearTimeout(this.zt),this.zt=setTimeout(()=>{this.trackY?.classList.remove("scrolling"),this.trackX?.classList.remove("scrolling"),this.zt=null},this.Tt))}Dt(t){0===t.button&&(t.preventDefault(),t.stopPropagation(),this.lt=!0,this.yt="y",this.wt=t.clientY,this.xt=this.Ct.scrollTop,this.thumbY.setPointerCapture(t.pointerId),this.trackY?.classList.add("dragging"),this.thumbY.addEventListener("pointermove",this.Ft),this.thumbY.addEventListener("pointerup",this.Ht),this.thumbY.addEventListener("pointercancel",this.Ht))}Ot(t){0===t.button&&(t.preventDefault(),t.stopPropagation(),this.lt=!0,this.yt="x",this.wt=t.clientX,this.xt=this.Ct.scrollLeft,this.thumbX.setPointerCapture(t.pointerId),this.trackX?.classList.add("dragging"),this.thumbX.addEventListener("pointermove",this.Ft),this.thumbX.addEventListener("pointerup",this.Ht),this.thumbX.addEventListener("pointercancel",this.Ht))}Pt(t){if(this.lt)if("y"===this.yt){const n=t.clientY-this.wt,{scrollHeight:e,clientHeight:i}=this.Ct,o=this.trackY.clientHeight-this.thumbY.offsetHeight;if(0>=o)return;this.Ct.scrollTop=this.xt+n*((e-i)/o)}else{const n=t.clientX-this.wt,{scrollWidth:e,clientWidth:i}=this.Ct,o=this.trackX.clientWidth-this.thumbX.offsetWidth;if(0>=o)return;this.Ct.scrollLeft=this.xt+n*((e-i)/o)}}jt(t){const n="y"===this.yt?this.thumbY:this.thumbX,e="y"===this.yt?this.trackY:this.trackX;this.lt=!1,n.releasePointerCapture(t.pointerId),e?.classList.remove("dragging"),n.removeEventListener("pointermove",this.Ft),n.removeEventListener("pointerup",this.Ht),n.removeEventListener("pointercancel",this.Ht),this.Gt()}Rt(t){if(t.target===this.thumbY||0!==t.button)return;t.preventDefault();const n=this.trackY.getBoundingClientRect(),e=(t.clientY-n.top)/n.height,{scrollHeight:i,clientHeight:o}=this.Ct;this.Ct.scrollTo({top:e*(i-o),behavior:"smooth"})}Vt(t){if(t.target===this.thumbX||0!==t.button)return;t.preventDefault();const n=this.trackX.getBoundingClientRect(),e=(t.clientX-n.left)/n.width,{scrollWidth:i,clientWidth:o}=this.Ct;this.Ct.scrollTo({left:e*(i-o),behavior:"smooth"})}}const St="\n/* ===================================== */\n/* Custom Scrollbar - Vertical Track */\n/* ===================================== */\n\n.ty-scrollbar-track-y {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n width: var(--ty-scrollbar-width, 8px);\n z-index: 3;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.25s ease-out;\n cursor: pointer;\n}\n\n.ty-scrollbar-track-y.has-overflow {\n pointer-events: auto;\n}\n\n.ty-scrollbar-track-y.has-overflow:hover,\n.ty-scrollbar-track-y.has-overflow.scrolling,\n.ty-scrollbar-track-y.dragging {\n opacity: 1;\n}\n\n.ty-scrollbar-track-y::before {\n content: '';\n position: absolute;\n inset: 0;\n background: var(--ty-scrollbar-track, transparent);\n border-radius: var(--ty-scrollbar-radius, 4px);\n opacity: 0;\n transition: opacity 0.15s ease-out;\n}\n\n.ty-scrollbar-track-y:hover::before,\n.ty-scrollbar-track-y.dragging::before {\n opacity: 1;\n background: var(--ty-scrollbar-track-hover, color-mix(in oklab, var(--ty-color-neutral-bold) 8%, transparent));\n}\n\n.ty-scrollbar-thumb-y {\n position: absolute;\n right: 0;\n width: 100%;\n min-height: var(--ty-scrollbar-thumb-min-height, 30px);\n background: var(--ty-scrollbar-thumb, color-mix(in oklab, var(--ty-color-neutral-bold) 40%, transparent));\n border-radius: var(--ty-scrollbar-radius, 4px);\n transition: background 0.15s ease-out;\n box-sizing: border-box;\n border: 1px solid transparent;\n}\n\n.ty-scrollbar-thumb-y:hover,\n.ty-scrollbar-track-y.dragging .ty-scrollbar-thumb-y {\n background: var(--ty-scrollbar-thumb-hover, color-mix(in oklab, var(--ty-color-neutral-bold) 55%, transparent));\n}\n\n.ty-scrollbar-thumb-y:active,\n.ty-scrollbar-track-y.dragging .ty-scrollbar-thumb-y {\n background: var(--ty-scrollbar-thumb-active, color-mix(in oklab, var(--ty-color-neutral-bold) 70%, transparent));\n}\n\n/* ===================================== */\n/* Custom Scrollbar - Horizontal Track */\n/* ===================================== */\n\n.ty-scrollbar-track-x {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: var(--ty-scrollbar-width, 8px);\n z-index: 3;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.25s ease-out;\n cursor: pointer;\n}\n\n.ty-scrollbar-track-x.has-overflow {\n pointer-events: auto;\n}\n\n.ty-scrollbar-track-x.has-overflow:hover,\n.ty-scrollbar-track-x.has-overflow.scrolling,\n.ty-scrollbar-track-x.dragging {\n opacity: 1;\n}\n\n.ty-scrollbar-track-x::before {\n content: '';\n position: absolute;\n inset: 0;\n background: var(--ty-scrollbar-track, transparent);\n border-radius: var(--ty-scrollbar-radius, 4px);\n opacity: 0;\n transition: opacity 0.15s ease-out;\n}\n\n.ty-scrollbar-track-x:hover::before,\n.ty-scrollbar-track-x.dragging::before {\n opacity: 1;\n background: var(--ty-scrollbar-track-hover, color-mix(in oklab, var(--ty-color-neutral-bold) 8%, transparent));\n}\n\n.ty-scrollbar-thumb-x {\n position: absolute;\n bottom: 0;\n height: 100%;\n min-width: var(--ty-scrollbar-thumb-min-height, 30px);\n background: var(--ty-scrollbar-thumb, color-mix(in oklab, var(--ty-color-neutral-bold) 40%, transparent));\n border-radius: var(--ty-scrollbar-radius, 4px);\n transition: background 0.15s ease-out;\n box-sizing: border-box;\n border: 1px solid transparent;\n}\n\n.ty-scrollbar-thumb-x:hover,\n.ty-scrollbar-track-x.dragging .ty-scrollbar-thumb-x {\n background: var(--ty-scrollbar-thumb-hover, color-mix(in oklab, var(--ty-color-neutral-bold) 55%, transparent));\n}\n\n.ty-scrollbar-thumb-x:active,\n.ty-scrollbar-track-x.dragging .ty-scrollbar-thumb-x {\n background: var(--ty-scrollbar-thumb-active, color-mix(in oklab, var(--ty-color-neutral-bold) 70%, transparent));\n}\n\n/* ===================================== */\n/* Touch devices - hide custom scrollbar */\n/* ===================================== */\n\n@media (pointer: coarse) and (hover: none) {\n .ty-scrollbar-track-y,\n .ty-scrollbar-track-x {\n display: none !important;\n }\n}\n\n/* Respect reduced motion */\n@media (prefers-reduced-motion: reduce) {\n .ty-scrollbar-track-y,\n .ty-scrollbar-track-x,\n .ty-scrollbar-thumb-y,\n .ty-scrollbar-thumb-x {\n transition-duration: 0ms !important;\n }\n}\n",Et='<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="12"></line><line x1="12" y1="16" x2="12.01" y2="16"></line></svg>',Tt=class extends i{constructor(){super(),this.Xt=null,this.Jt=null,this.Qt=null,this.B=!1,this.handleInputEvent=t=>{this.value=t.target.value,this.Xt&&this.Jt&&this.resizeTextarea(this.Xt,this.Jt),this.emitValueEvents(t)},this.handleFocusEvent=()=>{this.B=!0},this.handleBlurEvent=()=>{this.B=!1};const t=this.shadowRoot;s(t,{css:"\n:host {\n display: block;\n font-family: var(--ty-font-sans);\n width: 100%;\n}\n\n.textarea-container {\n display: flex;\n flex-direction: column;\n width: 100%;\n box-sizing: border-box;\n position: relative;\n /* For absolute positioned dummy element */\n}\n\n/* Bordered container — owns the border + active state (composer layout):\n header (top slot) · textarea (borderless) · footer (bottom slot). */\n.textarea-wrapper {\n position: relative;\n width: 100%;\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n border: 1px solid var(--input-border, var(--ty-input-border));\n border-radius: var(--ty-radius-base);\n background: var(--input-bg, var(--ty-input-bg));\n transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n}\n\n/* Active ring tied to the TEXTAREA specifically (not :focus-within) so tabbing\n to a footer button doesn't make the whole field look focused. */\n.textarea-wrapper:has(textarea:focus) {\n border-color: var(--input-border-focus, var(--ty-input-border-focus));\n box-shadow: 0 0 0 3px var(--input-shadow-focus, var(--ty-input-shadow-focus));\n}\n\n/* Error + disabled reflected from the inner textarea (both in shadow DOM, so\n :has is reliable here — unlike slotted content). */\n.textarea-wrapper:has(textarea.error) {\n border-color: var(--ty-color-danger);\n background: var(--ty-bg-danger-soft);\n}\n.textarea-wrapper:has(textarea.error):has(textarea:focus) {\n border-color: var(--ty-color-danger-bold);\n}\n.textarea-wrapper:has(textarea:disabled) {\n opacity: 0.5;\n background: var(--input-disabled-bg, var(--ty-input-disabled-bg));\n border-color: var(--input-disabled-border, var(--ty-input-disabled-border));\n}\n\n/* Scroll region wraps just the textarea so the custom scrollbar never overlaps\n the header/footer. */\n.textarea-scroll {\n position: relative;\n flex: 1 1 auto;\n min-height: 0;\n display: flex;\n}\n\n/* Custom scrollbar track positioned to the scroll region (textarea edges) */\n.textarea-scroll .ty-scrollbar-track-y {\n top: 2px;\n right: 2px;\n bottom: 2px;\n border-radius: 0 4px 4px 0;\n}\n\n/* Header / footer slot regions — zero footprint until they have content\n (the component toggles .has-content via slotchange). footer defaults to\n space-between so \"tools … submit\" works; a single wide button fills it. */\n.textarea-header,\n.textarea-footer {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n.textarea-footer { justify-content: space-between; }\n.textarea-header.has-content {\n padding: 6px 10px;\n border-bottom: 1px solid var(--ty-textarea-divider, var(--input-border, var(--ty-input-border)));\n}\n.textarea-footer.has-content {\n padding: 6px 10px;\n border-top: 1px solid var(--ty-textarea-divider, var(--input-border, var(--ty-input-border)));\n}\n\n/* ===== LABEL STYLING ===== */\n\n.ty-field-label {\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n font-weight: var(--ty-font-medium);\n color: var(--ty-label-color);\n margin-bottom: 6px;\n padding-left: 12px;\n}\n\n/* Required indicator - using SVG icon instead of CSS */\n.required-icon {\n display: inline-flex;\n align-items: center;\n color: var(--ty-color-danger);\n width: 12px;\n height: 12px;\n vertical-align: middle;\n}\n\n/* ===== ERROR MESSAGE STYLING ===== */\n\n.error-message {\n font-size: var(--ty-font-xs);\n line-height: var(--ty-leading-xs);\n letter-spacing: var(--ty-tracking-xs);\n color: var(--ty-color-danger);\n margin-top: 4px;\n padding-left: 12px;\n}\n\n/* Error state is reflected on .textarea-wrapper (see above). */\n\n/* ===== TEXTAREA BASE STYLING ===== */\n\ntextarea {\n /* Borderless — the .textarea-wrapper owns the border/background now. */\n box-sizing: border-box;\n width: 100%;\n flex: 1 1 auto;\n border: none;\n background: transparent;\n color: var(--input-color, var(--ty-input-color));\n font-family: inherit;\n /* Linear-paired typography */\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n font-weight: var(--ty-font-normal);\n outline: none;\n\n /* Default size (md) - refined spacing */\n min-height: 80px;\n /* Larger than input for multiline */\n padding: 12px 12px;\n /* Slightly larger padding for text areas */\n\n /* Auto-resize specific styles */\n overflow: hidden;\n /* Hide scrollbars since we're auto-resizing */\n resize: none;\n /* Disable manual resize by default */\n\n /* Ensure consistent text wrapping */\n white-space: pre-wrap;\n word-wrap: break-word;\n}\n\n/* Hide native scrollbar for webkit when custom scrollbar is active\n (scrollbar-width: none handles Firefox; this handles Chrome/Safari) */\n:host([data-custom-scroll]) textarea::-webkit-scrollbar {\n display: none;\n}\n\n/* Disabled — visual state lives on the wrapper; just the cursor/text here. */\ntextarea:disabled {\n cursor: not-allowed;\n color: var(--input-disabled-color, var(--ty-input-disabled-color));\n}\n\n/* Placeholder styling - subtle and elegant */\ntextarea::placeholder {\n color: var(--input-placeholder, var(--ty-input-placeholder));\n font-weight: 400;\n}\n\n/* ===== RESIZE CONTROL OPTIONS ===== */\n\n/* Allow manual resizing */\ntextarea.resize-both {\n resize: both;\n}\n\ntextarea.resize-horizontal {\n resize: horizontal;\n}\n\ntextarea.resize-vertical {\n resize: vertical;\n}\n\ntextarea.resize-none {\n resize: none;\n}\n\n/* Auto-resize mode (default) disables manual resize */\ntextarea:not(.resize-both):not(.resize-horizontal):not(.resize-vertical) {\n resize: none;\n}\n\n/* ===== DUMMY ELEMENT FOR AUTO-RESIZE ===== */\n\n.textarea-dummy {\n /* Hidden element that measures text height */\n position: absolute !important;\n top: 0 !important;\n left: 0 !important;\n visibility: hidden !important;\n white-space: pre-wrap !important;\n word-break: break-word !important;\n box-sizing: border-box !important;\n overflow: hidden !important;\n pointer-events: none !important;\n z-index: -1 !important;\n\n /* Ensure it has the same text behavior as textarea */\n word-wrap: break-word !important;\n overflow-wrap: break-word !important;\n}\n\n/* ===== SIZE MODIFIERS ===== */\n\n/* Extra Small */\ntextarea.xs {\n min-height: 64px;\n padding: 8px 10px;\n font-size: var(--ty-font-xs);\n line-height: var(--ty-leading-xs);\n letter-spacing: var(--ty-tracking-xs);\n}\n\n/* Small */\ntextarea.sm {\n min-height: 72px;\n padding: 10px 10px;\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n}\n\n/* Medium (default) */\ntextarea.md {\n min-height: 80px;\n padding: 12px 12px;\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n}\n\n/* Large */\ntextarea.lg {\n min-height: 96px;\n padding: 14px 14px;\n font-size: var(--ty-font-base);\n line-height: var(--ty-leading-base);\n letter-spacing: var(--ty-tracking-base);\n}\n\n/* Extra Large */\ntextarea.xl {\n min-height: 112px;\n padding: 16px 16px;\n font-size: var(--ty-font-lg);\n line-height: var(--ty-leading-lg);\n letter-spacing: var(--ty-tracking-lg);\n}\n\n/* ===== ACCESSIBILITY ENHANCEMENTS ===== */\n\ntextarea:focus-visible {\n outline: none;\n /* We use box-shadow instead */\n}\n\n/* High contrast mode support */\n@media (prefers-contrast: high) {\n textarea {\n border-width: 2px;\n }\n}\n\n/* Reduced motion support */\n@media (prefers-reduced-motion: reduce) {\n textarea {\n transition: none;\n }\n\n .textarea-dummy {\n transition: none;\n }\n}\n\n/* ===== CONTAINER-AWARE RESPONSIVE BEHAVIOR ===== */\n\n/* Scale down on smaller containers using container queries */\n@container (max-width: 480px) {\n textarea.lg {\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n padding: 12px 12px;\n min-height: 80px;\n }\n\n textarea.xl {\n font-size: var(--ty-font-base);\n line-height: var(--ty-leading-base);\n letter-spacing: var(--ty-tracking-base);\n padding: 14px 14px;\n min-height: 96px;\n }\n}\n\n@container (max-width: 320px) {\n textarea.xl {\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n padding: 12px 12px;\n min-height: 80px;\n }\n}\n\n/* Fallback for browsers without container query support */\n@media (max-width: 640px) {\n textarea.lg {\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n padding: 12px 12px;\n min-height: 80px;\n }\n\n textarea.xl {\n font-size: var(--ty-font-base);\n line-height: var(--ty-leading-base);\n letter-spacing: var(--ty-tracking-base);\n padding: 14px 14px;\n min-height: 96px;\n }\n}\n\n@media (max-width: 480px) {\n textarea.xl {\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n padding: 12px 12px;\n min-height: 80px;\n }\n}\n\n/* ===== ANIMATION AND TRANSITIONS ===== */\n\n/* Smooth height transitions for auto-resize */\ntextarea {\n transition:\n border-color 0.15s ease-in-out,\n box-shadow 0.15s ease-in-out,\n background-color 0.15s ease-in-out,\n height 0.1s ease-out;\n /* Smooth height changes */\n}\n\n/* Disable height transition on focus to avoid jarring effect */\ntextarea:focus {\n transition:\n border-color 0.15s ease-in-out,\n box-shadow 0.15s ease-in-out,\n background-color 0.15s ease-in-out;\n}\n\n/* For users who prefer reduced motion, disable height transitions */\n@media (prefers-reduced-motion: reduce) {\n textarea {\n transition: none;\n }\n}\n",id:"ty-textarea"}),$t()&&s(t,{css:St,id:"ty-custom-scrollbar"})}onConnect(){}onDisconnect(){if(this.tn(),this.Xt){const t=this.Xt.cloneNode(!0);this.Xt.parentNode?.replaceChild(t,this.Xt),this.Xt=null}this.Jt=null}onPropertiesChanged(t){}getFormValue(){return this.getProperty("value")||null}get value(){return this.getProperty("value")}set value(t){this.setProperty("value",t)}get name(){return this.getProperty("name")}set name(t){this.setProperty("name",t)}get placeholder(){return this.getProperty("placeholder")}set placeholder(t){this.setProperty("placeholder",t)}get label(){return this.getProperty("label")}set label(t){this.setProperty("label",t)}get disabled(){return this.getProperty("disabled")}set disabled(t){this.setProperty("disabled",t)}get required(){return this.getProperty("required")}set required(t){this.setProperty("required",t)}get error(){return this.getProperty("error")}set error(t){this.setProperty("error",t)}get size(){return this.getProperty("size")}set size(t){this.setProperty("size",t)}get rows(){return this.getProperty("rows")}set rows(t){this.setProperty("rows",t)}get cols(){return this.getProperty("cols")}set cols(t){this.setProperty("cols",t)}get resize(){return this.getProperty("resize")}set resize(t){this.setProperty("resize",t)}get minHeight(){return this.getProperty("minHeight")}set minHeight(t){this.setProperty("minHeight",t)}get maxHeight(){return this.getProperty("maxHeight")}set maxHeight(t){this.setProperty("maxHeight",t)}getFontStyle(t){const n=window.getComputedStyle(t);return{fontFamily:n.fontFamily,fontSize:n.fontSize,fontWeight:n.fontWeight,lineHeight:n.lineHeight,letterSpacing:n.letterSpacing,fontStyle:n.fontStyle}}getSpacingStyle(t){const n=window.getComputedStyle(t);return{padding:n.padding,paddingTop:n.paddingTop,paddingRight:n.paddingRight,paddingBottom:n.paddingBottom,paddingLeft:n.paddingLeft,margin:n.margin,borderWidth:n.borderWidth}}setupDummyElement(t){const n=this.shadowRoot,e=n.querySelector(".textarea-dummy");e&&e.remove();const i=document.createElement("pre"),o=this.getFontStyle(t),s=this.getSpacingStyle(t);i.className="textarea-dummy";const r=i.style;return r.position="absolute",r.top="0",r.left="0",r.visibility="hidden",r.whiteSpace="pre-wrap",r.wordBreak="break-word",r.boxSizing="border-box",r.overflow="hidden",r.pointerEvents="none",Object.entries(o).forEach(([t,n])=>{r[t]=n}),Object.entries(s).forEach(([t,n])=>{r[t]=n}),n.appendChild(i),this.Jt=i,i}resizeTextarea(t,n){if(!t||!n)return;const e=this.value,i=this.placeholder,o=t.clientHeight;n.textContent=""===e&&i?i:e+" ",n.style.width=t.clientWidth+"px";const s=n.scrollHeight,r=this.minHeight?parseInt(this.minHeight.replace("px",""),10):null,a=this.maxHeight?parseInt(this.maxHeight.replace("px",""),10):null;let l=s;null!==r&&(l=Math.max(l,r)),null!==a&&(l=Math.min(l,a)),Math.abs(l-o)>2&&(t.style.height=l+"px",null===a||a>s?(t.style.overflowY="hidden",this.tn()):(t.style.overflowY="auto",this.nn(t))),this.Qt?.update()}nn(t){if(this.Qt||!$t())return;t.style.scrollbarWidth="none",this.setAttribute("data-custom-scroll",""),this.Qt=new Ct(t,{vertical:!0,horizontal:!1});const n=this.shadowRoot.querySelector(".textarea-scroll");n&&this.Qt.trackY&&n.appendChild(this.Qt.trackY)}tn(){this.Qt&&(this.Qt.trackY?.remove(),this.Qt.destroy(),this.Qt=null,this.removeAttribute("data-custom-scroll"),this.Xt&&(this.Xt.style.scrollbarWidth=""))}emitValueEvents(t){const n=this.value;this.v.setFormValue(n||""),this.updateValidity();const e={bubbles:!0,composed:!0,detail:{value:n,originalEvent:t}};setTimeout(()=>{this.dispatchEvent(new CustomEvent("input",e)),this.dispatchEvent(new CustomEvent("change",e))},0)}buildClassList(){const t=[this.size];this.disabled&&t.push("disabled"),this.required&&t.push("required"),this.error&&t.push("error"),"none"!==this.resize&&t.push("resize-"+this.resize);const n=this.getAttribute("class");return n&&t.push(n),t.join(" ")}applyHeightConstraints(t){this.minHeight&&(t.style.minHeight=this.minHeight),this.maxHeight&&(t.style.maxHeight=this.maxHeight)}setupTextareaEvents(t){t.addEventListener("input",this.handleInputEvent),t.addEventListener("change",this.handleInputEvent),t.addEventListener("focus",this.handleFocusEvent),t.addEventListener("blur",this.handleBlurEvent)}render(){const t=this.shadowRoot,n=t.querySelector(".textarea-container"),e=t.querySelector("label"),i=t.querySelector("textarea"),o=t.querySelector(".error-message");if(n&&i){if(this.label?e&&(e.innerHTML=this.label+(this.required?` <span class="required-icon">${Et}</span>`:""),e.style.display="block"):e&&(e.style.display="none"),i.value=this.value||"",i.placeholder=this.placeholder||"",i.disabled=this.disabled,i.required=this.required,i.className=this.buildClassList(),this.label?i.setAttribute("aria-label",this.label):i.removeAttribute("aria-label"),this.name?i.setAttribute("name",this.name):i.removeAttribute("name"),this.rows&&i.setAttribute("rows",this.rows),this.cols&&i.setAttribute("cols",this.cols),this.applyHeightConstraints(i),this.error){if(!o){const t=document.createElement("div");t.className="error-message",n.appendChild(t)}const e=t.querySelector(".error-message");e&&(e.textContent=this.error)}else o&&o.remove();const s=this.setupDummyElement(i);setTimeout(()=>this.resizeTextarea(i,s),0),this.Xt=i}else{const n=document.createElement("div");n.className="textarea-container";const e=document.createElement("label");e.className="ty-field-label",this.label?(e.innerHTML=this.label+(this.required?` <span class="required-icon">${Et}</span>`:""),e.style.display="block"):e.style.display="none";const i=document.createElement("textarea");i.value=this.value||"",i.placeholder=this.placeholder||"",i.disabled=this.disabled,i.required=this.required,i.className=this.buildClassList(),this.label&&i.setAttribute("aria-label",this.label),this.name&&i.setAttribute("name",this.name),i.setAttribute("rows",this.rows||"3"),this.cols&&i.setAttribute("cols",this.cols),this.applyHeightConstraints(i),this.setupTextareaEvents(i);const o=document.createElement("div");o.className="textarea-wrapper";const s=document.createElement("div");s.className="textarea-header";const r=document.createElement("slot");r.setAttribute("name","header"),s.appendChild(r);const a=document.createElement("div");a.className="textarea-scroll",a.appendChild(i);const l=document.createElement("div");l.className="textarea-footer";const c=document.createElement("slot");c.setAttribute("name","footer"),l.appendChild(c),o.appendChild(s),o.appendChild(a),o.appendChild(l);const d=(t,n)=>{const e=()=>n.classList.toggle("has-content",t.assignedNodes({flatten:!0}).length>0);t.addEventListener("slotchange",e),e()};if(d(r,s),d(c,l),n.appendChild(e),n.appendChild(o),this.error){const t=document.createElement("div");t.className="error-message",t.textContent=this.error,n.appendChild(t)}t.appendChild(n);const h=this.setupDummyElement(i);setTimeout(()=>this.resizeTextarea(i,h),0),this.Xt=i}this.updateValidity()}updateValidity(){const t=this.shadowRoot?.querySelector("textarea");this.disabled?this.v.setValidity({}):this.required&&""===(t?t.value:(this.value??"")+"").trim()?this.v.setValidity({valueMissing:!0},"Please fill out this field",t??void 0):this.v.setValidity({})}};Tt.formAssociated=!0,Tt.properties={value:{type:"string",visual:!0,formValue:!0,emitChange:!0,default:""},name:{type:"string",default:""},placeholder:{type:"string",visual:!0,default:""},label:{type:"string",visual:!0,default:""},disabled:{type:"boolean",visual:!0,default:!1},required:{type:"boolean",visual:!0,default:!1},error:{type:"string",visual:!0,default:""},size:{type:"string",visual:!0,default:"md",validate:t=>["xs","sm","md","lg","xl"].includes(t),coerce:t=>["xs","sm","md","lg","xl"].includes(t)?t:"md"},rows:{type:"string",visual:!0,default:"3",coerce:t=>t+""},cols:{type:"string",visual:!0,default:"",coerce:t=>t?t+"":""},resize:{type:"string",visual:!0,default:"none",validate:t=>["none","both","horizontal","vertical"].includes(t),coerce:t=>["none","both","horizontal","vertical"].includes(t)?t:"none"},minHeight:{type:"string",visual:!0,default:""},maxHeight:{type:"string",visual:!0,default:""}};let Mt=Tt;customElements.get("ty-textarea")||customElements.define("ty-textarea",Mt);const At={"top-start":{vertical:"top",horizontal:"start"},top:{vertical:"top",horizontal:"center"},"top-end":{vertical:"top",horizontal:"end"},"right-start":{vertical:"center",horizontal:"end",orientation:"vertical"},right:{vertical:"center",horizontal:"end",orientation:"vertical"},"right-end":{vertical:"end",horizontal:"end",orientation:"vertical"},"bottom-start":{vertical:"bottom",horizontal:"start"},bottom:{vertical:"bottom",horizontal:"center"},"bottom-end":{vertical:"bottom",horizontal:"end"},"left-start":{vertical:"center",horizontal:"start",orientation:"vertical"},left:{vertical:"center",horizontal:"start",orientation:"vertical"},"left-end":{vertical:"end",horizontal:"start",orientation:"vertical"}},It={default:["bottom-start","bottom-end","top-start","top-end","bottom","top","left","right"],tooltip:["top","bottom","left","right","top-start","top-end","bottom-start","bottom-end"]};function Dt(t){const n=t.getBoundingClientRect();return{top:n.top,left:n.left,right:n.right,bottom:n.bottom,width:n.width,height:n.height,centerX:n.left+n.width/2,centerY:n.top+n.height/2}}function Lt(t){const{targetEl:n,floatingEl:e,preferences:i=It.default,offset:o=8,padding:s=8,containerPadding:r=0}=t,a=Dt(n),l=Dt(e),c=i.map(t=>function(t){const{targetRect:n,floatingRect:e,placement:i,offset:o,padding:s,scrollbarWidth:r,containerPadding:a}=t,l=At[i],{vertical:c,horizontal:d,orientation:h}=l,u=window.innerWidth,p=window.innerHeight;let b,g;window,window,b="vertical"===h?"start"===d?n.left-e.width-o+a:n.right+o-a:"start"===d?n.left:"center"===d?n.centerX-e.width/2:n.right-e.width,g="vertical"===h?"center"===c?n.centerY-e.height/2:"end"===c?n.bottom-e.height-a:n.top:"top"===c?n.top-e.height-o+a:n.bottom+o-a;const m={top:Math.min(0,g-s),left:Math.min(0,b-s),bottom:Math.min(0,p-(g+e.height+s)),right:Math.min(0,u-(b+e.width+s+r))},v=Object.values(m).reduce((t,n)=>t+Math.abs(n),0);return{x:Math.round(b),y:Math.round(g),placement:i,overflow:m,overflowAmount:v,fits:0===v}}({targetRect:a,floatingRect:l,placement:t,offset:o,padding:s,containerPadding:r,scrollbarWidth:15})),d=c.find(t=>t.fits)||c.reduce((t,n)=>t.overflowAmount>n.overflowAmount?n:t);return 0>d.overflow.right&&(d.x+=d.overflow.right),d}function Ot(t){const n=t.gap??4,e=t.padding??8,i=window.innerWidth,o=window.innerHeight,s=o-t.anchorRect.bottom,r=s>=t.popupHeight+n+e||s>=t.anchorRect.top;return{x:Math.max(e,Math.min(t.anchorRect.left,i-t.popupWidth-e)),topY:t.anchorRect.bottom+n,bottomY:o-t.anchorRect.top+n,below:r}}const Nt={id:"ty-tooltip",css:"\n/* Tooltip host element - display contents to not affect layout */\n:host {\n display: contents;\n}\n"},Rt=new WeakMap,qt=new WeakMap,Vt=new WeakMap,Ft=new WeakMap,Pt=new WeakMap;function Ht(t){const n=t||"dark",e=n.replace(/[+-]$/,"");return/^[A-Za-z][A-Za-z0-9_-]*$/.test(e)?n:"dark"}function jt(t){let n=Vt.get(t);return n||(n={showTimeout:null,hideTimeout:null},Vt.set(t,n)),n}function Bt(t,n){return t.hasAttribute(n)}function Wt(t,n,e){const i=t.getAttribute(n);if(null===i)return e;const o=parseInt(i,10);return isNaN(o)?e:o}function _t(t){return{placement:t.getAttribute("placement")||"top",offset:Wt(t,"offset",8),delay:Wt(t,"delay",600),disabled:Bt(t,"disabled"),flavor:Ht(t.getAttribute("flavor"))}}function Yt(t){return t.parentElement}function Ut(t){let n=Ft.get(t);if(!n){n=document.createElement("div"),n.id="ty-tooltip-"+Math.random().toString(36).slice(2,11),n.setAttribute("popover","manual"),n.setAttribute("role","tooltip"),n.className="ty-tooltip-popover",n.style.cssText="\n position: fixed;\n margin: 0;\n padding: 8px 12px;\n background: var(--ty-tooltip-bg, #262626);\n color: var(--ty-tooltip-color, #f5f5f5);\n border: none;\n border-radius: 6px;\n font-size: var(--ty-font-xs, 12px);\n font-weight: var(--ty-font-semibold, 600);\n line-height: 1.5;\n max-width: 250px;\n text-align: center;\n box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.2), 0 4px 6px -4px rgba(0, 0, 0, 0.1);\n user-select: none;\n pointer-events: none;\n ",document.body.appendChild(n),Ft.set(t,n);const e=Pt.get(t);e&&function(t,n){const e=(t.getAttribute("aria-describedby")||"").split(/\s+/).filter(Boolean);e.includes(n)||(e.push(n),t.setAttribute("aria-describedby",e.join(" ")))}(e,n.id)}const{flavor:e}=_t(t);return n.setAttribute("data-flavor",e),n.innerHTML=t.innerHTML,Gt(n,e),n}function Gt(t,n){switch(t.style.removeProperty("background"),t.style.removeProperty("color"),t.style.removeProperty("border-color"),n){case"dark":t.style.background="var(--ty-tooltip-bg, #262626)",t.style.color="var(--ty-tooltip-color, #f5f5f5)",t.style.borderColor="var(--ty-tooltip-border, #404040)";break;case"light":t.style.background="var(--ty-surface-elevated, #ffffff)",t.style.color="var(--ty-text-strong, #111827)",t.style.borderColor="var(--ty-border, #e5e7eb)";break;case"info":t.style.background="var(--ty-bg-info, #06b6d4)",t.style.color="var(--ty-text-strong, #f0f9ff)",t.style.borderColor="var(--ty-border-info, #22d3ee)";break;default:{const e=n.replace(/[+-]$/,""),i=n.slice(e.length);t.style.background=`var(--ty-bg-${e}${"+"===i?"-bold":"-"===i?"-soft":""}, var(--ty-bg-neutral))`,t.style.color=`var(--ty-color-${e}-strong, var(--ty-color-neutral-strong))`,t.style.borderColor=`var(--ty-border-${e}, var(--ty-color-${e}))`;break}}}function Kt(t){const{placement:n,offset:e}=_t(t),i=Yt(t),o=Ft.get(t);if(!i||!o)return;const s=Lt({targetEl:i,floatingEl:o,preferences:"top"===n?It.tooltip:"bottom"===n?["bottom","top","left","right"]:"left"===n?["left","right","top","bottom"]:"right"===n?["right","left","top","bottom"]:It.tooltip,offset:e});o.style.left=s.x+"px",o.style.top=s.y+"px"}function Zt(t){const n=Rt.get(t);n&&(n(),Rt.delete(t))}function Xt(t){const n=jt(t);null!==n.showTimeout&&(clearTimeout(n.showTimeout),n.showTimeout=null),null!==n.hideTimeout&&(clearTimeout(n.hideTimeout),n.hideTimeout=null)}function Jt(t){const n=Ft.get(t);if(n)try{n.hidePopover(),t.en=!1,Zt(t)}catch(e){}}function Qt(t){const n=jt(t),{delay:e}=_t(t);Xt(t),n.showTimeout=window.setTimeout(()=>function(t){const{disabled:n}=_t(t);if(n)return;const e=Ut(t);try{e.showPopover(),t.en=!0,Kt(t),function(t){const n=Yt(t),e=Ft.get(t);if(!n||!e)return;let i=null;const o=()=>{null!==i&&clearTimeout(i),i=window.setTimeout(()=>{i=null,Kt(t)},10)},s=new ResizeObserver(o);s.observe(n),s.observe(e);let r=null;const a=()=>{null===r&&(r=requestAnimationFrame(()=>{r=null,Kt(t)}))};window.addEventListener("scroll",a,!0),window.addEventListener("resize",o),Rt.set(t,()=>{s.disconnect(),window.removeEventListener("scroll",a,!0),window.removeEventListener("resize",o),null!==i&&clearTimeout(i),null!==r&&cancelAnimationFrame(r)})}(t)}catch(i){}}(t),e)}function tn(t){const n=jt(t);Xt(t),n.hideTimeout=window.setTimeout(()=>Jt(t),200)}class TyTooltip extends HTMLElement{constructor(){super(),this.en=!1,this.attachShadow({mode:"open"})}static get observedAttributes(){return["placement","offset","delay","disabled","flavor"]}connectedCallback(){this.en=!1,s(this.shadowRoot,Nt),function(t){const n=Yt(t);if(!n)return;Pt.set(t,n);const e=()=>Qt(t),i=()=>tn(t),o=()=>Qt(t),s=()=>tn(t);n.addEventListener("mouseenter",e),n.addEventListener("mouseleave",i),n.addEventListener("focusin",o),n.addEventListener("focusout",s),qt.set(t,()=>{n.removeEventListener("mouseenter",e),n.removeEventListener("mouseleave",i),n.removeEventListener("focusin",o),n.removeEventListener("focusout",s)})}(this),Ut(this)}disconnectedCallback(){!function(t){Xt(t),Zt(t);const n=qt.get(t);n&&(n(),qt.delete(t));const e=Ft.get(t),i=Pt.get(t);e&&i&&function(t,n){const e=(t.getAttribute("aria-describedby")||"").split(/\s+/).filter(t=>t&&t!==n);e.length>0?t.setAttribute("aria-describedby",e.join(" ")):t.removeAttribute("aria-describedby")}(i,e.id),e&&(e.remove(),Ft.delete(t)),Pt.delete(t),Vt.delete(t)}(this)}attributeChangedCallback(t,n,e){if("flavor"===t){const t=Ft.get(this);t&&Gt(t,Ht(e))}"disabled"===t&&null!==e&&Jt(this)}}customElements.get("ty-tooltip")||customElements.define("ty-tooltip",TyTooltip);const nn={locked:!1,scrollY:0,activeLocks:new Set};function en(){return document.documentElement}function on(){if(!nn.locked)return;const t=en();window,t.classList.remove("ty-scroll-locked"),t.style.overflow="",t.style.paddingRight="",nn.locked=!1}function sn(t){nn.activeLocks.has(t)||(nn.activeLocks.add(t),1===nn.activeLocks.size&&function(){if(nn.locked)return;const t=window.innerWidth-en().clientWidth,n=en();window,nn.scrollY=window.scrollY||en().scrollTop||0,nn.locked=!0,n.style.overflow="hidden",t>0&&(n.style.paddingRight=t+"px"),n.classList.add("ty-scroll-locked")}())}function rn(t){nn.activeLocks.has(t)&&(nn.activeLocks.delete(t),0===nn.activeLocks.size&&on())}const an=new WeakMap,ln=new WeakMap,cn=new WeakMap,dn=new WeakMap,hn=new WeakMap;function un(t,n){return t.hasAttribute(n)}function pn(t,n,e){const i=t.getAttribute(n);if(null===i)return e;const o=parseInt(i,10);return isNaN(o)?e:o}function bn(t){return{manual:un(t,"manual"),disableClose:un(t,"disable-close"),placement:t.getAttribute("placement")||"bottom",offset:pn(t,"offset",8)}}function gn(t){return t.parentElement}function mn(t){return t.querySelector(".popup-dialog")}function vn(t){let n=hn.get(t);return n||(n="popup-"+(t.id||Math.random().toString(36).substr(2,9)),hn.set(t,n)),n}function fn(t,n=!1){const{disableClose:e}=bn(t);if(!n&&e)return;const i=t.shadowRoot,o=i?mn(i):null;if(!o)return;o.classList.remove("open"),o.classList.remove("preparing-animation");const s=gn(t);s?.hasAttribute("aria-haspopup")&&s.setAttribute("aria-expanded","false"),setTimeout(()=>{o.classList.remove("position-calculated"),o.close()},150),t.dispatchEvent(new CustomEvent("close",{bubbles:!0}))}function yn(t){sn(vn(t));const n=t.shadowRoot,e=n?mn(n):null;if(!e)return;e.showModal();const i=gn(t);i?.hasAttribute("aria-haspopup")&&i.setAttribute("aria-expanded","true"),requestAnimationFrame(()=>{!function(t){const{placement:n,offset:e}=bn(t),i=t.shadowRoot,o=gn(t),s=i?mn(i):null;if(!o||!s)return;const r=Lt({targetEl:o,floatingEl:s,preferences:"top"===n?["top","bottom","left","right"]:"bottom"===n?["bottom","top","left","right"]:"left"===n?["left","right","top","bottom"]:"right"===n?["right","left","top","bottom"]:["bottom","top","right","left"],offset:e,padding:8,containerPadding:16});t.style.setProperty("--popup-x",r.x+"px"),t.style.setProperty("--popup-y",r.y+"px"),s.classList.add("position-calculated")}(t),e.classList.add("preparing-animation"),requestAnimationFrame(()=>{e.classList.add("open"),t.dispatchEvent(new CustomEvent("open",{bubbles:!0}))})})}function wn(t){const n=t.shadowRoot,e=n?mn(n):null;e&&(e.classList.contains("open")?fn(t):yn(t))}function xn(t){const{manual:n}=bn(t),e=gn(t);if(!e||n)return;e.setAttribute("aria-haspopup","dialog"),e.hasAttribute("aria-expanded")||e.setAttribute("aria-expanded","false");const i=an.get(t);i&&e.removeEventListener("pointerdown",i);const o=n=>function(t,n){n.preventDefault(),n.stopPropagation(),wn(t)}(t,n);an.set(t,o),e.addEventListener("pointerdown",o)}function kn(t){const n=gn(t),e=an.get(t);n&&e&&(n.removeEventListener("pointerdown",e),an.delete(t)),n?.removeAttribute("aria-haspopup"),n?.removeAttribute("aria-expanded")}function zn(t){const n=t.shadowRoot;if(!n)return;const e=mn(n);if(s(n,{css:"\n/* Popup component with dropdown-like behavior and tooltip positioning */\n/* Uses dialog element for top layer rendering like dropdown and date-picker */\n\n.popup-dialog {\n position: fixed;\n top: 0;\n left: 0;\n\n /* Reset dialog defaults */\n margin: 0;\n border: none;\n background: transparent;\n max-width: none;\n max-height: none;\n\n /* Shadow infrastructure - provide space for user shadows */\n padding: var(--popup-padding, 16px);\n\n /* Hidden by default - even when [open] (for positioning phase) */\n visibility: hidden;\n opacity: 0;\n /* NO TRANSFORM here - apply only when animating to avoid measurement errors! */\n\n /* Smooth transitions */\n transition:\n opacity 150ms ease-out,\n visibility 150ms ease-out,\n transform 150ms ease-out;\n\n /* Prevent interactions when hidden */\n pointer-events: none;\n}\n\n/* Apply position variables only when position is calculated (like dropdown) */\n.popup-dialog.position-calculated {\n top: var(--popup-y, 0px);\n left: var(--popup-x, 0px);\n}\n\n/* Apply scale for entrance animation (right before .open) */\n.popup-dialog.preparing-animation {\n transform: scale(0.95);\n}\n\n/* When open - smooth entrance animation */\n.popup-dialog.open {\n visibility: visible;\n opacity: 1;\n transform: scale(1);\n pointer-events: auto;\n}\n\n/* Make dialog backdrop transparent like dropdown/date-picker */\n.popup-dialog::backdrop {\n background: transparent;\n}\n\n/* Inner container - neutral structural container */\n.popup-container {\n /* No default styling - just provides structure */\n /* Users control all visual aspects via slotted content */\n display: contents;\n}\n\n/* Content slot styling */\n#popup-content {\n /* Allow slotted content to define its own styling */\n display: contents;\n}\n\n/* Remove default styling from slotted content - users have full control */\n#popup-content ::slotted(*) {\n /* Remove default styling that conflicts with user styling */\n /* Users now have complete control over popup appearance */\n /* background: unset; */\n /* border: unset; */\n /* box-shadow: unset; */\n\n /* Only maintain essential positioning */\n position: relative;\n\n /* Prevent content from being too wide - still helpful */\n max-width: min(400px, 90vw);\n max-height: min(500px, 80vh);\n overflow: auto;\n}\n",id:"ty-popup"}),!e){const e=document.createElement("dialog"),i=document.createElement("div"),o=document.createElement("slot");e.className="popup-dialog",i.className="popup-container",o.id="popup-content",n.appendChild(e),e.appendChild(i),i.appendChild(o),t.style.setProperty("--popup-x","0px"),t.style.setProperty("--popup-y","0px");const s=n=>function(t,n){n.stopPropagation();const e=t.shadowRoot,i=e?mn(e):null;i&&n.target===i&&(n.preventDefault(),fn(t))}(t,n);ln.set(t,s),e.addEventListener("pointerdown",s);const r=n=>function(t,n){if(n.stopPropagation(),"Escape"===n.key){const{disableClose:e}=bn(t);e?n.preventDefault():fn(t)}}(t,n);cn.set(t,r),t.addEventListener("keydown",r),e.addEventListener("close",()=>{rn(vn(t)),e.classList.remove("open"),e.classList.remove("preparing-animation"),t.dispatchEvent(new CustomEvent("close",{bubbles:!0}))})}t.closePopup=()=>fn(t,!0),t.openPopup=()=>yn(t),t.togglePopup=()=>wn(t);const i=n=>function(t,n){n.stopPropagation(),fn(t,!0)}(t,n);dn.set(t,i),t.addEventListener("ty:close-popup",i),xn(t)}class TyPopup extends HTMLElement{static get observedAttributes(){return["manual","disable-close","placement","offset"]}constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){zn(this)}disconnectedCallback(){!function(t){const n=hn.get(t);n&&(rn(n),hn.delete(t)),kn(t);const e=t.shadowRoot,i=e?mn(e):null;if(i){const n=ln.get(t);n&&(i.removeEventListener("pointerdown",n),ln.delete(t))}const o=cn.get(t);o&&(t.removeEventListener("keydown",o),cn.delete(t));const s=dn.get(t);s&&(t.removeEventListener("ty:close-popup",s),dn.delete(t))}(this)}attributeChangedCallback(t,n,e){switch(zn(this),t){case"placement":case"offset":zn(this);break;case"manual":case"disable-close":kn(this),xn(this)}}}customElements.get("ty-popup")||customElements.define("ty-popup",TyPopup);const $n=new WeakMap,Cn=new WeakMap,Sn=new WeakMap,En=new WeakMap,Tn=new WeakMap,Mn=new WeakMap;function An(t,n){if(!t.hasAttribute(n))return!1;const e=t.getAttribute(n);return null===e||"false"!==e.toLowerCase()}function In(t){return t.querySelector(".ty-modal-dialog")}function Dn(t,n,e){const i=new CustomEvent(n,{detail:e,bubbles:!0,cancelable:!0});t.dispatchEvent(i)}function Ln(t,n="programmatic",e){const i=t.shadowRoot,o=i?In(i):null;if(o&&o.open){if(!e?.force){const e=new CustomEvent("beforeclose",{detail:{reason:n},bubbles:!0,composed:!0,cancelable:!0});if(t.dispatchEvent(e),e.defaultPrevented)return}t.removeAttribute("open")}}function On(t){const n=t.shadowRoot;if(!n)return;const e=function(t){return{open:An(t,"open"),backdrop:!t.hasAttribute("backdrop")||An(t,"backdrop"),closeOnOutsideClick:!t.hasAttribute("close-on-outside-click")||An(t,"close-on-outside-click"),closeOnEscape:!t.hasAttribute("close-on-escape")||An(t,"close-on-escape")}}(t),i=function(t){let n=In(t);if(!n){n=document.createElement("dialog");const e=document.createElement("button"),i=document.createElement("div"),o=document.createElement("slot");n.className="ty-modal-dialog",e.className="close-button",e.type="button",e.setAttribute("aria-label","Close modal"),e.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-x-icon lucide-x"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>',i.className="modal-content",i.appendChild(o),n.appendChild(e),n.appendChild(i),t.appendChild(n)}return n}(n),o=function(t){let n=Mn.get(t);return n||(n="modal-"+(t.id||Math.random().toString(36).slice(2,11)),Mn.set(t,n)),n}(t);s(n,{css:"\n/* Modal Host Styling */\n:host {\n display: contents;\n /* Don't interfere with layout */\n /* CSS variables are now auto-generated via the with-vars? option */\n}\n\n/* ===== CLOSE BUTTON STYLING ===== */\n/* This is part of the modal wrapper functionality, not user content styling */\n\n.close-button {\n position: absolute;\n top: -8px;\n right: -8px;\n background: transparent;\n border: none;\n cursor: pointer;\n padding: 4px;\n border-radius: 4px;\n transition: var(--ty-transition-colors);\n z-index: 1;\n color: #d8d8d8;\n\n /* Remove all default browser styling that could cause outlines/borders */\n outline: none;\n box-shadow: none;\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n\n /* Remove mobile tap highlights and focus rings */\n -webkit-tap-highlight-color: transparent;\n -webkit-touch-callout: none;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n}\n\n.close-button:hover {\n color: white;\n}\n\n/* Explicitly remove focus and active states for all interaction modes */\n.close-button:focus,\n.close-button:focus-visible,\n.close-button:focus-within,\n.close-button:active {\n outline: none !important;\n box-shadow: none !important;\n border: none !important;\n background: transparent !important;\n}\n\n/* Override hover color even in focus/active states */\n.close-button:hover,\n.close-button:focus:hover,\n.close-button:active:hover {\n color: white;\n}\n\n.close-button.hide {\n visibility: hidden;\n}\n\n/* ===== DIALOG ELEMENT - PURE WRAPPER ===== */\n/* Modal dialog - provides only essential modal functionality without styling user content */\n\n.ty-modal-dialog {\n /* Reset default dialog styles */\n padding: 18px;\n border: none;\n margin: 0;\n background: transparent;\n\n /* Modal positioning - centered */\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n\n /* Layer management */\n z-index: 1000;\n overflow: hidden;\n\n /* No sizing - let user content determine size */\n max-width: 85vw;\n max-height: 90vh;\n\n outline: none;\n}\n\n/* ===== BACKDROP STYLING ===== */\n/* Backdrop is part of modal functionality, not user content */\n\n.ty-modal-dialog::backdrop {\n background: var(--ty-modal-backdrop, rgba(0, 0, 0, 0.5));\n backdrop-filter: var(--ty-modal-backdrop-blur, blur(2px));\n animation: ty-modal-backdrop-enter var(--ty-modal-duration, 200ms) ease-out;\n}\n\n/* When backdrop is disabled */\n.ty-modal-dialog:not([data-backdrop])::backdrop {\n background: transparent;\n backdrop-filter: none;\n}\n\n/* ===== MODAL CONTENT CONTAINER ===== */\n/* Minimal container - no styling imposed on user content */\n\n.modal-content {\n color: var(--ty-text);\n}\n\n/* ===== ANIMATION KEYFRAMES ===== */\n\n@keyframes ty-modal-backdrop-enter {\n from {\n opacity: 0;\n }\n\n to {\n opacity: 1;\n }\n}\n",id:"ty-modal"}),i.className="ty-modal-dialog",e.backdrop?i.setAttribute("data-backdrop","true"):i.removeAttribute("data-backdrop");const r=t.getAttribute("label");r?i.setAttribute("aria-label",r):i.removeAttribute("aria-label"),function(t,n,e){const i=$n.get(t);if(i&&(n.removeEventListener("click",i),$n.delete(t)),e){const e=n=>function(t,n){n.stopPropagation();const e=t.shadowRoot,i=e?In(e):null;i&&n.target===i&&(n.preventDefault(),Ln(t,"backdrop"))}(t,n);$n.set(t,e),n.addEventListener("click",e)}}(t,i,e.closeOnOutsideClick),function(t,n,e){const i=Cn.get(t);if(i&&(n.removeEventListener("keydown",i),Cn.delete(t)),e){const e=n=>function(t,n){n.stopPropagation(),"Escape"===n.key&&(n.preventDefault(),Ln(t,"escape"))}(t,n);Cn.set(t,e),n.addEventListener("keydown",e)}}(t,i,e.closeOnEscape),function(t,n,e){const i=n.querySelector(".close-button");if(!i)return;i.style.display=e?"":"none";const o=Sn.get(t);if(o&&(i.removeEventListener("click",o),Sn.delete(t)),e){const n=n=>function(t,n){n.preventDefault(),n.stopPropagation(),Ln(t,"close-button")}(t,n);Sn.set(t,n),i.addEventListener("click",n)}}(t,i,e.closeOnOutsideClick),function(t,n){const e=n.querySelector(".modal-content");if(!e)return;const i=En.get(t),o=Tn.get(t);if(i&&(e.removeEventListener("mouseenter",i),En.delete(t)),o&&(e.removeEventListener("mouseleave",o),Tn.delete(t)),window.innerWidth>=768&&0>=navigator.maxTouchPoints){const n=t=>function(t,n){const e=n.currentTarget.closest(".ty-modal-dialog");if(e){const t=e.querySelector(".close-button");t&&t.classList.add("hide")}}(0,t),i=t=>function(t,n){const e=n.currentTarget.closest(".ty-modal-dialog");if(e){const t=e.querySelector(".close-button");t&&t.classList.remove("hide")}}(0,t);En.set(t,n),Tn.set(t,i),e.addEventListener("mouseenter",n),e.addEventListener("mouseleave",i)}}(t,i),e.open?i.open||(sn(o),e.backdrop?i.showModal():i.show(),Dn(t,"open",{})):i.open&&(rn(o),i.close(),Dn(t,"close",{reason:"programmatic"})),i.onclose=n=>{n.target===i&&(rn(o),t.hasAttribute("open")&&(t.removeAttribute("open"),Dn(t,"close",{reason:"native",returnValue:i.returnValue||void 0})))}}class TyModal extends HTMLElement{static get observedAttributes(){return["open","backdrop","close-on-outside-click","close-on-escape","label"]}constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){On(this),this.show=()=>{this.setAttribute("open","true")},this.hide=t=>Ln(this,"programmatic",t)}disconnectedCallback(){!function(t){const n=Mn.get(t),e=t.shadowRoot,i=e?In(e):null;if(n&&(rn(n),Mn.delete(t)),!i)return;const o=$n.get(t);o&&(i.removeEventListener("click",o),$n.delete(t));const s=Cn.get(t);s&&(i.removeEventListener("keydown",s),Cn.delete(t));const r=i.querySelector(".close-button");if(r){const n=Sn.get(t);n&&(r.removeEventListener("click",n),Sn.delete(t))}const a=i.querySelector(".modal-content");if(a){const n=En.get(t),e=Tn.get(t);n&&(a.removeEventListener("mouseenter",n),En.delete(t)),e&&(a.removeEventListener("mouseleave",e),Tn.delete(t))}}(this)}attributeChangedCallback(t,n,e){this.isConnected&&On(this)}}customElements.get("ty-modal")||customElements.define("ty-modal",TyModal),customElements.get("ty-dialog")||customElements.define("ty-dialog",class extends TyModal{});const Nn=(t,n)=>{const e=e=>n?e?`var(--ty-color-${t}${e}, var(--ty-color-${t}, var(--ty-color-${n}${e})))`:`var(--ty-color-${t}, var(--ty-color-${n}))`:e?`var(--ty-color-${t}${e}, var(--ty-color-${t}))`:`var(--ty-color-${t})`;return`\n:host([flavor="${t}"]) {\n --select-accent: var(--ty-input-${t}-border, ${e("-soft")});\n --select-accent-bold: ${e("")};\n --select-ring: color-mix(in oklab, ${e("")} 15%, transparent);\n}\n:host([flavor="${t}+"]) {\n --select-accent: ${e("")};\n --select-accent-bold: ${e("-strong")};\n --select-ring: color-mix(in oklab, ${e("-strong")} 15%, transparent);\n}\n:host([flavor="${t}-"]) {\n --select-accent: ${e("-faint")};\n --select-accent-bold: ${e("-soft")};\n --select-ring: color-mix(in oklab, ${e("-soft")} 15%, transparent);\n}\n`},Rn=`\n/* Select-field-specific styles extending dropdown base styles */\n\n:host {\n font-family: var(--ty-font-sans);\n --mobile-border-color: var(--ty-border, #5858587d);\n}\n\n/* ===== DIALOG POSITIONING SUPPORT ===== */\n\n.dropdown-dialog {\n position: fixed;\n width: var(--dropdown-width, 200px);\n max-width: 100vw;\n margin: 0;\n padding: 0;\n border: none;\n background: transparent;\n box-sizing: border-box;\n padding: var(--dropdown-padding, 20px);\n /* Modal handles z-index automatically */\n\n /* Hidden by default */\n opacity: 0;\n transition: opacity 400ms ease;\n\n transform: translate(var(--dropdown-offset-x, 0px), var(--dropdown-offset-y, 0px));\n top: -1000px;\n left: -1000px;\n}\n\n/* When opened via showModal(), apply flex layout and direction */\n.dropdown-dialog[open] {\n display: flex;\n flex-direction: column;\n}\n\n/* Direction-based positioning with CSS classes */\n.dropdown-dialog.position-below {\n left: var(--dropdown-x);\n top: var(--dropdown-y);\n}\n\n.dropdown-dialog.position-above {\n left: var(--dropdown-x);\n bottom: var(--dropdown-y);\n top: auto;\n flex-direction: column-reverse;\n}\n\n.dropdown-dialog.position-above .dropdown-header {\n margin-top: 4px;\n}\n\n.dropdown-dialog.position-below .dropdown-header {\n margin-bottom: 4px;\n}\n\n.dropdown-dialog.position-below .dropdown-options {\n /* Optional: Add upward-pointing shadow for below positioning */\n box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1), var(--ty-shadow-md);\n}\n\n/* Animate when .open class is added */\n.dropdown-dialog.open {\n opacity: 1;\n}\n\n.dropdown-dialog.open .dropdown-options {\n opacity: 1;\n transform: translateY(0) scale(1);\n}\n\n.dropdown-dialog::backdrop {\n background: transparent;\n}\n\n/* ===== DIALOG HEADER ===== */\n\n.dropdown-header {\n display: flex;\n align-items: center;\n gap: var(--ty-spacing-2);\n position: relative;\n}\n\n.dropdown-search-input {\n width: 100%;\n min-width: 0;\n box-sizing: border-box;\n background: var(--input-bg, var(--ty-input-bg));\n color: var(--input-color, var(--ty-input-color));\n border: 1px solid var(--input-border, var(--ty-input-border));\n border-radius: var(--ty-radius-md);\n font-family: var(--ty-font-sans);\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n font-weight: var(--ty-font-normal);\n min-height: var(--ty-size-md);\n padding: var(--ty-spacing-2) var(--ty-spacing-3);\n padding-right: calc(var(--ty-spacing-3) + 1rem + var(--ty-spacing-2));\n transition: var(--ty-transition-all);\n outline: none;\n}\n\n.dropdown-search-input:focus {\n border-color: var(--input-border-focus, var(--ty-input-border-focus));\n box-shadow: 0 0 0 3px var(--input-shadow-focus, var(--ty-input-shadow-focus));\n}\n\n.dropdown-search-input:disabled {\n background-color: var(--input-disabled-bg, var(--ty-input-disabled-bg));\n color: var(--input-disabled-color, var(--ty-input-disabled-color));\n cursor: not-allowed;\n opacity: 0.6;\n}\n\n.dropdown-search-input::placeholder {\n color: var(--input-placeholder, var(--ty-input-placeholder));\n}\n\n.dropdown-search-chevron {\n position: absolute;\n top: 50%;\n right: var(--ty-spacing-3);\n transform: translateY(-50%);\n width: 1rem;\n height: 1rem;\n color: var(--input-placeholder, var(--ty-input-placeholder));\n transition: var(--ty-transition-transform);\n pointer-events: none;\n}\n\n.dropdown-search-chevron.open {\n transform: translateY(-50%) rotate(180deg);\n}\n\n.dropdown-search-chevron svg {\n width: 100%;\n height: 100%;\n}\n\n/* ===== SELECT FIELD-SPECIFIC STYLES ===== */\n\n/* Select stub modifications */\n.select-stub {\n min-height: var(--ty-size-md);\n display: flex;\n flex-wrap: wrap;\n gap: 0.25rem;\n align-items: center;\n padding: 0 2.5rem 0 0.75rem;\n /* Transitions - includes opacity for open state */\n transition: var(--ty-transition-all), opacity 0.2s ease;\n outline: none;\n background: var(--input-bg, var(--ty-input-bg));\n color: var(--input-color, var(--ty-input-color));\n border: 1px solid var(--select-accent, var(--input-border, var(--ty-input-border)));\n border-radius: var(--ty-radius-md);\n font-family: var(--ty-font-sans);\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n cursor: pointer;\n position: relative;\n width: 100%;\n box-sizing: border-box;\n}\n\n/* ===== SIZE MODIFIERS =====\n buildStubClasses() always stamps exactly one size class on .select-stub.\n min-height comes from the shared --ty-size-* tokens (same ones ty-input\n and ty-date-picker consume) so a given size is the same height on every\n field. Right padding stays 2.5rem for chevron room. Zero vertical\n padding — same fix as ty-input: with align-items:center on a flex\n container, ANY vertical padding adds on top of min-height instead of\n being absorbed by it, so a padded stub silently overflows past the\n shared field height (measured +3px at sm/md before this was zeroed).\n min-height + centering alone gets the exact height. */\n.select-stub.sm {\n min-height: var(--ty-size-sm);\n padding: 0 2.5rem 0 0.625rem;\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n}\n\n/* md matches the base rule; listed for parity/overrides */\n.select-stub.md {\n min-height: var(--ty-size-md);\n padding: 0 2.5rem 0 0.75rem;\n}\n\n.select-stub.lg {\n min-height: var(--ty-size-lg);\n padding: 0 2.5rem 0 0.875rem;\n font-size: var(--ty-font-base);\n line-height: var(--ty-leading-base);\n letter-spacing: var(--ty-tracking-base);\n}\n\n.select-stub:hover {\n border-color: var(--select-accent-bold, var(--input-border-hover, var(--ty-input-border-hover)));\n}\n\n.select-stub[disabled] {\n background-color: var(--input-disabled-bg, var(--ty-input-disabled-bg));\n color: var(--input-disabled-color, var(--ty-input-disabled-color));\n cursor: not-allowed;\n opacity: 0.6;\n}\n\n/* Hide stub when dropdown is open */\n.dropdown-wrapper:has(.dropdown-chevron.open) .select-stub {\n opacity: 0;\n pointer-events: none;\n}\n\n/* Open state — same escalation as ty-input's .focused: bolder border + ring.\n Applies whenever the stub stays visible while open (field skin without\n the opacity-hide above kicking in — e.g. single-select with no tags). */\n.dropdown-wrapper:has(.dropdown-chevron.open) .select-stub,\n.select-stub:focus,\n.select-stub:focus-visible {\n border-color: var(--select-accent-bold, var(--input-border-focus, var(--ty-input-border-focus)));\n box-shadow: 0 0 0 3px var(--select-ring, var(--input-shadow-focus, var(--ty-input-shadow-focus)));\n}\n\n/* Custom trigger (slot="trigger"): setupTriggerSlot() toggles this class when\n the consumer assigns their own content — the slot's fallback (start/selected/\n placeholder/end/chevron, i.e. the whole default field skin) is entirely\n replaced at that point, so the wrapping .select-stub itself must go bare.\n Without this, the stub's own border/background/padding and the open/focus\n ring above still wrapped the custom content in a second, unwanted outline. */\n.select-stub.custom-trigger {\n min-height: 0;\n padding: 0;\n border: none;\n background: transparent;\n}\n.select-stub.custom-trigger:hover,\n.dropdown-wrapper:has(.dropdown-chevron.open) .select-stub.custom-trigger,\n.select-stub.custom-trigger:focus,\n.select-stub.custom-trigger:focus-visible {\n border-color: transparent;\n box-shadow: none;\n}\n\n/* Hide stub chips when mobile dialog is open (let modal show them) */\n.dropdown-mode-mobile .dropdown-wrapper:has(.mobile-dialog[open]) .select-chips {\n display: none;\n}\n\n/* When tags are present, reduce padding to make room */\n.select-stub.has-tags {\n padding: 0.25rem 2.5rem 0.25rem 0.5rem;\n width: 100%;\n}\n\n.select-stub.has-tags slot[name="selected"] {\n display: flex;\n flex-wrap: wrap;\n gap: 0.25rem;\n}\n\n/* ===== CHEVRON INDICATOR ===== */\n\n.dropdown-chevron {\n position: absolute;\n top: 50%;\n right: var(--ty-spacing-3);\n transform: translateY(-50%);\n width: 1rem;\n height: 1rem;\n color: var(--input-placeholder, var(--ty-input-placeholder));\n transition: var(--ty-transition-transform);\n pointer-events: none;\n}\n\n.dropdown-chevron.open {\n transform: translateY(-50%) rotate(180deg);\n}\n\n.dropdown-chevron svg {\n width: 100%;\n height: 100%;\n}\n\n\n/* Tags container */\n.select-chips {\n display: flex;\n flex-wrap: wrap;\n gap: 0.5rem;\n align-items: center;\n min-width: 0;\n}\n\n.dropdown-placeholder {\n flex-grow: 1;\n color: var(--input-placeholder, var(--ty-input-placeholder, #9ca3af));\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n font-weight: var(--ty-font-light);\n font-style: italic;\n}\n\n/* Placeholder styling when tags are present */\n.dropdown-placeholder.hidden {\n display: none;\n}\n\n/* Options area styling - Override for select */\n.dropdown-options {\n opacity: 0;\n background: var(--input-bg, var(--ty-input-bg));\n border: 1px solid var(--input-border, var(--ty-input-border));\n border-radius: var(--ty-radius-lg);\n max-height: 16rem;\n width: 100%;\n max-width: 100%;\n overflow-x: hidden;\n overflow-y: auto;\n scroll-behavior: smooth;\n box-sizing: border-box;\n position: relative;\n box-shadow:\n 0 20px 25px -5px rgba(0, 0, 0, 0.1),\n 0 10px 10px -5px rgba(0, 0, 0, 0.04);\n\n /* Animation properties */\n transform: translateY(-8px) scale(0.95);\n transition:\n opacity 200ms cubic-bezier(0.16, 1, 0.3, 1),\n transform 200ms cubic-bezier(0.16, 1, 0.3, 1);\n\n /* Select-specific: flex wrap for tags */\n display: flex;\n flex-wrap: wrap;\n padding: 0.5rem;\n gap: 0.5rem;\n\n}\n\n/* Hide native scrollbar only when custom scrollbar is active */\n.dropdown-options.ty-custom-scroll {\n scrollbar-width: none;\n -ms-overflow-style: none;\n}\n\n.dropdown-options.ty-custom-scroll::-webkit-scrollbar {\n display: none;\n}\n\n/* Options wrapper - positioned container for scrollbar track */\n.dropdown-options-wrapper {\n position: relative;\n}\n\n/* Show custom scrollbar on hover */\n.dropdown-options-wrapper:hover .ty-scrollbar-track-y.has-overflow {\n opacity: 1;\n}\n\n/* Make ty-tags in dropdown clickable with pointer cursor */\n.dropdown-options ty-tag {\n user-select: none;\n transition: transform 0.1s ease;\n}\n\n.dropdown-options ty-tag:hover {\n transform: scale(1.02);\n}\n\n.dropdown-options ty-tag:active {\n transform: scale(0.98);\n}\n\n/* Visual feedback for selected tags in options */\n.dropdown-options ty-tag[selected] {\n opacity: 0.5;\n}\n\n/* Ensure ty-tag components in the select field have proper sizing */\n.select-chips ty-tag {\n max-width: 150px;\n}\n\n/* Responsive adjustments */\n@media (max-width: 640px) {\n .select-chips ty-tag {\n max-width: 100px;\n }\n}\n\n\n/* Ensure proper spacing in container layouts */\n.select-container {\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n}\n\n/* ===== DROPDOWN WRAPPER & LABEL ===== */\n\n.dropdown-wrapper {\n position: relative;\n display: block;\n width: 100%;\n}\n\n.ty-field-label {\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n font-weight: var(--ty-font-medium);\n color: var(--ty-label-color);\n margin-bottom: 6px;\n padding-left: 12px;\n display: flex;\n align-items: center;\n}\n\n/* Required indicator - using SVG icon */\n.required-icon {\n display: inline-flex;\n align-items: center;\n color: #ef4444;\n width: 12px;\n height: 12px;\n vertical-align: middle;\n margin-left: 4px;\n}\n\n.required-icon svg {\n width: 100%;\n height: 100%;\n}\n\n:host([disabled]) .select-container {\n pointer-events: none;\n}\n\n/* ============================================================================\n MOBILE MODAL STYLES\n ============================================================================ */\n\n.dropdown-mode-mobile .mobile-dialog {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n width: 100vw;\n height: 100dvh; /* dvh, not vh — shrinks with the on-screen keyboard so the\n dialog never sits partly behind it */\n max-width: 100vw;\n max-height: 100dvh;\n margin: 0;\n padding: 0;\n padding-top: 6dvh; /* Sit higher than the old 10vh, but 4dvh left the\n floating label with no headroom — it sits above\n .mobile-search-header via position:absolute, so it\n needs room inside this padding, not just inside the\n content box, or it crowds the very top of the screen */\n border: none;\n background: transparent; /* Backdrop handles background */\n /* Note: Don't set display - browser controls <dialog> visibility */\n align-items: flex-start;\n justify-content: center;\n opacity: 0;\n transition: opacity 300ms ease;\n}\n\n/* When opened via showModal(), add flex layout */\n.dropdown-mode-mobile .mobile-dialog[open] {\n display: flex;\n}\n\n.dropdown-mode-mobile .mobile-dialog.open {\n opacity: 1;\n}\n\n/* Native dialog backdrop with blur */\n.dropdown-mode-mobile .mobile-dialog::backdrop {\n background: rgba(0, 0, 0, 0.65); /* was 0.5 — needed more depth to reliably\n carry white header text/icons over a\n light page blurred behind it */\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n}\n\n.dropdown-mode-mobile .mobile-dialog-content {\n position: relative;\n display: flex;\n flex-direction: column;\n width: calc(100% - 32px); /* Side margins */\n max-width: 400px; /* Constrained width like dropdown */\n min-height: 200px;\n max-height: 90dvh; /* leaves room below the 6dvh padding-top, shrinks with keyboard */\n opacity: 0;\n transform: scale(0.95);\n transition: \n opacity 300ms cubic-bezier(0.16, 1, 0.3, 1),\n transform 300ms cubic-bezier(0.16, 1, 0.3, 1);\n}\n\n.dropdown-mode-mobile .mobile-dialog.open .mobile-dialog-content {\n opacity: 1;\n transform: scale(1);\n}\n\n.dropdown-mode-mobile .mobile-search-input:focus {\n border-color: var(--ty-border);\n}\n\n/* Mobile search header - label floats above, search + close below */\n.dropdown-mode-mobile .mobile-search-header {\n flex-shrink: 0;\n display: flex;\n flex-direction: column;\n margin-bottom: 16px;\n padding: 0;\n background: transparent;\n position: relative;\n}\n\n.dropdown-mode-mobile .mobile-header-content {\n display: flex;\n align-items: center;\n gap: 12px;\n width: 100%;\n /* When search is disabled, updateSearchVisibility() hides the icon+input\n (see select.ts) but leaves the close button as the row's only child —\n without this it falls back to flex-start and strands the button on the\n left. Harmless when search IS shown: the input's flex:1 already\n consumes all remaining space, so justify-content never gets a say. */\n justify-content: flex-end;\n}\n\n.dropdown-mode-mobile .mobile-header-label {\n position: absolute;\n bottom: 100%;\n left: 2px;\n margin-bottom: 8px; /* was 4px — too tight against the search row */\n font-size: var(--ty-font-base); /* was --ty-font-lg — read as oversized/heavy paired with 700 */\n line-height: var(--ty-leading-base);\n letter-spacing: var(--ty-tracking-base);\n font-weight: 600; /* was 700 — 700 at font-lg read as clunky */\n /* This sits on the dialog's ::backdrop (rgba(0,0,0,.65) + blur) — a fixed\n DARK overlay regardless of theme, not the theme's own surface color.\n A theme-toggling token (light mode → black) fights that: black text on\n a dark blurred backdrop is the wrong combination. Fixed white, same\n reasoning as ty-tooltip's deliberately theme-independent default in\n tyrell.css — this element's job is to pop against a dark backdrop in\n both themes, not to track the page's light/dark state. */\n color: #ffffff;\n pointer-events: none;\n}\n\n/* Close button — borderless ghost icon button (was a bordered circle badge,\n which read as a heavy, disconnected "chip" next to the plain search icon).\n Matches ty-button's ghost treatment: transparent at rest, soft neutral\n fill on hover/active, no border ever. */\n.dropdown-mode-mobile .mobile-close-button {\n flex-shrink: 0;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: none;\n border-radius: 50%;\n /* Same reasoning as .mobile-header-label: fixed white, not a theme token —\n this sits on the dark ::backdrop blur in both themes, never on a theme\n surface. */\n color: #ffffff;\n cursor: pointer;\n transition: var(--ty-transition-all);\n padding: 0;\n}\n\n/* Hover/active fills also go fixed-white-tinted rather than theme neutral —\n --ty-bg-neutral-soft is a LIGHT fill in light mode, which would swallow\n the white icon it's meant to sit behind. */\n.dropdown-mode-mobile .mobile-close-button:hover {\n background: rgba(255, 255, 255, 0.15);\n color: #ffffff;\n}\n\n.dropdown-mode-mobile .mobile-close-button:active {\n transform: scale(0.9);\n background: rgba(255, 255, 255, 0.25);\n}\n\n.dropdown-mode-mobile .mobile-close-button svg {\n width: 18px;\n height: 18px;\n}\n\n/* Mobile search input (matches dropdown.ts) */\n.dropdown-mode-mobile .mobile-search-input {\n flex: 1;\n min-width: 0;\n box-sizing: border-box;\n background: var(--ty-surface-floating);\n color: var(--ty-text);\n border: 2px solid;\n border-color: var(--mobile-border-color);\n border-radius: var(--ty-radius-md);\n font-family: var(--ty-font-sans);\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n font-weight: var(--ty-font-normal);\n padding: var(--ty-spacing-2) var(--ty-spacing-3);\n height: 40px;\n transition: var(--ty-transition-all);\n outline: none;\n}\n\n.dropdown-mode-mobile .mobile-search-input::placeholder {\n color: var(--ty-text-faint);\n}\n\n.dropdown-mode-mobile .mobile-search-input:focus {\n border-color: var(--ty-border);\n}\n\n/* ============================================================================\n MOBILE BODY & SECTIONS - UPDATED STRUCTURE\n ============================================================================ */\n\n/* Mobile body - contains both sections */\n.dropdown-mode-mobile .mobile-body {\n position: relative;\n display: flex;\n flex-direction: column;\n height: var(--body-height, 350px);\n max-height: 350px;\n overflow: hidden;\n background: var(--ty-surface-floating);\n border-radius: var(--ty-radius-lg);\n box-shadow: \n 0 20px 25px -5px rgba(0, 0, 0, 0.1),\n 0 10px 10px -5px rgba(0, 0, 0, 0.04);\n border: 2px solid;\n border-color: var(--mobile-border-color);\n}\n\n/* ===== SECTION HEADERS - Labels, not buttons ===== */\n\n.dropdown-mode-mobile .section-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n height: 36px;\n flex-shrink: 0;\n padding: 0 16px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--ty-text-bold);\n background: transparent;\n cursor: default;\n user-select: none;\n}\n\n.dropdown-mode-mobile .section-header .section-title {\n flex: 1;\n}\n\n.dropdown-mode-mobile .section-header .section-count {\n font-weight: 500;\n color: var(--ty-text-faint);\n margin-left: 0.25rem;\n}\n\n/* ===== SELECTED STRIP - pinned, capped height, collapses when empty ===== */\n\n.dropdown-mode-mobile .mobile-selected-section {\n display: flex;\n flex-direction: column;\n background: var(--ty-input-bg);\n overflow: hidden;\n flex: 0 0 auto;\n max-height: 40%;\n transition: max-height 200ms cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n/* Empty: collapse to header only */\n.dropdown-mode-mobile .mobile-selected-section[data-empty="true"] {\n max-height: 36px;\n flex: 0 0 36px;\n}\n\n.dropdown-mode-mobile .mobile-selected-section .section-content {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n padding: 0.75rem 1rem;\n display: flex;\n flex-wrap: wrap;\n gap: 0.5rem;\n align-content: flex-start;\n /* Soft fade at bottom edge — hints at scrollable overflow */\n -webkit-mask-image: linear-gradient(to bottom, black calc(100% - 12px), transparent);\n mask-image: linear-gradient(to bottom, black calc(100% - 12px), transparent);\n}\n\n/* ===== AVAILABLE LIST - takes remaining space ===== */\n\n.dropdown-mode-mobile .mobile-available-section {\n display: flex;\n flex-direction: column;\n background: var(--ty-input-bg);\n overflow: hidden;\n flex: 1 1 auto;\n min-height: 0;\n}\n\n.dropdown-mode-mobile .mobile-available-section .section-content {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n padding: 0.75rem 1rem;\n display: flex;\n flex-wrap: wrap;\n gap: 0.5rem;\n align-content: flex-start;\n}\n\n/* ===== EMPTY STATES =====\n Selected strip collapses (no text needed).\n Available shows the empty message only when there are zero tags total. */\n\n.dropdown-mode-mobile .empty-state {\n display: none;\n width: 100%;\n padding: 2rem 1rem;\n text-align: center;\n color: var(--ty-text-faint);\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n font-style: italic;\n}\n\n.dropdown-mode-mobile .mobile-available-section[data-empty="true"] .empty-state {\n display: block;\n}\n\n.dropdown-mode-mobile .mobile-selected-section[data-empty="true"] .section-content,\n.dropdown-mode-mobile .mobile-available-section[data-empty="true"] slot {\n display: none;\n}\n\n/* ===== TAG STYLING IN MOBILE ===== */\n\n.dropdown-mode-mobile .section-content ::slotted(ty-tag) {\n cursor: pointer;\n user-select: none;\n transition: transform 0.1s ease;\n margin: 2px 0; /* Vertical spacing like dropdown options */\n /* Fade + scale entry — replays on each (re)insertion when a tag moves\n between selected and available slots */\n animation: ty-select-tag-enter 180ms cubic-bezier(0.16, 1, 0.3, 1);\n}\n\n@media (hover: hover) {\n .dropdown-mode-mobile .section-content ::slotted(ty-tag:hover) {\n transform: scale(1.02);\n }\n}\n\n.dropdown-mode-mobile .section-content ::slotted(ty-tag:active) {\n transform: scale(0.96);\n}\n\n/* Dimmed appearance for hidden filtered tags */\n.dropdown-mode-mobile .section-content ::slotted(ty-tag[hidden]) {\n display: none !important;\n}\n\n@keyframes ty-select-tag-enter {\n from { opacity: 0; transform: scale(0.85); }\n to { opacity: 1; transform: scale(1); }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .dropdown-mode-mobile .section-content ::slotted(ty-tag) {\n animation: none;\n }\n}\n\n/* ==================== LOADING STATE ====================\n Spinner overlay shown inside the options area while the parent\n (external-search mode) is fetching. Search input stays usable.\n\n Carries its own surface so it stays visible even when the host\n has restyled the popup with a transparent or unusual background.\n Override with --ty-loader-bg / --ty-loader-radius / --ty-loader-border.\n*/\n.dropdown-loading {\n display: none;\n align-items: center;\n justify-content: center;\n gap: var(--ty-spacing-2);\n padding: var(--ty-spacing-4) var(--ty-spacing-3);\n color: var(--ty-text-soft);\n font-size: var(--ty-font-sm);\n min-height: 4rem;\n /* Match the .dropdown-options popup look — same background, border, radius, shadow */\n background: var(--ty-loader-bg, var(--input-bg, var(--ty-input-bg)));\n border: 1px solid var(--ty-loader-border, var(--input-border, var(--ty-input-border)));\n border-radius: var(--ty-loader-radius, var(--ty-radius-lg));\n box-shadow: var(--ty-loader-shadow, 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04));\n box-sizing: border-box;\n}\n\n.dropdown-options-wrapper.loading .dropdown-loading {\n display: flex;\n}\n\n/* Slot is transparent for layout — fallback (spinner + text) and user-provided\n slotted content both act as direct flex children of .dropdown-loading. */\n.dropdown-loading > slot[name="loading"] {\n display: contents;\n}\n\n/* Mobile: full-screen dialog is the surface — drop the card chrome,\n stack vertically, scale up so it feels native to a fullscreen view.\n Slotted content adapts automatically since the slot is display:contents. */\n.dropdown-mode-mobile .dropdown-loading {\n background: transparent;\n border: none;\n box-shadow: none;\n flex: 1;\n flex-direction: column;\n gap: var(--ty-spacing-3);\n padding: var(--ty-spacing-8) var(--ty-spacing-4);\n min-height: 12rem;\n}\n\n.dropdown-mode-mobile .dropdown-loading-spinner {\n width: 2rem;\n height: 2rem;\n}\n\n.dropdown-mode-mobile .dropdown-loading-text {\n font-size: var(--ty-font-base);\n}\n\n.dropdown-options-wrapper.loading .dropdown-options,\n.dropdown-options-wrapper.loading > slot#options-slot,\n.dropdown-options-wrapper.loading .empty-state {\n display: none;\n}\n\n.dropdown-loading-spinner {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1.125rem;\n height: 1.125rem;\n flex-shrink: 0;\n animation: ty-select-spin 0.7s linear infinite;\n /* Active-state indicator — full accent, not the soft resting shade */\n color: var(--select-accent-bold, var(--ty-color-primary));\n}\n\n.dropdown-loading-spinner svg {\n width: 100%;\n height: 100%;\n}\n\n.dropdown-loading-text {\n color: var(--ty-text-soft);\n}\n\n@keyframes ty-select-spin {\n to { transform: rotate(360deg); }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .dropdown-loading-spinner {\n animation-duration: 1.6s;\n }\n}\n\n/* Custom scrollbar styles */\n${St}\n\n/* ===== FLAVOR VARIANTS (set --select-accent*, consumed above) ===== */\n${r.filter(t=>"neutral"!==t).map(t=>Nn(t)).join("")}\n`;function qn(t=768){return window.matchMedia(`(pointer: coarse) and (max-width: ${t}px)`).matches}let Vn=0;const Fn=new WeakMap;function Pn(t){let n=Fn.get(t);return void 0===n&&(n=++Vn,Fn.set(t,n)),n}const Hn='<svg viewBox="0 0 20 20" fill="currentColor">\n <path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" />\n</svg>',jn='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">\n <circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/>\n</svg>',Bn=class extends i{constructor(){super(),this.sn="",this.rn=!1,this.an=!1,this.ln="Select...",this.cn="",this.F=!1,this.dn=!1,this.hn=!1,this.un=!1,this.pn=!1,this.bn="none",this.gn="auto",this.mn=!1,this.vn=null,this.fn="md",this.yn="Available",this.wn="No options available",this.xn={open:!1,search:"",highlightedIndex:-1,filteredTags:[],selectedValues:[],mode:"desktop"},this.kn=null,this.zn=null,this.$n=null,this.Cn=null,this.Sn=null,this.En=0,this.Tn=null,this.Mn=null,this.An=null,this.In=null,this.I=null;const t=this.shadowRoot;s(t,{css:Rn,id:"ty-select-base"}),s(t,{css:'\n/* ===== COMPACT skin: hugs content (field skin = base styles) ===== */\n.select-stub.compact {\n display: inline-flex;\n flex-wrap: nowrap;\n width: auto;\n gap: 0.5rem;\n /* extra right padding = room for the absolutely-positioned chevron */\n padding: 0.5rem 2.25rem 0.5rem 0.875rem;\n}\n\n/* Consumer-provided trigger (slot="trigger"): no chrome at all */\n.select-stub.custom-trigger {\n display: inline-block;\n border: none;\n background: none;\n padding: 0;\n min-height: 0;\n border-radius: 0;\n}\n.select-stub.custom-trigger:hover {\n border: none;\n}\n\n.select-count {\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 1.25rem;\n height: 1.25rem;\n padding: 0 0.375rem;\n border-radius: 9999px;\n /* --ty-text-primary never existed as a token — this silently fell back\n to inherited/unset color. Now follows the select\'s own flavor. */\n background: color-mix(in oklab, var(--select-accent, var(--ty-color-primary)) 15%, transparent);\n color: var(--select-accent-bold, var(--ty-color-primary-strong));\n font-size: var(--ty-font-xs);\n font-weight: var(--ty-font-semibold);\n font-style: normal;\n}\n.select-count[hidden] {\n display: none;\n}\n/* Selection text (field skin): single line, ellipsis, input colors */\n.select-stub .dropdown-placeholder {\n font-style: normal;\n flex: 1 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: var(--input-color, var(--ty-input-color));\n}\n\n/* Empty state: muted placeholder color */\n.select-stub .dropdown-placeholder.placeholder-shown {\n color: var(--input-placeholder, var(--ty-input-placeholder));\n}\n.select-stub .dropdown-placeholder[hidden] {\n display: none;\n}\n\n/* Single-select display clone (slot="selected"): the selected ty-option\n projected into the stub — its own :host([cloned]) styling strips the\n list-row chrome; here it just takes the text\'s flex slot. */\n.select-stub slot[name="selected"] {\n display: none;\n}\n.select-stub.has-clone slot[name="selected"] {\n display: block;\n flex: 1 1 auto;\n min-width: 0;\n overflow: hidden;\n}\n.select-stub.compact.has-clone slot[name="selected"] {\n flex: 0 1 auto;\n}\n\n/* start/end slot content (icons etc.) — spacing comes from the stub\'s flex\n gap; muted like ty-input adornments. end sits before the chevron. */\n.select-stub ::slotted([slot="start"]),\n.select-stub ::slotted([slot="end"]) {\n flex-shrink: 0;\n color: var(--ty-text-soft);\n}\n\n/* Compact skin: the text IS the trigger label — no grow, regular text color */\n.select-stub.compact .dropdown-placeholder {\n flex-grow: 0;\n color: var(--ty-text);\n}\n\n/* Trigger stays visible while the popup is open (the popup hides it) */\n.dropdown-wrapper:has(.dropdown-chevron.open) .select-stub {\n opacity: 1;\n pointer-events: auto;\n}\n\n/* ===== One-panel popup: search header fused with the options list ===== */\n\n/* Single unified shadow around the whole panel (header + list as one silhouette) */\n.dropdown-dialog.open {\n filter: drop-shadow(0 12px 24px rgba(0, 0, 0, 0.14)) drop-shadow(0 2px 6px rgba(0, 0, 0, 0.08));\n}\n\n/* Card-style header: the search input keeps its own bordered-field look\n (base styles) and sits inset in the panel, TagPicker-style — no divider,\n whitespace separates it from the list. */\n.dropdown-header {\n background: var(--input-bg, var(--ty-input-bg));\n border: 1px solid var(--input-border, var(--ty-input-border));\n border-bottom: none;\n border-radius: var(--ty-radius-lg) var(--ty-radius-lg) 0 0;\n padding: var(--ty-spacing-2) var(--ty-spacing-2) var(--ty-spacing-1);\n}\n.dropdown-dialog.position-below .dropdown-header {\n margin-bottom: 0;\n}\n.dropdown-dialog.position-above .dropdown-header {\n margin-top: 0;\n border-top: none;\n border-bottom: 1px solid var(--input-border, var(--ty-input-border));\n border-radius: 0 0 var(--ty-radius-lg) var(--ty-radius-lg);\n padding: var(--ty-spacing-1) var(--ty-spacing-2) var(--ty-spacing-2);\n}\n\n/* Magnifier adornment inside the search field (header padding + field inset) */\n.dropdown-search-icon {\n position: absolute;\n top: 50%;\n left: calc(var(--ty-spacing-2) + var(--ty-spacing-3));\n transform: translateY(-50%);\n width: 1rem;\n height: 1rem;\n color: var(--input-placeholder, var(--ty-input-placeholder));\n pointer-events: none;\n}\n.dropdown-search-icon svg {\n width: 100%;\n height: 100%;\n}\n\n/* Mobile header: flex row, icon flows inline before the input. Same 32x32\n footprint as .mobile-close-button (18px glyph centered in the box, not a\n bare 18px glyph flush at the edge) so the row has two matching bookends —\n a bare icon on one side and a 32px circle on the other read as lopsided\n even with equal flex gap on both sides. Matching them also centers the\n search input\'s flex:1 fill symmetrically between the two. Fixed white +\n 18px glyph, same reasoning as .mobile-header-label — this sits on the\n dark ::backdrop blur in both themes, not a theme surface. */\n.dropdown-mode-mobile .mobile-header-content .dropdown-search-icon {\n position: static;\n transform: none;\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n color: #ffffff;\n}\n.dropdown-mode-mobile .mobile-header-content .dropdown-search-icon svg {\n width: 18px;\n height: 18px;\n}\n\n/* Search input: bordered field from base styles; just size + icon room */\n.dropdown-search-input {\n min-height: 2.25rem;\n padding-right: var(--ty-spacing-2);\n /* room for the magnifier adornment */\n padding-left: calc(var(--ty-spacing-3) + 1rem + var(--ty-spacing-2));\n}\n/* Trigger already has a chevron - no second one inside the search row */\n.dropdown-search-chevron {\n display: none;\n}\n\n/* With the search row hidden nothing inside is focusable, so the <dialog>\n itself receives focus on open — suppress its UA focus ring */\n.dropdown-dialog:focus,\n.dropdown-dialog:focus-visible {\n outline: none;\n}\n\n/* Search row hidden (\'auto\' below threshold / searchable="false"):\n the options panel owns the whole silhouette */\n.dropdown-header[hidden] {\n display: none;\n}\n.dropdown-header[hidden] ~ .dropdown-options-wrapper .dropdown-options {\n border-top: 1px solid var(--input-border, var(--ty-input-border));\n border-radius: var(--ty-radius-lg);\n}\n.mobile-search-input[hidden],\n.mobile-header-content .dropdown-search-icon[hidden] {\n display: none;\n}\n\n/* Options: vertical list rows fused under the search header.\n No own shadow/animation - the panel appears as one via dialog opacity. */\n.dropdown-options {\n flex-direction: column;\n flex-wrap: nowrap;\n align-items: stretch;\n gap: 0;\n /* Card-style list: rounded rows sit inset from the panel edges */\n padding: var(--ty-spacing-1);\n border-top: none;\n border-radius: 0 0 var(--ty-radius-lg) var(--ty-radius-lg);\n box-shadow: none;\n transform: none;\n transition: none;\n /* ~9-10 visible rows before scrolling (custom scrollbar, native hidden) */\n max-height: 24rem;\n}\n.dropdown-dialog.position-below .dropdown-options {\n box-shadow: none;\n}\n.dropdown-dialog.position-above .dropdown-options {\n border-top: 1px solid var(--input-border, var(--ty-input-border));\n border-bottom: none;\n border-radius: var(--ty-radius-lg) var(--ty-radius-lg) 0 0;\n}\n\n/* Loading panel continues the fused silhouette exactly like .dropdown-options —\n the base layer styles it as a floating card (radius + shadow), which left a\n see-through gap under the search header while loading. */\n.dropdown-loading {\n border-top: none;\n border-radius: 0 0 var(--ty-radius-lg) var(--ty-radius-lg);\n box-shadow: none;\n}\n.dropdown-dialog.position-above .dropdown-loading {\n border-top: 1px solid var(--input-border, var(--ty-input-border));\n border-bottom: none;\n border-radius: var(--ty-radius-lg) var(--ty-radius-lg) 0 0;\n}\n\n/* Selection tick lives inside ty-option (lucide check on [selected]) */\n\n/* Mobile modal: same vertical list */\n.dropdown-mode-mobile .section-content ::slotted(ty-option) {\n display: block;\n width: 100%;\n}\n',id:"ty-select"})}onConnect(){this.shadowRoot.querySelectorAll("dialog").forEach(t=>{t.open&&t.close()}),this.render(),requestAnimationFrame(()=>{this.initializeState()}),this.An=new MutationObserver(()=>{this.ensureOptionRoles(),this.xn.selectedValues.length>0&&this.syncSelectedTags(this.xn.selectedValues),this.updateSearchVisibility(),this.updateSelectionDisplay(),this.updateMobileSelectedState()}),this.An.observe(this,{childList:!0}),this.ensureOptionRoles(),this.D()}D(){this.I=u(this.shadowRoot,this.I,this.getProperty("flavor"),({base:t})=>(t=>Nn(t,"neutral"))(t))}onDisconnect(){this.shadowRoot.querySelectorAll("dialog").forEach(t=>{t.open&&t.close()}),this.Sn&&(document.removeEventListener("keydown",this.Sn),this.Sn=null),null!==this.Tn&&(clearTimeout(this.Tn),this.Tn=null),this.Dn(),this.An&&(this.An.disconnect(),this.An=null)}onPropertiesChanged(t){for(const{name:n,newValue:e}of t)switch(n){case"value":const t=this.parseValue(e);this.xn.selectedValues=t,this.isConnected&&this.shadowRoot&&(this.syncSelectedTags(t),this.updateSelectionDisplay(),this.updateMobileSelectedState());break;case"name":this.sn=e||"";break;case"flavor":this.D();break;case"multiple":this.rn=e,!e&&this.xn.selectedValues.length>1&&this.updateComponentValue([this.xn.selectedValues[0]],!1,"set",null);break;case"compact":this.an=e;break;case"placeholder":this.ln=e||"Select...",this.isConnected&&this.shadowRoot&&this.updateSelectionDisplay();break;case"label":this.cn=e||"";break;case"disabled":this.F=e;break;case"readonly":this.dn=e;break;case"required":this.hn=e;break;case"externalSearch":this.un=e;break;case"searchable":this.gn=e,this.isConnected&&this.shadowRoot&&this.updateSearchVisibility();break;case"allowCreate":this.pn=e,this.isConnected&&this.shadowRoot&&this.updateSearchVisibility();break;case"createTransform":this.bn=e;break;case"size":this.fn=e;break;case"debounce":this.En=e;break;case"available-label":this.yn=e||"Available";break;case"no-options-message":this.wn=e||"No options available";break;case"loading":this.mn=e,this.applyLoadingState()}}applyLoadingState(){const t=this.shadowRoot;if(!t)return;const n=this.mn?g():null;t.querySelectorAll(".dropdown-options-wrapper").forEach(t=>{if(t.classList.toggle("loading",this.mn),this.mn){t.setAttribute("aria-busy","true");const e=t.querySelector(".dropdown-loading-spinner");e&&n&&(e.innerHTML=n)}else t.removeAttribute("aria-busy")})}getFormValue(){const t=this.xn.selectedValues;if(this.sn&&t.length>0){if(!this.rn)return t[0];const n=new FormData;return t.forEach(t=>{n.append(this.sn,t)}),n}return null}parseValue(t){return t&&"string"==typeof t&&""!==t.trim()?t.split(",").map(t=>t.trim()).filter(t=>""!==t):[]}initializeState(){const t=this.getProperty("value")||"";if(t){const n=this.parseValue(t);this.xn.selectedValues=n,this.syncSelectedTags(n),this.updateSelectionDisplay(),this.updateMobileSelectedState()}else{const t=this.getTagElements().filter(t=>t.hasAttribute("selected")).map(t=>this.getTagData(t).value);t.length>0&&this.updateComponentValue(t,!1)}}getTagElements(){return Array.from(this.querySelectorAll("ty-option:not([cloned]), ty-tag:not([cloned])"))}getTagData(t){return{value:t.value||t.getAttribute("value")||t.textContent||"",text:t.getAttribute("label")||t.textContent||"",element:t}}selectTag(t){t.setAttribute("selected","")}deselectTag(t){t.removeAttribute("selected")}getSelectedValues(){return this.getTagElements().filter(t=>t.hasAttribute("selected")).map(t=>this.getTagData(t).value).filter(t=>""!==t)}syncSelectedTags(t){const n=new Set(t);this.getTagElements().forEach(t=>{const e=this.getTagData(t).value,i=n.has(e),o=t.hasAttribute("selected");i&&!o?this.selectTag(t):!i&&o&&this.deselectTag(t),t.setAttribute("aria-selected",i+"")})}ensureOptionRoles(){this.getTagElements().forEach(t=>{t.hasAttribute("role")||t.setAttribute("role","option"),t.hasAttribute("aria-selected")||t.setAttribute("aria-selected","false")})}updateComponentValue(t,n=!1,e="set",i=null){const o=this.getSelectedValues(),s=t.join(",");JSON.stringify(t.sort())!==JSON.stringify(o.sort())&&(this.setProperty("value",s),n&&this.dispatchChangeEvent({value:this.rn?[...t]:t[0]??null,values:t,items:this.getSelectedItems(t),action:e,item:i}))}getSelectedItems(t){const n=new Map(this.getTagElements().map(t=>[this.getTagData(t).value,t]));return t.map(t=>{const e=n.get(t);return{value:t,label:e?.getAttribute("label")||e?.textContent?.trim()||t,flavor:e?.getAttribute("flavor")??null}})}calculatePosition(){const t=this.shadowRoot,n=t.querySelector(".select-stub"),e=t.querySelector(".dropdown-dialog");if(!n||!e)return;const i=n.getBoundingClientRect(),o=e.getBoundingClientRect(),s=Math.min(o.height||200,440),r=parseFloat(getComputedStyle(this).getPropertyValue("--ty-select-popup-width")),a=isNaN(r)?Math.max(i.width,320):r,l=Ot({anchorRect:i,popupWidth:a,popupHeight:s}),c=l.below,d=(c?l.topY:l.bottomY)-20,h=a+20+20;this.style.setProperty("--dropdown-x",l.x-20+"px"),this.style.setProperty("--dropdown-y",d+"px"),this.style.setProperty("--dropdown-width",h+"px"),this.style.setProperty("--dropdown-offset-x","0px"),this.style.setProperty("--dropdown-offset-y","0px"),this.style.setProperty("--dropdown-padding","20px"),c?(e.classList.add("position-below"),e.classList.remove("position-above")):(e.classList.add("position-above"),e.classList.remove("position-below")),this.style.setProperty("--dropdown-direction",c?"below":"above")}Ln(){if(!$t())return;const t=this.shadowRoot,n=t.querySelector(".dropdown-options"),e=t.querySelector(".dropdown-options-wrapper");n&&e&&(this.Dn(),n.classList.add("ty-custom-scroll"),this.Mn=new Ct(n,{vertical:!0}),this.Mn.trackY&&e.appendChild(this.Mn.trackY))}Dn(){this.Mn&&(this.Mn.trackY?.remove(),this.Mn.destroy(),this.Mn=null)}openDropdown(){const t=this.shadowRoot,n=t.querySelector(".dropdown-dialog");if(!n)return;const e=t.querySelector(".select-stub");e&&e.setAttribute("aria-expanded","true");const i=`select-${this.id||"anon"}-${Pn(this)}`;this.vn=i,sn(i),n.showModal(),n.classList.add("open"),this.calculatePosition(),this.xn.open=!0;const o=t.querySelector(".dropdown-chevron");o&&o.classList.add("open");const s=t.querySelector(".dropdown-search-chevron");s&&s.classList.add("open");const r=this.getTagElements().map(t=>this.getTagData(t));this.xn.filteredTags=r,this.xn.highlightedIndex=-1,this.updateOptionsVisibility(!0),this.Ln();const a=t.querySelector(".dropdown-search-input");a&&this.shouldShowSearch()&&setTimeout(()=>a.focus(),100),this.fireOpenEvent()}closeDropdown(){const t=this.shadowRoot,n=t.querySelector(".dropdown-dialog");if(!n)return;const e=t.querySelector(".select-stub");e&&e.setAttribute("aria-expanded","false"),this.Dn(),n.classList.remove("open"),n.classList.remove("position-above"),n.classList.remove("position-below"),n.close(),this.vn&&(rn(this.vn),this.vn=null),this.xn.open=!1,this.xn.highlightedIndex=-1;const i=t.querySelector(".dropdown-chevron");i&&i.classList.remove("open");const o=t.querySelector(".dropdown-search-chevron");o&&o.classList.remove("open");const s=""!==this.xn.search;this.xn.search="";const r=t.querySelector(".dropdown-search-input");if(r&&(r.value=""),this.un)s&&(null!==this.Tn&&(clearTimeout(this.Tn),this.Tn=null),this.fireSearchEvent(""));else{const t=this.getTagElements().map(t=>this.getTagData(t));this.xn.filteredTags=t,this.updateTagVisibility(t,t),this.clearHighlights(t)}this.fireCloseEvent()}openMobileModal(){const t=this.shadowRoot,n=t.querySelector(".mobile-dialog");if(!n)return;const e=t.querySelector(".select-stub");e&&e.setAttribute("aria-expanded","true");const i=`select-${this.id||"anon"}-${Pn(this)}`;this.vn=i,sn(i),n.showModal(),n.classList.add("open"),this.xn.open=!0;const o=this.getTagElements().map(t=>this.getTagData(t));this.xn.filteredTags=o,this.updateTagVisibility(o,o),requestAnimationFrame(()=>{this.updateMobileSelectedState()}),this.fireOpenEvent()}closeMobileModal(){const t=this.shadowRoot,n=t.querySelector(".mobile-dialog");if(!n)return;const e=t.querySelector(".select-stub");e&&e.setAttribute("aria-expanded","false"),n.classList.remove("open"),n.close(),this.vn&&(rn(this.vn),this.vn=null),this.xn.open=!1,this.xn.highlightedIndex=-1;const i=""!==this.xn.search;this.xn.search="";const o=t.querySelector(".mobile-search-input");o&&(o.value=""),this.un?i&&(null!==this.Tn&&(clearTimeout(this.Tn),this.Tn=null),this.fireSearchEvent("")):this.getTagElements().forEach(t=>t.removeAttribute("hidden")),this.fireCloseEvent()}handleStubClick(t){t.preventDefault(),t.stopPropagation(),this.F||this.dn||this.openDropdown()}handleStubKeydown(t){this.F||this.dn||this.xn.open||"Enter"!==t.key&&" "!==t.key&&"ArrowDown"!==t.key||(t.preventDefault(),this.openDropdown())}handleTagClick(t){const n=t.target.closest("ty-option, ty-tag");n&&!n.hasAttribute("disabled")&&(t.preventDefault(),t.stopPropagation(),this.selectByTag(n))}selectByTag(t){const n=this.getTagData(t).value,e=this.getSelectedValues();if(!this.rn)return this.updateComponentValue([n],!0,"set",n),void("mobile"===this.xn.mode?this.closeMobileModal():this.closeDropdown());if(t.hasAttribute("selected")){const t=e.filter(t=>t!==n);this.updateComponentValue(t,!0,"remove",n)}else this.updateComponentValue([...e,n],!0,"add",n)}tryCreateFromSearch(){if(!this.pn)return!1;const t=(this.xn.search||"").trim();if(!t)return!1;const n=t.toLowerCase(),e=this.getTagElements().map(t=>this.getTagData(t)).find(t=>t.value.toLowerCase()===n||t.text.toLowerCase()===n);if(e)return this.selectByTag(e.element),!0;const i=t,o="slug"===this.bn?i.trim().toLowerCase().replace(/\s+/g,"_").replace(/[^a-z0-9_]/g,"").replace(/_+/g,"_").replace(/^_|_$/g,""):i;if(!o)return!0;const s={value:o,label:i},r=new CustomEvent("create",{detail:s,bubbles:!0,composed:!0,cancelable:!0});if(this.dispatchEvent(r),r.defaultPrevented)return!0;const a=s.value,l=document.createElement("ty-option");if(l.setAttribute("value",a),l.textContent=i,this.appendChild(l),!this.rn)return this.updateComponentValue([a],!0,"create",a),"mobile"===this.xn.mode?this.closeMobileModal():this.closeDropdown(),!0;const c=this.getSelectedValues();return this.updateComponentValue([...c,a],!0,"create",a),this.clearSearchAfterCreate(),!0}clearSearchAfterCreate(){this.xn.search="",this.xn.highlightedIndex=-1;const t=this.shadowRoot;if(!t)return;const n=t.querySelector(".dropdown-search-input"),e=t.querySelector(".mobile-search-input");n&&(n.value=""),e&&(e.value="");const i=this.getTagElements().map(t=>this.getTagData(t));this.xn.filteredTags=i,this.updateTagVisibility(i,i),this.updateOptionsVisibility(!0),this.clearHighlights(i),this.updateMobileSelectedState(),(n??e)?.focus()}blockSearchClick(t){t.stopPropagation(),t.preventDefault()}handleSearchInput(t){const n=t.target.value;if(this.xn.search=n,this.un)return void this.dispatchSearchEvent(n);const e=this.getTagElements().map(t=>this.getTagData(t)),i=this.filterTags(e,n);this.xn.filteredTags=i,this.xn.highlightedIndex=-1,this.updateTagVisibility(i,e),this.updateOptionsVisibility(i.length>0),this.updateMobileSelectedState(),this.clearHighlights(e)}handleKeyboard(t){if(!this.xn.open)return;const n=this.shadowRoot.querySelector(".dropdown-search-input");if(t.target!==n&&document.activeElement===n)return;const e=this.xn.filteredTags,i=e.length,o=this.xn.highlightedIndex;switch(t.key){case"Escape":t.preventDefault(),t.stopPropagation(),this.closeDropdown();break;case"Enter":t.preventDefault(),t.stopPropagation(),o>=0&&i>o?this.selectByTag(e[o].element):this.tryCreateFromSearch();break;case"ArrowUp":let n;t.preventDefault(),t.stopPropagation(),n=0===i?-1:-1===o||0===o?i-1:o-1,this.xn.highlightedIndex=n,this.highlightTag(e,n);break;case"ArrowDown":let s;t.preventDefault(),t.stopPropagation(),s=0===i?-1:-1===o||o===i-1?0:o+1,this.xn.highlightedIndex=s,this.highlightTag(e,s)}}filterTags(t,n){if(!n||""===n.trim())return t;const e=n.toLowerCase();return t.filter(({text:t})=>t.toLowerCase().includes(e))}updateTagVisibility(t,n){const e=new Set(t.map(t=>t.value));n.forEach(({value:t,element:n})=>{e.has(t)?n.removeAttribute("hidden"):n.setAttribute("hidden","")})}updateOptionsVisibility(t){const n=this.shadowRoot.querySelector(".dropdown-options");n&&(n.style.display=t?"":"none")}clearHighlights(t){t.forEach(({element:t})=>{t.removeAttribute("highlighted")})}highlightTag(t,n){if(this.clearHighlights(t),n>=0&&t.length>n){const{element:e}=t[n];e.setAttribute("highlighted",""),e.scrollIntoView({behavior:"smooth",block:"nearest",inline:"nearest"})}}dispatchSearchEvent(t){null!==this.Tn&&(clearTimeout(this.Tn),this.Tn=null),this.En>0?this.Tn=window.setTimeout(()=>{this.fireSearchEvent(t),this.Tn=null},this.En):this.fireSearchEvent(t)}fireSearchEvent(t){this.dispatchEvent(new CustomEvent("search",{detail:{query:t,element:this},bubbles:!0,composed:!0}))}fireOpenEvent(){this.dispatchEvent(new CustomEvent("open",{detail:{mode:this.xn.mode,element:this},bubbles:!0,composed:!0})),this.un&&this.fireSearchEvent("")}fireCloseEvent(){this.dispatchEvent(new CustomEvent("close",{detail:{mode:this.xn.mode,element:this},bubbles:!0,composed:!0}))}dispatchChangeEvent(t){this.dispatchEvent(new CustomEvent("change",{detail:t,bubbles:!0,cancelable:!0}))}render(){this.xn.mode=qn()?"mobile":"desktop","mobile"===this.xn.mode?this.renderMobile():this.renderDesktop(),this.updateSearchVisibility(),this.applyLoadingState()}setupTriggerSlot(){const t=this.shadowRoot,n=t.querySelector(".select-stub"),e=t.querySelector('slot[name="trigger"]');if(!n||!e)return;const i=()=>n.classList.toggle("custom-trigger",e.assignedElements().length>0);e.addEventListener("slotchange",i),i()}setupEventListeners(){const t=this.shadowRoot,n=t.querySelector(".select-stub"),e=t.querySelector("#options-slot"),i=t.querySelector(".dropdown-search-input");n&&(this.kn=this.handleStubClick.bind(this),n.addEventListener("click",this.kn),n.addEventListener("keydown",this.handleStubKeydown.bind(this))),this.setupTriggerSlot(),e&&(this.zn=this.handleTagClick.bind(this),e.addEventListener("click",this.zn)),i&&(this.$n=this.handleSearchInput.bind(this),this.Cn=this.blockSearchClick.bind(this),i.addEventListener("input",this.$n),i.addEventListener("click",this.Cn));const o=t.querySelector(".dropdown-dialog");o&&o.addEventListener("click",t=>{t.target===o&&this.closeDropdown()}),this.Sn=this.handleKeyboard.bind(this),document.addEventListener("keydown",this.Sn)}buildStubClasses(){const t=[this.fn];return this.F&&t.push("disabled"),this.an&&t.push("compact"),t.join(" ")}renderDesktop(){const t=this.shadowRoot;if(!t.querySelector(".select-container")){const n=this.buildStubClasses(),e="select-listbox-"+Pn(this),i="select-label-"+Pn(this);t.innerHTML=`\n <div class="select-container dropdown-mode-desktop">\n ${this.cn?`\n <label class="ty-field-label" id="${i}">\n ${this.cn}\n ${this.hn?`<span class="required-icon">${X}</span>`:""}\n </label>\n `:""}\n <div class="dropdown-wrapper">\n <div class="dropdown-stub select-stub ${n}"\n role="combobox"\n aria-haspopup="listbox"\n aria-expanded="false"\n aria-controls="${e}"\n ${this.cn?`aria-labelledby="${i}"`:""}\n tabindex="${this.F?"-1":"0"}"\n ${this.F?'disabled aria-disabled="true"':""}>\n <slot name="trigger">\n <slot name="start"></slot>\n <slot name="selected"></slot>\n <span class="dropdown-placeholder">${this.ln}</span>\n <span class="select-count" hidden></span>\n <slot name="end"></slot>\n <div class="dropdown-chevron">\n ${Hn}\n </div>\n </slot>\n </div>\n <dialog class="dropdown-dialog">\n <div class="dropdown-header">\n <div class="dropdown-search-icon" aria-hidden="true">\n ${jn}\n </div>\n <input\n class="dropdown-search-input ${this.fn}"\n type="text"\n placeholder="Search..."\n ${this.F?"disabled":""}\n />\n <div class="dropdown-search-chevron">\n ${Hn}\n </div>\n </div>\n <div class="dropdown-options-wrapper">\n <div class="dropdown-options" id="${e}" role="listbox" ${this.rn?'aria-multiselectable="true"':""}>\n <slot id="options-slot"></slot>\n </div>\n <div class="dropdown-loading" aria-hidden="true">\n <slot name="loading">\n <span class="dropdown-loading-spinner"></span>\n <span class="dropdown-loading-text">Searching…</span>\n </slot>\n </div>\n </div>\n </dialog>\n </div>\n </div>\n `,this.setupEventListeners()}this.updateSelectionDisplay()}renderMobile(){const t=this.shadowRoot;if(!t.querySelector(".select-container")){const n=this.buildStubClasses(),e="select-listbox-"+Pn(this),i="select-label-"+Pn(this);t.innerHTML=`\n <div class="select-container dropdown-mode-mobile">\n ${this.cn?`\n <label class="ty-field-label" id="${i}">\n ${this.cn}\n ${this.hn?`<span class="required-icon">${X}</span>`:""}\n </label>\n `:""}\n <div class="dropdown-wrapper">\n <div class="dropdown-stub select-stub ${n}"\n role="combobox"\n aria-haspopup="listbox"\n aria-expanded="false"\n aria-controls="${e}"\n ${this.cn?`aria-labelledby="${i}"`:""}\n tabindex="${this.F?"-1":"0"}"\n ${this.F?'disabled aria-disabled="true"':""}>\n <slot name="trigger">\n <slot name="start"></slot>\n <slot name="selected"></slot>\n <span class="dropdown-placeholder">${this.ln}</span>\n <span class="select-count" hidden></span>\n <slot name="end"></slot>\n <div class="dropdown-chevron">\n ${Hn}\n </div>\n </slot>\n </div>\n\n <dialog class="mobile-dialog">\n <div class="mobile-dialog-content">\n\n \x3c!-- HEADER (matches dropdown.ts) --\x3e\n \n <div class="mobile-search-header">\n ${this.cn?`<span class="mobile-header-label">${this.cn}</span>`:""}\n <div class="mobile-header-content">\n <div class="dropdown-search-icon" aria-hidden="true">\n ${jn}\n </div>\n <input\n class="mobile-search-input ${this.fn}"\n type="text"\n placeholder="${this.cn?`Search ${this.cn}...`:"Search..."}"\n autofocus\n ${this.F?"disabled":""}\n />\n <button class="mobile-close-button" type="button" aria-label="Close">\n <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">\n <line x1="18" y1="6" x2="6" y2="18"></line>\n <line x1="6" y1="6" x2="18" y2="18"></line>\n </svg>\n </button>\n </div>\n </div>\n \n\n \x3c!-- BODY: options list with toggleable selected state --\x3e\n <div class="mobile-body">\n\n \x3c!-- AVAILABLE LIST (always visible, takes remaining space) --\x3e\n <div class="mobile-available-section" data-empty="false">\n <div class="section-header">\n <span class="section-title">${this.yn}</span>\n </div>\n <div class="section-content dropdown-options-wrapper" id="${e}" role="listbox" ${this.rn?'aria-multiselectable="true"':""}>\n <slot id="options-slot"></slot>\n <div class="empty-state">${this.wn}</div>\n <div class="dropdown-loading" aria-hidden="true">\n <slot name="loading">\n <span class="dropdown-loading-spinner"></span>\n <span class="dropdown-loading-text">Searching…</span>\n </slot>\n </div>\n </div>\n </div>\n\n </div>\n </div>\n </dialog>\n </div>\n </div>\n `,this.setupMobileEventListeners()}this.updateSelectionDisplay()}setupMobileEventListeners(){const t=this.shadowRoot,n=t.querySelector(".select-stub"),e=t.querySelector("#options-slot"),i=t.querySelector(".mobile-search-input"),o=t.querySelector(".mobile-close-button"),s=t.querySelector(".mobile-dialog");n&&(n.addEventListener("click",t=>this.handleMobileStubClick(t)),n.addEventListener("keydown",t=>this.handleMobileStubKeydown(t))),this.setupTriggerSlot(),e&&e.addEventListener("click",t=>this.handleMobileTagClick(t)),i&&i.addEventListener("input",t=>this.handleSearchInput(t)),o&&o.addEventListener("click",()=>this.closeMobileModal()),s&&(s.addEventListener("click",t=>{t.target===s&&this.closeMobileModal()}),s.addEventListener("cancel",t=>{t.preventDefault(),this.closeMobileModal()}))}handleMobileStubClick(t){t.preventDefault(),t.stopPropagation(),this.F||this.dn||this.openMobileModal()}handleMobileStubKeydown(t){this.F||this.dn||this.xn.open||"Enter"!==t.key&&" "!==t.key&&"ArrowDown"!==t.key||(t.preventDefault(),this.openMobileModal())}handleMobileTagClick(t){this.handleTagClick(t)}updateMobileSelectedState(){if("mobile"!==this.xn.mode)return;const t=this.shadowRoot,n=t.querySelector(".mobile-available-section");if(n){const e=this.getTagElements().filter(t=>!t.hasAttribute("hidden")).length;n.setAttribute("data-empty",(0===e)+"");const i=t.querySelector(".mobile-available-section .section-title");i&&(i.textContent=`${this.yn} (${e})`)}}shouldShowSearch(){return!!this.un||!!this.pn||"always"===this.gn||"never"!==this.gn&&this.getTagElements().length>7}updateSearchVisibility(){const t=this.shadowRoot;if(!t)return;const n=this.shouldShowSearch(),e=t.querySelector(".dropdown-header");e&&(e.hidden=!n);const i=t.querySelector(".mobile-search-input");i&&(i.hidden=!n);const o=t.querySelector(".mobile-header-content .dropdown-search-icon");o&&(o.hidden=!n)}updateSelectionDisplay(){const t=this.shadowRoot.querySelector(".select-stub");if(!t)return;const n=this.xn.selectedValues,e=n.length;t.classList.toggle("has-selection",e>0),t.classList.toggle("compact",this.an);const i=t.querySelector(".select-count");i&&(i.textContent=e+"",i.hidden=0===e||!this.rn||!this.an);const o=!this.rn&&e>0?n[0]:null;this.syncSelectedClone(o),t.classList.toggle("has-clone",null!==o);const s=t.querySelector(".dropdown-placeholder");s&&(s.hidden=null!==o,e>0&&this.rn&&!this.an?(s.textContent=this.getSelectedItems(n).map(t=>t.label).join(", "),s.classList.remove("placeholder-shown")):(s.textContent=this.ln,s.classList.add("placeholder-shown")))}syncSelectedClone(t){const n=this.querySelector(':scope > [cloned][slot="selected"]');if(n?.getAttribute("value")===t)return void(this.In=n);if(n?.remove(),null===t)return void(this.In=null);const e=this.getTagElements().find(n=>this.getTagData(n).value===t);if(e){const t=e.cloneNode(!0);t.removeAttribute("selected"),t.setAttribute("slot","selected"),t.setAttribute("cloned","true"),this.appendChild(t),this.In=t}else if(this.In?.getAttribute("value")===t){const t=this.In.cloneNode(!0);this.appendChild(t),this.In=t}}deselectValue(t){const n=this.getSelectedValues();n.includes(t)&&this.updateComponentValue(n.filter(n=>n!==t),!0,"remove",t)}get value(){return this.getSelectedValues().join(",")}set value(t){this.setProperty("value",t)}get name(){return this.getProperty("name")}set name(t){this.setProperty("name",t)}get multiple(){return this.getProperty("multiple")}set multiple(t){this.setProperty("multiple",t)}get compact(){return this.getProperty("compact")}set compact(t){this.setProperty("compact",t)}get placeholder(){return this.getProperty("placeholder")}set placeholder(t){this.setProperty("placeholder",t)}get label(){return this.getProperty("label")}set label(t){this.setProperty("label",t)}get disabled(){return this.getProperty("disabled")}set disabled(t){this.setProperty("disabled",t)}get loading(){return this.getProperty("loading")}set loading(t){this.setProperty("loading",t)}get readonly(){return this.getProperty("readonly")}set readonly(t){this.setProperty("readonly",t)}get required(){return this.getProperty("required")}set required(t){this.setProperty("required",t)}get searchable(){return this.getProperty("searchable")}set searchable(t){this.setProperty("searchable",t)}get externalSearch(){return this.getProperty("externalSearch")}set externalSearch(t){this.setProperty("externalSearch",t)}get debounce(){return this.getProperty("debounce")}set debounce(t){this.setProperty("debounce","string"==typeof t?parseInt(t,10):t)}get size(){return this.getProperty("size")}set size(t){this.setProperty("size",t)}get flavor(){return this.getProperty("flavor")}set flavor(t){this.setProperty("flavor",t)}get form(){return this.v.form}};Bn.properties={value:{type:"string",visual:!0,formValue:!0,emitChange:!1,default:"",coerce:t=>Array.isArray(t)?t.join(","):null==t?"":t+""},name:{type:"string",default:""},multiple:{type:"boolean",visual:!0,default:!1},compact:{type:"boolean",visual:!0,default:!1},placeholder:{type:"string",visual:!0,default:"Select..."},label:{type:"string",visual:!0,default:""},disabled:{type:"boolean",visual:!0,default:!1},readonly:{type:"boolean",visual:!0,default:!1},required:{type:"boolean",visual:!0,default:!1},externalSearch:{type:"boolean",visual:!0,default:!1,aliases:{"external-search":!0}},allowCreate:{type:"boolean",visual:!0,default:!1,aliases:{"allow-create":!0}},createTransform:{type:"string",visual:!1,default:"none",aliases:{"create-transform":!0},coerce:t=>"slug"===t?"slug":"none"},searchable:{type:"string",visual:!0,default:"auto",coerce:t=>!0===t||""===t||"true"===t?"always":!1===t||"false"===t?"never":"auto"},size:{type:"string",visual:!0,default:"md",validate:t=>["sm","md","lg"].includes(t),coerce:t=>"xs"===t?"sm":"xl"===t?"lg":["sm","md","lg"].includes(t)?t:"md"},debounce:{type:"number",default:0,validate:t=>t>=0&&5e3>=t,coerce:t=>{const n=+t;return isNaN(n)?0:Math.max(0,Math.min(5e3,n))}},"available-label":{type:"string",visual:!0,default:"Available"},"no-options-message":{type:"string",visual:!0,default:"No options available"},loading:{type:"boolean",visual:!0,default:!1},flavor:{type:"string",visual:!0,default:"neutral"}};let Wn=Bn;function _n(t,n){return t.replace(/\{([\w-]+)\}/g,(t,e)=>n[e]??t)}customElements.get("ty-select")||customElements.define("ty-select",Wn);class TySelectedTags extends HTMLElement{constructor(){super(...arguments),this.On=null,this.Nn=()=>this.renderChips(),this.An=null,this.Rn=null,this.qn=null}static get observedAttributes(){return["for"]}connectedCallback(){this.style.display||(this.style.display="contents"),this.bind(),this.renderChips(),this.An=new MutationObserver(()=>{this.template()!==this.qn&&this.renderChips()}),this.An.observe(this,{childList:!0})}disconnectedCallback(){this.unbind(),this.An?.disconnect(),this.An=null}attributeChangedCallback(){this.isConnected&&(this.bind(),this.renderChips())}resolvePicker(){const t=this.getAttribute("for");return(t?document.getElementById(t):this.previousElementSibling)??null}bind(){const t=this.resolvePicker();t!==this.On&&(this.unbind(),this.On=t,this.On?.addEventListener("change",this.Nn),this.On&&(this.Rn=new MutationObserver(()=>this.renderChips()),this.Rn.observe(this.On,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["selected"]})))}unbind(){this.On?.removeEventListener("change",this.Nn),this.Rn?.disconnect(),this.Rn=null,this.On=null}values(){return(this.On?.value??"").split(",").map(t=>t.trim()).filter(Boolean)}template(){return this.querySelector(":scope > template")}context(t){const n=this.On?.querySelector(`[value="${CSS.escape(t)}"]`),e={value:t,label:n?.getAttribute("label")||n?.textContent?.trim()||t,flavor:n?.getAttribute("flavor")??""};if(n)for(const i of Array.from(n.attributes))i.name.startsWith("data-")&&(e[i.name]=i.value);return e}templateSource(t){if(t.content.firstElementChild)return t.content;const n=document.createDocumentFragment();return t.childNodes.forEach(t=>n.appendChild(t.cloneNode(!0))),n}stampTemplate(t,n){const e=this.context(n),i=this.templateSource(t).cloneNode(!0),o=document.createTreeWalker(i,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_TEXT);for(let s=o.nextNode();s;s=o.nextNode())if(s.nodeType===Node.TEXT_NODE)s.textContent?.includes("{")&&(s.textContent=_n(s.textContent,e));else{const t=s;for(const n of Array.from(t.attributes)){if(!n.value.includes("{"))continue;const i=_n(n.value,e);!/^\{[\w-]+\}$/.test(n.value)||""!==i&&i!==n.value?t.setAttribute(n.name,i):t.removeAttribute(n.name)}}for(const s of Array.from(i.children))s.addEventListener("dismiss",t=>{t.stopPropagation(),this.deselect(n)});return i}defaultChip(t){const n=this.context(t),e=document.createElement("ty-tag");return e.setAttribute("value",t),e.setAttribute("dismissible","true"),n.flavor&&e.setAttribute("flavor",n.flavor),e.textContent=n.label,e.addEventListener("dismiss",()=>this.deselect(t)),e}renderChips(){const t=this.template();if(this.qn=t,!this.On)return void this.replaceChildren(...t?[t]:[]);const n=document.createDocumentFragment();t&&n.appendChild(t);for(const e of this.values())n.appendChild(t?this.stampTemplate(t,e):this.defaultChip(e));this.replaceChildren(n)}deselect(t){if(!this.On)return;const n=this.On;"function"==typeof n.deselectValue?n.deselectValue(t):(n.value=this.values().filter(n=>n!==t).join(","),this.renderChips())}}customElements.get("ty-selected-tags")||customElements.define("ty-selected-tags",TySelectedTags);const Yn=new WeakMap,Un=new WeakMap;function Gn(t){return{width:t.getAttribute("width")||"100%",height:t.getAttribute("height")||"400px",active:t.getAttribute("active"),placement:t.getAttribute("placement")||"top"}}function Kn(t){return Array.from(t.querySelectorAll("ty-tab"))}function Zn(t){return t.getAttribute("id")}function Xn(t,n){const e=Zn(n);return e&&function(t,n){return null!==t.querySelector(`[slot='label-${n}']`)}(t,e)?"slot":"text"}function Jn(t){return t.hasAttribute("disabled")}function Qn(t,n){const e=t.findIndex(t=>Zn(t)===n);return 0>e?void 0:e}function te(t,n){const e=t.getAttribute("active");return e&&void 0!==Qn(n,e)?e:n.length>0?Zn(n[0]):null}function ne(t){const n=Yn.get(t);if(!n)return;const e=t.shadowRoot;e&&(n.tabClickHandlers.forEach((t,n)=>{const i=e.querySelector(`[data-tab-id='${n}']`);i&&i.removeEventListener("pointerdown",t)}),n.tabClickHandlers.clear())}function ee(t,n,e){ne(t);const i={tabClickHandlers:new Map};e.forEach(e=>{const o=Zn(e);if(!o)return;const s=n.querySelector(`[data-tab-id='${o}']`);if(s){const n=n=>function(t,n,e){e.preventDefault(),e.stopPropagation(),function(t,n){t.setAttribute("active",n)}(t,n)}(t,o,n);s.addEventListener("pointerdown",n),i.tabClickHandlers.set(o,n)}}),Yn.set(t,i)}function ie(t,n){const e=t.shadowRoot;if(!e)return;const i=e.querySelector(".panels-wrapper");i&&(i.style.transform=`translateX(-${n*t.offsetWidth}px)`)}function oe(t,n,e){Kn(t).forEach(i=>{const o=Zn(i);if(!o)return;const s=n.querySelector(`[data-tab-id='${o}']`),r=o===e;if(s){s.setAttribute("aria-selected",r+""),s.setAttribute("tabindex",r?"0":"-1"),s.setAttribute("data-active",r+"");const n=t.querySelector(`[slot='label-${o}']`);n&&n.setAttribute("data-active",r+"")}})}function se(t,n){Kn(t).forEach(t=>{const e=Zn(t);if(!e)return;const i=e===n;t.setAttribute("data-active",i+""),i?(t.style.pointerEvents="auto",t.style.opacity="1"):(t.style.pointerEvents="none",t.style.opacity="0")})}function re(t,n){const e=t.shadowRoot;if(!e)return;const i=e.querySelector(".marker-wrapper");if(!i)return;const o=function(t,n,e){const i=n.querySelector(`[data-tab-id='${e}']`),o=n.querySelector(".tab-buttons");if(!i||!o)return null;const s=i.getBoundingClientRect();return{left:i.offsetLeft,top:i.offsetTop,width:s.width,height:s.height}}(0,e,n);if(!o)return;const s=!i.style.left||0===i.offsetWidth;s&&(i.style.transition="none"),i.style.left=o.left+"px",i.style.top=o.top+"px",i.style.width=o.width+"px",i.style.height=o.height+"px",s&&(i.style.transition="")}function ae(t){const n=t.shadowRoot;if(!n)return;const{width:e,height:i,placement:o}=Gn(t),r=Kn(t),a=te(t,r),l=a?Qn(r,a)??0:0;r.forEach(t=>{const n=Zn(t);n&&(t.setAttribute("role","tabpanel"),t.setAttribute("aria-labelledby","tab-"+n),t.setAttribute("tabindex","0"))});const c=n.querySelector(".tabs-container"),d=n.querySelector(".tab-buttons"),h=n.querySelector(".panels-viewport");if(s(n,{css:'\n:host {\n display: block;\n width: var(--tabs-width, 100%);\n height: var(--tabs-height, 400px);\n box-sizing: border-box;\n}\n\n.tabs-container {\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n position: relative;\n box-sizing: border-box;\n}\n\n/* Bottom placement reverses the order */\n.tabs-container[data-placement="bottom"] {\n flex-direction: column-reverse;\n}\n\n/* ===================================== */\n/* Tab Buttons Container */\n/* Expose as CSS Part for full styling control */\n/* ===================================== */\n\n.tab-buttons {\n display: flex;\n gap: 0;\n flex-shrink: 0;\n position: relative;\n /* For absolute positioned marker */\n \n /* Default minimal styling - customize via ::part(buttons-container) */\n border-bottom: 1px solid var(--ty-border);\n background: transparent;\n}\n\n/* Bottom placement moves border to top */\n.tabs-container[data-placement="bottom"] .tab-buttons {\n border-bottom: none;\n border-top: 1px solid var(--ty-border);\n}\n\n/* ===================================== */\n/* Marker Wrapper */\n/* Expose as CSS Part for custom marker styling */\n/* ===================================== */\n\n.marker-wrapper {\n position: absolute;\n z-index: 0;\n /* Behind buttons */\n pointer-events: none;\n /* Don\'t block clicks */\n transition: left var(--transition-duration, 300ms) var(--transition-easing, ease-in-out),\n width var(--transition-duration, 300ms) var(--transition-easing, ease-in-out),\n height var(--transition-duration, 300ms) var(--transition-easing, ease-in-out),\n top var(--transition-duration, 300ms) var(--transition-easing, ease-in-out);\n}\n\n/* Default marker - simple underline */\n.default-marker {\n position: absolute;\n bottom: 0;\n left: 0;\n height: 2px;\n width: 100%;\n background: var(--ty-color-primary);\n pointer-events: none;\n}\n\n/* Hide default marker when custom marker is slotted */\n.marker-wrapper:has(::slotted([slot="marker"])) .default-marker {\n display: none;\n}\n\n/* User\'s marker element fills the wrapper */\n::slotted([slot="marker"]) {\n display: block;\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n}\n\n/* ===================================== */\n/* Tab Buttons */\n/* ===================================== */\n\n.tab-button {\n min-width: 120px;\n padding: 6px 12px;\n border: none;\n background: transparent;\n cursor: pointer;\n font: inherit;\n color: var(--ty-text-soft);\n transition: color 200ms, background-color 200ms;\n white-space: nowrap;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n font-weight: var(--ty-font-bold);\n font-size: var(--ty-font-sm);\n position: relative;\n /* Establish stacking context */\n z-index: 10;\n /* Above marker */\n}\n\n.tab-button[aria-selected=true] {\n color: var(--ty-text-strong);\n}\n\n.tab-button[disabled] {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n}\n\n.tab-button:focus-visible {\n outline: 2px solid var(--ty-color-primary);\n outline-offset: -2px;\n}\n\n/* ===================================== */\n/* Panels Viewport */\n/* Expose as CSS Part for panels container styling */\n/* ===================================== */\n\n.panels-viewport {\n position: relative;\n flex: 1;\n overflow: hidden;\n /* Critical: hides off-screen panels */\n min-height: 0;\n /* Allows flex child to shrink */\n}\n\n/* ===================================== */\n/* Panels Wrapper (slides horizontally) */\n/* ===================================== */\n\n.panels-wrapper {\n display: flex;\n height: 100%;\n transition: transform var(--transition-duration, 300ms) var(--transition-easing, ease-in-out);\n}\n\n/* Respect user\'s motion preferences */\n@media (prefers-reduced-motion: reduce) {\n .panels-wrapper {\n transition-duration: 0ms !important;\n }\n\n .marker-wrapper {\n transition-duration: 0ms !important;\n }\n}\n\n/* ===================================== */\n/* Slotted Tab Panels */\n/* ===================================== */\n\n::slotted(ty-tab) {\n width: var(--tabs-width, 100%);\n height: 100%;\n flex-shrink: 0;\n}\n',id:"ty-tabs"}),t.style.setProperty("--tabs-width",e.includes("%")?"100%":e),t.style.setProperty("--tabs-height",i),t.style.setProperty("--active-index",l+""),c&&d&&h){c.setAttribute("data-placement",o),d.querySelectorAll(".tab-button").forEach(t=>t.remove());const e=function(t,n,e){return n.map(n=>{const i=Zn(n);if(!i)return"";const o=Xn(t,n),s="text"===o?n.getAttribute("label")||"Tab":"",r=Jn(n),a=i===e;return`<button\n class="tab-button"\n role="tab"\n data-tab-id="${i}"\n id="tab-${i}"\n aria-selected="${a}"\n tabindex="${a?"0":"-1"}"\n data-active="${a}"\n ${r?'disabled aria-disabled="true"':""}\n >\n ${"slot"===o?`<slot name="label-${i}"></slot>`:s}\n </button>`}).join("")}(t,r,a),i=document.createElement("div");i.innerHTML=e,Array.from(i.children).forEach(t=>{d.appendChild(t)}),ee(t,n,r),oe(t,n,a||""),requestAnimationFrame(()=>{const e=n.querySelector(".tab-buttons");e&&t.style.setProperty("--buttons-height",e.offsetHeight+"px"),ie(t,l),a&&re(t,a)}),a&&se(t,a)}else{n.innerHTML=`\n <div class="tabs-container" data-placement="${o}">\n ${function(t,n,e){const i=n.map(n=>{const i=Zn(n);if(!i)return"";const o=Xn(t,n),s="text"===o?n.getAttribute("label")||"Tab":"",r=Jn(n),a=i===e;return`<button\n class="tab-button"\n role="tab"\n data-tab-id="${i}"\n id="tab-${i}"\n aria-selected="${a}"\n tabindex="${a?"0":"-1"}"\n data-active="${a}"\n ${r?'disabled aria-disabled="true"':""}\n >\n ${"slot"===o?`<slot name="label-${i}"></slot>`:s}\n </button>`}).join("");return`\n <div class="tab-buttons" role="tablist" part="buttons-container">\n <div class="marker-wrapper" part="marker-wrapper">\n ${o=t,null===o.querySelector('[slot="marker"]')?'<div class="default-marker"></div>':""}\n <slot name="marker"></slot>\n </div>\n ${i}\n </div>\n `;var o}(t,r,a)}\n <div class="panels-viewport" part="panels-container">\n <div class="panels-wrapper">\n <slot></slot>\n </div>\n </div>\n </div>\n `,requestAnimationFrame(()=>{const e=n.querySelector(".tab-buttons");e&&t.style.setProperty("--buttons-height",e.offsetHeight+"px"),ie(t,l),a&&re(t,a)}),ee(t,n,r),oe(t,n,a||""),function(t){const n=Un.get(t);n&&n.disconnect();const{width:e}=Gn(t);if(e.includes("%")){const n=new ResizeObserver(n=>{const e=n[0].contentRect.width,i=Kn(t),o=te(t,i),s=o?Qn(i,o):0;t.style.setProperty("--tabs-width",e+"px"),void 0!==s&&ie(t,s),o&&re(t,o)});n.observe(t),Un.set(t,n)}}(t),a&&se(t,a);const e=n.querySelector('slot[name="marker"]');if(e){const t=()=>{const t=n.querySelector(".default-marker");if(t){const n=e.assignedElements().length>0;t.style.display=n?"none":""}};e.addEventListener("slotchange",t),t()}}}class TyTabs extends HTMLElement{static get observedAttributes(){return["width","height","active","placement"]}constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){ae(this)}disconnectedCallback(){ne(this),function(t){const n=Un.get(t);n&&(n.disconnect(),Un.delete(t))}(this)}attributeChangedCallback(t,n,e){"active"===t?(e&&function(t,n,e){const i=Kn(t),o=t.shadowRoot;if(!o)return;const s=e?Qn(i,e):void 0,r=Qn(i,n);if(e===n||void 0===r)return;t.style.setProperty("--active-index",r+""),ie(t,r),oe(t,o,n),se(t,n),re(t,n);const a=i[r];a?.resetScroll&&a.resetScroll(),function(t,n,e,i,o){const s=new CustomEvent("ty-tab-change",{detail:{activeId:n,activeIndex:e,previousId:i,previousIndex:o},bubbles:!0,cancelable:!1});t.dispatchEvent(s)}(t,n,r,e,s??null)}(this,e,n),ae(this)):ae(this)}}customElements.get("ty-tabs")||customElements.define("ty-tabs",TyTabs);const le=`\n:host {\n width: var(--tabs-width, 100%);\n height: calc(var(--tabs-height, 400px) - var(--buttons-height, 48px));\n display: block;\n box-sizing: border-box;\n flex-shrink: 0;\n transition: opacity var(--transition-duration, 400ms) var(--transition-easing, ease-in-out);\n}\n\n@media (prefers-reduced-motion: reduce) {\n :host {\n transition-duration: 0ms !important;\n }\n}\n\n.tab-wrapper {\n width: 100%;\n height: 100%;\n position: relative;\n overflow: hidden;\n}\n\n.tab-panel {\n width: 100%;\n height: 100%;\n overflow: auto;\n box-sizing: border-box;\n}\n\n.tab-panel.ty-custom-scroll {\n scrollbar-width: none;\n -ms-overflow-style: none;\n}\n\n.tab-panel.ty-custom-scroll::-webkit-scrollbar {\n display: none;\n}\n\n/* Show scrollbar on hover */\n.tab-wrapper:hover .ty-scrollbar-track-y.has-overflow {\n opacity: 1;\n}\n\n${St}\n`;class TyTab extends HTMLElement{constructor(){super(),this.Qt=null,this.attachShadow({mode:"open"})}static get observedAttributes(){return["id","label","disabled"]}connectedCallback(){this.Vn()}disconnectedCallback(){this.tn()}attributeChangedCallback(t,n,e){this.Vn()}Vn(){const t=this.shadowRoot;if(!t)return;const n=this.getAttribute("id");t.querySelector(".tab-wrapper")||(s(t,{css:le,id:"ty-tab"}),t.innerHTML=`\n <div class="tab-wrapper"\n role="tabpanel"\n ${n?`id="panel-${n}"`:""}\n ${n?`aria-labelledby="tab-${n}"`:""}\n >\n <div class="tab-panel">\n <slot></slot>\n </div>\n </div>\n `,this.nn())}nn(){const t=this.shadowRoot?.querySelector(".tab-panel"),n=this.shadowRoot?.querySelector(".tab-wrapper");t&&n&&$t()&&(t.classList.add("ty-custom-scroll"),this.Qt=new Ct(t,{vertical:!0}),this.Qt.trackY&&n.appendChild(this.Qt.trackY))}tn(){this.Qt&&(this.Qt.trackY?.remove(),this.Qt.destroy(),this.Qt=null)}resetScroll(){this.Qt?.scrollToTop(!1)}}customElements.get("ty-tab")||customElements.define("ty-tab",TyTab);const ce=new WeakMap,de=new WeakMap;function he(t){return{width:t.getAttribute("width")||"100%",height:t.getAttribute("height")||"700px",active:t.getAttribute("active"),completed:t.getAttribute("completed")||"",orientation:t.getAttribute("orientation")||"horizontal"}}function ue(t){return Array.from(t.querySelectorAll("ty-step"))}function pe(t){return t.getAttribute("id")}function be(t){const n=t.getAttribute("completed")||"";return n.trim()?new Set(n.split(",").map(t=>t.trim()).filter(Boolean)):new Set}function ge(t,n){const e=t.findIndex(t=>pe(t)===n);return 0>e?void 0:e}function me(t,n){const e=t.getAttribute("active");return e&&void 0!==ge(n,e)?e:n.length>0?pe(n[0]):null}function ve(t,n){return t.length>1&&n?t.findIndex(t=>pe(t)===n)/(t.length-1)*100:0}function fe(t){const n=ce.get(t);if(!n)return;const e=t.shadowRoot;e&&(n.stepClickHandlers.forEach((t,n)=>{const i=e.querySelector(`[data-step-id='${n}']`);i&&i.removeEventListener("pointerdown",t)}),n.stepClickHandlers.clear())}function ye(t,n,e){fe(t);const i={stepClickHandlers:new Map};e.forEach(e=>{const o=pe(e);if(!o)return;const s=n.querySelector(`[data-step-id='${o}']`);if(s){const n=n=>function(t,n,e){e.preventDefault(),e.stopPropagation();const i=ue(t),o=i.findIndex(t=>pe(t)===n);if(0>o)return;const s=me(t,i),r=s?ge(i,s)??null:null,a=new CustomEvent("ty-wizard-step-change",{detail:{activeId:n,activeIndex:o,previousId:s,previousIndex:r,direction:null===r?"none":o>r?"forward":r>o?"backward":"none"},bubbles:!0,cancelable:!1});t.dispatchEvent(a)}(t,o,n);s.addEventListener("pointerdown",n),i.stepClickHandlers.set(o,n)}}),ce.set(t,i)}function we(t,n){const e=t.shadowRoot;if(!e)return;const i=e.querySelector(".panels-wrapper");i&&(i.style.transform=`translateX(-${n*t.offsetWidth}px)`)}function xe(t){const n=t.shadowRoot;if(!n)return;const e=n.querySelector(".progress-overlay");if(!e)return;const i=ue(t),o=me(t,i);be(t);const s=ve(i,o);e.style.width=s+"%"}function ke(t,n,e){const i=ue(t),o=be(t);e&&i.findIndex(t=>pe(t)===e),i.forEach(i=>{const s=pe(i);if(!s)return;const r=n.querySelector(`[data-step-id='${s}']`),a=n.querySelector(`[data-step-id='${s}'] .step-circle`),l=s===e;if(r&&(r.setAttribute("aria-selected",l+""),r.setAttribute("tabindex",l?"0":"-1"),r.setAttribute("data-active",l+"")),a){const t=$e(i,s,e,o);a.setAttribute("data-state",t)}const c=t.querySelector(`[slot='indicator-${s}']`);c&&c.setAttribute("data-active",l+"")})}function ze(t,n){ue(t).forEach(t=>{const e=pe(t);if(!e)return;const i=e===n;t.setAttribute("data-active",i+""),i?(t.style.pointerEvents="auto",t.style.opacity="1"):(t.style.pointerEvents="none",t.style.opacity="0")})}function $e(t,n,e,i){const o=t.getAttribute("status");if(o&&["completed","active","pending","error"].includes(o))return o;const s=n===e;return i.has(n)?"completed":s?"active":"pending"}function Ce(t,n,e,i){e&&n.findIndex(t=>pe(t)===e);const o=n.map((n,o)=>{const s=pe(n);if(!s)return"";const r=n.getAttribute("label")||"Step "+(o+1),a=n.getAttribute("description")||"",l=function(t){return t.hasAttribute("disabled")}(n),c=s===e,d=function(t,n){return null!==t.querySelector(`[slot='indicator-${n}']`)}(t,s),h=$e(n,s,e,i);let u="";return u=d?`<slot name="indicator-${s}"></slot>`:"completed"===h?'<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg>':"error"===h?'<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>':`<span style="font-size: 12px; font-weight: 700;">${o+1}</span>`,`<button\n class="step-indicator"\n role="tab"\n data-step-id="${s}"\n id="step-${s}"\n aria-selected="${c}"\n tabindex="${c?"0":"-1"}"\n data-active="${c}"\n ${l?'disabled aria-disabled="true"':""}\n >\n <div class="step-circle" data-state="${h}" part="step-circle">\n ${u}\n </div>\n <div class="step-text">\n <span class="step-label">${r}</span>\n ${a?`<span class="step-description">${a}</span>`:""}\n </div>\n </button>`}).join(""),s=ve(n,e);return`\n <div class="step-indicators-wrapper" part="indicators-wrapper">\n <div class="step-indicators" style="--ty-wizard-step-count: ${n.length}">\n <div class="progress-line" part="progress-line" role="progressbar" aria-label="Wizard progress" aria-valuenow="${Math.round(s)}" aria-valuemin="0" aria-valuemax="100">\n <div class="progress-overlay" style="width: ${s}%"></div>\n </div>\n <div class="step-tablist" role="tablist" style="display: contents;">\n ${o}\n </div>\n </div>\n </div>\n `}function Se(t){const n=t.shadowRoot;if(!n)return;const{width:e,height:i}=he(t),o=ue(t),r=me(t,o),a=r?ge(o,r)??0:0,l=be(t);o.forEach(t=>{const n=pe(t);n&&(t.setAttribute("role","tabpanel"),t.setAttribute("aria-labelledby","step-"+n),t.setAttribute("tabindex","0"))});const c=n.querySelector(".wizard-container"),d=n.querySelector(".step-indicators-wrapper"),h=n.querySelector(".panels-viewport");if(s(n,{css:'\n/* ============================================================================\n Theming Tokens — see file header for the override surface.\n Every default chains back to the brand layer / global scale tokens.\n ============================================================================ */\n\n:host {\n display: block;\n width: var(--ty-wizard-width, 100%); /* set by width attribute — not a public token */\n height: var(--ty-wizard-height, 700px); /* set by height attribute — not a public token */\n box-sizing: border-box;\n\n /* State accents — the primary override surface. One variable retints the\n * matching circle background, border, and glow. */\n --ty-wizard-active-accent: var(--ty-color-primary);\n --ty-wizard-completed-accent: var(--ty-color-success);\n --ty-wizard-error-accent: var(--ty-color-danger);\n --ty-wizard-pending-accent: var(--ty-color-neutral);\n\n /* Container chrome — routes through global scales. Override --ty-radius-lg\n * or --ty-shadow-md app-wide and the wizard follows; override these locally\n * to give the wizard a distinct look. */\n --ty-wizard-bg: var(--ty-surface-floating);\n --ty-wizard-border: var(--ty-border);\n --ty-wizard-radius: var(--ty-radius-lg, 12px);\n --ty-wizard-shadow: var(--ty-shadow-md, 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1));\n\n /* Header strip */\n --ty-wizard-header-bg: var(--ty-surface-content);\n --ty-wizard-header-border: var(--ty-border-soft, var(--ty-border));\n --ty-wizard-header-padding: 24px 24px 16px;\n\n /* Progress line */\n --ty-wizard-progress-track: var(--ty-border);\n --ty-wizard-progress-fill: var(--ty-wizard-completed-accent);\n --ty-wizard-progress-height: 2px;\n\n /* Motion — routes through global motion tokens if defined. */\n --ty-wizard-transition-duration: var(--ty-transition-duration, 300ms);\n --ty-wizard-transition-easing: var(--ty-transition-easing, ease-in-out);\n\n /* Circle geometry */\n --ty-wizard-circle-size: 32px;\n --ty-wizard-circle-border-width: 2px;\n\n /* Panels viewport */\n --ty-wizard-panels-bg: var(--ty-surface-elevated);\n\n /* Focus */\n --ty-wizard-focus-outline: var(--ty-wizard-active-accent);\n}\n\n.wizard-container {\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n position: relative;\n box-sizing: border-box;\n border-radius: var(--ty-wizard-radius);\n border: 1px solid var(--ty-wizard-border);\n background: var(--ty-wizard-bg);\n box-shadow: var(--ty-wizard-shadow);\n overflow: hidden;\n}\n\n/* ===================================== */\n/* Step Indicators Wrapper */\n/* ===================================== */\n\n.step-indicators-wrapper {\n display: flex;\n flex-direction: column;\n flex-shrink: 0;\n position: relative;\n padding: var(--ty-wizard-header-padding);\n border-bottom: 1px solid var(--ty-wizard-header-border);\n background: var(--ty-wizard-header-bg);\n}\n\n/* ===================================== */\n/* Progress Line (behind step circles) */\n/* ===================================== */\n\n.progress-line {\n position: absolute;\n /*\n * With equal-width indicators (flex: 1), each takes 100%/N of the width.\n * Circle centers sit at 50%/N from the left edge of each indicator.\n * Inset = 50% / step-count from each side keeps the line between circle centres.\n */\n left: calc(50% / var(--ty-wizard-step-count, 4));\n right: calc(50% / var(--ty-wizard-step-count, 4));\n top: calc(var(--ty-wizard-circle-size, 32px) / 2 - 1px);\n height: var(--ty-wizard-progress-height);\n background: var(--ty-wizard-progress-track);\n z-index: 0;\n pointer-events: none;\n transition: opacity var(--ty-wizard-transition-duration) var(--ty-wizard-transition-easing);\n}\n\n.progress-overlay {\n position: absolute;\n left: 0;\n top: 0;\n height: 100%;\n background: var(--ty-wizard-progress-fill);\n transition: width var(--ty-wizard-transition-duration) var(--ty-wizard-transition-easing);\n will-change: width;\n}\n\n/* ===================================== */\n/* Step Indicators Container */\n/* ===================================== */\n\n.step-indicators {\n display: flex;\n align-items: flex-start;\n position: relative;\n}\n\n/* ===================================== */\n/* Individual Step Indicator */\n/* ===================================== */\n\n.step-indicator {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n cursor: pointer;\n background: transparent;\n border: none;\n padding: 0;\n font: inherit;\n transition: opacity 200ms;\n flex: 1;\n min-width: 0;\n}\n\n.step-indicator[aria-disabled="true"] {\n opacity: 0.4;\n cursor: not-allowed;\n pointer-events: none;\n}\n\n.step-indicator:focus-visible {\n outline: 2px solid var(--ty-wizard-focus-outline);\n outline-offset: 4px;\n border-radius: 50%;\n}\n\n/* ===================================== */\n/* Step Circle */\n/* ===================================== */\n\n.step-circle {\n width: var(--ty-wizard-circle-size);\n height: var(--ty-wizard-circle-size);\n border-radius: 50%;\n border: var(--ty-wizard-circle-border-width) solid;\n display: flex;\n align-items: center;\n justify-content: center;\n position: relative;\n z-index: 10;\n transition: all var(--ty-wizard-transition-duration) var(--ty-wizard-transition-easing);\n box-sizing: border-box;\n flex-shrink: 0;\n}\n\n.step-circle[data-state="completed"] {\n background: var(--ty-wizard-completed-accent);\n border-color: var(--ty-color-success-strong);\n color: var(--ty-solid-success-fg, white);\n box-shadow: 0 0 0 4px color-mix(in oklab, var(--ty-wizard-completed-accent) 12%, transparent);\n}\n\n.step-circle[data-state="active"] {\n background: var(--ty-wizard-active-accent);\n border-color: var(--ty-color-primary-strong);\n color: var(--ty-solid-primary-fg, white);\n box-shadow: 0 0 0 4px color-mix(in oklab, var(--ty-wizard-active-accent) 12%, transparent);\n}\n\n.step-circle[data-state="pending"] {\n background: var(--ty-surface-elevated);\n border-color: var(--ty-border);\n color: var(--ty-color-neutral);\n}\n\n.step-circle[data-state="error"] {\n background: var(--ty-wizard-error-accent);\n border-color: var(--ty-color-danger-strong);\n color: var(--ty-solid-danger-fg, white);\n box-shadow: 0 0 0 4px color-mix(in oklab, var(--ty-wizard-error-accent) 12%, transparent);\n}\n\n/* ===================================== */\n/* Step Text Container */\n/* ===================================== */\n\n.step-text {\n display: flex;\n flex-direction: column;\n gap: 2px;\n align-items: center;\n}\n\n/* ===================================== */\n/* Step Label */\n/* ===================================== */\n\n.step-label {\n font-size: var(--ty-font-sm, 14px);\n font-weight: var(--ty-font-semibold, 600);\n color: var(--ty-color-neutral);\n transition: color 200ms;\n}\n\n.step-indicator[aria-selected="true"] .step-label {\n color: var(--ty-color-neutral-strong);\n}\n\n.step-indicator[aria-selected="false"] .step-label {\n color: var(--ty-color-neutral);\n}\n\n/* ===================================== */\n/* Step Description */\n/* ===================================== */\n\n.step-description {\n font-size: var(--ty-font-xs, 12px);\n font-weight: var(--ty-font-normal, 400);\n color: var(--ty-color-neutral);\n transition: color 200ms;\n text-align: center;\n max-width: 120px;\n}\n\n.step-indicator[aria-selected="true"] .step-description {\n color: var(--ty-color-neutral-bold);\n}\n\n/* ===================================== */\n/* Custom Indicator Content via Slots */\n/* ===================================== */\n\n::slotted([slot^="indicator-"]) {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n}\n\n/* ===================================== */\n/* Panels Viewport */\n/* ===================================== */\n\n.panels-viewport {\n position: relative;\n flex: 1;\n overflow: hidden;\n min-height: 0;\n background: var(--ty-wizard-panels-bg);\n}\n\n/* ===================================== */\n/* Panels Wrapper (slides horizontally) */\n/* ===================================== */\n\n.panels-wrapper {\n display: flex;\n height: 100%;\n transition: transform var(--ty-wizard-transition-duration) var(--ty-wizard-transition-easing);\n will-change: transform;\n}\n\n/* ===================================== */\n/* Slotted Step Panels */\n/* ===================================== */\n\n::slotted(ty-step) {\n width: var(--ty-wizard-width, 100%);\n height: 100%;\n flex-shrink: 0;\n}\n\n/* ===================================== */\n/* Accessibility & Motion Preferences */\n/* ===================================== */\n\n@media (prefers-reduced-motion: reduce) {\n .panels-wrapper {\n transition-duration: 0ms !important;\n }\n\n .progress-overlay {\n transition-duration: 0ms !important;\n }\n\n .step-circle {\n transition-duration: 0ms !important;\n }\n\n .progress-line {\n transition-duration: 0ms !important;\n }\n}\n\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border-width: 0;\n}\n',id:"ty-wizard"}),t.style.setProperty("--ty-wizard-width",e.includes("%")?"100%":e),t.style.setProperty("--ty-wizard-height",i),t.style.setProperty("--ty-wizard-active-index",a+""),t.style.setProperty("--ty-wizard-step-count",o.length+""),c&&d&&h){d.remove();const e=Ce(t,o,r,l),i=document.createElement("div");i.innerHTML=e,c.insertBefore(i.firstElementChild,h),ye(t,n,o),ke(t,n,r||""),requestAnimationFrame(()=>{const e=n.querySelector(".step-indicators-wrapper");e&&t.style.setProperty("--ty-wizard-indicators-height",e.offsetHeight+"px"),we(t,a),xe(t)}),r&&ze(t,r)}else n.innerHTML=`\n <div class="wizard-container">\n ${Ce(t,o,r,l)}\n <div class="panels-viewport" part="panels-container">\n <div class="panels-wrapper">\n <slot></slot>\n </div>\n </div>\n </div>\n `,requestAnimationFrame(()=>{const e=n.querySelector(".step-indicators-wrapper");e&&t.style.setProperty("--ty-wizard-indicators-height",e.offsetHeight+"px"),we(t,a),xe(t)}),ye(t,n,o),ke(t,n,r||""),function(t){const n=de.get(t);n&&n.disconnect();const{width:e}=he(t);if(e.includes("%")){const n=new ResizeObserver(n=>{const e=n[0].contentRect.width,i=ue(t),o=me(t,i),s=o?ge(i,o):0;t.style.setProperty("--ty-wizard-width",e+"px"),void 0!==s&&we(t,s)});n.observe(t),de.set(t,n)}}(t),r&&ze(t,r)}class TyWizard extends HTMLElement{static get observedAttributes(){return["width","height","active","completed","orientation"]}constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){Se(this)}disconnectedCallback(){fe(this),function(t){const n=de.get(t);n&&(n.disconnect(),de.delete(t))}(this)}attributeChangedCallback(t,n,e){"active"===t?(e&&function(t,n){const e=ue(t),i=t.shadowRoot;if(!i)return;const o=me(t,e),s=o?ge(e,o):void 0,r=ge(e,n);if(o===n||void 0===r)return;t.style.setProperty("--ty-wizard-active-index",r+""),we(t,r),ke(t,i,n),xe(t),ze(t,n);const a=e[r];a?.resetScroll&&a.resetScroll(),function(t,n,e,i,o){const s=new CustomEvent("ty-wizard-step-change",{detail:{activeId:n,activeIndex:e,previousId:i,previousIndex:o,direction:null===o?"none":e>o?"forward":o>e?"backward":"none"},bubbles:!0,cancelable:!1});t.dispatchEvent(s)}(t,n,r,o,s??null)}(this,e),Se(this)):Se(this)}}customElements.get("ty-wizard")||customElements.define("ty-wizard",TyWizard);const Ee=`\n:host {\n width: var(--ty-wizard-width, 100%);\n height: calc(var(--ty-wizard-height, 700px) - var(--ty-wizard-indicators-height, 120px));\n display: block;\n box-sizing: border-box;\n flex-shrink: 0;\n transition: opacity var(--ty-wizard-transition-duration, 400ms) var(--ty-wizard-transition-easing, ease-in-out);\n}\n\n@media (prefers-reduced-motion: reduce) {\n :host {\n transition-duration: 0ms !important;\n }\n}\n\n.step-wrapper {\n width: 100%;\n height: 100%;\n position: relative;\n overflow: hidden;\n}\n\n.step-panel {\n width: 100%;\n height: 100%;\n overflow: auto;\n box-sizing: border-box;\n}\n\n.step-panel.ty-custom-scroll {\n scrollbar-width: none;\n -ms-overflow-style: none;\n}\n\n.step-panel.ty-custom-scroll::-webkit-scrollbar {\n display: none;\n}\n\n.step-wrapper:hover .ty-scrollbar-track-y.has-overflow {\n opacity: 1;\n}\n\n${St}\n`;class TyStep extends HTMLElement{constructor(){super(),this.Qt=null,this.attachShadow({mode:"open"})}static get observedAttributes(){return["id","label","description","disabled","status"]}connectedCallback(){this.Vn()}disconnectedCallback(){this.tn()}attributeChangedCallback(t,n,e){this.Vn()}Vn(){const t=this.shadowRoot;if(!t)return;const n=this.getAttribute("id");t.querySelector(".step-wrapper")||(s(t,{css:Ee,id:"ty-step"}),t.innerHTML=`\n <div class="step-wrapper"\n role="tabpanel"\n ${n?`id="panel-${n}"`:""}\n ${n?`aria-labelledby="step-${n}"`:""}\n >\n <div class="step-panel">\n <slot></slot>\n </div>\n </div>\n `,this.nn())}nn(){const t=this.shadowRoot?.querySelector(".step-panel"),n=this.shadowRoot?.querySelector(".step-wrapper");t&&n&&$t()&&(t.classList.add("ty-custom-scroll"),this.Qt=new Ct(t,{vertical:!0}),this.Qt.trackY&&n.appendChild(this.Qt.trackY))}tn(){this.Qt&&(this.Qt.trackY?.remove(),this.Qt.destroy(),this.Qt=null)}resetScroll(){this.Qt?.scrollToTop(!1)}}customElements.get("ty-step")||customElements.define("ty-step",TyStep);const Te=(t,n)=>{const e=e=>n?`var(--ty-color-${t}${e}, var(--ty-color-${n}${e}))`:`var(--ty-color-${t}${e})`,i=e=>n?`var(--ty-bg-${t}${e}, var(--ty-bg-${n}${e}))`:`var(--ty-bg-${t}${e})`;return`\n:host([flavor="${t}"]) {\n --calendar-month-accent: ${e("")};\n --calendar-month-selected-bg: ${i("")};\n --calendar-month-selected-color: ${e("-strong")};\n --calendar-month-selected-hover-bg: ${i("-bold")};\n}\n:host([flavor="${t}+"]) {\n --calendar-month-accent: ${e("-strong")};\n --calendar-month-selected-bg: ${i("-bold")};\n --calendar-month-selected-color: ${e("-strong")};\n --calendar-month-selected-hover-bg: ${i("-bold")};\n}\n:host([flavor="${t}-"]) {\n --calendar-month-accent: ${e("-soft")};\n --calendar-month-selected-bg: ${i("-soft")};\n --calendar-month-selected-color: ${e("")};\n --calendar-month-selected-hover-bg: ${i("")};\n}\n`},Me=`\n/* ============================================================================\n Theming Tokens\n Override these to retheme the calendar without touching the global palette.\n Defaults chain back to the global --ty-color-* / --ty-bg-* / --ty-border tokens.\n ============================================================================ */\n\n/* Theming tokens are applied as var(--ty-calendar-*, <default>) at point\n of use (not declared on :host) so consumers can override any of them\n from outside the shadow root. The 3 accent aliases — --ty-calendar-accent,\n --ty-calendar-today-accent, --ty-calendar-muted — still cascade into the\n derived defaults, so overriding one retints the related cells. */\n\n/* ============================================================================\n Base Calendar Container\n ============================================================================ */\n\n.calendar-flex-container {\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n gap: 0;\n padding: 0.75rem;\n border-radius: var(--ty-radius-md);\n font-family: system-ui, sans-serif;\n user-select: none;\n width: var(--calendar-width, fit-content);\n min-width: 280px;\n max-width: var(--calendar-max-width, none);\n}\n\n/* ============================================================================\n Rows (Header + 6 Day Rows)\n ============================================================================ */\n\n.calendar-row {\n display: flex;\n flex: 1;\n min-height: 0;\n}\n\n.calendar-header-row {\n flex: 0 0 auto;\n color: var(--ty-calendar-header-color, var(--ty-color-neutral-soft));\n}\n\n.calendar-day-row {\n flex: 1;\n min-height: 2rem;\n margin-bottom: 0.125rem;\n}\n\n/* ============================================================================\n Base Cell Styles\n ============================================================================ */\n\n.calendar-cell {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n min-width: 0;\n position: relative;\n box-sizing: border-box;\n}\n\n/* ============================================================================\n Header Cells\n ============================================================================ */\n\n.calendar-header-cell {\n text-align: center;\n font-weight: 500;\n text-transform: uppercase;\n padding: 0.25rem;\n letter-spacing: 0.05em;\n}\n\n/* ============================================================================\n Day Cells - Square with Better Visual Hierarchy\n ============================================================================ */\n\n.calendar-day-cell {\n /* Square cells */\n aspect-ratio: 1;\n\n /* Layout */\n display: flex;\n align-items: center;\n justify-content: center;\n flex-direction: column;\n\n /* Spacing */\n margin: 0.125rem;\n\n /* Visual: ghost cells — no boxes; the border is a theming hook only */\n border-radius: var(--ty-calendar-day-radius, 0.5rem);\n border: 1px solid var(--ty-calendar-day-border, transparent);\n background-color: var(--ty-calendar-day-bg, transparent);\n color: var(--ty-calendar-day-color, var(--ty-calendar-muted, var(--ty-text)));\n cursor: pointer;\n transition: background-color 0.15s ease, color 0.15s ease;\n\n /* Typography */\n font-weight: 400;\n font-variant-numeric: tabular-nums;\n}\n\n/* Hover: soft rounded pill, no border flash */\n.calendar-day-cell:hover {\n color: var(--ty-calendar-day-hover-color, var(--ty-text-strong));\n background-color: var(--ty-calendar-day-hover-bg, var(--ty-bg-neutral-soft));\n border-color: var(--ty-calendar-day-hover-border, transparent);\n}\n\n/* Keyboard focus ring (roving tabindex — see calendar-month.ts's render()).\n :focus-visible, not :focus, so mouse/pointerdown activation doesn't flash\n a ring; only Tab-in / arrow-key navigation does. */\n.calendar-day-cell:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--calendar-month-accent, var(--ty-color-primary));\n}\n\n/* ============================================================================\n Day States\n ============================================================================ */\n\n/* Today: accent number, no slab — never collides with hover, and the\n selected pill wins when today is picked */\n.calendar-day-cell.today {\n background-color: var(--ty-calendar-today-bg, transparent);\n color: var(--ty-calendar-today-color, var(--ty-calendar-today-accent, var(--calendar-month-accent, var(--ty-color-primary))));\n border-color: var(--ty-calendar-today-border, transparent);\n font-weight: 600;\n}\n\n/* Weekend: no distinction by default (hook kept for theming) */\n.calendar-day-cell.weekend {\n color: var(--ty-calendar-weekend-color, var(--ty-calendar-day-color, var(--ty-text)));\n}\n\n/* Other Month - Muted.\n Was color: var(--ty-color-neutral-faint) at opacity 0.5 — -faint alone is\n only ~2.5:1 against the content surface (already under the 4.5:1 AA text\n minimum), and blending it toward the background via opacity made it\n worse (~1.5:1 in light mode). --ty-calendar-other-month-color is its own\n token (tyrell.css :root / html.dark) calibrated to actually pass, with\n opacity dropped rather than layered on top. */\n.calendar-day-cell.other-month {\n color: var(--ty-calendar-other-month-color, #6b7280);\n}\n\n.calendar-day-cell.other-month:hover { \n color: var(--ty-calendar-day-hover-color, var(--ty-color-neutral-strong));\n background-color: var(--ty-calendar-day-hover-bg, var(--ty-bg-neutral-soft));\n opacity: 0.7;\n}\n\n/* Disabled - outside min/max bounds */\n.calendar-day-cell.disabled {\n color: var(--ty-calendar-disabled-color, var(--ty-color-neutral-faint));\n opacity: var(--ty-calendar-disabled-opacity, 0.35);\n cursor: default;\n pointer-events: none;\n}\n\n/* Selected: the one strong element in the grid */\n.calendar-day-cell.selected {\n background-color: var(--ty-calendar-selected-bg, var(--calendar-month-selected-bg, var(--ty-bg-primary)));\n color: var(--ty-calendar-selected-color, var(--calendar-month-selected-color, var(--ty-color-primary-strong)));\n border-color: var(--ty-calendar-selected-border, var(--ty-calendar-accent, var(--calendar-month-accent, transparent)));\n font-weight: 600;\n}\n\n.calendar-day-cell.selected:hover {\n background-color: var(--ty-calendar-selected-hover-bg, var(--calendar-month-selected-hover-bg, var(--ty-bg-primary-bold)));\n border-color: var(--ty-calendar-selected-hover-border, transparent);\n}\n\n.calendar-day-cell.selected.other-month {\n opacity: 0.7;\n}\n\n/* ============================================================================\n Size Variants\n ============================================================================ */\n\n/* Small - Compact (240px min-width) */\n.calendar-size-sm {\n padding: 0.5rem;\n min-width: 240px;\n}\n\n.calendar-size-sm .calendar-header-cell {\n font-size: 0.625rem;\n padding: 0.125rem;\n}\n\n.calendar-size-sm .calendar-day-cell {\n font-size: 0.75rem;\n margin: 0.0625rem;\n}\n\n.calendar-size-sm .calendar-day-row {\n min-height: 1.5rem;\n}\n\n/* Medium - Default (280px min-width) */\n.calendar-size-md {\n padding: 0.75rem;\n min-width: 280px;\n}\n\n.calendar-size-md .calendar-header-cell {\n font-size: 0.6875rem;\n padding: 0.25rem;\n}\n\n.calendar-size-md .calendar-day-cell {\n font-size: 0.8125rem;\n margin: 0.125rem;\n}\n\n.calendar-size-md .calendar-day-row {\n min-height: 2rem;\n}\n\n/* Large - Spacious (360px min-width) */\n.calendar-size-lg {\n padding: 1rem;\n min-width: 360px;\n}\n\n.calendar-size-lg .calendar-header-cell {\n font-size: 0.75rem;\n padding: 0.375rem;\n}\n\n.calendar-size-lg .calendar-day-cell {\n font-size: 0.875rem;\n margin: 0.1875rem;\n}\n\n.calendar-size-lg .calendar-day-row {\n min-height: 2.5rem;\n}\n\n/* ============================================================================\n Backwards Compatibility\n ============================================================================ */\n\n.calendar-day {\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n}\n\n/* ============================================================================\n Flavor Variants (set --calendar-month-*, consumed above)\n ============================================================================ */\n${r.map(t=>Te(t)).join("")}\n`;function Ae(t){if(!Number.isInteger(t)||1>t||t>12)throw new RangeError(`Invalid month: ${t}. Must be an integer between 1 and 12.`)}function Ie(t,n,e,i){const o=t.getFullYear(),s=t.getMonth()+1,r=t.getDate(),a=t.getDay(),l=o!==n||s!==e;let c=!1,d=!1;l&&(n>o||o===n&&e>s?c=!0:d=!0);const h=(p=function(){const t=new Date;return new Date(t.getFullYear(),t.getMonth(),t.getDate(),0,0,0,0)}(),(u=t).getFullYear()===p.getFullYear()&&u.getMonth()===p.getMonth()&&u.getDate()===p.getDate());var u,p;const b=i?.year===o&&i?.month===s&&i?.day===r;return{value:Date.UTC(o,s-1,r,0,0,0,0),localValue:t.getTime(),year:o,month:s,dayInMonth:r,weekend:0===a||6===a,otherMonth:l,prevMonth:c,nextMonth:d,today:h,isSelected:b,selectedYear:i?.year,selectedMonth:i?.month,selectedDay:i?.day}}function De(t,n){const e=new Date(t);return e.setDate(e.getDate()+n),e}function Le(t){const n=t.match(/^(\d{4})-(\d{2})-(\d{2})$/);if(!n)return null;const e=parseInt(n[1],10),i=parseInt(n[2],10),o=parseInt(n[3],10);if(1>e||e>9999)return null;if(1>i||i>12)return null;if(1>o||o>31)return null;const s=new Date(e,i-1,o);return s.getFullYear()!==e||s.getMonth()!==i-1||s.getDate()!==o?null:{year:e,month:i,day:o}}function Oe(t){return t instanceof HTMLElement}function Ne(t){if(!t)return null;const n=Le(t);return n?Date.UTC(n.year,n.month-1,n.day):null}function Re(t){if(!t||""===t)return null;const n=t+"";return/^\d+(\.\d+)?$/.test(n)?n+"px":n}class TyCalendarMonth extends HTMLElement{constructor(){super(),this.Fn="en-US",this.fn="md",this.I=null,this.Pn=null,this.Hn=[];const t=new Date;this.jn=t.getFullYear(),this.Bn=t.getMonth()+1,this.attachShadow({mode:"open"})}static get observedAttributes(){return["locale","size","min","max","flavor"]}connectedCallback(){this.Bn||(this.Bn=(new Date).getMonth()+1),this.jn||(this.jn=(new Date).getFullYear()),this.Fn||(this.Fn=this.getAttribute("locale")||"en-US");const t=this.getAttribute("size");!t||"sm"!==t&&"md"!==t&&"lg"!==t||(this.fn=t);const n=this.dayContentFn;n&&!this.Wn&&(this.Wn=n,delete this.dayContentFn);const e=this.customCSS;e&&!this._n&&(this._n=e,delete this.customCSS),this.J=Z(this,()=>{this.render()}),this.D(),this.render()}disconnectedCallback(){this.J&&(this.J(),this.J=void 0)}attributeChangedCallback(t,n,e){"locale"===t?(this.Fn=e||"en-US",this.render()):"size"===t?"sm"!==e&&"md"!==e&&"lg"!==e||(this.fn=e,this.render()):"min"===t||"max"===t?(this["min"===t?"Yn":"Un"]=e??void 0,this.render()):"flavor"===t&&this.D()}D(){this.I=u(this.shadowRoot,this.I,this.getAttribute("flavor"),({base:t})=>(t=>Te(t,"neutral"))(t))}get displayYear(){return this.jn}set displayYear(t){this.jn!==t&&(this.jn=t,this.Pn=null,this.render())}get displayMonth(){return this.Bn}set displayMonth(t){this.Bn!==t&&(this.Bn=t,this.Pn=null,this.render())}get locale(){return K(this,this.getAttribute("locale"))}set locale(t){this.Fn!==t&&(this.Fn=t,this.render())}get size(){return this.fn}set size(t){this.fn!==t&&(this.fn=t,this.render())}get flavor(){return this.getAttribute("flavor")||"primary"}set flavor(t){t?this.setAttribute("flavor",t):this.removeAttribute("flavor")}get width(){return this.Gn}set width(t){this.Gn!==t&&(this.Gn=t,this.applyWidthProperties())}get minWidth(){return this.Kn}set minWidth(t){this.Kn!==t&&(this.Kn=t,this.applyWidthProperties())}get maxWidth(){return this.Zn}set maxWidth(t){this.Zn!==t&&(this.Zn=t,this.applyWidthProperties())}get dayContentFn(){return this.Wn}set dayContentFn(t){this.Wn!==t&&(this.Wn=t,this.render())}get customCSS(){return this._n}set customCSS(t){this._n!==t&&(this._n=t,this.applyCustomCSS())}get min(){return this.Yn}set min(t){this.Yn!==t&&(this.Yn=t,this.render())}get max(){return this.Un}set max(t){this.Un!==t&&(this.Un=t,this.render())}get value(){return this.q}set value(t){const n=t??void 0;this.q!==n&&(this.q=n,this.render())}applyWidthProperties(){const t=Re(this.Gn),n=Re(this.Kn),e=Re(this.Zn);t?this.style.setProperty("--calendar-width",t):this.style.removeProperty("--calendar-width"),n?this.style.setProperty("--calendar-min-width",n):this.style.removeProperty("--calendar-min-width"),e?this.style.setProperty("--calendar-max-width",e):this.style.removeProperty("--calendar-max-width")}applyCustomCSS(){if(!this._n||!this.shadowRoot)return;const t=this.shadowRoot.adoptedStyleSheets;t.includes(this._n)||(this.shadowRoot.adoptedStyleSheets=[...t,this._n])}refresh(){this.render()}dispatchDayClick(t,n){const e={dayContext:t,value:t.value,year:t.year,month:t.month,day:t.dayInMonth,isHoliday:t.holiday,isToday:t.today,isWeekend:t.weekend,isOtherMonth:t.otherMonth};for(const i of["day-click","day-select"]){const t=new CustomEvent(i,{detail:e,bubbles:!0,cancelable:!0});this.dispatchEvent(t)}}renderDayCell(t,n,e){const i=document.createElement("div"),o=this.Wn?this.Wn(t):function(t){return""+t.dayInMonth}(t);if(this.Wn&&o&&!Oe(o)&&"string"!=typeof o)throw Error(`Custom dayContentFn must return a DOM element or string, got: ${typeof o}. Use document.createElement() to create DOM elements.`);const s=function(t){const n=["calendar-day"];return t.today&&n.push("today"),t.weekend&&n.push("weekend"),t.otherMonth&&n.push("other-month"),t.isSelected&&n.push("selected"),n}(t);return n&&s.push("disabled"),i.className=s.join(" "),"string"==typeof o?i.textContent=o:Oe(o)&&i.appendChild(o),i.setAttribute("role","gridcell"),i.setAttribute("aria-label",new Intl.DateTimeFormat(this.Fn,{weekday:"long",year:"numeric",month:"long",day:"numeric"}).format(new Date(t.localValue))),i.setAttribute("aria-selected",!!t.isSelected+""),t.today&&i.setAttribute("aria-current","date"),n?(i.setAttribute("aria-disabled","true"),i.setAttribute("tabindex","-1")):(i.setAttribute("tabindex",e?"0":"-1"),i.addEventListener("pointerdown",n=>{n.preventDefault(),this.dispatchDayClick(t,n)}),i.addEventListener("keydown",n=>{"Enter"!==n.key&&" "!==n.key||(n.preventDefault(),this.dispatchDayClick(t,n))})),i}render(){const t=this.shadowRoot;if(!t)return;let n;if(s(t,{css:Me,id:"ty-calendar-month"}),this.applyCustomCSS(),this.applyWidthProperties(),this.q){const t=new Date(this.q);n={year:t.getFullYear(),month:t.getMonth()+1,day:t.getDate()}}const e=function(t,n,e){return function(t){if(!Number.isInteger(t)||1>t||t>9999)throw new RangeError(`Invalid year: ${t}. Must be an integer between 1 and 9999.`)}(t),Ae(n),function(t,n,e,i,o){const s=[];for(let r=0;42>r;r++){const n=De(t,r);s.push(Ie(n,e,i,o))}return s}(function(t,n){const e=function(t,n){return new Date(t,n-1,1,0,0,0,0)}(t,n);return function(t){const n=t.getDay(),e=0===n?6:n-1,i=new Date(t);return i.setDate(t.getDate()-e),i.setHours(0,0,0,0),i}(e)}(t,n),0,t,n,e)}(this.jn,this.Bn,n),i=function(t,n="short"){const e=new Intl.DateTimeFormat(t,{weekday:n}),i=new Date(2024,0,7),o=Array.from({length:7},(t,n)=>{const o=De(i,n);return e.format(o)}),[s,...r]=o;return[...r,s]}(this.Fn,"short");t.innerHTML="";const o=document.createElement("div");o.className="calendar-flex-container calendar-size-"+this.fn,o.setAttribute("role","grid"),o.setAttribute("aria-label",new Intl.DateTimeFormat(this.Fn,{month:"long",year:"numeric"}).format(new Date(this.jn,this.Bn-1,1)));const r=document.createElement("div");r.className="calendar-row calendar-header-row",r.setAttribute("role","row"),i.forEach(t=>{const n=document.createElement("div");n.className="calendar-cell calendar-header-cell",n.setAttribute("role","columnheader"),n.textContent=t,r.appendChild(n)}),o.appendChild(r);const a=[];for(let s=0;42>s;s+=7)a.push(e.slice(s,s+7));const l=Ne(this.Yn),c=Ne(this.Un),d=t=>{const n=e[t].value;return null!==l&&l>n||null!==c&&n>c};let h=e.findIndex(t=>t.isSelected);-1===h&&(h=e.findIndex(t=>t.today)),-1===h&&(h=0),(null===this.Pn||0>this.Pn||this.Pn>41||d(this.Pn))&&(this.Pn=h),this.Hn=[];let u=0;a.forEach(t=>{const n=document.createElement("div");n.className="calendar-row calendar-day-row",n.setAttribute("role","row"),t.forEach(t=>{const e=this.renderDayCell(t,null!==l&&l>t.value||null!==c&&t.value>c,u===this.Pn);e.className=e.className+" calendar-cell calendar-day-cell",n.appendChild(e),this.Hn[u]=e,u++}),o.appendChild(n)}),o.addEventListener("keydown",t=>{const n=t,e="ArrowLeft"===n.key?-1:"ArrowRight"===n.key?1:"ArrowUp"===n.key?-7:"ArrowDown"===n.key?7:0;if(0===e)return;const i=this.Pn??h,o=i+e;if(0>o||o>41||d(o))return;n.preventDefault(),this.Hn[i]?.setAttribute("tabindex","-1"),this.Pn=o;const s=this.Hn[o];s&&(s.setAttribute("tabindex","0"),s.focus())}),t.appendChild(o)}}customElements.get("ty-calendar-month")||customElements.define("ty-calendar-month",TyCalendarMonth);const qe='\n/* ============================================================================\n Size Variants (CSS Custom Properties)\n ============================================================================ */\n\n/* Theming tokens applied as var(--ty-calendar-nav-*, <default>) at point of\n use (NOT on :host) so consumers can override them from outside — this\n component is nested inside ty-calendar\'s shadow, so a :host default would\n block inherited overrides. --ty-calendar-accent still cascades in. */\n\n:host([data-size="md"]) {\n --nav-btn-size: 2rem;\n --nav-btn-icon-size: 1.25rem;\n --nav-font-size: 1rem;\n --nav-padding: 0.5rem 0.75rem;\n --nav-default-width: 280px;\n}\n\n:host([data-size="sm"]) {\n --nav-btn-size: 1.5rem;\n --nav-btn-icon-size: 1rem;\n --nav-font-size: 0.875rem;\n --nav-padding: 0.375rem 0.5rem;\n --nav-default-width: 240px;\n}\n\n:host([data-size="lg"]) {\n --nav-btn-size: 2.5rem;\n --nav-btn-icon-size: 1.5rem;\n --nav-font-size: 1.125rem;\n --nav-padding: 0.625rem 1rem;\n --nav-default-width: 360px;\n}\n\n/* ============================================================================\n Main Navigation Header\n ============================================================================ */\n\n.calendar-navigation-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--nav-padding);\n font-family: system-ui, sans-serif;\n user-select: none;\n width: var(--nav-width, var(--nav-default-width));\n box-sizing: border-box;\n}\n\n/* ============================================================================\n Navigation Groups (Left, Center, Right)\n ============================================================================ */\n\n.nav-group {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n}\n\n.nav-group-left,\n.nav-group-right {\n flex: 0 0 auto;\n}\n\n.nav-group-center {\n flex: 1;\n justify-content: center;\n}\n\n/* ============================================================================\n Navigation Buttons\n ============================================================================ */\n\n.nav-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--nav-btn-size);\n height: var(--nav-btn-size);\n padding: 0;\n border: none;\n border-radius: var(--ty-radius-base);\n background-color: transparent;\n color: var(--ty-calendar-nav-color, var(--ty-color-neutral));\n cursor: pointer;\n transition: all 0.15s ease;\n outline: none;\n}\n\n.nav-btn:hover {\n background-color: var(--ty-calendar-nav-hover-bg, var(--ty-bg-neutral-soft));\n color: var(--ty-calendar-nav-hover-color, var(--ty-color-neutral-strong));\n}\n\n.nav-btn:active {\n background-color: var(--ty-calendar-nav-active-bg, var(--ty-bg-neutral));\n transform: scale(0.95);\n}\n\n.nav-btn:disabled {\n opacity: 0.35;\n cursor: default;\n pointer-events: none;\n}\n\n.nav-btn:focus-visible {\n outline: 2px solid var(--ty-calendar-nav-focus-outline, var(--ty-calendar-accent, var(--ty-color-primary)));\n outline-offset: 2px;\n}\n\n/* SVG sizing */\n.nav-btn svg {\n width: var(--nav-btn-icon-size);\n height: var(--nav-btn-icon-size);\n display: block;\n}\n\n/* ============================================================================\n Month/Year Display (Center)\n ============================================================================ */\n\n.month-year-display {\n font-size: var(--nav-font-size);\n font-weight: 600;\n color: var(--ty-calendar-nav-title-color, var(--ty-color-neutral-strong));\n text-align: center;\n white-space: nowrap;\n letter-spacing: -0.01em;\n}\n',Ve=class t extends i{constructor(){super();const t=new Date;this.xn={displayMonth:t.getMonth()+1,displayYear:t.getFullYear()},s(this.shadowRoot,{css:qe,id:"ty-calendar-navigation"})}onConnect(){this.xn.displayMonth=this.displayMonth,this.xn.displayYear=this.displayYear,this.J=Z(this,()=>{this.render()}),this.render()}onDisconnect(){this.J&&(this.J(),this.J=void 0)}onPropertiesChanged(t){for(const{name:n,newValue:e}of t)switch(n){case"display-month":this.xn.displayMonth=e;break;case"display-year":this.xn.displayYear=e}}get displayMonth(){return this.getProperty("display-month")}set displayMonth(t){this.setProperty("display-month",t)}get displayYear(){return this.getProperty("display-year")}set displayYear(t){this.setProperty("display-year",t)}get locale(){return K(this,this.getProperty("locale"))}set locale(t){this.setProperty("locale",t)}get size(){return this.getProperty("size")}set size(t){this.setProperty("size",t)}get width(){return this.getProperty("width")}set width(t){this.setProperty("width",t)}get min(){return this.getProperty("min")}set min(t){this.setProperty("min",t??"")}get max(){return this.getProperty("max")}set max(t){this.setProperty("max",t??"")}emitChangeEvent(t,n){const e=new CustomEvent("change",{detail:{month:t,year:n},bubbles:!0,cancelable:!0});this.dispatchEvent(e)}static monthIndex(t,n){return 12*t+(n-1)}boundIndices(){const n=Le(this.min),e=Le(this.max);return{minIdx:n?t.monthIndex(n.year,n.month):null,maxIdx:e?t.monthIndex(e.year,e.month):null}}clampIndex(t){const{minIdx:n,maxIdx:e}=this.boundIndices();return null!==n&&n>t?n:null!==e&&t>e?e:t}navigateBy(n){const e=t.monthIndex(this.xn.displayYear,this.xn.displayMonth),i=this.clampIndex(e+n);i!==e&&this.emitChangeEvent(i%12+1,Math.floor(i/12))}isNavDisabled(n){const e=t.monthIndex(this.xn.displayYear,this.xn.displayMonth);return this.clampIndex(e+n)===e}createButton(t,n,e,i,o=!1){const s=document.createElement("button");return s.className=t,s.title=n,s.innerHTML=e,s.disabled=o,s.addEventListener("click",i),s}render(){const t=this.shadowRoot;if(!t)return;s(t,{css:qe,id:"ty-calendar-navigation"}),this.setAttribute("data-size",this.size);const n=this.width;n?this.style.setProperty("--nav-width",n):this.style.removeProperty("--nav-width");const e=function(t,n="en-US",e="long"){Ae(t);const i=new Date(2024,t-1,1);return new Intl.DateTimeFormat(n,{month:e}).format(i)}(this.xn.displayMonth,this.locale,"long");t.innerHTML="";const i=document.createElement("div");i.className="calendar-navigation-header";const o=document.createElement("div");o.className="nav-group nav-group-left",o.appendChild(this.createButton("nav-btn nav-year-prev","Previous year","<?xml version='1.0' encoding='UTF-8'?>\n<svg width='24' viewBox='0 0 24 24' height='24' enable-background='new 0 0 24 24' xmlns='http://www.w3.org/2000/svg' stroke-width='0' stroke='currentColor' fill='currentColor'>\n<g>\n<rect width='24' height='24' fill='none'/>\n</g>\n<g>\n<g>\n<polygon points='17.59,18 19,16.59 14.42,12 19,7.41 17.59,6 11.59,12'/>\n<polygon points='11,18 12.41,16.59 7.83,12 12.41,7.41 11,6 5,12'/>\n</g>\n</g>\n</svg>",()=>this.navigateBy(-12),this.isNavDisabled(-12))),o.appendChild(this.createButton("nav-btn nav-month-prev","Previous month","<?xml version='1.0' encoding='UTF-8'?>\n<svg width='24' viewBox='0 0 24 24' height='24' xmlns='http://www.w3.org/2000/svg' stroke-width='0' stroke='currentColor' fill='currentColor'>\n<path fill='none' d='M0 0h24v24H0V0z'/>\n<path d='M15.41 16.59L10.83 12l4.58-4.59L14 6l-6 6 6 6 1.41-1.41z'/>\n</svg>",()=>this.navigateBy(-1),this.isNavDisabled(-1)));const r=document.createElement("div");r.className="nav-group nav-group-center";const a=document.createElement("div");a.className="month-year-display",a.textContent=`${e} ${this.xn.displayYear}`,r.appendChild(a);const l=document.createElement("div");l.className="nav-group nav-group-right",l.appendChild(this.createButton("nav-btn nav-month-next","Next month","<?xml version='1.0' encoding='UTF-8'?>\n<svg width='24' viewBox='0 0 24 24' height='24' xmlns='http://www.w3.org/2000/svg' stroke-width='0' stroke='currentColor' fill='currentColor'>\n<path fill='none' d='M0 0h24v24H0V0z'/>\n<path d='M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z'/>\n</svg>",()=>this.navigateBy(1),this.isNavDisabled(1))),l.appendChild(this.createButton("nav-btn nav-year-next","Next year","<?xml version='1.0' encoding='UTF-8'?>\n<svg width='24' viewBox='0 0 24 24' height='24' enable-background='new 0 0 24 24' xmlns='http://www.w3.org/2000/svg' stroke-width='0' stroke='currentColor' fill='currentColor'>\n<g>\n<rect width='24' height='24' fill='none'/>\n</g>\n<g>\n<g>\n<polygon points='6.41,6 5,7.41 9.58,12 5,16.59 6.41,18 12.41,12'/>\n<polygon points='13,6 11.59,7.41 16.17,12 11.59,16.59 13,18 19,12'/>\n</g>\n</g>\n</svg>",()=>this.navigateBy(12),this.isNavDisabled(12))),i.appendChild(o),i.appendChild(r),i.appendChild(l),t.appendChild(i)}};Ve.properties={"display-month":{type:"number",visual:!0,default:()=>(new Date).getMonth()+1,validate:t=>{const n=+t;return Number.isInteger(n)&&n>=1&&12>=n},coerce:t=>{const n=+t;return isNaN(n)||1>n||n>12?(new Date).getMonth()+1:n}},"display-year":{type:"number",visual:!0,default:()=>(new Date).getFullYear(),validate:t=>{const n=+t;return Number.isInteger(n)&&n>=1&&9999>=n},coerce:t=>{const n=+t;return isNaN(n)||1>n||n>9999?(new Date).getFullYear():n}},locale:{type:"string",visual:!0,default:"en-US"},size:{type:"string",visual:!0,default:"md",validate:t=>["sm","md","lg"].includes(t),coerce:t=>["sm","md","lg"].includes(t)?t:"md"},width:{type:"string",visual:!0,default:""},min:{type:"string",visual:!0,default:""},max:{type:"string",visual:!0,default:""}};let Fe=Ve;function Pe(t){return t&&/^\d{4}$/.test(t)?parseInt(t,10):null}function He(t){if(!t||!/^\d{1,2}$/.test(t))return null;const n=parseInt(t,10);return 1>n||n>12?null:n}function je(t,n,e){if(!t||!/^\d{1,2}$/.test(t))return null;const i=parseInt(t,10),o=new Date(n,e,0).getDate();return 1>i||i>o?null:i}function Be(t,n,e){return`${t}-${(""+n).padStart(2,"0")}-${(""+e).padStart(2,"0")}`}customElements.get("ty-calendar-navigation")||customElements.define("ty-calendar-navigation",Fe);const We=class extends HTMLElement{constructor(){super(),this.Xn=!0,this.Jn=!1,this.fn="md",this.Qn="primary";const t=function(){const t=new Date;return{year:t.getFullYear(),month:t.getMonth()+1,day:t.getDate()}}();this.xn={displayYear:t.year,displayMonth:t.month},this.attachShadow({mode:"open"}),"attachInternals"in this&&(this.v=this.attachInternals())}static get observedAttributes(){return["year","month","day","show-navigation","stateless","locale","name","size","width","min","max","flavor"]}connectedCallback(){this.initializeFromAttributes();const t=this.dayContentFn;t&&!this.Wn&&(this.Wn=t,delete this.dayContentFn);const n=this.customCSS;n&&!this._n&&(this._n=n,delete this.customCSS);const e=this.value;if(e&&"string"==typeof e&&e!==this.value){const t=e.match(/^(\d{4})-(\d{2})-(\d{2})$/);if(t){const n=parseInt(t[1],10),e=parseInt(t[2],10),i=parseInt(t[3],10);this.xn.selectedYear=n,this.xn.selectedMonth=e,this.xn.selectedDay=i,this.xn.displayYear=n,this.xn.displayMonth=e,this.Jn||(this.setAttribute("year",""+n),this.setAttribute("month",""+e),this.setAttribute("day",""+i))}delete this.value}this.render(),this.updateFormValue(),this.J=Z(this,()=>{this.render()})}disconnectedCallback(){this.J&&(this.J(),this.J=void 0),this.te=void 0,this.ne=void 0}attributeChangedCallback(t,n,e){if(n!==e)switch(t){case"year":case"month":case"day":this.syncStateFromAttributes(),this.syncChildComponents(),this.updateFormValue();break;case"show-navigation":this.Xn="false"!==e,this.render();break;case"stateless":this.Jn=null!==e&&"false"!==e;break;case"locale":this.syncChildComponents();break;case"size":"sm"!==e&&"md"!==e&&"lg"!==e||(this.fn=e,this.Gn=void 0,this.removeAttribute("width"),this.syncChildComponents());break;case"width":this.Gn=e||void 0,e&&(this.fn="md",this.removeAttribute("size")),this.syncChildComponents();break;case"name":this.updateFormValue();break;case"min":case"max":this["min"===t?"Yn":"Un"]=e||void 0,this.syncChildComponents(),this.updateValidity();break;case"flavor":this.Qn=e||"primary",this.syncChildComponents()}}get min(){return this.Yn}set min(t){t?this.setAttribute("min",t):this.removeAttribute("min")}get max(){return this.Un}set max(t){t?this.setAttribute("max",t):this.removeAttribute("max")}get flavor(){return this.Qn}set flavor(t){t?this.setAttribute("flavor",t):this.removeAttribute("flavor")}get year(){return this.xn.selectedYear}set year(t){void 0!==t?this.Jn?(this.xn.displayYear=t,this.setAttribute("year",""+t)):(this.xn.selectedYear=t,this.xn.displayYear=t,this.setAttribute("year",""+t)):(this.Jn||delete this.xn.selectedYear,this.removeAttribute("year")),this.syncChildComponents(),this.Jn||this.updateFormValue()}get month(){return this.xn.selectedMonth}set month(t){void 0!==t?this.Jn?(this.xn.displayMonth=t,this.setAttribute("month",""+t)):(this.xn.selectedMonth=t,this.xn.displayMonth=t,this.setAttribute("month",""+t)):(this.Jn||delete this.xn.selectedMonth,this.removeAttribute("month")),this.syncChildComponents(),this.Jn||this.updateFormValue()}get day(){return this.xn.selectedDay}set day(t){void 0!==t?(this.xn.selectedDay=t,this.setAttribute("day",""+t)):(delete this.xn.selectedDay,this.removeAttribute("day")),this.syncChildComponents(),this.updateFormValue()}get locale(){return K(this,this.getAttribute("locale"))}set locale(t){this.setAttribute("locale",t)}get showNavigation(){return this.Xn}set showNavigation(t){this.Xn=t,this.setAttribute("show-navigation",""+t)}get stateless(){return this.Jn}set stateless(t){this.Jn=t,t?this.setAttribute("stateless",""):this.removeAttribute("stateless")}get size(){return this.fn}set size(t){this.fn!==t&&(this.fn=t,this.Gn=void 0,this.removeAttribute("width"),this.setAttribute("size",t),this.syncChildComponents())}get width(){return this.Gn}set width(t){this.Gn!==t&&(this.Gn=t,t?(this.fn="md",this.removeAttribute("size"),this.setAttribute("width",t)):this.removeAttribute("width"),this.syncChildComponents())}get dayContentFn(){return this.Wn}set dayContentFn(t){this.Wn=t,this.syncChildComponents()}get customCSS(){return this._n}set customCSS(t){this._n=t,this.syncChildComponents()}get value(){const{selectedYear:t,selectedMonth:n,selectedDay:e}=this.xn;return t&&n&&e?Be(t,n,e):""}set value(t){if(t){const n=t.match(/^(\d{4})-(\d{2})-(\d{2})$/);if(n){const t=parseInt(n[1],10),e=parseInt(n[2],10),i=parseInt(n[3],10);this.xn.selectedYear=t,this.xn.selectedMonth=e,this.xn.selectedDay=i,this.xn.displayYear=t,this.xn.displayMonth=e,this.Jn||(this.setAttribute("year",""+t),this.setAttribute("month",""+e),this.setAttribute("day",""+i))}}else delete this.xn.selectedYear,delete this.xn.selectedMonth,delete this.xn.selectedDay,this.Jn||(this.removeAttribute("year"),this.removeAttribute("month"),this.removeAttribute("day"));this.syncChildComponents(),this.Jn||this.updateFormValue()}initializeFromAttributes(){const t=this.getAttribute("year"),n=this.getAttribute("month"),e=this.getAttribute("day"),i=this.getAttribute("show-navigation"),o=this.getAttribute("stateless"),s=this.getAttribute("size"),r=this.getAttribute("width");this.Yn=this.getAttribute("min")||void 0,this.Un=this.getAttribute("max")||void 0;const a=Pe(t);a&&(this.xn.displayYear=a);const l=He(n);if(l&&(this.xn.displayMonth=l),a&&l){const t=je(e,a,l);t&&(this.xn.selectedYear=a,this.xn.selectedMonth=l,this.xn.selectedDay=t)}i&&(this.Xn="false"!==i),null!==o&&(this.Jn="false"!==o),!s||"sm"!==s&&"md"!==s&&"lg"!==s||(this.fn=s),r&&(this.Gn=r)}syncStateFromAttributes(){const t=this.getAttribute("year"),n=this.getAttribute("month"),e=this.getAttribute("day"),i=Pe(t),o=He(n);if(i&&(this.xn.displayYear=i),o&&(this.xn.displayMonth=o),i&&o){const t=je(e,i,o);t?(this.xn.selectedYear=i,this.xn.selectedMonth=o,this.xn.selectedDay=t):(delete this.xn.selectedYear,delete this.xn.selectedMonth,delete this.xn.selectedDay)}else delete this.xn.selectedYear,delete this.xn.selectedMonth,delete this.xn.selectedDay}syncChildComponents(){if(this.te&&(this.te.displayMonth=this.xn.displayMonth,this.te.displayYear=this.xn.displayYear,this.te.locale=this.locale,this.te.size=this.fn,this.te.min=this.Yn??"",this.te.max=this.Un??"",this.te.width=this.Gn),this.ne){this.ne.displayMonth=this.xn.displayMonth,this.ne.displayYear=this.xn.displayYear,this.ne.locale=this.locale,this.ne.size=this.fn,this.ne.min=this.Yn,this.ne.max=this.Un,this.ne.flavor=this.Qn,this.ne.width=this.Gn,this.Wn&&(this.ne.dayContentFn=this.Wn),this._n&&(this.ne.customCSS=this._n);const{selectedYear:t,selectedMonth:n,selectedDay:e}=this.xn;this.ne.value=t&&n&&e?new Date(t,n-1,e).getTime():null}}updateFormValue(){if(this.Jn)return;if(!this.v)return;const t=this.getAttribute("name"),{selectedYear:n,selectedMonth:e,selectedDay:i}=this.xn;if(t&&n&&e&&i){const t=Be(n,e,i);this.v.setFormValue(t)}else this.v.setFormValue("");this.updateValidity()}updateValidity(){if(!this.v)return;const{selectedYear:t,selectedMonth:n,selectedDay:e}=this.xn;if(t&&n&&e){const i=Date.UTC(t,n-1,e),o=this.Yn?Le(this.Yn):null,s=this.Un?Le(this.Un):null;if(o&&i<Date.UTC(o.year,o.month-1,o.day))return void this.v.setValidity({rangeUnderflow:!0},`Date must be ${this.Yn} or later`);if(s&&i>Date.UTC(s.year,s.month-1,s.day))return void this.v.setValidity({rangeOverflow:!0},`Date must be ${this.Un} or earlier`)}this.v.setValidity({})}handleNavigationChange(t){t.preventDefault(),t.stopPropagation();const{month:n,year:e}=t.detail;this.xn.displayMonth=n,this.xn.displayYear=e,this.syncChildComponents(),this.dispatchEvent(new CustomEvent("navigate",{detail:{month:n,year:e,action:"navigate",source:"navigation"},bubbles:!0,composed:!0,cancelable:!1}))}handleDayClick(t){t.preventDefault(),t.stopPropagation();const{dayContext:n,year:e,month:i,day:o}=t.detail;this.Jn?this.dispatchEvent(new CustomEvent("day-click",{detail:t.detail,bubbles:!0,composed:!0,cancelable:!0})):(this.xn.selectedYear=e,this.xn.selectedMonth=i,this.xn.selectedDay=o,this.xn.displayYear=e,this.xn.displayMonth=i,this.setAttribute("year",""+e),this.setAttribute("month",""+i),this.setAttribute("day",""+o),this.updateFormValue(),this.syncChildComponents(),this.dispatchEvent(new CustomEvent("change",{detail:{year:e,month:i,day:o,action:"select",source:"day-click",dayContext:n},bubbles:!0,composed:!0,cancelable:!1})))}refresh(){this.syncChildComponents(),this.ne&&"function"==typeof this.ne.refresh&&this.ne.refresh()}createNavigation(){const t=document.createElement("ty-calendar-navigation");return t.displayMonth=this.xn.displayMonth,t.displayYear=this.xn.displayYear,t.locale=this.locale,t.size=this.fn,t.min=this.Yn??"",t.max=this.Un??"",this.Gn&&(t.width=this.Gn),t.addEventListener("change",t=>this.handleNavigationChange(t)),this.te=t,t}createMonthDisplay(){const t=document.createElement("ty-calendar-month");t.displayMonth=this.xn.displayMonth,t.displayYear=this.xn.displayYear,t.locale=this.locale,t.size=this.fn,t.min=this.Yn,t.max=this.Un,t.flavor=this.Qn,this.Gn&&(t.width=this.Gn);const{selectedYear:n,selectedMonth:e,selectedDay:i}=this.xn;return n&&e&&i&&(t.value=new Date(n,e-1,i).getTime()),this.Wn&&(t.dayContentFn=this.Wn),this._n&&(t.customCSS=this._n),t.addEventListener("day-click",t=>this.handleDayClick(t)),this.ne=t,t}render(){const t=this.shadowRoot;if(!t)return;s(t,{css:"\n/* ============================================================================\n Calendar Container\n ============================================================================ */\n\n.calendar-container {\n display: flex;\n flex-direction: column;\n gap: 0.125rem;\n box-sizing: border-box;\n font-family: system-ui, sans-serif;\n}\n\n/* ============================================================================\n Responsive Adjustments\n ============================================================================ */\n\n@media (max-width: 320px) {\n .calendar-container {\n gap: 0.375rem;\n }\n}\n",id:"ty-calendar"}),t.innerHTML="";const n=document.createElement("div");if(n.className="calendar-container",this.Xn){const t=this.createNavigation();n.appendChild(t)}const e=this.createMonthDisplay();n.appendChild(e),t.appendChild(n)}};We.formAssociated=!0;let _e=We;customElements.get("ty-calendar")||customElements.define("ty-calendar",_e);const Ye=(t,n)=>{const e=e=>n?e?`var(--ty-color-${t}${e}, var(--ty-color-${t}, var(--ty-color-${n}${e})))`:`var(--ty-color-${t}, var(--ty-color-${n}))`:e?`var(--ty-color-${t}${e}, var(--ty-color-${t}))`:`var(--ty-color-${t})`;return`\n:host([flavor="${t}"]) {\n --date-picker-accent: var(--ty-input-${t}-border, ${e("-soft")});\n --date-picker-accent-bold: ${e("")};\n --date-picker-ring: color-mix(in oklab, ${e("")} 15%, transparent);\n}\n:host([flavor="${t}+"]) {\n --date-picker-accent: ${e("")};\n --date-picker-accent-bold: ${e("-strong")};\n --date-picker-ring: color-mix(in oklab, ${e("-strong")} 15%, transparent);\n}\n:host([flavor="${t}-"]) {\n --date-picker-accent: ${e("-faint")};\n --date-picker-accent-bold: ${e("-soft")};\n --date-picker-ring: color-mix(in oklab, ${e("-soft")} 15%, transparent);\n}\n`},Ue=`\n/* Date Picker Component Styles */\n:host {\n display: block;\n width: auto;\n min-width: 200px;\n font-family: var(--ty-font-sans);\n\n /* ==========================================================================\n Theming Tokens — Date Picker Stub\n Thin shim over --ty-input-*. Override these to retheme just the date-picker\n trigger without affecting other inputs.\n ========================================================================== */\n --ty-date-picker-bg: var(--ty-input-bg);\n --ty-date-picker-color: var(--ty-input-color);\n --ty-date-picker-placeholder: var(--ty-input-placeholder);\n --ty-date-picker-border: var(--ty-input-border);\n --ty-date-picker-border-hover: var(--ty-input-border-hover);\n --ty-date-picker-border-focus: var(--ty-input-border-focus);\n --ty-date-picker-shadow-focus: var(--ty-input-shadow-focus);\n --ty-date-picker-disabled-bg: var(--ty-input-disabled-bg);\n --ty-date-picker-disabled-color: var(--ty-input-disabled-color);\n --ty-date-picker-radius: var(--ty-radius-md);\n\n /* ==========================================================================\n Theming Tokens — Calendar Popup Surface\n Shared with ty-calendar / ty-calendar-month theming.\n ========================================================================== */\n --ty-calendar-surface-bg: var(--ty-surface-floating);\n --ty-calendar-surface-border: var(--ty-input-border);\n --ty-calendar-surface-shadow: var(--ty-shadow-lg, 0 4px 20px rgba(0, 0, 0, 0.08), 0 1px 3px rgba(0, 0, 0, 0.1));\n --ty-calendar-surface-radius: var(--ty-radius-lg);\n\n /* ==========================================================================\n Theming Tokens — Time Section\n ========================================================================== */\n --ty-calendar-time-bg: transparent;\n --ty-calendar-time-border: var(--ty-border-faint);\n --ty-calendar-time-label-color: var(--ty-color-neutral);\n --ty-calendar-time-input-color: var(--ty-input-color);\n --ty-calendar-time-placeholder-color: var(--ty-input-placeholder);\n --ty-calendar-time-icon-color: var(--ty-color-neutral-soft);\n}\n\n/* Container structure (reuses dropdown patterns) */\n.dropdown-container {\n display: flex;\n flex-direction: column;\n width: 100%;\n box-sizing: border-box;\n}\n\n.ty-field-label {\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n font-weight: var(--ty-font-medium);\n color: var(--ty-label-color);\n margin-bottom: 6px;\n padding-left: 12px;\n display: flex;\n align-items: center;\n}\n\n.required-icon {\n display: inline-flex;\n align-items: center;\n color: #ef4444;\n width: 12px;\n height: 12px;\n vertical-align: middle;\n margin-left: 4px;\n}\n\n.dropdown-wrapper {\n position: relative;\n display: block;\n width: 100%;\n}\n\n/* Start-slot icon (leading content inside the date-picker stub) */\n.date-picker-stub ::slotted([slot="start"]) {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n margin-right: 0.5rem;\n color: var(--ty-color-text-soft);\n}\n\n.date-picker-stub ::slotted(ty-icon[slot="start"]) {\n width: 1em;\n height: 1em;\n}\n\n/* Date picker stub (styled like dropdown) */\n.date-picker-stub {\n width: 100%;\n cursor: pointer;\n box-sizing: border-box;\n position: relative;\n display: flex;\n align-items: center;\n background: var(--ty-date-picker-bg);\n color: var(--ty-date-picker-color);\n border: 1px solid var(--date-picker-accent, var(--ty-date-picker-border));\n border-radius: var(--ty-date-picker-radius);\n font-family: var(--ty-font-sans);\n font-size: var(--ty-font-sm);\n font-weight: var(--ty-font-normal);\n line-height: var(--ty-line-height-tight);\n min-height: var(--ty-size-md);\n padding: var(--ty-spacing-2) var(--ty-spacing-3);\n padding-right: calc(var(--ty-spacing-3) + 1rem + var(--ty-spacing-2));\n transition: var(--ty-transition-all), opacity 0.2s ease;\n outline: none;\n}\n\n.date-picker-stub:hover:not([disabled]):not(.open) {\n border-color: var(--date-picker-accent-bold, var(--ty-date-picker-border-hover));\n}\n\n.date-picker-stub[disabled] {\n background-color: var(--ty-date-picker-disabled-bg);\n color: var(--ty-date-picker-disabled-color);\n cursor: not-allowed;\n opacity: 0.6;\n}\n\n.date-picker-stub:focus,\n.date-picker-stub.open {\n border-color: var(--date-picker-accent-bold, var(--ty-date-picker-border-focus));\n box-shadow: 0 0 0 3px var(--date-picker-ring, var(--ty-date-picker-shadow-focus));\n}\n\n/* Size variants */\n.date-picker-stub.sm {\n min-height: var(--ty-size-sm);\n font-size: var(--ty-font-xs);\n padding: var(--ty-spacing-1) var(--ty-spacing-2);\n padding-right: calc(var(--ty-spacing-2) + 0.875rem + var(--ty-spacing-1));\n}\n\n.date-picker-stub.lg {\n min-height: var(--ty-size-lg);\n font-size: var(--ty-font-base);\n padding: var(--ty-spacing-2) var(--ty-spacing-4);\n padding-right: calc(var(--ty-spacing-4) + 1.125rem + var(--ty-spacing-2));\n}\n\n/* Flavor variants — set --date-picker-accent*, consumed by the stub rules above */\n${r.filter(t=>"neutral"!==t).map(t=>Ye(t)).join("")}\n\n/* Text content */\n.stub-text {\n flex: 1;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n user-select: none;\n color: inherit;\n pointer-events: none;\n}\n\n.stub-text.placeholder {\n color: var(--ty-date-picker-placeholder);\n}\n\n/* Icons */\n.stub-icons {\n display: flex;\n align-items: center;\n gap: var(--ty-spacing-1);\n position: absolute;\n right: var(--ty-spacing-3);\n top: 50%;\n transform: translateY(-50%);\n height: 1rem;\n pointer-events: none;\n z-index: 2;\n}\n\n.stub-clear {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 1rem;\n height: 1rem;\n padding: 0;\n border: none;\n background: none;\n color: var(--ty-color-neutral-soft);\n cursor: pointer;\n border-radius: var(--ty-radius-sm);\n transition: all 0.15s ease;\n pointer-events: auto;\n}\n\n.stub-clear:hover {\n /* Clear is a destructive utility action, not the field's semantic flavor\n — it stays neutral at rest and always warns danger-red on hover,\n regardless of the field's own flavor. (--ty-color-negative/\n --ty-bg-negative-faint used here previously don't exist as tokens —\n this silently fell back to unstyled inherited color.) */\n color: var(--ty-color-danger);\n background-color: var(--ty-bg-danger-soft);\n}\n\n.stub-arrow {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 1rem;\n height: 1rem;\n color: var(--date-picker-accent, var(--ty-color-neutral-soft));\n}\n\n.date-picker-stub:hover .stub-arrow {\n color: var(--date-picker-accent-bold, var(--ty-color-neutral));\n}\n\n.date-picker-stub:focus .stub-arrow,\n.date-picker-stub.open .stub-arrow {\n color: var(--date-picker-accent-bold, var(--ty-date-picker-border-focus));\n}\n\n/* Calendar dialog (showModal positioning system) */\n.calendar-dialog {\n position: fixed;\n flex-direction: column;\n max-width: 90vw;\n margin: 0;\n padding: 0;\n border: none;\n background: transparent;\n box-sizing: border-box;\n padding: var(--calendar-padding, 8px);\n\n /* Hidden by default */\n opacity: 0;\n transition: opacity 200ms ease;\n\n transform: translate(var(--calendar-offset-x, 0px), var(--calendar-offset-y, 0px));\n top: -1000px;\n left: -1000px;\n}\n\n/* Direction-based positioning with CSS classes */\n.calendar-dialog.position-below {\n left: var(--calendar-x);\n top: var(--calendar-y);\n}\n\n.calendar-dialog.position-above {\n left: var(--calendar-x);\n bottom: var(--calendar-y);\n top: auto;\n flex-direction: column-reverse;\n}\n\n.calendar-dialog.open {\n opacity: 1;\n}\n\n.calendar-dialog::backdrop {\n background: transparent\n}\n\n/* Calendar content container */\n.calendar-content {\n background-color: var(--ty-calendar-surface-bg);\n border: 1px solid var(--ty-calendar-surface-border);\n border-radius: var(--ty-calendar-surface-radius);\n box-shadow: var(--ty-calendar-surface-shadow);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n align-items: center;\n}\n\n/* Native date input for mobile */\n/* Native input is invisible — used only to trigger the OS picker */\n.native-date-input {\n position: absolute;\n inset: 0;\n opacity: 0;\n width: 100%;\n height: 100%;\n margin: 0;\n padding: 0;\n border: none;\n cursor: pointer;\n z-index: 1;\n}\n\n.native-date-input::-webkit-calendar-picker-indicator {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n margin: 0;\n padding: 0;\n cursor: pointer;\n}\n\n/* Time input section */\n.time-section {\n display: flex;\n min-height: 2.5rem;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n padding: 0.5rem 1rem;\n border-top: 1px solid var(--ty-calendar-time-border);\n background-color: var(--ty-calendar-time-bg);\n width: 100%;\n box-sizing: border-box;\n position: relative;\n}\n\n.time-label {\n font-size: var(--ty-font-sm);\n font-weight: 500;\n color: var(--ty-calendar-time-label-color);\n flex-shrink: 0;\n}\n\n.time-input {\n width: 3.5rem;\n border: 1px solid var(--ty-input-border);\n border-radius: var(--ty-radius-sm);\n background: var(--ty-input-bg);\n color: var(--ty-calendar-time-input-color);\n font-family: var(--ty-font-sans);\n font-size: var(--ty-font-sm);\n font-variant-numeric: tabular-nums;\n text-align: center;\n padding: 0.25rem 0.375rem;\n outline: none;\n transition: var(--ty-transition-all);\n}\n\n.time-input:focus {\n border-color: var(--ty-input-border-focus);\n box-shadow: 0 0 0 3px var(--ty-input-shadow-focus);\n}\n\n.time-input::placeholder {\n color: var(--ty-calendar-time-placeholder-color);\n}\n\n.time-icon {\n display: flex;\n align-items: center;\n color: var(--ty-calendar-time-icon-color);\n width: 1rem;\n height: 1rem;\n flex-shrink: 0;\n}\n`,Ge="<svg stroke='currentColor' fill='none' stroke-width='2' viewBox='0 0 24 24' width='16' height='16' xmlns='http://www.w3.org/2000/svg'><rect x='3' y='4' width='18' height='18' rx='2' ry='2'></rect><line x1='16' y1='2' x2='16' y2='6'></line><line x1='8' y1='2' x2='8' y2='6'></line><line x1='3' y1='10' x2='21' y2='10'></line></svg>",Ke="<svg stroke='currentColor' fill='none' stroke-width='2' viewBox='0 0 24 24' width='14' height='14' xmlns='http://www.w3.org/2000/svg'><line x1='18' y1='6' x2='6' y2='18'></line><line x1='6' y1='6' x2='18' y2='18'></line></svg>",Ze=new WeakMap;let Xe=0;function Je(t){let n=Ze.get(t);return void 0===n&&(n=++Xe,Ze.set(t,n)),n}function Qe(t,n){if(!t)return null;let e=null;if("string"==typeof t)if(/^\d{4}-\d{2}-\d{2}$/.test(t)){const[n,i,o]=t.split("-");e=new Date(parseInt(n,10),parseInt(i,10)-1,parseInt(o,10),0,0,0,0)}else e=new Date(t);else"number"==typeof t&&(e=new Date(t));return!e||isNaN(e.getTime())?null:{year:e.getFullYear(),month:e.getMonth()+1,day:e.getDate(),hour:n?e.getHours():0,minute:n?e.getMinutes():0}}function ti(t){const{year:n,month:e,day:i,hour:o,minute:s}=t;return n&&e&&i?new Date(n,e-1,i,o||0,s||0,0,0):null}function ni(t){if(!t.year||!t.month||!t.day)return null;const n=ti(t);return n?n.toISOString():null}function ei(t,n){if(!t.year||!t.month||!t.day)return null;const e=(""+t.year).padStart(4,"0"),i=(""+t.month).padStart(2,"0"),o=(""+t.day).padStart(2,"0");return n?`${e}-${i}-${o}T${(""+(t.hour||0)).padStart(2,"0")}:${(""+(t.minute||0)).padStart(2,"0")}`:`${e}-${i}-${o}`}function ii(t,n){return`${(""+t).padStart(2,"0")}:${(""+n).padStart(2,"0")}`}function oi(t){switch(t){case 0:return 1;case 1:return 3;case 3:return 4;case 4:case 5:return 5;default:return t}}class si{constructor(t,n,e=0,i=0){this.element=t,this.datePickerElement=n;const o=ii(e,i);this.state={hour:e,minute:i,caretPosition:0,displayValue:o,rawDigits:(""+e).padStart(2,"0")+(""+i).padStart(2,"0")},this.element.value=o,this.setupEventListeners()}setupEventListeners(){this.element.addEventListener("keydown",t=>this.handleKeyDown(t)),this.element.addEventListener("input",t=>this.handleInput(t)),this.element.addEventListener("click",()=>this.handleClick()),this.element.addEventListener("focus",()=>this.handleFocus())}handleKeyDown(t){const n=t.key;switch(n){case"ArrowRight":this.handleArrowRight(t);break;case"ArrowLeft":this.handleArrowLeft(t);break;case"Backspace":this.handleBackspace(t);break;case"Delete":this.handleDelete(t);break;case"Home":t.preventDefault(),this.updateState({caretPosition:0});break;case"End":t.preventDefault(),this.updateState({caretPosition:5});break;case"Tab":break;default:/^\d$/.test(n)&&this.handleDigitInput(t,parseInt(n,10))}}handleInput(t){t.preventDefault()}handleClick(){this.updateState({caretPosition:0})}handleFocus(){this.updateState({caretPosition:0})}handleArrowRight(t){t.preventDefault();const n=oi(this.state.caretPosition);this.updateState({caretPosition:n})}handleArrowLeft(t){t.preventDefault();const n=function(t){switch(t){case 5:return 4;case 4:return 3;case 3:return 1;case 1:case 0:return 0;default:return t}}(this.state.caretPosition);this.updateState({caretPosition:n})}handleDigitInput(t,n){t.preventDefault();const e=this.state.caretPosition;if(![0,1,3,4].includes(e))return;if(!function(t,n,e){switch(n){case 0:return 2>=t;case 1:return 2!==parseInt(e[0],10)||3>=t;case 3:return 5>=t;case 4:return!0;default:return!1}}(n,e,this.state.rawDigits))return;const i=this.replaceDigitAtPosition(e,n);if(!i)return;const o=oi(e);this.updateState({...i,caretPosition:o}),this.notifyTimeChange()}handleBackspace(t){t.preventDefault();const n=this.state.caretPosition;if(0===n)return;const e=1===n?0:3===n?1:4===n?3:5===n?4:0,i=this.zeroDigitAtPosition(e);i&&(this.updateState({...i,caretPosition:e}),this.notifyTimeChange())}handleDelete(t){t.preventDefault();const n=this.state.caretPosition;if(![0,1,3,4].includes(n))return;const e=this.zeroDigitAtPosition(n);e&&(this.updateState({...e,caretPosition:n}),this.notifyTimeChange())}replaceDigitAtPosition(t,n){const e=function(t){switch(t){case 0:default:return 0;case 1:return 1;case 3:return 2;case 4:return 3}}(t),i=this.state.rawDigits.split("");i[e]=""+n;const o=i.join(""),s=function(t){if(!t||4!==t.length)return null;const n=t.substring(0,2),e=t.substring(2,4),i=parseInt(n,10),o=parseInt(e,10);return 0>i||i>23||0>o||o>59?null:{hour:i,minute:o}}(o);return s?{rawDigits:o,hour:s.hour,minute:s.minute,displayValue:ii(s.hour,s.minute)}:null}zeroDigitAtPosition(t){return this.replaceDigitAtPosition(t,0)}updateState(t){this.state={...this.state,...t},this.element.value=this.state.displayValue;const n=this.state.caretPosition,e=0===n?0:1===n?1:2===n||3===n?3:4===n?4:5===n?5:n;this.element.setSelectionRange(e,e)}notifyTimeChange(){this.datePickerElement.handleTimeInputChange(this.state.hour,this.state.minute)}getTime(){return{hour:this.state.hour,minute:this.state.minute}}setTime(t,n){const e=ii(t,n);this.state={...this.state,hour:t,minute:n,displayValue:e,rawDigits:(""+t).padStart(2,"0")+(""+n).padStart(2,"0")},this.element.value=e}}const ri=class extends i{constructor(){super(),this.xn={withTime:!1,open:!1},this.ee=0,this.I=null,s(this.shadowRoot,{css:Ue,id:"ty-date-picker"})}onConnect(){this.initializeState(),this.render(),this.J=Z(this,()=>{this.render()}),this.D()}D(){this.I=u(this.shadowRoot,this.I,"default"===this.flavor?"neutral":this.flavor,({base:t})=>(t=>Ye(t,"neutral"))(t))}onDisconnect(){this.J&&(this.J(),this.J=void 0),this.cleanup()}onPropertiesChanged(t){for(const{name:n,newValue:e}of t)switch(n){case"flavor":this.D();break;case"size":case"label":case"placeholder":case"required":case"disabled":case"clearable":case"format":case"locale":break;case"value":{const t=Qe(e,this.xn.withTime);if(null===t){(void 0!==this.xn.year||void 0!==this.xn.month||void 0!==this.xn.day)&&(this.xn={withTime:this.xn.withTime,open:this.xn.open});break}const n={year:this.xn.year,month:this.xn.month,day:this.xn.day,hour:this.xn.hour,minute:this.xn.minute};(t?.year!==n.year||t?.month!==n.month||t?.day!==n.day||t?.hour!==n.hour||t?.minute!==n.minute)&&(this.xn={...this.xn,...t});break}case"with-time":e!==this.xn.withTime&&(this.xn.withTime=e,void 0!==this.xn.year&&void 0!==this.xn.month&&void 0!==this.xn.day&&this.syncFormValue())}}getFormValue(){return ni(this.getComponents())}getComponents(){return{year:this.xn.year,month:this.xn.month,day:this.xn.day,hour:this.xn.hour,minute:this.xn.minute}}hasDate(){return!!(this.xn.year&&this.xn.month&&this.xn.day)}getFormattedValue(t){const n=t||this.getComponents();return n.year&&n.month&&n.day?function(t,n,e,i){if(!t.year||!t.month||!t.day)return null;const o=ti(t);if(!o)return null;const s={dateStyle:n};return i&&(s.timeStyle="short"),new Intl.DateTimeFormat(e,s).format(o)}(n,this.getProperty("format")||"long",K(this,this.getProperty("locale")),this.xn.withTime):null}initializeState(){const t=this.getProperty("value"),n=this.getProperty("with-time"),e=Qe(t,n);this.xn=null===e?{withTime:n,open:!1}:{...e,withTime:n,open:!1},this.syncFormValue()}updateState(t,n=!1){this.xn={...this.xn,...t},(n||!this.xn.open||!this.xn.withTime)&&this.syncFormValue()}syncFormValue(){const t=this.getFormValue();t!==this.getProperty("value")&&this.setProperty("value",t||null)}handleTimeInputChange(t,n){if(!this.hasDate())return;const e={...this.getComponents(),hour:t,minute:n};this.updateState(e,!0),this.emitChangeEvent(e,"time-change")}emitChangeEvent(t,n){const e=t?ni(t):null,i=t?ei(t,this.xn.withTime):null,o=t?ti(t)?.getTime()??null:null,s=t?this.getFormattedValue(t):null,r=new CustomEvent("change",{detail:{value:e,localValue:i,milliseconds:o,formatted:s,source:n},bubbles:!0,cancelable:!0});this.dispatchEvent(r)}get size(){return this.getProperty("size")}set size(t){this.setProperty("size",t)}get flavor(){return this.getProperty("flavor")}set flavor(t){this.setProperty("flavor",t)}get label(){return this.getProperty("label")}set label(t){this.setProperty("label",t)}get placeholder(){return this.getProperty("placeholder")}set placeholder(t){this.setProperty("placeholder",t)}get name(){return this.getProperty("name")}set name(t){this.setProperty("name",t)}get format(){return this.getProperty("format")}set format(t){this.setProperty("format",t)}get locale(){return this.getProperty("locale")}set locale(t){this.setProperty("locale",t)}get required(){return this.getProperty("required")}set required(t){this.setProperty("required",t)}get disabled(){return this.getProperty("disabled")}set disabled(t){this.setProperty("disabled",t)}get clearable(){return this.getProperty("clearable")}set clearable(t){this.setProperty("clearable",t)}get min(){return this.getProperty("min")}set min(t){this.setProperty("min",t??"")}get max(){return this.getProperty("max")}set max(t){this.setProperty("max",t??"")}get withTime(){return this.getProperty("with-time")}set withTime(t){this.setProperty("with-time",t)}get value(){return this.getProperty("value")||null}set value(t){if(null==t||""===t)this.setProperty("value",null);else{const n=t instanceof Date?t.toISOString():t;this.setProperty("value",n)}}buildStubClasses(){const t=["date-picker-stub"],n=this.getProperty("size")||"md";return t.push(n),this.getProperty("disabled")&&t.push("disabled"),this.getProperty("required")&&t.push("required"),this.xn.open&&t.push("open"),t.join(" ")}renderStub(){const t=document.createElement("div");t.className=this.buildStubClasses();const n=this.getProperty("disabled");n&&t.setAttribute("disabled","true"),t.setAttribute("role","button"),t.setAttribute("aria-haspopup","dialog"),t.setAttribute("aria-expanded",this.xn.open+""),t.setAttribute("tabindex",n?"-1":"0"),n&&t.setAttribute("aria-disabled","true"),this.getProperty("label")&&t.setAttribute("aria-labelledby","date-picker-label-"+Je(this)),t.addEventListener("keydown",t=>{this.xn.open||"Enter"!==t.key&&" "!==t.key||(t.preventDefault(),this.handleStubClick(t))});const e=document.createElement("slot");e.name="start";const i=document.createElement("span");i.className="stub-text";const o=this.getFormattedValue(),s=this.getProperty("placeholder")||"Select date...";i.textContent=o||s,o||i.classList.add("placeholder");const r=document.createElement("div");if(r.className="stub-icons",this.getProperty("clearable")&&o&&!n){const t=document.createElement("button");t.className="stub-clear",t.type="button",t.innerHTML=Ke,t.addEventListener("click",t=>this.handleClearClick(t)),r.appendChild(t)}const a=document.createElement("span");return a.className="stub-arrow",a.innerHTML=Ge,r.appendChild(a),t.addEventListener("click",t=>this.handleStubClick(t)),t.appendChild(e),t.appendChild(i),t.appendChild(r),t}createTimeInputElement(){const t=document.createElement("input");return t.type="text",t.className="time-input",t.placeholder="HH:mm",t.autocomplete="off",t.maxLength=5,t}renderTimeSection(){const t=document.createElement("div");t.className="time-section";const n=document.createElement("label");n.className="time-label",n.textContent="Time:";const e=this.createTimeInputElement();this.ie=new si(e,this,this.xn.hour||0,this.xn.minute||0);const i=document.createElement("span");return i.className="time-icon",i.innerHTML="<svg stroke='currentColor' fill='none' stroke-width='2' viewBox='0 0 24 24' width='16' height='16' xmlns='http://www.w3.org/2000/svg'><circle cx='12' cy='12' r='10'></circle><polyline points='12,6 12,12 16,14'></polyline></svg>",t.appendChild(n),t.appendChild(e),t.appendChild(i),t}renderCalendarDropdown(){const t=document.createElement("dialog");t.className="calendar-dialog";const n=document.createElement("div");n.className="calendar-content";const e=document.createElement("ty-calendar");this.xn.year&&this.xn.month&&this.xn.day&&(e.setAttribute("year",""+this.xn.year),e.setAttribute("month",""+this.xn.month),e.setAttribute("day",""+this.xn.day));const i=K(this,this.getProperty("locale"));i&&e.setAttribute("locale",i);const o=this.getProperty("min"),s=this.getProperty("max");o&&e.setAttribute("min",o),s&&e.setAttribute("max",s);const r=this.getProperty("flavor");return r&&"default"!==r&&e.setAttribute("flavor",r),e.addEventListener("change",t=>this.handleCalendarChange(t)),n.appendChild(e),this.xn.withTime&&n.appendChild(this.renderTimeSection()),t.appendChild(n),t.addEventListener("close",()=>{this.updateState({open:!1})}),t}renderNativeInput(){const t=document.createElement("div");t.className="dropdown-wrapper";const n=document.createElement("div");n.className=this.buildStubClasses();const e=this.getProperty("disabled");e&&n.setAttribute("disabled","true");const i=document.createElement("input");i.className="native-date-input",i.type=this.xn.withTime?"datetime-local":"date",e&&(i.disabled=!0),this.getProperty("required")&&(i.required=!0);const o=this.getProperty("min"),s=this.getProperty("max");o&&(i.min=this.xn.withTime?o+"T00:00":o),s&&(i.max=this.xn.withTime?s+"T23:59":s);const r=ei(this.getComponents(),this.xn.withTime);r&&(i.value=r);const a=this.getProperty("placeholder")||"Select date...",l=this.getFormattedValue(),c=document.createElement("span");c.className="stub-text"+(l?"":" placeholder"),c.textContent=l||a,i.addEventListener("change",()=>{if(!i.value)return void this.clearValue();const t=Qe(i.value,this.xn.withTime);t&&(this.updateState(t,!0),this.emitChangeEvent(t,"selection"))});const d=document.createElement("slot");d.name="start",n.appendChild(d),n.appendChild(i),n.appendChild(c);const h=document.createElement("div");if(h.className="stub-icons",this.getProperty("clearable")&&r&&!e){const t=document.createElement("button");t.className="stub-clear",t.type="button",t.innerHTML=Ke,t.addEventListener("click",t=>this.handleClearClick(t)),h.appendChild(t)}const u=document.createElement("span");return u.className="stub-arrow",u.innerHTML=Ge,h.appendChild(u),n.appendChild(h),t.appendChild(n),t}calculateCalendarPosition(){if(!this.shadowRoot)return;if(qn())return;const t=this.shadowRoot.querySelector(".date-picker-stub"),n=this.shadowRoot.querySelector(".calendar-dialog");if(!t||!n)return;const e=t.getBoundingClientRect(),i=n.getBoundingClientRect(),o=Ot({anchorRect:e,popupWidth:i.width||320,popupHeight:i.height||400,gap:0}),s=o.below,r=s?o.topY:o.bottomY;this.style.setProperty("--calendar-x",o.x-8+"px"),this.style.setProperty("--calendar-y",r+"px"),this.style.setProperty("--calendar-offset-x","0px"),this.style.setProperty("--calendar-offset-y","0px"),s?(n.classList.add("position-below"),n.classList.remove("position-above")):(n.classList.add("position-above"),n.classList.remove("position-below"))}renderContainer(){const t=document.createElement("div");t.className="dropdown-container";const n=this.getProperty("label");if(n){const e=document.createElement("label");e.className="ty-field-label",e.id="date-picker-label-"+Je(this),e.innerHTML=n+(this.getProperty("required")?'<span class="required-icon">*</span>':""),t.appendChild(e)}return t}render(){if(!this.shadowRoot)return;if(s(this.shadowRoot,{css:Ue,id:"ty-date-picker"}),qn()){if(this.shadowRoot.querySelector(".native-date-input"))return void this.updateDisplay();this.shadowRoot.innerHTML="";const t=this.renderContainer();return t.appendChild(this.renderNativeInput()),void this.shadowRoot.appendChild(t)}const t=this.shadowRoot.querySelector(".calendar-dialog");if(t&&t.open&&this.xn.open)return this.updateDisplay(),void this.calculateCalendarPosition();this.shadowRoot.innerHTML="";const n=this.renderContainer(),e=document.createElement("div");e.className="dropdown-wrapper",e.appendChild(this.renderStub()),e.appendChild(this.renderCalendarDropdown()),n.appendChild(e),this.shadowRoot.appendChild(n),this.setupEventListeners()}updateDisplay(){if(!this.shadowRoot)return;const t=this.getFormattedValue(),n=this.getProperty("placeholder")||"Select date...",e=this.hasDate(),i=this.getProperty("clearable"),o=this.getProperty("disabled"),s=this.shadowRoot.querySelector(".stub-text");s&&(s.textContent=t||n,s.classList.toggle("placeholder",!t));const r=this.shadowRoot.querySelector(".stub-clear");if(r&&(r.style.display=i&&e&&!o?"":"none"),qn()){const t=this.shadowRoot.querySelector(".native-date-input");if(t){const n=ei(this.getComponents(),this.xn.withTime);t.value=n||""}return}const a=this.shadowRoot.querySelector("ty-calendar");if(a&&e&&(a.setAttribute("year",""+this.xn.year),a.setAttribute("month",""+this.xn.month),a.setAttribute("day",""+this.xn.day)),a){const t=this.getProperty("flavor");t&&"default"!==t?a.setAttribute("flavor",t):a.removeAttribute("flavor")}this.ie&&void 0!==this.xn.hour&&void 0!==this.xn.minute&&this.ie.setTime(this.xn.hour,this.xn.minute)}setupEventListeners(){this.oe&&document.removeEventListener("click",this.oe),this.se&&document.removeEventListener("keydown",this.se),this.oe=t=>this.handleOutsideClick(t),this.se=t=>this.handleEscapeKey(t),document.addEventListener("click",this.oe),document.addEventListener("keydown",this.se);const t=this.shadowRoot?.querySelector(".calendar-dialog");t&&(this.re=t=>this.handleDialogClick(t),t.addEventListener("click",this.re))}handleStubClick(t){t.preventDefault();const n=this.shadowRoot?.querySelector(".calendar-dialog");!this.xn.open||n&&n.open||(this.updateState({open:!1},!0),rn("date-picker-"+(this.id||""+this))),!this.getProperty("disabled")&&Date.now()-this.ee>300&&this.openDropdown()}clearValue(){this.updateState({year:void 0,month:void 0,day:void 0,hour:void 0,minute:void 0},!0),this.value=null,this.emitChangeEvent(null,"clear"),this.render()}handleClearClick(t){t.preventDefault(),t.stopPropagation(),this.clearValue()}handleCalendarChange(t){t.preventDefault(),t.stopPropagation();const n=t.detail.dayContext;if(!n)return;const e={year:n.year,month:n.month,day:n.dayInMonth,hour:this.xn.hour,minute:this.xn.minute};this.updateState(e,!0),this.emitChangeEvent(e,"selection"),this.xn.withTime?requestAnimationFrame(()=>{if(!this.shadowRoot)return;const t=this.shadowRoot.querySelector(".time-input");t&&t.focus()}):this.closeDropdown()}handleDialogClick(t){if(!this.shadowRoot)return;const n=this.shadowRoot.querySelector(".calendar-dialog"),e=this.shadowRoot.querySelector(".calendar-content");t.target===n&&this.xn.open&&e&&!e.contains(t.target)&&(t.preventDefault(),t.stopPropagation(),this.closeDropdown())}handleOutsideClick(t){if(!this.shadowRoot)return;const n=t.target,e=this.shadowRoot.querySelector(".calendar-dialog");this.xn.open&&e&&!this.contains(n)&&!e.contains(n)&&this.closeDropdown()}handleEscapeKey(t){"Escape"===t.key&&this.xn.open&&(t.preventDefault(),this.closeDropdown())}openDropdown(){this.xn.open||qn()||(this.updateState({open:!0}),this.dispatchEvent(new CustomEvent("open",{bubbles:!0,composed:!0})),this.render(),requestAnimationFrame(()=>{if(!this.shadowRoot)return;const t=this.shadowRoot.querySelector(".calendar-dialog");if(t){sn("date-picker-"+(this.id||""+this)),t.showModal(),this.calculateCalendarPosition(),t.classList.add("open");const n=this.shadowRoot.querySelector(".date-picker-stub");n&&n.setAttribute("aria-expanded","true");const e=this.shadowRoot.activeElement;e&&e.blur()}}))}closeDropdown(){if(!this.xn.open)return;this.ee=Date.now();const t="date-picker-"+(this.id||""+this);if(this.updateState({open:!1},!0),rn(t),this.shadowRoot){const t=this.shadowRoot.querySelector(".calendar-dialog");t&&(t.classList.remove("position-above","position-below","open"),t.close());const n=this.shadowRoot.querySelector(".date-picker-stub");n&&n.setAttribute("aria-expanded","false")}this.dispatchEvent(new CustomEvent("close",{bubbles:!0,composed:!0})),this.render()}cleanup(){if(this.oe&&document.removeEventListener("click",this.oe),this.se&&document.removeEventListener("keydown",this.se),this.re&&this.shadowRoot){const t=this.shadowRoot.querySelector(".calendar-dialog");t&&t.removeEventListener("click",this.re)}this.xn.open&&rn("date-picker-"+(this.id||""+this)),this.oe=void 0,this.se=void 0,this.re=void 0,this.ie=void 0}};ri.properties={size:{type:"string",visual:!0,default:"md",validate:t=>["sm","md","lg"].includes(t),coerce:t=>"xs"===t?"sm":"xl"===t?"lg":["sm","md","lg"].includes(t)?t:"md"},flavor:{type:"string",visual:!0,default:"default"},label:{type:"string",visual:!0,default:""},placeholder:{type:"string",visual:!0,default:"Select date..."},name:{type:"string",visual:!1,default:""},min:{type:"string",visual:!0,default:""},max:{type:"string",visual:!0,default:""},required:{type:"boolean",visual:!0,default:!1},disabled:{type:"boolean",visual:!0,default:!1},clearable:{type:"boolean",visual:!0,default:!0,aliases:{"not-clearable":!1}},format:{type:"string",visual:!0,default:"long",validate:t=>["short","medium","long","full"].includes(t),coerce:t=>["short","medium","long","full"].includes(t)?t:"long"},locale:{type:"string",visual:!0,default:""},value:{type:"string",visual:!0,formValue:!0,emitChange:!1,default:null},"with-time":{type:"boolean",visual:!0,default:!1}},ri.formAssociated=!0;let ai=ri;customElements.get("ty-date-picker")||customElements.define("ty-date-picker",ai);const li=new Map,ci=new Map;function di(t){return li.get(t)}function hi(t,n){ci.has(t)||ci.set(t,new Set),ci.get(t).add(n);const e=li.get(t);return e&&n(e),()=>{ci.get(t)?.delete(n),0===ci.get(t)?.size&&ci.delete(t)}}function ui(){return Object.fromEntries(li)}class TyResizeObserver extends HTMLElement{constructor(){super(),this.$t=null,this.ae=null;const t=this.attachShadow({mode:"open"});s(t,{css:"\n:host {\n /* Default to block display, user can override */\n display: block;\n /* Ensure the component can participate in layout */\n position: relative;\n}\n\n/* Slot content styling */\n::slotted(*) {\n /* No default styling - preserve natural layout */\n}\n",id:"ty-resize-observer"}),t.innerHTML="<slot></slot>"}static get observedAttributes(){return["id","debounce"]}get debounce(){return parseInt(this.getAttribute("debounce")||"0")}set debounce(t){this.setAttribute("debounce",t+"")}connectedCallback(){this.setupObserver()}disconnectedCallback(){this.cleanup()}setupObserver(){this.$t=new ResizeObserver(t=>{this.debounce>0?(this.ae&&clearTimeout(this.ae),this.ae=window.setTimeout(()=>{this.handleResize(t)},this.debounce)):this.handleResize(t)}),this.$t.observe(this)}handleResize(t){const{width:n,height:e}=t[0].contentRect;this.id&&function(t,n,e){li.set(t,{width:n,height:e});const i=ci.get(t);if(i){const t={width:n,height:e};i.forEach(n=>n(t))}}(this.id,n,e)}cleanup(){var t;this.$t&&(this.$t.disconnect(),this.$t=null),this.ae&&(clearTimeout(this.ae),this.ae=null),this.id&&(li.delete(t=this.id),ci.delete(t))}}customElements.define("ty-resize-observer",TyResizeObserver);const pi=`\n:host {\n display: block;\n position: relative;\n overflow: hidden;\n}\n\n.scroll-wrapper {\n width: 100%;\n height: 100%;\n overflow-y: auto;\n overflow-x: hidden;\n}\n\n/* Allow horizontal scrolling when enabled */\n:host([overflow-x]) .scroll-wrapper {\n overflow-x: auto;\n}\n\n:host([max-height]) .scroll-wrapper {\n max-height: var(--scroll-max-height);\n}\n\n/* ===================================== */\n/* hide-scrollbar: hides native, no custom */\n/* ===================================== */\n\n:host([hide-scrollbar]) .scroll-wrapper {\n scrollbar-width: none;\n -ms-overflow-style: none;\n}\n\n:host([hide-scrollbar]) .scroll-wrapper::-webkit-scrollbar {\n display: none;\n}\n\n/* scroll-anchoring: we manage scroll position in JS, so turn off the browser's\n native scroll anchoring to avoid double-compensation. */\n:host([scroll-anchoring]) .scroll-wrapper {\n overflow-anchor: none;\n}\n\n/* ===================================== */\n/* custom-scrollbar: hides native */\n/* ===================================== */\n\n:host([custom-scrollbar]) .scroll-wrapper {\n scrollbar-width: none;\n -ms-overflow-style: none;\n}\n\n:host([custom-scrollbar]) .scroll-wrapper::-webkit-scrollbar {\n display: none;\n}\n\n/* Show scrollbar tracks on host hover */\n:host([custom-scrollbar]:hover) .ty-scrollbar-track-y.has-overflow,\n:host([custom-scrollbar]:hover) .ty-scrollbar-track-x.has-overflow {\n opacity: 1;\n}\n\n/* Corner gap when both axes are present */\n:host([custom-scrollbar][overflow-x]) .ty-scrollbar-track-y {\n bottom: var(--ty-scrollbar-width, 8px);\n}\n\n:host([custom-scrollbar]) .ty-scrollbar-track-x {\n right: var(--ty-scrollbar-width, 8px);\n}\n\n/* ===================================== */\n/* Shadow Indicators */\n/* ===================================== */\n\n.shadow-overlay {\n position: absolute;\n inset: 0;\n pointer-events: none;\n z-index: 2;\n}\n\n.shadow-top,\n.shadow-bottom,\n.shadow-left,\n.shadow-right {\n position: absolute;\n opacity: 0;\n transition: var(--ty-scroll-shadow-transition, opacity 0.2s ease-out);\n pointer-events: none;\n}\n\n.shadow-top {\n top: -40px;\n left: 0;\n right: 0;\n height: 80px;\n background: var(--ty-scroll-shadow-top, radial-gradient(\n ellipse 100% 30% at center,\n color-mix(in oklab, var(--ty-color-neutral-bold) 12%, transparent),\n transparent,\n transparent\n ));\n clip-path: inset(50% 0 0 0);\n}\n\n.shadow-bottom {\n bottom: -30px;\n left: 0;\n right: 0;\n height: 60px;\n background: var(--ty-scroll-shadow-bottom, radial-gradient(\n ellipse 100% 20% at center,\n color-mix(in oklab, var(--ty-color-neutral-bold) 18%, transparent),\n transparent,\n transparent\n ));\n clip-path: inset(0 0 50% 0);\n}\n\n.shadow-left {\n left: -30px;\n top: 0;\n bottom: 0;\n width: 60px;\n background: var(--ty-scroll-shadow-left, radial-gradient(\n ellipse 30% 100% at center,\n color-mix(in oklab, var(--ty-color-neutral-bold) 12%, transparent),\n transparent,\n transparent\n ));\n clip-path: inset(0 0 0 50%);\n}\n\n.shadow-right {\n right: -30px;\n top: 0;\n bottom: 0;\n width: 60px;\n background: var(--ty-scroll-shadow-right, radial-gradient(\n ellipse 30% 100% at center,\n color-mix(in oklab, var(--ty-color-neutral-bold) 12%, transparent),\n transparent,\n transparent\n ));\n clip-path: inset(0 50% 0 0);\n}\n\n.shadow-left,\n.shadow-right {\n display: none;\n}\n\n:host([overflow-x]) .shadow-left,\n:host([overflow-x]) .shadow-right {\n display: block;\n}\n\n.shadow-top.visible,\n.shadow-bottom.visible,\n.shadow-left.visible,\n.shadow-right.visible {\n opacity: 1;\n}\n\n:host([shadow="false"]) .shadow-overlay {\n display: none;\n}\n\n/* Touch devices - restore native scrollbar */\n@media (pointer: coarse) and (hover: none) {\n :host([custom-scrollbar]) .scroll-wrapper {\n scrollbar-width: thin;\n scrollbar-color: var(--ty-border, color-mix(in oklab, var(--ty-color-neutral-bold) 25%, transparent)) transparent;\n }\n :host([custom-scrollbar]) .scroll-wrapper::-webkit-scrollbar {\n display: block;\n width: 4px;\n height: 4px;\n }\n :host([custom-scrollbar]) .scroll-wrapper::-webkit-scrollbar-thumb {\n background: var(--ty-border, color-mix(in oklab, var(--ty-color-neutral-bold) 25%, transparent));\n border-radius: 2px;\n }\n}\n\n/* Respect reduced motion */\n@media (prefers-reduced-motion: reduce) {\n .shadow-top,\n .shadow-bottom,\n .shadow-left,\n .shadow-right {\n transition-duration: 0ms !important;\n }\n}\n\n/* Shared scrollbar styles */\n${St}\n`;class TyScrollContainer extends HTMLElement{constructor(){super(),this.le=null,this.ce=null,this.de=null,this.he=null,this.ue=null,this.Qt=null,this.$t=null,this.pe=null,this.kt=null,this.be=!1,this.ge=!1,this.Mt=()=>{null===this.kt&&(this.kt=requestAnimationFrame(()=>{this.kt=null,this.me()}))},this.ve=()=>{this.Qt?.update(),this.me()};const t=this.attachShadow({mode:"open"});s(t,{css:pi,id:"ty-scroll-container"}),t.innerHTML='\n <div class="scroll-wrapper">\n <slot></slot>\n </div>\n <div class="shadow-overlay">\n <div class="shadow-top"></div>\n <div class="shadow-bottom"></div>\n <div class="shadow-left"></div>\n <div class="shadow-right"></div>\n </div>\n ',this.le=t.querySelector(".scroll-wrapper"),this.ce=t.querySelector(".shadow-top"),this.de=t.querySelector(".shadow-bottom"),this.he=t.querySelector(".shadow-left"),this.ue=t.querySelector(".shadow-right")}static get observedAttributes(){return["shadow","max-height","hide-scrollbar","custom-scrollbar","overflow-x","scroll-anchoring"]}get shadow(){return"false"!==this.getAttribute("shadow")}set shadow(t){t?this.removeAttribute("shadow"):this.setAttribute("shadow","false")}get maxHeight(){return this.getAttribute("max-height")}set maxHeight(t){t?this.setAttribute("max-height",t):this.removeAttribute("max-height"),this.fe()}get hideScrollbar(){return this.hasAttribute("hide-scrollbar")}set hideScrollbar(t){t?this.setAttribute("hide-scrollbar",""):this.removeAttribute("hide-scrollbar")}get customScrollbar(){return this.hasAttribute("custom-scrollbar")}set customScrollbar(t){t?this.setAttribute("custom-scrollbar",""):this.removeAttribute("custom-scrollbar")}get overflowX(){return this.hasAttribute("overflow-x")}set overflowX(t){t?this.setAttribute("overflow-x",""):this.removeAttribute("overflow-x")}get nearEdgeThreshold(){const t=parseInt(this.getAttribute("near-edge-threshold")||"",10);return Number.isFinite(t)?t:100}set nearEdgeThreshold(t){null==t?this.removeAttribute("near-edge-threshold"):this.setAttribute("near-edge-threshold",t+"")}get scrollAnchoring(){return this.hasAttribute("scroll-anchoring")}set scrollAnchoring(t){t?this.setAttribute("scroll-anchoring",""):this.removeAttribute("scroll-anchoring")}connectedCallback(){if(this.le?.addEventListener("scroll",this.Mt,{passive:!0}),this.$t=new ResizeObserver(()=>{this.Qt?.update(),this.me()}),this.le){this.$t.observe(this.le);const t=this.le.querySelector("slot");t&&t.addEventListener("slotchange",this.ve)}this.fe(),this.me(),this.nn(),this.ye()}disconnectedCallback(){this.le?.removeEventListener("scroll",this.Mt),this.tn(),this.we(),this.$t&&(this.$t.disconnect(),this.$t=null),null!==this.kt&&(cancelAnimationFrame(this.kt),this.kt=null)}attributeChangedCallback(t,n,e){n!==e&&("max-height"===t&&(this.fe(),this.me(),this.Qt?.update()),"custom-scrollbar"!==t&&"overflow-x"!==t||(this.tn(),this.nn(),this.me()),"scroll-anchoring"===t&&(this.we(),this.ye()))}ye(){!this.pe&&this.scrollAnchoring&&(this.pe=new MutationObserver(t=>{const n=this.le;if(!n)return;const e=n.getBoundingClientRect().top;let i=0;for(const o of t)o.addedNodes.forEach(t=>{if(t.nodeType!==Node.ELEMENT_NODE)return;const n=t.getBoundingClientRect();n.bottom>e?e>n.top&&(i+=e-n.top):i+=n.height});i>0&&(n.scrollTop+=i,this.Qt?.update())}),this.pe.observe(this,{childList:!0}))}we(){this.pe?.disconnect(),this.pe=null}nn(){if(this.Qt)return;if(!this.le||!this.customScrollbar)return;this.Qt=new Ct(this.le,{vertical:!0,horizontal:this.overflowX});const t=this.shadowRoot;this.Qt.trackY&&t.appendChild(this.Qt.trackY),this.Qt.trackX&&t.appendChild(this.Qt.trackX)}tn(){this.Qt&&(this.Qt.trackY?.remove(),this.Qt.trackX?.remove(),this.Qt.destroy(),this.Qt=null)}fe(){if(this.le){const t=this.maxHeight;t?(this.le.style.setProperty("--scroll-max-height",t),this.le.style.maxHeight=t):(this.le.style.removeProperty("--scroll-max-height"),this.le.style.maxHeight="")}}me(){if(!this.le)return;const{scrollTop:t,scrollLeft:n,scrollHeight:e,scrollWidth:i,clientHeight:o,clientWidth:s}=this.le;this.ce&&this.ce.classList.toggle("visible",t>2),this.de&&this.de.classList.toggle("visible",e-2>t+o),this.overflowX&&(this.he&&this.he.classList.toggle("visible",n>2),this.ue&&this.ue.classList.toggle("visible",i-2>n+s));const r=e-o;if(r>0){const n=this.nearEdgeThreshold,i=r-t;this.ge=this.xe("nearend",i,n,this.ge,{distance:i,scrollTop:t,scrollHeight:e,clientHeight:o}),this.be=this.xe("nearstart",t,n,this.be,{distance:t,scrollTop:t,scrollHeight:e,clientHeight:o})}else this.be=!1,this.ge=!1}xe(t,n,e,i,o){return e>=n&&(i||this.dispatchEvent(new CustomEvent(t,{detail:o,bubbles:!0,composed:!0})),!0)}updateShadows(){this.me(),this.Qt?.update()}scrollToTop(t=!0){this.le?.scrollTo({top:0,behavior:t?"smooth":"auto"})}scrollToBottom(t=!0){this.le&&this.le.scrollTo({top:this.le.scrollHeight,behavior:t?"smooth":"auto"})}scrollToLeft(t=!0){this.le?.scrollTo({left:0,behavior:t?"smooth":"auto"})}scrollToRight(t=!0){this.le&&this.le.scrollTo({left:this.le.scrollWidth,behavior:t?"smooth":"auto"})}scrollToElement(t,n=!0){const e="string"==typeof t?this.querySelector(t):t;e?.scrollIntoView({behavior:n?"smooth":"auto",block:"nearest"})}get scrollElement(){return this.le}}customElements.define("ty-scroll-container",TyScrollContainer),"undefined"!=typeof window&&(window.tyVersion=y,window.tyIcons={register:t=>{M(t)},get:t=>A(t),has:t=>I(t),list:()=>R(),cacheInfo:()=>q(),clearCache:()=>D()},window.tyResizeObserver={getSize:t=>di(t),onResize:(t,n)=>hi(t,n),get sizes(){return ui()}},window.tyLoader={set:t=>b(t),get:()=>g(),reset:()=>m()}),t.IconRegistry=V,t.TyButton=f,t.TyCalendar=_e,t.TyCalendarMonth=TyCalendarMonth,t.TyCalendarNavigation=Fe,t.TyCheckbox=ot,t.TyCopy=wt,t.TyDatePicker=ai,t.TyFileUpload=zt,t.TyIcon=j,t.TyInput=tt,t.TyModal=TyModal,t.TyOption=TyOption,t.TyPopup=TyPopup,t.TyRadio=ut,t.TyRadioGroup=bt,t.TyResizeObserver=TyResizeObserver,t.TyScrollContainer=TyScrollContainer,t.TySelect=Wn,t.TySelectedTags=TySelectedTags,t.TyStep=TyStep,t.TySwitch=lt,t.TyTab=TyTab,t.TyTabs=TyTabs,t.TyTag=_,t.TyTextarea=Mt,t.TyTooltip=TyTooltip,t.TyWizard=TyWizard,t.disableScrollLockDebug=function(){window.tyScrollDebug=!1},t.enableScrollLockDebug=function(){window.tyScrollDebug=!0},t.forceUnlockAll=function(){nn.activeLocks.clear(),on()},t.getActiveLocks=function(){return new Set(nn.activeLocks)},t.getAllSizes=ui,t.getLoaderSvg=g,t.getLockState=function(){return{locked:nn.locked,scrollY:nn.scrollY,activeLocks:Array.from(nn.activeLocks)}},t.getSize=di,t.isLocked=function(){return nn.locked},t.isLockedBy=function(t){return nn.activeLocks.has(t)},t.lockScroll=sn,t.onResize=hi,t.resetLoaderSvg=m,t.setLoaderSvg=b,t.unlockScroll=rn,Object.defineProperty(t,Symbol.toStringTag,{value:"Module"})});