tyrell-components 1.0.0-TC44 → 1.0.0-TC45
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 +1 -1
- package/lib/components/date-picker.d.ts +7 -0
- package/lib/components/date-picker.d.ts.map +1 -1
- package/lib/components/date-picker.js +9 -0
- package/lib/components/date-picker.js.map +1 -1
- package/lib/components/select.d.ts +32 -0
- package/lib/components/select.d.ts.map +1 -1
- package/lib/components/select.js +84 -0
- package/lib/components/select.js.map +1 -1
- package/lib/styles/select.d.ts +1 -1
- package/lib/styles/select.d.ts.map +1 -1
- package/lib/styles/select.js +48 -4
- package/lib/styles/select.js.map +1 -1
- package/lib/utils/positioning.d.ts +4 -0
- package/lib/utils/positioning.d.ts.map +1 -1
- package/lib/utils/positioning.js +4 -2
- package/lib/utils/positioning.js.map +1 -1
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +1 -1
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","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)=>`oklch(from ${t} calc(l + var(--ty-${n})) c h)`,d=(t,n)=>`oklch(from ${t} calc(l + sign(0.5 - l) * abs(var(--ty-${n}))) c h)`,c=(t,n)=>{const e=e=>a("--ty-solid",t,e,n),i="neutral"===t?" --_border-l: var(--ty-button-border-l-neutral, var(--ty-button-border-l, -0.15));":" --_border-l: var(--ty-button-border-l, -0.15);",o="neutral"===t?d:l;return`\nbutton.solid.${t} { --_ring: ${a("--ty-color",t,"",n)}; --_solid-bg: var(--ty-button-bg, var(--_muted-solid-bg, ${e("")})); --_solid-rest: var(--ty-button-bg, var(--_muted-solid-bg, ${e("")}));${i} color: var(--ty-button-color, var(--_muted-solid-fg, ${e("-fg")})); }\nbutton.solid.${t}.tone-plus { --_solid-bg: var(--ty-button-bg, var(--_muted-solid-bg, ${e("-strong")})); --_solid-rest: var(--ty-button-bg, var(--_muted-solid-bg, ${e("-strong")})); color: var(--ty-button-color, var(--_muted-solid-fg, ${e("-strong-fg")})); }\nbutton.solid.${t}.tone-minus { --_solid-bg: var(--ty-button-bg, var(--_muted-solid-bg, ${e("-soft")})); --_solid-rest: var(--ty-button-bg, var(--_muted-solid-bg, ${e("-soft")})); color: var(--ty-button-color, var(--_muted-solid-fg, ${e("-soft-fg")})); }\nbutton.solid.${t}:hover:not(:disabled) { --_solid-bg: var(--ty-button-bg-hover, ${e("-hover")}); }\nbutton.solid.${t}:active:not(:disabled) { --_solid-bg: ${e("-active")}; }\nbutton.solid.${t}.tone-plus:hover:not(:disabled) { --_solid-bg: var(--ty-button-bg-hover, ${o(e("-strong"),"solid-hover-l")}); }\nbutton.solid.${t}.tone-plus:active:not(:disabled) { --_solid-bg: ${o(e("-strong"),"solid-active-l")}; }\nbutton.solid.${t}.tone-minus:hover:not(:disabled) { --_solid-bg: var(--ty-button-bg-hover, ${l(e("-soft"),"solid-hover-l")}); }\nbutton.solid.${t}.tone-minus:active:not(:disabled) { --_solid-bg: ${l(e("-soft"),"solid-active-l")}; }\n`},h=(t,n)=>{const e=e=>"neutral"===t&&"-strong"===e?`var(--ty-solid-neutral${e})`:(e=>a("--ty-color",t,e,n))(e);return`\nbutton.outlined.${t} {\n color: var(--ty-button-color, var(--_muted-outlined-line, ${e("")}));\n border-color: var(--ty-button-border, var(--_muted-outlined-line, ${e("")}));\n}\nbutton.outlined.${t}.tone-plus {\n color: var(--ty-button-color, var(--_muted-outlined-line, ${e("-strong")}));\n border-color: var(--ty-button-border, var(--_muted-outlined-line, ${e("-strong")}));\n}\nbutton.outlined.${t}.tone-minus {\n color: var(--ty-button-color, var(--_muted-outlined-line, ${e("-soft")}));\n border-color: var(--ty-button-border, var(--_muted-outlined-line, ${e("-soft")}));\n}\nbutton.outlined.${t}:hover:not(:disabled) {\n background: var(--ty-button-bg-hover, ${a("--ty-bg",t,"-soft",n)});\n}\n/* Rest is whatever tone you picked; hover/active/focus always escalates to\n the SAME peak — most-emphasized ("+") color, regardless of starting\n tone. tone-plus is already there at rest, so this is a no-op for it.\n :hover only, :not(.muted) — muted's hover-reveal is a DIFFERENT contract\n (reveal the plain button's RESTING color, tested directly against it);\n this rule would outrank that fallback and show strong instead.\n :active/:focus-visible apply to muted too (no exclusion) — muted's own\n reveal-on-press mechanism has much lower specificity than this rule, so\n it simply wins outright, landing muted and plain on the same escalated\n color when both are pressed — which is what muted's OWN test expects. */\nbutton.outlined.${t}:not(.muted):hover:not(:disabled),\nbutton.outlined.${t}:active:not(:disabled),\nbutton.outlined.${t}:focus-visible {\n color: var(--ty-button-color, ${e("-strong")});\n border-color: var(--ty-button-border, ${e("-strong")});\n}\n`},u=(t,n)=>{const e=e=>"neutral"===t&&"-strong"===e?`var(--ty-solid-neutral${e})`:(e=>a("--ty-color",t,e,n))(e);return`\nbutton.ghost.${t} { color: var(--ty-button-color, var(--_muted-ghost-fg, ${e("")})); }\nbutton.ghost.${t}.tone-plus { color: var(--ty-button-color, var(--_muted-ghost-fg, ${e("-strong")})); }\nbutton.ghost.${t}.tone-minus { color: var(--ty-button-color, var(--_muted-ghost-fg, ${e("-soft")})); }\nbutton.ghost.${t}:hover:not(:disabled) {\n background: var(--ty-button-bg-hover, ${a("--ty-bg",t,"-soft",n)});\n}\n/* See outlinedFlavor above — same escalation-to-peak, same :hover-only\n :not(.muted) split, text only. */\nbutton.ghost.${t}:not(.muted):hover:not(:disabled),\nbutton.ghost.${t}:active:not(:disabled),\nbutton.ghost.${t}:focus-visible {\n color: var(--ty-button-color, ${e("-strong")});\n}\n`},p=`\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 /* Mode-flipped weight dial (tyrell.css): medium in light, normal in dark —\n light-on-dark text blooms, a fixed semibold read heavy there. Override\n with --ty-weight-action at any scope. */\n font-weight: var(--ty-weight-action, var(--ty-font-medium));\n white-space: nowrap;\n cursor: pointer;\n user-select: none;\n transition: var(--ty-local-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/* ===== MUTED =====\n Show the neutral tokens at rest instead of the flavor color; reveal the\n real flavor on interaction. Implemented as a fallback tier the flavor\n rules above already read (--_muted-*), which sits behind the public\n --ty-button-{bg,color,border} override slots and ahead of the flavor's\n own token — so a custom brand color still wins, muted or not. Unsetting\n --_muted-* on interaction falls the var() chain through to whatever's\n next (the user's override, or the real flavor color).\n Hover reveal is gated to real pointers (touch has no hover); :active /\n :focus-visible cover the tap case so touch still gets the color on press. */\n\n/* --_muted-solid-* reads the SOLID neutral ink tokens — a fill's L doesn't\n need page contrast. --_muted-outlined-line / --_muted-ghost-fg are bare\n text/border and DO — they stay on the regular text ladder (it already\n inverts correctly per mode), except tone-plus, which is legible AND\n loud on the ink dial (16.5:1 dark, matches solid's "+" identity). Base/\n soft on ink measured 1.01/1.20 dark contrast against the canvas —\n invisible; WCAG minimum is 4.5. */\nbutton.muted {\n --_muted-solid-bg: var(--ty-solid-neutral);\n --_muted-solid-fg: var(--ty-solid-neutral-fg);\n --_muted-outlined-line: var(--ty-color-neutral);\n --_muted-ghost-fg: var(--ty-color-neutral);\n}\nbutton.muted.tone-plus {\n --_muted-solid-bg: var(--ty-solid-neutral-strong);\n /* fg must track the tone's fill: neutral+ is inverted ink in dark mode\n (white fill), so inheriting base neutral's white fg would be\n white-on-white. */\n --_muted-solid-fg: var(--ty-solid-neutral-strong-fg);\n --_muted-outlined-line: var(--ty-solid-neutral-strong);\n --_muted-ghost-fg: var(--ty-solid-neutral-strong);\n}\nbutton.muted.tone-minus {\n --_muted-solid-bg: var(--ty-solid-neutral-soft);\n --_muted-solid-fg: var(--ty-solid-neutral-soft-fg);\n --_muted-outlined-line: var(--ty-color-neutral-soft);\n --_muted-ghost-fg: var(--ty-color-neutral-soft);\n}\n@media (hover: hover) and (pointer: fine) {\n button.muted:hover:not(:disabled) {\n --_muted-solid-bg: unset;\n --_muted-solid-fg: unset;\n --_muted-outlined-line: unset;\n --_muted-ghost-fg: unset;\n }\n}\nbutton.muted:active:not(:disabled),\nbutton.muted:focus-visible:not(:disabled) {\n --_muted-solid-bg: unset;\n --_muted-solid-fg: unset;\n --_muted-outlined-line: unset;\n --_muted-ghost-fg: unset;\n}\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-theme.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 --_ring: var(--ty-color-neutral);\n --_solid-bg: var(--ty-button-bg, var(--ty-solid-neutral));\n --_solid-rest: var(--ty-button-bg, var(--ty-solid-neutral));\n /* Bare .solid is the flavorless default = neutral ink, so it takes the\n neutral border offset; colored flavor rules reset this to the plain\n dial. */\n --_border-l: var(--ty-button-border-l-neutral, var(--ty-button-border-l, -0.15));\n background: var(--_solid-bg);\n color: var(--ty-button-color, var(--ty-solid-neutral-fg));\n /* Depth chrome — border + drop shadow, both scaled by --ty-button-depth.\n (A top-edge sheen — inset 0 1px 0 <lightened fill> — used to live here\n too; dropped, it read as a dizzying bright line rather than a subtle\n highlight.) depth 0 = border matches fill exactly and the shadow goes\n transparent — pixel-flat, but the 1px border stays in the layout so\n toggling depth never shifts geometry (and solid now shares the same\n box as outlined/ghost, which always had a 1px border).\n --ty-button-border-l flips sign with the mode (tyrell.css): dark mode\n runs a LIGHTER-than-fill hairline (fills read washed-out against dark\n surfaces without a lit edge), light mode a slightly darker one.\n Direct escape hatches outrank the derivation: --ty-solid-border-color\n pins the border to ANY color (the L-offset dials stop mattering), and\n --ty-solid-border-width changes thickness (widths ≠ 1px do shift\n geometry — that's inherent).\n Browsers without relative color drop these declarations: border falls\n back to the base button's 1px transparent, shadows to none. */\n border: var(--ty-solid-border-width, 1px) solid\n var(--ty-solid-border-color,\n oklch(from var(--_solid-rest, var(--_solid-bg)) calc(l + var(--_border-l, -0.15) * var(--ty-button-depth, 0.35)) c h));\n box-shadow: 0 1px 2px oklch(0 0 0 / calc(0.4 * var(--ty-button-depth, 0.35)));\n}\nbutton.solid.tone-plus { --_solid-bg: var(--ty-button-bg, var(--ty-solid-neutral-strong)); --_solid-rest: var(--ty-button-bg, var(--ty-solid-neutral-strong)); color: var(--ty-button-color, var(--ty-solid-neutral-strong-fg)); }\nbutton.solid.tone-minus { --_solid-bg: var(--ty-button-bg, var(--ty-solid-neutral-soft)); --_solid-rest: var(--ty-button-bg, var(--ty-solid-neutral-soft)); color: var(--ty-button-color, var(--ty-solid-neutral-soft-fg)); }\nbutton.solid:hover:not(:disabled) { --_solid-bg: var(--ty-button-bg-hover, var(--ty-solid-neutral-hover)); }\nbutton.solid:active:not(:disabled) { --_solid-bg: var(--ty-solid-neutral-active); }\nbutton.solid.tone-plus:hover:not(:disabled) {\n --_solid-bg: var(--ty-button-bg-hover, oklch(from var(--ty-solid-neutral-strong) calc(l + sign(0.5 - l) * abs(var(--ty-solid-hover-l))) c h));\n}\nbutton.solid.tone-plus:active:not(:disabled) {\n --_solid-bg: oklch(from var(--ty-solid-neutral-strong) calc(l + sign(0.5 - l) * abs(var(--ty-solid-active-l))) c h);\n}\nbutton.solid.tone-minus:hover:not(:disabled) {\n --_solid-bg: var(--ty-button-bg-hover, oklch(from var(--ty-solid-neutral-soft) calc(l + var(--ty-solid-hover-l)) c h));\n}\nbutton.solid.tone-minus:active:not(:disabled) {\n --_solid-bg: oklch(from var(--ty-solid-neutral-soft) calc(l + var(--ty-solid-active-l)) c h);\n}\n\n${r.map(t=>c(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=>h(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=>u(t)).join("")}`;function b(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 g=null;function m(t){g=t&&t.trim()?t:null}function v(){return g??'<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 f(){g=null}const y=class extends i{constructor(){super(),this.A=!1,this.D=null,s(this.shadowRoot,{css:p,id:"ty-button"})}onConnect(){this.I()}onDisconnect(){}onPropertiesChanged(t){t.some(t=>"flavor"===t.name)&&this.I()}I(){const{base:t}=this.parseFlavor();this.D=b(this.shadowRoot,this.D,t,()=>(t=>c(t,"neutral")+h(t,"neutral")+u(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 muted(){return this.getProperty("muted")}set muted(t){this.setProperty("muted",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",this.muted&&"muted","+"===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=v();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=v())}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))}};y.formAssociated=!0,y.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},muted:{type:"boolean",visual:!0,default:!1},wide:{type:"boolean",visual:!1,default:!1},name:{type:"string",default:""},value:{type:"string",default:""}};let w=y;customElements.get("ty-button")||customElements.define("ty-button",w);const x="1.0.0-TC44",k=new Map,z=new Map,$=new Map;let C=null,S=null;const E="ty-icons-v"+x,T="https://ty-icons.local/",M=new Map;let A=!1;function D(t){const n=new Set;Object.entries(t).forEach(([t,e])=>{k.set(t,e),n.add(t)}),n.size>0&&R(n)}function I(t){return k.get(t)}function O(t){return k.has(t)}async function L(){const t=new Set(k.keys());if(k.clear(),"caches"in window)try{await caches.delete(E),A=!1}catch(n){}R(t)}function N(t,n,e){z.set(t,e),n&&$.set(t,n)}function _(t){z.delete(t),$.delete(t)}function R(t){C||(C=new Set),t.forEach(t=>C.add(t)),null!==S&&clearTimeout(S);const n="undefined"!=typeof requestIdleCallback?requestIdleCallback:t=>setTimeout(t,0);S=n(()=>{const t=C;C=null,S=null,t&&t.size>0&&function(t){z.forEach((n,e)=>{const i=$.get(e);i?t.has(i)&&n(new Set([i])):n(t)})}(t)})}function q(){return Array.from(k.keys())}async function F(){const t={version:x,cacheName:E,available:"caches"in window};if(!t.available)return t;try{const n=await caches.open(E),e=(await n.keys()).filter(t=>t.url.startsWith(T));return{...t,iconCount:e.length}}catch(n){return t}}const V=Object.freeze(Object.defineProperty({__proto__:null,addWatcher:N,clearIcons:L,getCacheInfo:F,getCachedIcon:async function(t){const n=M.get(t);if(n)return n;const e=(async()=>{try{await async function(){if(!A&&"caches"in window){A=!0;try{const t=(await caches.keys()).filter(t=>t.startsWith("ty-icons-v")&&t!==E);await Promise.all(t.map(t=>caches.delete(t)))}catch(t){}}}();const n=await caches.open(E),e=await n.match(`${T}${t}`);if(e)return await e.text()}catch(n){}return null})();return M.set(t,e),e.finally(()=>{M.delete(t)}),e},getIcon:I,getIconNames:q,hasIcon:O,registerIcons:D,removeWatcher:_},Symbol.toStringTag,{value:"Module"}));let P=0;const H='<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>',j=class extends i{constructor(){super(),this.O=null,this.L="",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=H,this.L=H,this.shadowRoot.appendChild(this.N)}onConnect(){this.O="ty-icon-"+ ++P,this.name&&N(this.O,this.name,t=>{this.name&&t.has(this.name)&&this.render()}),this.updateClasses()}onDisconnect(){this.O&&(_(this.O),this.O=null)}onPropertiesChanged(t){for(const n of t)if("name"===n.name){this.O&&_(this.O);const t=n.newValue||"";t&&this.isConnected&&(this.O="ty-icon-"+ ++P,N(this.O,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(H);const n=I(t);this.renderSvg(n||H)}renderSvg(t){this.L!==t&&this.N&&(this.N.innerHTML=t,this.L=t)}};j.formAssociated=!1,j.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=j;customElements.get("ty-icon")||customElements.define("ty-icon",B);const W=`\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 /* Mode-flipped weight dial (tyrell.css): 440 light / 400 dark. Chips are\n labels, not actions — they run lighter than buttons. Override with\n --ty-weight-label at any scope. */\n font-weight: var(--ty-weight-label, 440);\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`,Y=class extends i{constructor(){super(),this._=null,this.D=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:W,id:"ty-tag"})}onConnect(){this.I(),queueMicrotask(()=>{this.setupEventListeners()})}I(){this.D=b(this.shadowRoot,this.D,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.I()}dispatchTagEvent(t,n){this.dispatchEvent(new CustomEvent(t,{detail:n,bubbles:!0,composed:!0,cancelable:!0}))}cleanupEventListeners(){this._&&(this._(),this._=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._=()=>{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)}};Y.formAssociated=!0,Y.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 U=Y;customElements.get("ty-tag")||customElements.define("ty-tag",U);class TyOption extends HTMLElement{constructor(){super(),this.R=void 0,this.q=!1,this.F=!1,this.V=!1,this.P=!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.R=t.value,delete this.value),this.render()}attributeChangedCallback(t,n,e){if(n!==e){switch(t){case"value":this.R=e||void 0;break;case"selected":this.q=null!==e;break;case"disabled":this.F=null!==e;break;case"highlighted":this.V=null!==e;break;case"hidden":this.P=null!==e}this.render()}}getOptionValue(){if(void 0!==this.R)return this.R;const t=this.getAttribute("value");return null!==t?t:this.textContent?.trim()||""}get value(){return this.getOptionValue()}set value(t){this.R!==t&&(this.R=t,void 0!==t?this.setAttribute("value",t):this.removeAttribute("value"),this.render())}get selected(){return this.q}set selected(t){this.q!==t&&(this.q=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.V}set highlighted(t){this.V!==t&&(this.V=t,t?this.setAttribute("highlighted",""):this.removeAttribute("highlighted"),this.render())}get hidden(){return this.P}set hidden(t){this.P!==t&&(this.P=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.q?n.setAttribute("selected",""):n.removeAttribute("selected"),this.V?n.setAttribute("highlighted",""):n.removeAttribute("highlighted"),this.P?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`},K=`\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: var(--ty-local-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/* :not(.focused) — hover must never override focus. Without the guard this\n rule out-ranks .focused by specificity, so hovering a FOCUSED unflavored\n input swapped its primary focus border for the dimmer neutral hover\n border (focus ring stayed, border dimmed — read as a glitch). Same\n pattern as date-picker's :hover:not(.open). */\n.input-wrapper:hover:not(.disabled):not(.focused) {\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: var(--ty-local-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 Z(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.H=null,this.j=!1,this.B=!1,this.W=!1,this.D=null,this.Y=null,this.U=null,this.G=null,this.K=null,this.Z=null,this.X=null,s(this.shadowRoot,{css:K,id:"ty-input"})}onConnect(){this.initializeShadowValue(),this.J=J(this,()=>{this.render()}),this.I()}I(){this.D=b(this.shadowRoot,this.D,this.flavor,({base:t})=>(t=>G(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.I();break;case"value":this.H=this.parseShadowValue(e||"");break;case"type":const t=this.getProperty("value")||"";this.H=this.parseShadowValue(t);break;case"error":e?"neutral"===this.getProperty("flavor")&&(this.setProperty("flavor","danger"),this.W=!0):this.W&&("danger"===this.getProperty("flavor")&&this.setProperty("flavor","neutral"),this.W=!1)}}onFormReset(){this.H=null,this.j=!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.H?this.H+"":null}initializeShadowValue(){const t=this.getProperty("value");t&&(this.H=this.parseShadowValue(t),this.v.setFormValue(null!==this.H?this.H+"":null))}parseShadowValue(t){if(!t||"string"!=typeof t||""===t.trim())return null;if(Z(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 Z(this.type)&&!this.j&&null!==this.H&&"number"==typeof this.H}getFormatConfig(){return{type:this.type,locale:this.locale,currency:this.currency,precision:this.precision}}getDisplayValue(){if(this.shouldFormat()){let t=this.H;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.H?this.H+"":""}get type(){return this.getProperty("type")}set type(t){this.setProperty("type",t)}get value(){return null!==this.H?this.H+"":""}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.H,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.H,formattedValue:this.shouldFormat()?this.getDisplayValue():null,rawValue:t,originalEvent:n},bubbles:!0,composed:!0}))}removeEventListeners(){if(!this.B)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.B=!1)}setupEventListeners(){if(this.B)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.H=this.parseShadowValue(e),this.v.setFormValue(null!==this.H?this.H+"":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.H=this.parseShadowValue(e),this.v.setFormValue(null!==this.H?this.H+"":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.j=!0,e.classList.add("focused"),Z(this.type)&&null!==this.H&&(n.value=this.H+""),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.j=!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.B=!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=Z(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: var(--ty-local-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: var(--ty-local-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.D=null,this.B=!1,this.tt=null,this.nt=null,this.G=null,this.K=null,s(this.shadowRoot,{css:ot,id:"ty-checkbox"})}onConnect(){this.setupEventListeners(),this.I()}I(){this.D=b(this.shadowRoot,this.D,this.flavor,({base:t})=>(t=>it(t,"neutral"))(t))}onDisconnect(){this.removeEventListeners()}onPropertiesChanged(t){t.some(t=>"flavor"===t.name)&&this.I()}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.B)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.B=!1):this.B=!1}setupEventListeners(){if(this.B)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.B=!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${K}\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: var(--ty-local-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: var(--ty-local-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`,dt=class extends i{constructor(){super(),this.D=null,this.B=!1,this.tt=null,this.nt=null,this.G=null,this.K=null,s(this.shadowRoot,{css:lt,id:"ty-switch"})}onConnect(){this.setupEventListeners(),this.I()}onDisconnect(){this.removeEventListeners()}onPropertiesChanged(t){t.some(t=>"flavor"===t.name)&&this.I()}I(){this.D=b(this.shadowRoot,this.D,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.B)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.B=!1):this.B=!1}setupEventListeners(){if(this.B)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.B=!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}};dt.formAssociated=!0,dt.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 ct=dt;customElements.get("ty-switch")||customElements.define("ty-switch",ct);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${K}\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: var(--ty-local-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.D=null,this.B=!1,this.tt=null,this.G=null,this.K=null,s(this.shadowRoot,{css:ut,id:"ty-radio"})}onConnect(){this.setupEventListeners(),this.dispatchEvent(new CustomEvent("ty-radio-connected",{bubbles:!0})),this.I()}onDisconnect(){this.removeEventListeners()}onPropertiesChanged(t){t.some(t=>"flavor"===t.name)&&this.I()}I(){this.D=b(this.shadowRoot,this.D,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.B)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.B=!1):this.B=!1}setupEventListeners(){if(this.B)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.B=!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.B=!1,this.et=null,this.nt=null,this.it=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.B&&(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.B=!1)}setupEventListeners(){this.B||(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.B=!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`},ft=`\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: var(--ty-local-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: var(--ty-local-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`,yt='<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.ot=null,this.st=!1,this.D=null,s(this.shadowRoot,{css:K,id:"ty-input"}),s(this.shadowRoot,{css:ft,id:"ty-copy"})}onConnect(){this.I()}I(){this.D=b(this.shadowRoot,this.D,this.flavor,({base:t})=>(t=>vt(t,"neutral"))(t))}onDisconnect(){null!==this.ot&&(clearTimeout(this.ot),this.ot=null)}onPropertiesChanged(t){t.some(t=>"flavor"===t.name)&&this.I()}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=wt,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=yt,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=yt,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">${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.st?" success":""}" type="button" aria-label="${this.st?"Copied!":"Copy to clipboard"}" ${this.disabled?"disabled":""}>\n ${this.st?wt:yt}\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.rt=[],this.lt=!1,this.B=!1,this.dt=null,this.ct=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: var(--ty-local-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: var(--ty-local-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: var(--ty-local-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.B)return;const t=this.shadowRoot,n=t.querySelector(".drop-zone"),e=t.querySelector(".file-input");this.dt=t=>{this.disabled||t.target.closest(".file-remove")||e.click()},this.ct=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.dt),n.addEventListener("keydown",this.ct),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.B=!0}removeEventListeners(){if(!this.B)return;const t=this.shadowRoot;if(!t)return;const n=t.querySelector(".drop-zone"),e=t.querySelector(".file-input");n&&e&&(this.dt&&n.removeEventListener("click",this.dt),this.ct&&n.removeEventListener("keydown",this.ct),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.B=!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=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 d=document.createElement("div");d.className="error-message",n.appendChild(d),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"}};$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.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.Dt=this.It.bind(this),this.Ot=this.Lt.bind(this),this.Nt=this._t.bind(this),this.Rt=this.qt.bind(this),this.Ft=this.Vt.bind(this),this.Pt=this.Ht.bind(this),this.St&&(this.trackY=this.jt("y"),this.thumbY=this.Bt("y"),this.trackY.appendChild(this.thumbY)),this.Et&&(this.trackX=this.jt("x"),this.thumbX=this.Bt("x"),this.trackX.appendChild(this.thumbX)),this.Ct.addEventListener("scroll",this.Mt,{passive:!0}),this.thumbY&&this.thumbY.addEventListener("pointerdown",this.Dt),this.trackY&&this.trackY.addEventListener("pointerdown",this.Nt),this.thumbX&&this.thumbX.addEventListener("pointerdown",this.Ot),this.trackX&&this.trackX.addEventListener("pointerdown",this.Rt),this.$t=new ResizeObserver(()=>this.update()),this.$t.observe(this.Ct),this.update()}jt(t){const n=document.createElement("div");return n.className="ty-scrollbar-track-"+t,n}Bt(t){const n=document.createElement("div");return n.className="ty-scrollbar-thumb-"+t,n}update(){this.Wt(),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.Dt),this.trackY&&this.trackY.removeEventListener("pointerdown",this.Nt),this.thumbX&&this.thumbX.removeEventListener("pointerdown",this.Ot),this.trackX&&this.trackX.removeEventListener("pointerdown",this.Rt),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()}))}Wt(){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))}It(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.Pt),this.thumbY.addEventListener("pointercancel",this.Pt))}Lt(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.Pt),this.thumbX.addEventListener("pointercancel",this.Pt))}Vt(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)}}Ht(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.Pt),n.removeEventListener("pointercancel",this.Pt),this.Gt()}_t(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"})}qt(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 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: var(--ty-local-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: var(--ty-local-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.Xt=null,this.Jt=null,this.Qt=null,this.j=!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.j=!0},this.handleBlurEvent=()=>{this.j=!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: var(--ty-local-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: var(--ty-local-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: var(--ty-local-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.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||!St())return;t.style.scrollbarWidth="none",this.setAttribute("data-custom-scroll",""),this.Qt=new Et(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">${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.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">${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 d=document.createElement("slot");d.setAttribute("name","footer"),l.appendChild(d),o.appendChild(s),o.appendChild(a),o.appendChild(l);const c=(t,n)=>{const e=()=>n.classList.toggle("has-content",t.assignedNodes({flatten:!0}).length>0);t.addEventListener("slotchange",e),e()};if(c(r,s),c(d,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({})}};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 Dt=At;customElements.get("ty-textarea")||customElements.define("ty-textarea",Dt);const It={"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"}},Ot={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 Lt(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=Ot.default,offset:o=8,padding:s=8,containerPadding:r=0}=t,a=Lt(n),l=Lt(e),d=i.map(t=>function(t){const{targetRect:n,floatingRect:e,placement:i,offset:o,padding:s,scrollbarWidth:r,containerPadding:a}=t,l=It[i],{vertical:d,horizontal:c,orientation:h}=l,u=window.innerWidth,p=window.innerHeight;let b,g;window,window,b="vertical"===h?"start"===c?n.left-e.width-o+a:n.right+o-a:"start"===c?n.left:"center"===c?n.centerX-e.width/2:n.right-e.width,g="vertical"===h?"center"===d?n.centerY-e.height/2:"end"===d?n.bottom-e.height-a:n.top:"top"===d?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})),c=d.find(t=>t.fits)||d.reduce((t,n)=>t.overflowAmount>n.overflowAmount?n:t);return 0>c.overflow.right&&(c.x+=c.overflow.right),c}function _t(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 Rt={id:"ty-tooltip",css:"\n/* Tooltip host element - display contents to not affect layout */\n:host {\n display: contents;\n}\n"},qt=new WeakMap,Ft=new WeakMap,Vt=new WeakMap,Pt=new WeakMap,Ht=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 Bt(t){let n=Vt.get(t);return n||(n={showTimeout:null,hideTimeout:null},Vt.set(t,n)),n}function Wt(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:Wt(t,"disabled"),flavor:jt(t.getAttribute("flavor"))}}function Gt(t){return t.parentElement}function Kt(t){let n=Pt.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),Pt.set(t,n);const e=Ht.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,Zt(n,e),n}function Zt(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=Pt.get(t);if(!i||!o)return;const s=Nt({targetEl:i,floatingEl:o,preferences:"top"===n?Ot.tooltip:"bottom"===n?["bottom","top","left","right"]:"left"===n?["left","right","top","bottom"]:"right"===n?["right","left","top","bottom"]:Ot.tooltip,offset:e});o.style.left=s.x+"px",o.style.top=s.y+"px"}function Jt(t){const n=qt.get(t);n&&(n(),qt.delete(t))}function Qt(t){const n=Bt(t);null!==n.showTimeout&&(clearTimeout(n.showTimeout),n.showTimeout=null),null!==n.hideTimeout&&(clearTimeout(n.hideTimeout),n.hideTimeout=null)}function tn(t){const n=Pt.get(t);if(n)try{n.hidePopover(),t.en=!1,Jt(t)}catch(e){}}function nn(t){const n=Bt(t),{delay:e}=Ut(t);Qt(t),n.showTimeout=window.setTimeout(()=>function(t){const{disabled:n}=Ut(t);if(n)return;const e=Kt(t);try{e.showPopover(),t.en=!0,Xt(t),function(t){const n=Gt(t),e=Pt.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),qt.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=Bt(t);Qt(t),n.hideTimeout=window.setTimeout(()=>tn(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,Rt),function(t){const n=Gt(t);if(!n)return;Ht.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),Ft.set(t,()=>{n.removeEventListener("mouseenter",e),n.removeEventListener("mouseleave",i),n.removeEventListener("focusin",o),n.removeEventListener("focusout",s)})}(this),Kt(this)}disconnectedCallback(){!function(t){Qt(t),Jt(t);const n=Ft.get(t);n&&(n(),Ft.delete(t));const e=Pt.get(t),i=Ht.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(),Pt.delete(t)),Ht.delete(t),Vt.delete(t)}(this)}attributeChangedCallback(t,n,e){if("flavor"===t){const t=Pt.get(this);t&&Zt(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 dn=new WeakMap,cn=new WeakMap,hn=new WeakMap,un=new WeakMap,pn=new WeakMap,bn=new WeakMap;function gn(t,n){return t.hasAttribute(n)}function mn(t,n,e){const i=t.getAttribute(n);if(null===i)return e;const o=parseInt(i,10);return isNaN(o)?e:o}function vn(t){return{manual:gn(t,"manual"),disableClose:gn(t,"disable-close"),placement:t.getAttribute("placement")||"bottom",offset:mn(t,"offset",8)}}function fn(t){return t.parentElement}function yn(t){return t.querySelector(".popup-dialog")}function wn(t){let n=bn.get(t);return n||(n="popup-"+(t.id||Math.random().toString(36).substr(2,9)),bn.set(t,n)),n}function xn(t,n=!1){const{disableClose:e}=vn(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=fn(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 kn(t){an(wn(t));const n=t.shadowRoot,e=n?yn(n):null;if(!e)return;e.showModal();const i=fn(t);i?.hasAttribute("aria-haspopup")&&i.setAttribute("aria-expanded","true"),requestAnimationFrame(()=>{!function(t){const{placement:n,offset:e}=vn(t),i=t.shadowRoot,o=fn(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 zn(t){const n=t.shadowRoot,e=n?yn(n):null;e&&(e.classList.contains("open")?xn(t):kn(t))}function $n(t,n){n.preventDefault(),n.stopPropagation(),zn(t)}function Cn(t){const{manual:n}=vn(t),e=fn(t);if(!e||n)return;e.setAttribute("aria-haspopup","dialog"),e.hasAttribute("aria-expanded")||e.setAttribute("aria-expanded","false");const i=dn.get(t);i&&e.removeEventListener("pointerdown",i);const o=cn.get(t);o&&e.removeEventListener("click",o);const s=n=>$n(t,n);dn.set(t,s),e.addEventListener("pointerdown",s);const r=n=>{0===n.detail&&$n(t,n)};cn.set(t,r),e.addEventListener("click",r)}function Sn(t){const n=fn(t),e=dn.get(t);n&&e&&(n.removeEventListener("pointerdown",e),dn.delete(t));const i=cn.get(t);n&&i&&(n.removeEventListener("click",i),cn.delete(t)),n?.removeAttribute("aria-haspopup"),n?.removeAttribute("aria-expanded")}function En(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(),xn(t))}(t,n);hn.set(t,s),e.addEventListener("pointerdown",s);const r=n=>function(t,n){if(n.stopPropagation(),"Escape"===n.key){const{disableClose:e}=vn(t);e?n.preventDefault():xn(t)}}(t,n);un.set(t,r),t.addEventListener("keydown",r),e.addEventListener("close",()=>{ln(wn(t)),e.classList.remove("open"),e.classList.remove("preparing-animation"),t.dispatchEvent(new CustomEvent("close",{bubbles:!0}))})}t.closePopup=()=>xn(t,!0),t.openPopup=()=>kn(t),t.togglePopup=()=>zn(t);const i=n=>function(t,n){n.stopPropagation(),xn(t,!0)}(t,n);pn.set(t,i),t.addEventListener("ty:close-popup",i),Cn(t)}class TyPopup extends HTMLElement{static get observedAttributes(){return["manual","disable-close","placement","offset"]}constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){En(this)}disconnectedCallback(){!function(t){const n=bn.get(t);n&&(ln(n),bn.delete(t)),Sn(t);const e=t.shadowRoot,i=e?yn(e):null;if(i){const n=hn.get(t);n&&(i.removeEventListener("pointerdown",n),hn.delete(t))}const o=un.get(t);o&&(t.removeEventListener("keydown",o),un.delete(t));const s=pn.get(t);s&&(t.removeEventListener("ty:close-popup",s),pn.delete(t))}(this)}attributeChangedCallback(t,n,e){switch(En(this),t){case"placement":case"offset":En(this);break;case"manual":case"disable-close":Sn(this),Cn(this)}}}customElements.get("ty-popup")||customElements.define("ty-popup",TyPopup);const Tn=new WeakMap,Mn=new WeakMap,An=new WeakMap,Dn=new WeakMap,In=new WeakMap,On=new WeakMap;function Ln(t,n){if(!t.hasAttribute(n))return!1;const e=t.getAttribute(n);return null===e||"false"!==e.toLowerCase()}function Nn(t){return t.querySelector(".ty-modal-dialog")}function _n(t,n,e){const i=new CustomEvent(n,{detail:e,bubbles:!0,cancelable:!0});t.dispatchEvent(i)}function Rn(t,n="programmatic",e){const i=t.shadowRoot,o=i?Nn(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 qn(t){const n=t.shadowRoot;if(!n)return;const e=function(t){return{open:Ln(t,"open"),backdrop:!t.hasAttribute("backdrop")||Ln(t,"backdrop"),closeOnOutsideClick:!t.hasAttribute("close-on-outside-click")||Ln(t,"close-on-outside-click"),closeOnEscape:!t.hasAttribute("close-on-escape")||Ln(t,"close-on-escape")}}(t),i=function(t){let n=Nn(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=On.get(t);return n||(n="modal-"+(t.id||Math.random().toString(36).slice(2,11)),On.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=Tn.get(t);if(i&&(n.removeEventListener("click",i),Tn.delete(t)),e){const e=n=>function(t,n){n.stopPropagation();const e=t.shadowRoot,i=e?Nn(e):null;i&&n.target===i&&(n.preventDefault(),Rn(t,"backdrop"))}(t,n);Tn.set(t,e),n.addEventListener("click",e)}}(t,i,e.closeOnOutsideClick),function(t,n,e){const i=Mn.get(t);if(i&&(n.removeEventListener("keydown",i),Mn.delete(t)),e){const e=n=>function(t,n){n.stopPropagation(),"Escape"===n.key&&(n.preventDefault(),Rn(t,"escape"))}(t,n);Mn.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=An.get(t);if(o&&(i.removeEventListener("click",o),An.delete(t)),e){const n=n=>function(t,n){n.preventDefault(),n.stopPropagation(),Rn(t,"close-button")}(t,n);An.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=Dn.get(t),o=In.get(t);if(i&&(e.removeEventListener("mouseenter",i),Dn.delete(t)),o&&(e.removeEventListener("mouseleave",o),In.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);Dn.set(t,n),In.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(),_n(t,"open",{})):i.open&&(ln(o),i.close(),_n(t,"close",{reason:"programmatic"})),i.onclose=n=>{n.target===i&&(ln(o),t.hasAttribute("open")&&(t.removeAttribute("open"),_n(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(){qn(this),this.show=()=>{this.setAttribute("open","true")},this.hide=t=>Rn(this,"programmatic",t)}disconnectedCallback(){!function(t){const n=On.get(t),e=t.shadowRoot,i=e?Nn(e):null;if(n&&(ln(n),On.delete(t)),!i)return;const o=Tn.get(t);o&&(i.removeEventListener("click",o),Tn.delete(t));const s=Mn.get(t);s&&(i.removeEventListener("keydown",s),Mn.delete(t));const r=i.querySelector(".close-button");if(r){const n=An.get(t);n&&(r.removeEventListener("click",n),An.delete(t))}const a=i.querySelector(".modal-content");if(a){const n=Dn.get(t),e=In.get(t);n&&(a.removeEventListener("mouseenter",n),Dn.delete(t)),e&&(a.removeEventListener("mouseleave",e),In.delete(t))}}(this)}attributeChangedCallback(t,n,e){this.isConnected&&qn(this)}}customElements.get("ty-modal")||customElements.define("ty-modal",TyModal),customElements.get("ty-dialog")||customElements.define("ty-dialog",class extends TyModal{});const Fn=(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 display: block;\n width: 100%;\n font-family: var(--ty-font-sans);\n --mobile-border-color: var(--ty-border, #5858587d);\n}\n\n/* compact is a toolbar/filter-bar trigger — it must hug its own content so\n it can sit inline next to other toolbar items, not claim a full row.\n inline-block (not plain inline): a block box still ignores width and\n collapses vertical margin, which is what we're fixing above. */\n:host([compact]) {\n display: inline-block;\n width: auto;\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 :not(.custom-trigger) — that skin has its own unconditional box-shadow:\n none reset below; excluding it here keeps the two rules from competing\n on specificity (:has()/:not() here would otherwise outrank it).\n :not(:has(search:focus)) — the search row auto-focuses on open, which\n already carries its own real :focus ring (below); without this guard the\n stub's "fake" open-ring stacks on top of it, and the field reads as two\n simultaneously-focused controls. Real focus wins; the stub ring is only\n for select skins that have nothing else to show it. */\n.dropdown-wrapper:has(.dropdown-chevron.open):not(:has(.dropdown-search-input:focus)) .select-stub:not(.custom-trigger),\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 /* Floating surface/border, not --input-* — this is a popup panel over\n arbitrary page content, not a form field. --ty-input-border resolves to\n the deliberately-faint resting-state input border (barely visible by\n design, escalates on hover/focus); reused here it made the popup's own\n edge nearly invisible against the page behind it. --ty-floating-border\n is the token tuned for exactly this: floating panels over content. */\n background: var(--ty-surface-floating);\n border: 1px solid var(--ty-floating-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 /* No gap here — label→field spacing comes from .ty-field-label's\n margin-bottom (6px), same as ty-input/ty-date-picker/ty-textarea.\n A flex gap would STACK on that margin (flex margins don't collapse),\n which is exactly the 4px misalignment this used to cause. */\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(--ty-surface-floating));\n border: 1px solid var(--ty-loader-border, var(--ty-floating-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=>Fn(t)).join("")}\n`;function Pn(t=768){return window.matchMedia(`(pointer: coarse) and (max-width: ${t}px)`).matches}let Hn=0;const jn=new WeakMap;function Bn(t){let n=jn.get(t);return void 0===n&&(n=++Hn,jn.set(t,n)),n}const Wn='<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>',Yn='<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>',Un=class extends i{constructor(){super(),this.sn="",this.rn=!1,this.an=!1,this.ln="Select...",this.dn="",this.F=!1,this.cn=!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.Dn=null,this.D=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 width: auto;\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. The header\'s OWN surface/border is\n part of the floating panel\'s chrome, not a form field — --ty-surface-\n floating/--ty-floating-border, matching .dropdown-options below it (same\n reasoning as the base-panel fix: --ty-input-* is deliberately faint for\n resting form fields and read as a missing/mismatched edge here). */\n.dropdown-header {\n background: var(--ty-surface-floating);\n border: 1px solid var(--ty-floating-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(--ty-floating-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(--ty-floating-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(--ty-floating-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(--ty-floating-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.I()}I(){this.D=b(this.shadowRoot,this.D,this.getProperty("flavor"),({base:t})=>(t=>Fn(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.In(),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.I();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.dn=e||"";break;case"disabled":this.F=e;break;case"readonly":this.cn=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?v():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),this.updateValidity(),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=_t({anchorRect:i,popupWidth:a,popupHeight:s}),d=l.below,c=(d?l.topY:l.bottomY)-20,h=a+20+20;this.style.setProperty("--dropdown-x",l.x-20+"px"),this.style.setProperty("--dropdown-y",c+"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"),d?(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",d?"below":"above")}On(){if(!St())return;const t=this.shadowRoot,n=t.querySelector(".dropdown-options"),e=t.querySelector(".dropdown-options-wrapper");n&&e&&(this.In(),n.classList.add("ty-custom-scroll"),this.Mn=new Et(n,{vertical:!0}),this.Mn.trackY&&e.appendChild(this.Mn.trackY))}In(){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"}-${Bn(this)}`;this.vn=i,an(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.On();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.In(),n.classList.remove("open"),n.classList.remove("position-above"),n.classList.remove("position-below"),n.close(),this.vn&&(ln(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"}-${Bn(this)}`;this.vn=i,an(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&&(ln(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.cn||this.openDropdown()}handleStubKeydown(t){this.F||this.cn||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 d=this.getSelectedValues();return this.updateComponentValue([...d,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=Pn()?"mobile":"desktop","mobile"===this.xn.mode?this.renderMobile():this.renderDesktop(),this.updateSearchVisibility(),this.applyLoadingState(),this.updateValidity()}updateValidity(){if(this.disabled)this.v.setValidity({});else if(this.required&&0===this.getSelectedValues().length){const t=this.shadowRoot?.querySelector(".select-stub");this.v.setValidity({valueMissing:!0},"Please select a value",t??void 0)}else this.v.setValidity({})}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-"+Bn(this),i="select-label-"+Bn(this);t.innerHTML=`\n <div class="select-container dropdown-mode-desktop">\n ${this.dn?`\n <label class="ty-field-label" id="${i}">\n ${this.dn}\n ${this.hn?`<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.dn?`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 ${Wn}\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 ${Yn}\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 ${Wn}\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-"+Bn(this),i="select-label-"+Bn(this);t.innerHTML=`\n <div class="select-container dropdown-mode-mobile">\n ${this.dn?`\n <label class="ty-field-label" id="${i}">\n ${this.dn}\n ${this.hn?`<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.dn?`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 ${Wn}\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.dn?`<span class="mobile-header-label">${this.dn}</span>`:""}\n <div class="mobile-header-content">\n <div class="dropdown-search-icon" aria-hidden="true">\n ${Yn}\n </div>\n <input\n class="mobile-search-input ${this.fn}"\n type="text"\n placeholder="${this.dn?`Search ${this.dn}...`:"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.cn||this.openMobileModal()}handleMobileStubKeydown(t){this.F||this.cn||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.Dn=n);if(n?.remove(),null===t)return void(this.Dn=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.Dn=t}else if(this.Dn?.getAttribute("value")===t){const t=this.Dn.cloneNode(!0);this.appendChild(t),this.Dn=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}};Un.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 Gn=Un;function Kn(t,n){return t.replace(/\{([\w-]+)\}/g,(t,e)=>n[e]??t)}customElements.get("ty-select")||customElements.define("ty-select",Gn);class TySelectedOptions extends HTMLElement{constructor(){super(...arguments),this.Ln=null,this.Nn=()=>this.renderChips(),this.An=null,this._n=null,this.Rn=null,this.qn="contents",this.Fn=()=>{this.qn=this.style.display||"contents",this.style.display="none"},this.Vn=()=>{this.style.display=this.qn}}static get observedAttributes(){return["for"]}connectedCallback(){this.style.display||(this.style.display="contents"),this.bind(),this.renderChips(),this.An=new MutationObserver(()=>{this.template()!==this.Rn&&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.Ln&&(this.unbind(),this.Ln=t,this.Ln?.addEventListener("change",this.Nn),this.Ln?.addEventListener("open",this.Fn),this.Ln?.addEventListener("close",this.Vn),this.Ln&&(this._n=new MutationObserver(()=>this.renderChips()),this._n.observe(this.Ln,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["selected"]})))}unbind(){this.Ln?.removeEventListener("change",this.Nn),this.Ln?.removeEventListener("open",this.Fn),this.Ln?.removeEventListener("close",this.Vn),this._n?.disconnect(),this._n=null,this.Ln=null,this.style.display=this.qn}values(){return(this.Ln?.value??"").split(",").map(t=>t.trim()).filter(Boolean)}template(){return this.querySelector(":scope > template")}context(t){const n=this.Ln?.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=Kn(s.textContent,e));else{const t=s;for(const n of Array.from(t.attributes)){if(!n.value.includes("{"))continue;const i=Kn(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.Rn=t,!this.Ln)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.Ln)return;const n=this.Ln;"function"==typeof n.deselectValue?n.deselectValue(t):(n.value=this.values().filter(n=>n!==t).join(","),this.renderChips())}}customElements.get("ty-selected-options")||customElements.define("ty-selected-options",TySelectedOptions),customElements.get("ty-selected-tags")||customElements.define("ty-selected-tags",class extends TySelectedOptions{});const Zn=new WeakMap,Xn=new WeakMap;function Jn(t){return{width:t.getAttribute("width")||"100%",height:t.getAttribute("height")||"400px",active:t.getAttribute("active"),placement:t.getAttribute("placement")||"top"}}function Qn(t){return Array.from(t.querySelectorAll("ty-tab"))}function te(t){return t.getAttribute("id")}function ne(t,n){const e=te(n);return e&&function(t,n){return null!==t.querySelector(`[slot='label-${n}']`)}(t,e)?"slot":"text"}function ee(t){return t.hasAttribute("disabled")}function ie(t,n){const e=t.findIndex(t=>te(t)===n);return 0>e?void 0:e}function oe(t,n){const e=t.getAttribute("active");return e&&void 0!==ie(n,e)?e:n.length>0?te(n[0]):null}function se(t,n){t.setAttribute("active",n)}function re(t,n,e){e.preventDefault(),e.stopPropagation(),se(t,n)}function ae(t){const n=Zn.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.tabKeyClickHandlers.forEach((t,n)=>{const i=e.querySelector(`[data-tab-id='${n}']`);i&&i.removeEventListener("click",t)}),n.tabClickHandlers.clear(),n.tabKeyClickHandlers.clear())}function le(t,n,e){ae(t);const i={tabClickHandlers:new Map,tabKeyClickHandlers:new Map};e.forEach(e=>{const o=te(e);if(!o)return;const s=n.querySelector(`[data-tab-id='${o}']`);if(s){const n=n=>re(t,o,n),e=n=>{0===n.detail&&re(t,o,n)};s.addEventListener("pointerdown",n),s.addEventListener("click",e),i.tabClickHandlers.set(o,n),i.tabKeyClickHandlers.set(o,e)}}),Zn.set(t,i)}function de(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 ce(t,n,e){Qn(t).forEach(i=>{const o=te(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 he(t,n){Qn(t).forEach(t=>{const e=te(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 ue(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 pe(t){const n=t.shadowRoot;if(!n)return;const e=n.querySelector(".tab-buttons");if(!e)return;!function(t){t.querySelector(".tab-overflow-trigger")?.remove()}(n);const i=Array.from(e.querySelectorAll(".tab-button"));if(i.forEach(t=>t.classList.remove("overflow-hidden")),0===i.length)return;const o=e.clientWidth;let s=0,r=i.length;for(let h=0;i.length>h;h++)if(s+=i[h].offsetWidth,s>o){r=h;break}if(r>=i.length)return;s=0,r=i.length;for(let h=0;i.length>h;h++)if(s+=i[h].offsetWidth,s>o-40){r=h;break}r=Math.max(r,1);const a=Qn(t),l=oe(t,a),d=new Set(i.slice(r)),c=l?i.find(t=>t.dataset.tabId===l):void 0;if(c&&d.has(c)){const t=i[r-1];d.delete(c),d.add(t)}i.forEach(t=>t.classList.toggle("overflow-hidden",d.has(t))),function(t,n,e,i){if(0===e.length)return;const o=new Map(i.map(t=>[te(t),t])),s=document.createElement("button");s.className="tab-overflow-trigger",s.type="button",s.setAttribute("aria-label",e.length+" more tabs"),s.textContent="⋯";const r=document.createElement("ty-popup");r.setAttribute("placement","bottom");const a=document.createElement("div");a.className="tab-overflow-menu",a.setAttribute("role","menu"),e.forEach(n=>{const e=n.dataset.tabId,i=e?o.get(e):void 0;if(!e||!i)return;const s=document.createElement("button");s.type="button",s.className="tab-overflow-item",s.setAttribute("role","menuitem"),s.textContent=function(t,n){const e=te(n);if(e&&"slot"===ne(t,n)){const n=t.querySelector(`[slot='label-${e}']`);return n?.textContent?.trim()||e}return n.getAttribute("label")||"Tab"}(t,i),ee(i)?s.disabled=!0:s.addEventListener("click",()=>{se(t,e),r.closePopup?.()}),a.appendChild(s)}),r.appendChild(a),s.appendChild(r),n.appendChild(s)}(t,e,i.filter(t=>d.has(t)),a)}function be(t){const n=t.shadowRoot;if(!n)return;const{width:e,height:i,placement:o}=Jn(t),r=Qn(t),a=oe(t,r),l=a?ie(r,a)??0:0;r.forEach(t=>{const n=te(t);n&&(t.setAttribute("role","tabpanel"),t.setAttribute("aria-labelledby","tab-"+n),t.setAttribute("tabindex","0"))});const d=n.querySelector(".tabs-container"),c=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: var(--ty-local-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.tab-button.overflow-hidden {\n display: none;\n}\n\n/* ===================================== */\n/* Overflow "more" trigger + menu */\n/* ===================================== */\n\n.tab-overflow-trigger {\n flex-shrink: 0;\n width: 40px;\n min-width: 40px;\n padding: 6px;\n border: none;\n background: transparent;\n cursor: pointer;\n color: var(--ty-text-soft);\n font-size: 18px;\n line-height: 1;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n position: relative;\n z-index: 10;\n}\n\n.tab-overflow-trigger:hover {\n color: var(--ty-text-strong);\n}\n\n.tab-overflow-trigger:focus-visible {\n outline: 2px solid var(--ty-color-primary);\n outline-offset: -2px;\n}\n\n.tab-overflow-menu {\n display: flex;\n flex-direction: column;\n min-width: 160px;\n max-height: 300px;\n overflow-y: auto;\n padding: var(--ty-spacing-2, 4px);\n background: var(--ty-surface-floating);\n border-radius: var(--ty-radius-md);\n box-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\n.tab-overflow-item {\n padding: var(--ty-spacing-2, 6px) var(--ty-spacing-3, 12px);\n border: none;\n background: transparent;\n text-align: left;\n cursor: pointer;\n border-radius: var(--ty-radius-md);\n color: var(--ty-text);\n font: inherit;\n font-size: var(--ty-font-sm);\n white-space: nowrap;\n}\n\n.tab-overflow-item:hover {\n background: var(--ty-bg-neutral-soft);\n color: var(--ty-text-strong);\n}\n\n.tab-overflow-item[disabled] {\n opacity: 0.5;\n cursor: not-allowed;\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+""),d&&c&&h){d.setAttribute("data-placement",o),c.querySelector(".tab-overflow-trigger")?.remove(),c.querySelectorAll(".tab-button").forEach(t=>t.remove());const e=function(t,n,e){return n.map(n=>{const i=te(n);if(!i)return"";const o=ne(t,n),s="text"===o?n.getAttribute("label")||"Tab":"",r=ee(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=>{c.appendChild(t)}),le(t,n,r),ce(t,n,a||""),requestAnimationFrame(()=>{const e=n.querySelector(".tab-buttons");e&&t.style.setProperty("--buttons-height",e.offsetHeight+"px"),de(t,l),a&&ue(t,a),pe(t)}),a&&he(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=te(n);if(!i)return"";const o=ne(t,n),s="text"===o?n.getAttribute("label")||"Tab":"",r=ee(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"),de(t,l),a&&ue(t,a),pe(t)}),le(t,n,r),ce(t,n,a||""),function(t){const n=Xn.get(t);n&&n.disconnect();const e=new ResizeObserver(n=>{const e=n[0],{width:i}=Jn(t),o=Qn(t),s=oe(t,o),r=s?ie(o,s):0;i.includes("%")&&t.style.setProperty("--tabs-width",e.contentRect.width+"px"),void 0!==r&&de(t,r),s&&ue(t,s),pe(t)});e.observe(t),Xn.set(t,e)}(t),a&&he(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(){be(this)}disconnectedCallback(){ae(this),function(t){const n=Xn.get(t);n&&(n.disconnect(),Xn.delete(t))}(this)}attributeChangedCallback(t,n,e){"active"===t?(e&&function(t,n,e){const i=Qn(t),o=t.shadowRoot;if(!o)return;const s=e?ie(i,e):void 0,r=ie(i,n);if(e===n||void 0===r)return;t.style.setProperty("--active-index",r+""),de(t,r),ce(t,o,n),he(t,n),ue(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),be(this)):be(this)}}customElements.get("ty-tabs")||customElements.define("ty-tabs",TyTabs);const ge=`\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.Qt=null,this.attachShadow({mode:"open"})}static get observedAttributes(){return["id","label","disabled"]}connectedCallback(){this.Pn()}disconnectedCallback(){this.tn()}attributeChangedCallback(t,n,e){this.Pn()}Pn(){const t=this.shadowRoot;if(!t)return;const n=this.getAttribute("id");t.querySelector(".tab-wrapper")||(s(t,{css:ge,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&&St()&&(t.classList.add("ty-custom-scroll"),this.Qt=new Et(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 me=new WeakMap,ve=new WeakMap;function fe(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 ye(t){return Array.from(t.querySelectorAll("ty-step"))}function we(t){return t.getAttribute("id")}function xe(t){const n=t.getAttribute("completed")||"";return n.trim()?new Set(n.split(",").map(t=>t.trim()).filter(Boolean)):new Set}function ke(t,n){const e=t.findIndex(t=>we(t)===n);return 0>e?void 0:e}function ze(t,n){const e=t.getAttribute("active");return e&&void 0!==ke(n,e)?e:n.length>0?we(n[0]):null}function $e(t,n){return t.length>1&&n?t.findIndex(t=>we(t)===n)/(t.length-1)*100:0}function Ce(t){const n=me.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 Se(t,n,e){Ce(t);const i={stepClickHandlers:new Map};e.forEach(e=>{const o=we(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=ye(t),o=i.findIndex(t=>we(t)===n);if(0>o)return;const s=ze(t,i),r=s?ke(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)}}),me.set(t,i)}function Ee(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 Te(t){const n=t.shadowRoot;if(!n)return;const e=n.querySelector(".progress-overlay");if(!e)return;const i=ye(t),o=ze(t,i);xe(t);const s=$e(i,o);e.style.width=s+"%"}function Me(t,n,e){const i=ye(t),o=xe(t);e&&i.findIndex(t=>we(t)===e),i.forEach(i=>{const s=we(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=De(i,s,e,o);a.setAttribute("data-state",t)}const d=t.querySelector(`[slot='indicator-${s}']`);d&&d.setAttribute("data-active",l+"")})}function Ae(t,n){ye(t).forEach(t=>{const e=we(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 De(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 Ie(t,n,e,i){e&&n.findIndex(t=>we(t)===e);const o=n.map((n,o)=>{const s=we(n);if(!s)return"";const r=n.getAttribute("label")||"Step "+(o+1),a=n.getAttribute("description")||"",l=function(t){return t.hasAttribute("disabled")}(n),d=s===e,c=function(t,n){return null!==t.querySelector(`[slot='indicator-${n}']`)}(t,s),h=De(n,s,e,i);let u="";return u=c?`<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="${d}"\n tabindex="${d?"0":"-1"}"\n data-active="${d}"\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=$e(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 Oe(t){const n=t.shadowRoot;if(!n)return;const{width:e,height:i}=fe(t),o=ye(t),r=ze(t,o),a=r?ke(o,r)??0:0,l=xe(t);o.forEach(t=>{const n=we(t);n&&(t.setAttribute("role","tabpanel"),t.setAttribute("aria-labelledby","step-"+n),t.setAttribute("tabindex","0"))});const d=n.querySelector(".wizard-container"),c=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: var(--ty-local-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 /* Derived from the accent this circle actually paints, not from\n --ty-solid-success-fg: the two diverge in dark mode (--ty-solid-l\n dims solid fills by 0.25 L), which stranded white text at 3.5:1. */\n color: oklch(\n from var(--ty-wizard-completed-accent)\n clamp(0, (var(--ty-solid-fg-threshold, 0.6) - l) * 1000, 1) 0 0\n );\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: oklch(\n from var(--ty-wizard-active-accent)\n clamp(0, (var(--ty-solid-fg-threshold, 0.6) - l) * 1000, 1) 0 0\n );\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: oklch(\n from var(--ty-wizard-error-accent)\n clamp(0, (var(--ty-solid-fg-threshold, 0.6) - l) * 1000, 1) 0 0\n );\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: var(--ty-local-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: var(--ty-local-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+""),d&&c&&h){c.remove();const e=Ie(t,o,r,l),i=document.createElement("div");i.innerHTML=e,d.insertBefore(i.firstElementChild,h),Se(t,n,o),Me(t,n,r||""),requestAnimationFrame(()=>{const e=n.querySelector(".step-indicators-wrapper");e&&t.style.setProperty("--ty-wizard-indicators-height",e.offsetHeight+"px"),Ee(t,a),Te(t)}),r&&Ae(t,r)}else n.innerHTML=`\n <div class="wizard-container">\n ${Ie(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"),Ee(t,a),Te(t)}),Se(t,n,o),Me(t,n,r||""),function(t){const n=ve.get(t);n&&n.disconnect();const{width:e}=fe(t);if(e.includes("%")){const n=new ResizeObserver(n=>{const e=n[0].contentRect.width,i=ye(t),o=ze(t,i),s=o?ke(i,o):0;t.style.setProperty("--ty-wizard-width",e+"px"),void 0!==s&&Ee(t,s)});n.observe(t),ve.set(t,n)}}(t),r&&Ae(t,r)}class TyWizard extends HTMLElement{static get observedAttributes(){return["width","height","active","completed","orientation"]}constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){Oe(this)}disconnectedCallback(){Ce(this),function(t){const n=ve.get(t);n&&(n.disconnect(),ve.delete(t))}(this)}attributeChangedCallback(t,n,e){"active"===t?(e&&function(t,n){const e=ye(t),i=t.shadowRoot;if(!i)return;const o=ze(t,e),s=o?ke(e,o):void 0,r=ke(e,n);if(o===n||void 0===r)return;t.style.setProperty("--ty-wizard-active-index",r+""),Ee(t,r),Me(t,i,n),Te(t),Ae(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),Oe(this)):Oe(this)}}customElements.get("ty-wizard")||customElements.define("ty-wizard",TyWizard);const Le=`\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.Qt=null,this.attachShadow({mode:"open"})}static get observedAttributes(){return["id","label","description","disabled","status"]}connectedCallback(){this.Pn()}disconnectedCallback(){this.tn()}attributeChangedCallback(t,n,e){this.Pn()}Pn(){const t=this.shadowRoot;if(!t)return;const n=this.getAttribute("id");t.querySelector(".step-wrapper")||(s(t,{css:Le,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&&St()&&(t.classList.add("ty-custom-scroll"),this.Qt=new Et(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 Ne=(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`},_e=`\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: var(--ty-local-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=>Ne(t)).join("")}\n`;function Re(t){if(!Number.isInteger(t)||1>t||t>12)throw new RangeError(`Invalid month: ${t}. Must be an integer between 1 and 12.`)}function qe(t,n,e,i){const o=t.getFullYear(),s=t.getMonth()+1,r=t.getDate(),a=t.getDay(),l=o!==n||s!==e;let d=!1,c=!1;l&&(n>o||o===n&&e>s?d=!0:c=!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:d,nextMonth:c,today:h,isSelected:b,selectedYear:i?.year,selectedMonth:i?.month,selectedDay:i?.day}}function Fe(t,n){const e=new Date(t);return e.setDate(e.getDate()+n),e}function Ve(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 Pe(t){return t instanceof HTMLElement}function He(t){if(!t)return null;const n=Ve(t);return n?Date.UTC(n.year,n.month-1,n.day):null}function je(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.fn="md",this.D=null,this.jn=null,this.Bn=[];const t=new Date;this.Wn=t.getFullYear(),this.Yn=t.getMonth()+1,this.attachShadow({mode:"open"})}static get observedAttributes(){return["locale","size","min","max","flavor"]}connectedCallback(){this.Yn||(this.Yn=(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.fn=t);const n=this.dayContentFn;n&&!this.Un&&(this.Un=n,delete this.dayContentFn);const e=this.customCSS;e&&!this.Gn&&(this.Gn=e,delete this.customCSS),this.J=J(this,()=>{this.render()}),this.I(),this.render()}disconnectedCallback(){this.J&&(this.J(),this.J=void 0)}attributeChangedCallback(t,n,e){"locale"===t?(this.Hn=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?"Kn":"Zn"]=e??void 0,this.render()):"flavor"===t&&this.I()}I(){this.D=b(this.shadowRoot,this.D,this.getAttribute("flavor"),({base:t})=>(t=>Ne(t,"neutral"))(t))}get displayYear(){return this.Wn}set displayYear(t){this.Wn!==t&&(this.Wn=t,this.jn=null,this.render())}get displayMonth(){return this.Yn}set displayMonth(t){this.Yn!==t&&(this.Yn=t,this.jn=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.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.Xn}set width(t){this.Xn!==t&&(this.Xn=t,this.applyWidthProperties())}get minWidth(){return this.Jn}set minWidth(t){this.Jn!==t&&(this.Jn=t,this.applyWidthProperties())}get maxWidth(){return this.Qn}set maxWidth(t){this.Qn!==t&&(this.Qn=t,this.applyWidthProperties())}get dayContentFn(){return this.Un}set dayContentFn(t){this.Un!==t&&(this.Un=t,this.render())}get customCSS(){return this.Gn}set customCSS(t){this.Gn!==t&&(this.Gn=t,this.applyCustomCSS())}get min(){return this.Kn}set min(t){this.Kn!==t&&(this.Kn=t,this.render())}get max(){return this.Zn}set max(t){this.Zn!==t&&(this.Zn=t,this.render())}get value(){return this.R}set value(t){const n=t??void 0;this.R!==n&&(this.R=n,this.render())}applyWidthProperties(){const t=je(this.Xn),n=je(this.Jn),e=je(this.Qn);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.Gn||!this.shadowRoot)return;const t=this.shadowRoot.adoptedStyleSheets;t.includes(this.Gn)||(this.shadowRoot.adoptedStyleSheets=[...t,this.Gn])}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.Un?this.Un(t):function(t){return""+t.dayInMonth}(t);if(this.Un&&o&&!Pe(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:Pe(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:_e,id:"ty-calendar-month"}),this.applyCustomCSS(),this.applyWidthProperties(),this.R){const t=new Date(this.R);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),Re(n),function(t,n,e,i,o){const s=[];for(let r=0;42>r;r++){const n=Fe(t,r);s.push(qe(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.Yn,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=Fe(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.fn,o.setAttribute("role","grid"),o.setAttribute("aria-label",new Intl.DateTimeFormat(this.Hn,{month:"long",year:"numeric"}).format(new Date(this.Wn,this.Yn-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=He(this.Kn),d=He(this.Zn),c=t=>{const n=e[t].value;return null!==l&&l>n||null!==d&&n>d};let h=e.findIndex(t=>t.isSelected);-1===h&&(h=e.findIndex(t=>t.today)),-1===h&&(h=0),(null===this.jn||0>this.jn||this.jn>41||c(this.jn))&&(this.jn=h),this.Bn=[];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!==d&&t.value>d,u===this.jn);e.className=e.className+" calendar-cell calendar-day-cell",n.appendChild(e),this.Bn[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.jn??h,o=i+e;if(0>o||o>41||c(o))return;n.preventDefault(),this.Bn[i]?.setAttribute("tabindex","-1"),this.jn=o;const s=this.Bn[o];s&&(s.setAttribute("tabindex","0"),s.focus())}),t.appendChild(o)}}customElements.get("ty-calendar-month")||customElements.define("ty-calendar-month",TyCalendarMonth);const Be='\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: var(--ty-local-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',We=class t extends i{constructor(){super();const t=new Date;this.xn={displayMonth:t.getMonth()+1,displayYear:t.getFullYear()},s(this.shadowRoot,{css:Be,id:"ty-calendar-navigation"})}onConnect(){this.xn.displayMonth=this.displayMonth,this.xn.displayYear=this.displayYear,this.J=J(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 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=Ve(this.min),e=Ve(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:Be,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"){Re(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)}};We.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 Ye=We;function Ue(t){return t&&/^\d{4}$/.test(t)?parseInt(t,10):null}function Ge(t){if(!t||!/^\d{1,2}$/.test(t))return null;const n=parseInt(t,10);return 1>n||n>12?null:n}function Ke(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 Ze(t,n,e){return`${t}-${(""+n).padStart(2,"0")}-${(""+e).padStart(2,"0")}`}customElements.get("ty-calendar-navigation")||customElements.define("ty-calendar-navigation",Ye);const Xe=class extends HTMLElement{constructor(){super(),this.te=!0,this.ne=!1,this.fn="md",this.ee="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.Un&&(this.Un=t,delete this.dayContentFn);const n=this.customCSS;n&&!this.Gn&&(this.Gn=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.ne||(this.setAttribute("year",""+n),this.setAttribute("month",""+e),this.setAttribute("day",""+i))}delete this.value}this.render(),this.updateFormValue(),this.J=J(this,()=>{this.render()})}disconnectedCallback(){this.J&&(this.J(),this.J=void 0),this.ie=void 0,this.oe=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.te="false"!==e,this.render();break;case"stateless":this.ne=null!==e&&"false"!==e;break;case"locale":this.syncChildComponents();break;case"size":"sm"!==e&&"md"!==e&&"lg"!==e||(this.fn=e,this.Xn=void 0,this.removeAttribute("width"),this.syncChildComponents());break;case"width":this.Xn=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?"Kn":"Zn"]=e||void 0,this.syncChildComponents(),this.updateValidity();break;case"flavor":this.ee=e||"primary",this.syncChildComponents()}}get min(){return this.Kn}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.ee}set flavor(t){t?this.setAttribute("flavor",t):this.removeAttribute("flavor")}get year(){return this.xn.selectedYear}set year(t){void 0!==t?this.ne?(this.xn.displayYear=t,this.setAttribute("year",""+t)):(this.xn.selectedYear=t,this.xn.displayYear=t,this.setAttribute("year",""+t)):(this.ne||delete this.xn.selectedYear,this.removeAttribute("year")),this.syncChildComponents(),this.ne||this.updateFormValue()}get month(){return this.xn.selectedMonth}set month(t){void 0!==t?this.ne?(this.xn.displayMonth=t,this.setAttribute("month",""+t)):(this.xn.selectedMonth=t,this.xn.displayMonth=t,this.setAttribute("month",""+t)):(this.ne||delete this.xn.selectedMonth,this.removeAttribute("month")),this.syncChildComponents(),this.ne||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 X(this,this.getAttribute("locale"))}set locale(t){this.setAttribute("locale",t)}get showNavigation(){return this.te}set showNavigation(t){this.te=t,this.setAttribute("show-navigation",""+t)}get stateless(){return this.ne}set stateless(t){this.ne=t,t?this.setAttribute("stateless",""):this.removeAttribute("stateless")}get size(){return this.fn}set size(t){this.fn!==t&&(this.fn=t,this.Xn=void 0,this.removeAttribute("width"),this.setAttribute("size",t),this.syncChildComponents())}get width(){return this.Xn}set width(t){this.Xn!==t&&(this.Xn=t,t?(this.fn="md",this.removeAttribute("size"),this.setAttribute("width",t)):this.removeAttribute("width"),this.syncChildComponents())}get dayContentFn(){return this.Un}set dayContentFn(t){this.Un=t,this.syncChildComponents()}get customCSS(){return this.Gn}set customCSS(t){this.Gn=t,this.syncChildComponents()}get value(){const{selectedYear:t,selectedMonth:n,selectedDay:e}=this.xn;return t&&n&&e?Ze(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.ne||(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.ne||(this.removeAttribute("year"),this.removeAttribute("month"),this.removeAttribute("day"));this.syncChildComponents(),this.ne||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.Kn=this.getAttribute("min")||void 0,this.Zn=this.getAttribute("max")||void 0;const a=Ue(t);a&&(this.xn.displayYear=a);const l=Ge(n);if(l&&(this.xn.displayMonth=l),a&&l){const t=Ke(e,a,l);t&&(this.xn.selectedYear=a,this.xn.selectedMonth=l,this.xn.selectedDay=t)}i&&(this.te="false"!==i),null!==o&&(this.ne="false"!==o),!s||"sm"!==s&&"md"!==s&&"lg"!==s||(this.fn=s),r&&(this.Xn=r)}syncStateFromAttributes(){const t=this.getAttribute("year"),n=this.getAttribute("month"),e=this.getAttribute("day"),i=Ue(t),o=Ge(n);if(i&&(this.xn.displayYear=i),o&&(this.xn.displayMonth=o),i&&o){const t=Ke(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.ie&&(this.ie.displayMonth=this.xn.displayMonth,this.ie.displayYear=this.xn.displayYear,this.ie.locale=this.locale,this.ie.size=this.fn,this.ie.min=this.Kn??"",this.ie.max=this.Zn??"",this.ie.width=this.Xn),this.oe){this.oe.displayMonth=this.xn.displayMonth,this.oe.displayYear=this.xn.displayYear,this.oe.locale=this.locale,this.oe.size=this.fn,this.oe.min=this.Kn,this.oe.max=this.Zn,this.oe.flavor=this.ee,this.oe.width=this.Xn,this.Un&&(this.oe.dayContentFn=this.Un),this.Gn&&(this.oe.customCSS=this.Gn);const{selectedYear:t,selectedMonth:n,selectedDay:e}=this.xn;this.oe.value=t&&n&&e?new Date(t,n-1,e).getTime():null}}updateFormValue(){if(this.ne)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=Ze(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.Kn?Ve(this.Kn):null,s=this.Zn?Ve(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.Kn} 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.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.ne?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.oe&&"function"==typeof this.oe.refresh&&this.oe.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.Kn??"",t.max=this.Zn??"",this.Xn&&(t.width=this.Xn),t.addEventListener("change",t=>this.handleNavigationChange(t)),this.ie=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.Kn,t.max=this.Zn,t.flavor=this.ee,this.Xn&&(t.width=this.Xn);const{selectedYear:n,selectedMonth:e,selectedDay:i}=this.xn;return n&&e&&i&&(t.value=new Date(n,e-1,i).getTime()),this.Un&&(t.dayContentFn=this.Un),this.Gn&&(t.customCSS=this.Gn),t.addEventListener("day-click",t=>this.handleDayClick(t)),this.oe=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.te){const t=this.createNavigation();n.appendChild(t)}const e=this.createMonthDisplay();n.appendChild(e),t.appendChild(n)}};Xe.formAssociated=!0;let Je=Xe;customElements.get("ty-calendar")||customElements.define("ty-calendar",Je);const Qe=(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`},ti=`\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=>Qe(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: var(--ty-local-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`,ni="<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>",ei="<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>",ii=new WeakMap;let oi=0;function si(t){let n=ii.get(t);return void 0===n&&(n=++oi,ii.set(t,n)),n}function ri(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 ai(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 li(t){if(!t.year||!t.month||!t.day)return null;const n=ai(t);return n?n.toISOString():null}function di(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 ci(t,n){return`${(""+t).padStart(2,"0")}:${(""+n).padStart(2,"0")}`}function hi(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 ui{constructor(t,n,e=0,i=0){this.element=t,this.datePickerElement=n;const o=ci(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=hi(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=hi(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:ci(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=ci(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 pi=class extends i{constructor(){super(),this.xn={withTime:!1,open:!1},this.se=0,this.D=null,s(this.shadowRoot,{css:ti,id:"ty-date-picker"})}onConnect(){this.initializeState(),this.render(),this.J=J(this,()=>{this.render()}),this.I()}I(){this.D=b(this.shadowRoot,this.D,"default"===this.flavor?"neutral":this.flavor,({base:t})=>(t=>Qe(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.I();break;case"size":case"label":case"placeholder":case"required":case"disabled":case"clearable":case"format":case"locale":break;case"value":{const t=ri(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 li(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=ai(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.xn.withTime):null}initializeState(){const t=this.getProperty("value"),n=this.getProperty("with-time"),e=ri(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?li(t):null,i=t?di(t,this.xn.withTime):null,o=t?ai(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-"+si(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=ei,t.addEventListener("click",t=>this.handleClearClick(t)),r.appendChild(t)}const a=document.createElement("span");return a.className="stub-arrow",a.innerHTML=ni,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.re=new ui(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=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.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=di(this.getComponents(),this.xn.withTime);r&&(i.value=r);const a=this.getProperty("placeholder")||"Select date...",l=this.getFormattedValue(),d=document.createElement("span");d.className="stub-text"+(l?"":" placeholder"),d.textContent=l||a,i.addEventListener("change",()=>{if(!i.value)return void this.clearValue();const t=ri(i.value,this.xn.withTime);t&&(this.updateState(t,!0),this.emitChangeEvent(t,"selection"))});const c=document.createElement("slot");c.name="start",n.appendChild(c),n.appendChild(i),n.appendChild(d);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=ei,t.addEventListener("click",t=>this.handleClearClick(t)),h.appendChild(t)}const u=document.createElement("span");return u.className="stub-arrow",u.innerHTML=ni,h.appendChild(u),n.appendChild(h),t.appendChild(n),t}calculateCalendarPosition(){if(!this.shadowRoot)return;if(Pn())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=_t({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-"+si(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:ti,id:"ty-date-picker"}),Pn()){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"),Pn()){const t=this.shadowRoot.querySelector(".native-date-input");if(t){const n=di(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.re&&void 0!==this.xn.hour&&void 0!==this.xn.minute&&this.re.setTime(this.xn.hour,this.xn.minute)}setupEventListeners(){this.ae&&document.removeEventListener("click",this.ae),this.le&&document.removeEventListener("keydown",this.le),this.ae=t=>this.handleOutsideClick(t),this.le=t=>this.handleEscapeKey(t),document.addEventListener("click",this.ae),document.addEventListener("keydown",this.le);const t=this.shadowRoot?.querySelector(".calendar-dialog");t&&(this.de=t=>this.handleDialogClick(t),t.addEventListener("click",this.de))}handleStubClick(t){t.preventDefault();const n=this.shadowRoot?.querySelector(".calendar-dialog");!this.xn.open||n&&n.open||(this.updateState({open:!1},!0),ln("date-picker-"+(this.id||""+this))),!this.getProperty("disabled")&&Date.now()-this.se>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||Pn()||(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.xn.open)return;this.se=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.ae&&document.removeEventListener("click",this.ae),this.le&&document.removeEventListener("keydown",this.le),this.de&&this.shadowRoot){const t=this.shadowRoot.querySelector(".calendar-dialog");t&&t.removeEventListener("click",this.de)}this.xn.open&&ln("date-picker-"+(this.id||""+this)),this.ae=void 0,this.le=void 0,this.de=void 0,this.re=void 0}};pi.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}},pi.formAssociated=!0;let bi=pi;customElements.get("ty-date-picker")||customElements.define("ty-date-picker",bi);const gi=new Map,mi=new Map;function vi(t){return gi.get(t)}function fi(t,n){mi.has(t)||mi.set(t,new Set),mi.get(t).add(n);const e=gi.get(t);return e&&n(e),()=>{mi.get(t)?.delete(n),0===mi.get(t)?.size&&mi.delete(t)}}function yi(){return Object.fromEntries(gi)}class TyResizeObserver extends HTMLElement{constructor(){super(),this.$t=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.$t=new ResizeObserver(t=>{this.debounce>0?(this.ce&&clearTimeout(this.ce),this.ce=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){gi.set(t,{width:n,height:e});const i=mi.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.ce&&(clearTimeout(this.ce),this.ce=null),this.id&&(gi.delete(t=this.id),mi.delete(t))}}customElements.define("ty-resize-observer",TyResizeObserver);const wi=`\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.he=null,this.ue=null,this.pe=null,this.be=null,this.ge=null,this.Qt=null,this.$t=null,this.me=null,this.kt=null,this.ve=!1,this.fe=!1,this.Mt=()=>{null===this.kt&&(this.kt=requestAnimationFrame(()=>{this.kt=null,this.ye()}))},this.we=()=>{this.Qt?.update(),this.ye()};const t=this.attachShadow({mode:"open"});s(t,{css:wi,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.he=t.querySelector(".scroll-wrapper"),this.ue=t.querySelector(".shadow-top"),this.pe=t.querySelector(".shadow-bottom"),this.be=t.querySelector(".shadow-left"),this.ge=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.xe()}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.he?.addEventListener("scroll",this.Mt,{passive:!0}),this.$t=new ResizeObserver(()=>{this.Qt?.update(),this.ye()}),this.he){this.$t.observe(this.he);const t=this.he.querySelector("slot");t&&t.addEventListener("slotchange",this.we)}this.xe(),this.ye(),this.nn(),this.ke()}disconnectedCallback(){this.he?.removeEventListener("scroll",this.Mt),this.tn(),this.ze(),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.xe(),this.ye(),this.Qt?.update()),"custom-scrollbar"!==t&&"overflow-x"!==t||(this.tn(),this.nn(),this.ye()),"scroll-anchoring"===t&&(this.ze(),this.ke()))}ke(){!this.me&&this.scrollAnchoring&&(this.me=new MutationObserver(t=>{const n=this.he;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.me.observe(this,{childList:!0}))}ze(){this.me?.disconnect(),this.me=null}nn(){if(this.Qt)return;if(!this.he||!this.customScrollbar)return;this.Qt=new Et(this.he,{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)}xe(){if(this.he){const t=this.maxHeight;t?(this.he.style.setProperty("--scroll-max-height",t),this.he.style.maxHeight=t):(this.he.style.removeProperty("--scroll-max-height"),this.he.style.maxHeight="")}}ye(){if(!this.he)return;const{scrollTop:t,scrollLeft:n,scrollHeight:e,scrollWidth:i,clientHeight:o,clientWidth:s}=this.he;this.ue&&this.ue.classList.toggle("visible",t>2),this.pe&&this.pe.classList.toggle("visible",e-2>t+o),this.overflowX&&(this.be&&this.be.classList.toggle("visible",n>2),this.ge&&this.ge.classList.toggle("visible",i-2>n+s));const r=e-o;if(r>0){const n=this.nearEdgeThreshold,i=r-t;this.fe=this.$e("nearend",i,n,this.fe,{distance:i,scrollTop:t,scrollHeight:e,clientHeight:o}),this.ve=this.$e("nearstart",t,n,this.ve,{distance:t,scrollTop:t,scrollHeight:e,clientHeight:o})}else this.ve=!1,this.fe=!1}$e(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.Qt?.update()}scrollToTop(t=!0){this.he?.scrollTo({top:0,behavior:t?"smooth":"auto"})}scrollToBottom(t=!0){this.he&&this.he.scrollTo({top:this.he.scrollHeight,behavior:t?"smooth":"auto"})}scrollToLeft(t=!0){this.he?.scrollTo({left:0,behavior:t?"smooth":"auto"})}scrollToRight(t=!0){this.he&&this.he.scrollTo({left:this.he.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.he}}customElements.define("ty-scroll-container",TyScrollContainer),"undefined"!=typeof window&&(window.tyVersion=x,window.tyIcons={register:t=>{D(t)},get:t=>I(t),has:t=>O(t),list:()=>q(),cacheInfo:()=>F(),clearCache:()=>L()},window.tyResizeObserver={getSize:t=>vi(t),onResize:(t,n)=>fi(t,n),get sizes(){return yi()}},window.tyLoader={set:t=>m(t),get:()=>v(),reset:()=>f()}),t.IconRegistry=V,t.TyButton=w,t.TyCalendar=Je,t.TyCalendarMonth=TyCalendarMonth,t.TyCalendarNavigation=Ye,t.TyCheckbox=rt,t.TyCopy=kt,t.TyDatePicker=bi,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=Gn,t.TySelectedOptions=TySelectedOptions,t.TySelectedTags=TySelectedOptions,t.TyStep=TyStep,t.TySwitch=ct,t.TyTab=TyTab,t.TyTabs=TyTabs,t.TyTag=U,t.TyTextarea=Dt,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=yi,t.getLoaderSvg=v,t.getLockState=function(){return{locked:on.locked,scrollY:on.scrollY,activeLocks:Array.from(on.activeLocks)}},t.getSize=vi,t.isLocked=function(){return on.locked},t.isLockedBy=function(t){return on.activeLocks.has(t)},t.lockScroll=an,t.onResize=fi,t.resetLoaderSvg=f,t.setLoaderSvg=m,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","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)=>`oklch(from ${t} calc(l + var(--ty-${n})) c h)`,c=(t,n)=>`oklch(from ${t} calc(l + sign(0.5 - l) * abs(var(--ty-${n}))) c h)`,d=(t,n)=>{const e=e=>a("--ty-solid",t,e,n),i="neutral"===t?" --_border-l: var(--ty-button-border-l-neutral, var(--ty-button-border-l, -0.15));":" --_border-l: var(--ty-button-border-l, -0.15);",o="neutral"===t?c:l;return`\nbutton.solid.${t} { --_ring: ${a("--ty-color",t,"",n)}; --_solid-bg: var(--ty-button-bg, var(--_muted-solid-bg, ${e("")})); --_solid-rest: var(--ty-button-bg, var(--_muted-solid-bg, ${e("")}));${i} color: var(--ty-button-color, var(--_muted-solid-fg, ${e("-fg")})); }\nbutton.solid.${t}.tone-plus { --_solid-bg: var(--ty-button-bg, var(--_muted-solid-bg, ${e("-strong")})); --_solid-rest: var(--ty-button-bg, var(--_muted-solid-bg, ${e("-strong")})); color: var(--ty-button-color, var(--_muted-solid-fg, ${e("-strong-fg")})); }\nbutton.solid.${t}.tone-minus { --_solid-bg: var(--ty-button-bg, var(--_muted-solid-bg, ${e("-soft")})); --_solid-rest: var(--ty-button-bg, var(--_muted-solid-bg, ${e("-soft")})); color: var(--ty-button-color, var(--_muted-solid-fg, ${e("-soft-fg")})); }\nbutton.solid.${t}:hover:not(:disabled) { --_solid-bg: var(--ty-button-bg-hover, ${e("-hover")}); }\nbutton.solid.${t}:active:not(:disabled) { --_solid-bg: ${e("-active")}; }\nbutton.solid.${t}.tone-plus:hover:not(:disabled) { --_solid-bg: var(--ty-button-bg-hover, ${o(e("-strong"),"solid-hover-l")}); }\nbutton.solid.${t}.tone-plus:active:not(:disabled) { --_solid-bg: ${o(e("-strong"),"solid-active-l")}; }\nbutton.solid.${t}.tone-minus:hover:not(:disabled) { --_solid-bg: var(--ty-button-bg-hover, ${l(e("-soft"),"solid-hover-l")}); }\nbutton.solid.${t}.tone-minus:active:not(:disabled) { --_solid-bg: ${l(e("-soft"),"solid-active-l")}; }\n`},h=(t,n)=>{const e=e=>"neutral"===t&&"-strong"===e?`var(--ty-solid-neutral${e})`:(e=>a("--ty-color",t,e,n))(e);return`\nbutton.outlined.${t} {\n color: var(--ty-button-color, var(--_muted-outlined-line, ${e("")}));\n border-color: var(--ty-button-border, var(--_muted-outlined-line, ${e("")}));\n}\nbutton.outlined.${t}.tone-plus {\n color: var(--ty-button-color, var(--_muted-outlined-line, ${e("-strong")}));\n border-color: var(--ty-button-border, var(--_muted-outlined-line, ${e("-strong")}));\n}\nbutton.outlined.${t}.tone-minus {\n color: var(--ty-button-color, var(--_muted-outlined-line, ${e("-soft")}));\n border-color: var(--ty-button-border, var(--_muted-outlined-line, ${e("-soft")}));\n}\nbutton.outlined.${t}:hover:not(:disabled) {\n background: var(--ty-button-bg-hover, ${a("--ty-bg",t,"-soft",n)});\n}\n/* Rest is whatever tone you picked; hover/active/focus always escalates to\n the SAME peak — most-emphasized ("+") color, regardless of starting\n tone. tone-plus is already there at rest, so this is a no-op for it.\n :hover only, :not(.muted) — muted's hover-reveal is a DIFFERENT contract\n (reveal the plain button's RESTING color, tested directly against it);\n this rule would outrank that fallback and show strong instead.\n :active/:focus-visible apply to muted too (no exclusion) — muted's own\n reveal-on-press mechanism has much lower specificity than this rule, so\n it simply wins outright, landing muted and plain on the same escalated\n color when both are pressed — which is what muted's OWN test expects. */\nbutton.outlined.${t}:not(.muted):hover:not(:disabled),\nbutton.outlined.${t}:active:not(:disabled),\nbutton.outlined.${t}:focus-visible {\n color: var(--ty-button-color, ${e("-strong")});\n border-color: var(--ty-button-border, ${e("-strong")});\n}\n`},u=(t,n)=>{const e=e=>"neutral"===t&&"-strong"===e?`var(--ty-solid-neutral${e})`:(e=>a("--ty-color",t,e,n))(e);return`\nbutton.ghost.${t} { color: var(--ty-button-color, var(--_muted-ghost-fg, ${e("")})); }\nbutton.ghost.${t}.tone-plus { color: var(--ty-button-color, var(--_muted-ghost-fg, ${e("-strong")})); }\nbutton.ghost.${t}.tone-minus { color: var(--ty-button-color, var(--_muted-ghost-fg, ${e("-soft")})); }\nbutton.ghost.${t}:hover:not(:disabled) {\n background: var(--ty-button-bg-hover, ${a("--ty-bg",t,"-soft",n)});\n}\n/* See outlinedFlavor above — same escalation-to-peak, same :hover-only\n :not(.muted) split, text only. */\nbutton.ghost.${t}:not(.muted):hover:not(:disabled),\nbutton.ghost.${t}:active:not(:disabled),\nbutton.ghost.${t}:focus-visible {\n color: var(--ty-button-color, ${e("-strong")});\n}\n`},p=`\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 /* Mode-flipped weight dial (tyrell.css): medium in light, normal in dark —\n light-on-dark text blooms, a fixed semibold read heavy there. Override\n with --ty-weight-action at any scope. */\n font-weight: var(--ty-weight-action, var(--ty-font-medium));\n white-space: nowrap;\n cursor: pointer;\n user-select: none;\n transition: var(--ty-local-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/* ===== MUTED =====\n Show the neutral tokens at rest instead of the flavor color; reveal the\n real flavor on interaction. Implemented as a fallback tier the flavor\n rules above already read (--_muted-*), which sits behind the public\n --ty-button-{bg,color,border} override slots and ahead of the flavor's\n own token — so a custom brand color still wins, muted or not. Unsetting\n --_muted-* on interaction falls the var() chain through to whatever's\n next (the user's override, or the real flavor color).\n Hover reveal is gated to real pointers (touch has no hover); :active /\n :focus-visible cover the tap case so touch still gets the color on press. */\n\n/* --_muted-solid-* reads the SOLID neutral ink tokens — a fill's L doesn't\n need page contrast. --_muted-outlined-line / --_muted-ghost-fg are bare\n text/border and DO — they stay on the regular text ladder (it already\n inverts correctly per mode), except tone-plus, which is legible AND\n loud on the ink dial (16.5:1 dark, matches solid's "+" identity). Base/\n soft on ink measured 1.01/1.20 dark contrast against the canvas —\n invisible; WCAG minimum is 4.5. */\nbutton.muted {\n --_muted-solid-bg: var(--ty-solid-neutral);\n --_muted-solid-fg: var(--ty-solid-neutral-fg);\n --_muted-outlined-line: var(--ty-color-neutral);\n --_muted-ghost-fg: var(--ty-color-neutral);\n}\nbutton.muted.tone-plus {\n --_muted-solid-bg: var(--ty-solid-neutral-strong);\n /* fg must track the tone's fill: neutral+ is inverted ink in dark mode\n (white fill), so inheriting base neutral's white fg would be\n white-on-white. */\n --_muted-solid-fg: var(--ty-solid-neutral-strong-fg);\n --_muted-outlined-line: var(--ty-solid-neutral-strong);\n --_muted-ghost-fg: var(--ty-solid-neutral-strong);\n}\nbutton.muted.tone-minus {\n --_muted-solid-bg: var(--ty-solid-neutral-soft);\n --_muted-solid-fg: var(--ty-solid-neutral-soft-fg);\n --_muted-outlined-line: var(--ty-color-neutral-soft);\n --_muted-ghost-fg: var(--ty-color-neutral-soft);\n}\n@media (hover: hover) and (pointer: fine) {\n button.muted:hover:not(:disabled) {\n --_muted-solid-bg: unset;\n --_muted-solid-fg: unset;\n --_muted-outlined-line: unset;\n --_muted-ghost-fg: unset;\n }\n}\nbutton.muted:active:not(:disabled),\nbutton.muted:focus-visible:not(:disabled) {\n --_muted-solid-bg: unset;\n --_muted-solid-fg: unset;\n --_muted-outlined-line: unset;\n --_muted-ghost-fg: unset;\n}\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-theme.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 --_ring: var(--ty-color-neutral);\n --_solid-bg: var(--ty-button-bg, var(--ty-solid-neutral));\n --_solid-rest: var(--ty-button-bg, var(--ty-solid-neutral));\n /* Bare .solid is the flavorless default = neutral ink, so it takes the\n neutral border offset; colored flavor rules reset this to the plain\n dial. */\n --_border-l: var(--ty-button-border-l-neutral, var(--ty-button-border-l, -0.15));\n background: var(--_solid-bg);\n color: var(--ty-button-color, var(--ty-solid-neutral-fg));\n /* Depth chrome — border + drop shadow, both scaled by --ty-button-depth.\n (A top-edge sheen — inset 0 1px 0 <lightened fill> — used to live here\n too; dropped, it read as a dizzying bright line rather than a subtle\n highlight.) depth 0 = border matches fill exactly and the shadow goes\n transparent — pixel-flat, but the 1px border stays in the layout so\n toggling depth never shifts geometry (and solid now shares the same\n box as outlined/ghost, which always had a 1px border).\n --ty-button-border-l flips sign with the mode (tyrell.css): dark mode\n runs a LIGHTER-than-fill hairline (fills read washed-out against dark\n surfaces without a lit edge), light mode a slightly darker one.\n Direct escape hatches outrank the derivation: --ty-solid-border-color\n pins the border to ANY color (the L-offset dials stop mattering), and\n --ty-solid-border-width changes thickness (widths ≠ 1px do shift\n geometry — that's inherent).\n Browsers without relative color drop these declarations: border falls\n back to the base button's 1px transparent, shadows to none. */\n border: var(--ty-solid-border-width, 1px) solid\n var(--ty-solid-border-color,\n oklch(from var(--_solid-rest, var(--_solid-bg)) calc(l + var(--_border-l, -0.15) * var(--ty-button-depth, 0.35)) c h));\n box-shadow: 0 1px 2px oklch(0 0 0 / calc(0.4 * var(--ty-button-depth, 0.35)));\n}\nbutton.solid.tone-plus { --_solid-bg: var(--ty-button-bg, var(--ty-solid-neutral-strong)); --_solid-rest: var(--ty-button-bg, var(--ty-solid-neutral-strong)); color: var(--ty-button-color, var(--ty-solid-neutral-strong-fg)); }\nbutton.solid.tone-minus { --_solid-bg: var(--ty-button-bg, var(--ty-solid-neutral-soft)); --_solid-rest: var(--ty-button-bg, var(--ty-solid-neutral-soft)); color: var(--ty-button-color, var(--ty-solid-neutral-soft-fg)); }\nbutton.solid:hover:not(:disabled) { --_solid-bg: var(--ty-button-bg-hover, var(--ty-solid-neutral-hover)); }\nbutton.solid:active:not(:disabled) { --_solid-bg: var(--ty-solid-neutral-active); }\nbutton.solid.tone-plus:hover:not(:disabled) {\n --_solid-bg: var(--ty-button-bg-hover, oklch(from var(--ty-solid-neutral-strong) calc(l + sign(0.5 - l) * abs(var(--ty-solid-hover-l))) c h));\n}\nbutton.solid.tone-plus:active:not(:disabled) {\n --_solid-bg: oklch(from var(--ty-solid-neutral-strong) calc(l + sign(0.5 - l) * abs(var(--ty-solid-active-l))) c h);\n}\nbutton.solid.tone-minus:hover:not(:disabled) {\n --_solid-bg: var(--ty-button-bg-hover, oklch(from var(--ty-solid-neutral-soft) calc(l + var(--ty-solid-hover-l)) c h));\n}\nbutton.solid.tone-minus:active:not(:disabled) {\n --_solid-bg: oklch(from var(--ty-solid-neutral-soft) calc(l + var(--ty-solid-active-l)) c h);\n}\n\n${r.map(t=>d(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=>h(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=>u(t)).join("")}`;function b(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 g=null;function m(t){g=t&&t.trim()?t:null}function v(){return g??'<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 f(){g=null}const y=class extends i{constructor(){super(),this.A=!1,this.D=null,s(this.shadowRoot,{css:p,id:"ty-button"})}onConnect(){this.I()}onDisconnect(){}onPropertiesChanged(t){t.some(t=>"flavor"===t.name)&&this.I()}I(){const{base:t}=this.parseFlavor();this.D=b(this.shadowRoot,this.D,t,()=>(t=>d(t,"neutral")+h(t,"neutral")+u(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 muted(){return this.getProperty("muted")}set muted(t){this.setProperty("muted",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",this.muted&&"muted","+"===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=v();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=v())}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))}};y.formAssociated=!0,y.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},muted:{type:"boolean",visual:!0,default:!1},wide:{type:"boolean",visual:!1,default:!1},name:{type:"string",default:""},value:{type:"string",default:""}};let w=y;customElements.get("ty-button")||customElements.define("ty-button",w);const x="1.0.0-TC45",k=new Map,z=new Map,$=new Map;let C=null,S=null;const E="ty-icons-v"+x,T="https://ty-icons.local/",M=new Map;let A=!1;function D(t){const n=new Set;Object.entries(t).forEach(([t,e])=>{k.set(t,e),n.add(t)}),n.size>0&&R(n)}function I(t){return k.get(t)}function O(t){return k.has(t)}async function L(){const t=new Set(k.keys());if(k.clear(),"caches"in window)try{await caches.delete(E),A=!1}catch(n){}R(t)}function N(t,n,e){z.set(t,e),n&&$.set(t,n)}function _(t){z.delete(t),$.delete(t)}function R(t){C||(C=new Set),t.forEach(t=>C.add(t)),null!==S&&clearTimeout(S);const n="undefined"!=typeof requestIdleCallback?requestIdleCallback:t=>setTimeout(t,0);S=n(()=>{const t=C;C=null,S=null,t&&t.size>0&&function(t){z.forEach((n,e)=>{const i=$.get(e);i?t.has(i)&&n(new Set([i])):n(t)})}(t)})}function F(){return Array.from(k.keys())}async function q(){const t={version:x,cacheName:E,available:"caches"in window};if(!t.available)return t;try{const n=await caches.open(E),e=(await n.keys()).filter(t=>t.url.startsWith(T));return{...t,iconCount:e.length}}catch(n){return t}}const V=Object.freeze(Object.defineProperty({__proto__:null,addWatcher:N,clearIcons:L,getCacheInfo:q,getCachedIcon:async function(t){const n=M.get(t);if(n)return n;const e=(async()=>{try{await async function(){if(!A&&"caches"in window){A=!0;try{const t=(await caches.keys()).filter(t=>t.startsWith("ty-icons-v")&&t!==E);await Promise.all(t.map(t=>caches.delete(t)))}catch(t){}}}();const n=await caches.open(E),e=await n.match(`${T}${t}`);if(e)return await e.text()}catch(n){}return null})();return M.set(t,e),e.finally(()=>{M.delete(t)}),e},getIcon:I,getIconNames:F,hasIcon:O,registerIcons:D,removeWatcher:_},Symbol.toStringTag,{value:"Module"}));let P=0;const H='<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>',j=class extends i{constructor(){super(),this.O=null,this.L="",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=H,this.L=H,this.shadowRoot.appendChild(this.N)}onConnect(){this.O="ty-icon-"+ ++P,this.name&&N(this.O,this.name,t=>{this.name&&t.has(this.name)&&this.render()}),this.updateClasses()}onDisconnect(){this.O&&(_(this.O),this.O=null)}onPropertiesChanged(t){for(const n of t)if("name"===n.name){this.O&&_(this.O);const t=n.newValue||"";t&&this.isConnected&&(this.O="ty-icon-"+ ++P,N(this.O,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(H);const n=I(t);this.renderSvg(n||H)}renderSvg(t){this.L!==t&&this.N&&(this.N.innerHTML=t,this.L=t)}};j.formAssociated=!1,j.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=j;customElements.get("ty-icon")||customElements.define("ty-icon",B);const W=`\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 /* Mode-flipped weight dial (tyrell.css): 440 light / 400 dark. Chips are\n labels, not actions — they run lighter than buttons. Override with\n --ty-weight-label at any scope. */\n font-weight: var(--ty-weight-label, 440);\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`,Y=class extends i{constructor(){super(),this._=null,this.D=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:W,id:"ty-tag"})}onConnect(){this.I(),queueMicrotask(()=>{this.setupEventListeners()})}I(){this.D=b(this.shadowRoot,this.D,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.I()}dispatchTagEvent(t,n){this.dispatchEvent(new CustomEvent(t,{detail:n,bubbles:!0,composed:!0,cancelable:!0}))}cleanupEventListeners(){this._&&(this._(),this._=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._=()=>{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)}};Y.formAssociated=!0,Y.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 U=Y;customElements.get("ty-tag")||customElements.define("ty-tag",U);class TyOption extends HTMLElement{constructor(){super(),this.R=void 0,this.F=!1,this.q=!1,this.V=!1,this.P=!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.R=t.value,delete this.value),this.render()}attributeChangedCallback(t,n,e){if(n!==e){switch(t){case"value":this.R=e||void 0;break;case"selected":this.F=null!==e;break;case"disabled":this.q=null!==e;break;case"highlighted":this.V=null!==e;break;case"hidden":this.P=null!==e}this.render()}}getOptionValue(){if(void 0!==this.R)return this.R;const t=this.getAttribute("value");return null!==t?t:this.textContent?.trim()||""}get value(){return this.getOptionValue()}set value(t){this.R!==t&&(this.R=t,void 0!==t?this.setAttribute("value",t):this.removeAttribute("value"),this.render())}get selected(){return this.F}set selected(t){this.F!==t&&(this.F=t,t?this.setAttribute("selected",""):this.removeAttribute("selected"),this.render())}get disabled(){return this.q}set disabled(t){this.q!==t&&(this.q=t,t?this.setAttribute("disabled",""):this.removeAttribute("disabled"),this.render())}get highlighted(){return this.V}set highlighted(t){this.V!==t&&(this.V=t,t?this.setAttribute("highlighted",""):this.removeAttribute("highlighted"),this.render())}get hidden(){return this.P}set hidden(t){this.P!==t&&(this.P=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.q?n.setAttribute("disabled",""):n.removeAttribute("disabled"),this.F?n.setAttribute("selected",""):n.removeAttribute("selected"),this.V?n.setAttribute("highlighted",""):n.removeAttribute("highlighted"),this.P?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`},K=`\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: var(--ty-local-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/* :not(.focused) — hover must never override focus. Without the guard this\n rule out-ranks .focused by specificity, so hovering a FOCUSED unflavored\n input swapped its primary focus border for the dimmer neutral hover\n border (focus ring stayed, border dimmed — read as a glitch). Same\n pattern as date-picker's :hover:not(.open). */\n.input-wrapper:hover:not(.disabled):not(.focused) {\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: var(--ty-local-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 Z(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.H=null,this.j=!1,this.B=!1,this.W=!1,this.D=null,this.Y=null,this.U=null,this.G=null,this.K=null,this.Z=null,this.X=null,s(this.shadowRoot,{css:K,id:"ty-input"})}onConnect(){this.initializeShadowValue(),this.J=J(this,()=>{this.render()}),this.I()}I(){this.D=b(this.shadowRoot,this.D,this.flavor,({base:t})=>(t=>G(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.I();break;case"value":this.H=this.parseShadowValue(e||"");break;case"type":const t=this.getProperty("value")||"";this.H=this.parseShadowValue(t);break;case"error":e?"neutral"===this.getProperty("flavor")&&(this.setProperty("flavor","danger"),this.W=!0):this.W&&("danger"===this.getProperty("flavor")&&this.setProperty("flavor","neutral"),this.W=!1)}}onFormReset(){this.H=null,this.j=!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.H?this.H+"":null}initializeShadowValue(){const t=this.getProperty("value");t&&(this.H=this.parseShadowValue(t),this.v.setFormValue(null!==this.H?this.H+"":null))}parseShadowValue(t){if(!t||"string"!=typeof t||""===t.trim())return null;if(Z(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 Z(this.type)&&!this.j&&null!==this.H&&"number"==typeof this.H}getFormatConfig(){return{type:this.type,locale:this.locale,currency:this.currency,precision:this.precision}}getDisplayValue(){if(this.shouldFormat()){let t=this.H;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.H?this.H+"":""}get type(){return this.getProperty("type")}set type(t){this.setProperty("type",t)}get value(){return null!==this.H?this.H+"":""}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.H,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.H,formattedValue:this.shouldFormat()?this.getDisplayValue():null,rawValue:t,originalEvent:n},bubbles:!0,composed:!0}))}removeEventListeners(){if(!this.B)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.B=!1)}setupEventListeners(){if(this.B)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.H=this.parseShadowValue(e),this.v.setFormValue(null!==this.H?this.H+"":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.H=this.parseShadowValue(e),this.v.setFormValue(null!==this.H?this.H+"":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.j=!0,e.classList.add("focused"),Z(this.type)&&null!==this.H&&(n.value=this.H+""),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.j=!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.B=!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=Z(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: var(--ty-local-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: var(--ty-local-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.D=null,this.B=!1,this.tt=null,this.nt=null,this.G=null,this.K=null,s(this.shadowRoot,{css:ot,id:"ty-checkbox"})}onConnect(){this.setupEventListeners(),this.I()}I(){this.D=b(this.shadowRoot,this.D,this.flavor,({base:t})=>(t=>it(t,"neutral"))(t))}onDisconnect(){this.removeEventListeners()}onPropertiesChanged(t){t.some(t=>"flavor"===t.name)&&this.I()}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.B)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.B=!1):this.B=!1}setupEventListeners(){if(this.B)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.B=!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${K}\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: var(--ty-local-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: var(--ty-local-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.D=null,this.B=!1,this.tt=null,this.nt=null,this.G=null,this.K=null,s(this.shadowRoot,{css:lt,id:"ty-switch"})}onConnect(){this.setupEventListeners(),this.I()}onDisconnect(){this.removeEventListeners()}onPropertiesChanged(t){t.some(t=>"flavor"===t.name)&&this.I()}I(){this.D=b(this.shadowRoot,this.D,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.B)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.B=!1):this.B=!1}setupEventListeners(){if(this.B)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.B=!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${K}\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: var(--ty-local-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.D=null,this.B=!1,this.tt=null,this.G=null,this.K=null,s(this.shadowRoot,{css:ut,id:"ty-radio"})}onConnect(){this.setupEventListeners(),this.dispatchEvent(new CustomEvent("ty-radio-connected",{bubbles:!0})),this.I()}onDisconnect(){this.removeEventListeners()}onPropertiesChanged(t){t.some(t=>"flavor"===t.name)&&this.I()}I(){this.D=b(this.shadowRoot,this.D,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.B)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.B=!1):this.B=!1}setupEventListeners(){if(this.B)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.B=!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.B=!1,this.et=null,this.nt=null,this.it=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.B&&(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.B=!1)}setupEventListeners(){this.B||(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.B=!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`},ft=`\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: var(--ty-local-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: var(--ty-local-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`,yt='<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.ot=null,this.st=!1,this.D=null,s(this.shadowRoot,{css:K,id:"ty-input"}),s(this.shadowRoot,{css:ft,id:"ty-copy"})}onConnect(){this.I()}I(){this.D=b(this.shadowRoot,this.D,this.flavor,({base:t})=>(t=>vt(t,"neutral"))(t))}onDisconnect(){null!==this.ot&&(clearTimeout(this.ot),this.ot=null)}onPropertiesChanged(t){t.some(t=>"flavor"===t.name)&&this.I()}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=wt,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=yt,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=yt,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">${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.st?" success":""}" type="button" aria-label="${this.st?"Copied!":"Copy to clipboard"}" ${this.disabled?"disabled":""}>\n ${this.st?wt:yt}\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.rt=[],this.lt=!1,this.B=!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: var(--ty-local-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: var(--ty-local-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: var(--ty-local-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.B)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.B=!0}removeEventListeners(){if(!this.B)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.B=!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=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.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"}};$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.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.Dt=this.It.bind(this),this.Ot=this.Lt.bind(this),this.Nt=this._t.bind(this),this.Rt=this.Ft.bind(this),this.qt=this.Vt.bind(this),this.Pt=this.Ht.bind(this),this.St&&(this.trackY=this.jt("y"),this.thumbY=this.Bt("y"),this.trackY.appendChild(this.thumbY)),this.Et&&(this.trackX=this.jt("x"),this.thumbX=this.Bt("x"),this.trackX.appendChild(this.thumbX)),this.Ct.addEventListener("scroll",this.Mt,{passive:!0}),this.thumbY&&this.thumbY.addEventListener("pointerdown",this.Dt),this.trackY&&this.trackY.addEventListener("pointerdown",this.Nt),this.thumbX&&this.thumbX.addEventListener("pointerdown",this.Ot),this.trackX&&this.trackX.addEventListener("pointerdown",this.Rt),this.$t=new ResizeObserver(()=>this.update()),this.$t.observe(this.Ct),this.update()}jt(t){const n=document.createElement("div");return n.className="ty-scrollbar-track-"+t,n}Bt(t){const n=document.createElement("div");return n.className="ty-scrollbar-thumb-"+t,n}update(){this.Wt(),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.Dt),this.trackY&&this.trackY.removeEventListener("pointerdown",this.Nt),this.thumbX&&this.thumbX.removeEventListener("pointerdown",this.Ot),this.trackX&&this.trackX.removeEventListener("pointerdown",this.Rt),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()}))}Wt(){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))}It(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.qt),this.thumbY.addEventListener("pointerup",this.Pt),this.thumbY.addEventListener("pointercancel",this.Pt))}Lt(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.qt),this.thumbX.addEventListener("pointerup",this.Pt),this.thumbX.addEventListener("pointercancel",this.Pt))}Vt(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)}}Ht(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.qt),n.removeEventListener("pointerup",this.Pt),n.removeEventListener("pointercancel",this.Pt),this.Gt()}_t(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"})}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.Ct;this.Ct.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: var(--ty-local-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: var(--ty-local-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.Xt=null,this.Jt=null,this.Qt=null,this.j=!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.j=!0},this.handleBlurEvent=()=>{this.j=!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: var(--ty-local-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: var(--ty-local-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: var(--ty-local-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.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||!St())return;t.style.scrollbarWidth="none",this.setAttribute("data-custom-scroll",""),this.Qt=new Et(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">${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.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">${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.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({})}};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 Dt=At;customElements.get("ty-textarea")||customElements.define("ty-textarea",Dt);const It={"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"}},Ot={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 Lt(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=Ot.default,offset:o=8,padding:s=8,containerPadding:r=0}=t,a=Lt(n),l=Lt(e),c=i.map(t=>function(t){const{targetRect:n,floatingRect:e,placement:i,offset:o,padding:s,scrollbarWidth:r,containerPadding:a}=t,l=It[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 _t(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("end"===t.align?t.anchorRect.right-t.popupWidth:t.anchorRect.left,i-t.popupWidth-e)),topY:t.anchorRect.bottom+n,bottomY:o-t.anchorRect.top+n,below:r}}const Rt={id:"ty-tooltip",css:"\n/* Tooltip host element - display contents to not affect layout */\n:host {\n display: contents;\n}\n"},Ft=new WeakMap,qt=new WeakMap,Vt=new WeakMap,Pt=new WeakMap,Ht=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 Bt(t){let n=Vt.get(t);return n||(n={showTimeout:null,hideTimeout:null},Vt.set(t,n)),n}function Wt(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:Wt(t,"disabled"),flavor:jt(t.getAttribute("flavor"))}}function Gt(t){return t.parentElement}function Kt(t){let n=Pt.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),Pt.set(t,n);const e=Ht.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,Zt(n,e),n}function Zt(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=Pt.get(t);if(!i||!o)return;const s=Nt({targetEl:i,floatingEl:o,preferences:"top"===n?Ot.tooltip:"bottom"===n?["bottom","top","left","right"]:"left"===n?["left","right","top","bottom"]:"right"===n?["right","left","top","bottom"]:Ot.tooltip,offset:e});o.style.left=s.x+"px",o.style.top=s.y+"px"}function Jt(t){const n=Ft.get(t);n&&(n(),Ft.delete(t))}function Qt(t){const n=Bt(t);null!==n.showTimeout&&(clearTimeout(n.showTimeout),n.showTimeout=null),null!==n.hideTimeout&&(clearTimeout(n.hideTimeout),n.hideTimeout=null)}function tn(t){const n=Pt.get(t);if(n)try{n.hidePopover(),t.en=!1,Jt(t)}catch(e){}}function nn(t){const n=Bt(t),{delay:e}=Ut(t);Qt(t),n.showTimeout=window.setTimeout(()=>function(t){const{disabled:n}=Ut(t);if(n)return;const e=Kt(t);try{e.showPopover(),t.en=!0,Xt(t),function(t){const n=Gt(t),e=Pt.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),Ft.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=Bt(t);Qt(t),n.hideTimeout=window.setTimeout(()=>tn(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,Rt),function(t){const n=Gt(t);if(!n)return;Ht.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),qt.set(t,()=>{n.removeEventListener("mouseenter",e),n.removeEventListener("mouseleave",i),n.removeEventListener("focusin",o),n.removeEventListener("focusout",s)})}(this),Kt(this)}disconnectedCallback(){!function(t){Qt(t),Jt(t);const n=qt.get(t);n&&(n(),qt.delete(t));const e=Pt.get(t),i=Ht.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(),Pt.delete(t)),Ht.delete(t),Vt.delete(t)}(this)}attributeChangedCallback(t,n,e){if("flavor"===t){const t=Pt.get(this);t&&Zt(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,bn=new WeakMap;function gn(t,n){return t.hasAttribute(n)}function mn(t,n,e){const i=t.getAttribute(n);if(null===i)return e;const o=parseInt(i,10);return isNaN(o)?e:o}function vn(t){return{manual:gn(t,"manual"),disableClose:gn(t,"disable-close"),placement:t.getAttribute("placement")||"bottom",offset:mn(t,"offset",8)}}function fn(t){return t.parentElement}function yn(t){return t.querySelector(".popup-dialog")}function wn(t){let n=bn.get(t);return n||(n="popup-"+(t.id||Math.random().toString(36).substr(2,9)),bn.set(t,n)),n}function xn(t,n=!1){const{disableClose:e}=vn(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=fn(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 kn(t){an(wn(t));const n=t.shadowRoot,e=n?yn(n):null;if(!e)return;e.showModal();const i=fn(t);i?.hasAttribute("aria-haspopup")&&i.setAttribute("aria-expanded","true"),requestAnimationFrame(()=>{!function(t){const{placement:n,offset:e}=vn(t),i=t.shadowRoot,o=fn(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 zn(t){const n=t.shadowRoot,e=n?yn(n):null;e&&(e.classList.contains("open")?xn(t):kn(t))}function $n(t,n){n.preventDefault(),n.stopPropagation(),zn(t)}function Cn(t){const{manual:n}=vn(t),e=fn(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=dn.get(t);o&&e.removeEventListener("click",o);const s=n=>$n(t,n);cn.set(t,s),e.addEventListener("pointerdown",s);const r=n=>{0===n.detail&&$n(t,n)};dn.set(t,r),e.addEventListener("click",r)}function Sn(t){const n=fn(t),e=cn.get(t);n&&e&&(n.removeEventListener("pointerdown",e),cn.delete(t));const i=dn.get(t);n&&i&&(n.removeEventListener("click",i),dn.delete(t)),n?.removeAttribute("aria-haspopup"),n?.removeAttribute("aria-expanded")}function En(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(),xn(t))}(t,n);hn.set(t,s),e.addEventListener("pointerdown",s);const r=n=>function(t,n){if(n.stopPropagation(),"Escape"===n.key){const{disableClose:e}=vn(t);e?n.preventDefault():xn(t)}}(t,n);un.set(t,r),t.addEventListener("keydown",r),e.addEventListener("close",()=>{ln(wn(t)),e.classList.remove("open"),e.classList.remove("preparing-animation"),t.dispatchEvent(new CustomEvent("close",{bubbles:!0}))})}t.closePopup=()=>xn(t,!0),t.openPopup=()=>kn(t),t.togglePopup=()=>zn(t);const i=n=>function(t,n){n.stopPropagation(),xn(t,!0)}(t,n);pn.set(t,i),t.addEventListener("ty:close-popup",i),Cn(t)}class TyPopup extends HTMLElement{static get observedAttributes(){return["manual","disable-close","placement","offset"]}constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){En(this)}disconnectedCallback(){!function(t){const n=bn.get(t);n&&(ln(n),bn.delete(t)),Sn(t);const e=t.shadowRoot,i=e?yn(e):null;if(i){const n=hn.get(t);n&&(i.removeEventListener("pointerdown",n),hn.delete(t))}const o=un.get(t);o&&(t.removeEventListener("keydown",o),un.delete(t));const s=pn.get(t);s&&(t.removeEventListener("ty:close-popup",s),pn.delete(t))}(this)}attributeChangedCallback(t,n,e){switch(En(this),t){case"placement":case"offset":En(this);break;case"manual":case"disable-close":Sn(this),Cn(this)}}}customElements.get("ty-popup")||customElements.define("ty-popup",TyPopup);const Tn=new WeakMap,Mn=new WeakMap,An=new WeakMap,Dn=new WeakMap,In=new WeakMap,On=new WeakMap;function Ln(t,n){if(!t.hasAttribute(n))return!1;const e=t.getAttribute(n);return null===e||"false"!==e.toLowerCase()}function Nn(t){return t.querySelector(".ty-modal-dialog")}function _n(t,n,e){const i=new CustomEvent(n,{detail:e,bubbles:!0,cancelable:!0});t.dispatchEvent(i)}function Rn(t,n="programmatic",e){const i=t.shadowRoot,o=i?Nn(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 Fn(t){const n=t.shadowRoot;if(!n)return;const e=function(t){return{open:Ln(t,"open"),backdrop:!t.hasAttribute("backdrop")||Ln(t,"backdrop"),closeOnOutsideClick:!t.hasAttribute("close-on-outside-click")||Ln(t,"close-on-outside-click"),closeOnEscape:!t.hasAttribute("close-on-escape")||Ln(t,"close-on-escape")}}(t),i=function(t){let n=Nn(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=On.get(t);return n||(n="modal-"+(t.id||Math.random().toString(36).slice(2,11)),On.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=Tn.get(t);if(i&&(n.removeEventListener("click",i),Tn.delete(t)),e){const e=n=>function(t,n){n.stopPropagation();const e=t.shadowRoot,i=e?Nn(e):null;i&&n.target===i&&(n.preventDefault(),Rn(t,"backdrop"))}(t,n);Tn.set(t,e),n.addEventListener("click",e)}}(t,i,e.closeOnOutsideClick),function(t,n,e){const i=Mn.get(t);if(i&&(n.removeEventListener("keydown",i),Mn.delete(t)),e){const e=n=>function(t,n){n.stopPropagation(),"Escape"===n.key&&(n.preventDefault(),Rn(t,"escape"))}(t,n);Mn.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=An.get(t);if(o&&(i.removeEventListener("click",o),An.delete(t)),e){const n=n=>function(t,n){n.preventDefault(),n.stopPropagation(),Rn(t,"close-button")}(t,n);An.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=Dn.get(t),o=In.get(t);if(i&&(e.removeEventListener("mouseenter",i),Dn.delete(t)),o&&(e.removeEventListener("mouseleave",o),In.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);Dn.set(t,n),In.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(),_n(t,"open",{})):i.open&&(ln(o),i.close(),_n(t,"close",{reason:"programmatic"})),i.onclose=n=>{n.target===i&&(ln(o),t.hasAttribute("open")&&(t.removeAttribute("open"),_n(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(){Fn(this),this.show=()=>{this.setAttribute("open","true")},this.hide=t=>Rn(this,"programmatic",t)}disconnectedCallback(){!function(t){const n=On.get(t),e=t.shadowRoot,i=e?Nn(e):null;if(n&&(ln(n),On.delete(t)),!i)return;const o=Tn.get(t);o&&(i.removeEventListener("click",o),Tn.delete(t));const s=Mn.get(t);s&&(i.removeEventListener("keydown",s),Mn.delete(t));const r=i.querySelector(".close-button");if(r){const n=An.get(t);n&&(r.removeEventListener("click",n),An.delete(t))}const a=i.querySelector(".modal-content");if(a){const n=Dn.get(t),e=In.get(t);n&&(a.removeEventListener("mouseenter",n),Dn.delete(t)),e&&(a.removeEventListener("mouseleave",e),In.delete(t))}}(this)}attributeChangedCallback(t,n,e){this.isConnected&&Fn(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 display: block;\n width: 100%;\n font-family: var(--ty-font-sans);\n --mobile-border-color: var(--ty-border, #5858587d);\n}\n\n/* compact is a toolbar/filter-bar trigger — it must hug its own content so\n it can sit inline next to other toolbar items, not claim a full row.\n inline-block (not plain inline): a block box still ignores width and\n collapses vertical margin, which is what we're fixing above. */\n:host([compact]) {\n display: inline-block;\n width: auto;\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 :not(.custom-trigger) — that skin has its own unconditional box-shadow:\n none reset below; excluding it here keeps the two rules from competing\n on specificity (:has()/:not() here would otherwise outrank it).\n :not(:has(search:focus)) — the search row auto-focuses on open, which\n already carries its own real :focus ring (below); without this guard the\n stub's "fake" open-ring stacks on top of it, and the field reads as two\n simultaneously-focused controls. Real focus wins; the stub ring is only\n for select skins that have nothing else to show it. */\n.dropdown-wrapper:has(.dropdown-chevron.open):not(:has(.dropdown-search-input:focus)) .select-stub:not(.custom-trigger),\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 /* Floating surface/border, not --input-* — this is a popup panel over\n arbitrary page content, not a form field. --ty-input-border resolves to\n the deliberately-faint resting-state input border (barely visible by\n design, escalates on hover/focus); reused here it made the popup's own\n edge nearly invisible against the page behind it. --ty-floating-border\n is the token tuned for exactly this: floating panels over content. */\n background: var(--ty-surface-floating);\n border: 1px solid var(--ty-floating-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 /* No gap here — label→field spacing comes from .ty-field-label's\n margin-bottom (6px), same as ty-input/ty-date-picker/ty-textarea.\n A flex gap would STACK on that margin (flex margins don't collapse),\n which is exactly the 4px misalignment this used to cause. */\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(--ty-surface-floating));\n border: 1px solid var(--ty-loader-border, var(--ty-floating-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`;function Pn(t=768){return window.matchMedia(`(pointer: coarse) and (max-width: ${t}px)`).matches}let Hn=0;const jn=new WeakMap;function Bn(t){let n=jn.get(t);return void 0===n&&(n=++Hn,jn.set(t,n)),n}const Wn='<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>',Yn='<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>',Un='<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>',Gn=class extends i{constructor(){super(),this.sn="",this.rn=!1,this.an=!1,this.ln="Select...",this.cn="",this.q=!1,this.dn=!1,this.hn=!1,this.un=!0,this.pn=!1,this.bn=!1,this.gn="none",this.mn="auto",this.vn=!1,this.fn=null,this.yn="md",this.wn="Available",this.xn="No options available",this.kn={open:!1,search:"",highlightedIndex:-1,filteredTags:[],selectedValues:[],mode:"desktop"},this.zn=null,this.$n=null,this.Cn=null,this.Sn=null,this.En=null,this.Tn=0,this.Mn=null,this.An=null,this.Dn=null,this.In=null,this.D=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 width: auto;\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\n/* Clear (x) button — normal flex child of .select-stub, not absolutely\n positioned like .dropdown-chevron: it just takes its own space in the\n row, no padding-right gutter math needed. Lives in the trigger slot\'s\n fallback content, so it\'s automatically absent under slot="trigger". */\n.select-clear {\n flex-shrink: 0;\n display: inline-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(--input-placeholder, var(--ty-input-placeholder));\n cursor: pointer;\n border-radius: var(--ty-radius-sm);\n transition: var(--ty-local-transition, all 0.15s ease);\n}\n.select-clear[hidden] {\n display: none;\n}\n.select-clear:hover {\n /* Destructive utility action — neutral at rest, warns danger-red on\n hover regardless of the field\'s own flavor. */\n color: var(--ty-color-danger);\n background-color: var(--ty-bg-danger-soft);\n}\n.select-clear svg {\n width: 100%;\n height: 100%;\n}\n\n/* Selection text (field skin): single line, ellipsis, input colors.\n flex-basis 0, not auto — .select-stub is flex-wrap:wrap, and auto\'s\n hypothetical size is the FULL untruncated text width (wrap-line\n assignment happens before shrinking), which pushed fixed-size siblings\n (.select-clear) onto a second line even though the text visibly had\n room after truncating. 0 makes this item contribute ~nothing to the\n line-fit check up front; grow/shrink + overflow:hidden still truncate\n it identically. */\n.select-stub .dropdown-placeholder {\n font-style: normal;\n flex: 1 1 0%;\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 flex-basis: auto (not the field skin\'s 0%) — content-hugging needs its\n natural content width as the starting point; 0% would collapse it since\n grow is also 0 here (nothing left to expand it back out). */\n.select-stub.compact .dropdown-placeholder {\n flex: 0 1 auto;\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. The header\'s OWN surface/border is\n part of the floating panel\'s chrome, not a form field — --ty-surface-\n floating/--ty-floating-border, matching .dropdown-options below it (same\n reasoning as the base-panel fix: --ty-input-* is deliberately faint for\n resting form fields and read as a missing/mismatched edge here). */\n.dropdown-header {\n background: var(--ty-surface-floating);\n border: 1px solid var(--ty-floating-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(--ty-floating-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(--ty-floating-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(--ty-floating-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(--ty-floating-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.kn.selectedValues.length>0&&this.syncSelectedTags(this.kn.selectedValues),this.updateSearchVisibility(),this.updateSelectionDisplay(),this.updateMobileSelectedState()}),this.Dn.observe(this,{childList:!0}),this.ensureOptionRoles(),this.I()}I(){this.D=b(this.shadowRoot,this.D,this.getProperty("flavor"),({base:t})=>(t=>qn(t,"neutral"))(t))}onDisconnect(){this.shadowRoot.querySelectorAll("dialog").forEach(t=>{t.open&&t.close()}),this.En&&(document.removeEventListener("keydown",this.En),this.En=null),null!==this.Mn&&(clearTimeout(this.Mn),this.Mn=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.kn.selectedValues=t,this.isConnected&&this.shadowRoot&&(this.syncSelectedTags(t),this.updateSelectionDisplay(),this.updateMobileSelectedState());break;case"name":this.sn=e||"";break;case"flavor":this.I();break;case"multiple":this.rn=e,!e&&this.kn.selectedValues.length>1&&this.updateComponentValue([this.kn.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.q=e;break;case"readonly":this.dn=e;break;case"required":this.hn=e;break;case"clearable":this.un=e,this.isConnected&&this.shadowRoot&&this.updateSelectionDisplay();break;case"externalSearch":this.pn=e;break;case"searchable":this.mn=e,this.isConnected&&this.shadowRoot&&this.updateSearchVisibility();break;case"allowCreate":this.bn=e,this.isConnected&&this.shadowRoot&&this.updateSearchVisibility();break;case"createTransform":this.gn=e;break;case"size":this.yn=e;break;case"debounce":this.Tn=e;break;case"available-label":this.wn=e||"Available";break;case"no-options-message":this.xn=e||"No options available";break;case"loading":this.vn=e,this.applyLoadingState()}}applyLoadingState(){const t=this.shadowRoot;if(!t)return;const n=this.vn?v():null;t.querySelectorAll(".dropdown-options-wrapper").forEach(t=>{if(t.classList.toggle("loading",this.vn),this.vn){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.kn.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.kn.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),this.updateValidity(),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=_t({anchorRect:i,popupWidth:a,popupHeight:s,align:this.getProperty("align")}),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(!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.An=new Et(n,{vertical:!0}),this.An.trackY&&e.appendChild(this.An.trackY))}On(){this.An&&(this.An.trackY?.remove(),this.An.destroy(),this.An=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"}-${Bn(this)}`;this.fn=i,an(i),n.showModal(),n.classList.add("open"),this.calculatePosition(),this.kn.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.kn.filteredTags=r,this.kn.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.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.kn.open=!1,this.kn.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.kn.search;this.kn.search="";const r=t.querySelector(".dropdown-search-input");if(r&&(r.value=""),this.pn)s&&(null!==this.Mn&&(clearTimeout(this.Mn),this.Mn=null),this.fireSearchEvent(""));else{const t=this.getTagElements().map(t=>this.getTagData(t));this.kn.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"}-${Bn(this)}`;this.fn=i,an(i),n.showModal(),n.classList.add("open"),this.kn.open=!0;const o=this.getTagElements().map(t=>this.getTagData(t));this.kn.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.fn&&(ln(this.fn),this.fn=null),this.kn.open=!1,this.kn.highlightedIndex=-1;const i=""!==this.kn.search;this.kn.search="";const o=t.querySelector(".mobile-search-input");o&&(o.value=""),this.pn?i&&(null!==this.Mn&&(clearTimeout(this.Mn),this.Mn=null),this.fireSearchEvent("")):this.getTagElements().forEach(t=>t.removeAttribute("hidden")),this.fireCloseEvent()}handleStubClick(t){t.preventDefault(),t.stopPropagation(),this.q||this.dn||this.openDropdown()}handleClearClick(t){t.preventDefault(),t.stopPropagation(),this.q||this.dn||this.clear()}handleStubKeydown(t){this.q||this.dn||this.kn.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.kn.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.bn)return!1;const t=(this.kn.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.gn?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.kn.mode?this.closeMobileModal():this.closeDropdown(),!0;const c=this.getSelectedValues();return this.updateComponentValue([...c,a],!0,"create",a),this.clearSearchAfterCreate(),!0}clearSearchAfterCreate(){this.kn.search="",this.kn.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.kn.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.kn.search=n,this.pn)return void this.dispatchSearchEvent(n);const e=this.getTagElements().map(t=>this.getTagData(t)),i=this.filterTags(e,n);this.kn.filteredTags=i,this.kn.highlightedIndex=-1,this.updateTagVisibility(i,e),this.updateOptionsVisibility(i.length>0),this.updateMobileSelectedState(),this.clearHighlights(e)}handleKeyboard(t){if(!this.kn.open)return;const n=this.shadowRoot.querySelector(".dropdown-search-input");if(t.target!==n&&document.activeElement===n)return;const e=this.kn.filteredTags,i=e.length,o=this.kn.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.kn.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.kn.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.Mn&&(clearTimeout(this.Mn),this.Mn=null),this.Tn>0?this.Mn=window.setTimeout(()=>{this.fireSearchEvent(t),this.Mn=null},this.Tn):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.kn.mode,element:this},bubbles:!0,composed:!0})),this.pn&&this.fireSearchEvent("")}fireCloseEvent(){this.dispatchEvent(new CustomEvent("close",{detail:{mode:this.kn.mode,element:this},bubbles:!0,composed:!0}))}dispatchChangeEvent(t){this.dispatchEvent(new CustomEvent("change",{detail:t,bubbles:!0,cancelable:!0}))}render(){this.kn.mode=Pn()?"mobile":"desktop","mobile"===this.kn.mode?this.renderMobile():this.renderDesktop(),this.updateSearchVisibility(),this.applyLoadingState(),this.updateValidity()}updateValidity(){if(this.disabled)this.v.setValidity({});else if(this.required&&0===this.getSelectedValues().length){const t=this.shadowRoot?.querySelector(".select-stub");this.v.setValidity({valueMissing:!0},"Please select a value",t??void 0)}else this.v.setValidity({})}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.zn=this.handleStubClick.bind(this),n.addEventListener("click",this.zn),n.addEventListener("keydown",this.handleStubKeydown.bind(this)));const o=t.querySelector(".select-clear");o?.addEventListener("click",this.handleClearClick.bind(this)),this.setupTriggerSlot(),e&&(this.$n=this.handleTagClick.bind(this),e.addEventListener("click",this.$n)),i&&(this.Cn=this.handleSearchInput.bind(this),this.Sn=this.blockSearchClick.bind(this),i.addEventListener("input",this.Cn),i.addEventListener("click",this.Sn));const s=t.querySelector(".dropdown-dialog");s&&s.addEventListener("click",t=>{t.target===s&&this.closeDropdown()}),this.En=this.handleKeyboard.bind(this),document.addEventListener("keydown",this.En)}buildStubClasses(){const t=[this.yn];return this.q&&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-"+Bn(this),i="select-label-"+Bn(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">${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.cn?`aria-labelledby="${i}"`:""}\n tabindex="${this.q?"-1":"0"}"\n ${this.q?'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 <button class="select-clear" type="button" aria-label="Clear selection" hidden>\n ${Un}\n </button>\n <div class="dropdown-chevron">\n ${Wn}\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 ${Yn}\n </div>\n <input\n class="dropdown-search-input ${this.yn}"\n type="text"\n placeholder="Search..."\n ${this.q?"disabled":""}\n />\n <div class="dropdown-search-chevron">\n ${Wn}\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-"+Bn(this),i="select-label-"+Bn(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">${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.cn?`aria-labelledby="${i}"`:""}\n tabindex="${this.q?"-1":"0"}"\n ${this.q?'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 <button class="select-clear" type="button" aria-label="Clear selection" hidden>\n ${Un}\n </button>\n <div class="dropdown-chevron">\n ${Wn}\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 ${Yn}\n </div>\n <input\n class="mobile-search-input ${this.yn}"\n type="text"\n placeholder="${this.cn?`Search ${this.cn}...`:"Search..."}"\n autofocus\n ${this.q?"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.wn}</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.xn}</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)));const r=t.querySelector(".select-clear");r?.addEventListener("click",this.handleClearClick.bind(this)),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.q||this.dn||this.openMobileModal()}handleMobileStubKeydown(t){this.q||this.dn||this.kn.open||"Enter"!==t.key&&" "!==t.key&&"ArrowDown"!==t.key||(t.preventDefault(),this.openMobileModal())}handleMobileTagClick(t){this.handleTagClick(t)}updateMobileSelectedState(){if("mobile"!==this.kn.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.wn} (${e})`)}}shouldShowSearch(){return!!this.pn||!!this.bn||"always"===this.mn||"never"!==this.mn&&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.kn.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=t.querySelector(".select-clear");o&&(o.hidden=!(e>0&&this.un&&!this.q&&!this.dn));const s=!this.rn&&e>0?n[0]:null;this.syncSelectedClone(s),t.classList.toggle("has-clone",null!==s);const r=t.querySelector(".dropdown-placeholder");r&&(r.hidden=null!==s,e>0&&this.rn&&!this.an?(r.textContent=this.getSelectedItems(n).map(t=>t.label).join(", "),r.classList.remove("placeholder-shown")):(r.textContent=this.ln,r.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)}clear(){this.updateComponentValue([],!0,"clear",null)}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 clearable(){return this.getProperty("clearable")}set clearable(t){this.setProperty("clearable",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 align(){return this.getProperty("align")}set align(t){this.setProperty("align",t)}get flavor(){return this.getProperty("flavor")}set flavor(t){this.setProperty("flavor",t)}get form(){return this.v.form}};Gn.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},clearable:{type:"boolean",visual:!0,default:!0,aliases:{"not-clearable":!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"},align:{type:"string",visual:!0,default:"start",validate:t=>["start","end"].includes(t),coerce:t=>"end"===t?"end":"start"},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 Kn=Gn;function Zn(t,n){return t.replace(/\{([\w-]+)\}/g,(t,e)=>n[e]??t)}customElements.get("ty-select")||customElements.define("ty-select",Kn);class TySelectedOptions extends HTMLElement{constructor(){super(...arguments),this.Nn=null,this._n=()=>this.renderChips(),this.Dn=null,this.Rn=null,this.Fn=null,this.qn="contents",this.Vn=()=>{this.qn=this.style.display||"contents",this.style.display="none"},this.Pn=()=>{this.style.display=this.qn}}static get observedAttributes(){return["for"]}connectedCallback(){this.style.display||(this.style.display="contents"),this.bind(),this.renderChips(),this.Dn=new MutationObserver(()=>{this.template()!==this.Fn&&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.Nn&&(this.unbind(),this.Nn=t,this.Nn?.addEventListener("change",this._n),this.Nn?.addEventListener("open",this.Vn),this.Nn?.addEventListener("close",this.Pn),this.Nn&&(this.Rn=new MutationObserver(()=>this.renderChips()),this.Rn.observe(this.Nn,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["selected"]})))}unbind(){this.Nn?.removeEventListener("change",this._n),this.Nn?.removeEventListener("open",this.Vn),this.Nn?.removeEventListener("close",this.Pn),this.Rn?.disconnect(),this.Rn=null,this.Nn=null,this.style.display=this.qn}values(){return(this.Nn?.value??"").split(",").map(t=>t.trim()).filter(Boolean)}template(){return this.querySelector(":scope > template")}context(t){const n=this.Nn?.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=Zn(s.textContent,e));else{const t=s;for(const n of Array.from(t.attributes)){if(!n.value.includes("{"))continue;const i=Zn(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.Fn=t,!this.Nn)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.Nn)return;const n=this.Nn;"function"==typeof n.deselectValue?n.deselectValue(t):(n.value=this.values().filter(n=>n!==t).join(","),this.renderChips())}}customElements.get("ty-selected-options")||customElements.define("ty-selected-options",TySelectedOptions),customElements.get("ty-selected-tags")||customElements.define("ty-selected-tags",class extends TySelectedOptions{});const Xn=new WeakMap,Jn=new WeakMap;function Qn(t){return{width:t.getAttribute("width")||"100%",height:t.getAttribute("height")||"400px",active:t.getAttribute("active"),placement:t.getAttribute("placement")||"top"}}function te(t){return Array.from(t.querySelectorAll("ty-tab"))}function ne(t){return t.getAttribute("id")}function ee(t,n){const e=ne(n);return e&&function(t,n){return null!==t.querySelector(`[slot='label-${n}']`)}(t,e)?"slot":"text"}function ie(t){return t.hasAttribute("disabled")}function oe(t,n){const e=t.findIndex(t=>ne(t)===n);return 0>e?void 0:e}function se(t,n){const e=t.getAttribute("active");return e&&void 0!==oe(n,e)?e:n.length>0?ne(n[0]):null}function re(t,n){t.setAttribute("active",n)}function ae(t,n,e){e.preventDefault(),e.stopPropagation(),re(t,n)}function le(t){const n=Xn.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.tabKeyClickHandlers.forEach((t,n)=>{const i=e.querySelector(`[data-tab-id='${n}']`);i&&i.removeEventListener("click",t)}),n.tabClickHandlers.clear(),n.tabKeyClickHandlers.clear())}function ce(t,n,e){le(t);const i={tabClickHandlers:new Map,tabKeyClickHandlers:new Map};e.forEach(e=>{const o=ne(e);if(!o)return;const s=n.querySelector(`[data-tab-id='${o}']`);if(s){const n=n=>ae(t,o,n),e=n=>{0===n.detail&&ae(t,o,n)};s.addEventListener("pointerdown",n),s.addEventListener("click",e),i.tabClickHandlers.set(o,n),i.tabKeyClickHandlers.set(o,e)}}),Xn.set(t,i)}function de(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 he(t,n,e){te(t).forEach(i=>{const o=ne(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 ue(t,n){te(t).forEach(t=>{const e=ne(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 pe(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 be(t){const n=t.shadowRoot;if(!n)return;const e=n.querySelector(".tab-buttons");if(!e)return;!function(t){t.querySelector(".tab-overflow-trigger")?.remove()}(n);const i=Array.from(e.querySelectorAll(".tab-button"));if(i.forEach(t=>t.classList.remove("overflow-hidden")),0===i.length)return;const o=e.clientWidth;let s=0,r=i.length;for(let h=0;i.length>h;h++)if(s+=i[h].offsetWidth,s>o){r=h;break}if(r>=i.length)return;s=0,r=i.length;for(let h=0;i.length>h;h++)if(s+=i[h].offsetWidth,s>o-40){r=h;break}r=Math.max(r,1);const a=te(t),l=se(t,a),c=new Set(i.slice(r)),d=l?i.find(t=>t.dataset.tabId===l):void 0;if(d&&c.has(d)){const t=i[r-1];c.delete(d),c.add(t)}i.forEach(t=>t.classList.toggle("overflow-hidden",c.has(t))),function(t,n,e,i){if(0===e.length)return;const o=new Map(i.map(t=>[ne(t),t])),s=document.createElement("button");s.className="tab-overflow-trigger",s.type="button",s.setAttribute("aria-label",e.length+" more tabs"),s.textContent="⋯";const r=document.createElement("ty-popup");r.setAttribute("placement","bottom");const a=document.createElement("div");a.className="tab-overflow-menu",a.setAttribute("role","menu"),e.forEach(n=>{const e=n.dataset.tabId,i=e?o.get(e):void 0;if(!e||!i)return;const s=document.createElement("button");s.type="button",s.className="tab-overflow-item",s.setAttribute("role","menuitem"),s.textContent=function(t,n){const e=ne(n);if(e&&"slot"===ee(t,n)){const n=t.querySelector(`[slot='label-${e}']`);return n?.textContent?.trim()||e}return n.getAttribute("label")||"Tab"}(t,i),ie(i)?s.disabled=!0:s.addEventListener("click",()=>{re(t,e),r.closePopup?.()}),a.appendChild(s)}),r.appendChild(a),s.appendChild(r),n.appendChild(s)}(t,e,i.filter(t=>c.has(t)),a)}function ge(t){const n=t.shadowRoot;if(!n)return;const{width:e,height:i,placement:o}=Qn(t),r=te(t),a=se(t,r),l=a?oe(r,a)??0:0;r.forEach(t=>{const n=ne(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: var(--ty-local-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.tab-button.overflow-hidden {\n display: none;\n}\n\n/* ===================================== */\n/* Overflow "more" trigger + menu */\n/* ===================================== */\n\n.tab-overflow-trigger {\n flex-shrink: 0;\n width: 40px;\n min-width: 40px;\n padding: 6px;\n border: none;\n background: transparent;\n cursor: pointer;\n color: var(--ty-text-soft);\n font-size: 18px;\n line-height: 1;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n position: relative;\n z-index: 10;\n}\n\n.tab-overflow-trigger:hover {\n color: var(--ty-text-strong);\n}\n\n.tab-overflow-trigger:focus-visible {\n outline: 2px solid var(--ty-color-primary);\n outline-offset: -2px;\n}\n\n.tab-overflow-menu {\n display: flex;\n flex-direction: column;\n min-width: 160px;\n max-height: 300px;\n overflow-y: auto;\n padding: var(--ty-spacing-2, 4px);\n background: var(--ty-surface-floating);\n border-radius: var(--ty-radius-md);\n box-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\n.tab-overflow-item {\n padding: var(--ty-spacing-2, 6px) var(--ty-spacing-3, 12px);\n border: none;\n background: transparent;\n text-align: left;\n cursor: pointer;\n border-radius: var(--ty-radius-md);\n color: var(--ty-text);\n font: inherit;\n font-size: var(--ty-font-sm);\n white-space: nowrap;\n}\n\n.tab-overflow-item:hover {\n background: var(--ty-bg-neutral-soft);\n color: var(--ty-text-strong);\n}\n\n.tab-overflow-item[disabled] {\n opacity: 0.5;\n cursor: not-allowed;\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.querySelector(".tab-overflow-trigger")?.remove(),d.querySelectorAll(".tab-button").forEach(t=>t.remove());const e=function(t,n,e){return n.map(n=>{const i=ne(n);if(!i)return"";const o=ee(t,n),s="text"===o?n.getAttribute("label")||"Tab":"",r=ie(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)}),ce(t,n,r),he(t,n,a||""),requestAnimationFrame(()=>{const e=n.querySelector(".tab-buttons");e&&t.style.setProperty("--buttons-height",e.offsetHeight+"px"),de(t,l),a&&pe(t,a),be(t)}),a&&ue(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=ne(n);if(!i)return"";const o=ee(t,n),s="text"===o?n.getAttribute("label")||"Tab":"",r=ie(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"),de(t,l),a&&pe(t,a),be(t)}),ce(t,n,r),he(t,n,a||""),function(t){const n=Jn.get(t);n&&n.disconnect();const e=new ResizeObserver(n=>{const e=n[0],{width:i}=Qn(t),o=te(t),s=se(t,o),r=s?oe(o,s):0;i.includes("%")&&t.style.setProperty("--tabs-width",e.contentRect.width+"px"),void 0!==r&&de(t,r),s&&pe(t,s),be(t)});e.observe(t),Jn.set(t,e)}(t),a&&ue(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(){ge(this)}disconnectedCallback(){le(this),function(t){const n=Jn.get(t);n&&(n.disconnect(),Jn.delete(t))}(this)}attributeChangedCallback(t,n,e){"active"===t?(e&&function(t,n,e){const i=te(t),o=t.shadowRoot;if(!o)return;const s=e?oe(i,e):void 0,r=oe(i,n);if(e===n||void 0===r)return;t.style.setProperty("--active-index",r+""),de(t,r),he(t,o,n),ue(t,n),pe(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),ge(this)):ge(this)}}customElements.get("ty-tabs")||customElements.define("ty-tabs",TyTabs);const me=`\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.Qt=null,this.attachShadow({mode:"open"})}static get observedAttributes(){return["id","label","disabled"]}connectedCallback(){this.Hn()}disconnectedCallback(){this.tn()}attributeChangedCallback(t,n,e){this.Hn()}Hn(){const t=this.shadowRoot;if(!t)return;const n=this.getAttribute("id");t.querySelector(".tab-wrapper")||(s(t,{css:me,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&&St()&&(t.classList.add("ty-custom-scroll"),this.Qt=new Et(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 ve=new WeakMap,fe=new WeakMap;function ye(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 we(t){return Array.from(t.querySelectorAll("ty-step"))}function xe(t){return t.getAttribute("id")}function ke(t){const n=t.getAttribute("completed")||"";return n.trim()?new Set(n.split(",").map(t=>t.trim()).filter(Boolean)):new Set}function ze(t,n){const e=t.findIndex(t=>xe(t)===n);return 0>e?void 0:e}function $e(t,n){const e=t.getAttribute("active");return e&&void 0!==ze(n,e)?e:n.length>0?xe(n[0]):null}function Ce(t,n){return t.length>1&&n?t.findIndex(t=>xe(t)===n)/(t.length-1)*100:0}function Se(t){const n=ve.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 Ee(t,n,e){Se(t);const i={stepClickHandlers:new Map};e.forEach(e=>{const o=xe(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=we(t),o=i.findIndex(t=>xe(t)===n);if(0>o)return;const s=$e(t,i),r=s?ze(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)}}),ve.set(t,i)}function Te(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 Me(t){const n=t.shadowRoot;if(!n)return;const e=n.querySelector(".progress-overlay");if(!e)return;const i=we(t),o=$e(t,i);ke(t);const s=Ce(i,o);e.style.width=s+"%"}function Ae(t,n,e){const i=we(t),o=ke(t);e&&i.findIndex(t=>xe(t)===e),i.forEach(i=>{const s=xe(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=Ie(i,s,e,o);a.setAttribute("data-state",t)}const c=t.querySelector(`[slot='indicator-${s}']`);c&&c.setAttribute("data-active",l+"")})}function De(t,n){we(t).forEach(t=>{const e=xe(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 Ie(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 Oe(t,n,e,i){e&&n.findIndex(t=>xe(t)===e);const o=n.map((n,o)=>{const s=xe(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=Ie(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=Ce(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 Le(t){const n=t.shadowRoot;if(!n)return;const{width:e,height:i}=ye(t),o=we(t),r=$e(t,o),a=r?ze(o,r)??0:0,l=ke(t);o.forEach(t=>{const n=xe(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: var(--ty-local-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 /* Derived from the accent this circle actually paints, not from\n --ty-solid-success-fg: the two diverge in dark mode (--ty-solid-l\n dims solid fills by 0.25 L), which stranded white text at 3.5:1. */\n color: oklch(\n from var(--ty-wizard-completed-accent)\n clamp(0, (var(--ty-solid-fg-threshold, 0.6) - l) * 1000, 1) 0 0\n );\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: oklch(\n from var(--ty-wizard-active-accent)\n clamp(0, (var(--ty-solid-fg-threshold, 0.6) - l) * 1000, 1) 0 0\n );\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: oklch(\n from var(--ty-wizard-error-accent)\n clamp(0, (var(--ty-solid-fg-threshold, 0.6) - l) * 1000, 1) 0 0\n );\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: var(--ty-local-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: var(--ty-local-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=Oe(t,o,r,l),i=document.createElement("div");i.innerHTML=e,c.insertBefore(i.firstElementChild,h),Ee(t,n,o),Ae(t,n,r||""),requestAnimationFrame(()=>{const e=n.querySelector(".step-indicators-wrapper");e&&t.style.setProperty("--ty-wizard-indicators-height",e.offsetHeight+"px"),Te(t,a),Me(t)}),r&&De(t,r)}else n.innerHTML=`\n <div class="wizard-container">\n ${Oe(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"),Te(t,a),Me(t)}),Ee(t,n,o),Ae(t,n,r||""),function(t){const n=fe.get(t);n&&n.disconnect();const{width:e}=ye(t);if(e.includes("%")){const n=new ResizeObserver(n=>{const e=n[0].contentRect.width,i=we(t),o=$e(t,i),s=o?ze(i,o):0;t.style.setProperty("--ty-wizard-width",e+"px"),void 0!==s&&Te(t,s)});n.observe(t),fe.set(t,n)}}(t),r&&De(t,r)}class TyWizard extends HTMLElement{static get observedAttributes(){return["width","height","active","completed","orientation"]}constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){Le(this)}disconnectedCallback(){Se(this),function(t){const n=fe.get(t);n&&(n.disconnect(),fe.delete(t))}(this)}attributeChangedCallback(t,n,e){"active"===t?(e&&function(t,n){const e=we(t),i=t.shadowRoot;if(!i)return;const o=$e(t,e),s=o?ze(e,o):void 0,r=ze(e,n);if(o===n||void 0===r)return;t.style.setProperty("--ty-wizard-active-index",r+""),Te(t,r),Ae(t,i,n),Me(t),De(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),Le(this)):Le(this)}}customElements.get("ty-wizard")||customElements.define("ty-wizard",TyWizard);const Ne=`\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.Qt=null,this.attachShadow({mode:"open"})}static get observedAttributes(){return["id","label","description","disabled","status"]}connectedCallback(){this.Hn()}disconnectedCallback(){this.tn()}attributeChangedCallback(t,n,e){this.Hn()}Hn(){const t=this.shadowRoot;if(!t)return;const n=this.getAttribute("id");t.querySelector(".step-wrapper")||(s(t,{css:Ne,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&&St()&&(t.classList.add("ty-custom-scroll"),this.Qt=new Et(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 _e=(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`},Re=`\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: var(--ty-local-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=>_e(t)).join("")}\n`;function Fe(t){if(!Number.isInteger(t)||1>t||t>12)throw new RangeError(`Invalid month: ${t}. Must be an integer between 1 and 12.`)}function qe(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 Ve(t,n){const e=new Date(t);return e.setDate(e.getDate()+n),e}function Pe(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 He(t){return t instanceof HTMLElement}function je(t){if(!t)return null;const n=Pe(t);return n?Date.UTC(n.year,n.month-1,n.day):null}function Be(t){if(!t||""===t)return null;const n=t+"";return/^\d+(\.\d+)?$/.test(n)?n+"px":n}class TyCalendarMonth extends HTMLElement{constructor(){super(),this.jn="en-US",this.yn="md",this.D=null,this.Bn=null,this.Wn=[];const t=new Date;this.Yn=t.getFullYear(),this.Un=t.getMonth()+1,this.attachShadow({mode:"open"})}static get observedAttributes(){return["locale","size","min","max","flavor"]}connectedCallback(){this.Un||(this.Un=(new Date).getMonth()+1),this.Yn||(this.Yn=(new Date).getFullYear()),this.jn||(this.jn=this.getAttribute("locale")||"en-US");const t=this.getAttribute("size");!t||"sm"!==t&&"md"!==t&&"lg"!==t||(this.yn=t);const n=this.dayContentFn;n&&!this.Gn&&(this.Gn=n,delete this.dayContentFn);const e=this.customCSS;e&&!this.Kn&&(this.Kn=e,delete this.customCSS),this.J=J(this,()=>{this.render()}),this.I(),this.render()}disconnectedCallback(){this.J&&(this.J(),this.J=void 0)}attributeChangedCallback(t,n,e){"locale"===t?(this.jn=e||"en-US",this.render()):"size"===t?"sm"!==e&&"md"!==e&&"lg"!==e||(this.yn=e,this.render()):"min"===t||"max"===t?(this["min"===t?"Zn":"Xn"]=e??void 0,this.render()):"flavor"===t&&this.I()}I(){this.D=b(this.shadowRoot,this.D,this.getAttribute("flavor"),({base:t})=>(t=>_e(t,"neutral"))(t))}get displayYear(){return this.Yn}set displayYear(t){this.Yn!==t&&(this.Yn=t,this.Bn=null,this.render())}get displayMonth(){return this.Un}set displayMonth(t){this.Un!==t&&(this.Un=t,this.Bn=null,this.render())}get locale(){return X(this,this.getAttribute("locale"))}set locale(t){this.jn!==t&&(this.jn=t,this.render())}get size(){return this.yn}set size(t){this.yn!==t&&(this.yn=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.Jn}set width(t){this.Jn!==t&&(this.Jn=t,this.applyWidthProperties())}get minWidth(){return this.Qn}set minWidth(t){this.Qn!==t&&(this.Qn=t,this.applyWidthProperties())}get maxWidth(){return this.te}set maxWidth(t){this.te!==t&&(this.te=t,this.applyWidthProperties())}get dayContentFn(){return this.Gn}set dayContentFn(t){this.Gn!==t&&(this.Gn=t,this.render())}get customCSS(){return this.Kn}set customCSS(t){this.Kn!==t&&(this.Kn=t,this.applyCustomCSS())}get min(){return this.Zn}set min(t){this.Zn!==t&&(this.Zn=t,this.render())}get max(){return this.Xn}set max(t){this.Xn!==t&&(this.Xn=t,this.render())}get value(){return this.R}set value(t){const n=t??void 0;this.R!==n&&(this.R=n,this.render())}applyWidthProperties(){const t=Be(this.Jn),n=Be(this.Qn),e=Be(this.te);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.Kn||!this.shadowRoot)return;const t=this.shadowRoot.adoptedStyleSheets;t.includes(this.Kn)||(this.shadowRoot.adoptedStyleSheets=[...t,this.Kn])}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.Gn?this.Gn(t):function(t){return""+t.dayInMonth}(t);if(this.Gn&&o&&!He(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:He(o)&&i.appendChild(o),i.setAttribute("role","gridcell"),i.setAttribute("aria-label",new Intl.DateTimeFormat(this.jn,{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:Re,id:"ty-calendar-month"}),this.applyCustomCSS(),this.applyWidthProperties(),this.R){const t=new Date(this.R);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),Fe(n),function(t,n,e,i,o){const s=[];for(let r=0;42>r;r++){const n=Ve(t,r);s.push(qe(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.Yn,this.Un,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=Ve(i,n);return e.format(o)}),[s,...r]=o;return[...r,s]}(this.jn,"short");t.innerHTML="";const o=document.createElement("div");o.className="calendar-flex-container calendar-size-"+this.yn,o.setAttribute("role","grid"),o.setAttribute("aria-label",new Intl.DateTimeFormat(this.jn,{month:"long",year:"numeric"}).format(new Date(this.Yn,this.Un-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=je(this.Zn),c=je(this.Xn),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.Wn=[];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.Wn[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.Wn[i]?.setAttribute("tabindex","-1"),this.Bn=o;const s=this.Wn[o];s&&(s.setAttribute("tabindex","0"),s.focus())}),t.appendChild(o)}}customElements.get("ty-calendar-month")||customElements.define("ty-calendar-month",TyCalendarMonth);const We='\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: var(--ty-local-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',Ye=class t extends i{constructor(){super();const t=new Date;this.kn={displayMonth:t.getMonth()+1,displayYear:t.getFullYear()},s(this.shadowRoot,{css:We,id:"ty-calendar-navigation"})}onConnect(){this.kn.displayMonth=this.displayMonth,this.kn.displayYear=this.displayYear,this.J=J(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.kn.displayMonth=e;break;case"display-year":this.kn.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=Pe(this.min),e=Pe(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.kn.displayYear,this.kn.displayMonth),i=this.clampIndex(e+n);i!==e&&this.emitChangeEvent(i%12+1,Math.floor(i/12))}isNavDisabled(n){const e=t.monthIndex(this.kn.displayYear,this.kn.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:We,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"){Fe(t);const i=new Date(2024,t-1,1);return new Intl.DateTimeFormat(n,{month:e}).format(i)}(this.kn.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.kn.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)}};Ye.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 Ue=Ye;function Ge(t){return t&&/^\d{4}$/.test(t)?parseInt(t,10):null}function Ke(t){if(!t||!/^\d{1,2}$/.test(t))return null;const n=parseInt(t,10);return 1>n||n>12?null:n}function Ze(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 Xe(t,n,e){return`${t}-${(""+n).padStart(2,"0")}-${(""+e).padStart(2,"0")}`}customElements.get("ty-calendar-navigation")||customElements.define("ty-calendar-navigation",Ue);const Je=class extends HTMLElement{constructor(){super(),this.ne=!0,this.ee=!1,this.yn="md",this.ie="primary";const t=function(){const t=new Date;return{year:t.getFullYear(),month:t.getMonth()+1,day:t.getDate()}}();this.kn={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.Gn&&(this.Gn=t,delete this.dayContentFn);const n=this.customCSS;n&&!this.Kn&&(this.Kn=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.kn.selectedYear=n,this.kn.selectedMonth=e,this.kn.selectedDay=i,this.kn.displayYear=n,this.kn.displayMonth=e,this.ee||(this.setAttribute("year",""+n),this.setAttribute("month",""+e),this.setAttribute("day",""+i))}delete this.value}this.render(),this.updateFormValue(),this.J=J(this,()=>{this.render()})}disconnectedCallback(){this.J&&(this.J(),this.J=void 0),this.oe=void 0,this.se=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.ne="false"!==e,this.render();break;case"stateless":this.ee=null!==e&&"false"!==e;break;case"locale":this.syncChildComponents();break;case"size":"sm"!==e&&"md"!==e&&"lg"!==e||(this.yn=e,this.Jn=void 0,this.removeAttribute("width"),this.syncChildComponents());break;case"width":this.Jn=e||void 0,e&&(this.yn="md",this.removeAttribute("size")),this.syncChildComponents();break;case"name":this.updateFormValue();break;case"min":case"max":this["min"===t?"Zn":"Xn"]=e||void 0,this.syncChildComponents(),this.updateValidity();break;case"flavor":this.ie=e||"primary",this.syncChildComponents()}}get min(){return this.Zn}set min(t){t?this.setAttribute("min",t):this.removeAttribute("min")}get max(){return this.Xn}set max(t){t?this.setAttribute("max",t):this.removeAttribute("max")}get flavor(){return this.ie}set flavor(t){t?this.setAttribute("flavor",t):this.removeAttribute("flavor")}get year(){return this.kn.selectedYear}set year(t){void 0!==t?this.ee?(this.kn.displayYear=t,this.setAttribute("year",""+t)):(this.kn.selectedYear=t,this.kn.displayYear=t,this.setAttribute("year",""+t)):(this.ee||delete this.kn.selectedYear,this.removeAttribute("year")),this.syncChildComponents(),this.ee||this.updateFormValue()}get month(){return this.kn.selectedMonth}set month(t){void 0!==t?this.ee?(this.kn.displayMonth=t,this.setAttribute("month",""+t)):(this.kn.selectedMonth=t,this.kn.displayMonth=t,this.setAttribute("month",""+t)):(this.ee||delete this.kn.selectedMonth,this.removeAttribute("month")),this.syncChildComponents(),this.ee||this.updateFormValue()}get day(){return this.kn.selectedDay}set day(t){void 0!==t?(this.kn.selectedDay=t,this.setAttribute("day",""+t)):(delete this.kn.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.ne}set showNavigation(t){this.ne=t,this.setAttribute("show-navigation",""+t)}get stateless(){return this.ee}set stateless(t){this.ee=t,t?this.setAttribute("stateless",""):this.removeAttribute("stateless")}get size(){return this.yn}set size(t){this.yn!==t&&(this.yn=t,this.Jn=void 0,this.removeAttribute("width"),this.setAttribute("size",t),this.syncChildComponents())}get width(){return this.Jn}set width(t){this.Jn!==t&&(this.Jn=t,t?(this.yn="md",this.removeAttribute("size"),this.setAttribute("width",t)):this.removeAttribute("width"),this.syncChildComponents())}get dayContentFn(){return this.Gn}set dayContentFn(t){this.Gn=t,this.syncChildComponents()}get customCSS(){return this.Kn}set customCSS(t){this.Kn=t,this.syncChildComponents()}get value(){const{selectedYear:t,selectedMonth:n,selectedDay:e}=this.kn;return t&&n&&e?Xe(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.kn.selectedYear=t,this.kn.selectedMonth=e,this.kn.selectedDay=i,this.kn.displayYear=t,this.kn.displayMonth=e,this.ee||(this.setAttribute("year",""+t),this.setAttribute("month",""+e),this.setAttribute("day",""+i))}}else delete this.kn.selectedYear,delete this.kn.selectedMonth,delete this.kn.selectedDay,this.ee||(this.removeAttribute("year"),this.removeAttribute("month"),this.removeAttribute("day"));this.syncChildComponents(),this.ee||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.Zn=this.getAttribute("min")||void 0,this.Xn=this.getAttribute("max")||void 0;const a=Ge(t);a&&(this.kn.displayYear=a);const l=Ke(n);if(l&&(this.kn.displayMonth=l),a&&l){const t=Ze(e,a,l);t&&(this.kn.selectedYear=a,this.kn.selectedMonth=l,this.kn.selectedDay=t)}i&&(this.ne="false"!==i),null!==o&&(this.ee="false"!==o),!s||"sm"!==s&&"md"!==s&&"lg"!==s||(this.yn=s),r&&(this.Jn=r)}syncStateFromAttributes(){const t=this.getAttribute("year"),n=this.getAttribute("month"),e=this.getAttribute("day"),i=Ge(t),o=Ke(n);if(i&&(this.kn.displayYear=i),o&&(this.kn.displayMonth=o),i&&o){const t=Ze(e,i,o);t?(this.kn.selectedYear=i,this.kn.selectedMonth=o,this.kn.selectedDay=t):(delete this.kn.selectedYear,delete this.kn.selectedMonth,delete this.kn.selectedDay)}else delete this.kn.selectedYear,delete this.kn.selectedMonth,delete this.kn.selectedDay}syncChildComponents(){if(this.oe&&(this.oe.displayMonth=this.kn.displayMonth,this.oe.displayYear=this.kn.displayYear,this.oe.locale=this.locale,this.oe.size=this.yn,this.oe.min=this.Zn??"",this.oe.max=this.Xn??"",this.oe.width=this.Jn),this.se){this.se.displayMonth=this.kn.displayMonth,this.se.displayYear=this.kn.displayYear,this.se.locale=this.locale,this.se.size=this.yn,this.se.min=this.Zn,this.se.max=this.Xn,this.se.flavor=this.ie,this.se.width=this.Jn,this.Gn&&(this.se.dayContentFn=this.Gn),this.Kn&&(this.se.customCSS=this.Kn);const{selectedYear:t,selectedMonth:n,selectedDay:e}=this.kn;this.se.value=t&&n&&e?new Date(t,n-1,e).getTime():null}}updateFormValue(){if(this.ee)return;if(!this.v)return;const t=this.getAttribute("name"),{selectedYear:n,selectedMonth:e,selectedDay:i}=this.kn;if(t&&n&&e&&i){const t=Xe(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.kn;if(t&&n&&e){const i=Date.UTC(t,n-1,e),o=this.Zn?Pe(this.Zn):null,s=this.Xn?Pe(this.Xn):null;if(o&&i<Date.UTC(o.year,o.month-1,o.day))return void this.v.setValidity({rangeUnderflow:!0},`Date must be ${this.Zn} 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.Xn} or earlier`)}this.v.setValidity({})}handleNavigationChange(t){t.preventDefault(),t.stopPropagation();const{month:n,year:e}=t.detail;this.kn.displayMonth=n,this.kn.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.ee?this.dispatchEvent(new CustomEvent("day-click",{detail:t.detail,bubbles:!0,composed:!0,cancelable:!0})):(this.kn.selectedYear=e,this.kn.selectedMonth=i,this.kn.selectedDay=o,this.kn.displayYear=e,this.kn.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.se&&"function"==typeof this.se.refresh&&this.se.refresh()}createNavigation(){const t=document.createElement("ty-calendar-navigation");return t.displayMonth=this.kn.displayMonth,t.displayYear=this.kn.displayYear,t.locale=this.locale,t.size=this.yn,t.min=this.Zn??"",t.max=this.Xn??"",this.Jn&&(t.width=this.Jn),t.addEventListener("change",t=>this.handleNavigationChange(t)),this.oe=t,t}createMonthDisplay(){const t=document.createElement("ty-calendar-month");t.displayMonth=this.kn.displayMonth,t.displayYear=this.kn.displayYear,t.locale=this.locale,t.size=this.yn,t.min=this.Zn,t.max=this.Xn,t.flavor=this.ie,this.Jn&&(t.width=this.Jn);const{selectedYear:n,selectedMonth:e,selectedDay:i}=this.kn;return n&&e&&i&&(t.value=new Date(n,e-1,i).getTime()),this.Gn&&(t.dayContentFn=this.Gn),this.Kn&&(t.customCSS=this.Kn),t.addEventListener("day-click",t=>this.handleDayClick(t)),this.se=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.ne){const t=this.createNavigation();n.appendChild(t)}const e=this.createMonthDisplay();n.appendChild(e),t.appendChild(n)}};Je.formAssociated=!0;let Qe=Je;customElements.get("ty-calendar")||customElements.define("ty-calendar",Qe);const ti=(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`},ni=`\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=>ti(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: var(--ty-local-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`,ei="<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>",ii="<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>",oi=new WeakMap;let si=0;function ri(t){let n=oi.get(t);return void 0===n&&(n=++si,oi.set(t,n)),n}function ai(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 li(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 ci(t){if(!t.year||!t.month||!t.day)return null;const n=li(t);return n?n.toISOString():null}function di(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 hi(t,n){return`${(""+t).padStart(2,"0")}:${(""+n).padStart(2,"0")}`}function ui(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 pi{constructor(t,n,e=0,i=0){this.element=t,this.datePickerElement=n;const o=hi(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=ui(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=ui(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:hi(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=hi(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 bi=class extends i{constructor(){super(),this.kn={withTime:!1,open:!1},this.re=0,this.D=null,s(this.shadowRoot,{css:ni,id:"ty-date-picker"})}onConnect(){this.initializeState(),this.render(),this.J=J(this,()=>{this.render()}),this.I()}I(){this.D=b(this.shadowRoot,this.D,"default"===this.flavor?"neutral":this.flavor,({base:t})=>(t=>ti(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.I();break;case"size":case"label":case"placeholder":case"required":case"disabled":case"clearable":case"format":case"locale":break;case"value":{const t=ai(e,this.kn.withTime);if(null===t){(void 0!==this.kn.year||void 0!==this.kn.month||void 0!==this.kn.day)&&(this.kn={withTime:this.kn.withTime,open:this.kn.open});break}const n={year:this.kn.year,month:this.kn.month,day:this.kn.day,hour:this.kn.hour,minute:this.kn.minute};(t?.year!==n.year||t?.month!==n.month||t?.day!==n.day||t?.hour!==n.hour||t?.minute!==n.minute)&&(this.kn={...this.kn,...t});break}case"with-time":e!==this.kn.withTime&&(this.kn.withTime=e,void 0!==this.kn.year&&void 0!==this.kn.month&&void 0!==this.kn.day&&this.syncFormValue())}}getFormValue(){return ci(this.getComponents())}getComponents(){return{year:this.kn.year,month:this.kn.month,day:this.kn.day,hour:this.kn.hour,minute:this.kn.minute}}hasDate(){return!!(this.kn.year&&this.kn.month&&this.kn.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=li(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.kn.withTime):null}initializeState(){const t=this.getProperty("value"),n=this.getProperty("with-time"),e=ai(t,n);this.kn=null===e?{withTime:n,open:!1}:{...e,withTime:n,open:!1},this.syncFormValue()}updateState(t,n=!1){this.kn={...this.kn,...t},(n||!this.kn.open||!this.kn.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?ci(t):null,i=t?di(t,this.kn.withTime):null,o=t?li(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)}}clear(){this.clearValue()}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.kn.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.kn.open+""),t.setAttribute("tabindex",n?"-1":"0"),n&&t.setAttribute("aria-disabled","true"),this.getProperty("label")&&t.setAttribute("aria-labelledby","date-picker-label-"+ri(this)),t.addEventListener("keydown",t=>{this.kn.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=ii,t.addEventListener("click",t=>this.handleClearClick(t)),r.appendChild(t)}const a=document.createElement("span");return a.className="stub-arrow",a.innerHTML=ei,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.ae=new pi(e,this,this.kn.hour||0,this.kn.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.kn.year&&this.kn.month&&this.kn.day&&(e.setAttribute("year",""+this.kn.year),e.setAttribute("month",""+this.kn.month),e.setAttribute("day",""+this.kn.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.kn.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.kn.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.kn.withTime?o+"T00:00":o),s&&(i.max=this.kn.withTime?s+"T23:59":s);const r=di(this.getComponents(),this.kn.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=ai(i.value,this.kn.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=ii,t.addEventListener("click",t=>this.handleClearClick(t)),h.appendChild(t)}const u=document.createElement("span");return u.className="stub-arrow",u.innerHTML=ei,h.appendChild(u),n.appendChild(h),t.appendChild(n),t}calculateCalendarPosition(){if(!this.shadowRoot)return;if(Pn())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=_t({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-"+ri(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:ni,id:"ty-date-picker"}),Pn()){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.kn.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"),Pn()){const t=this.shadowRoot.querySelector(".native-date-input");if(t){const n=di(this.getComponents(),this.kn.withTime);t.value=n||""}return}const a=this.shadowRoot.querySelector("ty-calendar");if(a&&e&&(a.setAttribute("year",""+this.kn.year),a.setAttribute("month",""+this.kn.month),a.setAttribute("day",""+this.kn.day)),a){const t=this.getProperty("flavor");t&&"default"!==t?a.setAttribute("flavor",t):a.removeAttribute("flavor")}this.ae&&void 0!==this.kn.hour&&void 0!==this.kn.minute&&this.ae.setTime(this.kn.hour,this.kn.minute)}setupEventListeners(){this.le&&document.removeEventListener("click",this.le),this.ce&&document.removeEventListener("keydown",this.ce),this.le=t=>this.handleOutsideClick(t),this.ce=t=>this.handleEscapeKey(t),document.addEventListener("click",this.le),document.addEventListener("keydown",this.ce);const t=this.shadowRoot?.querySelector(".calendar-dialog");t&&(this.de=t=>this.handleDialogClick(t),t.addEventListener("click",this.de))}handleStubClick(t){t.preventDefault();const n=this.shadowRoot?.querySelector(".calendar-dialog");!this.kn.open||n&&n.open||(this.updateState({open:!1},!0),ln("date-picker-"+(this.id||""+this))),!this.getProperty("disabled")&&Date.now()-this.re>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.kn.hour,minute:this.kn.minute};this.updateState(e,!0),this.emitChangeEvent(e,"selection"),this.kn.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.kn.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.kn.open&&e&&!this.contains(n)&&!e.contains(n)&&this.closeDropdown()}handleEscapeKey(t){"Escape"===t.key&&this.kn.open&&(t.preventDefault(),this.closeDropdown())}openDropdown(){this.kn.open||Pn()||(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.kn.open)return;this.re=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.le&&document.removeEventListener("click",this.le),this.ce&&document.removeEventListener("keydown",this.ce),this.de&&this.shadowRoot){const t=this.shadowRoot.querySelector(".calendar-dialog");t&&t.removeEventListener("click",this.de)}this.kn.open&&ln("date-picker-"+(this.id||""+this)),this.le=void 0,this.ce=void 0,this.de=void 0,this.ae=void 0}};bi.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}},bi.formAssociated=!0;let gi=bi;customElements.get("ty-date-picker")||customElements.define("ty-date-picker",gi);const mi=new Map,vi=new Map;function fi(t){return mi.get(t)}function yi(t,n){vi.has(t)||vi.set(t,new Set),vi.get(t).add(n);const e=mi.get(t);return e&&n(e),()=>{vi.get(t)?.delete(n),0===vi.get(t)?.size&&vi.delete(t)}}function wi(){return Object.fromEntries(mi)}class TyResizeObserver extends HTMLElement{constructor(){super(),this.$t=null,this.he=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.he&&clearTimeout(this.he),this.he=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){mi.set(t,{width:n,height:e});const i=vi.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.he&&(clearTimeout(this.he),this.he=null),this.id&&(mi.delete(t=this.id),vi.delete(t))}}customElements.define("ty-resize-observer",TyResizeObserver);const xi=`\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.ue=null,this.pe=null,this.be=null,this.ge=null,this.me=null,this.Qt=null,this.$t=null,this.ve=null,this.kt=null,this.fe=!1,this.ye=!1,this.Mt=()=>{null===this.kt&&(this.kt=requestAnimationFrame(()=>{this.kt=null,this.we()}))},this.xe=()=>{this.Qt?.update(),this.we()};const t=this.attachShadow({mode:"open"});s(t,{css:xi,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.ue=t.querySelector(".scroll-wrapper"),this.pe=t.querySelector(".shadow-top"),this.be=t.querySelector(".shadow-bottom"),this.ge=t.querySelector(".shadow-left"),this.me=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.ke()}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.ue?.addEventListener("scroll",this.Mt,{passive:!0}),this.$t=new ResizeObserver(()=>{this.Qt?.update(),this.we()}),this.ue){this.$t.observe(this.ue);const t=this.ue.querySelector("slot");t&&t.addEventListener("slotchange",this.xe)}this.ke(),this.we(),this.nn(),this.ze()}disconnectedCallback(){this.ue?.removeEventListener("scroll",this.Mt),this.tn(),this.$e(),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.ke(),this.we(),this.Qt?.update()),"custom-scrollbar"!==t&&"overflow-x"!==t||(this.tn(),this.nn(),this.we()),"scroll-anchoring"===t&&(this.$e(),this.ze()))}ze(){!this.ve&&this.scrollAnchoring&&(this.ve=new MutationObserver(t=>{const n=this.ue;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.ve.observe(this,{childList:!0}))}$e(){this.ve?.disconnect(),this.ve=null}nn(){if(this.Qt)return;if(!this.ue||!this.customScrollbar)return;this.Qt=new Et(this.ue,{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)}ke(){if(this.ue){const t=this.maxHeight;t?(this.ue.style.setProperty("--scroll-max-height",t),this.ue.style.maxHeight=t):(this.ue.style.removeProperty("--scroll-max-height"),this.ue.style.maxHeight="")}}we(){if(!this.ue)return;const{scrollTop:t,scrollLeft:n,scrollHeight:e,scrollWidth:i,clientHeight:o,clientWidth:s}=this.ue;this.pe&&this.pe.classList.toggle("visible",t>2),this.be&&this.be.classList.toggle("visible",e-2>t+o),this.overflowX&&(this.ge&&this.ge.classList.toggle("visible",n>2),this.me&&this.me.classList.toggle("visible",i-2>n+s));const r=e-o;if(r>0){const n=this.nearEdgeThreshold,i=r-t;this.ye=this.Ce("nearend",i,n,this.ye,{distance:i,scrollTop:t,scrollHeight:e,clientHeight:o}),this.fe=this.Ce("nearstart",t,n,this.fe,{distance:t,scrollTop:t,scrollHeight:e,clientHeight:o})}else this.fe=!1,this.ye=!1}Ce(t,n,e,i,o){return e>=n&&(i||this.dispatchEvent(new CustomEvent(t,{detail:o,bubbles:!0,composed:!0})),!0)}updateShadows(){this.we(),this.Qt?.update()}scrollToTop(t=!0){this.ue?.scrollTo({top:0,behavior:t?"smooth":"auto"})}scrollToBottom(t=!0){this.ue&&this.ue.scrollTo({top:this.ue.scrollHeight,behavior:t?"smooth":"auto"})}scrollToLeft(t=!0){this.ue?.scrollTo({left:0,behavior:t?"smooth":"auto"})}scrollToRight(t=!0){this.ue&&this.ue.scrollTo({left:this.ue.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.ue}}customElements.define("ty-scroll-container",TyScrollContainer),"undefined"!=typeof window&&(window.tyVersion=x,window.tyIcons={register:t=>{D(t)},get:t=>I(t),has:t=>O(t),list:()=>F(),cacheInfo:()=>q(),clearCache:()=>L()},window.tyResizeObserver={getSize:t=>fi(t),onResize:(t,n)=>yi(t,n),get sizes(){return wi()}},window.tyLoader={set:t=>m(t),get:()=>v(),reset:()=>f()}),t.IconRegistry=V,t.TyButton=w,t.TyCalendar=Qe,t.TyCalendarMonth=TyCalendarMonth,t.TyCalendarNavigation=Ue,t.TyCheckbox=rt,t.TyCopy=kt,t.TyDatePicker=gi,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=Kn,t.TySelectedOptions=TySelectedOptions,t.TySelectedTags=TySelectedOptions,t.TyStep=TyStep,t.TySwitch=dt,t.TyTab=TyTab,t.TyTabs=TyTabs,t.TyTag=U,t.TyTextarea=Dt,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=wi,t.getLoaderSvg=v,t.getLockState=function(){return{locked:on.locked,scrollY:on.scrollY,activeLocks:Array.from(on.activeLocks)}},t.getSize=fi,t.isLocked=function(){return on.locked},t.isLockedBy=function(t){return on.activeLocks.has(t)},t.lockScroll=an,t.onResize=yi,t.resetLoaderSvg=f,t.setLoaderSvg=m,t.unlockScroll=ln,Object.defineProperty(t,Symbol.toStringTag,{value:"Module"})});
|