@threadlabs/looma 0.13.5 → 0.13.6
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/components/ui-icon/ui-icon.html +67 -7
- package/dist/index.js +17 -18
- package/package.json +1 -1
- package/vanilla/UiIcon.js +1 -3
- package/vue/UiIcon.vue +337 -42
- package/vue/chunks/UiIcon.js +950 -32
- package/vue/components.css +3 -3
- package/components/ui-icon/ui-icon.js +0 -8
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getComponentHost, observeDocument, registerComponentDefinitions, setControllerModule } from "@nextwebwg/html-next/runtime";
|
|
2
2
|
|
|
3
|
-
export const definitions = [{"source":{"file":"./components/ui-action-bar/ui-action-bar.html"},"contract":{"version":1,"name":"UiActionBar","tag":"ui-action-bar","nativeElement":"div","props":{}},"template":{"kind":"element","name":"div","attributes":[],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"bar"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"tertiary"}],"children":[{"kind":"slot","fallback":[],"name":"tertiary"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"secondary"}],"children":[{"kind":"slot","fallback":[],"name":"secondary"},{"kind":"slot"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"primary"}],"children":[{"kind":"slot","fallback":[],"name":"primary"}]}]}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-action-bar-gap {\n syntax: \"*\";\n inherits: false;\n }\n\n /* The action row of a form or dialog. Tertiary actions (Back, Cancel, Discard) sit at the start\n edge; secondary actions (Save as draft, Preview) sit just before the primary one, which ends the\n row. The bar arranges its actions and leaves their look to them. */\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-action-bar-gap: var(--ui-action-bar-gap);\n\n --_gap: var(--ui-space-2);\n display: block;\n /* A size container sizes itself from its container, never its content. */\n container-type: inline-size;\n inline-size: 100%;\n min-inline-size: 0;\n }\n\n .bar,\n .tertiary,\n .secondary,\n .primary {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--_ui-action-bar-gap, var(--_gap));\n }\n\n /* The tertiary group takes the spare space, pushing the rest to the end edge; without it, the\n rest still ends the row. */\n .bar {\n justify-content: flex-end;\n }\n\n .tertiary {\n flex: 1 1 auto;\n }\n\n .tertiary:empty,\n .secondary:empty,\n .primary:empty {\n display: none;\n }\n\n /* A narrow container stacks the actions full width, primary on top: the row turned on its end,\n read from its end edge. Container queries cannot read custom properties, so the width is fixed. */\n @container (inline-size < 24rem) {\n .bar,\n .tertiary,\n .secondary,\n .primary {\n flex-direction: column-reverse;\n flex-wrap: nowrap;\n align-items: stretch;\n }\n\n .tertiary {\n flex: none;\n }\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true,"name":"tertiary"},{"dynamic":false,"required":true,"name":"secondary"},{"dynamic":false,"required":true},{"dynamic":false,"required":true,"name":"primary"}],"root":{"kind":"native","element":"div","choices":["div"]}},{"source":{"file":"./components/ui-affordance-scope/ui-affordance-scope.html"},"contract":{"version":1,"name":"UiAffordanceScope","tag":"ui-affordance-scope","nativeElement":"span","props":{"guide":{"type":{"enum":["dot","none"]},"required":false,"target":{"attribute":"guide"},"description":"What marks an anticipatory control at rest. dot shows a small guide dot where it will appear; none shows nothing until the pointer nears it, it is hovered,\n or it takes focus. Every guide inside the scope follows it, including a sidebar's resize line and the editor table's handles.","default":"dot"},"nearRadius":{"type":"number","required":false,"target":{"attribute":"nearradius"},"description":"How close, in pixels, the pointer must come to reveal an affordance.","default":16}}},"template":{"kind":"element","name":"span","attributes":[],"children":[{"kind":"slot"}]},"css":":host {\n display: contents;\n --ui-affordance-scope-engaged: 0;\n --ui-affordance-scope-guide: 1;\n }\n\n :host-state([engaged]) {\n --ui-affordance-scope-engaged: 1;\n }\n\n /* Published to descendants: each guide multiplies its opacity by it, so none reaches them all. */\n :host-state([guide=\"none\"]) {\n --ui-affordance-scope-guide: 0;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"engaged","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}}],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"span","choices":["span"]},"controller":"./components/ui-affordance-scope/ui-affordance-scope.js"},{"source":{"file":"./components/ui-avatar-group/ui-avatar-group.html"},"contract":{"version":1,"name":"UiAvatarGroup","tag":"ui-avatar-group","nativeElement":"div","props":{"label":{"type":"string","required":false,"target":{"attribute":"aria-label"},"description":"The group's accessible name, announced for the set of avatars as a whole. Name who they are rather than repeating the default.","default":"People"},"max":{"type":"number","required":false,"target":{"attribute":"max"},"description":"How many avatars to show. The rest are hidden and counted in a +N badge after the last visible one. Fractions round down, and 0 hides every avatar behind\n the badge.","default":5},"size":{"type":{"enum":["sm","md"]},"required":false,"target":{"attribute":"size"},"description":"The size of the avatars inside, matched by the +N badge and the overlap. Give each Avatar the same size.","default":"md"}}},"template":{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"role","value":"group"},{"kind":"attribute","name":"aria-label","expression":"label","expressionPlan":{"source":"label","ast":{"kind":"id","name":"label"},"dependencies":["label"]}}],"children":[{"kind":"slot"},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"overflow"},{"kind":"literal","name":"role","value":"img"},{"kind":"attribute","name":"hidden","expression":"not overflowCount","expressionPlan":{"source":"not overflowCount","ast":{"kind":"unary","op":"not","operand":{"kind":"id","name":"overflowCount"}},"dependencies":["overflowCount"]}},{"kind":"attribute","name":"aria-label","expression":"format('%s more', overflowCount)","expressionPlan":{"source":"format('%s more', overflowCount)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s more"},{"kind":"id","name":"overflowCount"}]},"dependencies":["overflowCount"]}}],"children":[{"kind":"element","name":"template","attributes":[{"kind":"directive","name":"value","expression":"format('+%s', overflowCount)","expressionPlan":{"source":"format('+%s', overflowCount)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"+%s"},{"kind":"id","name":"overflowCount"}]},"dependencies":["overflowCount"]}}],"children":[]}],"ref":"overflow"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-avatar-group-edge-ring {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-avatar-group-overlap-shadow {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-avatar-group-overlap-shadow: var(--ui-avatar-group-overlap-shadow);\n --_ui-avatar-group-edge-ring: var(--ui-avatar-group-edge-ring);\n\n /* Each avatar is ringed in the surface colour, so where one overlaps the next it reads as a\n * whole circle set on top, not a shape cut into the one beneath. */\n --_overlap-shadow: 0 0 0 0 transparent;\n --_edge-ring: 0 0 0 2px var(--ui-surface);\n\n display: flex;\n align-items: center;\n flex-direction: row;\n gap: 0;\n }\n\n /* Overlap and the separating shadow are applied by the controller: slotted avatars are nested\n * component roots outside this style scope. */\n :slotted(*) {\n margin-inline-start: -0.5rem;\n flex-shrink: 0;\n border-radius: 999px;\n }\n\n :slotted(*:first-child) {\n margin-inline-start: 0;\n }\n\n .overflow {\n margin-inline-start: -0.5rem;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n inline-size: 2.5rem;\n block-size: 2.5rem;\n border-radius: 999px;\n border: 1px solid var(--ui-border-strong);\n background: var(--ui-surface-elevated);\n color: var(--ui-text-primary);\n box-shadow:\n var(--_ui-avatar-group-overlap-shadow, var(--_overlap-shadow)),\n var(--_ui-avatar-group-edge-ring, var(--_edge-ring));\n font: inherit;\n font-size: var(--ui-font-size-xs);\n font-weight: 600;\n flex-shrink: 0;\n }\n\n :host-state([size=\"sm\"]) .overflow {\n margin-inline-start: -0.25rem;\n inline-size: 1.75rem;\n block-size: 1.75rem;\n }\n\n .overflow[hidden] {\n display: none;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"overflowCount","expression":{"source":"0","ast":{"kind":"literal","value":0},"dependencies":[]}}],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-avatar-group/ui-avatar-group.js"},{"source":{"file":"./components/ui-avatar/ui-avatar.html"},"contract":{"version":1,"name":"UiAvatar","tag":"ui-avatar","nativeElement":"span","props":{"active":{"type":"boolean","required":false,"target":{"attribute":"active"},"description":"Marks the person as active now, such as editing the same page: a ring in the success colour around the avatar. The ring is not announced, so say what it\n means in alt (\"Ada Lovelace, editing\").","default":false},"alt":{"type":"string","required":false,"target":{"attribute":"alt"},"description":"The avatar's accessible name, announced for it as an image. When empty, name is used, then \"Avatar\". Initials come from name first, so alt supplies them\n only when name is empty. An authored img carries its own alt instead.","default":""},"fallback":{"type":"string","required":false,"target":{"attribute":"fallback"},"description":"Text shown instead of the initials derived from name or alt, whenever there is no image. It is uppercased; keep it to a couple of characters, because the\n circle clips anything wider.","default":""},"name":{"type":"string","required":false,"target":{"attribute":"name"},"description":"The person's name. The initials are drawn from it: the first letters of the first two words, or the first two letters of a single word. It is also the\n accessible name when alt is empty.","default":""},"size":{"type":{"enum":["sm","md"]},"required":false,"target":{"attribute":"size"},"description":"md is 2.5rem, for a person on their own (a profile, a comment); sm is 1.75rem with smaller initials, for a row of people in a toolbar or header.","default":"md"},"src":{"type":"string","required":false,"target":{"attribute":"src"},"description":"The image to show, cropped to fill the circle. Until it loads, or if it fails, the avatar shows initials instead. An img element authored inside the avatar\n takes precedence over src."}}},"template":{"kind":"element","name":"span","attributes":[],"children":[{"kind":"slot"},{"kind":"element","name":"img","attributes":[{"kind":"literal","name":"class","value":"image"},{"kind":"attribute","name":"src","expression":"src","expressionPlan":{"source":"src","ast":{"kind":"id","name":"src"},"dependencies":["src"]}},{"kind":"literal","name":"alt","value":""},{"kind":"literal","name":"aria-hidden","value":"true"},{"kind":"attribute","name":"hidden","expression":"hasAuthoredImage or not hasImage","expressionPlan":{"source":"hasAuthoredImage or not hasImage","ast":{"kind":"binary","op":"or","left":{"kind":"id","name":"hasAuthoredImage"},"right":{"kind":"unary","op":"not","operand":{"kind":"id","name":"hasImage"}}},"dependencies":["hasAuthoredImage","hasImage"]}}],"children":[],"ref":"image"},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"fallback"},{"kind":"attribute","name":"aria-hidden","expression":"hasImage","expressionPlan":{"source":"hasImage","ast":{"kind":"id","name":"hasImage"},"dependencies":["hasImage"]}},{"kind":"attribute","name":"hidden","expression":"hasImage","expressionPlan":{"source":"hasImage","ast":{"kind":"id","name":"hasImage"},"dependencies":["hasImage"]}},{"kind":"directive","name":"value","expression":"initials","expressionPlan":{"source":"initials","ast":{"kind":"id","name":"initials"},"dependencies":["initials"]}}],"children":[]}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-avatar-border {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-avatar-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-avatar-text {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-avatar-active-ring {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n display: inline-grid;\n place-items: center;\n overflow: hidden;\n inline-size: 2.5rem;\n block-size: 2.5rem;\n border-radius: 999px;\n border: 1px solid var(--ui-avatar-border, var(--ui-border-strong));\n background: var(--ui-avatar-surface, var(--ui-accent-soft));\n color: var(--ui-avatar-text, var(--ui-accent-subtle-text, var(--ui-accent-solid)));\n font: inherit;\n font-size: var(--ui-font-size-sm);\n font-weight: 600;\n text-transform: uppercase;\n }\n\n :host-state([size=\"sm\"]) {\n inline-size: 1.75rem;\n block-size: 1.75rem;\n font-size: var(--ui-font-size-xs);\n }\n\n /* An outline, not a dot: the avatar clips its content to the circle, and an outline is drawn\n outside the box, so the ring survives the clip and the overlap in an Avatar Group. */\n :host-state([active]) {\n outline: 2px solid var(--ui-avatar-active-ring, var(--ui-success));\n outline-offset: 1px;\n }\n\n .image,\n :slotted(img) {\n grid-area: 1 / 1;\n inline-size: 100%;\n block-size: 100%;\n object-fit: cover;\n }\n\n .fallback {\n grid-area: 1 / 1;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n inline-size: 100%;\n block-size: 100%;\n }\n\n /* Centre the glyphs, not the line box: a label without descenders otherwise reads high. */\n /* Centre the glyphs, not the line box: a label without descenders otherwise reads high.\n * Trimming applies to block containers, so the box is a block with centred content. */\n @supports (text-box-trim: trim-both) {\n .fallback {\n display: block;\n text-align: center;\n align-content: center;\n text-box-trim: trim-both;\n text-box-edge: cap alphabetic;\n }\n }\n\n [hidden] {\n display: none;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"hasImage","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"hasAuthoredImage","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"initials","expression":{"source":"'?'","ast":{"kind":"literal","value":"?"},"dependencies":[]}}],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"span","choices":["span"]},"controller":"./components/ui-avatar/ui-avatar.js"},{"source":{"file":"./components/ui-badge/ui-badge.html"},"contract":{"version":1,"name":"UiBadge","tag":"ui-badge","nativeElement":"span","props":{"shape":{"type":{"enum":["pill","tag"]},"required":false,"target":{"attribute":"shape"},"description":"Silhouette. pill is rounded at both ends; tag is a label: flat at the start and coming to a point at the end, for a tag or a chosen chip.","default":"pill"},"tone":{"type":{"enum":["neutral","accent","info","success","warning","danger"]},"required":false,"target":{"attribute":"tone"},"description":"Which colour the badge speaks in. neutral is a quiet grey for plain labels; accent draws the eye in the accent colour; info, success, warning, and danger\n mark a status, so match the tone to what the badge says.","default":"neutral"},"variant":{"type":{"enum":["solid","subtle"]},"required":false,"target":{"attribute":"variant"},"description":"Emphasis. subtle sets the text in its tone over a soft wash of it; solid fills with the tone and uses contrasting text, for a status that has to stand out.\n The neutral tone looks the same in both.","default":"subtle"}}},"template":{"kind":"element","name":"span","attributes":[],"children":[{"kind":"slot"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-badge-border {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-badge-font-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-badge-font-weight {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-badge-line-height {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-badge-min-block-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-badge-padding-block {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-badge-padding-inline {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-badge-point {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-badge-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-badge-text {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n --_badge-surface: var(--ui-surface-subtle);\n --_badge-text: var(--ui-text-secondary);\n /* Every tone's edge is its fill, so it is unseen until forced colors draw it. */\n --_badge-border: var(--ui-surface-subtle);\n\n display: inline-flex;\n align-items: center;\n justify-content: center;\n max-width: 100%;\n padding: var(--ui-badge-padding-block, var(--ui-space-0-5)) var(--ui-badge-padding-inline, var(--ui-space-2));\n border: 1px solid var(--ui-badge-border, var(--_badge-border));\n border-radius: var(--ui-radius-round);\n background: var(--ui-badge-surface, var(--_badge-surface));\n color: var(--ui-badge-text, var(--_badge-text));\n font-family: var(--ui-font-family-sans);\n font-size: var(--ui-badge-font-size, var(--ui-font-size-sm));\n font-weight: var(--ui-badge-font-weight, var(--ui-font-medium));\n line-height: var(--ui-badge-line-height, var(--ui-line-height-tight));\n white-space: nowrap;\n }\n\n /* Centre the glyphs, not the line box: a label without descenders otherwise reads high.\n * Trimming applies to block containers; an inline-block is one and, like the inline-flex it\n * replaces, still sizes to its label rather than filling its container. */\n @supports (text-box-trim: trim-both) {\n :host {\n display: inline-block;\n min-block-size: var(--ui-badge-min-block-size, 1.5rem);\n text-align: center;\n align-content: center;\n text-box-trim: trim-both;\n text-box-edge: cap alphabetic;\n }\n }\n\n :host-state([tone=\"accent\"]) {\n --_badge-surface: var(--ui-accent-strong-surface, var(--ui-accent-solid));\n --_badge-border: var(--ui-accent-strong-surface, var(--ui-accent-solid));\n --_badge-text: var(--ui-accent-on-strong, var(--ui-text-on-accent));\n }\n\n :host-state([tone=\"danger\"]) {\n --_badge-surface: var(--ui-danger-strong-surface, var(--ui-danger-solid));\n --_badge-border: var(--ui-danger-strong-surface, var(--ui-danger-solid));\n --_badge-text: var(--ui-danger-on-strong, var(--ui-text-on-accent));\n }\n\n :host-state([tone=\"success\"]) {\n --_badge-surface: var(--ui-success-strong-surface, var(--ui-success-solid));\n --_badge-border: var(--ui-success-strong-surface, var(--ui-success-solid));\n --_badge-text: var(--ui-success-on-strong, var(--ui-text-on-accent));\n }\n\n :host-state([tone=\"warning\"]) {\n --_badge-surface: var(--ui-warning-strong-surface, var(--ui-warning-solid));\n --_badge-border: var(--ui-warning-strong-surface, var(--ui-warning-solid));\n --_badge-text: var(--ui-warning-on-strong, var(--ui-text-on-accent));\n }\n\n :host-state([tone=\"info\"]) {\n --_badge-surface: var(--ui-info-strong-surface, var(--ui-info-solid));\n --_badge-border: var(--ui-info-strong-surface, var(--ui-info-solid));\n --_badge-text: var(--ui-info-on-strong, var(--ui-text-on-accent));\n }\n\n :host-state([variant=\"subtle\"][tone=\"accent\"]) {\n --_badge-surface: var(--ui-accent-soft);\n --_badge-border: var(--ui-accent-soft);\n --_badge-text: var(--ui-accent-subtle-text, var(--ui-accent-solid));\n }\n\n :host-state([variant=\"subtle\"][tone=\"danger\"]) {\n --_badge-surface: var(--ui-danger-soft);\n --_badge-border: var(--ui-danger-soft);\n --_badge-text: var(--ui-danger-subtle-text, var(--ui-danger-solid));\n }\n\n :host-state([variant=\"subtle\"][tone=\"success\"]) {\n --_badge-surface: var(--ui-success-soft);\n --_badge-border: var(--ui-success-soft);\n --_badge-text: var(--ui-success-subtle-text, var(--ui-success-solid));\n }\n\n :host-state([variant=\"subtle\"][tone=\"warning\"]) {\n --_badge-surface: var(--ui-warning-soft);\n --_badge-border: var(--ui-warning-soft);\n --_badge-text: var(--ui-warning-subtle-text, var(--ui-warning-solid));\n }\n\n :host-state([variant=\"subtle\"][tone=\"info\"]) {\n --_badge-surface: var(--ui-info-soft);\n --_badge-border: var(--ui-info-soft);\n --_badge-text: var(--ui-info-subtle-text, var(--ui-info-solid));\n }\n\n /* A tag is flat at the start and points at the end. The point is cut from the box, so it has no\n outline to follow: the edge is the fill. The end padding grows by the point's depth so the\n label never runs into it. */\n :host-state([shape=\"tag\"]) {\n --_badge-point: var(--ui-badge-point, var(--ui-space-2));\n\n border-color: transparent;\n border-radius: 0;\n padding-inline-end: calc(var(--ui-badge-padding-inline, var(--ui-space-2)) + var(--_badge-point));\n clip-path: polygon(0 0, calc(100% - var(--_badge-point)) 0, 100% 50%, calc(100% - var(--_badge-point)) 100%, 0 100%);\n }\n\n :host-state([shape=\"tag\"]):dir(rtl) {\n padding-inline-end: var(--ui-badge-padding-inline, var(--ui-space-2));\n padding-inline-start: calc(var(--ui-badge-padding-inline, var(--ui-space-2)) + var(--_badge-point));\n clip-path: polygon(var(--_badge-point) 0, 100% 0, 100% 100%, var(--_badge-point) 100%, 0 50%);\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"span","choices":["span"]}},{"source":{"file":"./components/ui-breadcrumb-item/ui-breadcrumb-item.html"},"contract":{"version":1,"name":"UiBreadcrumbItem","tag":"ui-breadcrumb-item","nativeElement":"li","props":{"current":{"type":"boolean","required":false,"target":{"attribute":"current"},"description":"Marks the step as the view you are on: it is plain text with aria-current=\"page\". Every other step holds a link.","default":false}}},"template":{"kind":"element","name":"li","attributes":[{"kind":"attribute","name":"aria-current","expression":"{ true: 'page', false: null }[format('%s', current)]","expressionPlan":{"source":"{ true: 'page', false: null }[format('%s', current)]","ast":{"kind":"index","object":{"kind":"object","pairs":[{"key":"true","value":{"kind":"literal","value":"page"}},{"key":"false","value":{"kind":"literal","value":null}}]},"index":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s"},{"kind":"id","name":"current"}]}},"dependencies":["current"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"separator"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[{"kind":"element","name":"ui-icon","attributes":[{"kind":"literal","name":"name","value":"chevron-right"}],"children":[]}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"content"}],"children":[{"kind":"slot"}]}]},"css":"/* One step in a ui-breadcrumbs trail: a link up to that place, or the current view. A chevron leads\n every step but the first. An icon slotted before the name sits with it. */\n :host {\n display: inline-flex;\n align-items: center;\n gap: var(--ui-space-2);\n min-inline-size: 0;\n }\n\n .separator {\n display: inline-flex;\n color: var(--ui-text-muted);\n font-size: var(--ui-font-size-xs);\n }\n\n :host:first-child .separator {\n display: none;\n }\n\n .content {\n display: inline-flex;\n align-items: center;\n gap: var(--ui-space-1);\n min-inline-size: 0;\n }\n\n .content > :slotted(a) {\n display: inline-flex;\n align-items: center;\n gap: var(--ui-space-1);\n color: var(--ui-text-secondary);\n text-decoration: none;\n }\n\n .content > :slotted(a:hover) {\n color: var(--ui-text-primary);\n text-decoration: underline;\n }\n\n :host-state([current]) .content {\n color: var(--ui-text-primary);\n font-weight: var(--ui-font-medium);\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"li","choices":["li"]}},{"source":{"file":"./components/ui-breadcrumbs/ui-breadcrumbs.html"},"contract":{"version":1,"name":"UiBreadcrumbs","tag":"ui-breadcrumbs","nativeElement":"nav","props":{"label":{"type":"string","required":false,"target":{"attribute":"aria-label"},"description":"The navigation landmark's accessible name.","default":"Breadcrumb"}}},"template":{"kind":"element","name":"nav","attributes":[{"kind":"attribute","name":"aria-label","expression":"label","expressionPlan":{"source":"label","ast":{"kind":"id","name":"label"},"dependencies":["label"]}}],"children":[{"kind":"element","name":"ol","attributes":[{"kind":"literal","name":"role","value":"list"}],"children":[{"kind":"slot"}]}]},"css":"/* Where a view sits: a trail of ui-breadcrumb-item, from the top down to the current view. It wraps\n rather than scrolls, so every step stays reachable. */\n :host {\n display: block;\n min-inline-size: 0;\n color: var(--ui-text-muted);\n font-size: var(--ui-font-size-sm);\n }\n\n ol {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--ui-space-1) var(--ui-space-2);\n margin: 0;\n padding: 0;\n list-style: none;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"nav","choices":["nav"]}},{"source":{"file":"./components/ui-button/ui-button.html"},"contract":{"version":1,"name":"UiButton","tag":"ui-button","nativeElement":"button","props":{"align":{"type":{"enum":["center","start"]},"required":false,"target":{"attribute":"align"},"description":"Content alignment. start lays the content out like a list option: from the start edge, with start-aligned text.","default":"center"},"as":{"type":{"enum":["button","a"]},"required":false,"target":{"attribute":"as"},"description":"The native element the button renders: a button, or a link (a) that navigates to href.","default":"button"},"disabled":{"type":"boolean","required":false,"target":{"attribute":"disabled"},"description":"Makes the button unavailable: it cannot be pressed, its tone fades, and it loses its raised look. A disabled link (as=\"a\" with href) drops its href and\n states aria-disabled=\"true\" instead, because a link has no native disabled state.","default":false},"href":{"type":"string","required":false,"target":{"attribute":"href"},"description":"The link's destination. Pair it with as=\"a\" so the button renders as a real link that navigates. A disabled link drops its href and states\n aria-disabled=\"true\", so it cannot be followed."},"rel":{"type":"string","required":false,"target":{"attribute":"rel"},"description":"The link's relationship to its destination, as on a native link. Only meaningful with as=\"a\"."},"size":{"type":{"enum":["sm","md","lg"]},"required":false,"target":{"attribute":"size"},"description":"Height, padding, and type size. sm is the small control height (2rem by default) with tighter padding and smaller text, md is the standard control height\n (2.5rem), and lg is taller (3rem) with roomier padding.","default":"md"},"stretch":{"type":"boolean","required":false,"target":{"attribute":"stretch"},"description":"Fills the inline size of its container.","default":false},"target":{"type":"string","required":false,"target":{"attribute":"target"},"description":"Where a link opens, as on a native link. Only meaningful with as=\"a\"."},"tone":{"type":{"enum":["accent","neutral","danger","success","warning","info"]},"required":false,"target":{"attribute":"tone"},"description":"Which colour the button speaks in. It applies to every variant, so an outline, a ghost, and a solid in the same tone are the same action at three volumes:\n tone=\"danger\" variant=\"outline\" is a destructive secondary action. neutral is the quiet one, for a button that should not claim a colour.","default":"accent"},"type":{"type":{"enum":["button","submit","reset"]},"required":false,"target":{"attribute":"type"},"description":"The button's type, as on a native button. button by default, so it never submits a form by accident. A link has no type.","default":"button"},"variant":{"type":{"enum":["outline","solid","danger","ghost","link"]},"required":false,"target":{"attribute":"variant"},"description":"Emphasis: how loudly the button asks. solid fills with its tone, outline draws its tone at the edge over a wash of it, ghost carries only text until it is\n hovered, and link is an inline text action that reads as a link. danger is solid in the danger tone, kept for the call sites that name it.","default":"outline"}}},"template":{"kind":"element","name":"template","attributes":[],"children":[{"kind":"element","name":"a","attributes":[{"kind":"attribute","name":"href","expression":"{ true: null, false: href }[format('%s', disabled)]","expressionPlan":{"source":"{ true: null, false: href }[format('%s', disabled)]","ast":{"kind":"index","object":{"kind":"object","pairs":[{"key":"true","value":{"kind":"literal","value":null}},{"key":"false","value":{"kind":"id","name":"href"}}]},"index":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s"},{"kind":"id","name":"disabled"}]}},"dependencies":["disabled","href"]}},{"kind":"attribute","name":"target","expression":"target","expressionPlan":{"source":"target","ast":{"kind":"id","name":"target"},"dependencies":["target"]}},{"kind":"attribute","name":"rel","expression":"rel","expressionPlan":{"source":"rel","ast":{"kind":"id","name":"rel"},"dependencies":["rel"]}},{"kind":"attribute","name":"aria-disabled","expression":"{ true: 'true', false: null }[format('%s', disabled and href)]","expressionPlan":{"source":"{ true: 'true', false: null }[format('%s', disabled and href)]","ast":{"kind":"index","object":{"kind":"object","pairs":[{"key":"true","value":{"kind":"literal","value":"true"}},{"key":"false","value":{"kind":"literal","value":null}}]},"index":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s"},{"kind":"binary","op":"and","left":{"kind":"id","name":"disabled"},"right":{"kind":"id","name":"href"}}]}},"dependencies":["disabled","href"]}}],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'a'","testPlan":{"source":"as = 'a'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"a"}},"dependencies":["as"]}}},{"kind":"element","name":"button","attributes":[{"kind":"attribute","name":"type","expression":"type","expressionPlan":{"source":"type","ast":{"kind":"id","name":"type"},"dependencies":["type"]}},{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}}],"children":[{"kind":"slot"}],"flow":{"kind":"else"}}],"flow":{"kind":"match"}},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-button-active-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-button-border {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-button-disabled-filter {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-button-disabled-opacity {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-button-ghost-active-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-button-ghost-hover-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-button-ghost-text {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-button-hover-border {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-button-hover-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-button-link-hover-text {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-button-link-text {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-button-min-block-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-button-radius {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-button-shadow {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-button-solid-shadow {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-button-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-button-text {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n --_hue: var(--ui-accent);\n --_hue-hover: var(--ui-accent-hover);\n --_hue-active: var(--ui-accent-active);\n --_hue-text: var(--ui-accent-active);\n --_on-hue: var(--ui-on-accent);\n\n --_tone: var(--_hue);\n --_tone-hover: var(--_hue-hover);\n --_tone-active: var(--_hue-active);\n --_tone-text: var(--_hue-text);\n --_on-tone: var(--_on-hue);\n\n display: inline-flex;\n align-items: center;\n justify-content: center;\n vertical-align: middle;\n color: var(--_tone-text);\n }\n\n :host-state([align=\"start\"]) {\n justify-content: flex-start;\n text-align: start;\n }\n\n :host-state([stretch]) {\n display: flex;\n inline-size: 100%;\n }\n\n :host {\n appearance: none;\n min-block-size: var(--ui-button-min-block-size, var(--ui-control-size-md));\n border-style: solid;\n border-width: 1px;\n border-color: var(--ui-button-border, var(--_tone));\n border-radius: var(--ui-button-radius, var(--ui-radius-md));\n background-color: var(--ui-button-surface, oklch(from var(--_tone) l c h / 5%));\n color: var(--ui-button-text, var(--_tone-text));\n font: inherit;\n font-weight: var(--ui-font-medium);\n text-decoration: none;\n line-height: var(--ui-line-height-tight);\n padding: var(--ui-space-2) var(--ui-space-3);\n background-image: var(--ui-raised-highlight);\n box-shadow: var(--ui-button-shadow, var(--ui-raised));\n cursor: pointer;\n transition:\n background-color var(--ui-motion-fast) var(--ui-motion-ease),\n border-color var(--ui-motion-fast) var(--ui-motion-ease),\n color var(--ui-motion-fast) var(--ui-motion-ease),\n box-shadow var(--ui-motion-fast) var(--ui-motion-ease);\n margin: 0;\n }\n\n @supports (text-box-trim: trim-both) {\n :host {\n text-box-trim: trim-both;\n text-box-edge: cap alphabetic;\n }\n }\n\n :host-state([size=\"sm\"]) {\n min-block-size: var(--ui-control-size-sm);\n padding: var(--ui-space-1) var(--ui-space-2);\n font-size: var(--ui-font-size-sm);\n }\n\n :host-state([size=\"lg\"]) {\n min-block-size: var(--ui-control-size-lg);\n padding: var(--ui-space-3) var(--ui-space-4);\n font-size: var(--ui-font-size-md);\n }\n\n /* A link is never :enabled, so interactive states test \"not unavailable\" instead: for a button that\n is exactly :enabled, at the same specificity, and it also matches a link that can be followed. */\n :host:hover:not(:disabled, [aria-disabled=\"true\"]) {\n border-color: var(--ui-button-hover-border, var(--_tone-hover));\n background-color: var(--ui-button-hover-surface, oklch(from var(--_tone) l c h / 12%));\n }\n\n /* Pressed reads as pressed in: the highlight goes, and the shadow moves inside. */\n :host:active:not(:disabled, [aria-disabled=\"true\"]) {\n background-color: var(--ui-button-active-surface, oklch(from var(--_tone) l c h / 18%));\n background-image: none;\n box-shadow: var(--ui-pressed);\n }\n\n :host-state([variant=\"solid\"]), :host-state([variant=\"danger\"]) {\n border-color: var(--_tone);\n background-color: var(--_tone);\n color: var(--_on-tone);\n box-shadow: var(--ui-button-solid-shadow, var(--ui-raised));\n }\n\n :is(:host-state([variant=\"solid\"]), :host-state([variant=\"danger\"])):hover:not(:disabled, [aria-disabled=\"true\"]) {\n background-color: var(--_tone-hover);\n border-color: var(--_tone-hover);\n }\n\n :is(:host-state([variant=\"solid\"]), :host-state([variant=\"danger\"])):active:not(:disabled, [aria-disabled=\"true\"]) {\n background-color: var(--_tone-active);\n border-color: var(--_tone-active);\n background-image: none;\n box-shadow: var(--ui-pressed);\n }\n\n /* Tone is the colour, variant is the volume. Every pairing works: a danger outline is a\n destructive secondary action, not a special case. */\n :host-state([tone=\"neutral\"]) {\n --_hue: var(--ui-text);\n --_hue-hover: var(--ui-text);\n --_hue-active: var(--ui-text);\n --_hue-text: var(--ui-text);\n --_on-hue: var(--ui-surface);\n }\n\n :host-state([tone=\"danger\"]), :host-state([variant=\"danger\"]) {\n --_hue: var(--ui-danger);\n --_hue-hover: var(--ui-danger-hover);\n --_hue-active: var(--ui-danger-hover);\n --_hue-text: var(--ui-danger-hover);\n --_on-hue: var(--ui-on-danger);\n }\n\n :host-state([tone=\"success\"]) {\n --_hue: var(--ui-success);\n --_hue-hover: color-mix(in srgb, var(--ui-success) 85%, #000);\n --_hue-active: color-mix(in srgb, var(--ui-success) 75%, #000);\n --_hue-text: color-mix(in srgb, var(--ui-success) 85%, #000);\n --_on-hue: var(--ui-surface);\n }\n\n :host-state([tone=\"warning\"]) {\n --_hue: var(--ui-warning);\n --_hue-hover: color-mix(in srgb, var(--ui-warning) 85%, #000);\n --_hue-active: color-mix(in srgb, var(--ui-warning) 75%, #000);\n --_hue-text: color-mix(in srgb, var(--ui-warning) 85%, #000);\n --_on-hue: var(--ui-surface);\n }\n\n :host-state([tone=\"info\"]) {\n --_hue: var(--ui-info);\n --_hue-hover: color-mix(in srgb, var(--ui-info) 85%, #000);\n --_hue-active: color-mix(in srgb, var(--ui-info) 75%, #000);\n --_hue-text: color-mix(in srgb, var(--ui-info) 85%, #000);\n --_on-hue: var(--ui-surface);\n }\n\n :host-state([variant=\"ghost\"]) {\n border-color: transparent;\n background: transparent;\n box-shadow: none;\n color: var(--ui-button-ghost-text, var(--_tone-text));\n }\n\n /* Tints derive from the text colour, not a surface token, so hover and press show on any background. */\n :host-state([variant=\"ghost\"]):hover:not(:disabled, [aria-disabled=\"true\"]) {\n background-color: var(--ui-button-ghost-hover-surface, oklch(from var(--_tone) l c h / 10%));\n border-color: transparent;\n }\n\n :host-state([variant=\"ghost\"]):active:not(:disabled, [aria-disabled=\"true\"]) {\n background-color: var(--ui-button-ghost-active-surface, oklch(from var(--_tone) l c h / 16%));\n border-color: transparent;\n box-shadow: var(--ui-pressed);\n }\n\n /* A soft halo that transitions in with the other box-shadow changes, layered on the raised shadow. */\n :host:focus-visible {\n outline: none;\n box-shadow:\n var(--ui-button-shadow, var(--ui-raised)),\n var(--ui-focus-halo);\n }\n\n :host-state([variant=\"solid\"]):focus-visible {\n box-shadow:\n var(--ui-button-solid-shadow, var(--ui-raised)),\n var(--ui-focus-halo);\n }\n\n /* Disabled keeps the shape and washes out the rest: every variant keeps its own structure, so a\n disabled outline is still an outline and a disabled ghost still has no edge. One filter fades\n fill, border, and text together (--ui-disabled-filter), and the theme decides which way is\n toward the page. The highlight and shadow go, because nothing that cannot be pressed should\n look raised. */\n :host:is(:disabled, [aria-disabled=\"true\"]) {\n filter: var(--ui-button-disabled-filter, var(--ui-disabled-filter));\n opacity: var(--ui-button-disabled-opacity, 1);\n cursor: not-allowed;\n background-image: none;\n box-shadow: none;\n }\n\n /* Ghost has no hover to fall back on, so disabled is the one state it has to state outright:\n it takes a surface rather than reading as plain text. The surface is a wash of the faded tone,\n the way hover washes the live one, so it stays light in every tone. An opaque mix toward the\n hue came out a mid-grey slab for neutral, whose hue is the ink: louder than the enabled button. */\n :host-state([variant=\"ghost\"]):is(:disabled, [aria-disabled=\"true\"]) {\n background-color: oklch(from var(--_tone) l c h / 14%);\n border-color: transparent;\n }\n\n @media (pointer: coarse) {\n :host {\n min-block-size: var(--ui-control-min-block-size);\n }\n }\n\n /* Under touch, a link-style button's press lands within the control minimum: an invisible hit\n area, centred on it, like IconButton's. A boxed button grows to the minimum itself (below);\n a link-style one keeps its text size, so a standalone one (\"See all\" under a list) needs the\n area. Only the link needs it: a hit area on every button would reach over its neighbours. */\n html[data-ui-input-modality=\"touch\"] :host-state([variant=\"link\"]) {\n position: relative;\n }\n\n html[data-ui-input-modality=\"touch\"] :host-state([variant=\"link\"])::after {\n position: absolute;\n inset: 50% auto auto 50%;\n inline-size: max(100%, var(--ui-control-min-block-size));\n block-size: max(100%, var(--ui-control-min-block-size));\n transform: translate(-50%, -50%);\n content: \"\";\n }\n\n /* Link: an inline text action. No box, padding, or minimum height (inline targets are exempt under\n WCAG 2.5.8); the inherited font; an underline that strengthens on hover; a visible focus ring. */\n :host-state([variant=\"link\"]) {\n display: inline;\n min-block-size: 0;\n padding: 0;\n border: 0;\n border-radius: var(--ui-radius-sm);\n background: none;\n box-shadow: none;\n font: inherit;\n color: var(--ui-button-link-text, var(--ui-text-secondary));\n text-decoration-line: underline;\n text-decoration-thickness: 1px;\n text-decoration-color: color-mix(in srgb, currentColor 40%, transparent);\n text-underline-offset: 0.2em;\n transition: color var(--ui-motion-fast) var(--ui-motion-ease), text-decoration-color var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n :host-state([variant=\"link\"]):hover:not(:disabled, [aria-disabled=\"true\"]) {\n color: var(--ui-button-link-hover-text, var(--ui-text-primary));\n text-decoration-color: currentColor;\n background: none;\n transform: none;\n }\n\n :host-state([variant=\"link\"]):active:not(:disabled, [aria-disabled=\"true\"]) {\n background: none;\n transform: none;\n }\n\n :host-state([variant=\"link\"]):is(:disabled, [aria-disabled=\"true\"]) {\n background: none;\n border-color: transparent;\n }\n\n :host-state([variant=\"link\"]):focus-visible {\n box-shadow: none;\n /* Fallback keeps the ring if the token is missing: an unresolved var() would void the outline. */\n outline: 2px solid var(--ui-focus-ring);\n outline-offset: 2px;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"button","choices":["a","button"]}},{"source":{"file":"./components/ui-callout/ui-callout.html"},"contract":{"version":1,"name":"UiCallout","tag":"ui-callout","nativeElement":"div","props":{"tone":{"type":{"enum":["info","note","warning","success","danger"]},"required":false,"target":{"attribute":"tone"},"description":"Which kind of message the callout carries, shown by its icon and colour: info (the default) for neutral information, note for an aside in muted grey,\n warning for a caution, success for a confirmation, and danger for an error or a destructive consequence.","default":"info"}}},"template":{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"role","value":"note"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"icon"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[{"kind":"element","name":"svg","attributes":[{"kind":"literal","name":"viewBox","value":"0 0 24 24"},{"kind":"literal","name":"fill","value":"none"},{"kind":"literal","name":"stroke","value":"currentColor"},{"kind":"literal","name":"stroke-width","value":"2"},{"kind":"literal","name":"stroke-linecap","value":"round"},{"kind":"literal","name":"stroke-linejoin","value":"round"}],"children":[{"kind":"element","name":"circle","attributes":[{"kind":"literal","name":"cx","value":"12"},{"kind":"literal","name":"cy","value":"12"},{"kind":"literal","name":"r","value":"10"}],"children":[]},{"kind":"element","name":"path","attributes":[{"kind":"literal","name":"d","value":"M12 16v-4"}],"children":[]},{"kind":"element","name":"path","attributes":[{"kind":"literal","name":"d","value":"M12 8h.01"}],"children":[]}],"flow":{"kind":"if","test":"tone = 'info'","testPlan":{"source":"tone = 'info'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"tone"},"right":{"kind":"literal","value":"info"}},"dependencies":["tone"]}}},{"kind":"element","name":"svg","attributes":[{"kind":"literal","name":"viewBox","value":"0 0 24 24"},{"kind":"literal","name":"fill","value":"none"},{"kind":"literal","name":"stroke","value":"currentColor"},{"kind":"literal","name":"stroke-width","value":"2"},{"kind":"literal","name":"stroke-linecap","value":"round"},{"kind":"literal","name":"stroke-linejoin","value":"round"}],"children":[{"kind":"element","name":"path","attributes":[{"kind":"literal","name":"d","value":"M13.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8.5L13.5 2Z"}],"children":[]},{"kind":"element","name":"path","attributes":[{"kind":"literal","name":"d","value":"M13 2v7h7"}],"children":[]},{"kind":"element","name":"path","attributes":[{"kind":"literal","name":"d","value":"m9.5 17.5 4-4 2 2-4 4H9.5v-2Z"}],"children":[]}],"flow":{"kind":"if","test":"tone = 'note'","testPlan":{"source":"tone = 'note'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"tone"},"right":{"kind":"literal","value":"note"}},"dependencies":["tone"]}}},{"kind":"element","name":"svg","attributes":[{"kind":"literal","name":"viewBox","value":"0 0 24 24"},{"kind":"literal","name":"fill","value":"none"},{"kind":"literal","name":"stroke","value":"currentColor"},{"kind":"literal","name":"stroke-width","value":"2"},{"kind":"literal","name":"stroke-linecap","value":"round"},{"kind":"literal","name":"stroke-linejoin","value":"round"}],"children":[{"kind":"element","name":"path","attributes":[{"kind":"literal","name":"d","value":"m21.73 18-8-14a2 2 0 0 0-3.46 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z"}],"children":[]},{"kind":"element","name":"path","attributes":[{"kind":"literal","name":"d","value":"M12 9v4"}],"children":[]},{"kind":"element","name":"path","attributes":[{"kind":"literal","name":"d","value":"M12 17h.01"}],"children":[]}],"flow":{"kind":"if","test":"tone = 'warning'","testPlan":{"source":"tone = 'warning'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"tone"},"right":{"kind":"literal","value":"warning"}},"dependencies":["tone"]}}},{"kind":"element","name":"svg","attributes":[{"kind":"literal","name":"viewBox","value":"0 0 24 24"},{"kind":"literal","name":"fill","value":"none"},{"kind":"literal","name":"stroke","value":"currentColor"},{"kind":"literal","name":"stroke-width","value":"2"},{"kind":"literal","name":"stroke-linecap","value":"round"},{"kind":"literal","name":"stroke-linejoin","value":"round"}],"children":[{"kind":"element","name":"circle","attributes":[{"kind":"literal","name":"cx","value":"12"},{"kind":"literal","name":"cy","value":"12"},{"kind":"literal","name":"r","value":"10"}],"children":[]},{"kind":"element","name":"path","attributes":[{"kind":"literal","name":"d","value":"m9 12 2 2 4-4"}],"children":[]}],"flow":{"kind":"if","test":"tone = 'success'","testPlan":{"source":"tone = 'success'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"tone"},"right":{"kind":"literal","value":"success"}},"dependencies":["tone"]}}},{"kind":"element","name":"svg","attributes":[{"kind":"literal","name":"viewBox","value":"0 0 24 24"},{"kind":"literal","name":"fill","value":"none"},{"kind":"literal","name":"stroke","value":"currentColor"},{"kind":"literal","name":"stroke-width","value":"2"},{"kind":"literal","name":"stroke-linecap","value":"round"},{"kind":"literal","name":"stroke-linejoin","value":"round"}],"children":[{"kind":"element","name":"circle","attributes":[{"kind":"literal","name":"cx","value":"12"},{"kind":"literal","name":"cy","value":"12"},{"kind":"literal","name":"r","value":"10"}],"children":[]},{"kind":"element","name":"path","attributes":[{"kind":"literal","name":"d","value":"m15 9-6 6"}],"children":[]},{"kind":"element","name":"path","attributes":[{"kind":"literal","name":"d","value":"m9 9 6 6"}],"children":[]}],"flow":{"kind":"if","test":"tone = 'danger'","testPlan":{"source":"tone = 'danger'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"tone"},"right":{"kind":"literal","value":"danger"}},"dependencies":["tone"]}}}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"content"}],"children":[{"kind":"slot"}]}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-callout-border {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-callout-border-width {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-callout-gap {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-callout-icon {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-callout-icon-column {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-callout-icon-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-callout-leading-border-width {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-callout-padding-block {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-callout-padding-inline {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-callout-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-callout-text {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-callout-icon-column: var(--ui-callout-icon-column);\n --_ui-callout-icon: var(--ui-callout-icon);\n --_ui-callout-icon-size: var(--ui-callout-icon-size);\n\n --_callout-surface: var(--ui-info-soft);\n --_callout-border: var(--ui-info-solid);\n --_callout-icon: var(--ui-info-solid);\n\n display: grid;\n grid-template-columns: var(--ui-callout-icon-column, 1.125rem) minmax(0, 1fr);\n gap: var(--ui-callout-gap, calc(var(--ui-space-2) * 0.75));\n align-items: start;\n max-width: 100%;\n padding: var(--ui-callout-padding-block, var(--ui-space-2)) var(--ui-callout-padding-inline, var(--ui-space-3));\n border: var(--ui-callout-border-width, 1px) solid color-mix(in srgb, var(--ui-callout-border, var(--_callout-border)) 35%, transparent);\n border-inline-start: var(--ui-callout-leading-border-width, 4px) solid var(--ui-callout-border, var(--_callout-border));\n border-radius: var(--ui-radius-md);\n background: var(--ui-callout-surface, var(--_callout-surface));\n color: var(--ui-callout-text, var(--ui-text-primary));\n font-family: var(--ui-font-family-sans);\n font-size: var(--ui-font-size-sm);\n font-weight: var(--ui-font-normal);\n line-height: var(--ui-line-height-md);\n }\n\n /* One line box tall, so the icon centres on the first line of text. */\n .icon {\n display: grid;\n place-items: center;\n inline-size: var(--_ui-callout-icon-column, 1.125rem);\n block-size: 1lh;\n color: var(--_ui-callout-icon, var(--_callout-icon));\n }\n\n .icon svg {\n inline-size: var(--_ui-callout-icon-size, 1.125rem);\n block-size: var(--_ui-callout-icon-size, 1.125rem);\n }\n\n .content {\n min-inline-size: 0;\n }\n\n :host-state([tone=\"note\"]) {\n --_callout-surface: var(--ui-surface-muted);\n --_callout-border: var(--ui-border-strong);\n --_callout-icon: var(--ui-text-secondary);\n }\n\n :host-state([tone=\"warning\"]) {\n --_callout-surface: var(--ui-warning-soft);\n --_callout-border: var(--ui-warning-solid);\n --_callout-icon: var(--ui-warning-solid);\n }\n\n :host-state([tone=\"success\"]) {\n --_callout-surface: var(--ui-success-soft);\n --_callout-border: var(--ui-success-solid);\n --_callout-icon: var(--ui-success-solid);\n }\n\n :host-state([tone=\"danger\"]) {\n --_callout-surface: var(--ui-danger-soft);\n --_callout-border: var(--ui-danger-solid);\n --_callout-icon: var(--ui-danger-solid);\n }\n\n /* A link in the callout's text is underlined, so it reads as a link by more than colour. */\n .content :slotted(a) {\n color: var(--ui-accent-active);\n text-decoration: underline;\n text-decoration-thickness: 0.06em;\n text-underline-offset: 0.18em;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]}},{"source":{"file":"./components/ui-card/ui-card.html"},"contract":{"version":1,"name":"UiCard","tag":"ui-card","nativeElement":"div","props":{"as":{"type":{"enum":["div","section","article","aside"]},"required":false,"target":{"attribute":"as"},"description":"The native element the card renders. Choose the one that names the content: a section of a page, a self-contained article, or an aside.","default":"div"},"padding":{"type":{"enum":["sm","md","lg"]},"required":false,"target":{"attribute":"padding"},"description":"The space inside the card: sm is snug (0.75rem), md is the default (1.5rem), and lg is roomy (2rem).","default":"md"},"tone":{"type":{"enum":["neutral","danger"]},"required":false,"target":{"attribute":"tone"},"description":"danger draws an outlined card's border in the danger colour.","default":"neutral"},"variant":{"type":{"enum":["outlined","subtle","elevated"]},"required":false,"target":{"attribute":"variant"},"description":"The surface. outlined is a bordered panel on the page; subtle is a quiet filled one with no border, for supporting details set apart from the flow;\n elevated floats above the page with a shadow, for a view's one card, such as sign-in.","default":"outlined"}}},"template":{"kind":"element","name":"template","attributes":[],"children":[{"kind":"element","name":"section","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'section'","testPlan":{"source":"as = 'section'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"section"}},"dependencies":["as"]}}},{"kind":"element","name":"article","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'article'","testPlan":{"source":"as = 'article'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"article"}},"dependencies":["as"]}}},{"kind":"element","name":"aside","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'aside'","testPlan":{"source":"as = 'aside'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"aside"}},"dependencies":["as"]}}},{"kind":"element","name":"div","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"else"}}],"flow":{"kind":"match"}},"css":"/* A surface that groups content. Its children stack with even space between them, so a card\n needs no layout of its own. */\n :host {\n display: flex;\n flex-direction: column;\n gap: var(--ui-space-4);\n box-sizing: border-box;\n min-inline-size: 0;\n padding: var(--ui-space-5);\n border: 1px solid var(--ui-border-default);\n border-radius: var(--ui-radius-lg);\n background: var(--ui-surface-raised);\n color: var(--ui-text-primary);\n }\n\n :host-state([padding=\"sm\"]) {\n gap: var(--ui-space-2);\n padding: var(--ui-space-3);\n }\n\n :host-state([padding=\"lg\"]) {\n padding: var(--ui-space-6);\n }\n\n :host-state([variant=\"subtle\"]) {\n border-color: transparent;\n background: var(--ui-surface-muted);\n }\n\n :host-state([variant=\"elevated\"]) {\n border-color: var(--ui-border-subtle);\n box-shadow: var(--ui-shadow-lg);\n }\n\n :host-state([tone=\"danger\"]) {\n border-color: var(--ui-danger);\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["section","article","aside","div"]}},{"source":{"file":"./components/ui-checkbox/ui-checkbox.html"},"contract":{"version":1,"name":"UiCheckbox","tag":"ui-checkbox","nativeElement":"label","props":{"checked":{"type":"boolean","required":false,"target":{"attribute":"checked"},"description":"Whether the checkbox is checked initially or when set externally. A form reset returns it to this.","default":false},"disabled":{"type":"boolean","required":false,"target":{"attribute":"disabled"},"description":"Disables the native checkbox, so it cannot be toggled or focused.","default":false},"indeterminate":{"type":"boolean","required":false,"target":{"property":"indeterminate"},"description":"Shows the mixed state, for a checkbox that summarises a group whose items are partly checked. It sets the native indeterminate property, which is\n independent of checked, so update it as the group changes.","default":false},"name":{"type":"string","required":false,"target":{"attribute":"name"},"description":"The native name the checkbox submits under: a form that contains it sends name=value while it is checked, and nothing while it is unchecked, as a native\n checkbox does. Left empty, it takes no part in form submission.","default":""},"required":{"type":"boolean","required":false,"target":{"attribute":"required"},"description":"Marks the native checkbox required, so native form validation treats it as invalid until it is checked.","default":false},"value":{"type":"string","required":false,"target":{"attribute":"value"},"description":"The value a form submits under name while the checkbox is checked, also reported in the change event's detail so one handler can tell checkboxes apart. on\n by default, as on a native checkbox.","default":"on"}}},"template":{"kind":"element","name":"label","attributes":[],"children":[{"kind":"element","name":"input","attributes":[{"kind":"literal","name":"type","value":"checkbox"},{"kind":"property","key":"checked","name":"checked","expression":"internalChecked","expressionPlan":{"source":"internalChecked","ast":{"kind":"id","name":"internalChecked"},"dependencies":["internalChecked"]}},{"kind":"property","key":"indeterminate","name":"indeterminate","expression":"indeterminate","expressionPlan":{"source":"indeterminate","ast":{"kind":"id","name":"indeterminate"},"dependencies":["indeterminate"]}},{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}},{"kind":"attribute","name":"required","expression":"required","expressionPlan":{"source":"required","ast":{"kind":"id","name":"required"},"dependencies":["required"]}},{"kind":"attribute","name":"name","expression":"name","expressionPlan":{"source":"name","ast":{"kind":"id","name":"name"},"dependencies":["name"]}},{"kind":"attribute","name":"value","expression":"value","expressionPlan":{"source":"value","ast":{"kind":"id","name":"value"},"dependencies":["value"]}}],"children":[],"ref":"input"},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"text"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"label"}],"children":[{"kind":"slot"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"description"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[{"kind":"slot","fallback":[],"name":"description"}],"ref":"description"}]}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-checkbox-gap {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-checkbox-size {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-checkbox-size: var(--ui-checkbox-size);\n\n display: inline-flex;\n align-items: flex-start;\n gap: var(--ui-checkbox-gap, var(--ui-space-2));\n max-inline-size: 100%;\n color: var(--ui-text-primary);\n cursor: pointer;\n }\n\n /* The label, and under it an optional line saying what the choice means. */\n .text {\n display: flex;\n flex-direction: column;\n gap: var(--ui-space-1);\n min-inline-size: 0;\n }\n\n .label {\n min-inline-size: 0;\n line-height: var(--ui-line-height-md);\n }\n\n .description {\n color: var(--ui-text-secondary);\n font-size: var(--ui-font-size-sm);\n line-height: var(--ui-line-height);\n }\n\n .description:empty {\n display: none;\n }\n\n input {\n appearance: none;\n -webkit-appearance: none;\n position: relative;\n flex: 0 0 auto;\n inline-size: var(--_ui-checkbox-size, 1.125rem);\n block-size: var(--_ui-checkbox-size, 1.125rem);\n margin: 0.125em 0 0;\n border: 1px solid var(--ui-control-border-hover, var(--ui-border-strong));\n border-radius: var(--ui-radius-sm);\n background: var(--ui-control-surface, var(--ui-surface-default));\n box-shadow: inset 0 1px 2px color-mix(in srgb, var(--ui-text-primary) 8%, transparent);\n cursor: pointer;\n transition:\n background-color var(--ui-motion-fast) var(--ui-motion-ease),\n border-color var(--ui-motion-fast) var(--ui-motion-ease),\n box-shadow var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n input::after {\n content: \"\";\n position: absolute;\n opacity: 0;\n }\n\n input:checked,\n input:indeterminate {\n border-color: var(--ui-accent-solid);\n background: var(--ui-accent-solid);\n box-shadow: inset 0 1px 2px color-mix(in srgb, #000 16%, transparent);\n }\n\n /* Centre the tick's box, then lift it: a rotated L's ink sits ~0.11rem below its box centre. */\n input:checked::after {\n inset: 0;\n margin: auto;\n inline-size: 0.32rem;\n block-size: 0.58rem;\n /* Longhands, not `border: solid var(...)`: lowering drops a shorthand that omits a\n component, which left the tick with no style and no colour. */\n border-style: solid;\n border-color: var(--ui-text-on-accent);\n border-width: 0 0.125rem 0.125rem 0;\n opacity: 1;\n transform: translateY(-0.11rem) rotate(45deg);\n }\n\n input:indeterminate::after {\n inset: 50% 0.23rem auto;\n block-size: 0.125rem;\n border-radius: var(--ui-radius-round);\n background: var(--ui-text-on-accent);\n opacity: 1;\n transform: translateY(-50%);\n }\n\n input:hover:enabled {\n border-color: var(--ui-accent-solid);\n }\n\n input:focus-visible {\n outline: 2px solid var(--ui-focus-ring, var(--ui-accent-solid));\n outline-offset: 2px;\n }\n\n :host-state([disabled]) {\n color: var(--ui-disabled-text);\n cursor: not-allowed;\n }\n :host-state([disabled]) input {\n border-color: var(--ui-border-default);\n background: var(--ui-control-surface-disabled, var(--ui-surface-muted));\n cursor: not-allowed;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"internalChecked","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"event","name":"change","type":"object({ checked: boolean, value: string, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false}],"slots":[{"dynamic":false,"required":true},{"dynamic":false,"required":true,"name":"description"}],"root":{"kind":"native","element":"label","choices":["label"]},"controller":"./components/ui-checkbox/ui-checkbox.js"},{"source":{"file":"./components/ui-cluster/ui-cluster.html"},"contract":{"version":1,"name":"UiCluster","tag":"ui-cluster","nativeElement":"div","props":{"align":{"type":{"enum":["start","center","end","stretch"]},"required":false,"target":{"attribute":"align"},"description":"How items line up within each row: center (the default) aligns their middles, start their tops, end their bottoms, and stretch makes every item as tall as\n its row."},"gap":{"type":{"enum":["xs","s","m","l","xl"]},"required":false,"target":{"attribute":"gap"},"description":"Space between items, on the spacing scale: xs is 0.5rem, s 0.75rem (also the default), m 1rem, l 1.5rem, and xl 2rem. The --ui-cluster-gap custom property,\n set on the cluster itself, overrides it; set on an ancestor, it does nothing."},"justify":{"type":{"enum":["start","center","end","between"]},"required":false,"target":{"attribute":"justify"},"description":"Where items sit along each row: start (the default), center, end, or between, which pushes the first and last items to the ends of the row and spreads the\n spare space between them, as for a title with its actions."}}},"template":{"kind":"element","name":"div","attributes":[],"children":[{"kind":"slot"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-cluster-gap {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n --_layout-gap: var(--ui-space-3);\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--ui-cluster-gap, var(--_layout-gap));\n min-inline-size: 0;\n max-inline-size: 100%;\n margin: 0;\n }\n\n :host-state([gap=\"xs\"]) {\n --_layout-gap: var(--ui-space-2);\n }\n :host-state([gap=\"s\"]) {\n --_layout-gap: var(--ui-space-3);\n }\n :host-state([gap=\"m\"]) {\n --_layout-gap: var(--ui-space-4);\n }\n :host-state([gap=\"l\"]) {\n --_layout-gap: var(--ui-space-5);\n }\n :host-state([gap=\"xl\"]) {\n --_layout-gap: var(--ui-space-6);\n }\n :host-state([align=\"start\"]) {\n align-items: flex-start;\n }\n :host-state([align=\"end\"]) {\n align-items: flex-end;\n }\n :host-state([align=\"stretch\"]) {\n align-items: stretch;\n }\n :host-state([justify=\"center\"]) {\n justify-content: center;\n }\n :host-state([justify=\"end\"]) {\n justify-content: flex-end;\n }\n :host-state([justify=\"between\"]) {\n justify-content: space-between;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]}},{"source":{"file":"./components/ui-combobox/ui-combobox.html"},"contract":{"version":1,"name":"UiCombobox","tag":"ui-combobox","nativeElement":"div","props":{"allowCreate":{"type":"boolean","required":false,"target":{"attribute":"allowcreate"},"description":"Offers the current query as a new option, reported as create-item. When nothing else matches, the offer is highlighted, so Enter creates it; with nothing\n highlighted, Enter in multiple mode commits the typed text as a token separator does.","default":false},"allowFreeText":{"type":"boolean","required":false,"target":{"attribute":"allowfreetext"},"description":"Allows values that do not match an authored option.","default":false},"clearable":{"type":"boolean","required":false,"target":{"attribute":"clearable"},"description":"Adds a clear button to the field that empties the input and clears the selection, reported as value-change with kind \"clear\". In multiple mode it clears\n only the typed text; chosen items stay.","default":false},"disabled":{"type":"boolean","required":false,"target":{"attribute":"disabled"},"description":"Disables the input and every button in the field: the chosen-item badges, the clear and disclosure buttons, and the help button. The list closes and cannot\n be opened, the value cannot be cleared, and a named combobox submits nothing with its form.","default":false},"disclosure":{"type":"boolean","required":false,"target":{"attribute":"disclosure"},"description":"Adds a chevron button that opens and closes the full, unfiltered list of options, for users who would rather browse than type. ArrowDown opens the same\n list with or without it.","default":false},"help":{"type":"string","required":false,"target":{"attribute":"help"},"description":"Help text for the field. When set, a help button appears beside the field and opens a tooltip with this text; while it is open, the input is described by\n it.","default":""},"items":{"type":{"kind":"list","item":{"kind":"object","fields":[{"name":"id","type":{"kind":"terminal","name":"string"},"optional":false},{"name":"value","type":{"kind":"terminal","name":"string"},"optional":false},{"name":"label","type":{"kind":"terminal","name":"string"},"optional":false},{"name":"group","type":{"kind":"terminal","name":"string"},"optional":true},{"name":"disabled","type":{"kind":"terminal","name":"boolean"},"optional":true}],"open":false}},"required":false,"target":{"attribute":"items"},"description":"The selected items in multiple mode, as JSON; a named combobox submits each one's value. A form reset returns to these items, or to none when unset."},"label":{"type":"string","required":false,"target":{"attribute":"label"},"description":"The field's label, tied to its input and shown above it; required adds an asterisk. It also names the suggestion list. Pair it with\n labelVisibility=\"sr-only\" when the context already labels the field visibly.","default":""},"labelVisibility":{"type":{"enum":["visible","sr-only"]},"required":false,"target":{"attribute":"labelvisibility"},"description":"visible shows the label above the field; sr-only hides it visually but keeps it as the input's accessible name. Use sr-only only when the surrounding\n layout already makes the field's purpose clear.","default":"visible"},"multiple":{"type":"boolean","required":false,"target":{"attribute":"multiple"},"description":"Lets the user choose several options. Each choice becomes a removable badge before the input, the list stays open between picks, and choosing a checked\n option removes it. value-change then reports the whole list of items, and selected-values-change the list of their values; use selectedValues or items,\n not value, in this mode.","default":false},"name":{"type":"string","required":false,"target":{"attribute":"name"},"description":"The form field name the combobox submits its value under, never the label shown in the field. Single mode sends one entry: the selected option's value, the\n typed text when allowFreeText is set and no option is selected, or an empty string. Multiple mode sends one entry per chosen item's value, and nothing\n when none is chosen. A disabled combobox sends nothing.","default":""},"placeholder":{"type":"string","required":false,"target":{"attribute":"placeholder"},"description":"Hint text shown in the empty input, as on a native input. It disappears as the user types, so it never replaces label.","default":""},"query":{"type":"string","required":false,"target":{"attribute":"query"},"description":"The input's text, when the consumer controls it. Once set, the consumer owns the text: typing reports query-change, and the input returns to query unless\n query is updated to match. Leave it unset to let the combobox manage its own text, showing the chosen option's label."},"readonly":{"type":"boolean","required":false,"target":{"attribute":"readonly"},"description":"Shows the current value without letting it change: the text can be selected but not edited, the list does not open, and the clear, disclosure, and badge\n remove buttons are disabled. A named combobox still submits its value.","default":false},"required":{"type":"boolean","required":false,"target":{"attribute":"required"},"description":"Requires a value: adds an asterisk to the label, marks the input required for native form validation, and makes validation report \"A value is required.\"\n when the field is left empty. In multiple mode a chosen item satisfies it, whatever is left in the input.","default":false},"selectedValues":{"type":{"kind":"list","item":{"kind":"terminal","name":"string"}},"required":false,"target":{"attribute":"selectedvalues"},"description":"The selected option values in multiple mode, when the consumer controls the selection. Once set, the consumer owns it: each value shows as a badge with its\n authored option's label, adding or removing one reports selected-values-change with the new list, and the badges follow selectedValues, not the user,\n unless it is updated to match. Setting it reports nothing. It takes precedence over items; leave it unset to let the combobox keep its own\n selection."},"size":{"type":{"enum":["sm","md"]},"required":false,"target":{"attribute":"size"},"description":"Field height. md is the standard control height; sm is the small control height with tighter padding, for dense forms.","default":"md"},"tokenSeparators":{"type":{"kind":"list","item":{"kind":"terminal","name":"string"}},"required":false,"target":{"attribute":"tokenseparators"},"description":"Keys that commit the typed text in multiple mode, as KeyboardEvent key values such as \",\" or \";\". The text is added as the option whose label matches it,\n ignoring case, or with allowCreate is reported as create-item; otherwise it stays in the input."},"value":{"type":{"kind":"union","members":[{"kind":"terminal","name":"string"},{"kind":"terminal","name":"null"}]},"required":false,"target":{"attribute":"value"},"description":"The selected value in single mode, which a named combobox submits with its form. The field shows the matching option's label, and a form reset returns to\n this value."}}},"template":{"kind":"element","name":"div","attributes":[],"children":[{"kind":"element","name":"label","attributes":[{"kind":"attribute","name":"for","expression":"format('%s-input', uid)","expressionPlan":{"source":"format('%s-input', uid)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s-input"},{"kind":"id","name":"uid"}]},"dependencies":["uid"]}},{"kind":"attribute","name":"sr-only","expression":"labelVisibility = 'sr-only'","expressionPlan":{"source":"labelVisibility = 'sr-only'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"labelVisibility"},"right":{"kind":"literal","value":"sr-only"}},"dependencies":["labelVisibility"]},"target":"class"}],"children":[{"kind":"element","name":"template","attributes":[{"kind":"directive","name":"value","expression":"label","expressionPlan":{"source":"label","ast":{"kind":"id","name":"label"},"dependencies":["label"]}}],"children":[]},{"kind":"element","name":"template","attributes":[],"children":[{"kind":"text","value":"\n *"}],"flow":{"kind":"if","test":"required","testPlan":{"source":"required","ast":{"kind":"id","name":"required"},"dependencies":["required"]}}}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"control"}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"field"}],"children":[{"kind":"slot","fallback":[],"name":"start"},{"kind":"element","name":"template","attributes":[],"children":[{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"class","value":"item"},{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"tabindex","value":"-1"},{"kind":"attribute","name":"data-index","expression":"index","expressionPlan":{"source":"index","ast":{"kind":"id","name":"index"},"dependencies":["index"]}},{"kind":"attribute","name":"disabled","expression":"disabled or readonly or item.disabled","expressionPlan":{"source":"disabled or readonly or item.disabled","ast":{"kind":"binary","op":"or","left":{"kind":"binary","op":"or","left":{"kind":"id","name":"disabled"},"right":{"kind":"id","name":"readonly"}},"right":{"kind":"member","object":{"kind":"id","name":"item"},"key":"disabled"}},"dependencies":["disabled","item.disabled","readonly"]}},{"kind":"attribute","name":"aria-label","expression":"format('%s, press Delete or Backspace to remove', item.label)","expressionPlan":{"source":"format('%s, press Delete or Backspace to remove', item.label)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s, press Delete or Backspace to remove"},{"kind":"member","object":{"kind":"id","name":"item"},"key":"label"}]},"dependencies":["item.label"]}}],"children":[{"kind":"slot","fallback":[{"kind":"element","name":"ui-badge","attributes":[{"kind":"directive","name":"value","expression":"item.label","expressionPlan":{"source":"item.label","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"label"},"dependencies":["item.label"]}}],"children":[]}],"nameExpression":{"source":"format('item-%s', item.id)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"item-%s"},{"kind":"member","object":{"kind":"id","name":"item"},"key":"id"}]},"dependencies":["item.id"]}}],"flow":{"kind":"each","item":"item","list":"internalItems","listPlan":{"source":"internalItems","ast":{"kind":"id","name":"internalItems"},"dependencies":["internalItems"]},"index":"index","key":"item.id","keyPlan":{"source":"item.id","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"id"},"dependencies":["item.id"]}}}],"flow":{"kind":"if","test":"multiple","testPlan":{"source":"multiple","ast":{"kind":"id","name":"multiple"},"dependencies":["multiple"]}}},{"kind":"element","name":"input","attributes":[{"kind":"attribute","name":"id","expression":"format('%s-input', uid)","expressionPlan":{"source":"format('%s-input', uid)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s-input"},{"kind":"id","name":"uid"}]},"dependencies":["uid"]}},{"kind":"literal","name":"role","value":"combobox"},{"kind":"literal","name":"aria-autocomplete","value":"list"},{"kind":"literal","name":"autocomplete","value":"off"},{"kind":"attribute","name":"aria-controls","expression":"format('%s-listbox', uid)","expressionPlan":{"source":"format('%s-listbox', uid)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s-listbox"},{"kind":"id","name":"uid"}]},"dependencies":["uid"]}},{"kind":"attribute","name":"aria-expanded","expression":"expanded","expressionPlan":{"source":"expanded","ast":{"kind":"id","name":"expanded"},"dependencies":["expanded"]}},{"kind":"attribute","name":"aria-invalid","expression":"validationStatus = 'error'","expressionPlan":{"source":"validationStatus = 'error'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"validationStatus"},"right":{"kind":"literal","value":"error"}},"dependencies":["validationStatus"]}},{"kind":"attribute","name":"aria-busy","expression":"validationStatus = 'pending'","expressionPlan":{"source":"validationStatus = 'pending'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"validationStatus"},"right":{"kind":"literal","value":"pending"}},"dependencies":["validationStatus"]}},{"kind":"property","key":"value","name":"value","expression":"display","expressionPlan":{"source":"display","ast":{"kind":"id","name":"display"},"dependencies":["display"]}},{"kind":"attribute","name":"placeholder","expression":"placeholder","expressionPlan":{"source":"placeholder","ast":{"kind":"id","name":"placeholder"},"dependencies":["placeholder"]}},{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}},{"kind":"attribute","name":"readonly","expression":"readonly","expressionPlan":{"source":"readonly","ast":{"kind":"id","name":"readonly"},"dependencies":["readonly"]}},{"kind":"attribute","name":"required","expression":"required and not (multiple and internalItems[0])","expressionPlan":{"source":"required and not (multiple and internalItems[0])","ast":{"kind":"binary","op":"and","left":{"kind":"id","name":"required"},"right":{"kind":"unary","op":"not","operand":{"kind":"binary","op":"and","left":{"kind":"id","name":"multiple"},"right":{"kind":"index","object":{"kind":"id","name":"internalItems"},"index":{"kind":"literal","value":0}}}}},"dependencies":["internalItems.0","multiple","required"]}}],"children":[],"ref":"input"},{"kind":"element","name":"input","attributes":[{"kind":"literal","name":"type","value":"hidden"},{"kind":"attribute","name":"name","expression":"name","expressionPlan":{"source":"name","ast":{"kind":"id","name":"name"},"dependencies":["name"]}},{"kind":"attribute","name":"value","expression":"submitted","expressionPlan":{"source":"submitted","ast":{"kind":"id","name":"submitted"},"dependencies":["submitted"]}},{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}}],"children":[],"flow":{"kind":"if","test":"name and not multiple","testPlan":{"source":"name and not multiple","ast":{"kind":"binary","op":"and","left":{"kind":"id","name":"name"},"right":{"kind":"unary","op":"not","operand":{"kind":"id","name":"multiple"}}},"dependencies":["multiple","name"]}}},{"kind":"element","name":"template","attributes":[],"children":[{"kind":"element","name":"input","attributes":[{"kind":"literal","name":"type","value":"hidden"},{"kind":"attribute","name":"name","expression":"name","expressionPlan":{"source":"name","ast":{"kind":"id","name":"name"},"dependencies":["name"]}},{"kind":"attribute","name":"value","expression":"item.value","expressionPlan":{"source":"item.value","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"value"},"dependencies":["item.value"]}},{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}}],"children":[],"flow":{"kind":"each","item":"item","list":"internalItems","listPlan":{"source":"internalItems","ast":{"kind":"id","name":"internalItems"},"dependencies":["internalItems"]},"key":"item.id","keyPlan":{"source":"item.id","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"id"},"dependencies":["item.id"]}}}],"flow":{"kind":"if","test":"name and multiple","testPlan":{"source":"name and multiple","ast":{"kind":"binary","op":"and","left":{"kind":"id","name":"name"},"right":{"kind":"id","name":"multiple"}},"dependencies":["multiple","name"]}}},{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"data-combobox-action","value":"clear"},{"kind":"literal","name":"aria-label","value":"Clear"},{"kind":"attribute","name":"disabled","expression":"disabled or readonly","expressionPlan":{"source":"disabled or readonly","ast":{"kind":"binary","op":"or","left":{"kind":"id","name":"disabled"},"right":{"kind":"id","name":"readonly"}},"dependencies":["disabled","readonly"]}}],"children":[{"kind":"element","name":"svg","attributes":[{"kind":"literal","name":"class","value":"affordance-icon"},{"kind":"literal","name":"aria-hidden","value":"true"},{"kind":"literal","name":"viewBox","value":"0 0 24 24"},{"kind":"literal","name":"fill","value":"none"},{"kind":"literal","name":"stroke","value":"currentColor"},{"kind":"literal","name":"stroke-width","value":"2"},{"kind":"literal","name":"stroke-linecap","value":"round"}],"children":[{"kind":"element","name":"path","attributes":[{"kind":"literal","name":"d","value":"M7 7l10 10M17 7 7 17"}],"children":[]}]}],"flow":{"kind":"if","test":"clearable","testPlan":{"source":"clearable","ast":{"kind":"id","name":"clearable"},"dependencies":["clearable"]}}},{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"data-combobox-action","value":"disclosure"},{"kind":"literal","name":"tabindex","value":"-1"},{"kind":"literal","name":"aria-label","value":"Show suggestions"},{"kind":"attribute","name":"aria-controls","expression":"format('%s-listbox', uid)","expressionPlan":{"source":"format('%s-listbox', uid)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s-listbox"},{"kind":"id","name":"uid"}]},"dependencies":["uid"]}},{"kind":"attribute","name":"disabled","expression":"disabled or readonly","expressionPlan":{"source":"disabled or readonly","ast":{"kind":"binary","op":"or","left":{"kind":"id","name":"disabled"},"right":{"kind":"id","name":"readonly"}},"dependencies":["disabled","readonly"]}}],"children":[{"kind":"element","name":"svg","attributes":[{"kind":"literal","name":"class","value":"affordance-icon"},{"kind":"literal","name":"aria-hidden","value":"true"},{"kind":"literal","name":"viewBox","value":"0 0 24 24"},{"kind":"literal","name":"fill","value":"none"},{"kind":"literal","name":"stroke","value":"currentColor"},{"kind":"literal","name":"stroke-width","value":"2.25"},{"kind":"literal","name":"stroke-linecap","value":"round"},{"kind":"literal","name":"stroke-linejoin","value":"round"}],"children":[{"kind":"element","name":"path","attributes":[{"kind":"literal","name":"d","value":"m6 9 6 6 6-6"}],"children":[]}]}],"flow":{"kind":"if","test":"disclosure","testPlan":{"source":"disclosure","ast":{"kind":"id","name":"disclosure"},"dependencies":["disclosure"]}}}],"ref":"field"},{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"class","value":"help"},{"kind":"attribute","name":"id","expression":"format('%s-help', uid)","expressionPlan":{"source":"format('%s-help', uid)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s-help"},{"kind":"id","name":"uid"}]},"dependencies":["uid"]}},{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"aria-label","value":"Help"},{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}}],"children":[{"kind":"element","name":"svg","attributes":[{"kind":"literal","name":"class","value":"help-icon"},{"kind":"literal","name":"aria-hidden","value":"true"},{"kind":"literal","name":"viewBox","value":"0 0 24 24"},{"kind":"literal","name":"fill","value":"none"},{"kind":"literal","name":"stroke","value":"currentColor"},{"kind":"literal","name":"stroke-width","value":"2"},{"kind":"literal","name":"stroke-linecap","value":"round"},{"kind":"literal","name":"stroke-linejoin","value":"round"}],"children":[{"kind":"element","name":"circle","attributes":[{"kind":"literal","name":"cx","value":"12"},{"kind":"literal","name":"cy","value":"12"},{"kind":"literal","name":"r","value":"10"}],"children":[]},{"kind":"element","name":"path","attributes":[{"kind":"literal","name":"d","value":"M9.1 9a3 3 0 0 1 5.8 1c0 2-3 3-3 3"}],"children":[]},{"kind":"element","name":"path","attributes":[{"kind":"literal","name":"d","value":"M12 17h.01"}],"children":[]}]}],"flow":{"kind":"if","test":"help","testPlan":{"source":"help","ast":{"kind":"id","name":"help"},"dependencies":["help"]}}}]},{"kind":"element","name":"ui-tooltip","attributes":[{"kind":"literal","name":"trigger","value":"click"},{"kind":"attribute","name":"id","expression":"format('%s-help-text', uid)","expressionPlan":{"source":"format('%s-help-text', uid)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s-help-text"},{"kind":"id","name":"uid"}]},"dependencies":["uid"]}},{"kind":"attribute","name":"for","expression":"format('%s-help', uid)","expressionPlan":{"source":"format('%s-help', uid)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s-help"},{"kind":"id","name":"uid"}]},"dependencies":["uid"]}}],"children":[{"kind":"element","name":"template","attributes":[{"kind":"directive","name":"value","expression":"help","expressionPlan":{"source":"help","ast":{"kind":"id","name":"help"},"dependencies":["help"]}}],"children":[]}],"flow":{"kind":"if","test":"help","testPlan":{"source":"help","ast":{"kind":"id","name":"help"},"dependencies":["help"]}}},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"popup"},{"kind":"attribute","name":"hidden","expression":"not expanded","expressionPlan":{"source":"not expanded","ast":{"kind":"unary","op":"not","operand":{"kind":"id","name":"expanded"}},"dependencies":["expanded"]}}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"role","value":"listbox"},{"kind":"attribute","name":"id","expression":"format('%s-listbox', uid)","expressionPlan":{"source":"format('%s-listbox', uid)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s-listbox"},{"kind":"id","name":"uid"}]},"dependencies":["uid"]}},{"kind":"attribute","name":"aria-label","expression":"format('%s suggestions', label)","expressionPlan":{"source":"format('%s suggestions', label)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s suggestions"},{"kind":"id","name":"label"}]},"dependencies":["label"]}},{"kind":"attribute","name":"aria-busy","expression":"loading","expressionPlan":{"source":"loading","ast":{"kind":"id","name":"loading"},"dependencies":["loading"]}}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"attribute","name":"role","expression":"group.role","expressionPlan":{"source":"group.role","ast":{"kind":"member","object":{"kind":"id","name":"group"},"key":"role"},"dependencies":["group.role"]}},{"kind":"attribute","name":"aria-label","expression":"group.label","expressionPlan":{"source":"group.label","ast":{"kind":"member","object":{"kind":"id","name":"group"},"key":"label"},"dependencies":["group.label"]}}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"group"},{"kind":"directive","name":"value","expression":"group.name","expressionPlan":{"source":"group.name","ast":{"kind":"member","object":{"kind":"id","name":"group"},"key":"name"},"dependencies":["group.name"]}}],"children":[],"flow":{"kind":"if","test":"group.name","testPlan":{"source":"group.name","ast":{"kind":"member","object":{"kind":"id","name":"group"},"key":"name"},"dependencies":["group.name"]}}},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"option"},{"kind":"attribute","name":"active","expression":"row.index = active","expressionPlan":{"source":"row.index = active","ast":{"kind":"binary","op":"=","left":{"kind":"member","object":{"kind":"id","name":"row"},"key":"index"},"right":{"kind":"id","name":"active"}},"dependencies":["active","row.index"]},"target":"class"},{"kind":"literal","name":"role","value":"option"},{"kind":"attribute","name":"id","expression":"format('%s-option-%s', uid, row.index)","expressionPlan":{"source":"format('%s-option-%s', uid, row.index)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s-option-%s"},{"kind":"id","name":"uid"},{"kind":"member","object":{"kind":"id","name":"row"},"key":"index"}]},"dependencies":["row.index","uid"]}},{"kind":"attribute","name":"aria-selected","expression":"row.selected","expressionPlan":{"source":"row.selected","ast":{"kind":"member","object":{"kind":"id","name":"row"},"key":"selected"},"dependencies":["row.selected"]}},{"kind":"attribute","name":"aria-disabled","expression":"row.disabled","expressionPlan":{"source":"row.disabled","ast":{"kind":"member","object":{"kind":"id","name":"row"},"key":"disabled"},"dependencies":["row.disabled"]}},{"kind":"attribute","name":"data-index","expression":"row.index","expressionPlan":{"source":"row.index","ast":{"kind":"member","object":{"kind":"id","name":"row"},"key":"index"},"dependencies":["row.index"]}}],"children":[{"kind":"slot","fallback":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"primary"},{"kind":"directive","name":"value","expression":"row.label","expressionPlan":{"source":"row.label","ast":{"kind":"member","object":{"kind":"id","name":"row"},"key":"label"},"dependencies":["row.label"]}}],"children":[]}],"nameExpression":{"source":"format('option-%s', row.id)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"option-%s"},{"kind":"member","object":{"kind":"id","name":"row"},"key":"id"}]},"dependencies":["row.id"]}}],"flow":{"kind":"each","item":"row","list":"group.rows","listPlan":{"source":"group.rows","ast":{"kind":"member","object":{"kind":"id","name":"group"},"key":"rows"},"dependencies":["group.rows"]},"key":"row.id","keyPlan":{"source":"row.id","ast":{"kind":"member","object":{"kind":"id","name":"row"},"key":"id"},"dependencies":["row.id"]}}}],"flow":{"kind":"each","item":"group","list":"groups","listPlan":{"source":"groups","ast":{"kind":"id","name":"groups"},"dependencies":["groups"]},"key":"group.name","keyPlan":{"source":"group.name","ast":{"kind":"member","object":{"kind":"id","name":"group"},"key":"name"},"dependencies":["group.name"]}}},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"option"},{"kind":"attribute","name":"active","expression":"createIndex = active","expressionPlan":{"source":"createIndex = active","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"createIndex"},"right":{"kind":"id","name":"active"}},"dependencies":["active","createIndex"]},"target":"class"},{"kind":"literal","name":"role","value":"option"},{"kind":"literal","name":"aria-selected","value":"false"},{"kind":"attribute","name":"id","expression":"format('%s-option-%s', uid, createIndex)","expressionPlan":{"source":"format('%s-option-%s', uid, createIndex)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s-option-%s"},{"kind":"id","name":"uid"},{"kind":"id","name":"createIndex"}]},"dependencies":["createIndex","uid"]}},{"kind":"attribute","name":"data-index","expression":"createIndex","expressionPlan":{"source":"createIndex","ast":{"kind":"id","name":"createIndex"},"dependencies":["createIndex"]}},{"kind":"directive","name":"value","expression":"format('Create “%s”', raw)","expressionPlan":{"source":"format('Create “%s”', raw)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"Create “%s”"},{"kind":"id","name":"raw"}]},"dependencies":["raw"]}}],"children":[],"flow":{"kind":"if","test":"creatable","testPlan":{"source":"creatable","ast":{"kind":"id","name":"creatable"},"dependencies":["creatable"]}}},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"message"},{"kind":"directive","name":"value","expression":"message","expressionPlan":{"source":"message","ast":{"kind":"id","name":"message"},"dependencies":["message"]}}],"children":[],"flow":{"kind":"if","test":"message","testPlan":{"source":"message","ast":{"kind":"id","name":"message"},"dependencies":["message"]}}}],"ref":"listbox"},{"kind":"slot","fallback":[],"name":"footer"}],"ref":"popup"},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"message"},{"kind":"attribute","name":"id","expression":"format('%s-validation', uid)","expressionPlan":{"source":"format('%s-validation', uid)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s-validation"},{"kind":"id","name":"uid"}]},"dependencies":["uid"]}},{"kind":"attribute","name":"hidden","expression":"not validation.issues.length","expressionPlan":{"source":"not validation.issues.length","ast":{"kind":"unary","op":"not","operand":{"kind":"member","object":{"kind":"member","object":{"kind":"id","name":"validation"},"key":"issues"},"key":"length"}},"dependencies":["validation.issues.length"]}}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"directive","name":"value","expression":"issue.message","expressionPlan":{"source":"issue.message","ast":{"kind":"member","object":{"kind":"id","name":"issue"},"key":"message"},"dependencies":["issue.message"]}}],"children":[],"flow":{"kind":"each","item":"issue","list":"validation.issues","listPlan":{"source":"validation.issues","ast":{"kind":"member","object":{"kind":"id","name":"validation"},"key":"issues"},"dependencies":["validation.issues"]}}}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"sr-only"},{"kind":"literal","name":"role","value":"status"},{"kind":"literal","name":"aria-live","value":"polite"},{"kind":"literal","name":"aria-atomic","value":"true"},{"kind":"directive","name":"value","expression":"statusText","expressionPlan":{"source":"statusText","ast":{"kind":"id","name":"statusText"},"dependencies":["statusText"]}}],"children":[]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"authored-options"},{"kind":"literal","name":"hidden","value":""},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[{"kind":"slot"}],"ref":"options"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-combobox-affordance-text {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-combobox-item-input-min-inline-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-combobox-item-item-max-inline-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-combobox-item-min-block-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-combobox-label-font-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-combobox-label-text {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-combobox-max-block-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-combobox-message-text {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-combobox-option-check {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-combobox-option-text {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-combobox-label-text: var(--ui-combobox-label-text);\n --_ui-combobox-label-font-size: var(--ui-combobox-label-font-size);\n --_ui-combobox-affordance-text: var(--ui-combobox-affordance-text);\n --_ui-combobox-max-block-size: var(--ui-combobox-max-block-size);\n --_ui-combobox-option-text: var(--ui-combobox-option-text);\n --_ui-combobox-message-text: var(--ui-combobox-message-text);\n --_ui-combobox-option-check: var(--ui-combobox-option-check);\n --_ui-combobox-item-min-block-size: var(--ui-combobox-item-min-block-size);\n --_ui-combobox-item-input-min-inline-size: var(--ui-combobox-item-input-min-inline-size);\n --_ui-combobox-item-item-max-inline-size: var(--ui-combobox-item-item-max-inline-size);\n\n display: grid;\n gap: var(--ui-space-1);\n min-inline-size: 0;\n color: var(--ui-text-primary);\n font: inherit;\n }\n label {\n color: var(--_ui-combobox-label-text, var(--ui-text-primary));\n font-size: var(--_ui-combobox-label-font-size, var(--ui-font-size-sm));\n font-weight: 500;\n }\n /* The field and anything that annotates it sit on one row; the help button is beside the box,\n not inside it, because a control's box holds its value. */\n .control {\n display: flex;\n align-items: center;\n gap: var(--ui-space-2);\n min-inline-size: 0;\n }\n\n .field {\n flex: 1 1 auto;\n display: flex;\n min-inline-size: 0;\n border: 1px solid var(--ui-control-border, var(--ui-border-default));\n border-radius: var(--ui-radius-md);\n background: var(--ui-control-surface, var(--ui-surface-default));\n box-shadow: var(--ui-control-inset);\n transition: border-color var(--ui-motion-fast) var(--ui-motion-ease), box-shadow var(--ui-motion-fast) var(--ui-motion-ease);\n }\n .field:focus-within {\n border-color: var(--ui-control-focus, var(--ui-accent-solid));\n box-shadow:\n var(--ui-control-inset),\n var(--ui-control-focus-halo-shadow);\n }\n /* A ghost icon button: the affordance is the mark, not a box around it. */\n .help {\n flex: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n inline-size: var(--ui-control-size-sm);\n block-size: var(--ui-control-size-sm);\n padding: 0;\n border: 0;\n border-radius: var(--ui-radius-round);\n background: transparent;\n color: var(--ui-text-secondary);\n cursor: pointer;\n transition: background-color var(--ui-motion-fast) var(--ui-motion-ease), color var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n .help:hover:enabled,\n .help[aria-expanded=\"true\"] {\n background: color-mix(in srgb, currentColor 8%, transparent);\n color: var(--ui-text-primary);\n }\n\n .help:focus-visible {\n outline: none;\n box-shadow: var(--ui-focus-halo);\n }\n\n .help:disabled {\n color: var(--ui-disabled-text);\n cursor: not-allowed;\n }\n\n .help-icon {\n inline-size: var(--ui-icon-size-sm);\n block-size: var(--ui-icon-size-sm);\n }\n\n input::selection {\n background: color-mix(in srgb, var(--ui-accent-solid) 20%, transparent);\n color: inherit;\n }\n input {\n appearance: none;\n width: 100%;\n min-inline-size: 0;\n min-block-size: calc(var(--ui-control-size-md) - 2px);\n box-sizing: border-box;\n border: 0;\n border-radius: inherit;\n background: transparent;\n color: inherit;\n font: inherit;\n line-height: var(--ui-line-height-md);\n padding: var(--ui-space-2) var(--ui-space-3);\n margin: 0;\n outline: none;\n }\n :host-state([size=\"sm\"]) input {\n min-block-size: calc(var(--ui-control-size-sm) - 2px);\n padding: var(--ui-space-1) var(--ui-space-2);\n }\n button {\n appearance: none;\n display: inline-grid;\n place-items: center;\n align-self: stretch;\n border: 0;\n border-radius: var(--ui-radius-md);\n background: transparent;\n color: var(--_ui-combobox-affordance-text, var(--ui-text-secondary));\n font: inherit;\n font-weight: 400;\n min-inline-size: 2rem;\n padding: 0 var(--ui-space-1);\n cursor: pointer;\n }\n .affordance-icon {\n display: block;\n inline-size: var(--ui-icon-size-sm);\n block-size: var(--ui-icon-size-sm);\n }\n button:hover:enabled {\n background: var(--ui-surface-muted);\n color: var(--ui-text-primary);\n }\n button:focus-visible {\n outline: none;\n background: var(--ui-surface-muted);\n box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--ui-focus-ring) 45%, transparent);\n }\n input:disabled, button:disabled {\n color: var(--ui-disabled-text);\n cursor: not-allowed;\n }\n .field:has(input:disabled) {\n background: var(--ui-control-surface-disabled, var(--ui-surface-muted));\n }\n :host-state([validationStatus=\"error\"]) .field {\n border-color: var(--ui-danger-solid, var(--ui-accent-active));\n }\n .popup {\n box-sizing: border-box;\n min-inline-size: 12rem;\n max-inline-size: calc(100vw - 1rem);\n max-block-size: var(--_ui-combobox-max-block-size, 18rem);\n overflow: auto;\n margin: 0;\n padding: var(--ui-space-1);\n border: 1px solid var(--ui-border-default);\n border-radius: var(--ui-radius-md);\n background: var(--ui-surface-elevated);\n color: var(--ui-text-primary);\n box-shadow: var(--ui-elevation-overlay, var(--ui-shadow-lg));\n }\n [hidden] {\n display: none;\n }\n .option {\n padding: var(--ui-space-2) var(--ui-space-3);\n border-radius: var(--ui-radius-sm);\n cursor: pointer;\n overflow-wrap: anywhere;\n }\n .option:hover, .option.active {\n background: var(--ui-surface-muted);\n outline: 1px solid var(--ui-focus-ring);\n outline-offset: -1px;\n }\n .option[aria-disabled=\"true\"] {\n color: var(--ui-disabled-text);\n cursor: not-allowed;\n }\n .primary {\n display: block;\n color: var(--_ui-combobox-option-text, var(--ui-text-primary));\n font-weight: 500;\n }\n .message, .group {\n color: var(--_ui-combobox-message-text, var(--ui-text-secondary));\n font-weight: 400;\n font-size: var(--ui-font-size-sm);\n line-height: var(--ui-line-height-md);\n overflow-wrap: anywhere;\n }\n .group, .popup .message {\n padding: var(--ui-space-2) var(--ui-space-3);\n }\n .sr-only {\n position: absolute;\n inline-size: 1px;\n block-size: 1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n }\n @media (pointer: coarse) {\n button {\n min-inline-size: 2.75rem;\n min-block-size: 2.75rem;\n }\n }\n @media (forced-colors: active) {\n .field, .popup {\n border-color: CanvasText;\n }\n .option.active {\n outline-color: Highlight;\n }\n }\n\n /* Multiple mode: every option carries a checkbox, so a list that takes several answers says so\n before anything is picked. aria-selected is the state; this draws it.\n Longhands, not shorthands: lowering drops a shorthand that omits a component. */\n :host-state([multiple]) .option {\n display: flex;\n gap: var(--ui-space-2);\n align-items: center;\n }\n\n :host-state([multiple]) .option::before {\n content: \"\";\n flex: none;\n inline-size: 1.125rem;\n block-size: 1.125rem;\n border-style: solid;\n border-width: 1px;\n border-color: var(--ui-control-border-hover, var(--ui-border-strong));\n border-radius: var(--ui-radius-sm);\n background-color: var(--ui-control-surface, var(--ui-surface-default));\n background-repeat: no-repeat;\n background-position: center;\n background-size: 0.7rem;\n }\n\n :host-state([multiple]) .option[aria-selected=\"true\"]::before {\n border-color: var(--ui-accent-solid);\n background-color: var(--ui-accent-solid);\n background-image: var(\n --_ui-combobox-option-check,\n url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12 5 5 9-9'/%3E%3C/svg%3E\")\n );\n }\n\n /* Multiple mode: chips wrap before the cursor on one flexible field line. */\n :host-state([multiple]) .field {\n flex-wrap: wrap;\n align-items: center;\n gap: var(--ui-space-1);\n min-block-size: var(--_ui-combobox-item-min-block-size, 2.5rem);\n padding: var(--ui-space-1);\n }\n :host-state([multiple]) input {\n flex: 1 0 var(--_ui-combobox-item-input-min-inline-size, 5rem);\n width: auto;\n min-block-size: 1.75rem;\n padding: var(--ui-space-0-5) var(--ui-space-1);\n }\n .item {\n appearance: none;\n display: inline-flex;\n min-inline-size: 0;\n max-inline-size: min(100%, var(--_ui-combobox-item-item-max-inline-size, 12rem));\n overflow: hidden;\n padding: 0;\n border: 0;\n border-radius: var(--ui-radius-sm);\n background: transparent;\n color: inherit;\n font: inherit;\n cursor: default;\n }\n .item:focus-visible {\n outline: 2px solid var(--ui-focus-ring);\n outline-offset: 1px;\n }\n .item:disabled {\n opacity: 0.6;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"internalItems","type":"list(object({ id: string, value: string, label: string, group?: string, disabled?: boolean }))","expression":{"source":"[]","ast":{"kind":"array","items":[]},"dependencies":[]}},{"kind":"state","name":"raw","expression":{"source":"''","ast":{"kind":"literal","value":""},"dependencies":[]}},{"kind":"state","name":"display","expression":{"source":"''","ast":{"kind":"literal","value":""},"dependencies":[]}},{"kind":"state","name":"selected","type":"string | null","expression":{"source":"null","ast":{"kind":"literal","value":null},"dependencies":[]}},{"kind":"state","name":"expanded","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"rows","type":"list(object({ id: string, value: string, label: string, group?: string, disabled: boolean, selected: boolean }))","expression":{"source":"[]","ast":{"kind":"array","items":[]},"dependencies":[]}},{"kind":"state","name":"active","expression":{"source":"-1","ast":{"kind":"unary","op":"-","operand":{"kind":"literal","value":1}},"dependencies":[]}},{"kind":"state","name":"loading","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"helpOpen","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"lookupError","expression":{"source":"''","ast":{"kind":"literal","value":""},"dependencies":[]}},{"kind":"state","name":"validation","type":"object({ status: pristine | pending | valid | warning | error, touched: boolean, dirty: boolean, issues: list(object({ message: string })), ... })","expression":{"source":"{ status: 'pristine', touched: false, dirty: false, issues: [] }","ast":{"kind":"object","pairs":[{"key":"status","value":{"kind":"literal","value":"pristine"}},{"key":"touched","value":{"kind":"literal","value":false}},{"key":"dirty","value":{"kind":"literal","value":false}},{"key":"issues","value":{"kind":"array","items":[]}}]},"dependencies":[]}},{"kind":"state","name":"uid","expression":{"source":"''","ast":{"kind":"literal","value":""},"dependencies":[]}},{"kind":"state","name":"submitted","expression":{"source":"''","ast":{"kind":"literal","value":""},"dependencies":[]}},{"kind":"state","name":"groups","type":"list(object({ name: string, role: group | presentation, label: string | null, rows: list(object({ id: string, value: string, label: string, group?: string, disabled: boolean, selected: boolean, index: integer })) }))","expression":{"source":"[]","ast":{"kind":"array","items":[]},"dependencies":[]}},{"kind":"state","name":"creatable","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"createIndex","expression":{"source":"0","ast":{"kind":"literal","value":0},"dependencies":[]}},{"kind":"state","name":"message","expression":{"source":"''","ast":{"kind":"literal","value":""},"dependencies":[]}},{"kind":"state","name":"statusText","expression":{"source":"''","ast":{"kind":"literal","value":""},"dependencies":[]}},{"kind":"state","name":"validationStatus","expression":{"source":"'pristine'","ast":{"kind":"literal","value":"pristine"},"dependencies":[]}},{"kind":"event","name":"query-change","type":"object({ query: string, display: string, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"value-change","type":"object({ value: string | null, query: string, option: object({ id: string, value: string, label: string, group?: string, disabled?: boolean }) | null, kind: selection | clear | free-entry | create, trigger: keyboard | pointer | programmatic }) | list(object({ id: string, value: string, label: string, group?: string, disabled?: boolean }))","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"free-entry","type":"object({ value: string | null, query: string, option: object({ id: string, value: string, label: string, group?: string, disabled?: boolean }) | null, kind: selection | clear | free-entry | create, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"create-entry","type":"object({ value: string | null, query: string, option: object({ id: string, value: string, label: string, group?: string, disabled?: boolean }) | null, kind: selection | clear | free-entry | create, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"validation-change","type":"object({ status: pristine | pending | valid | warning | error, touched: boolean, dirty: boolean, issues: list(object({ message: string, path?: list(unknown), severity?: error | warning })), output?: unknown })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"options-change","type":"list(object({ id: string, value: string, label: string, group?: string, disabled?: boolean }))","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"add-item","type":"object({ item: object({ id: string, value: string, label: string, group?: string, disabled?: boolean }), index: integer, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"remove-item","type":"object({ item: object({ id: string, value: string, label: string, group?: string, disabled?: boolean }), index: integer, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"create-item","type":"object({ query: string, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"selected-values-change","type":"object({ selectedValues: list(string), trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"method","name":"validate","exportName":"validate","returns":"promise(unknown)"},{"kind":"method","name":"focusInput","exportName":"focusInput","returns":"promise(undefined)"}],"slots":[{"dynamic":false,"required":true,"name":"start"},{"dynamic":true,"required":false},{"dynamic":true,"required":false},{"dynamic":false,"required":true,"name":"footer"},{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-combobox/ui-combobox.js"},{"source":{"file":"./components/ui-container/ui-container.html"},"contract":{"version":1,"name":"UiContainer","tag":"ui-container","nativeElement":"div","props":{"gutters":{"type":{"enum":["s","m","l"]},"required":false,"target":{"attribute":"gutters"},"description":"Inline padding on both sides, which keeps content off the edges of a narrow screen: s is 0.75rem, m is 1rem (also the default), and l is 1.5rem."},"measure":{"type":{"enum":["narrow","wide"]},"required":false,"target":{"attribute":"measure"},"description":"The container's maximum width, in characters of the current font: narrow is 45ch, wide is 80ch, and unset is 65ch, a comfortable reading line. The\n container centres itself when its parent is wider. The --ui-container-measure custom property, set on the container itself, overrides it; set on an\n ancestor, it does nothing."}}},"template":{"kind":"element","name":"div","attributes":[],"children":[{"kind":"slot"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-container-gutters {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-container-measure {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n --_container-measure: 65ch;\n --_container-gutters: var(--ui-space-4);\n display: block;\n inline-size: 100%;\n max-inline-size: var(--ui-container-measure, var(--_container-measure));\n margin-inline: auto;\n padding-inline: var(--ui-container-gutters, var(--_container-gutters));\n }\n\n :host-state([measure=\"narrow\"]) {\n --_container-measure: 45ch;\n }\n :host-state([measure=\"wide\"]) {\n --_container-measure: 80ch;\n }\n :host-state([gutters=\"s\"]) {\n --_container-gutters: var(--ui-space-3);\n }\n :host-state([gutters=\"m\"]) {\n --_container-gutters: var(--ui-space-4);\n }\n :host-state([gutters=\"l\"]) {\n --_container-gutters: var(--ui-space-5);\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]}},{"source":{"file":"./components/ui-context-menu/ui-context-menu.html"},"contract":{"version":1,"name":"UiContextMenu","tag":"ui-context-menu","nativeElement":"span","props":{"for":{"type":"string","required":false,"target":{"attribute":"for"},"description":"ID of the element whose context click (right-click, long-press, Shift+F10, or the Menu key) opens the menu.","default":""},"open":{"type":"boolean","required":false,"target":{"attribute":"open"},"description":"Whether the context menu is open initially or when set externally.","default":false}}},"template":{"kind":"element","name":"span","attributes":[],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"menu"},{"kind":"literal","name":"role","value":"menu"},{"kind":"literal","name":"aria-orientation","value":"vertical"}],"children":[{"kind":"slot"}],"ref":"menu"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-context-menu-z-index {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-context-menu-z-index: var(--ui-context-menu-z-index);\n\n display: contents;\n }\n\n .menu {\n position: fixed;\n inset: auto;\n margin: 0;\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n padding: var(--ui-space-1);\n background: var(--ui-surface-elevated);\n border: 1px solid var(--ui-border-default);\n border-radius: var(--ui-radius-lg);\n box-shadow: var(--ui-elevation-overlay, var(--ui-shadow-lg));\n outline: 0;\n overflow: auto;\n z-index: var(--_ui-context-menu-z-index, 1000);\n min-width: 12rem;\n opacity: 0;\n transform: translateY(-4px) scale(0.99);\n transition:\n opacity var(--ui-motion-fast) var(--ui-motion-ease),\n transform var(--ui-motion-fast) var(--ui-motion-ease),\n display var(--ui-motion-fast) allow-discrete,\n overlay var(--ui-motion-fast) allow-discrete;\n }\n\n .menu:popover-open {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n\n @starting-style {\n .menu:popover-open {\n opacity: 0;\n transform: translateY(-4px) scale(0.99);\n }\n }\n\n .menu[hidden],\n .menu[popover]:not(:popover-open) {\n display: none;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .menu {\n transition: none;\n }\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"internalOpen","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"event","name":"open","type":"object({ open: boolean, reason: action | programmatic | light-dismiss | escape, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"close","type":"object({ open: boolean, reason: action | programmatic | light-dismiss | escape, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"select","type":"object({ value: string, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false}],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"span","choices":["span"]},"controller":"./components/ui-context-menu/ui-context-menu.js"},{"source":{"file":"./components/ui-cover/ui-cover.html"},"contract":{"version":1,"name":"UiCover","tag":"ui-cover","nativeElement":"div","props":{"size":{"type":{"enum":["screen","fill"]},"required":false,"target":{"attribute":"size"},"description":"How tall the cover is. screen is at least the viewport's height, for a view that is one centred card, such as sign-in; fill takes the space its parent\n gives it.","default":"screen"}}},"template":{"kind":"element","name":"div","attributes":[],"children":[{"kind":"slot"}]},"css":"/* A layout primitive that centres its content in the space, both ways, with room around it: the\n frame for a view that is one card or one message. */\n :host {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: var(--ui-space-6);\n box-sizing: border-box;\n min-block-size: 100dvh;\n padding: var(--ui-space-6) var(--ui-space-4);\n }\n\n :host-state([size=\"fill\"]) {\n flex: 1;\n min-block-size: 100%;\n }\n\n :host > :slotted(*) {\n max-inline-size: 100%;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]}},{"source":{"file":"./components/ui-description-item/ui-description-item.html"},"contract":{"version":1,"name":"UiDescriptionItem","tag":"ui-description-item","nativeElement":"div","props":{"term":{"type":"string","required":false,"target":{"attribute":"term"},"description":"What the value is, such as \"Invited by\". The value is the item's content.","default":""}}},"template":{"kind":"element","name":"div","attributes":[],"children":[{"kind":"element","name":"dt","attributes":[],"children":[{"kind":"element","name":"template","attributes":[{"kind":"directive","name":"value","expression":"term","expressionPlan":{"source":"term","ast":{"kind":"id","name":"term"},"dependencies":["term"]}}],"children":[]}]},{"kind":"element","name":"dd","attributes":[],"children":[{"kind":"slot"}]}]},"css":"/* One term and its value in a ui-description-list, laid out by the list's layout. */\n :host {\n display: var(--_ui-description-display, grid);\n grid-column: var(--_ui-description-column, 1 / -1);\n grid-template-columns: subgrid;\n flex-direction: column;\n align-items: var(--_ui-description-align, baseline);\n gap: var(--ui-space-1) var(--ui-space-6);\n min-inline-size: 0;\n padding: var(--_ui-description-padding, 0);\n border-width: var(--_ui-description-border-width, 0);\n border-style: solid;\n border-color: var(--ui-border-default);\n border-radius: var(--ui-radius-md);\n font-size: var(--ui-font-size-sm);\n }\n\n dt {\n color: var(--ui-text-muted);\n }\n\n dd {\n margin: 0;\n min-inline-size: 0;\n color: var(--ui-text-primary);\n font-weight: var(--ui-font-medium);\n font-size: var(--_ui-description-value-size, inherit);\n text-align: start;\n overflow-wrap: anywhere;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]}},{"source":{"file":"./components/ui-description-list/ui-description-list.html"},"contract":{"version":1,"name":"UiDescriptionList","tag":"ui-description-list","nativeElement":"dl","props":{"layout":{"type":{"enum":["rows","tiles"]},"required":false,"target":{"attribute":"layout"},"description":"rows sets each term beside its value, one per line, for a short summary; tiles sets each pair on its own bordered tile in a grid, term above value, for\n figures and facts to scan.","default":"rows"}}},"template":{"kind":"element","name":"dl","attributes":[],"children":[{"kind":"slot"}]},"css":"/* Named values: a term and what it is, for each item (ui-description-item). */\n /* Rows line every term up in one column and every value in the next, through subgrid. */\n :host {\n display: grid;\n grid-template-columns: minmax(6rem, max-content) minmax(0, 1fr);\n gap: var(--ui-space-2) var(--ui-space-6);\n min-inline-size: 0;\n margin: 0;\n }\n\n /* Tiles pass their shape to the items through private properties, which cross into each item. */\n :host-state([layout=\"tiles\"]) {\n --_ui-description-display: flex;\n --_ui-description-column: auto;\n --_ui-description-align: flex-start;\n --_ui-description-value-size: var(--ui-font-size-lg);\n --_ui-description-padding: var(--ui-space-3);\n --_ui-description-border-width: 1px;\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(min(100%, 10rem), 1fr));\n gap: var(--ui-space-3);\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"dl","choices":["dl"]}},{"source":{"file":"./components/ui-dialog/ui-dialog.html"},"contract":{"version":1,"name":"UiDialog","tag":"ui-dialog","nativeElement":"dialog","props":{"dismissible":{"type":"boolean","required":false,"target":{"attribute":"dismissible"},"description":"Also close on Escape and on a pointer press outside the dialog. The header close button and actions always close it.","default":false},"for":{"type":"string","required":false,"target":{"attribute":"for"},"description":"ID of the control that opens the dialog.","default":""},"label":{"type":"string","required":false,"target":{"attribute":"label"},"description":"Visible title in the dialog header; also its accessible name."},"modal":{"type":"boolean","required":false,"target":{"attribute":"modal"},"description":"Open in the top layer with a backdrop and make the rest of the page inert.","default":false},"open":{"type":"boolean","required":false,"target":{"attribute":"open"},"description":"Whether the dialog is open initially or when set externally.","default":false}}},"template":{"kind":"element","name":"dialog","attributes":[{"kind":"attribute","name":"aria-label","expression":"accessibleLabel","expressionPlan":{"source":"accessibleLabel","ast":{"kind":"id","name":"accessibleLabel"},"dependencies":["accessibleLabel"]}}],"children":[{"kind":"element","name":"header","attributes":[],"children":[{"kind":"element","name":"h2","attributes":[{"kind":"literal","name":"class","value":"title"},{"kind":"directive","name":"value","expression":"label","expressionPlan":{"source":"label","ast":{"kind":"id","name":"label"},"dependencies":["label"]}}],"children":[],"flow":{"kind":"if","test":"label","testPlan":{"source":"label","ast":{"kind":"id","name":"label"},"dependencies":["label"]}}},{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"class","value":"close"},{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"aria-label","value":"Close"}],"children":[],"ref":"close"}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"body"}],"children":[{"kind":"slot"}]},{"kind":"element","name":"footer","attributes":[],"children":[{"kind":"slot","fallback":[],"name":"actions"}]}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-dialog-duration {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-dialog-max-width {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-dialog-viewport-gap {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-dialog-duration: var(--ui-dialog-duration);\n\n position: fixed;\n inset: 0;\n box-sizing: border-box;\n inline-size: min(\n calc(100% - var(--ui-dialog-viewport-gap, var(--ui-space-4)) * 2),\n var(--ui-dialog-max-width, 440px)\n );\n max-inline-size: none;\n max-block-size: calc(100dvh - var(--ui-dialog-viewport-gap, var(--ui-space-4)) * 2);\n margin: auto;\n padding: 0;\n overflow: hidden;\n flex-direction: column;\n background: var(--ui-surface-elevated);\n border: 1px solid var(--ui-border-default);\n border-radius: var(--ui-radius-dialog);\n box-shadow: var(--ui-elevation-dialog, var(--ui-shadow-xl));\n visibility: hidden;\n pointer-events: none;\n opacity: 0;\n transform: scale(0.96);\n transition:\n opacity var(--ui-dialog-duration, var(--ui-motion-base)) var(--ui-motion-ease),\n transform var(--ui-dialog-duration, var(--ui-motion-base)) var(--ui-motion-ease),\n visibility var(--ui-dialog-duration, var(--ui-motion-base)),\n display var(--ui-dialog-duration, var(--ui-motion-base)) var(--ui-motion-ease) allow-discrete,\n overlay var(--ui-dialog-duration, var(--ui-motion-base)) var(--ui-motion-ease) allow-discrete;\n }\n\n :host[open] {\n display: flex;\n visibility: visible;\n pointer-events: auto;\n opacity: 1;\n transform: scale(1);\n animation: ui-dialog-enter var(--ui-dialog-duration, var(--ui-motion-base)) var(--ui-motion-ease);\n }\n\n /* Header and actions stay pinned; only the body scrolls when content is long. */\n header {\n display: flex;\n align-items: center;\n gap: var(--ui-space-3);\n flex: none;\n padding: var(--ui-space-3) var(--ui-space-3) var(--ui-space-3) var(--ui-space-5);\n border-block-end: 1px solid var(--ui-border-default);\n }\n\n /* :host-qualified so page heading rules that reach in cannot outrank the dialog chrome. */\n :host .title {\n flex: 1;\n min-inline-size: 0;\n margin: 0;\n padding: 0;\n border: 0;\n color: var(--ui-text-primary);\n letter-spacing: normal;\n font-size: var(--ui-font-size-lg);\n font-weight: var(--ui-font-semibold);\n line-height: var(--ui-line-height-tight);\n }\n\n .close {\n display: inline-grid;\n place-items: center;\n flex: none;\n margin-inline-start: auto;\n inline-size: var(--ui-control-size-sm);\n block-size: var(--ui-control-size-sm);\n padding: 0;\n border: 0;\n border-radius: var(--ui-radius-round);\n background: transparent;\n color: var(--ui-text-secondary);\n cursor: pointer;\n transition: background-color var(--ui-motion-fast) var(--ui-motion-ease), color var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n /* A CSS-drawn X. */\n .close::before,\n .close::after {\n content: \"\";\n grid-area: 1 / 1;\n inline-size: 0.875rem;\n block-size: 1.5px;\n border-radius: 1px;\n background: currentColor;\n transform: rotate(45deg);\n }\n\n .close::after {\n transform: rotate(-45deg);\n }\n\n .close:hover {\n background: var(--ui-surface-muted);\n color: var(--ui-text-primary);\n }\n\n .close:focus-visible {\n outline: 2px solid var(--ui-focus-ring);\n outline-offset: 2px;\n }\n\n /* A touch target, like Button on coarse pointers. */\n @media (pointer: coarse) {\n .close {\n inline-size: var(--ui-control-min-block-size);\n block-size: var(--ui-control-min-block-size);\n }\n }\n\n html[data-ui-input-modality=\"touch\"] :host .close {\n inline-size: var(--ui-control-min-block-size);\n block-size: var(--ui-control-min-block-size);\n }\n\n .body {\n flex: 1 1 auto;\n min-block-size: 0;\n overflow: auto;\n overscroll-behavior: contain;\n padding: var(--ui-space-5);\n /* Each edge that hides content fades: the scroll fade every Looma scroller uses (see ui-scroll-area). */\n --_ui-scroll-fade-direction: to bottom;\n --_ui-scroll-fade-size: var(--ui-scroll-fade-size, 24px);\n mask-image: linear-gradient(\n var(--_ui-scroll-fade-direction),\n transparent,\n #000 var(--_ui-scroll-fade-start),\n #000 calc(100% - var(--_ui-scroll-fade-end)),\n transparent\n );\n animation: ui-scroll-fade-start linear, ui-scroll-fade-start-hold linear, ui-scroll-fade-end-hold linear, ui-scroll-fade-end linear;\n animation-timeline: scroll(self block);\n animation-range:\n 0 var(--_ui-scroll-fade-size),\n var(--_ui-scroll-fade-size) calc(100% + 1px),\n -1px calc(100% - var(--_ui-scroll-fade-size)),\n calc(100% - var(--_ui-scroll-fade-size)) 100%;\n }\n\n footer {\n display: flex;\n flex: none;\n flex-wrap: wrap;\n justify-content: flex-end;\n gap: var(--ui-space-2);\n padding: var(--ui-space-3) var(--ui-space-5);\n border-block-start: 1px solid var(--ui-border-default);\n }\n\n footer:empty {\n display: none;\n }\n\n @keyframes ui-dialog-enter {\n from {\n opacity: 0;\n transform: scale(0.96);\n }\n }\n\n :host::backdrop {\n background-color: transparent;\n transition:\n background-color var(--_ui-dialog-duration, var(--ui-motion-base)) var(--ui-motion-ease),\n display var(--_ui-dialog-duration, var(--ui-motion-base)) var(--ui-motion-ease) allow-discrete,\n overlay var(--_ui-dialog-duration, var(--ui-motion-base)) var(--ui-motion-ease) allow-discrete;\n }\n\n :host[open]::backdrop {\n background-color: var(--ui-overlay-backdrop);\n animation: ui-dialog-backdrop-enter var(--_ui-dialog-duration, var(--ui-motion-base)) var(--ui-motion-ease);\n }\n\n @keyframes ui-dialog-backdrop-enter {\n from {\n background-color: transparent;\n }\n }","declarations":[{"kind":"state","name":"internalOpen","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"accessibleLabel","expression":{"source":"'Dialog'","ast":{"kind":"literal","value":"Dialog"},"dependencies":[]}},{"kind":"event","name":"close","type":"object({ open: boolean, reason: action | programmatic | light-dismiss | escape, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false}],"slots":[{"dynamic":false,"required":true},{"dynamic":false,"required":true,"name":"actions"}],"root":{"kind":"native","element":"dialog","choices":["dialog"]},"controller":"./components/ui-dialog/ui-dialog.js"},{"source":{"file":"./components/ui-disclosure/ui-disclosure.html"},"contract":{"version":1,"name":"UiDisclosure","tag":"ui-disclosure","nativeElement":"div","props":{"density":{"type":{"enum":["comfortable","compact"]},"required":false,"target":{"attribute":"density"},"description":"Compact trades padding and type size for rows that fit more on screen.","default":"comfortable"},"disabled":{"type":"boolean","required":false,"target":{"attribute":"disabled"},"description":"Disables the trigger and mutes its text, so the disclosure keeps its current state and the user cannot toggle it.","default":false},"open":{"type":"boolean","required":false,"target":{"attribute":"open"},"description":"Whether the disclosure is open initially or when set externally. The trigger toggles it from there, reporting each change as an open or close event.","default":false},"summary":{"type":"string","required":false,"target":{"attribute":"summary"},"description":"The text of the trigger row that opens and closes the disclosure. It is the trigger button's accessible name, so name what the content is.","default":"Details"}}},"template":{"kind":"element","name":"div","attributes":[],"children":[{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"class","value":"trigger"},{"kind":"literal","name":"type","value":"button"},{"kind":"attribute","name":"aria-controls","expression":"contentId","expressionPlan":{"source":"contentId","ast":{"kind":"id","name":"contentId"},"dependencies":["contentId"]}},{"kind":"attribute","name":"aria-expanded","expression":"internalOpen","expressionPlan":{"source":"internalOpen","ast":{"kind":"id","name":"internalOpen"},"dependencies":["internalOpen"]}},{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"directive","name":"value","expression":"summary","expressionPlan":{"source":"summary","ast":{"kind":"id","name":"summary"},"dependencies":["summary"]}}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"chevron"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[]}],"ref":"trigger"},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"panel"},{"kind":"attribute","name":"id","expression":"contentId","expressionPlan":{"source":"contentId","ast":{"kind":"id","name":"contentId"},"dependencies":["contentId"]}},{"kind":"attribute","name":"inert","expression":"not internalOpen","expressionPlan":{"source":"not internalOpen","ast":{"kind":"unary","op":"not","operand":{"kind":"id","name":"internalOpen"}},"dependencies":["internalOpen"]}}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"panel-inner"}],"children":[{"kind":"slot"}]}]}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-disclosure-trigger-min-block-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-disclosure-trigger-padding-block {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-disclosure-trigger-padding-inline {\n syntax: \"*\";\n inherits: false;\n }\n\n /* Density resolves into the summary row's own values; the public tokens still override them. */\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-disclosure-trigger-min-block-size: var(--ui-disclosure-trigger-min-block-size);\n --_ui-disclosure-trigger-padding-block: var(--ui-disclosure-trigger-padding-block);\n --_ui-disclosure-trigger-padding-inline: var(--ui-disclosure-trigger-padding-inline);\n\n --_trigger-min-block-size: var(--ui-control-size);\n --_trigger-padding-block: var(--ui-space-2);\n --_trigger-padding-inline: var(--ui-space-3);\n }\n\n :host-state([density=\"compact\"]) {\n --_trigger-min-block-size: var(--ui-control-size-sm);\n --_trigger-padding-block: var(--ui-space-1);\n --_trigger-padding-inline: var(--ui-space-2);\n }\n\n /* An accordion row, not a field: no enclosing box, just a divider, so it never reads as a\n * select or combobox. Stacked disclosures share their dividers. */\n :host {\n display: block;\n inline-size: 100%;\n overflow: clip;\n border-block-end: 1px solid var(--ui-border-default);\n color: var(--ui-text-primary);\n }\n\n .trigger {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n gap: var(--ui-space-3);\n align-items: center;\n inline-size: 100%;\n min-block-size: var(--_ui-disclosure-trigger-min-block-size, var(--_trigger-min-block-size));\n padding: var(--_ui-disclosure-trigger-padding-block, var(--_trigger-padding-block))\n var(--_ui-disclosure-trigger-padding-inline, var(--_trigger-padding-inline));\n border: 0;\n background: transparent;\n color: inherit;\n font: inherit;\n font-weight: var(--ui-font-semibold);\n text-align: start;\n cursor: pointer;\n border-radius: var(--ui-radius-sm);\n transition: background-color var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n .trigger:hover:not(:disabled) {\n background: var(--ui-surface-muted);\n }\n .trigger:focus-visible {\n outline: none;\n box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--ui-focus-ring) 45%, transparent);\n }\n .trigger:disabled {\n color: var(--ui-disabled-text);\n cursor: not-allowed;\n }\n\n .chevron {\n inline-size: 0.5rem;\n block-size: 0.5rem;\n border-inline-end: 2px solid currentColor;\n border-block-end: 2px solid currentColor;\n transform: rotate(45deg) translate(-1px, -1px);\n transition: transform var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n .panel {\n display: grid;\n grid-template-rows: 0fr;\n transition: grid-template-rows var(--ui-motion-fast) var(--ui-motion-ease-out, var(--ui-motion-ease));\n }\n\n .panel-inner {\n min-block-size: 0;\n overflow: hidden;\n padding-inline: var(--ui-space-3);\n }\n\n :host-state([internalOpen]) .panel {\n grid-template-rows: 1fr;\n }\n :host-state([internalOpen]) .panel-inner {\n padding-block: 0 var(--ui-space-3);\n }\n :host-state([internalOpen]) .chevron {\n transform: rotate(225deg) translate(-1px, -1px);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .panel,\n .chevron {\n transition: none;\n }\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"internalOpen","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"contentId","expression":{"source":"''","ast":{"kind":"literal","value":""},"dependencies":[]}},{"kind":"event","name":"open","type":"object({ open: boolean, reason: action | programmatic | light-dismiss | escape, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"close","type":"object({ open: boolean, reason: action | programmatic | light-dismiss | escape, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false}],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-disclosure/ui-disclosure.js"},{"source":{"file":"./components/ui-editable/ui-editable.html"},"contract":{"version":1,"name":"UiEditable","tag":"ui-editable","nativeElement":"div","props":{"actions":{"type":"boolean","required":false,"target":{"attribute":"actions"},"description":"Show explicit Save and Cancel buttons while editing. Without them, Enter or leaving the field saves and Escape cancels.","default":false},"disabled":{"type":"boolean","required":false,"target":{"attribute":"disabled"},"description":"Prevents entering or changing edit mode.","default":false},"edit":{"type":"boolean","required":false,"target":{"attribute":"edit"},"description":"Whether edit mode is active initially or when set externally.","default":false},"hint":{"type":"string","required":false,"target":{"attribute":"hint"},"description":"Optional text shown beside the value to signal it is editable (for example \"Edit\").","default":""},"label":{"type":"string","required":false,"target":{"attribute":"aria-label"},"description":"Accessible name for the editor.","default":"Edit value"},"value":{"type":"string","required":false,"target":{"attribute":"value"},"description":"The displayed value, and the text the editor starts from. It is not a form field: nothing is submitted with a form, so a form that needs the value copies\n it from the change event into a field of its own.","default":""}}},"template":{"kind":"element","name":"div","attributes":[],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"field"}],"children":[{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"class","value":"preview"},{"kind":"literal","name":"type","value":"button"},{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"text"},{"kind":"directive","name":"value","expression":"internalValue","expressionPlan":{"source":"internalValue","ast":{"kind":"id","name":"internalValue"},"dependencies":["internalValue"]}}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"hint"},{"kind":"literal","name":"aria-hidden","value":"true"},{"kind":"directive","name":"value","expression":"hint","expressionPlan":{"source":"hint","ast":{"kind":"id","name":"hint"},"dependencies":["hint"]}}],"children":[],"flow":{"kind":"if","test":"hint","testPlan":{"source":"hint","ast":{"kind":"id","name":"hint"},"dependencies":["hint"]}}}],"ref":"preview"},{"kind":"element","name":"input","attributes":[{"kind":"literal","name":"class","value":"input"},{"kind":"literal","name":"type","value":"text"},{"kind":"property","key":"value","name":"value","expression":"draft","expressionPlan":{"source":"draft","ast":{"kind":"id","name":"draft"},"dependencies":["draft"]}},{"kind":"attribute","name":"aria-label","expression":"label","expressionPlan":{"source":"label","ast":{"kind":"id","name":"label"},"dependencies":["label"]}},{"kind":"attribute","name":"disabled","expression":"disabled or not internalEdit","expressionPlan":{"source":"disabled or not internalEdit","ast":{"kind":"binary","op":"or","left":{"kind":"id","name":"disabled"},"right":{"kind":"unary","op":"not","operand":{"kind":"id","name":"internalEdit"}}},"dependencies":["disabled","internalEdit"]}}],"children":[],"ref":"input"}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"actions"}],"children":[{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"class","value":"save"},{"kind":"literal","name":"type","value":"button"}],"children":[{"kind":"text","value":"Save"}]},{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"class","value":"cancel"},{"kind":"literal","name":"type","value":"button"}],"children":[{"kind":"text","value":"Cancel"}]}],"flow":{"kind":"if","test":"actions","testPlan":{"source":"actions","ast":{"kind":"id","name":"actions"},"dependencies":["actions"]}}}]},"css":":host {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--ui-space-2);\n min-inline-size: 0;\n color: var(--ui-text-primary);\n }\n\n /* The value and the input share one grid cell with identical box metrics, so switching between\n * display and edit never changes the control's size or moves the text. */\n .field {\n display: inline-grid;\n min-inline-size: 8rem;\n max-inline-size: 100%;\n }\n\n .preview,\n .input {\n grid-area: 1 / 1;\n box-sizing: border-box;\n min-block-size: var(--ui-control-size-sm);\n margin: 0;\n padding: var(--ui-space-1) var(--ui-space-2);\n border: 1px solid transparent;\n border-radius: var(--ui-radius-md);\n font: inherit;\n line-height: var(--ui-line-height-md);\n color: inherit;\n transition:\n background-color var(--ui-motion-fast) var(--ui-motion-ease),\n border-color var(--ui-motion-fast) var(--ui-motion-ease),\n box-shadow var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n .preview {\n display: inline-flex;\n gap: var(--ui-space-2);\n align-items: center;\n background: transparent;\n text-align: start;\n cursor: pointer;\n }\n\n .preview:hover:not(:disabled) {\n background: var(--ui-surface-muted);\n }\n\n .preview:focus-visible {\n outline: none;\n box-shadow: var(--ui-focus-halo);\n }\n\n .hint {\n color: var(--ui-text-secondary);\n font-size: var(--ui-font-size-sm);\n }\n\n /* Contained so it takes the value's width instead of its own default input width. */\n .input {\n contain: inline-size;\n inline-size: 100%;\n min-inline-size: 0;\n visibility: hidden;\n background: var(--ui-control-surface, var(--ui-surface-elevated));\n }\n\n .input:focus {\n outline: none;\n border-color: var(--ui-control-focus, var(--ui-accent-solid));\n box-shadow:\n var(--ui-control-inset),\n var(--ui-control-focus-halo-shadow);\n }\n\n .input::selection {\n background: color-mix(in srgb, var(--ui-accent-solid) 20%, transparent);\n }\n\n :host-state([internalEdit]) .preview {\n visibility: hidden;\n }\n :host-state([internalEdit]) .input {\n visibility: visible;\n }\n\n .actions {\n display: none;\n gap: var(--ui-space-1);\n }\n :host-state([internalEdit]) .actions {\n display: inline-flex;\n }\n\n .actions button {\n min-block-size: var(--ui-control-size-sm);\n padding: 0 var(--ui-space-3);\n border: 1px solid var(--ui-border-strong);\n border-radius: var(--ui-radius-md);\n background: var(--ui-surface-elevated);\n background-image: var(--ui-raised-highlight);\n box-shadow: var(--ui-raised);\n color: inherit;\n font: inherit;\n font-size: var(--ui-font-size-sm);\n cursor: pointer;\n }\n\n .actions .save {\n border-color: var(--ui-accent-solid);\n background: var(--ui-accent-solid);\n color: var(--ui-text-on-accent);\n }\n\n .actions button:focus-visible {\n outline: none;\n box-shadow: var(--ui-focus-halo);\n }\n\n :host-state([disabled]) .preview {\n color: var(--ui-disabled-text);\n cursor: not-allowed;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"internalEdit","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"internalValue","expression":{"source":"''","ast":{"kind":"literal","value":""},"dependencies":[]}},{"kind":"state","name":"draft","expression":{"source":"''","ast":{"kind":"literal","value":""},"dependencies":[]}},{"kind":"event","name":"input","type":"object({ value: string, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"change","type":"object({ value: string, previousValue: string, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"edit-change","type":"object({ edit: boolean, reason: activate | commit | cancel | light-dismiss | escape | programmatic, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false}],"slots":[],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-editable/ui-editable.js"},{"source":{"file":"./components/ui-editor-insert-table-grid/ui-editor-insert-table-grid.html"},"contract":{"version":1,"name":"UiEditorInsertTableGrid","tag":"ui-editor-insert-table-grid","nativeElement":"div","props":{"headerRow":{"type":"boolean","required":false,"target":{"attribute":"headerrow"},"description":"Whether table insertion initially includes a header row.","default":false},"maxCols":{"type":{"kind":"terminal","name":"integer"},"required":false,"target":{"attribute":"maxcols"},"description":"The most columns the grid offers (at most 10).","default":8},"maxRows":{"type":{"kind":"terminal","name":"integer"},"required":false,"target":{"attribute":"maxrows"},"description":"The most rows the grid offers (at most 10).","default":8},"open":{"type":"boolean","required":false,"target":{"attribute":"open"},"description":"Whether the grid is shown.","default":false}}},"template":{"kind":"element","name":"div","attributes":[{"kind":"attribute","name":"hidden","expression":"not open","expressionPlan":{"source":"not open","ast":{"kind":"unary","op":"not","operand":{"kind":"id","name":"open"}},"dependencies":["open"]}}],"children":[{"kind":"element","name":"p","attributes":[{"kind":"literal","name":"class","value":"hint"},{"kind":"directive","name":"value","expression":"hint","expressionPlan":{"source":"hint","ast":{"kind":"id","name":"hint"},"dependencies":["hint"]}}],"children":[]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"grid"},{"kind":"literal","name":"role","value":"group"},{"kind":"literal","name":"aria-label","value":"Table dimensions"},{"kind":"attribute","name":"--_rows","expression":"rows","expressionPlan":{"source":"rows","ast":{"kind":"id","name":"rows"},"dependencies":["rows"]},"target":"style"},{"kind":"attribute","name":"--_cols","expression":"cols","expressionPlan":{"source":"cols","ast":{"kind":"id","name":"cols"},"dependencies":["cols"]},"target":"style"}],"children":[{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"class","value":"cell"},{"kind":"attribute","name":"selected","expression":"cell.selected","expressionPlan":{"source":"cell.selected","ast":{"kind":"member","object":{"kind":"id","name":"cell"},"key":"selected"},"dependencies":["cell.selected"]},"target":"class"},{"kind":"attribute","name":"data-row","expression":"cell.row","expressionPlan":{"source":"cell.row","ast":{"kind":"member","object":{"kind":"id","name":"cell"},"key":"row"},"dependencies":["cell.row"]}},{"kind":"attribute","name":"data-col","expression":"cell.col","expressionPlan":{"source":"cell.col","ast":{"kind":"member","object":{"kind":"id","name":"cell"},"key":"col"},"dependencies":["cell.col"]}},{"kind":"attribute","name":"aria-label","expression":"cell.label","expressionPlan":{"source":"cell.label","ast":{"kind":"member","object":{"kind":"id","name":"cell"},"key":"label"},"dependencies":["cell.label"]}},{"kind":"attribute","name":"aria-pressed","expression":"cell.selected","expressionPlan":{"source":"cell.selected","ast":{"kind":"member","object":{"kind":"id","name":"cell"},"key":"selected"},"dependencies":["cell.selected"]}}],"children":[],"flow":{"kind":"each","item":"cell","list":"cells","listPlan":{"source":"cells","ast":{"kind":"id","name":"cells"},"dependencies":["cells"]},"key":"cell.key","keyPlan":{"source":"cell.key","ast":{"kind":"member","object":{"kind":"id","name":"cell"},"key":"key"},"dependencies":["cell.key"]}}}]},{"kind":"element","name":"label","attributes":[{"kind":"literal","name":"class","value":"header"}],"children":[{"kind":"element","name":"input","attributes":[{"kind":"literal","name":"type","value":"checkbox"},{"kind":"property","key":"checked","name":"checked","expression":"withHeaderRow","expressionPlan":{"source":"withHeaderRow","ast":{"kind":"id","name":"withHeaderRow"},"dependencies":["withHeaderRow"]}}],"children":[],"ref":"header"},{"kind":"text","value":" Header row"}]},{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"class","value":"insert"}],"children":[{"kind":"text","value":"Insert table"}],"ref":"insert"}]},"css":":host {\n padding: var(--ui-space-3);\n background: var(--ui-surface);\n border: 1px solid var(--ui-border);\n border-radius: var(--ui-radius-md);\n box-shadow: var(--ui-shadow-lg, 0 10px 15px -3px rgb(0 0 0 / 0.1));\n }\n\n .hint {\n margin: 0 0 var(--ui-space-2);\n font-size: var(--ui-font-size-sm);\n color: var(--ui-text-muted);\n }\n\n .grid {\n display: grid;\n grid-template-columns: repeat(var(--_cols, 8), 1.25rem);\n grid-template-rows: repeat(var(--_rows, 8), 1.25rem);\n gap: 2px;\n margin-bottom: var(--ui-space-2);\n }\n\n .cell {\n width: 1.25rem;\n height: 1.25rem;\n padding: 0;\n border: 1px solid var(--ui-border);\n border-radius: 2px;\n background: var(--ui-surface);\n cursor: pointer;\n }\n\n .cell.selected {\n background: var(--ui-accent-solid, var(--ui-accent));\n border-color: var(--ui-accent-solid, var(--ui-accent));\n }\n\n .header {\n display: block;\n margin-bottom: var(--ui-space-2);\n font-size: var(--ui-font-size-sm);\n cursor: pointer;\n }\n\n :host .insert {\n width: 100%;\n padding: var(--ui-space-2) var(--ui-space-3);\n border: 1px solid var(--ui-border);\n border-radius: var(--ui-radius-sm);\n background: var(--ui-accent-solid, var(--ui-accent));\n color: var(--ui-accent-contrast);\n font-size: var(--ui-font-size-sm);\n cursor: pointer;\n }\n\n :host .insert:hover {\n filter: brightness(1.05);\n }\n\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"cells","type":"list(object({ key: string, row: integer, col: integer, label: string, selected: boolean }))","expression":{"source":"[]","ast":{"kind":"array","items":[]},"dependencies":[]}},{"kind":"state","name":"rows","expression":{"source":"8","ast":{"kind":"literal","value":8},"dependencies":[]}},{"kind":"state","name":"cols","expression":{"source":"8","ast":{"kind":"literal","value":8},"dependencies":[]}},{"kind":"state","name":"hint","expression":{"source":"''","ast":{"kind":"literal","value":""},"dependencies":[]}},{"kind":"state","name":"withHeaderRow","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"event","name":"insert","type":"object({ rows: integer, cols: integer, withHeaderRow: boolean })","bubbles":true,"composed":true,"cancelable":false}],"slots":[],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-editor-insert-table-grid/ui-editor-insert-table-grid.js"},{"source":{"file":"./components/ui-editor-mention-menu/ui-editor-mention-menu.html"},"contract":{"version":1,"name":"UiEditorMentionMenu","tag":"ui-editor-mention-menu","nativeElement":"div","props":{"anchorRect":{"type":{"kind":"union","members":[{"kind":"object","fields":[{"name":"left","type":{"kind":"terminal","name":"number"},"optional":true},{"name":"top","type":{"kind":"terminal","name":"number"},"optional":true},{"name":"right","type":{"kind":"terminal","name":"number"},"optional":true},{"name":"bottom","type":{"kind":"terminal","name":"number"},"optional":true},{"name":"x","type":{"kind":"terminal","name":"number"},"optional":true},{"name":"y","type":{"kind":"terminal","name":"number"},"optional":true},{"name":"width","type":{"kind":"terminal","name":"number"},"optional":true},{"name":"height","type":{"kind":"terminal","name":"number"},"optional":true}],"open":false},{"kind":"terminal","name":"null"}]},"required":false,"target":{"attribute":"anchorrect"},"description":"Where the @ was typed, in viewport coordinates."},"items":{"type":{"kind":"list","item":{"kind":"object","fields":[{"name":"id","type":{"kind":"terminal","name":"string"},"optional":false},{"name":"label","type":{"kind":"terminal","name":"string"},"optional":false},{"name":"detail","type":{"kind":"terminal","name":"string"},"optional":true},{"name":"initials","type":{"kind":"terminal","name":"string"},"optional":true}],"open":false}},"required":false,"target":{"attribute":"items"},"description":"The people the menu offers."},"loading":{"type":"boolean","required":false,"target":{"attribute":"aria-busy"},"description":"Whether a search is in progress.","default":false},"open":{"type":"boolean","required":false,"target":{"attribute":"open"},"description":"Whether the menu is open.","default":false},"query":{"type":"string","required":false,"target":{"attribute":"query"},"description":"The text typed after the @.","default":""},"selectedIndex":{"type":{"kind":"terminal","name":"integer"},"required":false,"target":{"attribute":"selectedindex"},"description":"The zero-based index of the highlighted person, capped at the last one shown, and announced through aria-activedescendant. The menu does not handle arrow\n keys itself: the editor sets this as the user moves, while hovering a person highlights them and reports a highlight event.","default":0}}},"template":{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"role","value":"listbox"},{"kind":"literal","name":"aria-label","value":"Mention a person"},{"kind":"attribute","name":"aria-busy","expression":"loading","expressionPlan":{"source":"loading","ast":{"kind":"id","name":"loading"},"dependencies":["loading"]}},{"kind":"attribute","name":"hidden","expression":"not visible","expressionPlan":{"source":"not visible","ast":{"kind":"unary","op":"not","operand":{"kind":"id","name":"visible"}},"dependencies":["visible"]}}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"header"}],"children":[{"kind":"element","name":"span","attributes":[],"children":[{"kind":"text","value":"People"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"hint"}],"children":[{"kind":"text","value":"Type after @ to search"}]}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"loading"},{"kind":"literal","name":"role","value":"status"}],"children":[{"kind":"text","value":"Searching…"}],"flow":{"kind":"if","test":"searching","testPlan":{"source":"searching","ast":{"kind":"id","name":"searching"},"dependencies":["searching"]}}},{"kind":"element","name":"ul","attributes":[{"kind":"literal","name":"class","value":"list"},{"kind":"literal","name":"role","value":"presentation"}],"children":[{"kind":"element","name":"li","attributes":[{"kind":"attribute","name":"id","expression":"format('%s-option-%s', prefix, index)","expressionPlan":{"source":"format('%s-option-%s', prefix, index)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s-option-%s"},{"kind":"id","name":"prefix"},{"kind":"id","name":"index"}]},"dependencies":["index","prefix"]}},{"kind":"literal","name":"class","value":"item"},{"kind":"attribute","name":"active","expression":"index = active","expressionPlan":{"source":"index = active","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"index"},"right":{"kind":"id","name":"active"}},"dependencies":["active","index"]},"target":"class"},{"kind":"literal","name":"role","value":"option"},{"kind":"attribute","name":"aria-selected","expression":"index = active","expressionPlan":{"source":"index = active","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"index"},"right":{"kind":"id","name":"active"}},"dependencies":["active","index"]}},{"kind":"attribute","name":"data-index","expression":"index","expressionPlan":{"source":"index","ast":{"kind":"id","name":"index"},"dependencies":["index"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"avatar"},{"kind":"literal","name":"aria-hidden","value":"true"},{"kind":"directive","name":"value","expression":"row.initials","expressionPlan":{"source":"row.initials","ast":{"kind":"member","object":{"kind":"id","name":"row"},"key":"initials"},"dependencies":["row.initials"]}}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"body"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"label"},{"kind":"directive","name":"value","expression":"row.label","expressionPlan":{"source":"row.label","ast":{"kind":"member","object":{"kind":"id","name":"row"},"key":"label"},"dependencies":["row.label"]}}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"detail"},{"kind":"directive","name":"value","expression":"row.detail","expressionPlan":{"source":"row.detail","ast":{"kind":"member","object":{"kind":"id","name":"row"},"key":"detail"},"dependencies":["row.detail"]}}],"children":[],"flow":{"kind":"if","test":"row.detail","testPlan":{"source":"row.detail","ast":{"kind":"member","object":{"kind":"id","name":"row"},"key":"detail"},"dependencies":["row.detail"]}}}]}],"flow":{"kind":"each","item":"row","list":"rows","listPlan":{"source":"rows","ast":{"kind":"id","name":"rows"},"dependencies":["rows"]},"index":"index"}}],"flow":{"kind":"if","test":"not searching","testPlan":{"source":"not searching","ast":{"kind":"unary","op":"not","operand":{"kind":"id","name":"searching"}},"dependencies":["searching"]}}}]},"css":":host {\n user-select: none;\n }\n\n :host {\n display: flex;\n overflow: hidden;\n flex-direction: column;\n background: var(--ui-surface);\n border: 1px solid var(--ui-border);\n border-radius: var(--ui-radius-dialog);\n box-shadow: var(--ui-shadow-lg, 0 8px 24px rgb(0 0 0 / 0.12));\n }\n\n .header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--ui-space-3);\n padding: var(--ui-space-2) var(--ui-space-3);\n color: var(--ui-text-secondary);\n border-bottom: 1px solid var(--ui-border);\n font-size: var(--ui-font-size-xs);\n font-weight: var(--ui-font-semibold);\n }\n\n .hint {\n overflow: hidden;\n color: var(--ui-text-muted);\n font-weight: var(--ui-font-normal);\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .list {\n max-height: 280px;\n padding: var(--ui-space-1) 0;\n margin: 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n list-style: none;\n /* Each edge that hides content fades: the scroll fade every Looma scroller uses (see ui-scroll-area). */\n --_ui-scroll-fade-direction: to bottom;\n --_ui-scroll-fade-size: var(--ui-scroll-fade-size, 24px);\n mask-image: linear-gradient(\n var(--_ui-scroll-fade-direction),\n transparent,\n #000 var(--_ui-scroll-fade-start),\n #000 calc(100% - var(--_ui-scroll-fade-end)),\n transparent\n );\n animation: ui-scroll-fade-start linear, ui-scroll-fade-start-hold linear, ui-scroll-fade-end-hold linear, ui-scroll-fade-end linear;\n animation-timeline: scroll(self block);\n animation-range:\n 0 var(--_ui-scroll-fade-size),\n var(--_ui-scroll-fade-size) calc(100% + 1px),\n -1px calc(100% - var(--_ui-scroll-fade-size)),\n calc(100% - var(--_ui-scroll-fade-size)) 100%;\n }\n\n .item {\n display: flex;\n align-items: center;\n min-height: 44px;\n padding: var(--ui-space-2) var(--ui-space-3);\n gap: var(--ui-space-3);\n cursor: pointer;\n }\n\n .item.active {\n background: var(--ui-accent-subtle, rgb(59 130 246 / 0.1));\n }\n\n .avatar {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n flex: 0 0 auto;\n color: var(--ui-accent-active, var(--ui-accent-solid));\n background: var(--ui-accent-soft, var(--ui-accent-subtle));\n border-radius: 999px;\n font-size: var(--ui-font-size-xs);\n font-weight: var(--ui-font-semibold);\n }\n\n .body {\n display: flex;\n min-width: 0;\n flex-direction: column;\n }\n\n .label,\n .detail {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .label {\n color: var(--ui-text-primary);\n font-size: var(--ui-font-size-sm);\n font-weight: var(--ui-font-medium);\n }\n\n .detail,\n .loading {\n color: var(--ui-text-muted);\n font-size: var(--ui-font-size-xs);\n }\n\n .loading {\n min-height: 44px;\n padding: var(--ui-space-3);\n }\n\n @media (max-width: 767px) {\n :host {\n border-bottom: 0;\n border-radius: var(--ui-radius-dialog) var(--ui-radius-dialog) 0 0;\n }\n\n .list {\n max-height: calc(60dvh - 48px);\n }\n }\n\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"visible","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"rows","type":"list(object({ id: string, label: string, detail?: string, initials: string }))","expression":{"source":"[]","ast":{"kind":"array","items":[]},"dependencies":[]}},{"kind":"state","name":"searching","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"active","expression":{"source":"0","ast":{"kind":"literal","value":0},"dependencies":[]}},{"kind":"state","name":"prefix","expression":{"source":"'ui-editor-mention-menu'","ast":{"kind":"literal","value":"ui-editor-mention-menu"},"dependencies":[]}},{"kind":"event","name":"highlight","type":"object({ index: integer })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"select","type":"object({ index: integer })","bubbles":true,"composed":true,"cancelable":false}],"slots":[],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-editor-mention-menu/ui-editor-mention-menu.js"},{"source":{"file":"./components/ui-editor-slash-menu/ui-editor-slash-menu.html"},"contract":{"version":1,"name":"UiEditorSlashMenu","tag":"ui-editor-slash-menu","nativeElement":"div","props":{"anchorRect":{"type":{"kind":"union","members":[{"kind":"object","fields":[{"name":"left","type":{"kind":"terminal","name":"number"},"optional":true},{"name":"top","type":{"kind":"terminal","name":"number"},"optional":true},{"name":"right","type":{"kind":"terminal","name":"number"},"optional":true},{"name":"bottom","type":{"kind":"terminal","name":"number"},"optional":true},{"name":"x","type":{"kind":"terminal","name":"number"},"optional":true},{"name":"y","type":{"kind":"terminal","name":"number"},"optional":true},{"name":"width","type":{"kind":"terminal","name":"number"},"optional":true},{"name":"height","type":{"kind":"terminal","name":"number"},"optional":true}],"open":false},{"kind":"terminal","name":"null"}]},"required":false,"target":{"attribute":"anchorrect"},"description":"Where the slash was typed, in viewport coordinates."},"items":{"type":{"kind":"list","item":{"kind":"object","fields":[{"name":"title","type":{"kind":"terminal","name":"string"},"optional":false},{"name":"description","type":{"kind":"terminal","name":"string"},"optional":false},{"name":"icon","type":{"kind":"terminal","name":"string"},"optional":false}],"open":false}},"required":false,"target":{"attribute":"items"},"description":"The blocks the menu offers."},"open":{"type":"boolean","required":false,"target":{"attribute":"open"},"description":"Whether the menu is open.","default":false},"query":{"type":"string","required":false,"target":{"attribute":"query"},"description":"The text typed after the slash.","default":""},"selectedIndex":{"type":{"kind":"terminal","name":"integer"},"required":false,"target":{"attribute":"selectedindex"},"description":"The zero-based index of the highlighted item. The menu does not handle arrow keys itself: the editor sets this as the user moves, while hovering an item\n highlights it and reports a highlight event.","default":0}}},"template":{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"role","value":"listbox"},{"kind":"literal","name":"aria-label","value":"Insert block"},{"kind":"attribute","name":"hidden","expression":"not visible","expressionPlan":{"source":"not visible","ast":{"kind":"unary","op":"not","operand":{"kind":"id","name":"visible"}},"dependencies":["visible"]}}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"header"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"header-label"}],"children":[{"kind":"text","value":"Insert"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"header-query"},{"kind":"directive","name":"value","expression":"query","expressionPlan":{"source":"query","ast":{"kind":"id","name":"query"},"dependencies":["query"]}}],"children":[],"flow":{"kind":"if","test":"query","testPlan":{"source":"query","ast":{"kind":"id","name":"query"},"dependencies":["query"]}}}]},{"kind":"element","name":"ul","attributes":[{"kind":"literal","name":"class","value":"list"},{"kind":"literal","name":"role","value":"presentation"}],"children":[{"kind":"element","name":"li","attributes":[{"kind":"literal","name":"class","value":"item"},{"kind":"attribute","name":"active","expression":"index = active","expressionPlan":{"source":"index = active","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"index"},"right":{"kind":"id","name":"active"}},"dependencies":["active","index"]},"target":"class"},{"kind":"literal","name":"role","value":"option"},{"kind":"attribute","name":"aria-selected","expression":"index = active","expressionPlan":{"source":"index = active","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"index"},"right":{"kind":"id","name":"active"}},"dependencies":["active","index"]}},{"kind":"attribute","name":"data-index","expression":"index","expressionPlan":{"source":"index","ast":{"kind":"id","name":"index"},"dependencies":["index"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"icon"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[{"kind":"element","name":"ui-icon","attributes":[{"kind":"attribute","name":"name","expression":"item.icon","expressionPlan":{"source":"item.icon","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"icon"},"dependencies":["item.icon"]}}],"children":[]}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"body"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"title"},{"kind":"directive","name":"value","expression":"item.title","expressionPlan":{"source":"item.title","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"title"},"dependencies":["item.title"]}}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"description"},{"kind":"directive","name":"value","expression":"item.description","expressionPlan":{"source":"item.description","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"description"},"dependencies":["item.description"]}}],"children":[]}]}],"flow":{"kind":"each","item":"item","list":"items","listPlan":{"source":"items","ast":{"kind":"id","name":"items"},"dependencies":["items"]},"index":"index"}}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"footer"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[{"kind":"element","name":"kbd","attributes":[],"children":[{"kind":"text","value":"↑↓"}]},{"kind":"text","value":" navigate · "},{"kind":"element","name":"kbd","attributes":[],"children":[{"kind":"text","value":"↵"}]},{"kind":"text","value":" insert · "},{"kind":"element","name":"kbd","attributes":[],"children":[{"kind":"text","value":"Esc"}]},{"kind":"text","value":" close\n "}]}]},"css":":host {\n user-select: none;\n }\n\n :host {\n background: var(--ui-surface);\n border: 1px solid var(--ui-border);\n border-radius: var(--ui-radius-dialog);\n box-shadow: var(--ui-shadow-lg, 0 8px 24px rgb(0 0 0 / 0.12));\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n\n @media (max-width: 767px) {\n :host {\n border-radius: var(--ui-radius-dialog) var(--ui-radius-dialog) 0 0;\n border-bottom: none;\n }\n }\n\n .header {\n display: none;\n align-items: center;\n gap: var(--ui-space-2);\n padding: var(--ui-space-3) var(--ui-space-4);\n border-bottom: 1px solid var(--ui-border);\n font-size: var(--ui-font-size-xs);\n color: var(--ui-text-muted);\n font-weight: var(--ui-font-semibold);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n }\n\n @media (max-width: 767px) {\n .header {\n display: flex;\n }\n }\n\n .header-query {\n background: var(--ui-surface-hover);\n border-radius: var(--ui-radius-sm);\n padding: 0.1em 0.4em;\n font-family: var(--ui-font-family-mono, ui-monospace, monospace);\n font-size: var(--ui-font-size-xs);\n color: var(--ui-accent);\n text-transform: none;\n letter-spacing: 0;\n }\n\n .list {\n list-style: none;\n margin: 0;\n padding: var(--ui-space-1) 0;\n overflow-y: auto;\n max-height: 280px;\n overscroll-behavior: contain;\n /* Each edge that hides content fades: the scroll fade every Looma scroller uses (see ui-scroll-area). */\n --_ui-scroll-fade-direction: to bottom;\n --_ui-scroll-fade-size: var(--ui-scroll-fade-size, 24px);\n mask-image: linear-gradient(\n var(--_ui-scroll-fade-direction),\n transparent,\n #000 var(--_ui-scroll-fade-start),\n #000 calc(100% - var(--_ui-scroll-fade-end)),\n transparent\n );\n animation: ui-scroll-fade-start linear, ui-scroll-fade-start-hold linear, ui-scroll-fade-end-hold linear, ui-scroll-fade-end linear;\n animation-timeline: scroll(self block);\n animation-range:\n 0 var(--_ui-scroll-fade-size),\n var(--_ui-scroll-fade-size) calc(100% + 1px),\n -1px calc(100% - var(--_ui-scroll-fade-size)),\n calc(100% - var(--_ui-scroll-fade-size)) 100%;\n }\n\n @media (max-width: 767px) {\n .list {\n max-height: calc(60dvh - 80px);\n padding: var(--ui-space-1) 0 var(--ui-space-2);\n }\n }\n\n .item {\n display: flex;\n align-items: center;\n gap: var(--ui-space-3);\n padding: var(--ui-space-2) var(--ui-space-3);\n min-height: 44px;\n cursor: pointer;\n transition: background-color 120ms ease;\n }\n\n .item.active {\n background: var(--ui-accent-subtle, rgb(59 130 246 / 0.1));\n }\n\n .icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n background: var(--ui-surface-hover);\n border: 1px solid var(--ui-border);\n border-radius: var(--ui-radius-md);\n font-size: var(--ui-font-size-sm);\n font-weight: var(--ui-font-bold);\n color: var(--ui-text-secondary);\n font-family: var(--ui-font-family-mono, ui-monospace, monospace);\n flex-shrink: 0;\n line-height: 1;\n }\n\n .item.active .icon {\n background: var(--ui-accent);\n border-color: var(--ui-accent);\n color: var(--ui-accent-contrast);\n }\n\n .icon {\n --_ui-default-icon-size: 1rem;\n --_ui-default-icon-stroke-width: var(--ui-editor-toolbar-icon-stroke-width, 1.75);\n }\n\n .body {\n display: flex;\n min-width: 0;\n flex-direction: column;\n gap: 1px;\n }\n\n .title {\n font-size: var(--ui-font-size-sm);\n font-weight: var(--ui-font-medium);\n color: var(--ui-text);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .description {\n font-size: var(--ui-font-size-xs);\n color: var(--ui-text-muted);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .footer {\n display: none;\n padding: var(--ui-space-2) var(--ui-space-3);\n border-top: 1px solid var(--ui-border);\n font-size: var(--ui-font-size-xs);\n color: var(--ui-text-muted);\n }\n\n @media (min-width: 768px) {\n .footer {\n display: block;\n }\n }\n\n :host kbd {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-family: var(--ui-font-family-mono, ui-monospace, monospace);\n font-size: var(--ui-font-size-2xs);\n background: var(--ui-surface-hover);\n border: 1px solid var(--ui-border);\n border-radius: 3px;\n padding: 0 3px;\n color: var(--ui-text-secondary);\n }\n\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"visible","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"active","expression":{"source":"0","ast":{"kind":"literal","value":0},"dependencies":[]}},{"kind":"event","name":"highlight","type":"object({ index: integer })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"select","type":"object({ index: integer })","bubbles":true,"composed":true,"cancelable":false}],"slots":[],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-editor-slash-menu/ui-editor-slash-menu.js"},{"source":{"file":"./components/ui-editor-table-context-menu/ui-editor-table-context-menu.html"},"contract":{"version":1,"name":"UiEditorTableContextMenu","tag":"ui-editor-table-context-menu","nativeElement":"div","props":{"actions":{"type":{"kind":"list","item":{"kind":"union","members":[{"kind":"keyword","value":"align-left"},{"kind":"keyword","value":"align-center"},{"kind":"keyword","value":"align-right"},{"kind":"keyword","value":"background-none"},{"kind":"keyword","value":"background-gray"},{"kind":"keyword","value":"background-yellow"},{"kind":"keyword","value":"background-blue"},{"kind":"keyword","value":"background-green"},{"kind":"keyword","value":"background-red"},{"kind":"keyword","value":"add-row-before"},{"kind":"keyword","value":"add-row-after"},{"kind":"keyword","value":"add-column-before"},{"kind":"keyword","value":"add-column-after"},{"kind":"keyword","value":"clear-cells"},{"kind":"keyword","value":"merge-cells"},{"kind":"keyword","value":"split-cell"},{"kind":"keyword","value":"delete-row"},{"kind":"keyword","value":"delete-column"},{"kind":"keyword","value":"delete-table"}]}},"required":false,"target":{"attribute":"actions"},"description":"The complete set of commands the current selection permits."},"cellBackground":{"type":"string","required":false,"target":{"attribute":"cellbackground"},"description":"Identifies the background choice that is active for the current cell.","default":""},"open":{"type":"boolean","required":false,"target":{"attribute":"open"},"description":"Shows the menu at the position owned by the editor integration.","default":false}}},"template":{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"role","value":"menu"},{"kind":"attribute","name":"hidden","expression":"not open","expressionPlan":{"source":"not open","ast":{"kind":"unary","op":"not","operand":{"kind":"id","name":"open"}},"dependencies":["open"]}}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"section"},{"kind":"literal","name":"role","value":"none"}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"heading"},{"kind":"literal","name":"role","value":"presentation"}],"children":[{"kind":"text","value":"Cell background"}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"swatches"},{"kind":"literal","name":"role","value":"group"},{"kind":"literal","name":"aria-label","value":"Cell background"}],"children":[{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"class","value":"swatch-button"},{"kind":"attribute","name":"selected","expression":"swatch.selected","expressionPlan":{"source":"swatch.selected","ast":{"kind":"member","object":{"kind":"id","name":"swatch"},"key":"selected"},"dependencies":["swatch.selected"]},"target":"class"},{"kind":"literal","name":"role","value":"menuitemradio"},{"kind":"attribute","name":"aria-checked","expression":"swatch.selected","expressionPlan":{"source":"swatch.selected","ast":{"kind":"member","object":{"kind":"id","name":"swatch"},"key":"selected"},"dependencies":["swatch.selected"]}},{"kind":"attribute","name":"data-action","expression":"swatch.action","expressionPlan":{"source":"swatch.action","ast":{"kind":"member","object":{"kind":"id","name":"swatch"},"key":"action"},"dependencies":["swatch.action"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"swatch"},{"kind":"attribute","name":"default","expression":"not swatch.color","expressionPlan":{"source":"not swatch.color","ast":{"kind":"unary","op":"not","operand":{"kind":"member","object":{"kind":"id","name":"swatch"},"key":"color"}},"dependencies":["swatch.color"]},"target":"class"},{"kind":"attribute","name":"--_swatch","expression":"swatch.color","expressionPlan":{"source":"swatch.color","ast":{"kind":"member","object":{"kind":"id","name":"swatch"},"key":"color"},"dependencies":["swatch.color"]},"target":"style"}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"swatch-label"},{"kind":"directive","name":"value","expression":"swatch.label","expressionPlan":{"source":"swatch.label","ast":{"kind":"member","object":{"kind":"id","name":"swatch"},"key":"label"},"dependencies":["swatch.label"]}}],"children":[]}],"flow":{"kind":"each","item":"swatch","list":"swatches","listPlan":{"source":"swatches","ast":{"kind":"id","name":"swatches"},"dependencies":["swatches"]},"key":"swatch.action","keyPlan":{"source":"swatch.action","ast":{"kind":"member","object":{"kind":"id","name":"swatch"},"key":"action"},"dependencies":["swatch.action"]}}}]}],"flow":{"kind":"if","test":"swatches","testPlan":{"source":"swatches","ast":{"kind":"id","name":"swatches"},"dependencies":["swatches"]}}},{"kind":"element","name":"template","attributes":[],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"sep"}],"children":[]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"section"},{"kind":"literal","name":"role","value":"none"}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"heading"},{"kind":"literal","name":"role","value":"presentation"},{"kind":"directive","name":"value","expression":"section.heading","expressionPlan":{"source":"section.heading","ast":{"kind":"member","object":{"kind":"id","name":"section"},"key":"heading"},"dependencies":["section.heading"]}}],"children":[]},{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"role","value":"menuitem"},{"kind":"attribute","name":"danger","expression":"item.danger","expressionPlan":{"source":"item.danger","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"danger"},"dependencies":["item.danger"]},"target":"class"},{"kind":"attribute","name":"data-action","expression":"item.action","expressionPlan":{"source":"item.action","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"action"},"dependencies":["item.action"]}}],"children":[{"kind":"element","name":"ui-icon","attributes":[{"kind":"attribute","name":"name","expression":"item.icon","expressionPlan":{"source":"item.icon","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"icon"},"dependencies":["item.icon"]}}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"directive","name":"value","expression":"item.label","expressionPlan":{"source":"item.label","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"label"},"dependencies":["item.label"]}}],"children":[]}],"flow":{"kind":"each","item":"item","list":"section.items","listPlan":{"source":"section.items","ast":{"kind":"member","object":{"kind":"id","name":"section"},"key":"items"},"dependencies":["section.items"]},"key":"item.action","keyPlan":{"source":"item.action","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"action"},"dependencies":["item.action"]}}}]}],"flow":{"kind":"each","item":"section","list":"sections","listPlan":{"source":"sections","ast":{"kind":"id","name":"sections"},"dependencies":["sections"]},"key":"section.heading","keyPlan":{"source":"section.heading","ast":{"kind":"member","object":{"kind":"id","name":"section"},"key":"heading"},"dependencies":["section.heading"]}}}]},"css":":host {\n /* The max-width is a promise about the menu's footprint, so it counts padding and border. */\n box-sizing: border-box;\n min-width: 14rem;\n max-width: min(17rem, calc(100vw - 24px));\n max-height: min(28rem, calc(100vh - 24px));\n padding: var(--ui-space-2);\n background: var(--ui-surface);\n border: 1px solid var(--ui-border);\n border-radius: var(--ui-radius-lg);\n box-shadow: var(--ui-shadow-lg, 0 10px 15px -3px rgb(0 0 0 / 0.1));\n display: flex;\n flex-direction: column;\n gap: 2px;\n overflow-y: auto;\n overscroll-behavior: contain;\n scrollbar-width: thin;\n }\n\n .section {\n display: flex;\n flex-direction: column;\n gap: 3px;\n }\n\n :host button {\n display: flex;\n align-items: center;\n gap: var(--ui-space-2);\n width: 100%;\n text-align: left;\n min-height: 32px;\n padding: var(--ui-space-2) var(--ui-space-2);\n border: none;\n border-radius: var(--ui-radius-sm);\n background: none;\n font-size: var(--ui-font-size-sm);\n cursor: pointer;\n color: var(--ui-text);\n }\n\n :host button {\n --_ui-default-icon-size: 1rem;\n --_ui-default-icon-stroke-width: var(--ui-editor-toolbar-icon-stroke-width, 1.75);\n }\n\n :host button:hover:not(:disabled) {\n background: var(--ui-surface-hover);\n }\n\n :host button.selected {\n background: var(--ui-accent-subtle, rgb(59 130 246 / 0.1));\n }\n\n :host button.danger {\n color: var(--ui-danger);\n }\n\n .swatches {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 3px;\n }\n\n .swatch-button {\n display: inline-flex;\n align-items: center;\n gap: var(--ui-space-2);\n }\n\n .swatch {\n display: inline-flex;\n width: 1rem;\n height: 1rem;\n border-radius: 999px;\n border: 1px solid var(--ui-border);\n background: var(--_swatch, #fff);\n box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.35);\n flex-shrink: 0;\n }\n\n .swatch.default {\n position: relative;\n background:\n linear-gradient(\n 135deg,\n transparent calc(50% - 1px),\n var(--ui-text-muted) calc(50% - 1px),\n var(--ui-text-muted) calc(50% + 1px),\n transparent calc(50% + 1px)\n ),\n var(--ui-surface);\n }\n\n .swatch-label {\n min-width: 0;\n white-space: nowrap;\n }\n\n .heading {\n padding: var(--ui-space-1) var(--ui-space-2);\n font-size: var(--ui-font-size-2xs);\n font-weight: 700;\n letter-spacing: 0.05em;\n text-transform: uppercase;\n color: var(--ui-text-muted);\n }\n\n .sep {\n height: 1px;\n background: var(--ui-border);\n margin: var(--ui-space-1) 0;\n }\n\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"swatches","type":"list(object({ action: string, label: string, color: string, selected: boolean })) | null","expression":{"source":"[]","ast":{"kind":"array","items":[]},"dependencies":[]}},{"kind":"state","name":"sections","type":"list(object({ heading: string, items: list(object({ action: string, label: string, icon: string, danger: boolean })) }))","expression":{"source":"[]","ast":{"kind":"array","items":[]},"dependencies":[]}},{"kind":"event","name":"action","type":"object({ action: align-left | align-center | align-right | background-none | background-gray | background-yellow | background-blue | background-green | background-red | add-row-before | add-row-after | add-column-before | add-column-after | clear-cells | merge-cells | split-cell | delete-row | delete-column | delete-table })","bubbles":true,"composed":true,"cancelable":false}],"slots":[],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-editor-table-context-menu/ui-editor-table-context-menu.js"},{"source":{"file":"./components/ui-editor-table-overlay/ui-editor-table-overlay.html"},"contract":{"version":1,"name":"UiEditorTableOverlay","tag":"ui-editor-table-overlay","nativeElement":"div","props":{"geometry":{"type":{"kind":"union","members":[{"kind":"object","fields":[{"name":"rowBoundaries","type":{"kind":"list","item":{"kind":"terminal","name":"number"}},"optional":false},{"name":"columnBoundaries","type":{"kind":"list","item":{"kind":"terminal","name":"number"}},"optional":false},{"name":"activeCell","type":{"kind":"union","members":[{"kind":"object","fields":[{"name":"left","type":{"kind":"terminal","name":"number"},"optional":false},{"name":"top","type":{"kind":"terminal","name":"number"},"optional":false},{"name":"width","type":{"kind":"terminal","name":"number"},"optional":false},{"name":"height","type":{"kind":"terminal","name":"number"},"optional":false},{"name":"rowIndex","type":{"kind":"terminal","name":"integer"},"optional":false},{"name":"columnIndex","type":{"kind":"terminal","name":"integer"},"optional":false}],"open":false},{"kind":"terminal","name":"null"}]},"optional":false},{"name":"hoveredCell","type":{"kind":"union","members":[{"kind":"object","fields":[{"name":"left","type":{"kind":"terminal","name":"number"},"optional":false},{"name":"top","type":{"kind":"terminal","name":"number"},"optional":false},{"name":"width","type":{"kind":"terminal","name":"number"},"optional":false},{"name":"height","type":{"kind":"terminal","name":"number"},"optional":false},{"name":"rowIndex","type":{"kind":"terminal","name":"integer"},"optional":false},{"name":"columnIndex","type":{"kind":"terminal","name":"integer"},"optional":false}],"open":false},{"kind":"terminal","name":"null"}]},"optional":true}],"open":false},{"kind":"terminal","name":"null"}]},"required":false,"target":{"attribute":"geometry"},"description":"The authoritative editor-measured table boundaries and active or hovered cell rectangles."},"open":{"type":"boolean","required":false,"target":{"attribute":"open"},"description":"Shows the controls after the editor has supplied current geometry.","default":false}}},"template":{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"aria-label","value":"Table controls"},{"kind":"attribute","name":"hidden","expression":"not open","expressionPlan":{"source":"not open","ast":{"kind":"unary","op":"not","operand":{"kind":"id","name":"open"}},"dependencies":["open"]}}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"rows"}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"control row"},{"kind":"attribute","name":"active","expression":"control.key = activeKey","expressionPlan":{"source":"control.key = activeKey","ast":{"kind":"binary","op":"=","left":{"kind":"member","object":{"kind":"id","name":"control"},"key":"key"},"right":{"kind":"id","name":"activeKey"}},"dependencies":["activeKey","control.key"]},"target":"class"},{"kind":"attribute","name":"top","expression":"control.offset","expressionPlan":{"source":"control.offset","ast":{"kind":"member","object":{"kind":"id","name":"control"},"key":"offset"},"dependencies":["control.offset"]},"target":"style"},{"kind":"attribute","name":"data-control-key","expression":"control.key","expressionPlan":{"source":"control.key","ast":{"kind":"member","object":{"kind":"id","name":"control"},"key":"key"},"dependencies":["control.key"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"line"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"guide"},{"kind":"literal","name":"data-ui-guide","value":""},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[]},{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"class","value":"handle"},{"kind":"attribute","name":"data-ui-affordance","expression":"control.affordance","expressionPlan":{"source":"control.affordance","ast":{"kind":"member","object":{"kind":"id","name":"control"},"key":"affordance"},"dependencies":["control.affordance"]}},{"kind":"attribute","name":"data-action","expression":"control.action","expressionPlan":{"source":"control.action","ast":{"kind":"member","object":{"kind":"id","name":"control"},"key":"action"},"dependencies":["control.action"]}},{"kind":"attribute","name":"data-boundary-index","expression":"control.index","expressionPlan":{"source":"control.index","ast":{"kind":"member","object":{"kind":"id","name":"control"},"key":"index"},"dependencies":["control.index"]}},{"kind":"attribute","name":"aria-label","expression":"control.label","expressionPlan":{"source":"control.label","ast":{"kind":"member","object":{"kind":"id","name":"control"},"key":"label"},"dependencies":["control.label"]}}],"children":[{"kind":"element","name":"ui-icon","attributes":[{"kind":"literal","name":"name","value":"plus"}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"tooltip"},{"kind":"literal","name":"role","value":"tooltip"},{"kind":"directive","name":"value","expression":"control.label","expressionPlan":{"source":"control.label","ast":{"kind":"member","object":{"kind":"id","name":"control"},"key":"label"},"dependencies":["control.label"]}}],"children":[]}]}],"flow":{"kind":"each","item":"control","list":"rows","listPlan":{"source":"rows","ast":{"kind":"id","name":"rows"},"dependencies":["rows"]},"key":"control.key","keyPlan":{"source":"control.key","ast":{"kind":"member","object":{"kind":"id","name":"control"},"key":"key"},"dependencies":["control.key"]}}}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"cols"}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"control col"},{"kind":"attribute","name":"active","expression":"control.key = activeKey","expressionPlan":{"source":"control.key = activeKey","ast":{"kind":"binary","op":"=","left":{"kind":"member","object":{"kind":"id","name":"control"},"key":"key"},"right":{"kind":"id","name":"activeKey"}},"dependencies":["activeKey","control.key"]},"target":"class"},{"kind":"attribute","name":"left","expression":"control.offset","expressionPlan":{"source":"control.offset","ast":{"kind":"member","object":{"kind":"id","name":"control"},"key":"offset"},"dependencies":["control.offset"]},"target":"style"},{"kind":"attribute","name":"data-control-key","expression":"control.key","expressionPlan":{"source":"control.key","ast":{"kind":"member","object":{"kind":"id","name":"control"},"key":"key"},"dependencies":["control.key"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"line"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"guide"},{"kind":"literal","name":"data-ui-guide","value":""},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[]},{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"class","value":"handle"},{"kind":"attribute","name":"data-ui-affordance","expression":"control.affordance","expressionPlan":{"source":"control.affordance","ast":{"kind":"member","object":{"kind":"id","name":"control"},"key":"affordance"},"dependencies":["control.affordance"]}},{"kind":"attribute","name":"data-action","expression":"control.action","expressionPlan":{"source":"control.action","ast":{"kind":"member","object":{"kind":"id","name":"control"},"key":"action"},"dependencies":["control.action"]}},{"kind":"attribute","name":"data-boundary-index","expression":"control.index","expressionPlan":{"source":"control.index","ast":{"kind":"member","object":{"kind":"id","name":"control"},"key":"index"},"dependencies":["control.index"]}},{"kind":"attribute","name":"aria-label","expression":"control.label","expressionPlan":{"source":"control.label","ast":{"kind":"member","object":{"kind":"id","name":"control"},"key":"label"},"dependencies":["control.label"]}}],"children":[{"kind":"element","name":"ui-icon","attributes":[{"kind":"literal","name":"name","value":"plus"}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"tooltip"},{"kind":"literal","name":"role","value":"tooltip"},{"kind":"directive","name":"value","expression":"control.label","expressionPlan":{"source":"control.label","ast":{"kind":"member","object":{"kind":"id","name":"control"},"key":"label"},"dependencies":["control.label"]}}],"children":[]}]}],"flow":{"kind":"each","item":"control","list":"cols","listPlan":{"source":"cols","ast":{"kind":"id","name":"cols"},"dependencies":["cols"]},"key":"control.key","keyPlan":{"source":"control.key","ast":{"kind":"member","object":{"kind":"id","name":"control"},"key":"key"},"dependencies":["control.key"]}}}]},{"kind":"element","name":"template","attributes":[],"children":[{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"class","value":"selector row"},{"kind":"attribute","name":"top","expression":"hovered.rowOffset","expressionPlan":{"source":"hovered.rowOffset","ast":{"kind":"member","object":{"kind":"id","name":"hovered"},"key":"rowOffset"},"dependencies":["hovered.rowOffset"]},"target":"style"},{"kind":"literal","name":"data-action","value":"select-row"},{"kind":"attribute","name":"data-row-index","expression":"hovered.rowIndex","expressionPlan":{"source":"hovered.rowIndex","ast":{"kind":"member","object":{"kind":"id","name":"hovered"},"key":"rowIndex"},"dependencies":["hovered.rowIndex"]}},{"kind":"attribute","name":"data-column-index","expression":"hovered.columnIndex","expressionPlan":{"source":"hovered.columnIndex","ast":{"kind":"member","object":{"kind":"id","name":"hovered"},"key":"columnIndex"},"dependencies":["hovered.columnIndex"]}},{"kind":"literal","name":"title","value":"Select row"},{"kind":"literal","name":"aria-label","value":"Select row"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"glyph"}],"children":[{"kind":"element","name":"ui-icon","attributes":[{"kind":"literal","name":"name","value":"grip-vertical"}],"children":[]}]}]},{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"class","value":"selector column"},{"kind":"attribute","name":"left","expression":"hovered.columnOffset","expressionPlan":{"source":"hovered.columnOffset","ast":{"kind":"member","object":{"kind":"id","name":"hovered"},"key":"columnOffset"},"dependencies":["hovered.columnOffset"]},"target":"style"},{"kind":"literal","name":"data-action","value":"select-column"},{"kind":"attribute","name":"data-row-index","expression":"hovered.rowIndex","expressionPlan":{"source":"hovered.rowIndex","ast":{"kind":"member","object":{"kind":"id","name":"hovered"},"key":"rowIndex"},"dependencies":["hovered.rowIndex"]}},{"kind":"attribute","name":"data-column-index","expression":"hovered.columnIndex","expressionPlan":{"source":"hovered.columnIndex","ast":{"kind":"member","object":{"kind":"id","name":"hovered"},"key":"columnIndex"},"dependencies":["hovered.columnIndex"]}},{"kind":"literal","name":"title","value":"Select column"},{"kind":"literal","name":"aria-label","value":"Select column"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"glyph"}],"children":[{"kind":"element","name":"ui-icon","attributes":[{"kind":"literal","name":"name","value":"grip-horizontal"}],"children":[]}]}]}],"flow":{"kind":"if","test":"hovered","testPlan":{"source":"hovered","ast":{"kind":"id","name":"hovered"},"dependencies":["hovered"]}}},{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"class","value":"cell-menu"},{"kind":"attribute","name":"left","expression":"active.menuLeft","expressionPlan":{"source":"active.menuLeft","ast":{"kind":"member","object":{"kind":"id","name":"active"},"key":"menuLeft"},"dependencies":["active.menuLeft"]},"target":"style"},{"kind":"attribute","name":"top","expression":"active.menuTop","expressionPlan":{"source":"active.menuTop","ast":{"kind":"member","object":{"kind":"id","name":"active"},"key":"menuTop"},"dependencies":["active.menuTop"]},"target":"style"},{"kind":"literal","name":"data-action","value":"open-cell-menu"},{"kind":"attribute","name":"data-row-index","expression":"active.rowIndex","expressionPlan":{"source":"active.rowIndex","ast":{"kind":"member","object":{"kind":"id","name":"active"},"key":"rowIndex"},"dependencies":["active.rowIndex"]}},{"kind":"attribute","name":"data-column-index","expression":"active.columnIndex","expressionPlan":{"source":"active.columnIndex","ast":{"kind":"member","object":{"kind":"id","name":"active"},"key":"columnIndex"},"dependencies":["active.columnIndex"]}},{"kind":"literal","name":"title","value":"Cell actions"},{"kind":"literal","name":"aria-label","value":"Cell actions"}],"children":[{"kind":"element","name":"ui-icon","attributes":[{"kind":"literal","name":"name","value":"chevron-down"}],"children":[]}],"flow":{"kind":"if","test":"active","testPlan":{"source":"active","ast":{"kind":"id","name":"active"},"dependencies":["active"]}}}]},"css":":host {\n display: block;\n width: 100%;\n height: 100%;\n overflow: visible;\n pointer-events: none;\n }\n\n :host {\n position: relative;\n width: 100%;\n height: 100%;\n overflow: visible;\n pointer-events: none;\n }\n\n .rows,\n .cols {\n pointer-events: none;\n position: absolute;\n }\n\n .rows {\n inset: 0;\n width: 100%;\n }\n\n .cols {\n inset: 0;\n height: 100%;\n }\n\n .control {\n position: absolute;\n z-index: 1;\n pointer-events: none;\n }\n\n .handle {\n position: absolute;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n padding: 0;\n border: 1px solid var(--ui-affordance-near-color, var(--ui-border-strong));\n border-radius: var(--ui-radius-round);\n background: color-mix(in srgb, var(--ui-surface-elevated) 96%, transparent);\n color: var(--ui-affordance-near-color, var(--ui-text-secondary));\n font: inherit;\n font-size: 16px;\n line-height: 1;\n box-shadow: var(--ui-shadow-xs, 0 1px 2px rgb(0 0 0 / 0.05));\n opacity: 0;\n scale: 0.72;\n transition:\n opacity var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease),\n scale var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease),\n color var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease),\n background-color var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease),\n border-color var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease);\n pointer-events: auto;\n cursor: pointer;\n }\n\n .handle {\n --_ui-default-icon-size: 14px;\n --_ui-default-icon-stroke-width: 2;\n }\n\n .handle[data-ui-proximity=\"near\"],\n .control.active .handle,\n .handle:focus-visible {\n opacity: 1;\n scale: 1;\n }\n\n .control.active .handle,\n .handle:focus-visible {\n border-color: var(--ui-affordance-direct-color, var(--ui-accent-solid));\n background: var(--ui-affordance-direct-color, var(--ui-accent-solid));\n color: var(--ui-text-on-accent);\n box-shadow: var(--ui-shadow-sm, 0 1px 3px rgb(0 0 0 / 0.1));\n }\n\n .handle:focus-visible,\n .selector:focus-visible,\n .cell-menu:focus-visible {\n outline: 2px solid var(--ui-focus-ring);\n outline-offset: 2px;\n }\n\n .control.row {\n left: 0;\n width: 100%;\n height: 0;\n }\n\n .control.row .handle {\n top: -12px;\n left: -30px;\n }\n\n .control.col {\n top: 0;\n width: 0;\n height: 100%;\n }\n\n .control.col .handle {\n top: -30px;\n left: -12px;\n }\n\n .line {\n position: absolute;\n background: var(--ui-affordance-direct-color, var(--ui-accent-solid));\n opacity: 0;\n transition: opacity var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease);\n }\n\n .control.row .line {\n inset: -1px 0 auto;\n height: 2px;\n }\n\n .control.col .line {\n inset: 0 auto 0 -1px;\n width: 2px;\n }\n\n .control.active .line {\n opacity: 0.8;\n }\n\n .guide {\n position: absolute;\n width: var(--ui-affordance-guide-size);\n height: var(--ui-affordance-guide-size);\n border-radius: var(--ui-radius-round);\n background: var(--ui-affordance-guide-color, var(--ui-border-strong));\n opacity: calc(var(--ui-affordance-guide-opacity) * var(--ui-affordance-scope-guide, 1));\n transition: opacity var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease);\n }\n\n .control.row .guide {\n left: -10px;\n top: -2px;\n }\n\n .control.col .guide {\n left: -2px;\n top: -10px;\n }\n\n .control:has(.handle[data-ui-proximity=\"near\"]) .guide,\n .control.active .guide {\n opacity: 0;\n }\n\n .tooltip {\n position: absolute;\n z-index: 2;\n top: calc(100% + 6px);\n left: 50%;\n width: max-content;\n max-width: 14rem;\n padding: var(--ui-space-1) var(--ui-space-2);\n border-radius: var(--ui-radius-sm);\n background: var(--ui-text-primary);\n color: var(--ui-surface-elevated);\n font-size: var(--ui-font-size-xs);\n font-weight: var(--ui-font-medium);\n line-height: var(--ui-line-height-md);\n opacity: 0;\n transform: translateX(-50%);\n transition: opacity var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease);\n pointer-events: none;\n }\n\n .control.row .tooltip {\n top: 50%;\n left: auto;\n right: calc(100% + 8px);\n transform: translateY(-50%);\n }\n\n .control.active .tooltip,\n .handle:focus-visible .tooltip {\n opacity: 1;\n }\n\n .selector,\n .cell-menu {\n position: absolute;\n z-index: 2;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n border: 1px solid transparent;\n background: transparent;\n color: var(--ui-text-secondary);\n box-shadow: none;\n pointer-events: auto;\n cursor: pointer;\n transition:\n color var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease),\n background-color var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease),\n border-color var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease),\n box-shadow var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease);\n }\n\n .selector:hover,\n .cell-menu:hover {\n background: var(--ui-surface-muted);\n color: var(--ui-text-primary);\n box-shadow: var(--ui-shadow-xs, 0 1px 2px rgb(0 0 0 / 0.05));\n }\n\n .selector {\n border-radius: var(--ui-radius-round);\n }\n\n .selector::before {\n content: \"\";\n position: absolute;\n inset: 50% auto auto 50%;\n border-radius: var(--ui-radius-round);\n background: var(--ui-affordance-guide-color, var(--ui-border-strong));\n opacity: calc(var(--ui-affordance-guide-opacity) * var(--ui-affordance-scope-guide, 1));\n transform: translate(-50%, -50%);\n transition: opacity var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease);\n pointer-events: none;\n }\n\n .selector .glyph {\n display: block;\n width: 14px;\n height: 14px;\n --_ui-default-icon-size: 14px;\n --_ui-default-icon-stroke-width: 2;\n opacity: 0;\n transform: scale(0.72);\n transition:\n opacity var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease),\n transform var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease);\n }\n\n .selector:hover::before,\n .selector:focus-visible::before {\n opacity: 0;\n }\n\n .selector:hover .glyph,\n .selector:focus-visible .glyph {\n opacity: 1;\n transform: scale(1);\n }\n\n .selector.row {\n left: -9px;\n width: 18px;\n height: 32px;\n transform: translateY(-50%);\n }\n\n .selector.row::before {\n width: 2px;\n height: 16px;\n }\n\n .selector.column {\n top: -9px;\n width: 32px;\n height: 18px;\n transform: translateX(-50%);\n }\n\n .selector.column::before {\n width: 16px;\n height: 2px;\n }\n\n @media (hover: none), (pointer: coarse) {\n .selector::before {\n opacity: 0;\n }\n\n .selector .glyph {\n opacity: 1;\n transform: none;\n }\n }\n\n .cell-menu {\n width: 24px;\n height: 24px;\n border-radius: var(--ui-radius-sm);\n background: color-mix(in srgb, var(--ui-surface-muted) 78%, transparent);\n }\n\n .cell-menu {\n --_ui-default-icon-size: 15px;\n --_ui-default-icon-stroke-width: 2;\n }\n\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"rows","type":"list(object({ key: string, index: integer, offset: string, affordance: insert-row | insert-column, action: add-row-before | add-row-after | add-column-before | add-column-after, label: string }))","expression":{"source":"[]","ast":{"kind":"array","items":[]},"dependencies":[]}},{"kind":"state","name":"cols","type":"list(object({ key: string, index: integer, offset: string, affordance: insert-row | insert-column, action: add-row-before | add-row-after | add-column-before | add-column-after, label: string }))","expression":{"source":"[]","ast":{"kind":"array","items":[]},"dependencies":[]}},{"kind":"state","name":"hovered","type":"object({ left: number, top: number, width: number, height: number, rowIndex: integer, columnIndex: integer, rowOffset: string, columnOffset: string }) | null","expression":{"source":"null","ast":{"kind":"literal","value":null},"dependencies":[]}},{"kind":"state","name":"active","type":"object({ left: number, top: number, width: number, height: number, rowIndex: integer, columnIndex: integer, menuLeft: string, menuTop: string }) | null","expression":{"source":"null","ast":{"kind":"literal","value":null},"dependencies":[]}},{"kind":"state","name":"activeKey","expression":{"source":"''","ast":{"kind":"literal","value":""},"dependencies":[]}},{"kind":"event","name":"action","type":"object({ action: add-row-before | add-row-after | add-column-before | add-column-after, boundaryIndex: integer }) | object({ action: select-row | select-column, rowIndex: integer, columnIndex: integer }) | object({ action: open-cell-menu, rowIndex: integer, columnIndex: integer, anchor: object({ left: number, top: number, right: number, bottom: number }) })","bubbles":true,"composed":true,"cancelable":false}],"slots":[],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-editor-table-overlay/ui-editor-table-overlay.js"},{"source":{"file":"./components/ui-editor-table-toolbar/ui-editor-table-toolbar.html"},"contract":{"version":1,"name":"UiEditorTableToolbar","tag":"ui-editor-table-toolbar","nativeElement":"div","props":{"actions":{"type":{"kind":"list","item":{"kind":"union","members":[{"kind":"keyword","value":"align-left"},{"kind":"keyword","value":"align-center"},{"kind":"keyword","value":"align-right"},{"kind":"keyword","value":"background-none"},{"kind":"keyword","value":"background-gray"},{"kind":"keyword","value":"background-yellow"},{"kind":"keyword","value":"background-blue"},{"kind":"keyword","value":"background-green"},{"kind":"keyword","value":"background-red"},{"kind":"keyword","value":"add-row-before"},{"kind":"keyword","value":"add-row-after"},{"kind":"keyword","value":"add-column-before"},{"kind":"keyword","value":"add-column-after"},{"kind":"keyword","value":"clear-cells"},{"kind":"keyword","value":"merge-cells"},{"kind":"keyword","value":"split-cell"},{"kind":"keyword","value":"delete-row"},{"kind":"keyword","value":"delete-column"},{"kind":"keyword","value":"delete-table"}]}},"required":false,"target":{"attribute":"actions"},"description":"The complete set of commands the current selection permits."},"cellAlignment":{"type":{"enum":["left","center","right"]},"required":false,"target":{"attribute":"cellalignment"},"description":"Marks the alignment command that is active for the current cell.","default":"left"},"cellBackground":{"type":"string","required":false,"target":{"attribute":"cellbackground"},"description":"Identifies the background choice that is active for the current cell.","default":""},"open":{"type":"boolean","required":false,"target":{"attribute":"open"},"description":"Shows the toolbar while a table selection is active.","default":false}}},"template":{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"role","value":"toolbar"},{"kind":"literal","name":"aria-label","value":"Table actions"},{"kind":"attribute","name":"hidden","expression":"not open","expressionPlan":{"source":"not open","ast":{"kind":"unary","op":"not","operand":{"kind":"id","name":"open"}},"dependencies":["open"]}}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"group"},{"kind":"literal","name":"role","value":"group"},{"kind":"literal","name":"aria-label","value":"Cell alignment"}],"children":[{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"class","value":"icon-button"},{"kind":"attribute","name":"active","expression":"item.active","expressionPlan":{"source":"item.active","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"active"},"dependencies":["item.active"]},"target":"class"},{"kind":"attribute","name":"data-action","expression":"item.action","expressionPlan":{"source":"item.action","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"action"},"dependencies":["item.action"]}},{"kind":"attribute","name":"aria-label","expression":"item.label","expressionPlan":{"source":"item.label","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"label"},"dependencies":["item.label"]}},{"kind":"attribute","name":"title","expression":"item.label","expressionPlan":{"source":"item.label","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"label"},"dependencies":["item.label"]}},{"kind":"attribute","name":"aria-pressed","expression":"item.active","expressionPlan":{"source":"item.active","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"active"},"dependencies":["item.active"]}}],"children":[{"kind":"element","name":"ui-icon","attributes":[{"kind":"attribute","name":"name","expression":"item.action","expressionPlan":{"source":"item.action","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"action"},"dependencies":["item.action"]}}],"children":[]}],"flow":{"kind":"each","item":"item","list":"alignments","listPlan":{"source":"alignments","ast":{"kind":"id","name":"alignments"},"dependencies":["alignments"]},"key":"item.action","keyPlan":{"source":"item.action","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"action"},"dependencies":["item.action"]}}}],"flow":{"kind":"if","test":"alignments","testPlan":{"source":"alignments","ast":{"kind":"id","name":"alignments"},"dependencies":["alignments"]}}},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"sep"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[],"flow":{"kind":"if","test":"alignments and structure","testPlan":{"source":"alignments and structure","ast":{"kind":"binary","op":"and","left":{"kind":"id","name":"alignments"},"right":{"kind":"id","name":"structure"}},"dependencies":["alignments","structure"]}}},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"group"},{"kind":"literal","name":"role","value":"group"},{"kind":"literal","name":"aria-label","value":"Table structure"}],"children":[{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"attribute","name":"data-action","expression":"item.action","expressionPlan":{"source":"item.action","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"action"},"dependencies":["item.action"]}}],"children":[{"kind":"element","name":"ui-icon","attributes":[{"kind":"attribute","name":"name","expression":"item.icon","expressionPlan":{"source":"item.icon","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"icon"},"dependencies":["item.icon"]}}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"directive","name":"value","expression":"item.label","expressionPlan":{"source":"item.label","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"label"},"dependencies":["item.label"]}}],"children":[]}],"flow":{"kind":"each","item":"item","list":"structure","listPlan":{"source":"structure","ast":{"kind":"id","name":"structure"},"dependencies":["structure"]},"key":"item.action","keyPlan":{"source":"item.action","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"action"},"dependencies":["item.action"]}}}],"flow":{"kind":"if","test":"structure","testPlan":{"source":"structure","ast":{"kind":"id","name":"structure"},"dependencies":["structure"]}}},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"sep"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[],"flow":{"kind":"if","test":"(alignments or structure) and hasOverflow","testPlan":{"source":"(alignments or structure) and hasOverflow","ast":{"kind":"binary","op":"and","left":{"kind":"binary","op":"or","left":{"kind":"id","name":"alignments"},"right":{"kind":"id","name":"structure"}},"right":{"kind":"id","name":"hasOverflow"}},"dependencies":["alignments","hasOverflow","structure"]}}},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"overflow"}],"children":[{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"class","value":"more"},{"kind":"literal","name":"data-action","value":"toggle-overflow"},{"kind":"literal","name":"aria-haspopup","value":"menu"},{"kind":"attribute","name":"aria-expanded","expression":"overflowOpen","expressionPlan":{"source":"overflowOpen","ast":{"kind":"id","name":"overflowOpen"},"dependencies":["overflowOpen"]}}],"children":[{"kind":"element","name":"ui-icon","attributes":[{"kind":"literal","name":"name","value":"table"}],"children":[]},{"kind":"element","name":"span","attributes":[],"children":[{"kind":"text","value":"Table options"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"chevron"}],"children":[{"kind":"element","name":"ui-icon","attributes":[{"kind":"literal","name":"name","value":"chevron-down"}],"children":[]}]}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"menu"},{"kind":"literal","name":"role","value":"menu"},{"kind":"literal","name":"aria-label","value":"More table actions"}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"menu-section"},{"kind":"literal","name":"role","value":"none"}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"menu-heading"},{"kind":"literal","name":"role","value":"presentation"}],"children":[{"kind":"text","value":"Background"}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"swatches"},{"kind":"literal","name":"role","value":"group"},{"kind":"literal","name":"aria-label","value":"Cell background"}],"children":[{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"class","value":"swatch-button"},{"kind":"attribute","name":"selected","expression":"swatch.selected","expressionPlan":{"source":"swatch.selected","ast":{"kind":"member","object":{"kind":"id","name":"swatch"},"key":"selected"},"dependencies":["swatch.selected"]},"target":"class"},{"kind":"literal","name":"role","value":"menuitemradio"},{"kind":"attribute","name":"aria-checked","expression":"swatch.selected","expressionPlan":{"source":"swatch.selected","ast":{"kind":"member","object":{"kind":"id","name":"swatch"},"key":"selected"},"dependencies":["swatch.selected"]}},{"kind":"attribute","name":"data-action","expression":"swatch.action","expressionPlan":{"source":"swatch.action","ast":{"kind":"member","object":{"kind":"id","name":"swatch"},"key":"action"},"dependencies":["swatch.action"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"swatch"},{"kind":"attribute","name":"default","expression":"not swatch.color","expressionPlan":{"source":"not swatch.color","ast":{"kind":"unary","op":"not","operand":{"kind":"member","object":{"kind":"id","name":"swatch"},"key":"color"}},"dependencies":["swatch.color"]},"target":"class"},{"kind":"attribute","name":"--_swatch","expression":"swatch.color","expressionPlan":{"source":"swatch.color","ast":{"kind":"member","object":{"kind":"id","name":"swatch"},"key":"color"},"dependencies":["swatch.color"]},"target":"style"}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"directive","name":"value","expression":"swatch.label","expressionPlan":{"source":"swatch.label","ast":{"kind":"member","object":{"kind":"id","name":"swatch"},"key":"label"},"dependencies":["swatch.label"]}}],"children":[]}],"flow":{"kind":"each","item":"swatch","list":"swatches","listPlan":{"source":"swatches","ast":{"kind":"id","name":"swatches"},"dependencies":["swatches"]},"key":"swatch.action","keyPlan":{"source":"swatch.action","ast":{"kind":"member","object":{"kind":"id","name":"swatch"},"key":"action"},"dependencies":["swatch.action"]}}}]}],"flow":{"kind":"if","test":"swatches","testPlan":{"source":"swatches","ast":{"kind":"id","name":"swatches"},"dependencies":["swatches"]}}},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"menu-section divided"},{"kind":"literal","name":"role","value":"none"}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"menu-heading"},{"kind":"literal","name":"role","value":"presentation"},{"kind":"directive","name":"value","expression":"section.heading","expressionPlan":{"source":"section.heading","ast":{"kind":"member","object":{"kind":"id","name":"section"},"key":"heading"},"dependencies":["section.heading"]}}],"children":[]},{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"role","value":"menuitem"},{"kind":"attribute","name":"danger","expression":"item.danger","expressionPlan":{"source":"item.danger","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"danger"},"dependencies":["item.danger"]},"target":"class"},{"kind":"attribute","name":"data-action","expression":"item.action","expressionPlan":{"source":"item.action","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"action"},"dependencies":["item.action"]}}],"children":[{"kind":"element","name":"ui-icon","attributes":[{"kind":"attribute","name":"name","expression":"item.icon","expressionPlan":{"source":"item.icon","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"icon"},"dependencies":["item.icon"]}}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"directive","name":"value","expression":"item.label","expressionPlan":{"source":"item.label","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"label"},"dependencies":["item.label"]}}],"children":[]}],"flow":{"kind":"each","item":"item","list":"section.items","listPlan":{"source":"section.items","ast":{"kind":"member","object":{"kind":"id","name":"section"},"key":"items"},"dependencies":["section.items"]},"key":"item.action","keyPlan":{"source":"item.action","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"action"},"dependencies":["item.action"]}}}],"flow":{"kind":"each","item":"section","list":"sections","listPlan":{"source":"sections","ast":{"kind":"id","name":"sections"},"dependencies":["sections"]},"key":"section.heading","keyPlan":{"source":"section.heading","ast":{"kind":"member","object":{"kind":"id","name":"section"},"key":"heading"},"dependencies":["section.heading"]}}}],"flow":{"kind":"if","test":"overflowOpen","testPlan":{"source":"overflowOpen","ast":{"kind":"id","name":"overflowOpen"},"dependencies":["overflowOpen"]}}}],"flow":{"kind":"if","test":"hasOverflow","testPlan":{"source":"hasOverflow","ast":{"kind":"id","name":"hasOverflow"},"dependencies":["hasOverflow"]}}}]},"css":".looma-editor__mobile-toolbar-shell :host {\n min-width: max-content;\n min-height: 100%;\n padding: 0;\n background: transparent;\n border: 0;\n border-radius: 0;\n box-shadow: none;\n backdrop-filter: none;\n }\n\n .looma-editor__mobile-toolbar-shell :host button {\n min-height: 44px;\n background: transparent;\n }\n\n .looma-editor__mobile-toolbar-shell :host button.active,\n .looma-editor__mobile-toolbar-shell :host button.selected {\n background: var(--ui-accent-soft, var(--ui-accent-subtle));\n }\n\n .looma-editor__mobile-toolbar-shell :host .menu {\n top: auto;\n right: 0;\n bottom: calc(100% + var(--ui-space-2));\n max-height: min(50dvh, 22rem);\n overflow-y: auto;\n overscroll-behavior: contain;\n }\n :host {\n display: inline-flex;\n align-items: center;\n gap: var(--ui-space-1);\n padding: var(--ui-space-1);\n background: color-mix(in srgb, var(--ui-surface) 94%, transparent);\n border: 1px solid var(--ui-border);\n border-radius: calc(var(--ui-radius-md) + 2px);\n box-shadow: var(--ui-shadow-lg, 0 10px 15px -3px rgb(0 0 0 / 0.1));\n backdrop-filter: blur(10px);\n }\n\n .group {\n display: inline-flex;\n align-items: center;\n gap: 2px;\n overflow: hidden;\n }\n\n .sep {\n width: 1px;\n align-self: stretch;\n background: var(--ui-border);\n }\n\n .overflow {\n position: relative;\n }\n\n :host button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--ui-space-2);\n min-height: 32px;\n border: 0;\n border-radius: var(--ui-radius-sm);\n background: transparent;\n color: var(--ui-text-primary);\n cursor: pointer;\n font-size: var(--ui-font-size-sm);\n font-weight: 500;\n line-height: 1;\n padding: var(--ui-space-2) var(--ui-space-2);\n white-space: nowrap;\n }\n\n :host button:hover {\n background: var(--ui-surface-hover);\n }\n\n :host button.active {\n background: var(--ui-accent-soft, var(--ui-accent-subtle));\n color: var(--ui-accent-active);\n }\n\n .group button {\n border-radius: var(--ui-radius-sm);\n }\n\n .group button + button {\n border-left: 0;\n }\n\n :host .more {\n border: 0;\n border-radius: var(--ui-radius-sm);\n }\n\n :host button.danger {\n color: var(--ui-danger);\n }\n\n :host {\n --_ui-default-icon-size: var(--ui-editor-toolbar-icon-size, 1rem);\n --_ui-default-icon-stroke-width: var(--ui-editor-toolbar-icon-stroke-width, 1.75);\n }\n\n .chevron {\n display: inline-flex;\n --_ui-default-icon-size: 0.875rem;\n }\n\n :host .icon-button {\n width: 32px;\n padding-inline: 0;\n }\n\n .menu {\n position: absolute;\n top: calc(100% + var(--ui-space-2));\n right: 0;\n min-width: 12rem;\n padding: var(--ui-space-1);\n background: var(--ui-surface);\n border: 1px solid var(--ui-border);\n border-radius: var(--ui-radius-md);\n box-shadow: var(--ui-shadow-lg, 0 10px 15px -3px rgb(0 0 0 / 0.1));\n display: flex;\n flex-direction: column;\n gap: 2px;\n z-index: 2;\n }\n\n .menu-section + .menu-section {\n margin-top: var(--ui-space-1);\n padding-top: var(--ui-space-1);\n border-top: 1px solid color-mix(in srgb, var(--ui-border) 80%, transparent);\n }\n\n .menu-heading {\n padding: var(--ui-space-1) var(--ui-space-2);\n font-size: var(--ui-font-size-2xs);\n font-weight: 700;\n letter-spacing: 0.05em;\n text-transform: uppercase;\n color: var(--ui-text-muted);\n }\n\n .menu button {\n display: flex;\n justify-content: flex-start;\n width: 100%;\n text-align: left;\n }\n\n .swatches {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 2px;\n }\n\n :host .swatch-button {\n gap: var(--ui-space-1);\n justify-content: flex-start;\n }\n\n .swatch {\n width: 14px;\n height: 14px;\n flex: 0 0 14px;\n border: 1px solid color-mix(in srgb, var(--ui-border) 80%, #000);\n border-radius: 3px;\n background: var(--_swatch);\n }\n\n .swatch.default {\n background:\n linear-gradient(135deg, transparent 44%, var(--ui-danger) 46% 54%, transparent 56%),\n var(--ui-surface);\n }\n\n .swatch-button.selected {\n background: var(--ui-accent-soft, var(--ui-accent-subtle));\n }\n\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"alignments","type":"list(object({ action: align-left | align-center | align-right, label: string, active: boolean }))","expression":{"source":"[]","ast":{"kind":"array","items":[]},"dependencies":[]}},{"kind":"state","name":"structure","type":"list(object({ action: add-row-after | add-column-after, label: string, icon: string }))","expression":{"source":"[]","ast":{"kind":"array","items":[]},"dependencies":[]}},{"kind":"state","name":"swatches","type":"list(object({ action: string, label: string, color: string, selected: boolean }))","expression":{"source":"[]","ast":{"kind":"array","items":[]},"dependencies":[]}},{"kind":"state","name":"sections","type":"list(object({ heading: string, items: list(object({ action: string, label: string, icon: string, danger: boolean })) }))","expression":{"source":"[]","ast":{"kind":"array","items":[]},"dependencies":[]}},{"kind":"state","name":"hasOverflow","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"overflowOpen","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"event","name":"action","type":"object({ action: align-left | align-center | align-right | background-none | background-gray | background-yellow | background-blue | background-green | background-red | add-row-before | add-row-after | add-column-before | add-column-after | clear-cells | merge-cells | split-cell | delete-row | delete-column | delete-table })","bubbles":true,"composed":true,"cancelable":false}],"slots":[],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-editor-table-toolbar/ui-editor-table-toolbar.js"},{"source":{"file":"./components/ui-editor-toolbar/ui-editor-toolbar.html"},"contract":{"version":1,"name":"UiEditorToolbar","tag":"ui-editor-toolbar","nativeElement":"div","props":{"floating":{"type":"boolean","required":false,"target":{"attribute":"floating"},"description":"Shows the toolbar as a floating bar beside the selection rather than pinned to the editor.","default":false}}},"template":{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"role","value":"toolbar"},{"kind":"literal","name":"aria-label","value":"Editor toolbar"}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"strip"}],"children":[{"kind":"slot"}],"ref":"strip"}]},"css":":host {\n position: sticky;\n top: 0;\n z-index: var(--ui-editor-toolbar-z-index, 10);\n display: flex;\n align-items: center;\n padding: var(--ui-editor-toolbar-padding-block, 6px) var(--ui-editor-toolbar-padding-inline, 12px);\n min-height: var(--ui-editor-toolbar-min-height, 48px);\n background: var(--ui-editor-toolbar-surface, var(--ui-surface));\n border-bottom: 1px solid var(--ui-editor-toolbar-border, var(--ui-border));\n }\n\n /* One row, always. When the controls outgrow the space, the row scrolls sideways rather than\n wrapping into several lines, and a fade at each edge that has more to show says so. */\n .strip {\n display: flex;\n flex: 1 1 auto;\n align-items: center;\n justify-content: flex-start;\n gap: var(--ui-editor-toolbar-gap, 2px);\n min-width: 0;\n overflow-x: auto;\n overflow-y: hidden;\n overscroll-behavior-inline: contain;\n scrollbar-width: none;\n }\n\n .strip::-webkit-scrollbar {\n display: none;\n }\n\n .strip > :slotted(*) {\n flex: 0 0 auto;\n }\n\n /* The edge fades are the scroll fade every Looma scroller uses (see ui-scroll-area), a mask on the\n strip, so a floating toolbar's border and shadow stay whole. */\n .strip {\n --_ui-scroll-fade-direction: to right;\n --_ui-scroll-fade-size: var(--ui-editor-toolbar-fade-size, var(--ui-scroll-fade-size, 24px));\n mask-image: linear-gradient(\n var(--_ui-scroll-fade-direction),\n transparent,\n #000 var(--_ui-scroll-fade-start),\n #000 calc(100% - var(--_ui-scroll-fade-end)),\n transparent\n );\n animation: ui-scroll-fade-start linear, ui-scroll-fade-start-hold linear, ui-scroll-fade-end-hold linear, ui-scroll-fade-end linear;\n animation-timeline: scroll(self inline);\n animation-range:\n 0 var(--_ui-scroll-fade-size),\n var(--_ui-scroll-fade-size) calc(100% + 1px),\n -1px calc(100% - var(--_ui-scroll-fade-size)),\n calc(100% - var(--_ui-scroll-fade-size)) 100%;\n }\n\n :host:dir(rtl) .strip {\n --_ui-scroll-fade-direction: to left;\n }\n\n :slotted(.divider) {\n width: 1px;\n height: 20px;\n background: var(--ui-editor-toolbar-divider, var(--ui-border));\n flex-shrink: 0;\n margin: 0 var(--ui-editor-toolbar-divider-margin, 4px);\n }\n\n :host-state([floating]) {\n position: relative;\n top: auto;\n width: max-content;\n max-width: min(calc(100vw - 24px), 100%);\n min-height: auto;\n padding: var(--ui-editor-toolbar-floating-padding, 4px);\n background: color-mix(in srgb, var(--ui-editor-toolbar-surface, var(--ui-surface)) 96%, transparent);\n border: 1px solid var(--ui-editor-toolbar-border, var(--ui-border));\n border-radius: var(--ui-editor-toolbar-floating-radius, var(--ui-radius-lg));\n box-shadow: var(--ui-editor-toolbar-floating-shadow, var(--ui-shadow-lg, 0 10px 24px rgb(0 0 0 / 0.12)));\n backdrop-filter: blur(10px);\n }\n\n @media (max-width: 767px) {\n :host {\n position: fixed;\n top: auto;\n bottom: env(safe-area-inset-bottom);\n left: 0;\n right: 0;\n min-height: var(--ui-editor-toolbar-mobile-min-height, 56px);\n border-top: 1px solid var(--ui-editor-toolbar-border, var(--ui-border));\n border-bottom: none;\n box-shadow: var(--ui-editor-toolbar-mobile-shadow, 0 -2px 8px rgb(0 0 0 / 0.06));\n }\n\n :host-state([floating]) {\n position: relative;\n inset: auto;\n min-height: auto;\n border: 1px solid var(--ui-editor-toolbar-border, var(--ui-border));\n border-radius: var(--ui-editor-toolbar-floating-radius, var(--ui-radius-lg));\n box-shadow: var(--ui-editor-toolbar-floating-shadow, var(--ui-shadow-lg, 0 10px 24px rgb(0 0 0 / 0.12)));\n }\n }\n\n /* Inside LoomaEditor's sticky shell, the shell is the sticky surface. */\n .looma-editor__sticky-toolbar-shell :host {\n position: relative;\n min-height: var(--ui-editor-toolbar-min-height, 48px);\n background: transparent;\n border: 0;\n box-shadow: none;\n }\n\n /* Inside LoomaEditor's mobile shell, the toolbar is a scroll-snapping strip. */\n .looma-editor__mobile-toolbar-shell :host-state([floating]) {\n width: 100%;\n max-width: none;\n min-height: 100%;\n padding: 0;\n background: transparent;\n border: 0;\n border-radius: 0;\n box-shadow: none;\n backdrop-filter: none;\n }\n\n .looma-editor__mobile-toolbar-shell :host-state([floating]) .strip {\n scroll-snap-type: x mandatory;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]}},{"source":{"file":"./components/ui-floating-action-button/ui-floating-action-button.html"},"contract":{"version":1,"name":"UiFloatingActionButton","tag":"ui-floating-action-button","nativeElement":"button","props":{"disabled":{"type":"boolean","required":false,"target":{"attribute":"disabled"},"description":"Disables the button, so it cannot be pressed or focused, and fades it to 60% opacity.","default":false},"label":{"type":"string","required":false,"target":{"attribute":"aria-label"},"description":"The button's accessible name. The button usually holds only an icon, so name the action it performs.","default":""},"mobileOnly":{"type":"boolean","required":false,"target":{"attribute":"mobileonly"},"description":"Hides the button on viewports 768px wide and wider, for a shortcut that only phones need. Make sure the action is reachable another way at those\n widths.","default":false}}},"template":{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"attribute","name":"aria-label","expression":"label","expressionPlan":{"source":"label","ast":{"kind":"id","name":"label"},"dependencies":["label"]}},{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}}],"children":[{"kind":"slot"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-floating-action-button-inset-block-end {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-floating-action-button-inset-inline-end {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-floating-action-button-z-index {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n position: fixed;\n inset-block-end: calc(var(--ui-floating-action-button-inset-block-end, var(--ui-space-6)) + env(safe-area-inset-bottom));\n inset-inline-end: max(\n var(--ui-floating-action-button-inset-inline-end, var(--ui-space-5)),\n env(safe-area-inset-right)\n );\n inline-size: var(--ui-control-min-block-size);\n block-size: var(--ui-control-min-block-size);\n display: inline-flex;\n z-index: var(--ui-floating-action-button-z-index, 100);\n }\n\n :host {\n appearance: none;\n border: none;\n border-radius: 999px;\n margin: 0;\n padding: 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: var(--ui-accent);\n color: var(--ui-on-accent);\n box-shadow: 0 4px 12px color-mix(in srgb, var(--ui-accent) 40%, transparent);\n cursor: pointer;\n transition:\n background-color var(--ui-motion-fast) var(--ui-motion-ease),\n transform var(--ui-motion-fast) var(--ui-motion-ease),\n box-shadow var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n :host:hover:enabled {\n background: var(--ui-accent-hover);\n box-shadow: 0 6px 16px color-mix(in srgb, var(--ui-accent) 50%, transparent);\n }\n\n :host:active:enabled {\n transform: scale(0.94);\n }\n\n :host:focus-visible {\n outline: 2px solid var(--ui-focus-ring);\n outline-offset: 2px;\n }\n\n :host:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n }\n\n :slotted(svg) {\n inline-size: var(--ui-icon-size-lg);\n block-size: var(--ui-icon-size-lg);\n flex-shrink: 0;\n }\n\n @media (min-width: 768px) {\n :host-state([mobileOnly]) {\n display: none;\n }\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"button","choices":["button"]}},{"source":{"file":"./components/ui-form-field/ui-form-field.html"},"contract":{"version":1,"name":"UiFormField","tag":"ui-form-field","nativeElement":"div","props":{"disabled":{"type":"boolean","required":false,"target":{"attribute":"disabled"},"description":"Disables the field's control: the first input, textarea, or select inside it. The field writes this to the control whenever it updates, so set it here\n rather than on the control.","default":false},"invalid":{"type":"boolean","required":false,"target":{"attribute":"invalid"},"description":"Marks the field's control invalid by setting aria-invalid on it. Pair it with content in the error slot, which the field already links to the control as\n its description.","default":false},"required":{"type":"boolean","required":false,"target":{"attribute":"required"},"description":"Marks the field's control required, for native form validation. Like disabled, it is written to the control, so set it here rather than on the control. It\n adds no visual marker; show one in the label if the form needs it.","default":false}}},"template":{"kind":"element","name":"div","attributes":[],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"label"}],"children":[{"kind":"slot","fallback":[],"name":"label"}]},{"kind":"slot"},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"help"}],"children":[{"kind":"slot","fallback":[],"name":"help"}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"error"}],"children":[{"kind":"slot","fallback":[],"name":"error"}]}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-form-field-help-min-block-size {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-form-field-help-min-block-size: var(--ui-form-field-help-min-block-size);\n\n display: grid;\n gap: var(--ui-space-2);\n min-inline-size: 0;\n align-content: start;\n color: var(--ui-text-primary);\n }\n\n /* Each named region styles whatever fills it, however it was slotted (slot=\"…\" in HTML, #label\n in Vue), and generates no box of its own, so an empty region adds no gap. */\n .label,\n .help,\n .error {\n display: contents;\n }\n\n .label {\n color: var(--ui-text-secondary);\n font-size: var(--ui-font-size-sm);\n }\n\n .help {\n color: var(--ui-text-muted);\n font-size: var(--ui-font-size-sm);\n line-height: var(--ui-line-height-md);\n }\n\n .help > :slotted(*) {\n min-block-size: var(--_ui-form-field-help-min-block-size, 0);\n }\n\n /* An error reads in the danger colour, the one the invalid control's border takes. */\n .error,\n :slotted([role=\"alert\"]) {\n color: var(--ui-danger);\n font-size: var(--ui-font-size-sm);\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true,"name":"label"},{"dynamic":false,"required":true},{"dynamic":false,"required":true,"name":"help"},{"dynamic":false,"required":true,"name":"error"}],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-form-field/ui-form-field.js"},{"source":{"file":"./components/ui-grid/ui-grid.html"},"contract":{"version":1,"name":"UiGrid","tag":"ui-grid","nativeElement":"div","props":{"gap":{"type":{"enum":["xs","s","m","l","xl"]},"required":false,"target":{"attribute":"gap"},"description":"Space between cells, on the spacing scale: xs is 0.5rem, s 0.75rem, m 1rem (also the default), l 1.5rem, and xl 2rem. The --ui-grid-gap custom property,\n set on the grid itself, overrides it; set on an ancestor, it does nothing."},"min":{"type":{"enum":["sm","md","lg"]},"required":false,"target":{"attribute":"min"},"description":"The narrowest a column may get before the grid drops to fewer columns: sm is 12rem (also the default), md is 16rem, and lg is 20rem. The grid fits as many\n equal columns as its width allows, and a single column never overflows a narrower container."}}},"template":{"kind":"element","name":"div","attributes":[],"children":[{"kind":"slot"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-grid-gap {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-grid-min {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n --_grid-gap: var(--ui-space-4);\n --_grid-min: 12rem;\n display: grid;\n gap: var(--ui-grid-gap, var(--_grid-gap));\n grid-template-columns: repeat(auto-fit, minmax(min(var(--ui-grid-min, var(--_grid-min)), 100%), 1fr));\n min-inline-size: 0;\n max-inline-size: 100%;\n margin: 0;\n }\n\n :host-state([gap=\"xs\"]) {\n --_grid-gap: var(--ui-space-2);\n }\n :host-state([gap=\"s\"]) {\n --_grid-gap: var(--ui-space-3);\n }\n :host-state([gap=\"m\"]) {\n --_grid-gap: var(--ui-space-4);\n }\n :host-state([gap=\"l\"]) {\n --_grid-gap: var(--ui-space-5);\n }\n :host-state([gap=\"xl\"]) {\n --_grid-gap: var(--ui-space-6);\n }\n :host-state([min=\"md\"]) {\n --_grid-min: 16rem;\n }\n :host-state([min=\"lg\"]) {\n --_grid-min: 20rem;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]}},{"source":{"file":"./components/ui-icon-button/ui-icon-button.html"},"contract":{"version":1,"name":"UiIconButton","tag":"ui-icon-button","nativeElement":"button","props":{"anticipatory":{"type":"boolean","required":false,"target":{"attribute":"anticipatory"},"description":"Keeps the button out of sight until it is wanted: at rest a fine pointer sees only a small guide dot, and the button appears on hover, on focus, or when\n the pointer comes near inside a ui-affordance-scope. Touch devices and the solid variant always show it.","default":false},"disabled":{"type":"boolean","required":false,"target":{"attribute":"disabled"},"description":"Disables the button, so it cannot be pressed or focused, and washes it out: the same shape, with less colour and contrast (--ui-disabled-filter).","default":false},"label":{"type":"string","required":false,"target":{"attribute":"aria-label"},"description":"Accessible name for the icon."},"round":{"type":"boolean","required":false,"target":{"attribute":"round"},"description":"Use a fully circular shape.","default":false},"size":{"type":{"enum":["sm","md","lg"]},"required":false,"target":{"attribute":"size"},"description":"Button and icon size together: sm is 1.75rem with a small icon, md is 2rem, and lg is 2.5rem with a large icon. On touch, every size gets an invisible hit\n area of at least 44px.","default":"md"},"variant":{"type":{"enum":["ghost","outline","solid"]},"required":false,"target":{"attribute":"variant"},"description":"Emphasis. ghost shows only the icon until it is hovered, for toolbars and dense rows; outline adds a border on the default surface; solid fills with the\n accent colour, for the one primary action in a group.","default":"ghost"}}},"template":{"kind":"element","name":"button","attributes":[{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}},{"kind":"literal","name":"type","value":"button"},{"kind":"attribute","name":"aria-label","expression":"label","expressionPlan":{"source":"label","ast":{"kind":"id","name":"label"},"dependencies":["label"]}}],"children":[{"kind":"slot"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-icon-button-active-scale {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-button-border {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-button-disabled-filter {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-button-disabled-opacity {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-button-hover-border {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-button-hover-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-button-hover-text {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-button-icon-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-button-icon-stroke-width {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-button-outline-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-button-outline-text {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-button-radius {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-button-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-button-solid-hover-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-button-solid-shadow {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-button-solid-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-button-solid-text {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-button-surface {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-icon-button-icon-size: var(--ui-icon-button-icon-size);\n --_ui-icon-button-icon-stroke-width: var(--ui-icon-button-icon-stroke-width);\n\n display: inline-flex;\n color: var(--ui-text-secondary);\n }\n\n :host-state([anticipatory]) {\n position: relative;\n }\n\n :host-state([anticipatory])::before {\n content: \"\";\n position: absolute;\n inset: 50% auto auto 50%;\n z-index: 1;\n inline-size: var(--ui-affordance-guide-size);\n block-size: var(--ui-affordance-guide-size);\n border-radius: var(--ui-radius-round);\n background: var(--ui-affordance-guide-color, var(--ui-border-strong));\n opacity: calc(var(--ui-affordance-guide-opacity) * var(--ui-affordance-scope-guide, 1));\n transform: translate(-50%, -50%);\n transition: opacity var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease);\n pointer-events: none;\n }\n\n /* At rest an anticipatory button shows only its guide dot; proximity, hover, or focus reveals the\n * surface and icon. The root is the native button, so hiding it outright would hide the dot\n * too, and slotted icons sit outside this scope; `color: transparent` hides currentColor icons. */\n @media (hover: hover) and (pointer: fine) {\n :host-state([anticipatory]):not(:host-state([variant=\"solid\"]), [data-ui-proximity=\"near\"], :hover, :focus-visible) {\n border-color: transparent;\n background: transparent;\n box-shadow: none;\n color: transparent;\n }\n }\n\n :host-state([anticipatory]):is(:host-state([variant=\"solid\"]), [data-ui-proximity=\"near\"], :hover, :focus-visible)::before {\n opacity: 0;\n }\n\n :host {\n /* The size prop resolves here; --ui-icon-button-size overrides it on an element. */\n --_size: 2rem;\n appearance: none;\n inline-size: var(--ui-icon-button-size, var(--_size));\n block-size: var(--ui-icon-button-size, var(--_size));\n min-inline-size: var(--ui-icon-button-size, var(--_size));\n min-block-size: var(--ui-icon-button-size, var(--_size));\n padding: 0;\n margin: 0;\n border: 1px solid transparent;\n border-radius: var(--ui-icon-button-radius, var(--ui-radius-md));\n background: var(--ui-icon-button-surface, transparent);\n color: inherit;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition:\n background-color var(--ui-motion-fast) var(--ui-motion-ease),\n border-color var(--ui-motion-fast) var(--ui-motion-ease),\n color var(--ui-motion-fast) var(--ui-motion-ease),\n box-shadow var(--ui-motion-fast) var(--ui-motion-ease),\n transform var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n @media (hover: none), (pointer: coarse) {\n :host-state([anticipatory])::before {\n opacity: 0;\n }\n }\n\n /* A touch target without a bigger button: an invisible hit area, at least the control\n minimum, centred on the button (::before is the anticipatory guide). */\n @media (pointer: coarse) {\n :host {\n position: relative;\n }\n\n :host::after {\n content: \"\";\n position: absolute;\n inset: 50% auto auto 50%;\n inline-size: max(100%, var(--ui-control-min-block-size));\n block-size: max(100%, var(--ui-control-min-block-size));\n transform: translate(-50%, -50%);\n }\n }\n\n html[data-ui-input-modality=\"touch\"] :host {\n position: relative;\n }\n\n html[data-ui-input-modality=\"touch\"] :host::after {\n content: \"\";\n position: absolute;\n inset: 50% auto auto 50%;\n inline-size: max(100%, var(--ui-control-min-block-size));\n block-size: max(100%, var(--ui-control-min-block-size));\n transform: translate(-50%, -50%);\n }\n\n :host-state([size=\"sm\"]) {\n --_size: 1.75rem;\n inline-size: var(--ui-icon-button-size, var(--_size));\n block-size: var(--ui-icon-button-size, var(--_size));\n min-inline-size: var(--ui-icon-button-size, var(--_size));\n min-block-size: var(--ui-icon-button-size, var(--_size));\n }\n\n :host-state([size=\"lg\"]) {\n --_size: 2.5rem;\n inline-size: var(--ui-icon-button-size, var(--_size));\n block-size: var(--ui-icon-button-size, var(--_size));\n min-inline-size: var(--ui-icon-button-size, var(--_size));\n min-block-size: var(--ui-icon-button-size, var(--_size));\n }\n\n :host-state([round]) {\n border-radius: var(--ui-radius-round);\n }\n\n :host-state([variant=\"outline\"]) {\n border-color: var(--ui-icon-button-border, var(--ui-border-default));\n background: var(--ui-icon-button-outline-surface, var(--ui-surface-default));\n color: var(--ui-icon-button-outline-text, var(--ui-text-primary));\n }\n\n :host-state([variant=\"solid\"]) {\n background: var(--ui-icon-button-solid-surface, var(--ui-accent-solid));\n color: var(--ui-icon-button-solid-text, var(--ui-text-on-accent));\n box-shadow: var(\n --ui-icon-button-solid-shadow,\n 0 1px 2px color-mix(in srgb, var(--ui-accent-solid) 18%, transparent)\n );\n }\n\n :host:hover:enabled {\n /* Derived from the text colour so the ghost hover shows on any background. */\n background: var(--ui-icon-button-hover-surface, color-mix(in srgb, currentColor 8%, transparent));\n color: var(--ui-icon-button-hover-text, var(--ui-text-primary));\n }\n\n :host-state([variant=\"outline\"]):hover:enabled {\n border-color: var(--ui-icon-button-hover-border, var(--ui-border-strong));\n }\n\n :host-state([variant=\"solid\"]):hover:enabled {\n background: var(--ui-icon-button-solid-hover-surface, var(--ui-accent-hover));\n }\n\n :host:active:enabled {\n transform: scale(var(--ui-icon-button-active-scale, 0.96));\n }\n\n :host:focus-visible {\n outline: none;\n box-shadow: var(--ui-focus-halo);\n }\n\n /* Disabled colours fall back to each variant's own; ghost takes only the icon colour. */\n /* Disabled washes the button out the way Button does: the same shape, one filter. */\n :host:disabled {\n filter: var(--ui-icon-button-disabled-filter, var(--ui-disabled-filter));\n opacity: var(--ui-icon-button-disabled-opacity, 1);\n cursor: not-allowed;\n box-shadow: none;\n }\n\n :host {\n --_icon-button-icon-default: var(--ui-icon-size-md);\n /* A slotted ui-icon is its own component, out of reach of the svg rule below; these are its\n defaults, which its own --ui-icon-* hooks still override. */\n --_ui-default-icon-size: var(--_ui-icon-button-icon-size, var(--_icon-button-icon-default));\n --_ui-default-icon-stroke-width: var(--_ui-icon-button-icon-stroke-width, 1.75);\n }\n\n :host-state([size=\"sm\"]) {\n --_icon-button-icon-default: var(--ui-icon-size-sm);\n }\n\n :host-state([size=\"lg\"]) {\n --_icon-button-icon-default: var(--ui-icon-size-lg);\n }\n\n :slotted(svg) {\n inline-size: var(--_ui-icon-button-icon-size, var(--_icon-button-icon-default));\n block-size: var(--_ui-icon-button-icon-size, var(--_icon-button-icon-default));\n flex-shrink: 0;\n stroke-width: var(--_ui-icon-button-icon-stroke-width, 1.75);\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"button","choices":["button"]},"controller":"./components/ui-icon-button/ui-icon-button.js"},{"source":{"file":"./components/ui-icon/ui-icon.html"},"contract":{"version":1,"name":"UiIcon","tag":"ui-icon","nativeElement":"span","props":{"name":{"type":"string","required":false,"target":{"attribute":"name"},"description":"Which icon to draw, by its name in Looma's icon set (LOOMA_ICONS), such as \"align-left\". An unknown or empty name draws nothing. The icon is hidden from\n assistive technology, so name the control it sits in.","default":""}}},"template":{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[{"kind":"element","name":"svg","attributes":[{"kind":"literal","name":"viewBox","value":"0 0 24 24"},{"kind":"literal","name":"fill","value":"none"},{"kind":"literal","name":"stroke","value":"currentColor"},{"kind":"literal","name":"stroke-width","value":"2"},{"kind":"literal","name":"stroke-linecap","value":"round"},{"kind":"literal","name":"stroke-linejoin","value":"round"},{"kind":"literal","name":"focusable","value":"false"}],"children":[{"kind":"element","name":"g","attributes":[],"children":[{"kind":"element","name":"path","attributes":[{"kind":"attribute","name":"d","expression":"shape.d","expressionPlan":{"source":"shape.d","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"d"},"dependencies":["shape.d"]}}],"children":[],"flow":{"kind":"if","test":"shape.tag = 'path'","testPlan":{"source":"shape.tag = 'path'","ast":{"kind":"binary","op":"=","left":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"tag"},"right":{"kind":"literal","value":"path"}},"dependencies":["shape.tag"]}}},{"kind":"element","name":"circle","attributes":[{"kind":"attribute","name":"cx","expression":"shape.cx","expressionPlan":{"source":"shape.cx","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"cx"},"dependencies":["shape.cx"]}},{"kind":"attribute","name":"cy","expression":"shape.cy","expressionPlan":{"source":"shape.cy","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"cy"},"dependencies":["shape.cy"]}},{"kind":"attribute","name":"r","expression":"shape.r","expressionPlan":{"source":"shape.r","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"r"},"dependencies":["shape.r"]}}],"children":[],"flow":{"kind":"if","test":"shape.tag = 'circle'","testPlan":{"source":"shape.tag = 'circle'","ast":{"kind":"binary","op":"=","left":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"tag"},"right":{"kind":"literal","value":"circle"}},"dependencies":["shape.tag"]}}},{"kind":"element","name":"rect","attributes":[{"kind":"attribute","name":"x","expression":"shape.x","expressionPlan":{"source":"shape.x","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"x"},"dependencies":["shape.x"]}},{"kind":"attribute","name":"y","expression":"shape.y","expressionPlan":{"source":"shape.y","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"y"},"dependencies":["shape.y"]}},{"kind":"attribute","name":"width","expression":"shape.width","expressionPlan":{"source":"shape.width","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"width"},"dependencies":["shape.width"]}},{"kind":"attribute","name":"height","expression":"shape.height","expressionPlan":{"source":"shape.height","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"height"},"dependencies":["shape.height"]}},{"kind":"attribute","name":"rx","expression":"shape.rx","expressionPlan":{"source":"shape.rx","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"rx"},"dependencies":["shape.rx"]}}],"children":[],"flow":{"kind":"if","test":"shape.tag = 'rect'","testPlan":{"source":"shape.tag = 'rect'","ast":{"kind":"binary","op":"=","left":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"tag"},"right":{"kind":"literal","value":"rect"}},"dependencies":["shape.tag"]}}},{"kind":"element","name":"line","attributes":[{"kind":"attribute","name":"x1","expression":"shape.x1","expressionPlan":{"source":"shape.x1","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"x1"},"dependencies":["shape.x1"]}},{"kind":"attribute","name":"x2","expression":"shape.x2","expressionPlan":{"source":"shape.x2","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"x2"},"dependencies":["shape.x2"]}},{"kind":"attribute","name":"y1","expression":"shape.y1","expressionPlan":{"source":"shape.y1","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"y1"},"dependencies":["shape.y1"]}},{"kind":"attribute","name":"y2","expression":"shape.y2","expressionPlan":{"source":"shape.y2","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"y2"},"dependencies":["shape.y2"]}}],"children":[],"flow":{"kind":"if","test":"shape.tag = 'line'","testPlan":{"source":"shape.tag = 'line'","ast":{"kind":"binary","op":"=","left":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"tag"},"right":{"kind":"literal","value":"line"}},"dependencies":["shape.tag"]}}}],"flow":{"kind":"each","item":"shape","list":"shapes","listPlan":{"source":"shapes","ast":{"kind":"id","name":"shapes"},"dependencies":["shapes"]}}}]}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-icon-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-stroke-width {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the svg reads the stroke from the root. A Looma component that\n sizes the icons it renders sets --_ui-default-icon-*, which the icon's own hooks override. */\n --_ui-icon-stroke-width: var(--ui-icon-stroke-width, var(--_ui-default-icon-stroke-width));\n\n display: inline-flex;\n flex: none;\n inline-size: var(--ui-icon-size, var(--_ui-default-icon-size, 1em));\n block-size: var(--ui-icon-size, var(--_ui-default-icon-size, 1em));\n }\n\n svg {\n inline-size: 100%;\n block-size: 100%;\n stroke-width: var(--_ui-icon-stroke-width, 2);\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"shapes","type":"list(object({ tag: path | circle | rect | line, d?: string, cx?: string, cy?: string, r?: string, x?: string, y?: string, width?: string, height?: string, rx?: string, x1?: string, x2?: string, y1?: string, y2?: string }))","expression":{"source":"[]","ast":{"kind":"array","items":[]},"dependencies":[]}}],"slots":[],"root":{"kind":"native","element":"span","choices":["span"]},"controller":"./components/ui-icon/ui-icon.js"},{"source":{"file":"./components/ui-input-group/ui-input-group.html"},"contract":{"version":1,"name":"UiInputGroup","tag":"ui-input-group","nativeElement":"div","props":{"disabled":{"type":"boolean","required":false,"target":{"attribute":"disabled"},"description":"Fades the group's framing to match a disabled input inside it. Disable the input itself too.","default":false}}},"template":{"kind":"element","name":"div","attributes":[],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"affix"}],"children":[{"kind":"slot","fallback":[],"name":"prefix"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"field"}],"children":[{"kind":"slot"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"affix"}],"children":[{"kind":"slot","fallback":[],"name":"suffix"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"action"}],"children":[{"kind":"slot","fallback":[],"name":"action"}]}]},"css":"/* An input with fixed text before or after it, such as a domain after a site's name\n (\"acme\" + \".example.com\") or slashes around a path. The group draws the field's border and\n focus ring around the input and its affixes together; the input inside drops its own through\n its custom properties, so it is still the one ui-input, with its form behaviour intact. The\n affixes are plain text beside the input, so name the input with a label that says what the\n whole value is. The action slot takes one button at the end, inside the border, for the one\n thing the field is for (\"Continue\" after a site's address), so it reads as the field's action\n and not the form's. */\n :host {\n /* The group's own border and height stand for the input's, so the group is a lone Input's height.\n Hooks do not inherit, so these are defaults for the input; its own hooks still win. */\n --_ui-default-input-border-width: 0;\n --_ui-default-input-min-block-size: 0;\n --_ui-default-input-border: transparent;\n --_ui-default-input-border-hover: transparent;\n --_ui-default-input-focus-border: transparent;\n --_ui-default-input-invalid-border: transparent;\n --_ui-default-input-invalid-focus-shadow: none;\n --_ui-default-input-shadow: none;\n --_ui-default-input-focus-shadow: none;\n --_ui-default-input-focus-outline: none;\n --_ui-default-input-radius: 0;\n --_ui-default-input-surface: transparent;\n\n display: flex;\n align-items: stretch;\n box-sizing: border-box;\n inline-size: 100%;\n min-inline-size: 0;\n min-block-size: var(--ui-control-size-md);\n /* The frame reads the shared control tokens with a lone Input's fallbacks, so the two match. */\n border: 1px solid var(--ui-control-border, var(--ui-border-strong));\n border-radius: var(--ui-radius-md);\n background: var(--ui-control-surface, var(--ui-surface-elevated));\n box-shadow: var(--ui-control-inset);\n overflow: hidden;\n /* A press anywhere in the frame focuses the input. */\n cursor: text;\n transition: border-color var(--ui-motion-fast) var(--ui-motion-ease), box-shadow var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n :host:hover:not(:has(input:focus, input:disabled)) {\n border-color: var(--ui-control-border-hover, var(--ui-text-secondary));\n }\n\n /* The ring shows when the field's input would show its own: when it is focus-visible, which a\n text input is for a pointer as well as a keyboard. A focused action button draws its own. */\n :host:has(.field input:focus-visible) {\n border-color: var(--ui-control-focus, var(--ui-accent-solid));\n box-shadow:\n var(--ui-control-inset),\n var(--ui-control-focus-halo-shadow);\n }\n\n :host:has([aria-invalid=\"true\"], :user-invalid) {\n border-color: var(--ui-danger-solid);\n }\n\n :host:has(input:is([aria-invalid=\"true\"], :user-invalid):focus-visible) {\n box-shadow:\n var(--ui-control-inset),\n 0 0 0 3px color-mix(in srgb, var(--ui-danger-solid) 22%, transparent);\n }\n\n /* Forced colors drop box shadows, so the focus ring becomes an outline. */\n @media (forced-colors: active) {\n :host:has(input:focus-visible) {\n outline: 2px solid Highlight;\n outline-offset: 1px;\n }\n }\n\n :host-state([disabled]),\n :host:has(input:disabled) {\n background: var(--ui-control-surface-disabled, var(--ui-surface-muted));\n box-shadow: none;\n cursor: not-allowed;\n }\n\n .field {\n display: flex;\n flex: 1;\n min-inline-size: 0;\n }\n\n .affix {\n display: inline-flex;\n flex: none;\n align-items: center;\n padding-inline: var(--ui-space-2);\n color: var(--ui-text-secondary);\n font-family: var(--ui-font-family-mono);\n font-size: var(--ui-font-size-sm);\n white-space: nowrap;\n }\n\n /* Centred rather than padded above and below: the group is exactly a lone Input's height, so a\n small button sits inside it with the difference split evenly, and the field keeps its height. */\n .action {\n display: flex;\n flex: none;\n align-items: center;\n padding-inline: var(--ui-space-1);\n }\n\n .affix:empty,\n .action:empty {\n display: none;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true,"name":"prefix"},{"dynamic":false,"required":true},{"dynamic":false,"required":true,"name":"suffix"},{"dynamic":false,"required":true,"name":"action"}],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-input-group/ui-input-group.js"},{"source":{"file":"./components/ui-input/ui-input.html"},"contract":{"version":1,"name":"UiInput","tag":"ui-input","nativeElement":"input","props":{"disabled":{"type":"boolean","required":false,"target":{"attribute":"disabled"},"description":"Prevents editing and form submission.","default":false},"invalid":{"type":"boolean","required":false,"target":{"attribute":"aria-invalid"},"description":"Exposes invalid state to assistive technology and styling.","default":false},"readonly":{"type":"boolean","required":false,"target":{"attribute":"readonly"},"description":"Allows selection without allowing edits.","default":false},"required":{"type":"boolean","required":false,"target":{"attribute":"required"},"description":"Marks the control as required for form validation.","default":false},"value":{"type":"string","required":false,"target":{"attribute":"value"},"description":"The input's text. Setting or changing it replaces the live text; between changes the user's typing stands, so follow input events to keep it in step. It is\n also the input's default, so a form reset returns to it."}}},"template":{"kind":"element","name":"input","attributes":[{"kind":"attribute","name":"value","expression":"value","expressionPlan":{"source":"value","ast":{"kind":"id","name":"value"},"dependencies":["value"]}},{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}},{"kind":"attribute","name":"readonly","expression":"readonly","expressionPlan":{"source":"readonly","ast":{"kind":"id","name":"readonly"},"dependencies":["readonly"]}},{"kind":"attribute","name":"required","expression":"required","expressionPlan":{"source":"required","ast":{"kind":"id","name":"required"},"dependencies":["required"]}},{"kind":"attribute","name":"aria-invalid","expression":"invalid","expressionPlan":{"source":"invalid","ast":{"kind":"id","name":"invalid"},"dependencies":["invalid"]}}],"children":[]},"css":"/* This component's hooks style the element they are set on, and never a nested one. An Input\n Group sets --_ui-default-input-* for the input inside it, below the input's own hooks. */\n @property --ui-input-border {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-input-border-hover {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-input-border-width {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-input-focus-border {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-input-focus-outline {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-input-focus-shadow {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-input-invalid-border {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-input-invalid-focus-shadow {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-input-min-block-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-input-radius {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-input-shadow {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-input-surface {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n box-sizing: border-box;\n display: inline-block;\n inline-size: 100%;\n min-inline-size: 0;\n min-block-size: var(--ui-input-min-block-size, var(--_ui-default-input-min-block-size, var(--ui-control-size-md)));\n margin: 0;\n padding: var(--ui-space-2) var(--ui-space-3);\n appearance: none;\n border: var(--ui-input-border-width, var(--_ui-default-input-border-width, 1px)) solid\n var(--ui-input-border, var(--_ui-default-input-border, var(--ui-control-border, var(--ui-border-strong))));\n border-radius: var(--ui-input-radius, var(--_ui-default-input-radius, var(--ui-radius-md)));\n background: var(--ui-input-surface, var(--_ui-default-input-surface, var(--ui-control-surface, var(--ui-surface-elevated))));\n color: var(--ui-text-primary);\n font: inherit;\n line-height: var(--ui-line-height-md);\n box-shadow: var(--ui-input-shadow, var(--_ui-default-input-shadow, var(--ui-control-inset)));\n transition:\n border-color var(--ui-motion-fast) var(--ui-motion-ease),\n box-shadow var(--ui-motion-fast) var(--ui-motion-ease),\n background-color var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n /* Tabbing into a field selects its text; tint that selection softly instead of the page highlight. */\n :host::selection {\n background: color-mix(in srgb, var(--ui-accent-solid) 20%, transparent);\n color: inherit;\n }\n\n :host::placeholder {\n color: var(--ui-control-placeholder, var(--ui-text-secondary));\n opacity: 1;\n }\n\n :host:hover:not(:focus):not(:disabled) {\n border-color: var(--ui-input-border-hover, var(--_ui-default-input-border-hover, var(--ui-control-border-hover, var(--ui-text-secondary))));\n }\n\n :host:focus-visible {\n border-color: var(--ui-input-focus-border, var(--_ui-default-input-focus-border, var(--ui-control-focus, var(--ui-accent-solid))));\n outline: none;\n box-shadow: var(--ui-input-focus-shadow, var(--_ui-default-input-focus-shadow, var(--ui-control-inset), var(--ui-control-focus-halo-shadow)));\n }\n\n /* The app's invalid flag, or the browser's own verdict once the user has left an invalid field. */\n :host[aria-invalid=\"true\"],\n :host:user-invalid {\n border-color: var(--ui-input-invalid-border, var(--_ui-default-input-invalid-border, var(--ui-danger-solid)));\n }\n\n :host:is([aria-invalid=\"true\"], :user-invalid):focus-visible {\n box-shadow: var(\n --ui-input-invalid-focus-shadow,\n var(\n --_ui-default-input-invalid-focus-shadow,\n var(--ui-control-inset),\n 0 0 0 3px color-mix(in srgb, var(--ui-danger-solid) 22%, transparent)\n )\n );\n }\n\n :host:disabled {\n background: var(--ui-control-surface-disabled, var(--ui-surface-muted));\n color: var(--ui-disabled-text);\n box-shadow: none;\n cursor: not-allowed;\n }\n\n /* Forced colors drop box shadows, so the focus ring becomes an outline. */\n @media (forced-colors: active) {\n :host:focus-visible {\n outline: var(--ui-input-focus-outline, var(--_ui-default-input-focus-outline, 2px solid Highlight));\n outline-offset: 1px;\n }\n }\n\n /* No text-box-trim here: trimming a native input's line box below its line height lets the text\n * scroll vertically inside the field. Native inputs already center their single line. */\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[],"root":{"kind":"native","element":"input","choices":["input"]},"controller":"./components/ui-input/ui-input.js"},{"source":{"file":"./components/ui-list-item/ui-list-item.html"},"contract":{"version":1,"name":"UiListItem","tag":"ui-list-item","nativeElement":"li","props":{"current":{"type":"boolean","required":false,"target":{"attribute":"aria-current"},"description":"Marks the item as the current one, such as the site you are in: it takes the selected surface and aria-current=\"true\", which assistive technology\n announces. Set it on one item at a time.","default":false},"variant":{"type":{"enum":["row","card"]},"required":false,"target":{"attribute":"variant"},"description":"How the item is drawn. A row is flat and takes a hover surface when it is a link, for items read down a list. A card sits on a raised, bordered surface,\n for items set in a grid (a List with layout=\"grid\"). Both have the same parts: leading, title, description, and trailing.","default":"row"}}},"template":{"kind":"element","name":"li","attributes":[{"kind":"attribute","name":"aria-current","expression":"current","expressionPlan":{"source":"current","ast":{"kind":"id","name":"current"},"dependencies":["current"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"leading"}],"children":[{"kind":"slot","fallback":[],"name":"leading"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"content"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"title"}],"children":[{"kind":"slot"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"description"}],"children":[{"kind":"slot","fallback":[],"name":"description"}]}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"trailing"}],"children":[{"kind":"slot","fallback":[],"name":"trailing"}]}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-list-item-gap {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-list-item-icon-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-list-item-padding-block {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-list-item-padding-inline {\n syntax: \"*\";\n inherits: false;\n }\n\n /* One entry in a list: something to recognise (leading, usually an icon), its name (the default\n slot), one line about it (description), and what it offers (trailing, such as a button or a\n badge). The title and description are one line each and end in an ellipsis, so every item in a\n list has the same height.\n\n A link in the title is the whole item: its hit area stretches over the item, so the icon and the\n padding follow it too, and the item takes the link's focus ring. The link stays a real link, so\n a router, a modified click, and \"open in new tab\" all work. Trailing controls sit above it and\n stay their own. */\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-list-item-icon-size: var(--ui-list-item-icon-size);\n\n position: relative;\n box-sizing: border-box;\n display: flex;\n align-items: center;\n gap: var(--ui-list-item-gap, var(--ui-space-3));\n min-inline-size: 0;\n min-block-size: var(--_ui-list-item-min-size, var(--ui-control-size, 2.5rem));\n padding-block: var(--ui-list-item-padding-block, var(--_ui-list-item-padding-block, var(--ui-space-2)));\n padding-inline: var(--ui-list-item-padding-inline, var(--_ui-list-item-padding-inline, var(--ui-space-3)));\n border-radius: var(--ui-radius-md);\n color: var(--ui-text-primary);\n transition: background-color var(--ui-motion-fast) var(--ui-motion-ease), border-color var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n :host-state([variant=\"card\"]) {\n padding-block: var(--ui-list-item-padding-block, var(--ui-space-3));\n padding-inline: var(--ui-list-item-padding-inline, var(--ui-space-4));\n border: 1px solid var(--ui-border-default);\n border-radius: var(--ui-radius-lg);\n background: var(--ui-surface-raised);\n }\n\n :host:has(.title a[href]:hover) {\n background: var(--ui-surface-hover);\n }\n\n :host-state([variant=\"card\"]):has(.title a[href]:hover) {\n border-color: var(--ui-border-strong);\n }\n\n :host-state([current]) {\n background: var(--ui-surface-hover);\n }\n\n :host:has(.title a[href]:focus-visible) {\n box-shadow: 0 0 0 2px var(--ui-focus-ring);\n }\n\n .leading,\n .trailing {\n display: inline-flex;\n flex: none;\n align-items: center;\n gap: var(--ui-space-2);\n }\n\n .leading {\n color: var(--ui-text-muted);\n font-size: var(--_ui-list-item-icon-size, var(--ui-font-size-lg));\n }\n\n /* Trailing controls take their own clicks, above the title link's stretched hit area. */\n .trailing {\n position: relative;\n z-index: 1;\n color: var(--ui-text-muted);\n font-size: var(--ui-font-size-sm);\n }\n\n .content {\n display: flex;\n flex: 1;\n flex-direction: column;\n gap: var(--ui-space-0-5, 2px);\n min-inline-size: 0;\n }\n\n .title,\n .description {\n display: block;\n min-inline-size: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .title {\n font-size: var(--ui-font-size-md);\n font-weight: var(--_ui-list-item-title-weight, var(--ui-font-medium));\n line-height: var(--ui-line-height-tight);\n }\n\n .description {\n color: var(--ui-text-muted);\n font-size: var(--ui-font-size-sm);\n line-height: var(--ui-line-height-tight);\n }\n\n .title > :slotted(a) {\n color: inherit;\n text-decoration: none;\n }\n\n .title > :slotted(a:focus-visible) {\n outline: none;\n box-shadow: none;\n }\n\n .title > :slotted(a[href])::after {\n position: absolute;\n inset: 0;\n border-radius: inherit;\n content: \"\";\n }\n\n /* An unused region takes no space. */\n .leading:empty,\n .description:empty,\n .trailing:empty {\n display: none;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true,"name":"leading"},{"dynamic":false,"required":true},{"dynamic":false,"required":true,"name":"description"},{"dynamic":false,"required":true,"name":"trailing"}],"root":{"kind":"native","element":"li","choices":["li"]}},{"source":{"file":"./components/ui-list/ui-list.html"},"contract":{"version":1,"name":"UiList","tag":"ui-list","nativeElement":"ul","props":{"density":{"type":{"enum":["comfortable","compact"]},"required":false,"target":{"attribute":"density"},"description":"How much room each item takes. comfortable is a full row, easy to point at, for lists of things to open; compact sets items close together with no row\n padding, for a short list of facts inside other content, such as the features a plan includes.","default":"comfortable"},"layout":{"type":{"enum":["rows","grid"]},"required":false,"target":{"attribute":"layout"},"description":"How the items are laid out. Rows stack the items one per line, for a list read top to bottom. Grid sets them in as many columns as fit, each at least\n --ui-list-min-item-width (14rem) wide, for card items such as pinned or featured entries.","default":"rows"}}},"template":{"kind":"element","name":"ul","attributes":[{"kind":"literal","name":"role","value":"list"}],"children":[{"kind":"slot"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-list-gap {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-list-min-item-width {\n syntax: \"*\";\n inherits: false;\n }\n\n /* A list of items (ui-list-item). It owns the spacing between them, so a view never sets it. The\n explicit list role keeps the list announced as one: some browsers drop it from a list with no\n markers. */\n :host {\n display: flex;\n flex-direction: column;\n gap: var(--ui-list-gap, var(--ui-space-1));\n min-inline-size: 0;\n margin: 0;\n padding: 0;\n list-style: none;\n }\n\n /* Compact passes its size to the items through private properties, which cross into each item. */\n :host-state([density=\"compact\"]) {\n --_ui-list-item-min-size: 0;\n --_ui-list-item-padding-block: 0;\n --_ui-list-item-padding-inline: 0;\n --_ui-list-item-title-weight: var(--ui-font-normal);\n gap: var(--ui-list-gap, var(--ui-space-2));\n }\n\n :host-state([layout=\"grid\"]) {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(min(100%, var(--ui-list-min-item-width, 14rem)), 1fr));\n gap: var(--ui-list-gap, var(--ui-space-3));\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"ul","choices":["ul"]}},{"source":{"file":"./components/ui-menu-item/ui-menu-item.html"},"contract":{"version":1,"name":"UiMenuItem","tag":"ui-menu-item","nativeElement":"div","props":{"disabled":{"type":"boolean","required":false,"target":{"attribute":"aria-disabled"},"description":"Makes the item unavailable: it is faded, skipped by the arrow keys, and choosing it does nothing. It stays visible and is announced as disabled.","default":false},"value":{"type":"string","required":false,"target":{"attribute":"data-value"},"description":"The value the enclosing menu reports in its select event when this item is chosen. Give each item a distinct value so one handler can tell them\n apart.","default":""}}},"template":{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"role","value":"menuitem"},{"kind":"literal","name":"tabindex","value":"-1"},{"kind":"attribute","name":"aria-disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}},{"kind":"attribute","name":"data-value","expression":"value","expressionPlan":{"source":"value","ast":{"kind":"id","name":"value"},"dependencies":["value"]}}],"children":[{"kind":"slot"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-menu-item-font-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-menu-item-hover-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-menu-item-min-block-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-menu-item-padding-block {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-menu-item-padding-inline {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-menu-item-radius {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n display: block;\n box-sizing: border-box;\n width: 100%;\n padding: var(--ui-menu-item-padding-block, var(--_ui-default-menu-item-padding-block, var(--ui-space-2)))\n var(--ui-menu-item-padding-inline, var(--_ui-default-menu-item-padding-inline, var(--ui-space-3)));\n text-align: left;\n border-radius: var(--ui-menu-item-radius, var(--_ui-default-menu-item-radius, var(--ui-radius-md)));\n color: var(--ui-text-primary);\n font-size: var(--ui-menu-item-font-size, var(--_ui-default-menu-item-font-size, var(--ui-font-size-md)));\n font-weight: var(--ui-font-medium);\n cursor: pointer;\n outline: none;\n transition: background-color var(--ui-motion-fast) var(--ui-motion-ease), color var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n /* Centre the glyphs, not the line box: a label without descenders otherwise reads high. */\n /* Centre the glyphs, not the line box: a label without descenders otherwise reads high.\n * Trimming applies to block containers, so the box is a block with centred content. */\n @supports (text-box-trim: trim-both) {\n :host {\n display: block;\n min-block-size: var(--ui-menu-item-min-block-size, var(--ui-control-size-md, 2.5rem));\n align-content: center;\n text-box-trim: trim-both;\n text-box-edge: cap alphabetic;\n }\n }\n\n :host:is(:hover, :focus-visible):not([aria-disabled=\"true\"]) {\n background: var(--ui-menu-item-hover-surface, var(--ui-surface-subtle));\n }\n\n :host[aria-disabled=\"true\"] {\n opacity: 0.6;\n cursor: not-allowed;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]}},{"source":{"file":"./components/ui-menu/ui-menu.html"},"contract":{"version":1,"name":"UiMenu","tag":"ui-menu","nativeElement":"div","props":{"density":{"type":{"enum":["comfortable","compact"]},"required":false,"target":{"attribute":"density"},"description":"Compact trades padding and type size for rows that fit more on screen.","default":"comfortable"},"for":{"type":"string","required":false,"target":{"attribute":"for"},"description":"ID of the control that toggles and anchors the menu.","default":""},"open":{"type":"boolean","required":false,"target":{"attribute":"open"},"description":"Whether the menu is open initially or when set externally.","default":false},"placement":{"type":"string","required":false,"target":{"attribute":"placement"},"description":"Positions an associated menu relative to its trigger.","default":"bottom-start"}}},"template":{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"role","value":"menu"},{"kind":"literal","name":"aria-orientation","value":"vertical"}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"surface"}],"children":[{"kind":"slot"}]}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-menu-viewport-gap {\n syntax: \"*\";\n inherits: false;\n }\n\n /* Compact sets its items' defaults, so nothing has to rescale a global; an item's own hooks\n still win. */\n :host-state([density=\"compact\"]) {\n --_ui-default-menu-item-padding-block: var(--ui-space-1);\n --_ui-default-menu-item-padding-inline: var(--ui-space-2);\n --_ui-default-menu-item-font-size: var(--ui-font-size-sm);\n --_ui-default-menu-item-radius: var(--ui-radius-sm);\n padding: var(--ui-space-1);\n gap: 0;\n }\n\n :host {\n /* A menu nested in a compact one starts again from its own density. */\n --_ui-default-menu-item-padding-block: initial;\n --_ui-default-menu-item-padding-inline: initial;\n --_ui-default-menu-item-font-size: initial;\n --_ui-default-menu-item-radius: initial;\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n inline-size: max-content;\n min-inline-size: min(12rem, calc(100vw - var(--ui-menu-viewport-gap, var(--ui-space-2)) * 2));\n max-inline-size: calc(100vw - var(--ui-menu-viewport-gap, var(--ui-space-2)) * 2);\n padding: 0;\n border: 0;\n outline: 0;\n border-radius: 0;\n background: transparent;\n box-shadow: none;\n overflow: visible;\n }\n\n .surface {\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n max-inline-size: inherit;\n padding: var(--ui-space-1);\n background: var(--ui-surface-elevated);\n border: 1px solid var(--ui-border-default);\n border-radius: var(--ui-radius-lg);\n box-shadow: var(--ui-elevation-overlay, var(--ui-shadow-lg));\n max-block-size: inherit;\n overflow: auto;\n }\n\n :host:not(:host-state([internalOpen])) {\n display: none;\n }\n\n :host[popover] {\n position: fixed;\n inset: auto;\n margin: 0;\n overflow: visible;\n max-block-size: calc(100dvh - var(--ui-menu-viewport-gap, var(--ui-space-2)) * 2);\n opacity: 0;\n transform: translateY(-4px) scale(0.99);\n transition:\n opacity var(--ui-motion-fast) var(--ui-motion-ease),\n transform var(--ui-motion-fast) var(--ui-motion-ease),\n display var(--ui-motion-fast) allow-discrete,\n overlay var(--ui-motion-fast) allow-discrete;\n }\n\n :host[popover]:popover-open {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n\n @starting-style {\n :host[popover]:popover-open {\n opacity: 0;\n transform: translateY(-4px) scale(0.99);\n }\n }\n\n :host[hidden] {\n display: none;\n }\n\n @media (prefers-reduced-motion: reduce) {\n :host[popover] {\n transition: none;\n }\n }","declarations":[{"kind":"state","name":"internalOpen","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"event","name":"select","type":"object({ value: string, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"open","type":"object({ open: boolean, reason: action | programmatic, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"close","type":"object({ open: boolean, reason: action | programmatic | light-dismiss | escape, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false}],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-menu/ui-menu.js"},{"source":{"file":"./components/ui-nav-item/ui-nav-item.html"},"contract":{"version":1,"name":"UiNavItem","tag":"ui-nav-item","nativeElement":"button","props":{"as":{"type":{"enum":["button","a"]},"required":false,"target":{"attribute":"as"},"description":"The native element the item renders: a button, or a link (a) that navigates to href.","default":"button"},"current":{"type":{"kind":"union","members":[{"kind":"terminal","name":"boolean"},{"kind":"keyword","value":"page"},{"kind":"keyword","value":"step"},{"kind":"keyword","value":"location"}]},"required":false,"target":{"attribute":"current"},"description":"Marks the item as where you are: it takes the selected surface, a stronger label, and a bar on its start edge, and states aria-current, which assistive\n technology announces. true means the current page (aria-current=\"page\"); step marks the current step of a process, and location the current place in a\n set, such as a section of a record. Set it on one item at a time.","default":false},"href":{"type":"string","required":false,"target":{"attribute":"href"},"description":"The link's destination. Pair it with as=\"a\" so the item renders as a real link: a router, a modified click, and \"open in new tab\" all work. Without it the\n item is a button, for switching views inside the app."},"rel":{"type":"string","required":false,"target":{"attribute":"rel"},"description":"The link's relationship to its destination, as on a native link. Only meaningful with as=\"a\"."},"target":{"type":"string","required":false,"target":{"attribute":"target"},"description":"Where a link opens, as on a native link. Only meaningful with as=\"a\"."}}},"template":{"kind":"element","name":"template","attributes":[],"children":[{"kind":"element","name":"a","attributes":[{"kind":"attribute","name":"href","expression":"href","expressionPlan":{"source":"href","ast":{"kind":"id","name":"href"},"dependencies":["href"]}},{"kind":"attribute","name":"target","expression":"target","expressionPlan":{"source":"target","ast":{"kind":"id","name":"target"},"dependencies":["target"]}},{"kind":"attribute","name":"rel","expression":"rel","expressionPlan":{"source":"rel","ast":{"kind":"id","name":"rel"},"dependencies":["rel"]}},{"kind":"attribute","name":"aria-current","expression":"{ true: 'page', false: null, page: 'page', step: 'step', location: 'location' }[format('%s', current)]","expressionPlan":{"source":"{ true: 'page', false: null, page: 'page', step: 'step', location: 'location' }[format('%s', current)]","ast":{"kind":"index","object":{"kind":"object","pairs":[{"key":"true","value":{"kind":"literal","value":"page"}},{"key":"false","value":{"kind":"literal","value":null}},{"key":"page","value":{"kind":"literal","value":"page"}},{"key":"step","value":{"kind":"literal","value":"step"}},{"key":"location","value":{"kind":"literal","value":"location"}}]},"index":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s"},{"kind":"id","name":"current"}]}},"dependencies":["current"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"indicator"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"leading"}],"children":[{"kind":"slot","fallback":[],"name":"leading"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"content"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"label"}],"children":[{"kind":"slot"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"description"}],"children":[{"kind":"slot","fallback":[],"name":"description"}]}]}],"flow":{"kind":"when","test":"as = 'a'","testPlan":{"source":"as = 'a'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"a"}},"dependencies":["as"]}}},{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"attribute","name":"aria-current","expression":"{ true: 'page', false: null, page: 'page', step: 'step', location: 'location' }[format('%s', current)]","expressionPlan":{"source":"{ true: 'page', false: null, page: 'page', step: 'step', location: 'location' }[format('%s', current)]","ast":{"kind":"index","object":{"kind":"object","pairs":[{"key":"true","value":{"kind":"literal","value":"page"}},{"key":"false","value":{"kind":"literal","value":null}},{"key":"page","value":{"kind":"literal","value":"page"}},{"key":"step","value":{"kind":"literal","value":"step"}},{"key":"location","value":{"kind":"literal","value":"location"}}]},"index":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s"},{"kind":"id","name":"current"}]}},"dependencies":["current"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"indicator"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"leading"}],"children":[{"kind":"slot","fallback":[],"name":"leading"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"content"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"label"}],"children":[{"kind":"slot"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"description"}],"children":[{"kind":"slot","fallback":[],"name":"description"}]}]}],"flow":{"kind":"else"}}],"flow":{"kind":"match"}},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-nav-item-current-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-nav-item-indicator-color {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-nav-item-indicator-width {\n syntax: \"*\";\n inherits: false;\n }\n\n /* One destination in a side or rail navigation: an icon to find it by (leading), its name (the\n default slot), and an optional line under it (description), such as the record a section\n belongs to. Label and description are one line each and end in an ellipsis, so every item in a\n navigation has the same height and the rail never grows sideways. */\n :host {\n --_indicator-width: var(--ui-nav-item-indicator-width, 3px);\n --_indicator-color: var(--ui-nav-item-indicator-color, var(--ui-accent));\n position: relative;\n box-sizing: border-box;\n display: flex;\n align-items: center;\n gap: var(--ui-space-3);\n inline-size: 100%;\n min-inline-size: 0;\n min-block-size: var(--ui-control-size, 2.5rem);\n margin: 0;\n padding-block: var(--ui-space-2);\n padding-inline: var(--ui-space-3);\n border: 0;\n border-radius: var(--ui-radius-md);\n background: transparent;\n color: var(--ui-text-secondary);\n font: inherit;\n font-weight: var(--ui-font-medium);\n text-align: start;\n text-decoration: none;\n cursor: pointer;\n appearance: none;\n transition: background-color var(--ui-motion-fast) var(--ui-motion-ease), color var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n :host:hover:not([aria-current]) {\n background: var(--ui-surface-hover);\n color: var(--ui-text-primary);\n }\n\n /* The ring is an outline, drawn inside the item: forced colors keep an outline where they drop a\n box shadow, and a scrolling rail cannot clip a ring that stays within the item. */\n :host:focus-visible {\n outline: 2px solid var(--ui-focus-ring);\n outline-offset: -2px;\n }\n\n :host[aria-current] {\n background: var(--ui-nav-item-current-surface, var(--ui-accent-soft));\n color: var(--ui-accent-subtle-text, var(--ui-text-primary));\n font-weight: var(--ui-font-semibold);\n }\n\n /* The bar on the start edge is a border, not a fill: forced colors replace backgrounds but keep a\n border, so the current item stays marked in high contrast. Logical edges mirror it in a\n right-to-left page. */\n .indicator {\n position: absolute;\n inset-block: var(--ui-space-2);\n inset-inline-start: 0;\n display: none;\n border-inline-start: var(--_indicator-width) solid var(--_indicator-color);\n border-radius: var(--ui-radius-round);\n }\n\n :host[aria-current] .indicator {\n display: block;\n }\n\n @media (forced-colors: active) {\n .indicator {\n border-inline-start-color: Highlight;\n }\n }\n\n .leading {\n display: inline-flex;\n flex: none;\n align-items: center;\n color: inherit;\n font-size: var(--ui-font-size-lg);\n }\n\n .content {\n display: flex;\n flex: 1;\n flex-direction: column;\n gap: var(--ui-space-0-5, 2px);\n min-inline-size: 0;\n }\n\n .label,\n .description {\n display: block;\n min-inline-size: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .label {\n font-size: var(--ui-font-size-md);\n line-height: var(--ui-line-height-tight);\n }\n\n .description {\n color: var(--ui-text-muted);\n font-size: var(--ui-font-size-sm);\n font-weight: var(--ui-font-normal);\n line-height: var(--ui-line-height-tight);\n }\n\n /* An unused region takes no space. */\n .leading:empty,\n .description:empty {\n display: none;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true,"name":"leading"},{"dynamic":false,"required":true},{"dynamic":false,"required":true,"name":"description"}],"root":{"kind":"native","element":"button","choices":["a","button"]}},{"source":{"file":"./components/ui-page-header/ui-page-header.html"},"contract":{"version":1,"name":"UiPageHeader","tag":"ui-page-header","nativeElement":"header","props":{"align":{"type":{"enum":["start","center"]},"required":false,"target":{"attribute":"align"},"description":"Where the header sits. start runs along the page's start edge with actions at the end; center stacks everything centred, for a standalone card such as\n sign-in.","default":"start"}}},"template":{"kind":"element","name":"header","attributes":[],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"leading"}],"children":[{"kind":"slot","fallback":[],"name":"leading"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"copy"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"eyebrow"}],"children":[{"kind":"slot","fallback":[],"name":"eyebrow"}]},{"kind":"element","name":"h1","attributes":[{"kind":"literal","name":"class","value":"title"}],"children":[{"kind":"slot"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"description"}],"children":[{"kind":"slot","fallback":[],"name":"description"}]}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"actions"}],"children":[{"kind":"slot","fallback":[],"name":"actions"}]}]},"css":"/* The top of a view: its title (the page's one h1), with an optional icon or mark before it, a\n short eyebrow above it, a line or two of description under it, and the view's own actions at\n the end. Every view titles itself the same way, at the same size. */\n :host {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--ui-space-3) var(--ui-space-4);\n min-inline-size: 0;\n }\n\n .leading {\n display: inline-flex;\n flex: none;\n align-self: center;\n color: var(--ui-text-muted);\n font-size: var(--ui-font-size-2xl);\n }\n\n .copy {\n display: flex;\n flex: 1 1 16rem;\n flex-direction: column;\n gap: var(--ui-space-1);\n min-inline-size: 0;\n }\n\n .eyebrow {\n color: var(--ui-text-muted);\n font-size: var(--ui-font-size-xs);\n font-weight: var(--ui-font-semibold);\n letter-spacing: 0.06em;\n text-transform: uppercase;\n }\n\n .title {\n margin: 0;\n color: var(--ui-text-primary);\n font-size: var(--ui-font-size-2xl);\n font-weight: var(--ui-font-bold, 700);\n line-height: var(--ui-line-height-tight);\n overflow-wrap: anywhere;\n }\n\n .description {\n color: var(--ui-text-secondary);\n font-size: var(--ui-font-size-md);\n line-height: var(--ui-line-height);\n }\n\n .actions {\n display: inline-flex;\n flex: none;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--ui-space-2);\n }\n\n :host-state([align=\"center\"]) {\n flex-direction: column;\n text-align: center;\n }\n\n :host-state([align=\"center\"]) .copy {\n align-items: center;\n flex-basis: auto;\n }\n\n .leading:empty,\n .eyebrow:empty,\n .description:empty,\n .actions:empty {\n display: none;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true,"name":"leading"},{"dynamic":false,"required":true,"name":"eyebrow"},{"dynamic":false,"required":true},{"dynamic":false,"required":true,"name":"description"},{"dynamic":false,"required":true,"name":"actions"}],"root":{"kind":"native","element":"header","choices":["header"]}},{"source":{"file":"./components/ui-popover/ui-popover.html"},"contract":{"version":1,"name":"UiPopover","tag":"ui-popover","nativeElement":"span","props":{"for":{"type":"string","required":false,"target":{"attribute":"for"},"description":"ID of the control that toggles and anchors the popover.","default":""},"open":{"type":"boolean","required":false,"target":{"attribute":"open"},"description":"Whether the popover is open initially or when set externally.","default":false},"placement":{"type":"string","required":false,"target":{"attribute":"placement"},"description":"Positions the surface relative to its trigger.","default":"bottom-start"}}},"template":{"kind":"element","name":"span","attributes":[],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"surface"}],"children":[{"kind":"slot"}]}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-popover-viewport-gap {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n box-sizing: border-box;\n max-inline-size: min(\n 20rem,\n calc(100vw - var(--ui-popover-viewport-gap, var(--ui-space-2)) * 2)\n );\n max-block-size: calc(100dvh - var(--ui-popover-viewport-gap, var(--ui-space-2)) * 2);\n overflow: visible;\n padding: 0;\n border: 0;\n outline: 0;\n border-radius: 0;\n background: transparent;\n box-shadow: none;\n }\n\n .surface {\n box-sizing: border-box;\n max-inline-size: inherit;\n max-block-size: inherit;\n overflow: auto;\n padding: var(--ui-space-3);\n background: var(--ui-surface-elevated);\n border: 1px solid var(--ui-border-default);\n border-radius: var(--ui-radius-lg);\n box-shadow: var(--ui-elevation-overlay, var(--ui-shadow-lg));\n }\n\n :host:not(:host-state([internalOpen])) {\n display: none;\n }\n\n :host[popover] {\n position: fixed;\n inset: auto;\n margin: 0;\n opacity: 0;\n transform: translateY(-4px) scale(0.99);\n transition:\n opacity var(--ui-motion-fast) var(--ui-motion-ease),\n transform var(--ui-motion-fast) var(--ui-motion-ease),\n display var(--ui-motion-fast) allow-discrete,\n overlay var(--ui-motion-fast) allow-discrete;\n }\n\n :host[popover]:popover-open {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n\n @starting-style {\n :host[popover]:popover-open {\n opacity: 0;\n transform: translateY(-4px) scale(0.99);\n }\n }\n\n :host[hidden] {\n display: none;\n }\n\n @media (prefers-reduced-motion: reduce) {\n :host[popover] {\n transition: none;\n }\n }","declarations":[{"kind":"state","name":"internalOpen","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"event","name":"open","type":"object({ open: boolean, reason: action | programmatic | light-dismiss | escape, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"close","type":"object({ open: boolean, reason: action | programmatic | light-dismiss | escape, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false}],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"span","choices":["span"]},"controller":"./components/ui-popover/ui-popover.js"},{"source":{"file":"./components/ui-radio-group/ui-radio-group.html"},"contract":{"version":1,"name":"UiRadioGroup","tag":"ui-radio-group","nativeElement":"fieldset","props":{"disabled":{"type":"boolean","required":false,"target":{"attribute":"disabled"},"description":"Disables every radio in the group through the native fieldset, so no choice can be made and the group submits nothing with its form. A radio disabled on\n its own stays disabled when the group is enabled.","default":false},"label":{"type":"string","required":false,"target":{"attribute":"label"},"description":"The group's legend, shown above the radios and announced as the group's name. Phrase it as the question the radios answer.","default":"Options"},"name":{"type":"string","required":false,"target":{"attribute":"name"},"description":"The native name given to every radio in the group, under which a form submits the chosen value. Left empty, the group generates a unique name that keeps\n the radios together, so set it when the choice submits with a form.","default":""},"orientation":{"type":{"enum":["horizontal","vertical"]},"required":false,"target":{"attribute":"orientation"},"description":"horizontal lays the radios out in a row; vertical stacks them in a column. The arrow keys move between radios either way.","default":"horizontal"},"required":{"type":"boolean","required":false,"target":{"attribute":"aria-required"},"description":"Makes a choice required, as a required native radio does for its group: the group states aria-required, every radio in it is marked required, and native\n form validation fails until one is checked.","default":false},"value":{"type":"string","required":false,"target":{"attribute":"value"},"description":"The value of the checked radio, initially or when set externally; empty checks none. The user's choice updates it from there and is reported as select and\n change events, and a form reset returns the group to it.","default":""}}},"template":{"kind":"element","name":"fieldset","attributes":[{"kind":"literal","name":"role","value":"radiogroup"},{"kind":"attribute","name":"aria-required","expression":"required","expressionPlan":{"source":"required","ast":{"kind":"id","name":"required"},"dependencies":["required"]}},{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}}],"children":[{"kind":"element","name":"legend","attributes":[],"children":[{"kind":"element","name":"template","attributes":[{"kind":"directive","name":"value","expression":"label","expressionPlan":{"source":"label","ast":{"kind":"id","name":"label"},"dependencies":["label"]}}],"children":[]}]},{"kind":"slot"}]},"css":":host {\n display: inline-flex;\n align-items: center;\n gap: var(--ui-space-2);\n min-inline-size: 0;\n margin: 0;\n padding: 0;\n border: 0;\n }\n\n legend {\n float: inline-start;\n inline-size: 100%;\n margin: 0 0 var(--ui-space-2);\n padding: 0;\n color: var(--ui-text-primary);\n font-weight: var(--ui-font-medium);\n }\n\n legend + * {\n clear: both;\n }\n\n :host-state([orientation=\"vertical\"]) {\n display: inline-grid;\n justify-items: start;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"internalValue","expression":{"source":"''","ast":{"kind":"literal","value":""},"dependencies":[]}},{"kind":"event","name":"select","type":"object({ value: string, previousValue: string, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"change","type":"object({ checked: boolean, value: string, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false}],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"fieldset","choices":["fieldset"]},"controller":"./components/ui-radio-group/ui-radio-group.js"},{"source":{"file":"./components/ui-radio/ui-radio.html"},"contract":{"version":1,"name":"UiRadio","tag":"ui-radio","nativeElement":"label","props":{"checked":{"type":"boolean","required":false,"target":{"attribute":"checked"},"description":"Whether the radio is checked initially or when set externally. A form reset returns it to this. Inside a ui-radio-group the group's value decides\n instead.","default":false},"disabled":{"type":"boolean","required":false,"target":{"attribute":"disabled"},"description":"Disables the native radio, so it cannot be chosen, focused, or reached with the arrow keys.","default":false},"name":{"type":"string","required":false,"target":{"attribute":"name"},"description":"The native name that groups radios: of the radios that share a name, only one can be checked, and the arrow keys move between them. Inside a ui-radio-group\n the group sets the name, so leave this empty there.","default":""},"required":{"type":"boolean","required":false,"target":{"attribute":"required"},"description":"Marks the native radio required, so native form validation fails until a radio with the same name is checked.","default":false},"value":{"type":"string","required":false,"target":{"attribute":"value"},"description":"The value this radio stands for: submitted with a form, reported in its change event, and matched against a ui-radio-group's value to decide which radio is\n checked.","default":"on"}}},"template":{"kind":"element","name":"label","attributes":[],"children":[{"kind":"element","name":"input","attributes":[{"kind":"literal","name":"type","value":"radio"},{"kind":"property","key":"checked","name":"checked","expression":"internalChecked","expressionPlan":{"source":"internalChecked","ast":{"kind":"id","name":"internalChecked"},"dependencies":["internalChecked"]}},{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}},{"kind":"attribute","name":"required","expression":"required","expressionPlan":{"source":"required","ast":{"kind":"id","name":"required"},"dependencies":["required"]}},{"kind":"attribute","name":"value","expression":"value","expressionPlan":{"source":"value","ast":{"kind":"id","name":"value"},"dependencies":["value"]}},{"kind":"attribute","name":"name","expression":"name","expressionPlan":{"source":"name","ast":{"kind":"id","name":"name"},"dependencies":["name"]}}],"children":[],"ref":"input"},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"text"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"label"}],"children":[{"kind":"slot"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"description"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[{"kind":"slot","fallback":[],"name":"description"}],"ref":"description"}]}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-radio-gap {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-radio-size {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-radio-size: var(--ui-radio-size);\n\n display: inline-flex;\n align-items: flex-start;\n gap: var(--ui-radio-gap, var(--ui-space-2));\n max-inline-size: 100%;\n color: var(--ui-text-primary);\n cursor: pointer;\n }\n\n /* The label, and under it an optional line saying what the choice means. */\n .text {\n display: flex;\n flex-direction: column;\n gap: var(--ui-space-1);\n min-inline-size: 0;\n }\n\n .label {\n min-inline-size: 0;\n line-height: var(--ui-line-height-md);\n }\n\n .description {\n color: var(--ui-text-secondary);\n font-size: var(--ui-font-size-sm);\n line-height: var(--ui-line-height);\n }\n\n .description:empty {\n display: none;\n }\n\n input {\n flex: 0 0 auto;\n inline-size: var(--_ui-radio-size, 1.125rem);\n block-size: var(--_ui-radio-size, 1.125rem);\n margin: 0.125em 0 0;\n accent-color: var(--ui-accent-solid);\n cursor: pointer;\n }\n\n input:focus-visible {\n outline: 2px solid var(--ui-focus-ring, var(--ui-accent-solid));\n outline-offset: 2px;\n }\n\n :host-state([disabled]) {\n color: var(--ui-disabled-text);\n cursor: not-allowed;\n }\n :host-state([disabled]) input {\n cursor: not-allowed;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"internalChecked","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"event","name":"change","type":"object({ checked: boolean, value: string, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false}],"slots":[{"dynamic":false,"required":true},{"dynamic":false,"required":true,"name":"description"}],"root":{"kind":"native","element":"label","choices":["label"]},"controller":"./components/ui-radio/ui-radio.js"},{"source":{"file":"./components/ui-reel/ui-reel.html"},"contract":{"version":1,"name":"UiReel","tag":"ui-reel","nativeElement":"div","props":{"gap":{"type":{"enum":["xs","s","m","l","xl"]},"required":false,"target":{"attribute":"gap"},"description":"Space between items, on the spacing scale: xs is 0.5rem, s 0.75rem, m 1rem (also the default), l 1.5rem, and xl 2rem. The --ui-reel-gap custom property,\n set on the reel itself, overrides it; set on an ancestor, it does nothing."},"itemWidth":{"type":{"enum":["sm","md","lg"]},"required":false,"target":{"attribute":"itemwidth"},"description":"A fixed width for every item: sm is 12rem, md is 16rem, and lg is 20rem. Unset, each item keeps its content's width. Items never shrink to fit, so the reel\n scrolls sideways once they overflow."},"snap":{"type":{"enum":["start","center"]},"required":false,"target":{"attribute":"snap"},"description":"Snaps scrolling to items: start comes to rest with an item's start edge at the reel's start, and center with an item centred in the reel. Unset, the reel\n scrolls freely."}}},"template":{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"role","value":"region"},{"kind":"literal","name":"tabindex","value":"0"}],"children":[{"kind":"slot"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-reel-gap {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-reel-item-width {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-reel-item-width: var(--ui-reel-item-width);\n\n --_reel-gap: var(--ui-space-4);\n --_reel-item-width: auto;\n display: flex;\n inline-size: 100%;\n gap: var(--ui-reel-gap, var(--_reel-gap));\n min-inline-size: 0;\n max-inline-size: 100%;\n margin: 0;\n overflow-x: auto;\n overflow-y: hidden;\n overscroll-behavior-inline: contain;\n }\n\n /* Each end that hides items fades: the scroll fade every Looma scroller uses (see ui-scroll-area). */\n :host {\n --_ui-scroll-fade-direction: to right;\n --_ui-scroll-fade-size: var(--ui-scroll-fade-size, 24px);\n mask-image: linear-gradient(\n var(--_ui-scroll-fade-direction),\n transparent,\n #000 var(--_ui-scroll-fade-start),\n #000 calc(100% - var(--_ui-scroll-fade-end)),\n transparent\n );\n animation: ui-scroll-fade-start linear, ui-scroll-fade-start-hold linear, ui-scroll-fade-end-hold linear, ui-scroll-fade-end linear;\n animation-timeline: scroll(self inline);\n animation-range:\n 0 var(--_ui-scroll-fade-size),\n var(--_ui-scroll-fade-size) calc(100% + 1px),\n -1px calc(100% - var(--_ui-scroll-fade-size)),\n calc(100% - var(--_ui-scroll-fade-size)) 100%;\n }\n\n :host:dir(rtl) {\n --_ui-scroll-fade-direction: to left;\n }\n\n :host > :slotted(*) {\n min-inline-size: 0;\n flex: 0 0 var(--_ui-reel-item-width, var(--_reel-item-width));\n }\n\n :host-state([gap=\"xs\"]) {\n --_reel-gap: var(--ui-space-2);\n }\n :host-state([gap=\"s\"]) {\n --_reel-gap: var(--ui-space-3);\n }\n :host-state([gap=\"m\"]) {\n --_reel-gap: var(--ui-space-4);\n }\n :host-state([gap=\"l\"]) {\n --_reel-gap: var(--ui-space-5);\n }\n :host-state([gap=\"xl\"]) {\n --_reel-gap: var(--ui-space-6);\n }\n :host-state([itemWidth=\"sm\"]) {\n --_reel-item-width: 12rem;\n }\n :host-state([itemWidth=\"md\"]) {\n --_reel-item-width: 16rem;\n }\n :host-state([itemWidth=\"lg\"]) {\n --_reel-item-width: 20rem;\n }\n :host-state([snap]) {\n scroll-snap-type: inline mandatory;\n }\n :host-state([snap=\"start\"]) > :slotted(*) {\n scroll-snap-align: start;\n }\n :host-state([snap=\"center\"]) > :slotted(*) {\n scroll-snap-align: center;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]}},{"source":{"file":"./components/ui-scroll-area/ui-scroll-area.html"},"contract":{"version":1,"name":"UiScrollArea","tag":"ui-scroll-area","nativeElement":"div","props":{"orientation":{"type":{"enum":["vertical","horizontal"]},"required":false,"target":{"attribute":"orientation"},"description":"The direction the content scrolls. Vertical scrolls up and down and clips sideways overflow; horizontal scrolls sideways and clips vertical\n overflow.","default":"vertical"}}},"template":{"kind":"element","name":"div","attributes":[],"children":[{"kind":"slot"}]},"css":"/* A region that scrolls when its content outgrows it. Each edge that hides content fades, growing\n in as the content leaves that edge (the scroll fade in tokens.css), so the reader can tell there\n is more; an edge with nothing past it stays crisp, and content that fits shows no fade. The\n fade is a mask, so it blends into whatever is behind the area without knowing its colour. */\n :host {\n display: block;\n box-sizing: border-box;\n min-block-size: 0;\n min-inline-size: 0;\n overflow-x: hidden;\n overflow-y: auto;\n overscroll-behavior: contain;\n --_ui-scroll-fade-direction: to bottom;\n --_ui-scroll-fade-inline: to right;\n --_ui-scroll-fade-size: var(--ui-scroll-fade-size, 24px);\n mask-image: linear-gradient(\n var(--_ui-scroll-fade-direction),\n transparent,\n #000 var(--_ui-scroll-fade-start),\n #000 calc(100% - var(--_ui-scroll-fade-end)),\n transparent\n );\n animation: ui-scroll-fade-start linear, ui-scroll-fade-start-hold linear, ui-scroll-fade-end-hold linear, ui-scroll-fade-end linear;\n animation-timeline: scroll(self block);\n animation-range:\n 0 var(--_ui-scroll-fade-size),\n var(--_ui-scroll-fade-size) calc(100% + 1px),\n -1px calc(100% - var(--_ui-scroll-fade-size)),\n calc(100% - var(--_ui-scroll-fade-size)) 100%;\n }\n\n :host-state([orientation=\"horizontal\"]) {\n overflow-x: auto;\n overflow-y: hidden;\n --_ui-scroll-fade-direction: var(--_ui-scroll-fade-inline);\n animation-timeline: scroll(self inline);\n }\n\n :host:dir(rtl) {\n --_ui-scroll-fade-inline: to left;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]}},{"source":{"file":"./components/ui-search-result-row/ui-search-result-row.html"},"contract":{"version":1,"name":"UiSearchResultRow","tag":"ui-search-result-row","nativeElement":"button","props":{"disabled":{"type":"boolean","required":false,"target":{"attribute":"disabled"},"description":"Disables the row's button, so it cannot be chosen or focused, and fades it to 60% opacity.","default":false},"selected":{"type":"boolean","required":false,"target":{"attribute":"aria-current"},"description":"Marks the row as the current result: it gets the hover surface and aria-current=\"true\", which assistive technology announces as current. Set it on one row\n at a time, such as the result the arrow keys have moved to.","default":false}}},"template":{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}},{"kind":"attribute","name":"aria-current","expression":"selected","expressionPlan":{"source":"selected","ast":{"kind":"id","name":"selected"},"dependencies":["selected"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"leading"}],"children":[{"kind":"slot","fallback":[],"name":"leading"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"content"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"title"}],"children":[{"kind":"slot","fallback":[],"name":"title"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"meta"}],"children":[{"kind":"slot","fallback":[],"name":"meta"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"excerpt"}],"children":[{"kind":"slot","fallback":[],"name":"excerpt"}]}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"trailing"}],"children":[{"kind":"slot","fallback":[],"name":"trailing"}]}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-search-result-row-border {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-search-result-row-gap {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-search-result-row-hover-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-search-result-row-min-height {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-search-result-row-padding-block {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-search-result-row-padding-inline {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-search-result-row-selected-bg {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-search-result-row-surface {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n appearance: none;\n inline-size: 100%;\n min-block-size: var(--ui-search-result-row-min-height, 56px);\n margin: 0;\n padding-block: var(--ui-search-result-row-padding-block, var(--ui-space-3));\n padding-inline: var(--ui-search-result-row-padding-inline, var(--ui-space-4));\n display: flex;\n align-items: flex-start;\n gap: var(--ui-search-result-row-gap, var(--ui-space-3));\n background: var(--ui-search-result-row-surface, transparent);\n border: none;\n border-block-end: 1px solid var(--ui-search-result-row-border, var(--ui-border));\n color: inherit;\n cursor: pointer;\n text-align: left;\n transition: background-color var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n :host:last-child {\n border-block-end: none;\n }\n\n :host:hover:enabled {\n background: var(--ui-search-result-row-hover-surface, color-mix(in srgb, var(--ui-surface) 85%, black 3%));\n }\n\n :host-state([selected]) {\n background: var(\n --ui-search-result-row-selected-bg,\n var(--ui-search-result-row-hover-surface, color-mix(in srgb, var(--ui-surface) 85%, black 3%))\n );\n }\n\n :host:focus-visible {\n outline: 2px solid var(--ui-focus-ring);\n outline-offset: -2px;\n }\n\n :host:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n }\n\n .leading,\n .trailing {\n display: inline-flex;\n align-items: flex-start;\n flex-shrink: 0;\n }\n\n .content {\n min-inline-size: 0;\n flex: 1;\n display: flex;\n flex-direction: column;\n }\n\n .title,\n .meta,\n .excerpt {\n display: block;\n min-inline-size: 0;\n }\n\n /* An unused region takes no space. */\n .leading:empty,\n .meta:empty,\n .excerpt:empty,\n .trailing:empty {\n display: none;\n }\n\n :slotted([slot=\"title\"]),\n :slotted([slot=\"meta\"]),\n :slotted([slot=\"excerpt\"]) {\n display: block;\n margin: 0;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true,"name":"leading"},{"dynamic":false,"required":true,"name":"title"},{"dynamic":false,"required":true,"name":"meta"},{"dynamic":false,"required":true,"name":"excerpt"},{"dynamic":false,"required":true,"name":"trailing"}],"root":{"kind":"native","element":"button","choices":["button"]}},{"source":{"file":"./components/ui-search-shell/ui-search-shell.html"},"contract":{"version":1,"name":"UiSearchShell","tag":"ui-search-shell","nativeElement":"div","props":{"dismissible":{"type":"boolean","required":false,"target":{"attribute":"dismissible"},"description":"Allows Escape and backdrop activation to close the search surface.","default":false},"label":{"type":"string","required":false,"target":{"attribute":"aria-label"},"description":"Provides the native dialog's accessible name.","default":"Search"},"modal":{"type":"boolean","required":false,"target":{"attribute":"modal"},"description":"Makes the rest of the page inert while the search surface is open.","default":false},"open":{"type":"boolean","required":false,"target":{"attribute":"open"},"description":"Shows the search surface.","default":false}}},"template":{"kind":"element","name":"div","attributes":[],"children":[{"kind":"element","name":"dialog","attributes":[{"kind":"attribute","name":"aria-label","expression":"label","expressionPlan":{"source":"label","ast":{"kind":"id","name":"label"},"dependencies":["label"]}}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"panel"}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"search"}],"children":[{"kind":"slot","fallback":[],"name":"search"}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"status"}],"children":[{"kind":"slot","fallback":[],"name":"status"}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"body"}],"children":[{"kind":"slot","fallback":[],"name":"body"}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"footer"}],"children":[{"kind":"slot","fallback":[],"name":"footer"}]}]}],"ref":"dialog"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-search-shell-border {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-search-shell-focus-color {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-search-shell-max-height {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-search-shell-max-width {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-search-shell-padding-top {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-search-shell-radius {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-search-shell-shadow {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-search-shell-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-search-shell-viewport-gap {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-search-shell-z-index {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-search-shell-z-index: var(--ui-search-shell-z-index);\n --_ui-search-shell-padding-top: var(--ui-search-shell-padding-top);\n --_ui-search-shell-viewport-gap: var(--ui-search-shell-viewport-gap);\n --_ui-search-shell-max-width: var(--ui-search-shell-max-width);\n --_ui-search-shell-max-height: var(--ui-search-shell-max-height);\n --_ui-search-shell-surface: var(--ui-search-shell-surface);\n --_ui-search-shell-border: var(--ui-search-shell-border);\n --_ui-search-shell-radius: var(--ui-search-shell-radius);\n --_ui-search-shell-shadow: var(--ui-search-shell-shadow);\n --_ui-search-shell-focus-color: var(--ui-search-shell-focus-color);\n\n display: contents;\n }\n\n dialog {\n position: fixed;\n inset: 0;\n z-index: var(--_ui-search-shell-z-index, 400);\n box-sizing: border-box;\n inline-size: 100%;\n max-inline-size: none;\n block-size: 100%;\n max-block-size: none;\n margin: 0;\n padding: var(--_ui-search-shell-padding-top, 10vh) var(--_ui-search-shell-viewport-gap, var(--ui-space-4))\n var(--_ui-search-shell-viewport-gap, var(--ui-space-4));\n overflow: auto;\n border: 0;\n background: var(--ui-overlay-backdrop);\n color: var(--ui-text-primary);\n }\n\n dialog::backdrop {\n background: var(--ui-overlay-backdrop);\n }\n\n .panel {\n position: relative;\n display: flex;\n flex-direction: column;\n inline-size: min(100%, var(--_ui-search-shell-max-width, 40rem));\n max-block-size: var(--_ui-search-shell-max-height, 80vh);\n margin-inline: auto;\n overflow: hidden;\n background: var(--_ui-search-shell-surface, var(--ui-surface-elevated));\n border: 1px solid var(--_ui-search-shell-border, var(--ui-border-default));\n border-radius: var(--_ui-search-shell-radius, var(--ui-radius-dialog));\n box-shadow: var(--_ui-search-shell-shadow, var(--ui-elevation-dialog, var(--ui-shadow-xl)));\n }\n\n .search {\n padding: var(--ui-space-3);\n border-block-end: 1px solid var(--ui-border-default);\n transition: border-color var(--ui-motion-fast) var(--ui-motion-ease), box-shadow var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n /* The search region shows where typing goes, whatever the author put in it. */\n .search:focus-within {\n border-block-end-color: var(--_ui-search-shell-focus-color, var(--ui-control-focus));\n box-shadow: inset 0 -1px 0 var(--_ui-search-shell-focus-color, var(--ui-control-focus));\n }\n\n :slotted(input[slot=\"search\"]) {\n box-sizing: border-box;\n inline-size: 100%;\n min-block-size: var(--ui-control-min-block-size);\n padding: var(--ui-space-2) var(--ui-space-3);\n border: 1px solid var(--ui-control-border);\n border-radius: var(--ui-radius-md);\n background: var(--ui-control-surface);\n color: var(--ui-text-primary);\n font: inherit;\n box-shadow: var(--ui-shadow-xs);\n }\n\n :slotted(input[slot=\"search\"]:focus-visible) {\n border-color: var(--ui-control-focus);\n outline: 2px solid var(--ui-focus-ring);\n outline-offset: 2px;\n }\n\n .status,\n .footer {\n flex-shrink: 0;\n padding: var(--ui-space-2) var(--ui-space-4);\n color: var(--ui-text-secondary);\n font-size: var(--ui-font-size-sm);\n }\n\n .status {\n border-block-end: 1px solid var(--ui-border-default);\n }\n\n /* Laid out like the dialog's action row: actions right-aligned, spaced as buttons, no fill. */\n .footer {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: flex-end;\n gap: var(--ui-space-2);\n padding: var(--ui-space-3) var(--ui-space-4);\n border-block-start: 1px solid var(--ui-border-default);\n }\n\n .status:empty,\n .footer:empty {\n display: none;\n }\n\n .body {\n flex: 1;\n min-block-size: 0;\n overflow: auto;\n padding: var(--ui-space-2);\n /* Each edge that hides content fades: the scroll fade every Looma scroller uses (see ui-scroll-area). */\n --_ui-scroll-fade-direction: to bottom;\n --_ui-scroll-fade-size: var(--ui-scroll-fade-size, 24px);\n mask-image: linear-gradient(\n var(--_ui-scroll-fade-direction),\n transparent,\n #000 var(--_ui-scroll-fade-start),\n #000 calc(100% - var(--_ui-scroll-fade-end)),\n transparent\n );\n animation: ui-scroll-fade-start linear, ui-scroll-fade-start-hold linear, ui-scroll-fade-end-hold linear, ui-scroll-fade-end linear;\n animation-timeline: scroll(self block);\n animation-range:\n 0 var(--_ui-scroll-fade-size),\n var(--_ui-scroll-fade-size) calc(100% + 1px),\n -1px calc(100% - var(--_ui-scroll-fade-size)),\n calc(100% - var(--_ui-scroll-fade-size)) 100%;\n }\n\n @media (max-width: 47.9375rem) {\n dialog {\n padding: 0;\n }\n\n .panel {\n inline-size: 100%;\n min-block-size: 100dvh;\n max-block-size: none;\n border: 0;\n border-radius: 0;\n }\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"internalOpen","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"event","name":"close","type":"object({ open: boolean, reason: action | programmatic | light-dismiss | escape, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false}],"slots":[{"dynamic":false,"required":true,"name":"search"},{"dynamic":false,"required":true,"name":"status"},{"dynamic":false,"required":true,"name":"body"},{"dynamic":false,"required":true,"name":"footer"}],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-search-shell/ui-search-shell.js"},{"source":{"file":"./components/ui-section/ui-section.html"},"contract":{"version":1,"name":"UiSection","tag":"ui-section","nativeElement":"section","props":{"heading":{"type":"string","required":false,"target":{"attribute":"heading"},"description":"The section's heading, an h2. Leave it empty for a section with no visible heading, and name the section with aria-label.","default":""},"tone":{"type":{"enum":["neutral","danger"]},"required":false,"target":{"attribute":"tone"},"description":"danger marks a section of destructive actions (a danger zone): its heading and a card's border take the danger colour.","default":"neutral"},"variant":{"type":{"enum":["plain","card","divided"]},"required":false,"target":{"attribute":"variant"},"description":"How the section is set apart. plain is a heading and content in the flow of the page; card sits it on a bordered surface, for a settings group; divided\n rules it off from the section before it, for a long form.","default":"plain"}}},"template":{"kind":"element","name":"section","attributes":[],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"head"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"copy"}],"children":[{"kind":"element","name":"h2","attributes":[{"kind":"literal","name":"class","value":"heading"},{"kind":"attribute","name":"hidden","expression":"not heading","expressionPlan":{"source":"not heading","ast":{"kind":"unary","op":"not","operand":{"kind":"id","name":"heading"}},"dependencies":["heading"]}}],"children":[{"kind":"element","name":"template","attributes":[{"kind":"directive","name":"value","expression":"heading","expressionPlan":{"source":"heading","ast":{"kind":"id","name":"heading"},"dependencies":["heading"]}}],"children":[]}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"description"}],"children":[{"kind":"slot","fallback":[],"name":"description"}]}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"actions"}],"children":[{"kind":"slot","fallback":[],"name":"actions"}]}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"body"}],"children":[{"kind":"slot"}]}]},"css":"/* A part of a view: a heading, an optional line under it, actions for the whole section at its\n end, and the content. Sections space themselves out through the Stack around them. */\n :host {\n display: flex;\n flex-direction: column;\n gap: var(--ui-space-4);\n min-inline-size: 0;\n }\n\n :host-state([variant=\"card\"]) {\n padding: var(--ui-space-5);\n border: 1px solid var(--ui-border-default);\n border-radius: var(--ui-radius-lg);\n background: var(--ui-surface-raised);\n }\n\n :host-state([variant=\"divided\"]) {\n padding-block-start: var(--ui-space-6);\n border-block-start: 1px solid var(--ui-border-default);\n }\n\n :host-state([variant=\"card\"][tone=\"danger\"]) {\n border-color: var(--ui-danger);\n }\n\n .head {\n display: flex;\n flex-wrap: wrap;\n align-items: flex-start;\n justify-content: space-between;\n gap: var(--ui-space-2) var(--ui-space-4);\n }\n\n .copy {\n display: flex;\n flex: 1 1 16rem;\n flex-direction: column;\n gap: var(--ui-space-1);\n min-inline-size: 0;\n }\n\n .heading {\n margin: 0;\n color: var(--ui-text-primary);\n font-size: var(--ui-font-size-lg);\n font-weight: var(--ui-font-semibold);\n line-height: var(--ui-line-height-tight);\n }\n\n :host-state([tone=\"danger\"]) .heading {\n color: var(--ui-danger);\n }\n\n .description {\n color: var(--ui-text-secondary);\n font-size: var(--ui-font-size-sm);\n line-height: var(--ui-line-height);\n }\n\n .actions {\n display: inline-flex;\n flex-wrap: wrap;\n gap: var(--ui-space-2);\n }\n\n .body {\n display: flex;\n flex-direction: column;\n gap: var(--ui-space-4);\n min-inline-size: 0;\n }\n\n .description:empty,\n .actions:empty {\n display: none;\n }\n\n .head:has(.heading[hidden]):has(.description:empty):has(.actions:empty) {\n display: none;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true,"name":"description"},{"dynamic":false,"required":true,"name":"actions"},{"dynamic":false,"required":true}],"root":{"kind":"native","element":"section","choices":["section"]}},{"source":{"file":"./components/ui-select/ui-select.html"},"contract":{"version":1,"name":"UiSelect","tag":"ui-select","nativeElement":"select","props":{"disabled":{"type":"boolean","required":false,"target":{"attribute":"disabled"},"description":"Prevents selection and form submission.","default":false},"invalid":{"type":"boolean","required":false,"target":{"attribute":"aria-invalid"},"description":"Exposes invalid state to assistive technology and styling.","default":false},"required":{"type":"boolean","required":false,"target":{"attribute":"required"},"description":"Requires a non-empty option for form validation.","default":false},"value":{"type":"string","required":false,"target":{"attribute":"value"},"description":"The value of the selected option, initially or when set externally. It is also the default, so a form reset returns to it rather than to the first\n option."}}},"template":{"kind":"element","name":"select","attributes":[{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}},{"kind":"attribute","name":"required","expression":"required","expressionPlan":{"source":"required","ast":{"kind":"id","name":"required"},"dependencies":["required"]}},{"kind":"attribute","name":"aria-invalid","expression":"invalid","expressionPlan":{"source":"invalid","ast":{"kind":"id","name":"invalid"},"dependencies":["invalid"]}}],"children":[{"kind":"slot"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-select-focus-shadow {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-select-radius {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-select-shadow {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n box-sizing: border-box;\n display: inline-block;\n inline-size: 100%;\n min-inline-size: 0;\n min-block-size: var(--ui-control-size-md);\n margin: 0;\n padding: var(--ui-space-2) var(--ui-space-3);\n border: 1px solid var(--ui-control-border, var(--ui-border-strong));\n border-radius: var(--ui-select-radius, var(--ui-radius-md));\n background-color: var(--ui-control-surface, var(--ui-surface-elevated));\n color: var(--ui-text-primary);\n color-scheme: light dark;\n font: inherit;\n line-height: var(--ui-line-height-md);\n box-shadow: var(--ui-select-shadow, var(--ui-control-inset));\n transition:\n border-color var(--ui-motion-fast) var(--ui-motion-ease),\n box-shadow var(--ui-motion-fast) var(--ui-motion-ease),\n background-color var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n /* The select draws its own chevron: the native caret cannot be inset or sized consistently.\n * The root stays a native <s-lect>, so the icon is a background image rather than an element. */\n :host {\n appearance: none;\n padding-inline-end: calc(var(--ui-space-3) + 1.5rem);\n background-image: var(\n --ui-select-chevron,\n url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235c5c58' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E\")\n );\n background-repeat: no-repeat;\n background-position: right var(--ui-space-3) center;\n background-size: 1.125rem 1.125rem;\n }\n\n :host:hover:not(:focus):not(:disabled) {\n border-color: var(--ui-control-border-hover, var(--ui-text-secondary));\n }\n\n :host:focus-visible {\n border-color: var(--ui-control-focus, var(--ui-accent-solid));\n outline: none;\n box-shadow: var(--ui-select-focus-shadow, var(--ui-control-inset), var(--ui-control-focus-halo-shadow));\n }\n\n /* The app's invalid flag, or the browser's own verdict once the user has left an invalid field. */\n :host[aria-invalid=\"true\"],\n :host:user-invalid {\n border-color: var(--ui-danger-solid);\n }\n\n :host:is([aria-invalid=\"true\"], :user-invalid):focus-visible {\n box-shadow:\n var(--ui-control-inset),\n 0 0 0 3px color-mix(in srgb, var(--ui-danger-solid) 22%, transparent);\n }\n\n :host:disabled {\n background-color: var(--ui-control-surface-disabled, var(--ui-surface-muted));\n color: var(--ui-disabled-text);\n box-shadow: none;\n cursor: not-allowed;\n }\n\n :host[size]:not([size=\"1\"]) {\n min-block-size: 7rem;\n padding: var(--ui-space-2);\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"select","choices":["select"]},"controller":"./components/ui-select/ui-select.js"},{"source":{"file":"./components/ui-separator/ui-separator.html"},"contract":{"version":1,"name":"UiSeparator","tag":"ui-separator","nativeElement":"hr","props":{"orientation":{"type":{"enum":["horizontal","vertical"]},"required":false,"target":{"attribute":"aria-orientation"},"description":"Whether the separator divides stacked content (horizontal) or inline content (vertical).","default":"horizontal"}}},"template":{"kind":"element","name":"hr","attributes":[{"kind":"attribute","name":"aria-orientation","expression":"orientation","expressionPlan":{"source":"orientation","ast":{"kind":"id","name":"orientation"},"dependencies":["orientation"]}}],"children":[]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-separator-color {\n syntax: \"*\";\n inherits: false;\n }\n\n /* The root is the hr, so the rules name :host; a bare hr matches only a descendant. */\n :host {\n box-sizing: border-box;\n align-self: stretch;\n margin: 0;\n border: 0;\n border-block-start: 1px solid var(--ui-separator-color, var(--ui-border-default));\n }\n\n :host[aria-orientation=\"vertical\"] {\n block-size: auto;\n border-block-start: 0;\n border-inline-start: 1px solid var(--ui-separator-color, var(--ui-border-default));\n }","declarations":[],"slots":[],"root":{"kind":"native","element":"hr","choices":["hr"]}},{"source":{"file":"./components/ui-sidebar/ui-sidebar.html"},"contract":{"version":1,"name":"UiSidebar","tag":"ui-sidebar","nativeElement":"aside","props":{"breakpoint":{"type":{"enum":["sm","md","lg"]},"required":false,"target":{"attribute":"breakpoint"},"description":"Below this viewport width (40rem, 48rem, 64rem) the sidebar becomes an off-canvas drawer, closed until toggled.","default":"md"},"collapsed":{"type":"boolean","required":false,"target":{"attribute":"collapsed"},"description":"Whether the docked sidebar is collapsed.","default":false},"maxWidth":{"type":"number","required":false,"target":{"attribute":"maxwidth"},"description":"The widest width the resize handle allows, in pixels.","default":480},"minWidth":{"type":"number","required":false,"target":{"attribute":"minwidth"},"description":"The narrowest width the resize handle allows, in pixels.","default":200},"resizable":{"type":"boolean","required":false,"target":{"attribute":"resizable"},"description":"Adds a resize handle on the inner edge (drag, or arrow keys, Home, and End).","default":false},"resizeLabel":{"type":"string","required":false,"target":{"attribute":"aria-label"},"description":"Accessible name of the resize handle.","default":"Resize sidebar"},"resizeStep":{"type":"number","required":false,"target":{"attribute":"resizestep"},"description":"Arrow-key resize step in pixels.","default":16},"side":{"type":{"enum":["start","end"]},"required":false,"target":{"attribute":"side"},"description":"The edge the sidebar sits on. The page places it beside its main content.","default":"start"},"width":{"type":"number","required":false,"target":{"attribute":"width"},"description":"Docked width in pixels. 0 uses --ui-sidebar-width (280px by default); dragging the handle updates it.","default":0}}},"template":{"kind":"element","name":"aside","attributes":[],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"content"}],"children":[{"kind":"slot"}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"resizer"},{"kind":"literal","name":"role","value":"separator"},{"kind":"literal","name":"aria-orientation","value":"vertical"},{"kind":"literal","name":"tabindex","value":"0"},{"kind":"literal","name":"data-ui-affordance","value":"resize"},{"kind":"attribute","name":"aria-label","expression":"resizeLabel","expressionPlan":{"source":"resizeLabel","ast":{"kind":"id","name":"resizeLabel"},"dependencies":["resizeLabel"]}},{"kind":"attribute","name":"hidden","expression":"not resizable or drawer or internalCollapsed","expressionPlan":{"source":"not resizable or drawer or internalCollapsed","ast":{"kind":"binary","op":"or","left":{"kind":"binary","op":"or","left":{"kind":"unary","op":"not","operand":{"kind":"id","name":"resizable"}},"right":{"kind":"id","name":"drawer"}},"right":{"kind":"id","name":"internalCollapsed"}},"dependencies":["drawer","internalCollapsed","resizable"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"guide"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[]}],"ref":"resizer"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-sidebar-backdrop {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-sidebar-border {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-sidebar-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-sidebar-width {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-sidebar-backdrop: var(--ui-sidebar-backdrop);\n\n position: relative;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n flex: none;\n inline-size: var(--_sidebar-width, var(--ui-sidebar-width, 280px));\n max-inline-size: 100%;\n min-block-size: 0;\n background: var(--ui-sidebar-surface, var(--ui-surface-default));\n border-inline-end: 1px solid var(--ui-sidebar-border, var(--ui-border-default));\n }\n\n :host-state([side=\"end\"]) {\n border-inline-end: 0;\n border-inline-start: 1px solid var(--ui-sidebar-border, var(--ui-border-default));\n }\n\n /* The panel's content scrolls, and each edge that hides content fades: the scroll fade every\n Looma scroller uses (see ui-scroll-area). */\n .content {\n flex: 1;\n min-block-size: 0;\n overflow: auto;\n --_ui-scroll-fade-direction: to bottom;\n --_ui-scroll-fade-size: var(--ui-scroll-fade-size, 24px);\n mask-image: linear-gradient(\n var(--_ui-scroll-fade-direction),\n transparent,\n #000 var(--_ui-scroll-fade-start),\n #000 calc(100% - var(--_ui-scroll-fade-end)),\n transparent\n );\n animation: ui-scroll-fade-start linear, ui-scroll-fade-start-hold linear, ui-scroll-fade-end-hold linear, ui-scroll-fade-end linear;\n animation-timeline: scroll(self block);\n animation-range:\n 0 var(--_ui-scroll-fade-size),\n var(--_ui-scroll-fade-size) calc(100% + 1px),\n -1px calc(100% - var(--_ui-scroll-fade-size)),\n calc(100% - var(--_ui-scroll-fade-size)) 100%;\n }\n\n /* Collapsed while docked. */\n :host-state([internalCollapsed]):not([popover]) {\n display: none;\n }\n\n .resizer {\n position: absolute;\n z-index: 1;\n inset-block: 0;\n /* On the panel's inner edge: the end edge of a start sidebar. */\n inset-inline-end: 0;\n inline-size: 8px;\n min-inline-size: 8px;\n transform: translateX(50%);\n cursor: col-resize;\n touch-action: none;\n outline: none;\n }\n\n .resizer[hidden] {\n display: none;\n }\n\n :host-state([side=\"end\"]) .resizer {\n inset-inline-end: auto;\n inset-inline-start: 0;\n transform: translateX(-50%);\n }\n\n .resizer::after {\n content: \"\";\n position: absolute;\n inset-block: 0;\n inset-inline-start: 3px;\n inline-size: 2px;\n background: color-mix(in srgb, var(--ui-affordance-guide-color, var(--ui-border-strong)) 45%, transparent);\n opacity: calc(var(--ui-affordance-guide-opacity) * var(--ui-affordance-scope-guide, 1));\n transition:\n background-color var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease),\n opacity var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease);\n }\n\n .guide {\n position: absolute;\n inset-block-start: 50%;\n inset-inline-start: 50%;\n inline-size: 6px;\n block-size: 22px;\n border: 1px solid var(--ui-border-strong);\n border-radius: var(--ui-radius-round);\n background: var(--ui-surface-elevated);\n opacity: 0;\n transform: translate(-50%, -50%);\n transition: opacity var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease);\n pointer-events: none;\n }\n\n .resizer:is(:hover, :focus-visible)::after {\n background: var(--ui-affordance-direct-color, var(--ui-accent-solid, var(--ui-focus-ring)));\n opacity: 1;\n }\n\n .resizer:is(:hover, :focus-visible) > .guide {\n opacity: 1;\n }\n\n /* Drawer: a popover in the top layer, sliding in from its edge. Closed popovers are hidden by the UA. */\n :host[popover] {\n position: fixed;\n inset-block: 0;\n inset-inline-start: 0;\n inset-inline-end: auto;\n margin: 0;\n padding: 0;\n inline-size: min(var(--_sidebar-width, var(--ui-sidebar-width, 280px)), 85vw);\n max-block-size: none;\n block-size: 100dvh;\n border-block: 0;\n box-shadow: var(--ui-elevation-overlay, var(--ui-shadow-lg));\n transform: translateX(0);\n transition:\n transform var(--ui-motion-base) var(--ui-motion-ease-out),\n display var(--ui-motion-base) allow-discrete,\n overlay var(--ui-motion-base) allow-discrete;\n }\n\n /* The author display above would otherwise override the UA rule that hides a closed popover. */\n :host[popover]:not(:popover-open) {\n display: none;\n transform: translateX(-100%);\n }\n\n :host-state([side=\"end\"])[popover] {\n inset-inline-start: auto;\n inset-inline-end: 0;\n }\n\n :host-state([side=\"end\"])[popover]:not(:popover-open) {\n transform: translateX(100%);\n }\n\n @starting-style {\n :host[popover]:popover-open {\n transform: translateX(-100%);\n }\n :host-state([side=\"end\"])[popover]:popover-open {\n transform: translateX(100%);\n }\n }\n\n :host[popover]::backdrop {\n background: var(--_ui-sidebar-backdrop, rgb(0 0 0 / 0.32));\n }\n\n @media (prefers-reduced-motion: reduce) {\n :host[popover] {\n transition: none;\n }\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"internalCollapsed","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"drawer","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"event","name":"resize","type":"object({ width: number, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"toggle","type":"object({ open: boolean, mode: docked | drawer, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false}],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"aside","choices":["aside"]},"controller":"./components/ui-sidebar/ui-sidebar.js"},{"source":{"file":"./components/ui-spinner/ui-spinner.html"},"contract":{"version":1,"name":"UiSpinner","tag":"ui-spinner","nativeElement":"span","props":{"label":{"type":"string","required":false,"target":{"attribute":"label"},"description":"What is loading, for assistive technology (\"Loading pages\"). With a label the spinner is a status that is announced; without one it is decoration, for a\n spinner beside visible text that already says so.","default":""},"size":{"type":{"enum":["sm","md"]},"required":false,"target":{"attribute":"size"},"description":"sm fits inside a button or a line of small text; md sits beside body text.","default":"md"}}},"template":{"kind":"element","name":"span","attributes":[{"kind":"attribute","name":"role","expression":"{ true: 'status', false: null }[format('%s', label != '')]","expressionPlan":{"source":"{ true: 'status', false: null }[format('%s', label != '')]","ast":{"kind":"index","object":{"kind":"object","pairs":[{"key":"true","value":{"kind":"literal","value":"status"}},{"key":"false","value":{"kind":"literal","value":null}}]},"index":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s"},{"kind":"binary","op":"!=","left":{"kind":"id","name":"label"},"right":{"kind":"literal","value":""}}]}},"dependencies":["label"]}},{"kind":"attribute","name":"aria-label","expression":"{ true: label, false: null }[format('%s', label != '')]","expressionPlan":{"source":"{ true: label, false: null }[format('%s', label != '')]","ast":{"kind":"index","object":{"kind":"object","pairs":[{"key":"true","value":{"kind":"id","name":"label"}},{"key":"false","value":{"kind":"literal","value":null}}]},"index":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s"},{"kind":"binary","op":"!=","left":{"kind":"id","name":"label"},"right":{"kind":"literal","value":""}}]}},"dependencies":["label"]}},{"kind":"attribute","name":"aria-hidden","expression":"{ true: null, false: 'true' }[format('%s', label != '')]","expressionPlan":{"source":"{ true: null, false: 'true' }[format('%s', label != '')]","ast":{"kind":"index","object":{"kind":"object","pairs":[{"key":"true","value":{"kind":"literal","value":null}},{"key":"false","value":{"kind":"literal","value":"true"}}]},"index":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s"},{"kind":"binary","op":"!=","left":{"kind":"id","name":"label"},"right":{"kind":"literal","value":""}}]}},"dependencies":["label"]}}],"children":[{"kind":"element","name":"ui-icon","attributes":[{"kind":"literal","name":"name","value":"loader"}],"children":[]}]},"css":"/* Something is on its way. It turns in the current text colour; with reduced motion it holds still,\n and the label (or the text beside it) still says what is happening. */\n :host {\n display: inline-flex;\n flex: none;\n color: currentColor;\n font-size: var(--ui-font-size-lg);\n line-height: 1;\n animation: ui-spinner-turn 0.8s linear infinite;\n }\n\n :host-state([size=\"sm\"]) {\n font-size: var(--ui-font-size-md);\n }\n\n @keyframes ui-spinner-turn {\n to {\n transform: rotate(1turn);\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n :host {\n animation: none;\n }\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[],"root":{"kind":"native","element":"span","choices":["span"]}},{"source":{"file":"./components/ui-stack/ui-stack.html"},"contract":{"version":1,"name":"UiStack","tag":"ui-stack","nativeElement":"div","props":{"align":{"type":{"enum":["start","center","end","stretch"]},"required":false,"target":{"attribute":"align"},"description":"How items sit across the stack: stretch (the default) makes each fill the stack's width; start, center, and end keep each at its own width, against the\n start, in the middle, or against the end."},"gap":{"type":{"enum":["xs","s","m","l","xl"]},"required":false,"target":{"attribute":"gap"},"description":"Space between items, on the spacing scale: xs is 0.5rem, s 0.75rem, m 1rem (also the default), l 1.5rem, and xl 2rem. The --ui-stack-gap custom property,\n set on the stack itself, overrides it; set on an ancestor, it does nothing."},"justify":{"type":{"enum":["start","center","end","between"]},"required":false,"target":{"attribute":"justify"},"description":"Where items sit along a stack that is taller than its content: start (the default), center, end, or between, which spreads the spare space between items.\n It has no effect unless the stack is given a height or stretched to one."}}},"template":{"kind":"element","name":"div","attributes":[],"children":[{"kind":"slot"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-stack-gap {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n --_layout-gap: var(--ui-space-4);\n display: flex;\n flex-direction: column;\n align-items: stretch;\n gap: var(--ui-stack-gap, var(--_layout-gap));\n min-inline-size: 0;\n max-inline-size: 100%;\n margin: 0;\n }\n\n :host-state([gap=\"xs\"]) {\n --_layout-gap: var(--ui-space-2);\n }\n :host-state([gap=\"s\"]) {\n --_layout-gap: var(--ui-space-3);\n }\n :host-state([gap=\"m\"]) {\n --_layout-gap: var(--ui-space-4);\n }\n :host-state([gap=\"l\"]) {\n --_layout-gap: var(--ui-space-5);\n }\n :host-state([gap=\"xl\"]) {\n --_layout-gap: var(--ui-space-6);\n }\n :host-state([align=\"start\"]) {\n align-items: flex-start;\n }\n :host-state([align=\"center\"]) {\n align-items: center;\n }\n :host-state([align=\"end\"]) {\n align-items: flex-end;\n }\n :host-state([justify=\"center\"]) {\n justify-content: center;\n }\n :host-state([justify=\"end\"]) {\n justify-content: flex-end;\n }\n :host-state([justify=\"between\"]) {\n justify-content: space-between;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]}},{"source":{"file":"./components/ui-status-message/ui-status-message.html"},"contract":{"version":1,"name":"UiStatusMessage","tag":"ui-status-message","nativeElement":"div","props":{"heading":{"type":"string","required":false,"target":{"attribute":"heading"},"description":"A short heading above the message, such as \"No pages yet\". Optional.","default":""},"kind":{"type":{"enum":["empty","loading","error"]},"required":false,"target":{"attribute":"kind"},"description":"What the view is saying. empty: there is nothing here yet (announced politely); loading: it is on its way, with a spinner (announced politely); error: it\n could not be shown, in the danger tone (announced at once).","default":"empty"},"layout":{"type":{"enum":["inline","panel","fill"]},"required":false,"target":{"attribute":"layout"},"description":"Where it sits. inline takes its place in the view's flow; panel sits it on a dashed surface, for an empty area in a page; fill centres it in all the space\n it is given, for a whole view that is loading or failed.","default":"inline"}}},"template":{"kind":"element","name":"div","attributes":[{"kind":"attribute","name":"role","expression":"{ true: 'alert', false: 'status' }[format('%s', kind = 'error')]","expressionPlan":{"source":"{ true: 'alert', false: 'status' }[format('%s', kind = 'error')]","ast":{"kind":"index","object":{"kind":"object","pairs":[{"key":"true","value":{"kind":"literal","value":"alert"}},{"key":"false","value":{"kind":"literal","value":"status"}}]},"index":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s"},{"kind":"binary","op":"=","left":{"kind":"id","name":"kind"},"right":{"kind":"literal","value":"error"}}]}},"dependencies":["kind"]}}],"children":[{"kind":"element","name":"ui-spinner","attributes":[{"kind":"literal","name":"size","value":"sm"},{"kind":"attribute","name":"hidden","expression":"kind != 'loading'","expressionPlan":{"source":"kind != 'loading'","ast":{"kind":"binary","op":"!=","left":{"kind":"id","name":"kind"},"right":{"kind":"literal","value":"loading"}},"dependencies":["kind"]}}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"copy"}],"children":[{"kind":"element","name":"strong","attributes":[{"kind":"literal","name":"class","value":"heading"},{"kind":"attribute","name":"hidden","expression":"not heading","expressionPlan":{"source":"not heading","ast":{"kind":"unary","op":"not","operand":{"kind":"id","name":"heading"}},"dependencies":["heading"]}}],"children":[{"kind":"element","name":"template","attributes":[{"kind":"directive","name":"value","expression":"heading","expressionPlan":{"source":"heading","ast":{"kind":"id","name":"heading"},"dependencies":["heading"]}}],"children":[]}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"message"}],"children":[{"kind":"slot"}]}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"action"}],"children":[{"kind":"slot","fallback":[],"name":"action"}]}]},"css":"/* The one way a view says it is loading, has nothing yet, or failed, with an optional next step.\n Every view says it the same way, in the same place, at the same size. */\n :host {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--ui-space-2) var(--ui-space-4);\n padding-block: var(--ui-space-4);\n color: var(--ui-text-muted);\n font-size: var(--ui-font-size-md);\n line-height: var(--ui-line-height);\n }\n\n :host-state([kind=\"error\"]) {\n color: var(--ui-danger);\n }\n\n :host-state([layout=\"panel\"]) {\n padding: var(--ui-space-6);\n border: 1px dashed var(--ui-border-default);\n border-radius: var(--ui-radius-lg);\n }\n\n :host-state([layout=\"fill\"]) {\n flex: 1;\n flex-direction: column;\n justify-content: center;\n min-block-size: 50vh;\n text-align: center;\n }\n\n .copy {\n display: flex;\n flex: 1 1 12rem;\n flex-direction: column;\n gap: var(--ui-space-1);\n min-inline-size: 0;\n }\n\n :host-state([layout=\"fill\"]) .copy {\n flex: none;\n align-items: center;\n }\n\n .heading {\n color: var(--ui-text-primary);\n font-weight: var(--ui-font-semibold);\n }\n\n .action {\n display: inline-flex;\n flex-wrap: wrap;\n gap: var(--ui-space-2);\n }\n\n .action:empty {\n display: none;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true},{"dynamic":false,"required":true,"name":"action"}],"root":{"kind":"native","element":"div","choices":["div"]}},{"source":{"file":"./components/ui-switch/ui-switch.html"},"contract":{"version":1,"name":"UiSwitch","tag":"ui-switch","nativeElement":"label","props":{"checked":{"type":"boolean","required":false,"target":{"attribute":"checked"},"description":"Whether the switch is checked initially or when set externally. A form reset returns it to this.","default":false},"disabled":{"type":"boolean","required":false,"target":{"attribute":"disabled"},"description":"Disables the native switch, so it cannot be toggled or focused.","default":false},"name":{"type":"string","required":false,"target":{"attribute":"name"},"description":"The native name the switch submits under: a form that contains it sends name=value while it is on, and nothing while it is off, as a native checkbox does.\n Left empty, it takes no part in form submission.","default":""},"required":{"type":"boolean","required":false,"target":{"attribute":"required"},"description":"Marks the native switch required, so native form validation treats it as invalid until it is on.","default":false},"value":{"type":"string","required":false,"target":{"attribute":"value"},"description":"The value a form submits under name while the switch is on, also reported in the change event's detail so one handler can tell switches apart. on by\n default, as on a native checkbox.","default":"on"}}},"template":{"kind":"element","name":"label","attributes":[],"children":[{"kind":"element","name":"input","attributes":[{"kind":"literal","name":"type","value":"checkbox"},{"kind":"literal","name":"role","value":"switch"},{"kind":"property","key":"checked","name":"checked","expression":"internalChecked","expressionPlan":{"source":"internalChecked","ast":{"kind":"id","name":"internalChecked"},"dependencies":["internalChecked"]}},{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}},{"kind":"attribute","name":"required","expression":"required","expressionPlan":{"source":"required","ast":{"kind":"id","name":"required"},"dependencies":["required"]}},{"kind":"attribute","name":"name","expression":"name","expressionPlan":{"source":"name","ast":{"kind":"id","name":"name"},"dependencies":["name"]}},{"kind":"attribute","name":"value","expression":"value","expressionPlan":{"source":"value","ast":{"kind":"id","name":"value"},"dependencies":["value"]}}],"children":[],"ref":"input"},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"text"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"label"}],"children":[{"kind":"slot"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"description"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[{"kind":"slot","fallback":[],"name":"description"}],"ref":"description"}]}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-switch-gap {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-switch-track-height {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-switch-track-width {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-switch-track-width: var(--ui-switch-track-width);\n --_ui-switch-track-height: var(--ui-switch-track-height);\n\n display: inline-flex;\n align-items: flex-start;\n gap: var(--ui-switch-gap, var(--ui-space-2));\n max-inline-size: 100%;\n color: var(--ui-text-primary);\n cursor: pointer;\n }\n\n /* The label, and under it an optional line saying what the choice means. */\n .text {\n display: flex;\n flex-direction: column;\n gap: var(--ui-space-1);\n min-inline-size: 0;\n }\n\n .label {\n min-inline-size: 0;\n line-height: var(--ui-line-height-md);\n }\n\n .description {\n color: var(--ui-text-secondary);\n font-size: var(--ui-font-size-sm);\n line-height: var(--ui-line-height);\n }\n\n .description:empty {\n display: none;\n }\n\n input {\n appearance: none;\n -webkit-appearance: none;\n position: relative;\n flex: 0 0 auto;\n width: var(--_ui-switch-track-width, 2.5rem);\n height: var(--_ui-switch-track-height, 1.5rem);\n padding: 0;\n border: 1px solid var(--ui-control-border-hover, var(--ui-border-strong));\n border-radius: 999px;\n background: var(--ui-control-surface, var(--ui-surface-default));\n box-shadow: inset 0 1px 2px color-mix(in srgb, var(--ui-text-primary) 10%, transparent);\n cursor: pointer;\n transition: background-color var(--ui-motion-fast) var(--ui-motion-ease), border-color var(--ui-motion-fast) var(--ui-motion-ease);\n margin: 0;\n }\n\n input::after {\n content: \"\";\n position: absolute;\n top: 3px;\n left: 3px;\n width: 1rem;\n height: 1rem;\n border-radius: 999px;\n background: var(--ui-text-secondary);\n box-shadow: var(--ui-shadow-xs);\n transition: transform var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n input:checked {\n background: var(--ui-accent-solid);\n border-color: var(--ui-accent-solid);\n }\n\n input:checked::after {\n transform: translateX(1rem);\n background: var(--ui-text-on-accent);\n }\n\n input:focus-visible {\n outline: 2px solid var(--ui-focus-ring, var(--ui-accent-solid));\n outline-offset: 2px;\n }\n\n :host-state([disabled]) {\n color: var(--ui-disabled-text);\n cursor: not-allowed;\n }\n :host-state([disabled]) input {\n border-color: var(--ui-border-default);\n background: var(--ui-control-surface-disabled, var(--ui-surface-muted));\n cursor: not-allowed;\n }\n\n @media (prefers-reduced-motion: reduce) {\n input, input::after {\n transition: none;\n }\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"internalChecked","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"event","name":"change","type":"object({ checked: boolean, value: string, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false}],"slots":[{"dynamic":false,"required":true},{"dynamic":false,"required":true,"name":"description"}],"root":{"kind":"native","element":"label","choices":["label"]},"controller":"./components/ui-switch/ui-switch.js"},{"source":{"file":"./components/ui-switcher/ui-switcher.html"},"contract":{"version":1,"name":"UiSwitcher","tag":"ui-switcher","nativeElement":"div","props":{"align":{"type":{"enum":["start","center","end","stretch"]},"required":false,"target":{"attribute":"align"},"description":"How items line up while they sit in a row: stretch (the default) makes them equally tall; start, center, and end align their tops, middles, or\n bottoms."},"gap":{"type":{"enum":["xs","s","m","l","xl"]},"required":false,"target":{"attribute":"gap"},"description":"Space between items, on the spacing scale: xs is 0.5rem, s 0.75rem, m 1rem (also the default), l 1.5rem, and xl 2rem. The --ui-switcher-gap custom\n property, set on the switcher itself, overrides it; set on an ancestor, it does nothing."},"threshold":{"type":{"enum":["xs","sm","md","lg"]},"required":false,"target":{"attribute":"threshold"},"description":"The container width at which items switch between a row and a stack: wider, they all sit side by side; narrower, each takes the full width. xs is 20rem, sm\n is 30rem (also the default), md is 45rem, and lg is 60rem."}}},"template":{"kind":"element","name":"div","attributes":[],"children":[{"kind":"slot"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-switcher-gap {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-switcher-threshold {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-switcher-threshold: var(--ui-switcher-threshold);\n\n --_switcher-gap: var(--ui-space-4);\n display: flex;\n flex-wrap: wrap;\n gap: var(--ui-switcher-gap, var(--_switcher-gap));\n min-inline-size: 0;\n max-inline-size: 100%;\n margin: 0;\n }\n\n :host > :slotted(*) {\n min-inline-size: 0;\n flex-grow: 1;\n /* The large multiplier makes the basis flip as a group at the intrinsic threshold. */\n flex-basis: calc((var(--_ui-switcher-threshold, 30rem) - 100%) * 999);\n }\n\n :host-state([gap=\"xs\"]) {\n --_switcher-gap: var(--ui-space-2);\n }\n :host-state([gap=\"s\"]) {\n --_switcher-gap: var(--ui-space-3);\n }\n :host-state([gap=\"m\"]) {\n --_switcher-gap: var(--ui-space-4);\n }\n :host-state([gap=\"l\"]) {\n --_switcher-gap: var(--ui-space-5);\n }\n :host-state([gap=\"xl\"]) {\n --_switcher-gap: var(--ui-space-6);\n }\n :host-state([threshold=\"xs\"]) > :slotted(*) {\n flex-basis: calc((var(--_ui-switcher-threshold, 20rem) - 100%) * 999);\n }\n :host-state([threshold=\"md\"]) > :slotted(*) {\n flex-basis: calc((var(--_ui-switcher-threshold, 45rem) - 100%) * 999);\n }\n :host-state([threshold=\"lg\"]) > :slotted(*) {\n flex-basis: calc((var(--_ui-switcher-threshold, 60rem) - 100%) * 999);\n }\n :host-state([align=\"start\"]) {\n align-items: flex-start;\n }\n :host-state([align=\"center\"]) {\n align-items: center;\n }\n :host-state([align=\"end\"]) {\n align-items: flex-end;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]}},{"source":{"file":"./components/ui-tabs/ui-tabs.html"},"contract":{"version":1,"name":"UiTabs","tag":"ui-tabs","nativeElement":"div","props":{"density":{"type":{"enum":["comfortable","compact"]},"required":false,"target":{"attribute":"density"},"description":"Compact trades padding and type size for rows that fit more on screen.","default":"comfortable"},"label":{"type":"string","required":false,"target":{"attribute":"aria-label"},"description":"The tab list's accessible name, announced when focus enters the list. Name what the tabs switch between.","default":"Tabs"},"orientation":{"type":{"enum":["horizontal","vertical"]},"required":false,"target":{"attribute":"aria-orientation"},"description":"horizontal puts the tabs in a row above the panels, moved between with the Left and Right arrow keys; vertical puts them in a column beside the panels,\n moved between with Up and Down.","default":"horizontal"},"stretch":{"type":"boolean","required":false,"target":{"attribute":"stretch"},"description":"Share the full width of the tab list equally between tabs instead of sizing each to its label.","default":false},"value":{"type":"string","required":false,"target":{"attribute":"value"},"description":"The id of the selected panel, initially or when set externally; empty selects the first panel. Choosing a tab updates it from there and reports a select\n event. A panel without an id is given a generated one.","default":""}}},"template":{"kind":"element","name":"div","attributes":[],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"list"},{"kind":"literal","name":"role","value":"tablist"},{"kind":"attribute","name":"aria-label","expression":"label","expressionPlan":{"source":"label","ast":{"kind":"id","name":"label"},"dependencies":["label"]}},{"kind":"attribute","name":"aria-orientation","expression":"orientation","expressionPlan":{"source":"orientation","ast":{"kind":"id","name":"orientation"},"dependencies":["orientation"]}}],"children":[{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"role","value":"tab"},{"kind":"attribute","name":"id","expression":"format('%s-tab', tab.id)","expressionPlan":{"source":"format('%s-tab', tab.id)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s-tab"},{"kind":"member","object":{"kind":"id","name":"tab"},"key":"id"}]},"dependencies":["tab.id"]}},{"kind":"attribute","name":"value","expression":"tab.id","expressionPlan":{"source":"tab.id","ast":{"kind":"member","object":{"kind":"id","name":"tab"},"key":"id"},"dependencies":["tab.id"]}},{"kind":"attribute","name":"aria-controls","expression":"tab.id","expressionPlan":{"source":"tab.id","ast":{"kind":"member","object":{"kind":"id","name":"tab"},"key":"id"},"dependencies":["tab.id"]}},{"kind":"attribute","name":"aria-selected","expression":"tab.id = internalValue","expressionPlan":{"source":"tab.id = internalValue","ast":{"kind":"binary","op":"=","left":{"kind":"member","object":{"kind":"id","name":"tab"},"key":"id"},"right":{"kind":"id","name":"internalValue"}},"dependencies":["internalValue","tab.id"]}},{"kind":"directive","name":"value","expression":"tab.label","expressionPlan":{"source":"tab.label","ast":{"kind":"member","object":{"kind":"id","name":"tab"},"key":"label"},"dependencies":["tab.label"]}}],"children":[],"flow":{"kind":"each","item":"tab","list":"tabs","listPlan":{"source":"tabs","ast":{"kind":"id","name":"tabs"},"dependencies":["tabs"]},"key":"tab.id","keyPlan":{"source":"tab.id","ast":{"kind":"member","object":{"kind":"id","name":"tab"},"key":"id"},"dependencies":["tab.id"]}}}],"ref":"list"},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"panels"}],"children":[{"kind":"slot"}],"ref":"panels"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-tabs-tab-min-block-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-tabs-tab-padding-block {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-tabs-tab-padding-inline {\n syntax: \"*\";\n inherits: false;\n }\n\n /* Density resolves into the tab row's own values; the public tokens still override them. */\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-tabs-tab-min-block-size: var(--ui-tabs-tab-min-block-size);\n --_ui-tabs-tab-padding-block: var(--ui-tabs-tab-padding-block);\n --_ui-tabs-tab-padding-inline: var(--ui-tabs-tab-padding-inline);\n\n --_tab-min-block-size: var(--ui-control-size);\n --_tab-padding-block: var(--ui-space-2);\n --_tab-padding-inline: var(--ui-space-3);\n }\n\n :host-state([density=\"compact\"]) {\n --_tab-min-block-size: var(--ui-control-size-sm);\n --_tab-padding-block: var(--ui-space-1);\n --_tab-padding-inline: var(--ui-space-2);\n }\n\n :host {\n display: grid;\n inline-size: 100%;\n min-inline-size: 0;\n }\n\n .list {\n display: grid;\n grid-auto-flow: column;\n grid-auto-columns: max-content;\n justify-content: start;\n inline-size: 100%;\n max-inline-size: 100%;\n /* Tabs that do not fit scroll sideways rather than wrapping or squeezing. */\n overflow-x: auto;\n /* overflow-x: auto would make the block axis scrollable too; a sideways swipe must not scroll the\n strip or the page vertically. */\n overflow-y: hidden;\n overscroll-behavior: contain;\n scrollbar-width: thin;\n border-block-end: 1px solid var(--ui-border-default);\n }\n\n .list button {\n min-block-size: var(--_ui-tabs-tab-min-block-size, var(--_tab-min-block-size));\n margin: 0 0 -1px;\n padding: var(--_ui-tabs-tab-padding-block, var(--_tab-padding-block)) var(--_ui-tabs-tab-padding-inline, var(--_tab-padding-inline));\n border: 0;\n border-block-end: 2px solid transparent;\n background: transparent;\n color: var(--ui-text-secondary);\n font: inherit;\n font-size: var(--ui-font-size-sm);\n font-weight: var(--ui-font-medium);\n cursor: pointer;\n transition:\n color var(--ui-motion-fast) var(--ui-motion-ease),\n background-color var(--ui-motion-fast) var(--ui-motion-ease),\n border-color var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n /* Centre the glyphs, not the line box: a label without descenders otherwise reads high. */\n /* Centre the glyphs, not the line box: a label without descenders otherwise reads high.\n * Trimming applies to block containers, so the box is a block with centred content. */\n @supports (text-box-trim: trim-both) {\n .list button {\n display: block;\n text-align: center;\n align-content: center;\n text-box-trim: trim-both;\n text-box-edge: cap alphabetic;\n }\n }\n\n :host-state([stretch]) .list {\n grid-auto-columns: minmax(max-content, 1fr);\n }\n\n .list button {\n white-space: nowrap;\n }\n\n .list button:hover {\n color: var(--ui-text-primary);\n background: var(--ui-surface-muted);\n }\n .list button[aria-selected=\"true\"] {\n color: var(--ui-accent-solid);\n border-block-end-color: var(--ui-accent-solid);\n }\n .list button:focus-visible {\n position: relative;\n outline: none;\n box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--ui-focus-ring) 45%, transparent);\n border-radius: var(--ui-radius-sm);\n }\n\n .panels {\n min-inline-size: 0;\n }\n :slotted(*) {\n padding: var(--ui-space-4);\n }\n\n :host-state([orientation=\"vertical\"]) {\n grid-template-columns: max-content minmax(0, 1fr);\n align-items: start;\n }\n\n :host-state([orientation=\"vertical\"]) .list {\n grid-auto-flow: row;\n grid-auto-columns: auto;\n border-block-end: 0;\n border-inline-end: 1px solid var(--ui-border-default);\n }\n\n :host-state([orientation=\"vertical\"]) .list button {\n margin: 0 -1px 0 0;\n border-block-end: 0;\n border-inline-end: 2px solid transparent;\n text-align: start;\n }\n\n :host-state([orientation=\"vertical\"]) .list button[aria-selected=\"true\"] {\n border-inline-end-color: var(--ui-accent-solid);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .list button {\n transition: none;\n }\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"internalValue","expression":{"source":"''","ast":{"kind":"literal","value":""},"dependencies":[]}},{"kind":"state","name":"tabs","type":"list(object({ id: string, label: string }))","expression":{"source":"[]","ast":{"kind":"array","items":[]},"dependencies":[]}},{"kind":"event","name":"select","type":"object({ value: string, previousValue: string, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false}],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-tabs/ui-tabs.js"},{"source":{"file":"./components/ui-text/ui-text.html"},"contract":{"version":1,"name":"UiText","tag":"ui-text","nativeElement":"p","props":{"align":{"type":{"enum":["start","center"]},"required":false,"target":{"attribute":"align"},"description":"Aligns the text within its line.","default":"start"},"as":{"type":{"enum":["p","span","div","small","strong","label"]},"required":false,"target":{"attribute":"as"},"description":"The native element the text renders: a paragraph by default, inline span, small, or strong within a line, a div for a block, or a label for a\n control.","default":"p"},"size":{"type":{"enum":["inherit","xs","sm","md","lg"]},"required":false,"target":{"attribute":"size"},"description":"The step on the type scale. inherit (the default) keeps the size of the text around it; xs is for fine print, sm for supporting text such as help and\n metadata, md is body text, and lg is a lead paragraph.","default":"inherit"},"tone":{"type":{"enum":["default","secondary","muted","accent","danger","success"]},"required":false,"target":{"attribute":"tone"},"description":"The text's colour, by meaning. secondary is supporting prose such as a description; muted is quieter still, for metadata and hints; accent draws the eye;\n danger states an error; success confirms one.","default":"default"},"truncate":{"type":"boolean","required":false,"target":{"attribute":"truncate"},"description":"Keeps the text on one line, ending in an ellipsis when it does not fit.","default":false},"variant":{"type":{"enum":["body","eyebrow","code"]},"required":false,"target":{"attribute":"variant"},"description":"body is running text. eyebrow is a short, uppercase, tracked label that names what follows, such as a group of links; code sets a value to copy or read\n exactly, such as an address, in the monospace face.","default":"body"},"weight":{"type":{"enum":["inherit","normal","medium","semibold"]},"required":false,"target":{"attribute":"weight"},"description":"The weight. inherit keeps the surrounding weight; medium and semibold emphasise a name or a figure.","default":"inherit"}}},"template":{"kind":"element","name":"template","attributes":[],"children":[{"kind":"element","name":"span","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'span'","testPlan":{"source":"as = 'span'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"span"}},"dependencies":["as"]}}},{"kind":"element","name":"div","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'div'","testPlan":{"source":"as = 'div'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"div"}},"dependencies":["as"]}}},{"kind":"element","name":"small","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'small'","testPlan":{"source":"as = 'small'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"small"}},"dependencies":["as"]}}},{"kind":"element","name":"strong","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'strong'","testPlan":{"source":"as = 'strong'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"strong"}},"dependencies":["as"]}}},{"kind":"element","name":"label","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'label'","testPlan":{"source":"as = 'label'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"label"}},"dependencies":["as"]}}},{"kind":"element","name":"p","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"else"}}],"flow":{"kind":"match"}},"css":"/* Running text, set on the type scale and in a tone that says what it is, so a view never styles\n text of its own. The root is a paragraph unless as= names a span, div, small, strong, or label. */\n :host {\n margin: 0;\n min-inline-size: 0;\n color: var(--ui-text-primary);\n text-align: start;\n }\n\n :host-state([size=\"xs\"]) {\n font-size: var(--ui-font-size-xs);\n line-height: var(--ui-line-height);\n }\n :host-state([size=\"sm\"]) {\n font-size: var(--ui-font-size-sm);\n line-height: var(--ui-line-height);\n }\n :host-state([size=\"md\"]) {\n font-size: var(--ui-font-size-md);\n line-height: var(--ui-line-height);\n }\n :host-state([size=\"lg\"]) {\n font-size: var(--ui-font-size-lg);\n line-height: var(--ui-line-height-relaxed);\n }\n\n :host-state([tone=\"secondary\"]) {\n color: var(--ui-text-secondary);\n }\n :host-state([tone=\"muted\"]) {\n color: var(--ui-text-muted);\n }\n :host-state([tone=\"accent\"]) {\n color: var(--ui-accent-active);\n }\n :host-state([tone=\"danger\"]) {\n color: var(--ui-danger);\n }\n :host-state([tone=\"success\"]) {\n color: var(--ui-success);\n }\n\n :host-state([weight=\"normal\"]) {\n font-weight: var(--ui-font-normal);\n }\n :host-state([weight=\"medium\"]) {\n font-weight: var(--ui-font-medium);\n }\n :host-state([weight=\"semibold\"]) {\n font-weight: var(--ui-font-semibold);\n }\n\n :host-state([variant=\"eyebrow\"]) {\n font-size: var(--ui-font-size-xs);\n font-weight: var(--ui-font-semibold);\n letter-spacing: 0.06em;\n text-transform: uppercase;\n }\n :host-state([variant=\"code\"]) {\n font-family: var(--ui-font-family-mono);\n }\n\n /* A link in running text is underlined, so it stands apart from the words around it by more than\n colour. */\n :host :slotted(a) {\n color: var(--ui-accent-active);\n text-decoration: underline;\n text-decoration-thickness: 0.06em;\n text-underline-offset: 0.18em;\n }\n\n :host-state([truncate]) {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n :host-state([align=\"center\"]) {\n text-align: center;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"p","choices":["span","div","small","strong","label","p"]}},{"source":{"file":"./components/ui-textarea/ui-textarea.html"},"contract":{"version":1,"name":"UiTextarea","tag":"ui-textarea","nativeElement":"textarea","props":{"disabled":{"type":"boolean","required":false,"target":{"attribute":"disabled"},"description":"Prevents editing and form submission.","default":false},"invalid":{"type":"boolean","required":false,"target":{"attribute":"aria-invalid"},"description":"Exposes invalid state to assistive technology and styling.","default":false},"readonly":{"type":"boolean","required":false,"target":{"attribute":"readonly"},"description":"Allows selection without allowing edits.","default":false},"required":{"type":"boolean","required":false,"target":{"attribute":"required"},"description":"Marks the control as required for form validation.","default":false},"rows":{"type":{"kind":"terminal","name":"integer"},"required":false,"target":{"attribute":"rows"},"description":"Initial number of visible text rows.","default":4},"value":{"type":"string","required":false,"target":{"attribute":"value"},"description":"The textarea's text. Setting or changing it replaces the live text; between changes the user's typing stands, so follow input events to keep it in step. It\n is also the textarea's default, so a form reset returns to it."}}},"template":{"kind":"element","name":"textarea","attributes":[{"kind":"attribute","name":"value","expression":"value","expressionPlan":{"source":"value","ast":{"kind":"id","name":"value"},"dependencies":["value"]}},{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}},{"kind":"attribute","name":"readonly","expression":"readonly","expressionPlan":{"source":"readonly","ast":{"kind":"id","name":"readonly"},"dependencies":["readonly"]}},{"kind":"attribute","name":"required","expression":"required","expressionPlan":{"source":"required","ast":{"kind":"id","name":"required"},"dependencies":["required"]}},{"kind":"attribute","name":"aria-invalid","expression":"invalid","expressionPlan":{"source":"invalid","ast":{"kind":"id","name":"invalid"},"dependencies":["invalid"]}},{"kind":"attribute","name":"rows","expression":"rows","expressionPlan":{"source":"rows","ast":{"kind":"id","name":"rows"},"dependencies":["rows"]}}],"children":[]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-textarea-focus-shadow {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-textarea-radius {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-textarea-shadow {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n box-sizing: border-box;\n display: inline-block;\n inline-size: 100%;\n min-inline-size: 0;\n min-block-size: calc(3rem * 2);\n margin: 0;\n padding: var(--ui-space-2) var(--ui-space-3);\n appearance: none;\n resize: vertical;\n border: 1px solid var(--ui-control-border, var(--ui-border-strong));\n border-radius: var(--ui-textarea-radius, var(--ui-radius-md));\n background: var(--ui-control-surface, var(--ui-surface-elevated));\n color: var(--ui-text-primary);\n font: inherit;\n line-height: var(--ui-line-height-md);\n box-shadow: var(--ui-textarea-shadow, var(--ui-control-inset));\n transition:\n border-color var(--ui-motion-fast) var(--ui-motion-ease),\n box-shadow var(--ui-motion-fast) var(--ui-motion-ease),\n background-color var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n /* Tabbing into a field selects its text; tint that selection softly instead of the page highlight. */\n :host::selection {\n background: color-mix(in srgb, var(--ui-accent-solid) 20%, transparent);\n color: inherit;\n }\n\n :host::placeholder {\n color: var(--ui-control-placeholder, var(--ui-text-secondary));\n opacity: 1;\n }\n\n :host:hover:not(:focus):not(:disabled) {\n border-color: var(--ui-control-border-hover, var(--ui-text-secondary));\n }\n\n :host:focus-visible {\n border-color: var(--ui-control-focus, var(--ui-accent-solid));\n outline: none;\n box-shadow: var(--ui-textarea-focus-shadow, var(--ui-control-inset), var(--ui-control-focus-halo-shadow));\n }\n\n /* The app's invalid flag, or the browser's own verdict once the user has left an invalid field. */\n :host[aria-invalid=\"true\"],\n :host:user-invalid {\n border-color: var(--ui-danger-solid);\n }\n\n :host:is([aria-invalid=\"true\"], :user-invalid):focus-visible {\n box-shadow:\n var(--ui-control-inset),\n 0 0 0 3px color-mix(in srgb, var(--ui-danger-solid) 22%, transparent);\n }\n\n :host:disabled {\n background: var(--ui-control-surface-disabled, var(--ui-surface-muted));\n color: var(--ui-disabled-text);\n box-shadow: none;\n cursor: not-allowed;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[],"root":{"kind":"native","element":"textarea","choices":["textarea"]},"controller":"./components/ui-textarea/ui-textarea.js"},{"source":{"file":"./components/ui-toast-region/ui-toast-region.html"},"contract":{"version":1,"name":"UiToastRegion","tag":"ui-toast-region","nativeElement":"div","props":{"auto":{"type":"boolean","required":false,"target":{"attribute":"auto"},"description":"Dismiss each message automatically after its duration. Timers pause while the pointer or focus is on a message.","default":false},"duration":{"type":"number","required":false,"target":{"attribute":"duration"},"description":"Milliseconds an automatically dismissed message stays visible.","default":5000},"message":{"type":"string","required":false,"target":{"attribute":"message"},"description":"Fallback message used by the declarative show command.","default":"Notification"},"open":{"type":"boolean","required":false,"target":{"attribute":"open"},"description":"Whether the messages authored inside the region are visible.","default":false}}},"template":{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"role","value":"region"},{"kind":"literal","name":"aria-label","value":"Notifications"},{"kind":"literal","name":"aria-live","value":"polite"},{"kind":"literal","name":"popover","value":"manual"}],"children":[{"kind":"slot"},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"toast"},{"kind":"attribute","name":"closing","expression":"toast.closing","expressionPlan":{"source":"toast.closing","ast":{"kind":"member","object":{"kind":"id","name":"toast"},"key":"closing"},"dependencies":["toast.closing"]},"target":"class"},{"kind":"attribute","name":"id","expression":"toast.id","expressionPlan":{"source":"toast.id","ast":{"kind":"member","object":{"kind":"id","name":"toast"},"key":"id"},"dependencies":["toast.id"]}},{"kind":"attribute","name":"role","expression":"toast.role","expressionPlan":{"source":"toast.role","ast":{"kind":"member","object":{"kind":"id","name":"toast"},"key":"role"},"dependencies":["toast.role"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"message"},{"kind":"directive","name":"value","expression":"toast.message","expressionPlan":{"source":"toast.message","ast":{"kind":"member","object":{"kind":"id","name":"toast"},"key":"message"},"dependencies":["toast.message"]}}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"dismiss"},{"kind":"attribute","name":"data-toast","expression":"toast.id","expressionPlan":{"source":"toast.id","ast":{"kind":"member","object":{"kind":"id","name":"toast"},"key":"id"},"dependencies":["toast.id"]}}],"children":[{"kind":"element","name":"ui-icon-button","attributes":[{"kind":"literal","name":"size","value":"sm"},{"kind":"literal","name":"variant","value":"ghost"},{"kind":"attribute","name":"round","expression":"true","expressionPlan":{"source":"true","ast":{"kind":"literal","value":true},"dependencies":[]}},{"kind":"attribute","name":"label","expression":"format('Dismiss %s', toast.message)","expressionPlan":{"source":"format('Dismiss %s', toast.message)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"Dismiss %s"},{"kind":"member","object":{"kind":"id","name":"toast"},"key":"message"}]},"dependencies":["toast.message"]}}],"children":[{"kind":"element","name":"svg","attributes":[{"kind":"literal","name":"viewBox","value":"0 0 24 24"},{"kind":"literal","name":"fill","value":"none"},{"kind":"literal","name":"stroke","value":"currentColor"},{"kind":"literal","name":"stroke-width","value":"2"},{"kind":"literal","name":"stroke-linecap","value":"round"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[{"kind":"element","name":"path","attributes":[{"kind":"literal","name":"d","value":"M18 6 6 18M6 6l12 12"}],"children":[]}]}]}]}],"flow":{"kind":"each","item":"toast","list":"toasts","listPlan":{"source":"toasts","ast":{"kind":"id","name":"toasts"},"dependencies":["toasts"]},"key":"toast.id","keyPlan":{"source":"toast.id","ast":{"kind":"member","object":{"kind":"id","name":"toast"},"key":"id"},"dependencies":["toast.id"]}}}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-toast-region-enter-duration {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-toast-region-exit-duration {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-toast-region-enter-duration: var(--ui-toast-region-enter-duration);\n --_ui-toast-region-exit-duration: var(--ui-toast-region-exit-duration);\n\n position: fixed;\n top: calc(var(--ui-space-4) + env(safe-area-inset-top));\n right: auto;\n bottom: auto;\n left: 50%;\n transform: translateX(-50%);\n z-index: 9999;\n display: grid;\n gap: var(--ui-space-2);\n inline-size: min(24rem, calc(100vw - var(--ui-space-4) * 2));\n max-inline-size: 100%;\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n overflow: visible;\n border: 0;\n outline: 0;\n background: transparent;\n box-shadow: none;\n pointer-events: none;\n }\n\n :host:not(:popover-open) {\n display: none;\n }\n\n :host > .toast,\n :host > :slotted(*) {\n pointer-events: auto;\n }\n\n .toast {\n display: grid;\n grid-template-columns: 1fr auto;\n gap: var(--ui-space-2);\n align-items: start;\n border: 1px solid var(--ui-border-default);\n border-radius: var(--ui-radius-lg);\n padding: var(--ui-space-3) var(--ui-space-4);\n background: var(--ui-surface-elevated);\n color: var(--ui-text-primary);\n box-shadow: var(--ui-elevation-overlay, var(--ui-shadow-lg));\n animation: ui-toast-enter var(--_ui-toast-region-enter-duration, 0.32s) var(--ui-motion-ease-out, cubic-bezier(0.16, 1, 0.3, 1)) both;\n }\n\n /* Leaving slides on down and fades; the controller removes the toast when this ends. */\n .toast.closing {\n animation: ui-toast-exit var(--_ui-toast-region-exit-duration, 0.22s) var(--ui-motion-ease) both;\n pointer-events: none;\n }\n\n @keyframes ui-toast-enter {\n from {\n opacity: 0;\n transform: translateY(-1rem);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n @keyframes ui-toast-exit {\n from {\n opacity: 1;\n transform: translateY(0);\n }\n to {\n opacity: 0;\n transform: translateY(0.75rem);\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .toast, .toast.closing {\n animation: none;\n }\n }\n\n .message {\n min-inline-size: 0;\n align-self: center;\n }\n\n .dismiss {\n align-self: center;\n margin-inline-end: calc(var(--ui-space-2) * -1);\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"internalOpen","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"toasts","type":"list(object({ id: string, message: string, role: alert | status, closing: boolean }))","expression":{"source":"[]","ast":{"kind":"array","items":[]},"dependencies":[]}},{"kind":"event","name":"close","type":"object({ open: boolean, reason: action | timeout | programmatic | light-dismiss | escape, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"dismiss","type":"object({ id: string, reason: action | timeout, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"method","name":"show","exportName":"show","returns":"promise(string)"}],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-toast-region/ui-toast-region.js"},{"source":{"file":"./components/ui-tooltip/ui-tooltip.html"},"contract":{"version":1,"name":"UiTooltip","tag":"ui-tooltip","nativeElement":"span","props":{"for":{"type":"string","required":false,"target":{"attribute":"for"},"description":"ID of the control described and visually anchored by the tooltip.","default":""},"hideDelay":{"type":"number","required":false,"target":{"attribute":"hidedelay"},"description":"Waits this many milliseconds before hiding after pointer exit.","default":100},"inverse":{"type":"boolean","required":false,"target":{"attribute":"inverse"},"description":"Use the high-contrast inverse surface (dark on light themes, light on dark themes).","default":false},"open":{"type":"boolean","required":false,"target":{"attribute":"open"},"description":"Whether the tooltip is open initially or when set externally.","default":false},"placement":{"type":"string","required":false,"target":{"attribute":"placement"},"description":"Positions the description relative to its trigger.","default":"top-start"},"showDelay":{"type":"number","required":false,"target":{"attribute":"showdelay"},"description":"Waits this many milliseconds before showing after pointer entry.","default":500},"trigger":{"type":{"enum":["hover","click","focus"]},"required":false,"target":{"attribute":"trigger"},"description":"How the trigger opens it. hover also opens on keyboard focus; click toggles it and suits a help button, where hovering a question mark says nothing; focus\n opens only while the trigger holds focus.","default":"hover"}}},"template":{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"role","value":"tooltip"},{"kind":"attribute","name":"hidden","expression":"not internalOpen","expressionPlan":{"source":"not internalOpen","ast":{"kind":"unary","op":"not","operand":{"kind":"id","name":"internalOpen"}},"dependencies":["internalOpen"]}}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"surface"}],"children":[{"kind":"slot"}]}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-tooltip-arrow-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-tooltip-border {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-tooltip-inverse-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-tooltip-inverse-text {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-tooltip-max-inline-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-tooltip-radius {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-tooltip-shadow {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-tooltip-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-tooltip-text {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-tooltip-border: var(--ui-tooltip-border);\n --_ui-tooltip-max-inline-size: var(--ui-tooltip-max-inline-size);\n --_ui-tooltip-radius: var(--ui-tooltip-radius);\n --_ui-tooltip-surface: var(--ui-tooltip-surface);\n --_ui-tooltip-text: var(--ui-tooltip-text);\n --_ui-tooltip-shadow: var(--ui-tooltip-shadow);\n --_ui-tooltip-inverse-surface: var(--ui-tooltip-inverse-surface);\n --_ui-tooltip-inverse-text: var(--ui-tooltip-inverse-text);\n --_ui-tooltip-arrow-size: var(--ui-tooltip-arrow-size);\n\n position: fixed;\n inset: auto;\n margin: 0;\n display: inline-block;\n box-sizing: border-box;\n padding: 0;\n border: 0;\n outline: 0;\n border-radius: 0;\n background: transparent;\n /* The UA popover default (overflow: auto) would clip the arrow. */\n overflow: visible;\n opacity: 0;\n transform: translateY(4px);\n transition:\n opacity var(--ui-motion-fast) var(--ui-motion-ease),\n transform var(--ui-motion-fast) var(--ui-motion-ease),\n display var(--ui-motion-fast) allow-discrete,\n overlay var(--ui-motion-fast) allow-discrete;\n }\n\n .surface {\n --_tooltip-line: var(--_ui-tooltip-border, var(--ui-border-default));\n position: relative;\n box-sizing: border-box;\n max-inline-size: var(--_ui-tooltip-max-inline-size, 18rem);\n border: 1px solid var(--_tooltip-line);\n border-radius: var(--_ui-tooltip-radius, var(--ui-radius-sm));\n background: var(--_ui-tooltip-surface, var(--ui-surface-elevated));\n color: var(--_ui-tooltip-text, var(--ui-text-primary));\n padding: var(--ui-space-1) var(--ui-space-2);\n font-family: var(--ui-font-family-sans);\n font-size: var(--ui-font-size-sm);\n line-height: var(--ui-line-height-tight);\n box-shadow: var(--_ui-tooltip-shadow, var(--ui-elevation-tooltip, var(--ui-shadow-md)));\n }\n\n :host-state([inverse]) .surface {\n --_tooltip-line: var(--_ui-tooltip-inverse-surface, var(--ui-text-primary));\n background: var(--_ui-tooltip-inverse-surface, var(--ui-text-primary));\n color: var(--_ui-tooltip-inverse-text, var(--ui-surface-default));\n }\n\n /* A rotated square shares the surface fill and draws the two outward border edges. Its centre sits on\n * the surface border line, so the fill covers that stretch of border and the outline runs unbroken. */\n .surface::after {\n content: \"\";\n position: absolute;\n z-index: 1;\n inset-inline-start: var(--ui-space-3);\n inset-block-end: calc(var(--_ui-tooltip-arrow-size, 0.5rem) / -2 - 0.5px);\n inline-size: var(--_ui-tooltip-arrow-size, 0.5rem);\n block-size: var(--_ui-tooltip-arrow-size, 0.5rem);\n box-sizing: border-box;\n background: inherit;\n border: 0 solid var(--_tooltip-line);\n border-inline-end-width: 1px;\n border-block-end-width: 1px;\n border-end-end-radius: 1px;\n transform: rotate(45deg);\n }\n\n :is(:host-state([placement=\"bottom\"]), :host-state([placement=\"bottom-start\"]), :host-state([placement=\"bottom-end\"])) .surface::after {\n inset-block-start: calc(var(--_ui-tooltip-arrow-size, 0.5rem) / -2 - 0.5px);\n inset-block-end: auto;\n border-inline-end-width: 0;\n border-block-end-width: 0;\n border-inline-start-width: 1px;\n border-block-start-width: 1px;\n border-end-end-radius: 0;\n border-start-start-radius: 1px;\n }\n\n :is(:host-state([placement=\"top-end\"]), :host-state([placement=\"bottom-end\"])) .surface::after {\n inset-inline-start: auto;\n inset-inline-end: var(--ui-space-3);\n }\n\n :host:popover-open {\n opacity: 1;\n transform: translateY(0);\n }\n\n @starting-style {\n :host:popover-open {\n opacity: 0;\n transform: translateY(4px);\n }\n }\n\n :host[hidden] {\n display: none;\n }\n\n @media (prefers-reduced-motion: reduce) {\n :host {\n transition: none;\n }\n }","declarations":[{"kind":"state","name":"internalOpen","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"event","name":"open","type":"object({ open: boolean, reason: action | programmatic | light-dismiss | escape, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"close","type":"object({ open: boolean, reason: action | programmatic | light-dismiss | escape, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false}],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"span","choices":["span"]},"controller":"./components/ui-tooltip/ui-tooltip.js"},{"source":{"file":"./components/ui-top-bar/ui-top-bar.html"},"contract":{"version":1,"name":"UiTopBar","tag":"ui-top-bar","nativeElement":"header","props":{}},"template":{"kind":"element","name":"header","attributes":[],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"leading"}],"children":[{"kind":"slot","fallback":[],"name":"leading"}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"title"}],"children":[{"kind":"slot"}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"search"}],"children":[{"kind":"slot","fallback":[],"name":"search"}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"actions"}],"children":[{"kind":"slot","fallback":[],"name":"actions"}]}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-top-bar-actions-gap {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-top-bar-border {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-top-bar-gap {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-top-bar-height {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-top-bar-padding-inline {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-top-bar-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-top-bar-z-index {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-top-bar-actions-gap: var(--ui-top-bar-actions-gap);\n\n position: sticky;\n inset-block-start: 0;\n z-index: var(--ui-top-bar-z-index, 100);\n min-block-size: calc(var(--ui-top-bar-height, 56px) + env(safe-area-inset-top));\n display: flex;\n align-items: center;\n gap: var(--ui-top-bar-gap, var(--ui-space-3));\n padding-block-start: env(safe-area-inset-top);\n padding-inline-start: max(var(--ui-top-bar-padding-inline, var(--ui-space-4)), env(safe-area-inset-left));\n padding-inline-end: max(var(--ui-top-bar-padding-inline, var(--ui-space-4)), env(safe-area-inset-right));\n background: var(--ui-top-bar-surface, var(--ui-surface-elevated));\n border-block-end: 1px solid var(--ui-top-bar-border, var(--ui-border-default));\n }\n\n .leading,\n .search,\n .actions {\n display: flex;\n align-items: center;\n flex-shrink: 0;\n }\n\n .actions {\n gap: var(--_ui-top-bar-actions-gap, var(--ui-space-1));\n }\n\n .title {\n min-inline-size: 0;\n flex: 1;\n }\n\n /* An unused region takes no space, so it adds no gap. */\n .leading:empty,\n .search:empty,\n .actions:empty {\n display: none;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true,"name":"leading"},{"dynamic":false,"required":true},{"dynamic":false,"required":true,"name":"search"},{"dynamic":false,"required":true,"name":"actions"}],"root":{"kind":"native","element":"header","choices":["header"]}},{"source":{"file":"./components/ui-tree-item/ui-tree-item.html"},"contract":{"version":1,"name":"UiTreeItem","tag":"ui-tree-item","nativeElement":"div","props":{"accepts":{"type":"string","required":false,"target":{"attribute":"data-accepts"},"description":"A comma-separated list of the dragType values this branch accepts dropped inside it. Empty accepts any type. It does not affect drops before or after the\n item.","default":""},"container":{"type":"boolean","required":false,"target":{"attribute":"container"},"description":"Makes the item a branch even before it has children: it gets the expand button and aria-expanded, and accepts drops inside it. An item with nested items is\n a branch without it.","default":false},"disabled":{"type":"boolean","required":false,"target":{"attribute":"aria-disabled"},"description":"Makes the item unavailable: faded, skipped by keyboard navigation, unable to expand or be dragged, and closed to drops inside it.","default":false},"dragType":{"type":"string","required":false,"target":{"attribute":"data-drag-type"},"description":"The item's kind, for drag rules: it can be dropped before or after only items of the same type, and inside a branch only if that branch's accepts allows\n it. Reported as sourceType and targetType.","default":"item"},"dropDepth":{"type":"number","required":false,"target":{"attribute":"data-drop-depth"},"description":"Overrides the level this item counts as when the tree checks maxDepth for a drop onto it. Unset, its level in the rendered tree is used; set it when the\n item sits deeper in the real hierarchy than the rendered tree shows."},"dropScope":{"type":"string","required":false,"target":{"attribute":"data-drop-scope"},"description":"Names the list the item sits in, such as its parent's id, and is reported as sourceScope and targetScope in the tree's reorder events, so a handler can\n tell a reorder within one list from a move between lists. It never restricts where an item can be dropped; dragType and accepts do that.","default":""},"expanded":{"type":"boolean","required":false,"target":{"attribute":"expanded"},"description":"Whether the branch shows its children, initially or when set externally. The expand button, a click on the row, and the arrow keys toggle it from there,\n each reported as an expand event. Only meaningful for a branch.","default":false},"itemId":{"type":"string","required":false,"target":{"attribute":"data-item-id"},"description":"The item's identifier, reported as sourceId and targetId in the tree's reorder events and as id in its expand event. A sortable item needs one to be\n dragged, and a drop onto an item without one is not reported.","default":""},"label":{"type":"string","required":false,"target":{"attribute":"aria-label"},"description":"The item's accessible name, also shown as the row text unless the label slot supplies content.","default":""},"marquee":{"type":"boolean","required":false,"target":{"attribute":"marquee"},"description":"Scrolls a name too long for its row while the row is hovered or focused, then puts it back. Off by default: a tree of short names should not move, and a\n product decides whether reading the whole name matters more than a still list.","default":false},"selected":{"type":"boolean","required":false,"target":{"attribute":"aria-selected"},"description":"Marks the item selected: it sets aria-selected and gives the row the highlighted surface. The tree does not select on click, so drive it from your own\n state.","default":false},"sortable":{"type":"boolean","required":false,"target":{"attribute":"sortable"},"description":"Gives the item a drag handle, shown on hover, so it can be dragged to a new place in the tree. The tree reports the drop as a reorder event and leaves\n moving the item to you. Needs itemId; a disabled item, and any item under touch input, shows no handle.","default":false},"subtreeDepth":{"type":"number","required":false,"target":{"attribute":"data-subtree-depth"},"description":"Overrides how many levels sit beneath this item when the tree checks maxDepth for a drag of it. Unset, the tree counts the rendered descendants; set it\n when some are not rendered, such as children that load later."}}},"template":{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"role","value":"treeitem"},{"kind":"attribute","name":"aria-label","expression":"label","expressionPlan":{"source":"label","ast":{"kind":"id","name":"label"},"dependencies":["label"]}},{"kind":"attribute","name":"aria-level","expression":"structuralLevel","expressionPlan":{"source":"structuralLevel","ast":{"kind":"id","name":"structuralLevel"},"dependencies":["structuralLevel"]}},{"kind":"attribute","name":"aria-selected","expression":"selected","expressionPlan":{"source":"selected","ast":{"kind":"id","name":"selected"},"dependencies":["selected"]}},{"kind":"attribute","name":"aria-disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}},{"kind":"attribute","name":"data-item-id","expression":"itemId","expressionPlan":{"source":"itemId","ast":{"kind":"id","name":"itemId"},"dependencies":["itemId"]}},{"kind":"attribute","name":"data-drag-type","expression":"dragType","expressionPlan":{"source":"dragType","ast":{"kind":"id","name":"dragType"},"dependencies":["dragType"]}},{"kind":"attribute","name":"data-drop-scope","expression":"dropScope","expressionPlan":{"source":"dropScope","ast":{"kind":"id","name":"dropScope"},"dependencies":["dropScope"]}},{"kind":"attribute","name":"data-accepts","expression":"accepts","expressionPlan":{"source":"accepts","ast":{"kind":"id","name":"accepts"},"dependencies":["accepts"]}},{"kind":"attribute","name":"data-drop-depth","expression":"dropDepth","expressionPlan":{"source":"dropDepth","ast":{"kind":"id","name":"dropDepth"},"dependencies":["dropDepth"]}},{"kind":"attribute","name":"data-subtree-depth","expression":"subtreeDepth","expressionPlan":{"source":"subtreeDepth","ast":{"kind":"id","name":"subtreeDepth"},"dependencies":["subtreeDepth"]}}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"row"}],"children":[{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"class","value":"drag-handle"},{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"draggable","value":"true"},{"kind":"attribute","name":"aria-label","expression":"format('Drag %s to reorder', label)","expressionPlan":{"source":"format('Drag %s to reorder', label)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"Drag %s to reorder"},{"kind":"id","name":"label"}]},"dependencies":["label"]}}],"children":[{"kind":"element","name":"svg","attributes":[{"kind":"literal","name":"aria-hidden","value":"true"},{"kind":"literal","name":"focusable","value":"false"},{"kind":"literal","name":"viewBox","value":"0 0 24 24"},{"kind":"literal","name":"fill","value":"none"},{"kind":"literal","name":"stroke","value":"currentColor"},{"kind":"literal","name":"stroke-width","value":"2"},{"kind":"literal","name":"stroke-linecap","value":"round"},{"kind":"literal","name":"stroke-linejoin","value":"round"}],"children":[{"kind":"element","name":"circle","attributes":[{"kind":"literal","name":"cx","value":"9"},{"kind":"literal","name":"cy","value":"12"},{"kind":"literal","name":"r","value":"1"}],"children":[]},{"kind":"element","name":"circle","attributes":[{"kind":"literal","name":"cx","value":"9"},{"kind":"literal","name":"cy","value":"5"},{"kind":"literal","name":"r","value":"1"}],"children":[]},{"kind":"element","name":"circle","attributes":[{"kind":"literal","name":"cx","value":"9"},{"kind":"literal","name":"cy","value":"19"},{"kind":"literal","name":"r","value":"1"}],"children":[]},{"kind":"element","name":"circle","attributes":[{"kind":"literal","name":"cx","value":"15"},{"kind":"literal","name":"cy","value":"12"},{"kind":"literal","name":"r","value":"1"}],"children":[]},{"kind":"element","name":"circle","attributes":[{"kind":"literal","name":"cx","value":"15"},{"kind":"literal","name":"cy","value":"5"},{"kind":"literal","name":"r","value":"1"}],"children":[]},{"kind":"element","name":"circle","attributes":[{"kind":"literal","name":"cx","value":"15"},{"kind":"literal","name":"cy","value":"19"},{"kind":"literal","name":"r","value":"1"}],"children":[]}]}],"flow":{"kind":"if","test":"sortable and not disabled","testPlan":{"source":"sortable and not disabled","ast":{"kind":"binary","op":"and","left":{"kind":"id","name":"sortable"},"right":{"kind":"unary","op":"not","operand":{"kind":"id","name":"disabled"}}},"dependencies":["disabled","sortable"]}},"ref":"dragHandle"},{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"class","value":"disclosure"},{"kind":"literal","name":"type","value":"button"},{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}},{"kind":"attribute","name":"hidden","expression":"not isContainer","expressionPlan":{"source":"not isContainer","ast":{"kind":"unary","op":"not","operand":{"kind":"id","name":"isContainer"}},"dependencies":["isContainer"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"disclosure-icon"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[]}],"ref":"disclosure"},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"leading"}],"children":[{"kind":"slot","fallback":[],"name":"leading"}],"ref":"leading"},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"label"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"label-text"}],"children":[{"kind":"slot","fallback":[{"kind":"element","name":"template","attributes":[{"kind":"directive","name":"value","expression":"label","expressionPlan":{"source":"label","ast":{"kind":"id","name":"label"},"dependencies":["label"]}}],"children":[]}],"name":"label"}],"ref":"labelText"}],"ref":"label"},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"actions"}],"children":[{"kind":"slot","fallback":[],"name":"actions"}],"ref":"actions"},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"drop-indicator row-drop-indicator"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[]}],"ref":"row"},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"children"},{"kind":"literal","name":"role","value":"group"},{"kind":"attribute","name":"hidden","expression":"not (isContainer and internalExpanded)","expressionPlan":{"source":"not (isContainer and internalExpanded)","ast":{"kind":"unary","op":"not","operand":{"kind":"binary","op":"and","left":{"kind":"id","name":"isContainer"},"right":{"kind":"id","name":"internalExpanded"}}},"dependencies":["internalExpanded","isContainer"]}}],"children":[{"kind":"slot"}],"ref":"children"},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"drop-indicator subtree-drop-indicator"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[]}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-tree-item-depth {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-tree-item-font-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-tree-item-label-padding-block {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-tree-item-label-padding-inline {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-tree-item-min-block-size {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. The tree's density\n sets the defaults, in --_ui-default-*. */\n --_ui-tree-item-min-block-size: var(--ui-tree-item-min-block-size, var(--_ui-default-tree-item-min-block-size));\n --_ui-tree-item-font-size: var(--ui-tree-item-font-size, var(--_ui-default-tree-item-font-size));\n --_ui-tree-item-label-padding-block: var(--ui-tree-item-label-padding-block, var(--_ui-default-tree-item-label-padding-block));\n --_ui-tree-item-label-padding-inline: var(--ui-tree-item-label-padding-inline);\n\n --_tree-row-min-height: 32px;\n --_tree-disclosure-size: 16px;\n\n position: relative;\n display: block;\n min-inline-size: 0;\n margin-inline-start: calc(var(--ui-tree-item-depth, 0) * var(--_ui-tree-indent, 16px));\n }\n\n .row {\n position: relative;\n display: grid;\n grid-template-columns: var(--_tree-disclosure-size) auto minmax(0, 1fr);\n align-items: center;\n min-block-size: var(--_ui-tree-item-min-block-size, var(--_tree-row-min-height));\n min-inline-size: 0;\n font-size: var(--_ui-tree-item-font-size, var(--ui-font-size-sm));\n border-radius: var(--ui-radius-md);\n color: var(--ui-text-secondary);\n transition:\n background-color var(--ui-motion-fast) var(--ui-motion-ease),\n color var(--ui-motion-fast) var(--ui-motion-ease),\n opacity var(--ui-motion-fast) var(--ui-motion-ease),\n box-shadow var(--ui-motion-fast) var(--ui-motion-ease),\n min-block-size var(--ui-motion-base) var(--ui-motion-ease);\n }\n\n .row:hover,\n :host-state([selected]) .row,\n .row:focus-within {\n color: var(--ui-text-primary);\n background: var(--ui-surface-muted);\n }\n\n :host-state([disabled]) .row {\n opacity: 0.55;\n }\n\n :host[data-dragging] .row {\n opacity: 0.42;\n }\n\n :host:focus {\n outline: none;\n }\n\n :host:focus-visible .row {\n box-shadow: 0 0 0 2px var(--ui-focus-ring);\n }\n\n /* Child combinators: drop feedback belongs to this item's own row, not the rows nested in it. */\n :host[data-drop-position=\"inside\"] > .row {\n background: var(--ui-accent-subtle);\n box-shadow: inset 0 0 0 1px var(--_ui-tree-drop-color, var(--ui-accent-solid));\n }\n\n .disclosure,\n .disclosure-spacer {\n grid-column: 1;\n grid-row: 1;\n inline-size: var(--_tree-disclosure-size);\n block-size: 28px;\n }\n\n .disclosure {\n display: grid;\n /* Start-aligned: the chevron's ink, not its hit area, aligns with the content above it. */\n place-items: center start;\n padding: 0;\n color: var(--ui-text-muted);\n background: transparent;\n border: 0;\n border-radius: var(--ui-radius-sm);\n cursor: pointer;\n }\n\n .disclosure[hidden] {\n display: none;\n }\n\n .disclosure:hover {\n color: var(--ui-text-primary);\n background: var(--ui-surface-elevated);\n }\n\n .disclosure-icon {\n display: grid;\n place-items: center;\n inline-size: 12px;\n block-size: 12px;\n transform: rotate(-90deg);\n transition: transform var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n .disclosure-icon::before {\n display: block;\n inline-size: 0.375rem;\n block-size: 0.375rem;\n border-inline-end: 1.5px solid currentColor;\n border-block-end: 1.5px solid currentColor;\n content: \"\";\n /* A chevron's ink sits below its box centre; lift it so it centres optically (in either rotation). */\n transform: translateY(-20%) rotate(45deg);\n }\n\n :host[aria-expanded=\"true\"] .disclosure-icon {\n transform: rotate(0deg);\n }\n\n /* Lucide grip-vertical, filling the handle as in Looma 0.2. */\n .drag-handle svg {\n display: block;\n inline-size: 100%;\n block-size: 100%;\n }\n\n /* Slotted content is outside this scope, so :has() cannot see it; hide only a truly empty slot. */\n .leading {\n display: inline-grid;\n place-items: center;\n grid-column: 2;\n grid-row: 1;\n inline-size: 1em;\n block-size: 1em;\n margin-inline-start: var(--ui-space-1);\n color: var(--ui-text-muted);\n /* Above the label, so a sliding name passes under the icon. */\n position: relative;\n z-index: 1;\n }\n\n .leading:empty {\n display: none;\n }\n\n /* Icons match the label's size (as in Knit's tree): an unsized SVG would otherwise render 300×150. */\n :slotted(svg),\n :slotted(img) {\n display: block;\n inline-size: 1em;\n block-size: 1em;\n flex: none;\n }\n\n /* The label spans the row's height and centres its content, so slotted content (a link) can\n stretch to fill the row as its own hit area; the padding tokens remove the inset. */\n .label {\n grid-column: 3;\n grid-row: 1;\n align-self: stretch;\n display: flex;\n align-items: center;\n min-inline-size: 0;\n /* The cell clips: a name longer than the row slides inside it rather than over its icons. */\n overflow: hidden;\n padding: var(--_ui-tree-item-label-padding-block, var(--ui-space-1)) var(--_ui-tree-item-label-padding-inline, var(--ui-space-2));\n /* The length of the fade before the controls. The label's one flex child lays out no gap; this\n is where the controller reads the length in pixels to stop a sliding name before the fade. */\n column-gap: var(--ui-space-3);\n }\n\n /* Slotted label content fills the cell, so a link is the row's hit area rather than sizing to\n its own text and reading as overflow. */\n .label-text {\n display: flex;\n align-items: center;\n /* Stretches, so slotted content can still be the row's full-height hit area. */\n align-self: stretch;\n block-size: 100%;\n min-inline-size: 0;\n inline-size: 100%;\n white-space: nowrap;\n }\n\n .label-text > :slotted(*) {\n flex: 1 1 auto;\n min-inline-size: 0;\n }\n\n /* The controls sit over the label's end, so the text fades out where they begin. The fade is\n the truncation mark while it shows: an ellipsis under it would read as a second one. */\n .row:hover > .label,\n .row:focus-within > .label {\n text-overflow: clip;\n mask-image: linear-gradient(\n to right,\n #000 calc(100% - var(--_tree-actions-width, 1.75rem) - var(--ui-space-3)),\n transparent calc(100% - var(--_tree-actions-width, 1.75rem))\n );\n }\n\n .row:hover > .label:dir(rtl),\n .row:focus-within > .label:dir(rtl) {\n mask-image: linear-gradient(\n to left,\n #000 calc(100% - var(--_tree-actions-width, 1.75rem) - var(--ui-space-3)),\n transparent calc(100% - var(--_tree-actions-width, 1.75rem))\n );\n }\n\n /* A hovered row reads its whole name: the label slides far enough to show the end, waits\n there, and comes back. Only when it actually overflows — the controller measures by how\n much — after the controls have taken their place over its end — and hands over the distance\n and a duration from it, so every name moves at the same speed. */\n .row[data-ui-marquee] > .label > .label-text {\n /* Once, and it stays at the end while the pointer is there: a name that keeps sliding back\n and forth under the pointer is harder to read than one that arrives and holds. */\n animation: ui-tree-item-marquee var(--_marquee-duration) linear 0.5s 1 normal forwards;\n will-change: transform;\n }\n\n /* This comes after the hover fade, which it replaces at the same specificity. While the name\n slides, the label reaches back under the icon (the controller measures how far) with its text\n where it was, and fades out across that stretch, gone by the icon's middle: the name slips\n under the icon rather than stopping at a hard edge beside it. */\n .row[data-ui-marquee] > .label {\n margin-inline-start: calc(-1 * var(--_marquee-lead, 0px));\n padding-inline-start: calc(var(--_marquee-lead, 0px) + var(--_ui-tree-item-label-padding-inline, var(--ui-space-2)));\n mask-image: linear-gradient(\n to right,\n transparent calc(var(--_marquee-lead, 0px) / 2),\n #000 calc(var(--_marquee-lead, 0px) + var(--_ui-tree-item-label-padding-inline, var(--ui-space-2))),\n #000 calc(100% - var(--_tree-actions-width, 1.75rem) - var(--ui-space-3)),\n transparent calc(100% - var(--_tree-actions-width, 1.75rem))\n );\n }\n\n .row[data-ui-marquee] > .label:dir(rtl) {\n mask-image: linear-gradient(\n to left,\n transparent calc(var(--_marquee-lead, 0px) / 2),\n #000 calc(var(--_marquee-lead, 0px) + var(--_ui-tree-item-label-padding-inline, var(--ui-space-2))),\n #000 calc(100% - var(--_tree-actions-width, 1.75rem) - var(--ui-space-3)),\n transparent calc(100% - var(--_tree-actions-width, 1.75rem))\n );\n }\n\n @keyframes ui-tree-item-marquee {\n from {\n transform: translateX(0);\n }\n\n to {\n transform: translateX(var(--_marquee-distance));\n }\n }\n\n /* Reduced motion keeps the fade, which already says the name continues. */\n @media (prefers-reduced-motion: reduce) {\n .row[data-ui-marquee] > .label > .label-text {\n animation: none;\n }\n }\n\n .row:hover > .label > :slotted(*),\n .row:focus-within > .label > :slotted(*) {\n text-overflow: clip;\n }\n\n .actions {\n position: absolute;\n z-index: 1;\n inset-block: 0;\n inset-inline-end: 0;\n display: inline-flex;\n align-items: center;\n min-inline-size: 0;\n opacity: 0;\n pointer-events: none;\n transition: opacity var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n .row:hover > .actions,\n .row:focus-within > .actions {\n opacity: 1;\n pointer-events: auto;\n }\n\n /* Without hover there is no reveal, so the controls keep their own column. */\n @media (hover: none) {\n .row {\n grid-template-columns: var(--_tree-disclosure-size) auto minmax(0, 1fr) auto;\n }\n\n .actions {\n position: static;\n grid-column: 4;\n grid-row: 1;\n padding-inline-start: 0;\n background: none;\n opacity: 1;\n pointer-events: auto;\n }\n }\n\n /* The handle sits beside what it drags. A leaf row has no disclosure, so the handle takes that\n empty column, right before the icon; a branch's disclosure is there, so its handle sits just\n outside the row. It is bare until pointed at: a resting surface behind it read as a faint\n patch rather than as a control. */\n .drag-handle {\n position: absolute;\n z-index: 2;\n inset-block-start: 50%;\n inset-inline-start: 0;\n inline-size: var(--_tree-disclosure-size);\n block-size: 24px;\n display: grid;\n place-items: center;\n padding: 5px 2px;\n color: var(--ui-text-muted);\n background: transparent;\n border: 0;\n border-radius: var(--ui-radius-sm);\n cursor: grab;\n /* Hidden until the row is hovered, but always hittable: the handle sits outside the row, and moving\n the pointer onto it must not hide it on the way. */\n opacity: 0;\n transform: translateY(-50%);\n transition: opacity var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n .row:hover .drag-handle,\n .drag-handle:hover,\n .drag-handle:focus-visible,\n :host[data-dragging] > .row > .drag-handle {\n opacity: 1;\n }\n\n :host-state([isContainer]) > .row > .drag-handle {\n inset-inline-start: calc(-1 * var(--_tree-disclosure-size) - 2px);\n }\n\n .drag-handle:hover,\n .drag-handle:focus-visible {\n color: var(--ui-text-primary);\n background: var(--ui-surface-hover);\n }\n\n .drag-handle:active {\n cursor: grabbing;\n }\n\n .drop-indicator {\n position: absolute;\n z-index: 3;\n inset-inline: 1px;\n display: none;\n block-size: 2px;\n border-radius: 999px;\n background: var(--_ui-tree-drop-color, var(--ui-accent-solid));\n pointer-events: none;\n }\n\n .drop-indicator::before,\n .drop-indicator::after {\n content: \"\";\n position: absolute;\n inset-block-start: 50%;\n inline-size: 7px;\n block-size: 7px;\n border: 2px solid var(--_ui-tree-drop-color, var(--ui-accent-solid));\n border-radius: 999px;\n background: var(--ui-surface-elevated);\n transform: translateY(-50%);\n }\n\n .drop-indicator::before {\n inset-inline-start: -1px;\n }\n .drop-indicator::after {\n inset-inline-end: -1px;\n }\n\n :host[data-drop-position=\"before\"] > .row > .row-drop-indicator {\n display: block;\n inset-block-start: -1px;\n }\n\n :host[data-drop-position=\"after\"] > .subtree-drop-indicator {\n display: block;\n inset-block-end: -1px;\n }\n\n .children[hidden] {\n display: none;\n }\n\n html[data-ui-input-modality=\"touch\"] :host {\n --_tree-row-min-height: 44px;\n }\n\n html[data-ui-input-modality=\"touch\"] :host .drag-handle {\n display: none;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .row,\n .disclosure-icon,\n .drag-handle {\n transition: none;\n }\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"internalExpanded","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"structuralLevel","expression":{"source":"1","ast":{"kind":"literal","value":1},"dependencies":[]}},{"kind":"state","name":"tabStop","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"isContainer","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"event","name":"expand","type":"object({ id: string, expanded: boolean, trigger: keyboard | pointer | programmatic })","bubbles":false,"composed":true,"cancelable":false}],"slots":[{"dynamic":false,"required":true,"name":"leading"},{"dynamic":false,"required":false,"name":"label"},{"dynamic":false,"required":true,"name":"actions"},{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-tree-item/ui-tree-item.js"},{"source":{"file":"./components/ui-tree/ui-tree.html"},"contract":{"version":1,"name":"UiTree","tag":"ui-tree","nativeElement":"div","props":{"density":{"type":{"enum":["comfortable","compact"]},"required":false,"target":{"attribute":"density"},"description":"Compact trades padding and type size for rows that fit more on screen.","default":"comfortable"},"hoverExpandDelay":{"type":"number","required":false,"target":{"attribute":"hoverexpanddelay"},"description":"How long, in milliseconds, a dragged item must hover over the middle of a collapsed branch before the branch opens to receive it. 0 opens it at\n once.","default":700},"label":{"type":"string","required":false,"target":{"attribute":"label"},"description":"The tree's accessible name, announced when focus enters it. Name what the tree holds.","default":"Tree"},"marquee":{"type":"boolean","required":false,"target":{"attribute":"marquee"},"description":"Scrolls a name too long for its row while that row is hovered or focused, then puts it back. Off by default: a tree of names that fit should not move. An\n item may set its own marquee to opt in or out on its own.","default":false},"maxDepth":{"type":"number","required":false,"target":{"attribute":"maxdepth"},"description":"The deepest level a drag may produce, counting the top level as 1. A drop that would place the dragged item, or any item beneath it, deeper than this is\n refused and reported as reorder-rejected. 0 means no limit.","default":0}}},"template":{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"role","value":"tree"}],"children":[{"kind":"slot"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-tree-drop-color {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-tree-gutter {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-tree-indent {\n syntax: \"*\";\n inherits: false;\n }\n\n /* Reaches the items the way density does, so the setting lives on the tree the way a reader\n thinks about it: this list scrolls its long names. */\n :host-state([marquee]) {\n --_ui-default-tree-item-marquee: 1;\n }\n\n /* The items' defaults for this density: an item's own hook still wins. */\n :host-state([density=\"compact\"]) {\n --_ui-default-tree-item-min-block-size: var(--ui-control-size-sm);\n --_ui-default-tree-item-font-size: var(--ui-font-size-sm);\n --_ui-default-tree-item-label-padding-block: 0;\n }\n\n :host {\n /* Hooks do not inherit: the tree hands its own to its items here, and a tree nested in an item\n starts again from its own settings. */\n --_ui-tree-indent: var(--ui-tree-indent);\n --_ui-tree-drop-color: var(--ui-tree-drop-color);\n --_ui-default-tree-item-marquee: initial;\n --_ui-default-tree-item-min-block-size: initial;\n --_ui-default-tree-item-font-size: initial;\n --_ui-default-tree-item-label-padding-block: initial;\n display: block;\n min-inline-size: 0;\n padding-inline-start: var(--ui-tree-gutter, 0px);\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"event","name":"reorder","type":"object({ sourceId: string, targetId: string, position: before | inside | after, sourceType: string, targetType: string, sourceScope: string, targetScope: string, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"reorder-rejected","type":"object({ sourceId: string, targetId: string, position: before | inside | after, reason: max-depth, maxDepth: integer, resultingDepth: integer, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false}],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-tree/ui-tree.js"}];
|
|
3
|
+
export const definitions = [{"source":{"file":"./components/ui-action-bar/ui-action-bar.html"},"contract":{"version":1,"name":"UiActionBar","tag":"ui-action-bar","nativeElement":"div","props":{}},"template":{"kind":"element","name":"div","attributes":[],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"bar"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"tertiary"}],"children":[{"kind":"slot","fallback":[],"name":"tertiary"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"secondary"}],"children":[{"kind":"slot","fallback":[],"name":"secondary"},{"kind":"slot"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"primary"}],"children":[{"kind":"slot","fallback":[],"name":"primary"}]}]}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-action-bar-gap {\n syntax: \"*\";\n inherits: false;\n }\n\n /* The action row of a form or dialog. Tertiary actions (Back, Cancel, Discard) sit at the start\n edge; secondary actions (Save as draft, Preview) sit just before the primary one, which ends the\n row. The bar arranges its actions and leaves their look to them. */\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-action-bar-gap: var(--ui-action-bar-gap);\n\n --_gap: var(--ui-space-2);\n display: block;\n /* A size container sizes itself from its container, never its content. */\n container-type: inline-size;\n inline-size: 100%;\n min-inline-size: 0;\n }\n\n .bar,\n .tertiary,\n .secondary,\n .primary {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--_ui-action-bar-gap, var(--_gap));\n }\n\n /* The tertiary group takes the spare space, pushing the rest to the end edge; without it, the\n rest still ends the row. */\n .bar {\n justify-content: flex-end;\n }\n\n .tertiary {\n flex: 1 1 auto;\n }\n\n .tertiary:empty,\n .secondary:empty,\n .primary:empty {\n display: none;\n }\n\n /* A narrow container stacks the actions full width, primary on top: the row turned on its end,\n read from its end edge. Container queries cannot read custom properties, so the width is fixed. */\n @container (inline-size < 24rem) {\n .bar,\n .tertiary,\n .secondary,\n .primary {\n flex-direction: column-reverse;\n flex-wrap: nowrap;\n align-items: stretch;\n }\n\n .tertiary {\n flex: none;\n }\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true,"name":"tertiary"},{"dynamic":false,"required":true,"name":"secondary"},{"dynamic":false,"required":true},{"dynamic":false,"required":true,"name":"primary"}],"root":{"kind":"native","element":"div","choices":["div"]}},{"source":{"file":"./components/ui-affordance-scope/ui-affordance-scope.html"},"contract":{"version":1,"name":"UiAffordanceScope","tag":"ui-affordance-scope","nativeElement":"span","props":{"guide":{"type":{"enum":["dot","none"]},"required":false,"target":{"attribute":"guide"},"description":"What marks an anticipatory control at rest. dot shows a small guide dot where it will appear; none shows nothing until the pointer nears it, it is hovered,\n or it takes focus. Every guide inside the scope follows it, including a sidebar's resize line and the editor table's handles.","default":"dot"},"nearRadius":{"type":"number","required":false,"target":{"attribute":"nearradius"},"description":"How close, in pixels, the pointer must come to reveal an affordance.","default":16}}},"template":{"kind":"element","name":"span","attributes":[],"children":[{"kind":"slot"}]},"css":":host {\n display: contents;\n --ui-affordance-scope-engaged: 0;\n --ui-affordance-scope-guide: 1;\n }\n\n :host-state([engaged]) {\n --ui-affordance-scope-engaged: 1;\n }\n\n /* Published to descendants: each guide multiplies its opacity by it, so none reaches them all. */\n :host-state([guide=\"none\"]) {\n --ui-affordance-scope-guide: 0;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"engaged","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}}],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"span","choices":["span"]},"controller":"./components/ui-affordance-scope/ui-affordance-scope.js"},{"source":{"file":"./components/ui-avatar-group/ui-avatar-group.html"},"contract":{"version":1,"name":"UiAvatarGroup","tag":"ui-avatar-group","nativeElement":"div","props":{"label":{"type":"string","required":false,"target":{"attribute":"aria-label"},"description":"The group's accessible name, announced for the set of avatars as a whole. Name who they are rather than repeating the default.","default":"People"},"max":{"type":"number","required":false,"target":{"attribute":"max"},"description":"How many avatars to show. The rest are hidden and counted in a +N badge after the last visible one. Fractions round down, and 0 hides every avatar behind\n the badge.","default":5},"size":{"type":{"enum":["sm","md"]},"required":false,"target":{"attribute":"size"},"description":"The size of the avatars inside, matched by the +N badge and the overlap. Give each Avatar the same size.","default":"md"}}},"template":{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"role","value":"group"},{"kind":"attribute","name":"aria-label","expression":"label","expressionPlan":{"source":"label","ast":{"kind":"id","name":"label"},"dependencies":["label"]}}],"children":[{"kind":"slot"},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"overflow"},{"kind":"literal","name":"role","value":"img"},{"kind":"attribute","name":"hidden","expression":"not overflowCount","expressionPlan":{"source":"not overflowCount","ast":{"kind":"unary","op":"not","operand":{"kind":"id","name":"overflowCount"}},"dependencies":["overflowCount"]}},{"kind":"attribute","name":"aria-label","expression":"format('%s more', overflowCount)","expressionPlan":{"source":"format('%s more', overflowCount)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s more"},{"kind":"id","name":"overflowCount"}]},"dependencies":["overflowCount"]}}],"children":[{"kind":"element","name":"template","attributes":[{"kind":"directive","name":"value","expression":"format('+%s', overflowCount)","expressionPlan":{"source":"format('+%s', overflowCount)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"+%s"},{"kind":"id","name":"overflowCount"}]},"dependencies":["overflowCount"]}}],"children":[]}],"ref":"overflow"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-avatar-group-edge-ring {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-avatar-group-overlap-shadow {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-avatar-group-overlap-shadow: var(--ui-avatar-group-overlap-shadow);\n --_ui-avatar-group-edge-ring: var(--ui-avatar-group-edge-ring);\n\n /* Each avatar is ringed in the surface colour, so where one overlaps the next it reads as a\n * whole circle set on top, not a shape cut into the one beneath. */\n --_overlap-shadow: 0 0 0 0 transparent;\n --_edge-ring: 0 0 0 2px var(--ui-surface);\n\n display: flex;\n align-items: center;\n flex-direction: row;\n gap: 0;\n }\n\n /* Overlap and the separating shadow are applied by the controller: slotted avatars are nested\n * component roots outside this style scope. */\n :slotted(*) {\n margin-inline-start: -0.5rem;\n flex-shrink: 0;\n border-radius: 999px;\n }\n\n :slotted(*:first-child) {\n margin-inline-start: 0;\n }\n\n .overflow {\n margin-inline-start: -0.5rem;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n inline-size: 2.5rem;\n block-size: 2.5rem;\n border-radius: 999px;\n border: 1px solid var(--ui-border-strong);\n background: var(--ui-surface-elevated);\n color: var(--ui-text-primary);\n box-shadow:\n var(--_ui-avatar-group-overlap-shadow, var(--_overlap-shadow)),\n var(--_ui-avatar-group-edge-ring, var(--_edge-ring));\n font: inherit;\n font-size: var(--ui-font-size-xs);\n font-weight: 600;\n flex-shrink: 0;\n }\n\n :host-state([size=\"sm\"]) .overflow {\n margin-inline-start: -0.25rem;\n inline-size: 1.75rem;\n block-size: 1.75rem;\n }\n\n .overflow[hidden] {\n display: none;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"overflowCount","expression":{"source":"0","ast":{"kind":"literal","value":0},"dependencies":[]}}],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-avatar-group/ui-avatar-group.js"},{"source":{"file":"./components/ui-avatar/ui-avatar.html"},"contract":{"version":1,"name":"UiAvatar","tag":"ui-avatar","nativeElement":"span","props":{"active":{"type":"boolean","required":false,"target":{"attribute":"active"},"description":"Marks the person as active now, such as editing the same page: a ring in the success colour around the avatar. The ring is not announced, so say what it\n means in alt (\"Ada Lovelace, editing\").","default":false},"alt":{"type":"string","required":false,"target":{"attribute":"alt"},"description":"The avatar's accessible name, announced for it as an image. When empty, name is used, then \"Avatar\". Initials come from name first, so alt supplies them\n only when name is empty. An authored img carries its own alt instead.","default":""},"fallback":{"type":"string","required":false,"target":{"attribute":"fallback"},"description":"Text shown instead of the initials derived from name or alt, whenever there is no image. It is uppercased; keep it to a couple of characters, because the\n circle clips anything wider.","default":""},"name":{"type":"string","required":false,"target":{"attribute":"name"},"description":"The person's name. The initials are drawn from it: the first letters of the first two words, or the first two letters of a single word. It is also the\n accessible name when alt is empty.","default":""},"size":{"type":{"enum":["sm","md"]},"required":false,"target":{"attribute":"size"},"description":"md is 2.5rem, for a person on their own (a profile, a comment); sm is 1.75rem with smaller initials, for a row of people in a toolbar or header.","default":"md"},"src":{"type":"string","required":false,"target":{"attribute":"src"},"description":"The image to show, cropped to fill the circle. Until it loads, or if it fails, the avatar shows initials instead. An img element authored inside the avatar\n takes precedence over src."}}},"template":{"kind":"element","name":"span","attributes":[],"children":[{"kind":"slot"},{"kind":"element","name":"img","attributes":[{"kind":"literal","name":"class","value":"image"},{"kind":"attribute","name":"src","expression":"src","expressionPlan":{"source":"src","ast":{"kind":"id","name":"src"},"dependencies":["src"]}},{"kind":"literal","name":"alt","value":""},{"kind":"literal","name":"aria-hidden","value":"true"},{"kind":"attribute","name":"hidden","expression":"hasAuthoredImage or not hasImage","expressionPlan":{"source":"hasAuthoredImage or not hasImage","ast":{"kind":"binary","op":"or","left":{"kind":"id","name":"hasAuthoredImage"},"right":{"kind":"unary","op":"not","operand":{"kind":"id","name":"hasImage"}}},"dependencies":["hasAuthoredImage","hasImage"]}}],"children":[],"ref":"image"},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"fallback"},{"kind":"attribute","name":"aria-hidden","expression":"hasImage","expressionPlan":{"source":"hasImage","ast":{"kind":"id","name":"hasImage"},"dependencies":["hasImage"]}},{"kind":"attribute","name":"hidden","expression":"hasImage","expressionPlan":{"source":"hasImage","ast":{"kind":"id","name":"hasImage"},"dependencies":["hasImage"]}},{"kind":"directive","name":"value","expression":"initials","expressionPlan":{"source":"initials","ast":{"kind":"id","name":"initials"},"dependencies":["initials"]}}],"children":[]}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-avatar-border {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-avatar-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-avatar-text {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-avatar-active-ring {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n display: inline-grid;\n place-items: center;\n overflow: hidden;\n inline-size: 2.5rem;\n block-size: 2.5rem;\n border-radius: 999px;\n border: 1px solid var(--ui-avatar-border, var(--ui-border-strong));\n background: var(--ui-avatar-surface, var(--ui-accent-soft));\n color: var(--ui-avatar-text, var(--ui-accent-subtle-text, var(--ui-accent-solid)));\n font: inherit;\n font-size: var(--ui-font-size-sm);\n font-weight: 600;\n text-transform: uppercase;\n }\n\n :host-state([size=\"sm\"]) {\n inline-size: 1.75rem;\n block-size: 1.75rem;\n font-size: var(--ui-font-size-xs);\n }\n\n /* An outline, not a dot: the avatar clips its content to the circle, and an outline is drawn\n outside the box, so the ring survives the clip and the overlap in an Avatar Group. */\n :host-state([active]) {\n outline: 2px solid var(--ui-avatar-active-ring, var(--ui-success));\n outline-offset: 1px;\n }\n\n .image,\n :slotted(img) {\n grid-area: 1 / 1;\n inline-size: 100%;\n block-size: 100%;\n object-fit: cover;\n }\n\n .fallback {\n grid-area: 1 / 1;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n inline-size: 100%;\n block-size: 100%;\n }\n\n /* Centre the glyphs, not the line box: a label without descenders otherwise reads high. */\n /* Centre the glyphs, not the line box: a label without descenders otherwise reads high.\n * Trimming applies to block containers, so the box is a block with centred content. */\n @supports (text-box-trim: trim-both) {\n .fallback {\n display: block;\n text-align: center;\n align-content: center;\n text-box-trim: trim-both;\n text-box-edge: cap alphabetic;\n }\n }\n\n [hidden] {\n display: none;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"hasImage","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"hasAuthoredImage","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"initials","expression":{"source":"'?'","ast":{"kind":"literal","value":"?"},"dependencies":[]}}],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"span","choices":["span"]},"controller":"./components/ui-avatar/ui-avatar.js"},{"source":{"file":"./components/ui-badge/ui-badge.html"},"contract":{"version":1,"name":"UiBadge","tag":"ui-badge","nativeElement":"span","props":{"shape":{"type":{"enum":["pill","tag"]},"required":false,"target":{"attribute":"shape"},"description":"Silhouette. pill is rounded at both ends; tag is a label: flat at the start and coming to a point at the end, for a tag or a chosen chip.","default":"pill"},"tone":{"type":{"enum":["neutral","accent","info","success","warning","danger"]},"required":false,"target":{"attribute":"tone"},"description":"Which colour the badge speaks in. neutral is a quiet grey for plain labels; accent draws the eye in the accent colour; info, success, warning, and danger\n mark a status, so match the tone to what the badge says.","default":"neutral"},"variant":{"type":{"enum":["solid","subtle"]},"required":false,"target":{"attribute":"variant"},"description":"Emphasis. subtle sets the text in its tone over a soft wash of it; solid fills with the tone and uses contrasting text, for a status that has to stand out.\n The neutral tone looks the same in both.","default":"subtle"}}},"template":{"kind":"element","name":"span","attributes":[],"children":[{"kind":"slot"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-badge-border {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-badge-font-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-badge-font-weight {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-badge-line-height {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-badge-min-block-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-badge-padding-block {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-badge-padding-inline {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-badge-point {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-badge-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-badge-text {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n --_badge-surface: var(--ui-surface-subtle);\n --_badge-text: var(--ui-text-secondary);\n /* Every tone's edge is its fill, so it is unseen until forced colors draw it. */\n --_badge-border: var(--ui-surface-subtle);\n\n display: inline-flex;\n align-items: center;\n justify-content: center;\n max-width: 100%;\n padding: var(--ui-badge-padding-block, var(--ui-space-0-5)) var(--ui-badge-padding-inline, var(--ui-space-2));\n border: 1px solid var(--ui-badge-border, var(--_badge-border));\n border-radius: var(--ui-radius-round);\n background: var(--ui-badge-surface, var(--_badge-surface));\n color: var(--ui-badge-text, var(--_badge-text));\n font-family: var(--ui-font-family-sans);\n font-size: var(--ui-badge-font-size, var(--ui-font-size-sm));\n font-weight: var(--ui-badge-font-weight, var(--ui-font-medium));\n line-height: var(--ui-badge-line-height, var(--ui-line-height-tight));\n white-space: nowrap;\n }\n\n /* Centre the glyphs, not the line box: a label without descenders otherwise reads high.\n * Trimming applies to block containers; an inline-block is one and, like the inline-flex it\n * replaces, still sizes to its label rather than filling its container. */\n @supports (text-box-trim: trim-both) {\n :host {\n display: inline-block;\n min-block-size: var(--ui-badge-min-block-size, 1.5rem);\n text-align: center;\n align-content: center;\n text-box-trim: trim-both;\n text-box-edge: cap alphabetic;\n }\n }\n\n :host-state([tone=\"accent\"]) {\n --_badge-surface: var(--ui-accent-strong-surface, var(--ui-accent-solid));\n --_badge-border: var(--ui-accent-strong-surface, var(--ui-accent-solid));\n --_badge-text: var(--ui-accent-on-strong, var(--ui-text-on-accent));\n }\n\n :host-state([tone=\"danger\"]) {\n --_badge-surface: var(--ui-danger-strong-surface, var(--ui-danger-solid));\n --_badge-border: var(--ui-danger-strong-surface, var(--ui-danger-solid));\n --_badge-text: var(--ui-danger-on-strong, var(--ui-text-on-accent));\n }\n\n :host-state([tone=\"success\"]) {\n --_badge-surface: var(--ui-success-strong-surface, var(--ui-success-solid));\n --_badge-border: var(--ui-success-strong-surface, var(--ui-success-solid));\n --_badge-text: var(--ui-success-on-strong, var(--ui-text-on-accent));\n }\n\n :host-state([tone=\"warning\"]) {\n --_badge-surface: var(--ui-warning-strong-surface, var(--ui-warning-solid));\n --_badge-border: var(--ui-warning-strong-surface, var(--ui-warning-solid));\n --_badge-text: var(--ui-warning-on-strong, var(--ui-text-on-accent));\n }\n\n :host-state([tone=\"info\"]) {\n --_badge-surface: var(--ui-info-strong-surface, var(--ui-info-solid));\n --_badge-border: var(--ui-info-strong-surface, var(--ui-info-solid));\n --_badge-text: var(--ui-info-on-strong, var(--ui-text-on-accent));\n }\n\n :host-state([variant=\"subtle\"][tone=\"accent\"]) {\n --_badge-surface: var(--ui-accent-soft);\n --_badge-border: var(--ui-accent-soft);\n --_badge-text: var(--ui-accent-subtle-text, var(--ui-accent-solid));\n }\n\n :host-state([variant=\"subtle\"][tone=\"danger\"]) {\n --_badge-surface: var(--ui-danger-soft);\n --_badge-border: var(--ui-danger-soft);\n --_badge-text: var(--ui-danger-subtle-text, var(--ui-danger-solid));\n }\n\n :host-state([variant=\"subtle\"][tone=\"success\"]) {\n --_badge-surface: var(--ui-success-soft);\n --_badge-border: var(--ui-success-soft);\n --_badge-text: var(--ui-success-subtle-text, var(--ui-success-solid));\n }\n\n :host-state([variant=\"subtle\"][tone=\"warning\"]) {\n --_badge-surface: var(--ui-warning-soft);\n --_badge-border: var(--ui-warning-soft);\n --_badge-text: var(--ui-warning-subtle-text, var(--ui-warning-solid));\n }\n\n :host-state([variant=\"subtle\"][tone=\"info\"]) {\n --_badge-surface: var(--ui-info-soft);\n --_badge-border: var(--ui-info-soft);\n --_badge-text: var(--ui-info-subtle-text, var(--ui-info-solid));\n }\n\n /* A tag is flat at the start and points at the end. The point is cut from the box, so it has no\n outline to follow: the edge is the fill. The end padding grows by the point's depth so the\n label never runs into it. */\n :host-state([shape=\"tag\"]) {\n --_badge-point: var(--ui-badge-point, var(--ui-space-2));\n\n border-color: transparent;\n border-radius: 0;\n padding-inline-end: calc(var(--ui-badge-padding-inline, var(--ui-space-2)) + var(--_badge-point));\n clip-path: polygon(0 0, calc(100% - var(--_badge-point)) 0, 100% 50%, calc(100% - var(--_badge-point)) 100%, 0 100%);\n }\n\n :host-state([shape=\"tag\"]):dir(rtl) {\n padding-inline-end: var(--ui-badge-padding-inline, var(--ui-space-2));\n padding-inline-start: calc(var(--ui-badge-padding-inline, var(--ui-space-2)) + var(--_badge-point));\n clip-path: polygon(var(--_badge-point) 0, 100% 0, 100% 100%, var(--_badge-point) 100%, 0 50%);\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"span","choices":["span"]}},{"source":{"file":"./components/ui-breadcrumb-item/ui-breadcrumb-item.html"},"contract":{"version":1,"name":"UiBreadcrumbItem","tag":"ui-breadcrumb-item","nativeElement":"li","props":{"current":{"type":"boolean","required":false,"target":{"attribute":"current"},"description":"Marks the step as the view you are on: it is plain text with aria-current=\"page\". Every other step holds a link.","default":false}}},"template":{"kind":"element","name":"li","attributes":[{"kind":"attribute","name":"aria-current","expression":"{ true: 'page', false: null }[format('%s', current)]","expressionPlan":{"source":"{ true: 'page', false: null }[format('%s', current)]","ast":{"kind":"index","object":{"kind":"object","pairs":[{"key":"true","value":{"kind":"literal","value":"page"}},{"key":"false","value":{"kind":"literal","value":null}}]},"index":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s"},{"kind":"id","name":"current"}]}},"dependencies":["current"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"separator"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[{"kind":"element","name":"ui-icon","attributes":[{"kind":"literal","name":"name","value":"chevron-right"}],"children":[]}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"content"}],"children":[{"kind":"slot"}]}]},"css":"/* One step in a ui-breadcrumbs trail: a link up to that place, or the current view. A chevron leads\n every step but the first. An icon slotted before the name sits with it. */\n :host {\n display: inline-flex;\n align-items: center;\n gap: var(--ui-space-2);\n min-inline-size: 0;\n }\n\n .separator {\n display: inline-flex;\n color: var(--ui-text-muted);\n font-size: var(--ui-font-size-xs);\n }\n\n :host:first-child .separator {\n display: none;\n }\n\n .content {\n display: inline-flex;\n align-items: center;\n gap: var(--ui-space-1);\n min-inline-size: 0;\n }\n\n .content > :slotted(a) {\n display: inline-flex;\n align-items: center;\n gap: var(--ui-space-1);\n color: var(--ui-text-secondary);\n text-decoration: none;\n }\n\n .content > :slotted(a:hover) {\n color: var(--ui-text-primary);\n text-decoration: underline;\n }\n\n :host-state([current]) .content {\n color: var(--ui-text-primary);\n font-weight: var(--ui-font-medium);\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"li","choices":["li"]}},{"source":{"file":"./components/ui-breadcrumbs/ui-breadcrumbs.html"},"contract":{"version":1,"name":"UiBreadcrumbs","tag":"ui-breadcrumbs","nativeElement":"nav","props":{"label":{"type":"string","required":false,"target":{"attribute":"aria-label"},"description":"The navigation landmark's accessible name.","default":"Breadcrumb"}}},"template":{"kind":"element","name":"nav","attributes":[{"kind":"attribute","name":"aria-label","expression":"label","expressionPlan":{"source":"label","ast":{"kind":"id","name":"label"},"dependencies":["label"]}}],"children":[{"kind":"element","name":"ol","attributes":[{"kind":"literal","name":"role","value":"list"}],"children":[{"kind":"slot"}]}]},"css":"/* Where a view sits: a trail of ui-breadcrumb-item, from the top down to the current view. It wraps\n rather than scrolls, so every step stays reachable. */\n :host {\n display: block;\n min-inline-size: 0;\n color: var(--ui-text-muted);\n font-size: var(--ui-font-size-sm);\n }\n\n ol {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--ui-space-1) var(--ui-space-2);\n margin: 0;\n padding: 0;\n list-style: none;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"nav","choices":["nav"]}},{"source":{"file":"./components/ui-button/ui-button.html"},"contract":{"version":1,"name":"UiButton","tag":"ui-button","nativeElement":"button","props":{"align":{"type":{"enum":["center","start"]},"required":false,"target":{"attribute":"align"},"description":"Content alignment. start lays the content out like a list option: from the start edge, with start-aligned text.","default":"center"},"as":{"type":{"enum":["button","a"]},"required":false,"target":{"attribute":"as"},"description":"The native element the button renders: a button, or a link (a) that navigates to href.","default":"button"},"disabled":{"type":"boolean","required":false,"target":{"attribute":"disabled"},"description":"Makes the button unavailable: it cannot be pressed, its tone fades, and it loses its raised look. A disabled link (as=\"a\" with href) drops its href and\n states aria-disabled=\"true\" instead, because a link has no native disabled state.","default":false},"href":{"type":"string","required":false,"target":{"attribute":"href"},"description":"The link's destination. Pair it with as=\"a\" so the button renders as a real link that navigates. A disabled link drops its href and states\n aria-disabled=\"true\", so it cannot be followed."},"rel":{"type":"string","required":false,"target":{"attribute":"rel"},"description":"The link's relationship to its destination, as on a native link. Only meaningful with as=\"a\"."},"size":{"type":{"enum":["sm","md","lg"]},"required":false,"target":{"attribute":"size"},"description":"Height, padding, and type size. sm is the small control height (2rem by default) with tighter padding and smaller text, md is the standard control height\n (2.5rem), and lg is taller (3rem) with roomier padding.","default":"md"},"stretch":{"type":"boolean","required":false,"target":{"attribute":"stretch"},"description":"Fills the inline size of its container.","default":false},"target":{"type":"string","required":false,"target":{"attribute":"target"},"description":"Where a link opens, as on a native link. Only meaningful with as=\"a\"."},"tone":{"type":{"enum":["accent","neutral","danger","success","warning","info"]},"required":false,"target":{"attribute":"tone"},"description":"Which colour the button speaks in. It applies to every variant, so an outline, a ghost, and a solid in the same tone are the same action at three volumes:\n tone=\"danger\" variant=\"outline\" is a destructive secondary action. neutral is the quiet one, for a button that should not claim a colour.","default":"accent"},"type":{"type":{"enum":["button","submit","reset"]},"required":false,"target":{"attribute":"type"},"description":"The button's type, as on a native button. button by default, so it never submits a form by accident. A link has no type.","default":"button"},"variant":{"type":{"enum":["outline","solid","danger","ghost","link"]},"required":false,"target":{"attribute":"variant"},"description":"Emphasis: how loudly the button asks. solid fills with its tone, outline draws its tone at the edge over a wash of it, ghost carries only text until it is\n hovered, and link is an inline text action that reads as a link. danger is solid in the danger tone, kept for the call sites that name it.","default":"outline"}}},"template":{"kind":"element","name":"template","attributes":[],"children":[{"kind":"element","name":"a","attributes":[{"kind":"attribute","name":"href","expression":"{ true: null, false: href }[format('%s', disabled)]","expressionPlan":{"source":"{ true: null, false: href }[format('%s', disabled)]","ast":{"kind":"index","object":{"kind":"object","pairs":[{"key":"true","value":{"kind":"literal","value":null}},{"key":"false","value":{"kind":"id","name":"href"}}]},"index":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s"},{"kind":"id","name":"disabled"}]}},"dependencies":["disabled","href"]}},{"kind":"attribute","name":"target","expression":"target","expressionPlan":{"source":"target","ast":{"kind":"id","name":"target"},"dependencies":["target"]}},{"kind":"attribute","name":"rel","expression":"rel","expressionPlan":{"source":"rel","ast":{"kind":"id","name":"rel"},"dependencies":["rel"]}},{"kind":"attribute","name":"aria-disabled","expression":"{ true: 'true', false: null }[format('%s', disabled and href)]","expressionPlan":{"source":"{ true: 'true', false: null }[format('%s', disabled and href)]","ast":{"kind":"index","object":{"kind":"object","pairs":[{"key":"true","value":{"kind":"literal","value":"true"}},{"key":"false","value":{"kind":"literal","value":null}}]},"index":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s"},{"kind":"binary","op":"and","left":{"kind":"id","name":"disabled"},"right":{"kind":"id","name":"href"}}]}},"dependencies":["disabled","href"]}}],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'a'","testPlan":{"source":"as = 'a'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"a"}},"dependencies":["as"]}}},{"kind":"element","name":"button","attributes":[{"kind":"attribute","name":"type","expression":"type","expressionPlan":{"source":"type","ast":{"kind":"id","name":"type"},"dependencies":["type"]}},{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}}],"children":[{"kind":"slot"}],"flow":{"kind":"else"}}],"flow":{"kind":"match"}},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-button-active-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-button-border {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-button-disabled-filter {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-button-disabled-opacity {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-button-ghost-active-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-button-ghost-hover-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-button-ghost-text {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-button-hover-border {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-button-hover-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-button-link-hover-text {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-button-link-text {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-button-min-block-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-button-radius {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-button-shadow {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-button-solid-shadow {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-button-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-button-text {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n --_hue: var(--ui-accent);\n --_hue-hover: var(--ui-accent-hover);\n --_hue-active: var(--ui-accent-active);\n --_hue-text: var(--ui-accent-active);\n --_on-hue: var(--ui-on-accent);\n\n --_tone: var(--_hue);\n --_tone-hover: var(--_hue-hover);\n --_tone-active: var(--_hue-active);\n --_tone-text: var(--_hue-text);\n --_on-tone: var(--_on-hue);\n\n display: inline-flex;\n align-items: center;\n justify-content: center;\n vertical-align: middle;\n color: var(--_tone-text);\n }\n\n :host-state([align=\"start\"]) {\n justify-content: flex-start;\n text-align: start;\n }\n\n :host-state([stretch]) {\n display: flex;\n inline-size: 100%;\n }\n\n :host {\n appearance: none;\n min-block-size: var(--ui-button-min-block-size, var(--ui-control-size-md));\n border-style: solid;\n border-width: 1px;\n border-color: var(--ui-button-border, var(--_tone));\n border-radius: var(--ui-button-radius, var(--ui-radius-md));\n background-color: var(--ui-button-surface, oklch(from var(--_tone) l c h / 5%));\n color: var(--ui-button-text, var(--_tone-text));\n font: inherit;\n font-weight: var(--ui-font-medium);\n text-decoration: none;\n line-height: var(--ui-line-height-tight);\n padding: var(--ui-space-2) var(--ui-space-3);\n background-image: var(--ui-raised-highlight);\n box-shadow: var(--ui-button-shadow, var(--ui-raised));\n cursor: pointer;\n transition:\n background-color var(--ui-motion-fast) var(--ui-motion-ease),\n border-color var(--ui-motion-fast) var(--ui-motion-ease),\n color var(--ui-motion-fast) var(--ui-motion-ease),\n box-shadow var(--ui-motion-fast) var(--ui-motion-ease);\n margin: 0;\n }\n\n @supports (text-box-trim: trim-both) {\n :host {\n text-box-trim: trim-both;\n text-box-edge: cap alphabetic;\n }\n }\n\n :host-state([size=\"sm\"]) {\n min-block-size: var(--ui-control-size-sm);\n padding: var(--ui-space-1) var(--ui-space-2);\n font-size: var(--ui-font-size-sm);\n }\n\n :host-state([size=\"lg\"]) {\n min-block-size: var(--ui-control-size-lg);\n padding: var(--ui-space-3) var(--ui-space-4);\n font-size: var(--ui-font-size-md);\n }\n\n /* A link is never :enabled, so interactive states test \"not unavailable\" instead: for a button that\n is exactly :enabled, at the same specificity, and it also matches a link that can be followed. */\n :host:hover:not(:disabled, [aria-disabled=\"true\"]) {\n border-color: var(--ui-button-hover-border, var(--_tone-hover));\n background-color: var(--ui-button-hover-surface, oklch(from var(--_tone) l c h / 12%));\n }\n\n /* Pressed reads as pressed in: the highlight goes, and the shadow moves inside. */\n :host:active:not(:disabled, [aria-disabled=\"true\"]) {\n background-color: var(--ui-button-active-surface, oklch(from var(--_tone) l c h / 18%));\n background-image: none;\n box-shadow: var(--ui-pressed);\n }\n\n :host-state([variant=\"solid\"]), :host-state([variant=\"danger\"]) {\n border-color: var(--_tone);\n background-color: var(--_tone);\n color: var(--_on-tone);\n box-shadow: var(--ui-button-solid-shadow, var(--ui-raised));\n }\n\n :is(:host-state([variant=\"solid\"]), :host-state([variant=\"danger\"])):hover:not(:disabled, [aria-disabled=\"true\"]) {\n background-color: var(--_tone-hover);\n border-color: var(--_tone-hover);\n }\n\n :is(:host-state([variant=\"solid\"]), :host-state([variant=\"danger\"])):active:not(:disabled, [aria-disabled=\"true\"]) {\n background-color: var(--_tone-active);\n border-color: var(--_tone-active);\n background-image: none;\n box-shadow: var(--ui-pressed);\n }\n\n /* Tone is the colour, variant is the volume. Every pairing works: a danger outline is a\n destructive secondary action, not a special case. */\n :host-state([tone=\"neutral\"]) {\n --_hue: var(--ui-text);\n --_hue-hover: var(--ui-text);\n --_hue-active: var(--ui-text);\n --_hue-text: var(--ui-text);\n --_on-hue: var(--ui-surface);\n }\n\n :host-state([tone=\"danger\"]), :host-state([variant=\"danger\"]) {\n --_hue: var(--ui-danger);\n --_hue-hover: var(--ui-danger-hover);\n --_hue-active: var(--ui-danger-hover);\n --_hue-text: var(--ui-danger-hover);\n --_on-hue: var(--ui-on-danger);\n }\n\n :host-state([tone=\"success\"]) {\n --_hue: var(--ui-success);\n --_hue-hover: color-mix(in srgb, var(--ui-success) 85%, #000);\n --_hue-active: color-mix(in srgb, var(--ui-success) 75%, #000);\n --_hue-text: color-mix(in srgb, var(--ui-success) 85%, #000);\n --_on-hue: var(--ui-surface);\n }\n\n :host-state([tone=\"warning\"]) {\n --_hue: var(--ui-warning);\n --_hue-hover: color-mix(in srgb, var(--ui-warning) 85%, #000);\n --_hue-active: color-mix(in srgb, var(--ui-warning) 75%, #000);\n --_hue-text: color-mix(in srgb, var(--ui-warning) 85%, #000);\n --_on-hue: var(--ui-surface);\n }\n\n :host-state([tone=\"info\"]) {\n --_hue: var(--ui-info);\n --_hue-hover: color-mix(in srgb, var(--ui-info) 85%, #000);\n --_hue-active: color-mix(in srgb, var(--ui-info) 75%, #000);\n --_hue-text: color-mix(in srgb, var(--ui-info) 85%, #000);\n --_on-hue: var(--ui-surface);\n }\n\n :host-state([variant=\"ghost\"]) {\n border-color: transparent;\n background: transparent;\n box-shadow: none;\n color: var(--ui-button-ghost-text, var(--_tone-text));\n }\n\n /* Tints derive from the text colour, not a surface token, so hover and press show on any background. */\n :host-state([variant=\"ghost\"]):hover:not(:disabled, [aria-disabled=\"true\"]) {\n background-color: var(--ui-button-ghost-hover-surface, oklch(from var(--_tone) l c h / 10%));\n border-color: transparent;\n }\n\n :host-state([variant=\"ghost\"]):active:not(:disabled, [aria-disabled=\"true\"]) {\n background-color: var(--ui-button-ghost-active-surface, oklch(from var(--_tone) l c h / 16%));\n border-color: transparent;\n box-shadow: var(--ui-pressed);\n }\n\n /* A soft halo that transitions in with the other box-shadow changes, layered on the raised shadow. */\n :host:focus-visible {\n outline: none;\n box-shadow:\n var(--ui-button-shadow, var(--ui-raised)),\n var(--ui-focus-halo);\n }\n\n :host-state([variant=\"solid\"]):focus-visible {\n box-shadow:\n var(--ui-button-solid-shadow, var(--ui-raised)),\n var(--ui-focus-halo);\n }\n\n /* Disabled keeps the shape and washes out the rest: every variant keeps its own structure, so a\n disabled outline is still an outline and a disabled ghost still has no edge. One filter fades\n fill, border, and text together (--ui-disabled-filter), and the theme decides which way is\n toward the page. The highlight and shadow go, because nothing that cannot be pressed should\n look raised. */\n :host:is(:disabled, [aria-disabled=\"true\"]) {\n filter: var(--ui-button-disabled-filter, var(--ui-disabled-filter));\n opacity: var(--ui-button-disabled-opacity, 1);\n cursor: not-allowed;\n background-image: none;\n box-shadow: none;\n }\n\n /* Ghost has no hover to fall back on, so disabled is the one state it has to state outright:\n it takes a surface rather than reading as plain text. The surface is a wash of the faded tone,\n the way hover washes the live one, so it stays light in every tone. An opaque mix toward the\n hue came out a mid-grey slab for neutral, whose hue is the ink: louder than the enabled button. */\n :host-state([variant=\"ghost\"]):is(:disabled, [aria-disabled=\"true\"]) {\n background-color: oklch(from var(--_tone) l c h / 14%);\n border-color: transparent;\n }\n\n @media (pointer: coarse) {\n :host {\n min-block-size: var(--ui-control-min-block-size);\n }\n }\n\n /* Under touch, a link-style button's press lands within the control minimum: an invisible hit\n area, centred on it, like IconButton's. A boxed button grows to the minimum itself (below);\n a link-style one keeps its text size, so a standalone one (\"See all\" under a list) needs the\n area. Only the link needs it: a hit area on every button would reach over its neighbours. */\n html[data-ui-input-modality=\"touch\"] :host-state([variant=\"link\"]) {\n position: relative;\n }\n\n html[data-ui-input-modality=\"touch\"] :host-state([variant=\"link\"])::after {\n position: absolute;\n inset: 50% auto auto 50%;\n inline-size: max(100%, var(--ui-control-min-block-size));\n block-size: max(100%, var(--ui-control-min-block-size));\n transform: translate(-50%, -50%);\n content: \"\";\n }\n\n /* Link: an inline text action. No box, padding, or minimum height (inline targets are exempt under\n WCAG 2.5.8); the inherited font; an underline that strengthens on hover; a visible focus ring. */\n :host-state([variant=\"link\"]) {\n display: inline;\n min-block-size: 0;\n padding: 0;\n border: 0;\n border-radius: var(--ui-radius-sm);\n background: none;\n box-shadow: none;\n font: inherit;\n color: var(--ui-button-link-text, var(--ui-text-secondary));\n text-decoration-line: underline;\n text-decoration-thickness: 1px;\n text-decoration-color: color-mix(in srgb, currentColor 40%, transparent);\n text-underline-offset: 0.2em;\n transition: color var(--ui-motion-fast) var(--ui-motion-ease), text-decoration-color var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n :host-state([variant=\"link\"]):hover:not(:disabled, [aria-disabled=\"true\"]) {\n color: var(--ui-button-link-hover-text, var(--ui-text-primary));\n text-decoration-color: currentColor;\n background: none;\n transform: none;\n }\n\n :host-state([variant=\"link\"]):active:not(:disabled, [aria-disabled=\"true\"]) {\n background: none;\n transform: none;\n }\n\n :host-state([variant=\"link\"]):is(:disabled, [aria-disabled=\"true\"]) {\n background: none;\n border-color: transparent;\n }\n\n :host-state([variant=\"link\"]):focus-visible {\n box-shadow: none;\n /* Fallback keeps the ring if the token is missing: an unresolved var() would void the outline. */\n outline: 2px solid var(--ui-focus-ring);\n outline-offset: 2px;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"button","choices":["a","button"]}},{"source":{"file":"./components/ui-callout/ui-callout.html"},"contract":{"version":1,"name":"UiCallout","tag":"ui-callout","nativeElement":"div","props":{"tone":{"type":{"enum":["info","note","warning","success","danger"]},"required":false,"target":{"attribute":"tone"},"description":"Which kind of message the callout carries, shown by its icon and colour: info (the default) for neutral information, note for an aside in muted grey,\n warning for a caution, success for a confirmation, and danger for an error or a destructive consequence.","default":"info"}}},"template":{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"role","value":"note"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"icon"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[{"kind":"element","name":"svg","attributes":[{"kind":"literal","name":"viewBox","value":"0 0 24 24"},{"kind":"literal","name":"fill","value":"none"},{"kind":"literal","name":"stroke","value":"currentColor"},{"kind":"literal","name":"stroke-width","value":"2"},{"kind":"literal","name":"stroke-linecap","value":"round"},{"kind":"literal","name":"stroke-linejoin","value":"round"}],"children":[{"kind":"element","name":"circle","attributes":[{"kind":"literal","name":"cx","value":"12"},{"kind":"literal","name":"cy","value":"12"},{"kind":"literal","name":"r","value":"10"}],"children":[]},{"kind":"element","name":"path","attributes":[{"kind":"literal","name":"d","value":"M12 16v-4"}],"children":[]},{"kind":"element","name":"path","attributes":[{"kind":"literal","name":"d","value":"M12 8h.01"}],"children":[]}],"flow":{"kind":"if","test":"tone = 'info'","testPlan":{"source":"tone = 'info'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"tone"},"right":{"kind":"literal","value":"info"}},"dependencies":["tone"]}}},{"kind":"element","name":"svg","attributes":[{"kind":"literal","name":"viewBox","value":"0 0 24 24"},{"kind":"literal","name":"fill","value":"none"},{"kind":"literal","name":"stroke","value":"currentColor"},{"kind":"literal","name":"stroke-width","value":"2"},{"kind":"literal","name":"stroke-linecap","value":"round"},{"kind":"literal","name":"stroke-linejoin","value":"round"}],"children":[{"kind":"element","name":"path","attributes":[{"kind":"literal","name":"d","value":"M13.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8.5L13.5 2Z"}],"children":[]},{"kind":"element","name":"path","attributes":[{"kind":"literal","name":"d","value":"M13 2v7h7"}],"children":[]},{"kind":"element","name":"path","attributes":[{"kind":"literal","name":"d","value":"m9.5 17.5 4-4 2 2-4 4H9.5v-2Z"}],"children":[]}],"flow":{"kind":"if","test":"tone = 'note'","testPlan":{"source":"tone = 'note'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"tone"},"right":{"kind":"literal","value":"note"}},"dependencies":["tone"]}}},{"kind":"element","name":"svg","attributes":[{"kind":"literal","name":"viewBox","value":"0 0 24 24"},{"kind":"literal","name":"fill","value":"none"},{"kind":"literal","name":"stroke","value":"currentColor"},{"kind":"literal","name":"stroke-width","value":"2"},{"kind":"literal","name":"stroke-linecap","value":"round"},{"kind":"literal","name":"stroke-linejoin","value":"round"}],"children":[{"kind":"element","name":"path","attributes":[{"kind":"literal","name":"d","value":"m21.73 18-8-14a2 2 0 0 0-3.46 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z"}],"children":[]},{"kind":"element","name":"path","attributes":[{"kind":"literal","name":"d","value":"M12 9v4"}],"children":[]},{"kind":"element","name":"path","attributes":[{"kind":"literal","name":"d","value":"M12 17h.01"}],"children":[]}],"flow":{"kind":"if","test":"tone = 'warning'","testPlan":{"source":"tone = 'warning'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"tone"},"right":{"kind":"literal","value":"warning"}},"dependencies":["tone"]}}},{"kind":"element","name":"svg","attributes":[{"kind":"literal","name":"viewBox","value":"0 0 24 24"},{"kind":"literal","name":"fill","value":"none"},{"kind":"literal","name":"stroke","value":"currentColor"},{"kind":"literal","name":"stroke-width","value":"2"},{"kind":"literal","name":"stroke-linecap","value":"round"},{"kind":"literal","name":"stroke-linejoin","value":"round"}],"children":[{"kind":"element","name":"circle","attributes":[{"kind":"literal","name":"cx","value":"12"},{"kind":"literal","name":"cy","value":"12"},{"kind":"literal","name":"r","value":"10"}],"children":[]},{"kind":"element","name":"path","attributes":[{"kind":"literal","name":"d","value":"m9 12 2 2 4-4"}],"children":[]}],"flow":{"kind":"if","test":"tone = 'success'","testPlan":{"source":"tone = 'success'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"tone"},"right":{"kind":"literal","value":"success"}},"dependencies":["tone"]}}},{"kind":"element","name":"svg","attributes":[{"kind":"literal","name":"viewBox","value":"0 0 24 24"},{"kind":"literal","name":"fill","value":"none"},{"kind":"literal","name":"stroke","value":"currentColor"},{"kind":"literal","name":"stroke-width","value":"2"},{"kind":"literal","name":"stroke-linecap","value":"round"},{"kind":"literal","name":"stroke-linejoin","value":"round"}],"children":[{"kind":"element","name":"circle","attributes":[{"kind":"literal","name":"cx","value":"12"},{"kind":"literal","name":"cy","value":"12"},{"kind":"literal","name":"r","value":"10"}],"children":[]},{"kind":"element","name":"path","attributes":[{"kind":"literal","name":"d","value":"m15 9-6 6"}],"children":[]},{"kind":"element","name":"path","attributes":[{"kind":"literal","name":"d","value":"m9 9 6 6"}],"children":[]}],"flow":{"kind":"if","test":"tone = 'danger'","testPlan":{"source":"tone = 'danger'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"tone"},"right":{"kind":"literal","value":"danger"}},"dependencies":["tone"]}}}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"content"}],"children":[{"kind":"slot"}]}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-callout-border {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-callout-border-width {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-callout-gap {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-callout-icon {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-callout-icon-column {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-callout-icon-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-callout-leading-border-width {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-callout-padding-block {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-callout-padding-inline {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-callout-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-callout-text {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-callout-icon-column: var(--ui-callout-icon-column);\n --_ui-callout-icon: var(--ui-callout-icon);\n --_ui-callout-icon-size: var(--ui-callout-icon-size);\n\n --_callout-surface: var(--ui-info-soft);\n --_callout-border: var(--ui-info-solid);\n --_callout-icon: var(--ui-info-solid);\n\n display: grid;\n grid-template-columns: var(--ui-callout-icon-column, 1.125rem) minmax(0, 1fr);\n gap: var(--ui-callout-gap, calc(var(--ui-space-2) * 0.75));\n align-items: start;\n max-width: 100%;\n padding: var(--ui-callout-padding-block, var(--ui-space-2)) var(--ui-callout-padding-inline, var(--ui-space-3));\n border: var(--ui-callout-border-width, 1px) solid color-mix(in srgb, var(--ui-callout-border, var(--_callout-border)) 35%, transparent);\n border-inline-start: var(--ui-callout-leading-border-width, 4px) solid var(--ui-callout-border, var(--_callout-border));\n border-radius: var(--ui-radius-md);\n background: var(--ui-callout-surface, var(--_callout-surface));\n color: var(--ui-callout-text, var(--ui-text-primary));\n font-family: var(--ui-font-family-sans);\n font-size: var(--ui-font-size-sm);\n font-weight: var(--ui-font-normal);\n line-height: var(--ui-line-height-md);\n }\n\n /* One line box tall, so the icon centres on the first line of text. */\n .icon {\n display: grid;\n place-items: center;\n inline-size: var(--_ui-callout-icon-column, 1.125rem);\n block-size: 1lh;\n color: var(--_ui-callout-icon, var(--_callout-icon));\n }\n\n .icon svg {\n inline-size: var(--_ui-callout-icon-size, 1.125rem);\n block-size: var(--_ui-callout-icon-size, 1.125rem);\n }\n\n .content {\n min-inline-size: 0;\n }\n\n :host-state([tone=\"note\"]) {\n --_callout-surface: var(--ui-surface-muted);\n --_callout-border: var(--ui-border-strong);\n --_callout-icon: var(--ui-text-secondary);\n }\n\n :host-state([tone=\"warning\"]) {\n --_callout-surface: var(--ui-warning-soft);\n --_callout-border: var(--ui-warning-solid);\n --_callout-icon: var(--ui-warning-solid);\n }\n\n :host-state([tone=\"success\"]) {\n --_callout-surface: var(--ui-success-soft);\n --_callout-border: var(--ui-success-solid);\n --_callout-icon: var(--ui-success-solid);\n }\n\n :host-state([tone=\"danger\"]) {\n --_callout-surface: var(--ui-danger-soft);\n --_callout-border: var(--ui-danger-solid);\n --_callout-icon: var(--ui-danger-solid);\n }\n\n /* A link in the callout's text is underlined, so it reads as a link by more than colour. */\n .content :slotted(a) {\n color: var(--ui-accent-active);\n text-decoration: underline;\n text-decoration-thickness: 0.06em;\n text-underline-offset: 0.18em;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]}},{"source":{"file":"./components/ui-card/ui-card.html"},"contract":{"version":1,"name":"UiCard","tag":"ui-card","nativeElement":"div","props":{"as":{"type":{"enum":["div","section","article","aside"]},"required":false,"target":{"attribute":"as"},"description":"The native element the card renders. Choose the one that names the content: a section of a page, a self-contained article, or an aside.","default":"div"},"padding":{"type":{"enum":["sm","md","lg"]},"required":false,"target":{"attribute":"padding"},"description":"The space inside the card: sm is snug (0.75rem), md is the default (1.5rem), and lg is roomy (2rem).","default":"md"},"tone":{"type":{"enum":["neutral","danger"]},"required":false,"target":{"attribute":"tone"},"description":"danger draws an outlined card's border in the danger colour.","default":"neutral"},"variant":{"type":{"enum":["outlined","subtle","elevated"]},"required":false,"target":{"attribute":"variant"},"description":"The surface. outlined is a bordered panel on the page; subtle is a quiet filled one with no border, for supporting details set apart from the flow;\n elevated floats above the page with a shadow, for a view's one card, such as sign-in.","default":"outlined"}}},"template":{"kind":"element","name":"template","attributes":[],"children":[{"kind":"element","name":"section","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'section'","testPlan":{"source":"as = 'section'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"section"}},"dependencies":["as"]}}},{"kind":"element","name":"article","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'article'","testPlan":{"source":"as = 'article'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"article"}},"dependencies":["as"]}}},{"kind":"element","name":"aside","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'aside'","testPlan":{"source":"as = 'aside'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"aside"}},"dependencies":["as"]}}},{"kind":"element","name":"div","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"else"}}],"flow":{"kind":"match"}},"css":"/* A surface that groups content. Its children stack with even space between them, so a card\n needs no layout of its own. */\n :host {\n display: flex;\n flex-direction: column;\n gap: var(--ui-space-4);\n box-sizing: border-box;\n min-inline-size: 0;\n padding: var(--ui-space-5);\n border: 1px solid var(--ui-border-default);\n border-radius: var(--ui-radius-lg);\n background: var(--ui-surface-raised);\n color: var(--ui-text-primary);\n }\n\n :host-state([padding=\"sm\"]) {\n gap: var(--ui-space-2);\n padding: var(--ui-space-3);\n }\n\n :host-state([padding=\"lg\"]) {\n padding: var(--ui-space-6);\n }\n\n :host-state([variant=\"subtle\"]) {\n border-color: transparent;\n background: var(--ui-surface-muted);\n }\n\n :host-state([variant=\"elevated\"]) {\n border-color: var(--ui-border-subtle);\n box-shadow: var(--ui-shadow-lg);\n }\n\n :host-state([tone=\"danger\"]) {\n border-color: var(--ui-danger);\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["section","article","aside","div"]}},{"source":{"file":"./components/ui-checkbox/ui-checkbox.html"},"contract":{"version":1,"name":"UiCheckbox","tag":"ui-checkbox","nativeElement":"label","props":{"checked":{"type":"boolean","required":false,"target":{"attribute":"checked"},"description":"Whether the checkbox is checked initially or when set externally. A form reset returns it to this.","default":false},"disabled":{"type":"boolean","required":false,"target":{"attribute":"disabled"},"description":"Disables the native checkbox, so it cannot be toggled or focused.","default":false},"indeterminate":{"type":"boolean","required":false,"target":{"property":"indeterminate"},"description":"Shows the mixed state, for a checkbox that summarises a group whose items are partly checked. It sets the native indeterminate property, which is\n independent of checked, so update it as the group changes.","default":false},"name":{"type":"string","required":false,"target":{"attribute":"name"},"description":"The native name the checkbox submits under: a form that contains it sends name=value while it is checked, and nothing while it is unchecked, as a native\n checkbox does. Left empty, it takes no part in form submission.","default":""},"required":{"type":"boolean","required":false,"target":{"attribute":"required"},"description":"Marks the native checkbox required, so native form validation treats it as invalid until it is checked.","default":false},"value":{"type":"string","required":false,"target":{"attribute":"value"},"description":"The value a form submits under name while the checkbox is checked, also reported in the change event's detail so one handler can tell checkboxes apart. on\n by default, as on a native checkbox.","default":"on"}}},"template":{"kind":"element","name":"label","attributes":[],"children":[{"kind":"element","name":"input","attributes":[{"kind":"literal","name":"type","value":"checkbox"},{"kind":"property","key":"checked","name":"checked","expression":"internalChecked","expressionPlan":{"source":"internalChecked","ast":{"kind":"id","name":"internalChecked"},"dependencies":["internalChecked"]}},{"kind":"property","key":"indeterminate","name":"indeterminate","expression":"indeterminate","expressionPlan":{"source":"indeterminate","ast":{"kind":"id","name":"indeterminate"},"dependencies":["indeterminate"]}},{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}},{"kind":"attribute","name":"required","expression":"required","expressionPlan":{"source":"required","ast":{"kind":"id","name":"required"},"dependencies":["required"]}},{"kind":"attribute","name":"name","expression":"name","expressionPlan":{"source":"name","ast":{"kind":"id","name":"name"},"dependencies":["name"]}},{"kind":"attribute","name":"value","expression":"value","expressionPlan":{"source":"value","ast":{"kind":"id","name":"value"},"dependencies":["value"]}}],"children":[],"ref":"input"},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"text"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"label"}],"children":[{"kind":"slot"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"description"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[{"kind":"slot","fallback":[],"name":"description"}],"ref":"description"}]}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-checkbox-gap {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-checkbox-size {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-checkbox-size: var(--ui-checkbox-size);\n\n display: inline-flex;\n align-items: flex-start;\n gap: var(--ui-checkbox-gap, var(--ui-space-2));\n max-inline-size: 100%;\n color: var(--ui-text-primary);\n cursor: pointer;\n }\n\n /* The label, and under it an optional line saying what the choice means. */\n .text {\n display: flex;\n flex-direction: column;\n gap: var(--ui-space-1);\n min-inline-size: 0;\n }\n\n .label {\n min-inline-size: 0;\n line-height: var(--ui-line-height-md);\n }\n\n .description {\n color: var(--ui-text-secondary);\n font-size: var(--ui-font-size-sm);\n line-height: var(--ui-line-height);\n }\n\n .description:empty {\n display: none;\n }\n\n input {\n appearance: none;\n -webkit-appearance: none;\n position: relative;\n flex: 0 0 auto;\n inline-size: var(--_ui-checkbox-size, 1.125rem);\n block-size: var(--_ui-checkbox-size, 1.125rem);\n margin: 0.125em 0 0;\n border: 1px solid var(--ui-control-border-hover, var(--ui-border-strong));\n border-radius: var(--ui-radius-sm);\n background: var(--ui-control-surface, var(--ui-surface-default));\n box-shadow: inset 0 1px 2px color-mix(in srgb, var(--ui-text-primary) 8%, transparent);\n cursor: pointer;\n transition:\n background-color var(--ui-motion-fast) var(--ui-motion-ease),\n border-color var(--ui-motion-fast) var(--ui-motion-ease),\n box-shadow var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n input::after {\n content: \"\";\n position: absolute;\n opacity: 0;\n }\n\n input:checked,\n input:indeterminate {\n border-color: var(--ui-accent-solid);\n background: var(--ui-accent-solid);\n box-shadow: inset 0 1px 2px color-mix(in srgb, #000 16%, transparent);\n }\n\n /* Centre the tick's box, then lift it: a rotated L's ink sits ~0.11rem below its box centre. */\n input:checked::after {\n inset: 0;\n margin: auto;\n inline-size: 0.32rem;\n block-size: 0.58rem;\n /* Longhands, not `border: solid var(...)`: lowering drops a shorthand that omits a\n component, which left the tick with no style and no colour. */\n border-style: solid;\n border-color: var(--ui-text-on-accent);\n border-width: 0 0.125rem 0.125rem 0;\n opacity: 1;\n transform: translateY(-0.11rem) rotate(45deg);\n }\n\n input:indeterminate::after {\n inset: 50% 0.23rem auto;\n block-size: 0.125rem;\n border-radius: var(--ui-radius-round);\n background: var(--ui-text-on-accent);\n opacity: 1;\n transform: translateY(-50%);\n }\n\n input:hover:enabled {\n border-color: var(--ui-accent-solid);\n }\n\n input:focus-visible {\n outline: 2px solid var(--ui-focus-ring, var(--ui-accent-solid));\n outline-offset: 2px;\n }\n\n :host-state([disabled]) {\n color: var(--ui-disabled-text);\n cursor: not-allowed;\n }\n :host-state([disabled]) input {\n border-color: var(--ui-border-default);\n background: var(--ui-control-surface-disabled, var(--ui-surface-muted));\n cursor: not-allowed;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"internalChecked","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"event","name":"change","type":"object({ checked: boolean, value: string, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false}],"slots":[{"dynamic":false,"required":true},{"dynamic":false,"required":true,"name":"description"}],"root":{"kind":"native","element":"label","choices":["label"]},"controller":"./components/ui-checkbox/ui-checkbox.js"},{"source":{"file":"./components/ui-cluster/ui-cluster.html"},"contract":{"version":1,"name":"UiCluster","tag":"ui-cluster","nativeElement":"div","props":{"align":{"type":{"enum":["start","center","end","stretch"]},"required":false,"target":{"attribute":"align"},"description":"How items line up within each row: center (the default) aligns their middles, start their tops, end their bottoms, and stretch makes every item as tall as\n its row."},"gap":{"type":{"enum":["xs","s","m","l","xl"]},"required":false,"target":{"attribute":"gap"},"description":"Space between items, on the spacing scale: xs is 0.5rem, s 0.75rem (also the default), m 1rem, l 1.5rem, and xl 2rem. The --ui-cluster-gap custom property,\n set on the cluster itself, overrides it; set on an ancestor, it does nothing."},"justify":{"type":{"enum":["start","center","end","between"]},"required":false,"target":{"attribute":"justify"},"description":"Where items sit along each row: start (the default), center, end, or between, which pushes the first and last items to the ends of the row and spreads the\n spare space between them, as for a title with its actions."}}},"template":{"kind":"element","name":"div","attributes":[],"children":[{"kind":"slot"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-cluster-gap {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n --_layout-gap: var(--ui-space-3);\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--ui-cluster-gap, var(--_layout-gap));\n min-inline-size: 0;\n max-inline-size: 100%;\n margin: 0;\n }\n\n :host-state([gap=\"xs\"]) {\n --_layout-gap: var(--ui-space-2);\n }\n :host-state([gap=\"s\"]) {\n --_layout-gap: var(--ui-space-3);\n }\n :host-state([gap=\"m\"]) {\n --_layout-gap: var(--ui-space-4);\n }\n :host-state([gap=\"l\"]) {\n --_layout-gap: var(--ui-space-5);\n }\n :host-state([gap=\"xl\"]) {\n --_layout-gap: var(--ui-space-6);\n }\n :host-state([align=\"start\"]) {\n align-items: flex-start;\n }\n :host-state([align=\"end\"]) {\n align-items: flex-end;\n }\n :host-state([align=\"stretch\"]) {\n align-items: stretch;\n }\n :host-state([justify=\"center\"]) {\n justify-content: center;\n }\n :host-state([justify=\"end\"]) {\n justify-content: flex-end;\n }\n :host-state([justify=\"between\"]) {\n justify-content: space-between;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]}},{"source":{"file":"./components/ui-combobox/ui-combobox.html"},"contract":{"version":1,"name":"UiCombobox","tag":"ui-combobox","nativeElement":"div","props":{"allowCreate":{"type":"boolean","required":false,"target":{"attribute":"allowcreate"},"description":"Offers the current query as a new option, reported as create-item. When nothing else matches, the offer is highlighted, so Enter creates it; with nothing\n highlighted, Enter in multiple mode commits the typed text as a token separator does.","default":false},"allowFreeText":{"type":"boolean","required":false,"target":{"attribute":"allowfreetext"},"description":"Allows values that do not match an authored option.","default":false},"clearable":{"type":"boolean","required":false,"target":{"attribute":"clearable"},"description":"Adds a clear button to the field that empties the input and clears the selection, reported as value-change with kind \"clear\". In multiple mode it clears\n only the typed text; chosen items stay.","default":false},"disabled":{"type":"boolean","required":false,"target":{"attribute":"disabled"},"description":"Disables the input and every button in the field: the chosen-item badges, the clear and disclosure buttons, and the help button. The list closes and cannot\n be opened, the value cannot be cleared, and a named combobox submits nothing with its form.","default":false},"disclosure":{"type":"boolean","required":false,"target":{"attribute":"disclosure"},"description":"Adds a chevron button that opens and closes the full, unfiltered list of options, for users who would rather browse than type. ArrowDown opens the same\n list with or without it.","default":false},"help":{"type":"string","required":false,"target":{"attribute":"help"},"description":"Help text for the field. When set, a help button appears beside the field and opens a tooltip with this text; while it is open, the input is described by\n it.","default":""},"items":{"type":{"kind":"list","item":{"kind":"object","fields":[{"name":"id","type":{"kind":"terminal","name":"string"},"optional":false},{"name":"value","type":{"kind":"terminal","name":"string"},"optional":false},{"name":"label","type":{"kind":"terminal","name":"string"},"optional":false},{"name":"group","type":{"kind":"terminal","name":"string"},"optional":true},{"name":"disabled","type":{"kind":"terminal","name":"boolean"},"optional":true}],"open":false}},"required":false,"target":{"attribute":"items"},"description":"The selected items in multiple mode, as JSON; a named combobox submits each one's value. A form reset returns to these items, or to none when unset."},"label":{"type":"string","required":false,"target":{"attribute":"label"},"description":"The field's label, tied to its input and shown above it; required adds an asterisk. It also names the suggestion list. Pair it with\n labelVisibility=\"sr-only\" when the context already labels the field visibly.","default":""},"labelVisibility":{"type":{"enum":["visible","sr-only"]},"required":false,"target":{"attribute":"labelvisibility"},"description":"visible shows the label above the field; sr-only hides it visually but keeps it as the input's accessible name. Use sr-only only when the surrounding\n layout already makes the field's purpose clear.","default":"visible"},"multiple":{"type":"boolean","required":false,"target":{"attribute":"multiple"},"description":"Lets the user choose several options. Each choice becomes a removable badge before the input, the list stays open between picks, and choosing a checked\n option removes it. value-change then reports the whole list of items, and selected-values-change the list of their values; use selectedValues or items,\n not value, in this mode.","default":false},"name":{"type":"string","required":false,"target":{"attribute":"name"},"description":"The form field name the combobox submits its value under, never the label shown in the field. Single mode sends one entry: the selected option's value, the\n typed text when allowFreeText is set and no option is selected, or an empty string. Multiple mode sends one entry per chosen item's value, and nothing\n when none is chosen. A disabled combobox sends nothing.","default":""},"placeholder":{"type":"string","required":false,"target":{"attribute":"placeholder"},"description":"Hint text shown in the empty input, as on a native input. It disappears as the user types, so it never replaces label.","default":""},"query":{"type":"string","required":false,"target":{"attribute":"query"},"description":"The input's text, when the consumer controls it. Once set, the consumer owns the text: typing reports query-change, and the input returns to query unless\n query is updated to match. Leave it unset to let the combobox manage its own text, showing the chosen option's label."},"readonly":{"type":"boolean","required":false,"target":{"attribute":"readonly"},"description":"Shows the current value without letting it change: the text can be selected but not edited, the list does not open, and the clear, disclosure, and badge\n remove buttons are disabled. A named combobox still submits its value.","default":false},"required":{"type":"boolean","required":false,"target":{"attribute":"required"},"description":"Requires a value: adds an asterisk to the label, marks the input required for native form validation, and makes validation report \"A value is required.\"\n when the field is left empty. In multiple mode a chosen item satisfies it, whatever is left in the input.","default":false},"selectedValues":{"type":{"kind":"list","item":{"kind":"terminal","name":"string"}},"required":false,"target":{"attribute":"selectedvalues"},"description":"The selected option values in multiple mode, when the consumer controls the selection. Once set, the consumer owns it: each value shows as a badge with its\n authored option's label, adding or removing one reports selected-values-change with the new list, and the badges follow selectedValues, not the user,\n unless it is updated to match. Setting it reports nothing. It takes precedence over items; leave it unset to let the combobox keep its own\n selection."},"size":{"type":{"enum":["sm","md"]},"required":false,"target":{"attribute":"size"},"description":"Field height. md is the standard control height; sm is the small control height with tighter padding, for dense forms.","default":"md"},"tokenSeparators":{"type":{"kind":"list","item":{"kind":"terminal","name":"string"}},"required":false,"target":{"attribute":"tokenseparators"},"description":"Keys that commit the typed text in multiple mode, as KeyboardEvent key values such as \",\" or \";\". The text is added as the option whose label matches it,\n ignoring case, or with allowCreate is reported as create-item; otherwise it stays in the input."},"value":{"type":{"kind":"union","members":[{"kind":"terminal","name":"string"},{"kind":"terminal","name":"null"}]},"required":false,"target":{"attribute":"value"},"description":"The selected value in single mode, which a named combobox submits with its form. The field shows the matching option's label, and a form reset returns to\n this value."}}},"template":{"kind":"element","name":"div","attributes":[],"children":[{"kind":"element","name":"label","attributes":[{"kind":"attribute","name":"for","expression":"format('%s-input', uid)","expressionPlan":{"source":"format('%s-input', uid)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s-input"},{"kind":"id","name":"uid"}]},"dependencies":["uid"]}},{"kind":"attribute","name":"sr-only","expression":"labelVisibility = 'sr-only'","expressionPlan":{"source":"labelVisibility = 'sr-only'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"labelVisibility"},"right":{"kind":"literal","value":"sr-only"}},"dependencies":["labelVisibility"]},"target":"class"}],"children":[{"kind":"element","name":"template","attributes":[{"kind":"directive","name":"value","expression":"label","expressionPlan":{"source":"label","ast":{"kind":"id","name":"label"},"dependencies":["label"]}}],"children":[]},{"kind":"element","name":"template","attributes":[],"children":[{"kind":"text","value":"\n *"}],"flow":{"kind":"if","test":"required","testPlan":{"source":"required","ast":{"kind":"id","name":"required"},"dependencies":["required"]}}}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"control"}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"field"}],"children":[{"kind":"slot","fallback":[],"name":"start"},{"kind":"element","name":"template","attributes":[],"children":[{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"class","value":"item"},{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"tabindex","value":"-1"},{"kind":"attribute","name":"data-index","expression":"index","expressionPlan":{"source":"index","ast":{"kind":"id","name":"index"},"dependencies":["index"]}},{"kind":"attribute","name":"disabled","expression":"disabled or readonly or item.disabled","expressionPlan":{"source":"disabled or readonly or item.disabled","ast":{"kind":"binary","op":"or","left":{"kind":"binary","op":"or","left":{"kind":"id","name":"disabled"},"right":{"kind":"id","name":"readonly"}},"right":{"kind":"member","object":{"kind":"id","name":"item"},"key":"disabled"}},"dependencies":["disabled","item.disabled","readonly"]}},{"kind":"attribute","name":"aria-label","expression":"format('%s, press Delete or Backspace to remove', item.label)","expressionPlan":{"source":"format('%s, press Delete or Backspace to remove', item.label)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s, press Delete or Backspace to remove"},{"kind":"member","object":{"kind":"id","name":"item"},"key":"label"}]},"dependencies":["item.label"]}}],"children":[{"kind":"slot","fallback":[{"kind":"element","name":"ui-badge","attributes":[{"kind":"directive","name":"value","expression":"item.label","expressionPlan":{"source":"item.label","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"label"},"dependencies":["item.label"]}}],"children":[]}],"nameExpression":{"source":"format('item-%s', item.id)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"item-%s"},{"kind":"member","object":{"kind":"id","name":"item"},"key":"id"}]},"dependencies":["item.id"]}}],"flow":{"kind":"each","item":"item","list":"internalItems","listPlan":{"source":"internalItems","ast":{"kind":"id","name":"internalItems"},"dependencies":["internalItems"]},"index":"index","key":"item.id","keyPlan":{"source":"item.id","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"id"},"dependencies":["item.id"]}}}],"flow":{"kind":"if","test":"multiple","testPlan":{"source":"multiple","ast":{"kind":"id","name":"multiple"},"dependencies":["multiple"]}}},{"kind":"element","name":"input","attributes":[{"kind":"attribute","name":"id","expression":"format('%s-input', uid)","expressionPlan":{"source":"format('%s-input', uid)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s-input"},{"kind":"id","name":"uid"}]},"dependencies":["uid"]}},{"kind":"literal","name":"role","value":"combobox"},{"kind":"literal","name":"aria-autocomplete","value":"list"},{"kind":"literal","name":"autocomplete","value":"off"},{"kind":"attribute","name":"aria-controls","expression":"format('%s-listbox', uid)","expressionPlan":{"source":"format('%s-listbox', uid)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s-listbox"},{"kind":"id","name":"uid"}]},"dependencies":["uid"]}},{"kind":"attribute","name":"aria-expanded","expression":"expanded","expressionPlan":{"source":"expanded","ast":{"kind":"id","name":"expanded"},"dependencies":["expanded"]}},{"kind":"attribute","name":"aria-invalid","expression":"validationStatus = 'error'","expressionPlan":{"source":"validationStatus = 'error'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"validationStatus"},"right":{"kind":"literal","value":"error"}},"dependencies":["validationStatus"]}},{"kind":"attribute","name":"aria-busy","expression":"validationStatus = 'pending'","expressionPlan":{"source":"validationStatus = 'pending'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"validationStatus"},"right":{"kind":"literal","value":"pending"}},"dependencies":["validationStatus"]}},{"kind":"property","key":"value","name":"value","expression":"display","expressionPlan":{"source":"display","ast":{"kind":"id","name":"display"},"dependencies":["display"]}},{"kind":"attribute","name":"placeholder","expression":"placeholder","expressionPlan":{"source":"placeholder","ast":{"kind":"id","name":"placeholder"},"dependencies":["placeholder"]}},{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}},{"kind":"attribute","name":"readonly","expression":"readonly","expressionPlan":{"source":"readonly","ast":{"kind":"id","name":"readonly"},"dependencies":["readonly"]}},{"kind":"attribute","name":"required","expression":"required and not (multiple and internalItems[0])","expressionPlan":{"source":"required and not (multiple and internalItems[0])","ast":{"kind":"binary","op":"and","left":{"kind":"id","name":"required"},"right":{"kind":"unary","op":"not","operand":{"kind":"binary","op":"and","left":{"kind":"id","name":"multiple"},"right":{"kind":"index","object":{"kind":"id","name":"internalItems"},"index":{"kind":"literal","value":0}}}}},"dependencies":["internalItems.0","multiple","required"]}}],"children":[],"ref":"input"},{"kind":"element","name":"input","attributes":[{"kind":"literal","name":"type","value":"hidden"},{"kind":"attribute","name":"name","expression":"name","expressionPlan":{"source":"name","ast":{"kind":"id","name":"name"},"dependencies":["name"]}},{"kind":"attribute","name":"value","expression":"submitted","expressionPlan":{"source":"submitted","ast":{"kind":"id","name":"submitted"},"dependencies":["submitted"]}},{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}}],"children":[],"flow":{"kind":"if","test":"name and not multiple","testPlan":{"source":"name and not multiple","ast":{"kind":"binary","op":"and","left":{"kind":"id","name":"name"},"right":{"kind":"unary","op":"not","operand":{"kind":"id","name":"multiple"}}},"dependencies":["multiple","name"]}}},{"kind":"element","name":"template","attributes":[],"children":[{"kind":"element","name":"input","attributes":[{"kind":"literal","name":"type","value":"hidden"},{"kind":"attribute","name":"name","expression":"name","expressionPlan":{"source":"name","ast":{"kind":"id","name":"name"},"dependencies":["name"]}},{"kind":"attribute","name":"value","expression":"item.value","expressionPlan":{"source":"item.value","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"value"},"dependencies":["item.value"]}},{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}}],"children":[],"flow":{"kind":"each","item":"item","list":"internalItems","listPlan":{"source":"internalItems","ast":{"kind":"id","name":"internalItems"},"dependencies":["internalItems"]},"key":"item.id","keyPlan":{"source":"item.id","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"id"},"dependencies":["item.id"]}}}],"flow":{"kind":"if","test":"name and multiple","testPlan":{"source":"name and multiple","ast":{"kind":"binary","op":"and","left":{"kind":"id","name":"name"},"right":{"kind":"id","name":"multiple"}},"dependencies":["multiple","name"]}}},{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"data-combobox-action","value":"clear"},{"kind":"literal","name":"aria-label","value":"Clear"},{"kind":"attribute","name":"disabled","expression":"disabled or readonly","expressionPlan":{"source":"disabled or readonly","ast":{"kind":"binary","op":"or","left":{"kind":"id","name":"disabled"},"right":{"kind":"id","name":"readonly"}},"dependencies":["disabled","readonly"]}}],"children":[{"kind":"element","name":"svg","attributes":[{"kind":"literal","name":"class","value":"affordance-icon"},{"kind":"literal","name":"aria-hidden","value":"true"},{"kind":"literal","name":"viewBox","value":"0 0 24 24"},{"kind":"literal","name":"fill","value":"none"},{"kind":"literal","name":"stroke","value":"currentColor"},{"kind":"literal","name":"stroke-width","value":"2"},{"kind":"literal","name":"stroke-linecap","value":"round"}],"children":[{"kind":"element","name":"path","attributes":[{"kind":"literal","name":"d","value":"M7 7l10 10M17 7 7 17"}],"children":[]}]}],"flow":{"kind":"if","test":"clearable","testPlan":{"source":"clearable","ast":{"kind":"id","name":"clearable"},"dependencies":["clearable"]}}},{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"data-combobox-action","value":"disclosure"},{"kind":"literal","name":"tabindex","value":"-1"},{"kind":"literal","name":"aria-label","value":"Show suggestions"},{"kind":"attribute","name":"aria-controls","expression":"format('%s-listbox', uid)","expressionPlan":{"source":"format('%s-listbox', uid)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s-listbox"},{"kind":"id","name":"uid"}]},"dependencies":["uid"]}},{"kind":"attribute","name":"disabled","expression":"disabled or readonly","expressionPlan":{"source":"disabled or readonly","ast":{"kind":"binary","op":"or","left":{"kind":"id","name":"disabled"},"right":{"kind":"id","name":"readonly"}},"dependencies":["disabled","readonly"]}}],"children":[{"kind":"element","name":"svg","attributes":[{"kind":"literal","name":"class","value":"affordance-icon"},{"kind":"literal","name":"aria-hidden","value":"true"},{"kind":"literal","name":"viewBox","value":"0 0 24 24"},{"kind":"literal","name":"fill","value":"none"},{"kind":"literal","name":"stroke","value":"currentColor"},{"kind":"literal","name":"stroke-width","value":"2.25"},{"kind":"literal","name":"stroke-linecap","value":"round"},{"kind":"literal","name":"stroke-linejoin","value":"round"}],"children":[{"kind":"element","name":"path","attributes":[{"kind":"literal","name":"d","value":"m6 9 6 6 6-6"}],"children":[]}]}],"flow":{"kind":"if","test":"disclosure","testPlan":{"source":"disclosure","ast":{"kind":"id","name":"disclosure"},"dependencies":["disclosure"]}}}],"ref":"field"},{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"class","value":"help"},{"kind":"attribute","name":"id","expression":"format('%s-help', uid)","expressionPlan":{"source":"format('%s-help', uid)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s-help"},{"kind":"id","name":"uid"}]},"dependencies":["uid"]}},{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"aria-label","value":"Help"},{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}}],"children":[{"kind":"element","name":"svg","attributes":[{"kind":"literal","name":"class","value":"help-icon"},{"kind":"literal","name":"aria-hidden","value":"true"},{"kind":"literal","name":"viewBox","value":"0 0 24 24"},{"kind":"literal","name":"fill","value":"none"},{"kind":"literal","name":"stroke","value":"currentColor"},{"kind":"literal","name":"stroke-width","value":"2"},{"kind":"literal","name":"stroke-linecap","value":"round"},{"kind":"literal","name":"stroke-linejoin","value":"round"}],"children":[{"kind":"element","name":"circle","attributes":[{"kind":"literal","name":"cx","value":"12"},{"kind":"literal","name":"cy","value":"12"},{"kind":"literal","name":"r","value":"10"}],"children":[]},{"kind":"element","name":"path","attributes":[{"kind":"literal","name":"d","value":"M9.1 9a3 3 0 0 1 5.8 1c0 2-3 3-3 3"}],"children":[]},{"kind":"element","name":"path","attributes":[{"kind":"literal","name":"d","value":"M12 17h.01"}],"children":[]}]}],"flow":{"kind":"if","test":"help","testPlan":{"source":"help","ast":{"kind":"id","name":"help"},"dependencies":["help"]}}}]},{"kind":"element","name":"ui-tooltip","attributes":[{"kind":"literal","name":"trigger","value":"click"},{"kind":"attribute","name":"id","expression":"format('%s-help-text', uid)","expressionPlan":{"source":"format('%s-help-text', uid)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s-help-text"},{"kind":"id","name":"uid"}]},"dependencies":["uid"]}},{"kind":"attribute","name":"for","expression":"format('%s-help', uid)","expressionPlan":{"source":"format('%s-help', uid)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s-help"},{"kind":"id","name":"uid"}]},"dependencies":["uid"]}}],"children":[{"kind":"element","name":"template","attributes":[{"kind":"directive","name":"value","expression":"help","expressionPlan":{"source":"help","ast":{"kind":"id","name":"help"},"dependencies":["help"]}}],"children":[]}],"flow":{"kind":"if","test":"help","testPlan":{"source":"help","ast":{"kind":"id","name":"help"},"dependencies":["help"]}}},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"popup"},{"kind":"attribute","name":"hidden","expression":"not expanded","expressionPlan":{"source":"not expanded","ast":{"kind":"unary","op":"not","operand":{"kind":"id","name":"expanded"}},"dependencies":["expanded"]}}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"role","value":"listbox"},{"kind":"attribute","name":"id","expression":"format('%s-listbox', uid)","expressionPlan":{"source":"format('%s-listbox', uid)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s-listbox"},{"kind":"id","name":"uid"}]},"dependencies":["uid"]}},{"kind":"attribute","name":"aria-label","expression":"format('%s suggestions', label)","expressionPlan":{"source":"format('%s suggestions', label)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s suggestions"},{"kind":"id","name":"label"}]},"dependencies":["label"]}},{"kind":"attribute","name":"aria-busy","expression":"loading","expressionPlan":{"source":"loading","ast":{"kind":"id","name":"loading"},"dependencies":["loading"]}}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"attribute","name":"role","expression":"group.role","expressionPlan":{"source":"group.role","ast":{"kind":"member","object":{"kind":"id","name":"group"},"key":"role"},"dependencies":["group.role"]}},{"kind":"attribute","name":"aria-label","expression":"group.label","expressionPlan":{"source":"group.label","ast":{"kind":"member","object":{"kind":"id","name":"group"},"key":"label"},"dependencies":["group.label"]}}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"group"},{"kind":"directive","name":"value","expression":"group.name","expressionPlan":{"source":"group.name","ast":{"kind":"member","object":{"kind":"id","name":"group"},"key":"name"},"dependencies":["group.name"]}}],"children":[],"flow":{"kind":"if","test":"group.name","testPlan":{"source":"group.name","ast":{"kind":"member","object":{"kind":"id","name":"group"},"key":"name"},"dependencies":["group.name"]}}},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"option"},{"kind":"attribute","name":"active","expression":"row.index = active","expressionPlan":{"source":"row.index = active","ast":{"kind":"binary","op":"=","left":{"kind":"member","object":{"kind":"id","name":"row"},"key":"index"},"right":{"kind":"id","name":"active"}},"dependencies":["active","row.index"]},"target":"class"},{"kind":"literal","name":"role","value":"option"},{"kind":"attribute","name":"id","expression":"format('%s-option-%s', uid, row.index)","expressionPlan":{"source":"format('%s-option-%s', uid, row.index)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s-option-%s"},{"kind":"id","name":"uid"},{"kind":"member","object":{"kind":"id","name":"row"},"key":"index"}]},"dependencies":["row.index","uid"]}},{"kind":"attribute","name":"aria-selected","expression":"row.selected","expressionPlan":{"source":"row.selected","ast":{"kind":"member","object":{"kind":"id","name":"row"},"key":"selected"},"dependencies":["row.selected"]}},{"kind":"attribute","name":"aria-disabled","expression":"row.disabled","expressionPlan":{"source":"row.disabled","ast":{"kind":"member","object":{"kind":"id","name":"row"},"key":"disabled"},"dependencies":["row.disabled"]}},{"kind":"attribute","name":"data-index","expression":"row.index","expressionPlan":{"source":"row.index","ast":{"kind":"member","object":{"kind":"id","name":"row"},"key":"index"},"dependencies":["row.index"]}}],"children":[{"kind":"slot","fallback":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"primary"},{"kind":"directive","name":"value","expression":"row.label","expressionPlan":{"source":"row.label","ast":{"kind":"member","object":{"kind":"id","name":"row"},"key":"label"},"dependencies":["row.label"]}}],"children":[]}],"nameExpression":{"source":"format('option-%s', row.id)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"option-%s"},{"kind":"member","object":{"kind":"id","name":"row"},"key":"id"}]},"dependencies":["row.id"]}}],"flow":{"kind":"each","item":"row","list":"group.rows","listPlan":{"source":"group.rows","ast":{"kind":"member","object":{"kind":"id","name":"group"},"key":"rows"},"dependencies":["group.rows"]},"key":"row.id","keyPlan":{"source":"row.id","ast":{"kind":"member","object":{"kind":"id","name":"row"},"key":"id"},"dependencies":["row.id"]}}}],"flow":{"kind":"each","item":"group","list":"groups","listPlan":{"source":"groups","ast":{"kind":"id","name":"groups"},"dependencies":["groups"]},"key":"group.name","keyPlan":{"source":"group.name","ast":{"kind":"member","object":{"kind":"id","name":"group"},"key":"name"},"dependencies":["group.name"]}}},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"option"},{"kind":"attribute","name":"active","expression":"createIndex = active","expressionPlan":{"source":"createIndex = active","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"createIndex"},"right":{"kind":"id","name":"active"}},"dependencies":["active","createIndex"]},"target":"class"},{"kind":"literal","name":"role","value":"option"},{"kind":"literal","name":"aria-selected","value":"false"},{"kind":"attribute","name":"id","expression":"format('%s-option-%s', uid, createIndex)","expressionPlan":{"source":"format('%s-option-%s', uid, createIndex)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s-option-%s"},{"kind":"id","name":"uid"},{"kind":"id","name":"createIndex"}]},"dependencies":["createIndex","uid"]}},{"kind":"attribute","name":"data-index","expression":"createIndex","expressionPlan":{"source":"createIndex","ast":{"kind":"id","name":"createIndex"},"dependencies":["createIndex"]}},{"kind":"directive","name":"value","expression":"format('Create “%s”', raw)","expressionPlan":{"source":"format('Create “%s”', raw)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"Create “%s”"},{"kind":"id","name":"raw"}]},"dependencies":["raw"]}}],"children":[],"flow":{"kind":"if","test":"creatable","testPlan":{"source":"creatable","ast":{"kind":"id","name":"creatable"},"dependencies":["creatable"]}}},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"message"},{"kind":"directive","name":"value","expression":"message","expressionPlan":{"source":"message","ast":{"kind":"id","name":"message"},"dependencies":["message"]}}],"children":[],"flow":{"kind":"if","test":"message","testPlan":{"source":"message","ast":{"kind":"id","name":"message"},"dependencies":["message"]}}}],"ref":"listbox"},{"kind":"slot","fallback":[],"name":"footer"}],"ref":"popup"},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"message"},{"kind":"attribute","name":"id","expression":"format('%s-validation', uid)","expressionPlan":{"source":"format('%s-validation', uid)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s-validation"},{"kind":"id","name":"uid"}]},"dependencies":["uid"]}},{"kind":"attribute","name":"hidden","expression":"not validation.issues.length","expressionPlan":{"source":"not validation.issues.length","ast":{"kind":"unary","op":"not","operand":{"kind":"member","object":{"kind":"member","object":{"kind":"id","name":"validation"},"key":"issues"},"key":"length"}},"dependencies":["validation.issues.length"]}}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"directive","name":"value","expression":"issue.message","expressionPlan":{"source":"issue.message","ast":{"kind":"member","object":{"kind":"id","name":"issue"},"key":"message"},"dependencies":["issue.message"]}}],"children":[],"flow":{"kind":"each","item":"issue","list":"validation.issues","listPlan":{"source":"validation.issues","ast":{"kind":"member","object":{"kind":"id","name":"validation"},"key":"issues"},"dependencies":["validation.issues"]}}}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"sr-only"},{"kind":"literal","name":"role","value":"status"},{"kind":"literal","name":"aria-live","value":"polite"},{"kind":"literal","name":"aria-atomic","value":"true"},{"kind":"directive","name":"value","expression":"statusText","expressionPlan":{"source":"statusText","ast":{"kind":"id","name":"statusText"},"dependencies":["statusText"]}}],"children":[]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"authored-options"},{"kind":"literal","name":"hidden","value":""},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[{"kind":"slot"}],"ref":"options"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-combobox-affordance-text {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-combobox-item-input-min-inline-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-combobox-item-item-max-inline-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-combobox-item-min-block-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-combobox-label-font-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-combobox-label-text {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-combobox-max-block-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-combobox-message-text {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-combobox-option-check {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-combobox-option-text {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-combobox-label-text: var(--ui-combobox-label-text);\n --_ui-combobox-label-font-size: var(--ui-combobox-label-font-size);\n --_ui-combobox-affordance-text: var(--ui-combobox-affordance-text);\n --_ui-combobox-max-block-size: var(--ui-combobox-max-block-size);\n --_ui-combobox-option-text: var(--ui-combobox-option-text);\n --_ui-combobox-message-text: var(--ui-combobox-message-text);\n --_ui-combobox-option-check: var(--ui-combobox-option-check);\n --_ui-combobox-item-min-block-size: var(--ui-combobox-item-min-block-size);\n --_ui-combobox-item-input-min-inline-size: var(--ui-combobox-item-input-min-inline-size);\n --_ui-combobox-item-item-max-inline-size: var(--ui-combobox-item-item-max-inline-size);\n\n display: grid;\n gap: var(--ui-space-1);\n min-inline-size: 0;\n color: var(--ui-text-primary);\n font: inherit;\n }\n label {\n color: var(--_ui-combobox-label-text, var(--ui-text-primary));\n font-size: var(--_ui-combobox-label-font-size, var(--ui-font-size-sm));\n font-weight: 500;\n }\n /* The field and anything that annotates it sit on one row; the help button is beside the box,\n not inside it, because a control's box holds its value. */\n .control {\n display: flex;\n align-items: center;\n gap: var(--ui-space-2);\n min-inline-size: 0;\n }\n\n .field {\n flex: 1 1 auto;\n display: flex;\n min-inline-size: 0;\n border: 1px solid var(--ui-control-border, var(--ui-border-default));\n border-radius: var(--ui-radius-md);\n background: var(--ui-control-surface, var(--ui-surface-default));\n box-shadow: var(--ui-control-inset);\n transition: border-color var(--ui-motion-fast) var(--ui-motion-ease), box-shadow var(--ui-motion-fast) var(--ui-motion-ease);\n }\n .field:focus-within {\n border-color: var(--ui-control-focus, var(--ui-accent-solid));\n box-shadow:\n var(--ui-control-inset),\n var(--ui-control-focus-halo-shadow);\n }\n /* A ghost icon button: the affordance is the mark, not a box around it. */\n .help {\n flex: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n inline-size: var(--ui-control-size-sm);\n block-size: var(--ui-control-size-sm);\n padding: 0;\n border: 0;\n border-radius: var(--ui-radius-round);\n background: transparent;\n color: var(--ui-text-secondary);\n cursor: pointer;\n transition: background-color var(--ui-motion-fast) var(--ui-motion-ease), color var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n .help:hover:enabled,\n .help[aria-expanded=\"true\"] {\n background: color-mix(in srgb, currentColor 8%, transparent);\n color: var(--ui-text-primary);\n }\n\n .help:focus-visible {\n outline: none;\n box-shadow: var(--ui-focus-halo);\n }\n\n .help:disabled {\n color: var(--ui-disabled-text);\n cursor: not-allowed;\n }\n\n .help-icon {\n inline-size: var(--ui-icon-size-sm);\n block-size: var(--ui-icon-size-sm);\n }\n\n input::selection {\n background: color-mix(in srgb, var(--ui-accent-solid) 20%, transparent);\n color: inherit;\n }\n input {\n appearance: none;\n width: 100%;\n min-inline-size: 0;\n min-block-size: calc(var(--ui-control-size-md) - 2px);\n box-sizing: border-box;\n border: 0;\n border-radius: inherit;\n background: transparent;\n color: inherit;\n font: inherit;\n line-height: var(--ui-line-height-md);\n padding: var(--ui-space-2) var(--ui-space-3);\n margin: 0;\n outline: none;\n }\n :host-state([size=\"sm\"]) input {\n min-block-size: calc(var(--ui-control-size-sm) - 2px);\n padding: var(--ui-space-1) var(--ui-space-2);\n }\n button {\n appearance: none;\n display: inline-grid;\n place-items: center;\n align-self: stretch;\n border: 0;\n border-radius: var(--ui-radius-md);\n background: transparent;\n color: var(--_ui-combobox-affordance-text, var(--ui-text-secondary));\n font: inherit;\n font-weight: 400;\n min-inline-size: 2rem;\n padding: 0 var(--ui-space-1);\n cursor: pointer;\n }\n .affordance-icon {\n display: block;\n inline-size: var(--ui-icon-size-sm);\n block-size: var(--ui-icon-size-sm);\n }\n button:hover:enabled {\n background: var(--ui-surface-muted);\n color: var(--ui-text-primary);\n }\n button:focus-visible {\n outline: none;\n background: var(--ui-surface-muted);\n box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--ui-focus-ring) 45%, transparent);\n }\n input:disabled, button:disabled {\n color: var(--ui-disabled-text);\n cursor: not-allowed;\n }\n .field:has(input:disabled) {\n background: var(--ui-control-surface-disabled, var(--ui-surface-muted));\n }\n :host-state([validationStatus=\"error\"]) .field {\n border-color: var(--ui-danger-solid, var(--ui-accent-active));\n }\n .popup {\n box-sizing: border-box;\n min-inline-size: 12rem;\n max-inline-size: calc(100vw - 1rem);\n max-block-size: var(--_ui-combobox-max-block-size, 18rem);\n overflow: auto;\n margin: 0;\n padding: var(--ui-space-1);\n border: 1px solid var(--ui-border-default);\n border-radius: var(--ui-radius-md);\n background: var(--ui-surface-elevated);\n color: var(--ui-text-primary);\n box-shadow: var(--ui-elevation-overlay, var(--ui-shadow-lg));\n }\n [hidden] {\n display: none;\n }\n .option {\n padding: var(--ui-space-2) var(--ui-space-3);\n border-radius: var(--ui-radius-sm);\n cursor: pointer;\n overflow-wrap: anywhere;\n }\n .option:hover, .option.active {\n background: var(--ui-surface-muted);\n outline: 1px solid var(--ui-focus-ring);\n outline-offset: -1px;\n }\n .option[aria-disabled=\"true\"] {\n color: var(--ui-disabled-text);\n cursor: not-allowed;\n }\n .primary {\n display: block;\n color: var(--_ui-combobox-option-text, var(--ui-text-primary));\n font-weight: 500;\n }\n .message, .group {\n color: var(--_ui-combobox-message-text, var(--ui-text-secondary));\n font-weight: 400;\n font-size: var(--ui-font-size-sm);\n line-height: var(--ui-line-height-md);\n overflow-wrap: anywhere;\n }\n .group, .popup .message {\n padding: var(--ui-space-2) var(--ui-space-3);\n }\n .sr-only {\n position: absolute;\n inline-size: 1px;\n block-size: 1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n }\n @media (pointer: coarse) {\n button {\n min-inline-size: 2.75rem;\n min-block-size: 2.75rem;\n }\n }\n @media (forced-colors: active) {\n .field, .popup {\n border-color: CanvasText;\n }\n .option.active {\n outline-color: Highlight;\n }\n }\n\n /* Multiple mode: every option carries a checkbox, so a list that takes several answers says so\n before anything is picked. aria-selected is the state; this draws it.\n Longhands, not shorthands: lowering drops a shorthand that omits a component. */\n :host-state([multiple]) .option {\n display: flex;\n gap: var(--ui-space-2);\n align-items: center;\n }\n\n :host-state([multiple]) .option::before {\n content: \"\";\n flex: none;\n inline-size: 1.125rem;\n block-size: 1.125rem;\n border-style: solid;\n border-width: 1px;\n border-color: var(--ui-control-border-hover, var(--ui-border-strong));\n border-radius: var(--ui-radius-sm);\n background-color: var(--ui-control-surface, var(--ui-surface-default));\n background-repeat: no-repeat;\n background-position: center;\n background-size: 0.7rem;\n }\n\n :host-state([multiple]) .option[aria-selected=\"true\"]::before {\n border-color: var(--ui-accent-solid);\n background-color: var(--ui-accent-solid);\n background-image: var(\n --_ui-combobox-option-check,\n url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12 5 5 9-9'/%3E%3C/svg%3E\")\n );\n }\n\n /* Multiple mode: chips wrap before the cursor on one flexible field line. */\n :host-state([multiple]) .field {\n flex-wrap: wrap;\n align-items: center;\n gap: var(--ui-space-1);\n min-block-size: var(--_ui-combobox-item-min-block-size, 2.5rem);\n padding: var(--ui-space-1);\n }\n :host-state([multiple]) input {\n flex: 1 0 var(--_ui-combobox-item-input-min-inline-size, 5rem);\n width: auto;\n min-block-size: 1.75rem;\n padding: var(--ui-space-0-5) var(--ui-space-1);\n }\n .item {\n appearance: none;\n display: inline-flex;\n min-inline-size: 0;\n max-inline-size: min(100%, var(--_ui-combobox-item-item-max-inline-size, 12rem));\n overflow: hidden;\n padding: 0;\n border: 0;\n border-radius: var(--ui-radius-sm);\n background: transparent;\n color: inherit;\n font: inherit;\n cursor: default;\n }\n .item:focus-visible {\n outline: 2px solid var(--ui-focus-ring);\n outline-offset: 1px;\n }\n .item:disabled {\n opacity: 0.6;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"internalItems","type":"list(object({ id: string, value: string, label: string, group?: string, disabled?: boolean }))","expression":{"source":"[]","ast":{"kind":"array","items":[]},"dependencies":[]}},{"kind":"state","name":"raw","expression":{"source":"''","ast":{"kind":"literal","value":""},"dependencies":[]}},{"kind":"state","name":"display","expression":{"source":"''","ast":{"kind":"literal","value":""},"dependencies":[]}},{"kind":"state","name":"selected","type":"string | null","expression":{"source":"null","ast":{"kind":"literal","value":null},"dependencies":[]}},{"kind":"state","name":"expanded","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"rows","type":"list(object({ id: string, value: string, label: string, group?: string, disabled: boolean, selected: boolean }))","expression":{"source":"[]","ast":{"kind":"array","items":[]},"dependencies":[]}},{"kind":"state","name":"active","expression":{"source":"-1","ast":{"kind":"unary","op":"-","operand":{"kind":"literal","value":1}},"dependencies":[]}},{"kind":"state","name":"loading","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"helpOpen","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"lookupError","expression":{"source":"''","ast":{"kind":"literal","value":""},"dependencies":[]}},{"kind":"state","name":"validation","type":"object({ status: pristine | pending | valid | warning | error, touched: boolean, dirty: boolean, issues: list(object({ message: string })), ... })","expression":{"source":"{ status: 'pristine', touched: false, dirty: false, issues: [] }","ast":{"kind":"object","pairs":[{"key":"status","value":{"kind":"literal","value":"pristine"}},{"key":"touched","value":{"kind":"literal","value":false}},{"key":"dirty","value":{"kind":"literal","value":false}},{"key":"issues","value":{"kind":"array","items":[]}}]},"dependencies":[]}},{"kind":"state","name":"uid","expression":{"source":"''","ast":{"kind":"literal","value":""},"dependencies":[]}},{"kind":"state","name":"submitted","expression":{"source":"''","ast":{"kind":"literal","value":""},"dependencies":[]}},{"kind":"state","name":"groups","type":"list(object({ name: string, role: group | presentation, label: string | null, rows: list(object({ id: string, value: string, label: string, group?: string, disabled: boolean, selected: boolean, index: integer })) }))","expression":{"source":"[]","ast":{"kind":"array","items":[]},"dependencies":[]}},{"kind":"state","name":"creatable","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"createIndex","expression":{"source":"0","ast":{"kind":"literal","value":0},"dependencies":[]}},{"kind":"state","name":"message","expression":{"source":"''","ast":{"kind":"literal","value":""},"dependencies":[]}},{"kind":"state","name":"statusText","expression":{"source":"''","ast":{"kind":"literal","value":""},"dependencies":[]}},{"kind":"state","name":"validationStatus","expression":{"source":"'pristine'","ast":{"kind":"literal","value":"pristine"},"dependencies":[]}},{"kind":"event","name":"query-change","type":"object({ query: string, display: string, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"value-change","type":"object({ value: string | null, query: string, option: object({ id: string, value: string, label: string, group?: string, disabled?: boolean }) | null, kind: selection | clear | free-entry | create, trigger: keyboard | pointer | programmatic }) | list(object({ id: string, value: string, label: string, group?: string, disabled?: boolean }))","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"free-entry","type":"object({ value: string | null, query: string, option: object({ id: string, value: string, label: string, group?: string, disabled?: boolean }) | null, kind: selection | clear | free-entry | create, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"create-entry","type":"object({ value: string | null, query: string, option: object({ id: string, value: string, label: string, group?: string, disabled?: boolean }) | null, kind: selection | clear | free-entry | create, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"validation-change","type":"object({ status: pristine | pending | valid | warning | error, touched: boolean, dirty: boolean, issues: list(object({ message: string, path?: list(unknown), severity?: error | warning })), output?: unknown })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"options-change","type":"list(object({ id: string, value: string, label: string, group?: string, disabled?: boolean }))","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"add-item","type":"object({ item: object({ id: string, value: string, label: string, group?: string, disabled?: boolean }), index: integer, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"remove-item","type":"object({ item: object({ id: string, value: string, label: string, group?: string, disabled?: boolean }), index: integer, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"create-item","type":"object({ query: string, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"selected-values-change","type":"object({ selectedValues: list(string), trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"method","name":"validate","exportName":"validate","returns":"promise(unknown)"},{"kind":"method","name":"focusInput","exportName":"focusInput","returns":"promise(undefined)"}],"slots":[{"dynamic":false,"required":true,"name":"start"},{"dynamic":true,"required":false},{"dynamic":true,"required":false},{"dynamic":false,"required":true,"name":"footer"},{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-combobox/ui-combobox.js"},{"source":{"file":"./components/ui-container/ui-container.html"},"contract":{"version":1,"name":"UiContainer","tag":"ui-container","nativeElement":"div","props":{"gutters":{"type":{"enum":["s","m","l"]},"required":false,"target":{"attribute":"gutters"},"description":"Inline padding on both sides, which keeps content off the edges of a narrow screen: s is 0.75rem, m is 1rem (also the default), and l is 1.5rem."},"measure":{"type":{"enum":["narrow","wide"]},"required":false,"target":{"attribute":"measure"},"description":"The container's maximum width, in characters of the current font: narrow is 45ch, wide is 80ch, and unset is 65ch, a comfortable reading line. The\n container centres itself when its parent is wider. The --ui-container-measure custom property, set on the container itself, overrides it; set on an\n ancestor, it does nothing."}}},"template":{"kind":"element","name":"div","attributes":[],"children":[{"kind":"slot"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-container-gutters {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-container-measure {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n --_container-measure: 65ch;\n --_container-gutters: var(--ui-space-4);\n display: block;\n inline-size: 100%;\n max-inline-size: var(--ui-container-measure, var(--_container-measure));\n margin-inline: auto;\n padding-inline: var(--ui-container-gutters, var(--_container-gutters));\n }\n\n :host-state([measure=\"narrow\"]) {\n --_container-measure: 45ch;\n }\n :host-state([measure=\"wide\"]) {\n --_container-measure: 80ch;\n }\n :host-state([gutters=\"s\"]) {\n --_container-gutters: var(--ui-space-3);\n }\n :host-state([gutters=\"m\"]) {\n --_container-gutters: var(--ui-space-4);\n }\n :host-state([gutters=\"l\"]) {\n --_container-gutters: var(--ui-space-5);\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]}},{"source":{"file":"./components/ui-context-menu/ui-context-menu.html"},"contract":{"version":1,"name":"UiContextMenu","tag":"ui-context-menu","nativeElement":"span","props":{"for":{"type":"string","required":false,"target":{"attribute":"for"},"description":"ID of the element whose context click (right-click, long-press, Shift+F10, or the Menu key) opens the menu.","default":""},"open":{"type":"boolean","required":false,"target":{"attribute":"open"},"description":"Whether the context menu is open initially or when set externally.","default":false}}},"template":{"kind":"element","name":"span","attributes":[],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"menu"},{"kind":"literal","name":"role","value":"menu"},{"kind":"literal","name":"aria-orientation","value":"vertical"}],"children":[{"kind":"slot"}],"ref":"menu"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-context-menu-z-index {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-context-menu-z-index: var(--ui-context-menu-z-index);\n\n display: contents;\n }\n\n .menu {\n position: fixed;\n inset: auto;\n margin: 0;\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n padding: var(--ui-space-1);\n background: var(--ui-surface-elevated);\n border: 1px solid var(--ui-border-default);\n border-radius: var(--ui-radius-lg);\n box-shadow: var(--ui-elevation-overlay, var(--ui-shadow-lg));\n outline: 0;\n overflow: auto;\n z-index: var(--_ui-context-menu-z-index, 1000);\n min-width: 12rem;\n opacity: 0;\n transform: translateY(-4px) scale(0.99);\n transition:\n opacity var(--ui-motion-fast) var(--ui-motion-ease),\n transform var(--ui-motion-fast) var(--ui-motion-ease),\n display var(--ui-motion-fast) allow-discrete,\n overlay var(--ui-motion-fast) allow-discrete;\n }\n\n .menu:popover-open {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n\n @starting-style {\n .menu:popover-open {\n opacity: 0;\n transform: translateY(-4px) scale(0.99);\n }\n }\n\n .menu[hidden],\n .menu[popover]:not(:popover-open) {\n display: none;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .menu {\n transition: none;\n }\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"internalOpen","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"event","name":"open","type":"object({ open: boolean, reason: action | programmatic | light-dismiss | escape, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"close","type":"object({ open: boolean, reason: action | programmatic | light-dismiss | escape, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"select","type":"object({ value: string, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false}],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"span","choices":["span"]},"controller":"./components/ui-context-menu/ui-context-menu.js"},{"source":{"file":"./components/ui-cover/ui-cover.html"},"contract":{"version":1,"name":"UiCover","tag":"ui-cover","nativeElement":"div","props":{"size":{"type":{"enum":["screen","fill"]},"required":false,"target":{"attribute":"size"},"description":"How tall the cover is. screen is at least the viewport's height, for a view that is one centred card, such as sign-in; fill takes the space its parent\n gives it.","default":"screen"}}},"template":{"kind":"element","name":"div","attributes":[],"children":[{"kind":"slot"}]},"css":"/* A layout primitive that centres its content in the space, both ways, with room around it: the\n frame for a view that is one card or one message. */\n :host {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: var(--ui-space-6);\n box-sizing: border-box;\n min-block-size: 100dvh;\n padding: var(--ui-space-6) var(--ui-space-4);\n }\n\n :host-state([size=\"fill\"]) {\n flex: 1;\n min-block-size: 100%;\n }\n\n :host > :slotted(*) {\n max-inline-size: 100%;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]}},{"source":{"file":"./components/ui-description-item/ui-description-item.html"},"contract":{"version":1,"name":"UiDescriptionItem","tag":"ui-description-item","nativeElement":"div","props":{"term":{"type":"string","required":false,"target":{"attribute":"term"},"description":"What the value is, such as \"Invited by\". The value is the item's content.","default":""}}},"template":{"kind":"element","name":"div","attributes":[],"children":[{"kind":"element","name":"dt","attributes":[],"children":[{"kind":"element","name":"template","attributes":[{"kind":"directive","name":"value","expression":"term","expressionPlan":{"source":"term","ast":{"kind":"id","name":"term"},"dependencies":["term"]}}],"children":[]}]},{"kind":"element","name":"dd","attributes":[],"children":[{"kind":"slot"}]}]},"css":"/* One term and its value in a ui-description-list, laid out by the list's layout. */\n :host {\n display: var(--_ui-description-display, grid);\n grid-column: var(--_ui-description-column, 1 / -1);\n grid-template-columns: subgrid;\n flex-direction: column;\n align-items: var(--_ui-description-align, baseline);\n gap: var(--ui-space-1) var(--ui-space-6);\n min-inline-size: 0;\n padding: var(--_ui-description-padding, 0);\n border-width: var(--_ui-description-border-width, 0);\n border-style: solid;\n border-color: var(--ui-border-default);\n border-radius: var(--ui-radius-md);\n font-size: var(--ui-font-size-sm);\n }\n\n dt {\n color: var(--ui-text-muted);\n }\n\n dd {\n margin: 0;\n min-inline-size: 0;\n color: var(--ui-text-primary);\n font-weight: var(--ui-font-medium);\n font-size: var(--_ui-description-value-size, inherit);\n text-align: start;\n overflow-wrap: anywhere;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]}},{"source":{"file":"./components/ui-description-list/ui-description-list.html"},"contract":{"version":1,"name":"UiDescriptionList","tag":"ui-description-list","nativeElement":"dl","props":{"layout":{"type":{"enum":["rows","tiles"]},"required":false,"target":{"attribute":"layout"},"description":"rows sets each term beside its value, one per line, for a short summary; tiles sets each pair on its own bordered tile in a grid, term above value, for\n figures and facts to scan.","default":"rows"}}},"template":{"kind":"element","name":"dl","attributes":[],"children":[{"kind":"slot"}]},"css":"/* Named values: a term and what it is, for each item (ui-description-item). */\n /* Rows line every term up in one column and every value in the next, through subgrid. */\n :host {\n display: grid;\n grid-template-columns: minmax(6rem, max-content) minmax(0, 1fr);\n gap: var(--ui-space-2) var(--ui-space-6);\n min-inline-size: 0;\n margin: 0;\n }\n\n /* Tiles pass their shape to the items through private properties, which cross into each item. */\n :host-state([layout=\"tiles\"]) {\n --_ui-description-display: flex;\n --_ui-description-column: auto;\n --_ui-description-align: flex-start;\n --_ui-description-value-size: var(--ui-font-size-lg);\n --_ui-description-padding: var(--ui-space-3);\n --_ui-description-border-width: 1px;\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(min(100%, 10rem), 1fr));\n gap: var(--ui-space-3);\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"dl","choices":["dl"]}},{"source":{"file":"./components/ui-dialog/ui-dialog.html"},"contract":{"version":1,"name":"UiDialog","tag":"ui-dialog","nativeElement":"dialog","props":{"dismissible":{"type":"boolean","required":false,"target":{"attribute":"dismissible"},"description":"Also close on Escape and on a pointer press outside the dialog. The header close button and actions always close it.","default":false},"for":{"type":"string","required":false,"target":{"attribute":"for"},"description":"ID of the control that opens the dialog.","default":""},"label":{"type":"string","required":false,"target":{"attribute":"label"},"description":"Visible title in the dialog header; also its accessible name."},"modal":{"type":"boolean","required":false,"target":{"attribute":"modal"},"description":"Open in the top layer with a backdrop and make the rest of the page inert.","default":false},"open":{"type":"boolean","required":false,"target":{"attribute":"open"},"description":"Whether the dialog is open initially or when set externally.","default":false}}},"template":{"kind":"element","name":"dialog","attributes":[{"kind":"attribute","name":"aria-label","expression":"accessibleLabel","expressionPlan":{"source":"accessibleLabel","ast":{"kind":"id","name":"accessibleLabel"},"dependencies":["accessibleLabel"]}}],"children":[{"kind":"element","name":"header","attributes":[],"children":[{"kind":"element","name":"h2","attributes":[{"kind":"literal","name":"class","value":"title"},{"kind":"directive","name":"value","expression":"label","expressionPlan":{"source":"label","ast":{"kind":"id","name":"label"},"dependencies":["label"]}}],"children":[],"flow":{"kind":"if","test":"label","testPlan":{"source":"label","ast":{"kind":"id","name":"label"},"dependencies":["label"]}}},{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"class","value":"close"},{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"aria-label","value":"Close"}],"children":[],"ref":"close"}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"body"}],"children":[{"kind":"slot"}]},{"kind":"element","name":"footer","attributes":[],"children":[{"kind":"slot","fallback":[],"name":"actions"}]}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-dialog-duration {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-dialog-max-width {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-dialog-viewport-gap {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-dialog-duration: var(--ui-dialog-duration);\n\n position: fixed;\n inset: 0;\n box-sizing: border-box;\n inline-size: min(\n calc(100% - var(--ui-dialog-viewport-gap, var(--ui-space-4)) * 2),\n var(--ui-dialog-max-width, 440px)\n );\n max-inline-size: none;\n max-block-size: calc(100dvh - var(--ui-dialog-viewport-gap, var(--ui-space-4)) * 2);\n margin: auto;\n padding: 0;\n overflow: hidden;\n flex-direction: column;\n background: var(--ui-surface-elevated);\n border: 1px solid var(--ui-border-default);\n border-radius: var(--ui-radius-dialog);\n box-shadow: var(--ui-elevation-dialog, var(--ui-shadow-xl));\n visibility: hidden;\n pointer-events: none;\n opacity: 0;\n transform: scale(0.96);\n transition:\n opacity var(--ui-dialog-duration, var(--ui-motion-base)) var(--ui-motion-ease),\n transform var(--ui-dialog-duration, var(--ui-motion-base)) var(--ui-motion-ease),\n visibility var(--ui-dialog-duration, var(--ui-motion-base)),\n display var(--ui-dialog-duration, var(--ui-motion-base)) var(--ui-motion-ease) allow-discrete,\n overlay var(--ui-dialog-duration, var(--ui-motion-base)) var(--ui-motion-ease) allow-discrete;\n }\n\n :host[open] {\n display: flex;\n visibility: visible;\n pointer-events: auto;\n opacity: 1;\n transform: scale(1);\n animation: ui-dialog-enter var(--ui-dialog-duration, var(--ui-motion-base)) var(--ui-motion-ease);\n }\n\n /* Header and actions stay pinned; only the body scrolls when content is long. */\n header {\n display: flex;\n align-items: center;\n gap: var(--ui-space-3);\n flex: none;\n padding: var(--ui-space-3) var(--ui-space-3) var(--ui-space-3) var(--ui-space-5);\n border-block-end: 1px solid var(--ui-border-default);\n }\n\n /* :host-qualified so page heading rules that reach in cannot outrank the dialog chrome. */\n :host .title {\n flex: 1;\n min-inline-size: 0;\n margin: 0;\n padding: 0;\n border: 0;\n color: var(--ui-text-primary);\n letter-spacing: normal;\n font-size: var(--ui-font-size-lg);\n font-weight: var(--ui-font-semibold);\n line-height: var(--ui-line-height-tight);\n }\n\n .close {\n display: inline-grid;\n place-items: center;\n flex: none;\n margin-inline-start: auto;\n inline-size: var(--ui-control-size-sm);\n block-size: var(--ui-control-size-sm);\n padding: 0;\n border: 0;\n border-radius: var(--ui-radius-round);\n background: transparent;\n color: var(--ui-text-secondary);\n cursor: pointer;\n transition: background-color var(--ui-motion-fast) var(--ui-motion-ease), color var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n /* A CSS-drawn X. */\n .close::before,\n .close::after {\n content: \"\";\n grid-area: 1 / 1;\n inline-size: 0.875rem;\n block-size: 1.5px;\n border-radius: 1px;\n background: currentColor;\n transform: rotate(45deg);\n }\n\n .close::after {\n transform: rotate(-45deg);\n }\n\n .close:hover {\n background: var(--ui-surface-muted);\n color: var(--ui-text-primary);\n }\n\n .close:focus-visible {\n outline: 2px solid var(--ui-focus-ring);\n outline-offset: 2px;\n }\n\n /* A touch target, like Button on coarse pointers. */\n @media (pointer: coarse) {\n .close {\n inline-size: var(--ui-control-min-block-size);\n block-size: var(--ui-control-min-block-size);\n }\n }\n\n html[data-ui-input-modality=\"touch\"] :host .close {\n inline-size: var(--ui-control-min-block-size);\n block-size: var(--ui-control-min-block-size);\n }\n\n .body {\n flex: 1 1 auto;\n min-block-size: 0;\n overflow: auto;\n overscroll-behavior: contain;\n padding: var(--ui-space-5);\n /* Each edge that hides content fades: the scroll fade every Looma scroller uses (see ui-scroll-area). */\n --_ui-scroll-fade-direction: to bottom;\n --_ui-scroll-fade-size: var(--ui-scroll-fade-size, 24px);\n mask-image: linear-gradient(\n var(--_ui-scroll-fade-direction),\n transparent,\n #000 var(--_ui-scroll-fade-start),\n #000 calc(100% - var(--_ui-scroll-fade-end)),\n transparent\n );\n animation: ui-scroll-fade-start linear, ui-scroll-fade-start-hold linear, ui-scroll-fade-end-hold linear, ui-scroll-fade-end linear;\n animation-timeline: scroll(self block);\n animation-range:\n 0 var(--_ui-scroll-fade-size),\n var(--_ui-scroll-fade-size) calc(100% + 1px),\n -1px calc(100% - var(--_ui-scroll-fade-size)),\n calc(100% - var(--_ui-scroll-fade-size)) 100%;\n }\n\n footer {\n display: flex;\n flex: none;\n flex-wrap: wrap;\n justify-content: flex-end;\n gap: var(--ui-space-2);\n padding: var(--ui-space-3) var(--ui-space-5);\n border-block-start: 1px solid var(--ui-border-default);\n }\n\n footer:empty {\n display: none;\n }\n\n @keyframes ui-dialog-enter {\n from {\n opacity: 0;\n transform: scale(0.96);\n }\n }\n\n :host::backdrop {\n background-color: transparent;\n transition:\n background-color var(--_ui-dialog-duration, var(--ui-motion-base)) var(--ui-motion-ease),\n display var(--_ui-dialog-duration, var(--ui-motion-base)) var(--ui-motion-ease) allow-discrete,\n overlay var(--_ui-dialog-duration, var(--ui-motion-base)) var(--ui-motion-ease) allow-discrete;\n }\n\n :host[open]::backdrop {\n background-color: var(--ui-overlay-backdrop);\n animation: ui-dialog-backdrop-enter var(--_ui-dialog-duration, var(--ui-motion-base)) var(--ui-motion-ease);\n }\n\n @keyframes ui-dialog-backdrop-enter {\n from {\n background-color: transparent;\n }\n }","declarations":[{"kind":"state","name":"internalOpen","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"accessibleLabel","expression":{"source":"'Dialog'","ast":{"kind":"literal","value":"Dialog"},"dependencies":[]}},{"kind":"event","name":"close","type":"object({ open: boolean, reason: action | programmatic | light-dismiss | escape, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false}],"slots":[{"dynamic":false,"required":true},{"dynamic":false,"required":true,"name":"actions"}],"root":{"kind":"native","element":"dialog","choices":["dialog"]},"controller":"./components/ui-dialog/ui-dialog.js"},{"source":{"file":"./components/ui-disclosure/ui-disclosure.html"},"contract":{"version":1,"name":"UiDisclosure","tag":"ui-disclosure","nativeElement":"div","props":{"density":{"type":{"enum":["comfortable","compact"]},"required":false,"target":{"attribute":"density"},"description":"Compact trades padding and type size for rows that fit more on screen.","default":"comfortable"},"disabled":{"type":"boolean","required":false,"target":{"attribute":"disabled"},"description":"Disables the trigger and mutes its text, so the disclosure keeps its current state and the user cannot toggle it.","default":false},"open":{"type":"boolean","required":false,"target":{"attribute":"open"},"description":"Whether the disclosure is open initially or when set externally. The trigger toggles it from there, reporting each change as an open or close event.","default":false},"summary":{"type":"string","required":false,"target":{"attribute":"summary"},"description":"The text of the trigger row that opens and closes the disclosure. It is the trigger button's accessible name, so name what the content is.","default":"Details"}}},"template":{"kind":"element","name":"div","attributes":[],"children":[{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"class","value":"trigger"},{"kind":"literal","name":"type","value":"button"},{"kind":"attribute","name":"aria-controls","expression":"contentId","expressionPlan":{"source":"contentId","ast":{"kind":"id","name":"contentId"},"dependencies":["contentId"]}},{"kind":"attribute","name":"aria-expanded","expression":"internalOpen","expressionPlan":{"source":"internalOpen","ast":{"kind":"id","name":"internalOpen"},"dependencies":["internalOpen"]}},{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"directive","name":"value","expression":"summary","expressionPlan":{"source":"summary","ast":{"kind":"id","name":"summary"},"dependencies":["summary"]}}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"chevron"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[]}],"ref":"trigger"},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"panel"},{"kind":"attribute","name":"id","expression":"contentId","expressionPlan":{"source":"contentId","ast":{"kind":"id","name":"contentId"},"dependencies":["contentId"]}},{"kind":"attribute","name":"inert","expression":"not internalOpen","expressionPlan":{"source":"not internalOpen","ast":{"kind":"unary","op":"not","operand":{"kind":"id","name":"internalOpen"}},"dependencies":["internalOpen"]}}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"panel-inner"}],"children":[{"kind":"slot"}]}]}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-disclosure-trigger-min-block-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-disclosure-trigger-padding-block {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-disclosure-trigger-padding-inline {\n syntax: \"*\";\n inherits: false;\n }\n\n /* Density resolves into the summary row's own values; the public tokens still override them. */\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-disclosure-trigger-min-block-size: var(--ui-disclosure-trigger-min-block-size);\n --_ui-disclosure-trigger-padding-block: var(--ui-disclosure-trigger-padding-block);\n --_ui-disclosure-trigger-padding-inline: var(--ui-disclosure-trigger-padding-inline);\n\n --_trigger-min-block-size: var(--ui-control-size);\n --_trigger-padding-block: var(--ui-space-2);\n --_trigger-padding-inline: var(--ui-space-3);\n }\n\n :host-state([density=\"compact\"]) {\n --_trigger-min-block-size: var(--ui-control-size-sm);\n --_trigger-padding-block: var(--ui-space-1);\n --_trigger-padding-inline: var(--ui-space-2);\n }\n\n /* An accordion row, not a field: no enclosing box, just a divider, so it never reads as a\n * select or combobox. Stacked disclosures share their dividers. */\n :host {\n display: block;\n inline-size: 100%;\n overflow: clip;\n border-block-end: 1px solid var(--ui-border-default);\n color: var(--ui-text-primary);\n }\n\n .trigger {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n gap: var(--ui-space-3);\n align-items: center;\n inline-size: 100%;\n min-block-size: var(--_ui-disclosure-trigger-min-block-size, var(--_trigger-min-block-size));\n padding: var(--_ui-disclosure-trigger-padding-block, var(--_trigger-padding-block))\n var(--_ui-disclosure-trigger-padding-inline, var(--_trigger-padding-inline));\n border: 0;\n background: transparent;\n color: inherit;\n font: inherit;\n font-weight: var(--ui-font-semibold);\n text-align: start;\n cursor: pointer;\n border-radius: var(--ui-radius-sm);\n transition: background-color var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n .trigger:hover:not(:disabled) {\n background: var(--ui-surface-muted);\n }\n .trigger:focus-visible {\n outline: none;\n box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--ui-focus-ring) 45%, transparent);\n }\n .trigger:disabled {\n color: var(--ui-disabled-text);\n cursor: not-allowed;\n }\n\n .chevron {\n inline-size: 0.5rem;\n block-size: 0.5rem;\n border-inline-end: 2px solid currentColor;\n border-block-end: 2px solid currentColor;\n transform: rotate(45deg) translate(-1px, -1px);\n transition: transform var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n .panel {\n display: grid;\n grid-template-rows: 0fr;\n transition: grid-template-rows var(--ui-motion-fast) var(--ui-motion-ease-out, var(--ui-motion-ease));\n }\n\n .panel-inner {\n min-block-size: 0;\n overflow: hidden;\n padding-inline: var(--ui-space-3);\n }\n\n :host-state([internalOpen]) .panel {\n grid-template-rows: 1fr;\n }\n :host-state([internalOpen]) .panel-inner {\n padding-block: 0 var(--ui-space-3);\n }\n :host-state([internalOpen]) .chevron {\n transform: rotate(225deg) translate(-1px, -1px);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .panel,\n .chevron {\n transition: none;\n }\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"internalOpen","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"contentId","expression":{"source":"''","ast":{"kind":"literal","value":""},"dependencies":[]}},{"kind":"event","name":"open","type":"object({ open: boolean, reason: action | programmatic | light-dismiss | escape, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"close","type":"object({ open: boolean, reason: action | programmatic | light-dismiss | escape, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false}],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-disclosure/ui-disclosure.js"},{"source":{"file":"./components/ui-editable/ui-editable.html"},"contract":{"version":1,"name":"UiEditable","tag":"ui-editable","nativeElement":"div","props":{"actions":{"type":"boolean","required":false,"target":{"attribute":"actions"},"description":"Show explicit Save and Cancel buttons while editing. Without them, Enter or leaving the field saves and Escape cancels.","default":false},"disabled":{"type":"boolean","required":false,"target":{"attribute":"disabled"},"description":"Prevents entering or changing edit mode.","default":false},"edit":{"type":"boolean","required":false,"target":{"attribute":"edit"},"description":"Whether edit mode is active initially or when set externally.","default":false},"hint":{"type":"string","required":false,"target":{"attribute":"hint"},"description":"Optional text shown beside the value to signal it is editable (for example \"Edit\").","default":""},"label":{"type":"string","required":false,"target":{"attribute":"aria-label"},"description":"Accessible name for the editor.","default":"Edit value"},"value":{"type":"string","required":false,"target":{"attribute":"value"},"description":"The displayed value, and the text the editor starts from. It is not a form field: nothing is submitted with a form, so a form that needs the value copies\n it from the change event into a field of its own.","default":""}}},"template":{"kind":"element","name":"div","attributes":[],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"field"}],"children":[{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"class","value":"preview"},{"kind":"literal","name":"type","value":"button"},{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"text"},{"kind":"directive","name":"value","expression":"internalValue","expressionPlan":{"source":"internalValue","ast":{"kind":"id","name":"internalValue"},"dependencies":["internalValue"]}}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"hint"},{"kind":"literal","name":"aria-hidden","value":"true"},{"kind":"directive","name":"value","expression":"hint","expressionPlan":{"source":"hint","ast":{"kind":"id","name":"hint"},"dependencies":["hint"]}}],"children":[],"flow":{"kind":"if","test":"hint","testPlan":{"source":"hint","ast":{"kind":"id","name":"hint"},"dependencies":["hint"]}}}],"ref":"preview"},{"kind":"element","name":"input","attributes":[{"kind":"literal","name":"class","value":"input"},{"kind":"literal","name":"type","value":"text"},{"kind":"property","key":"value","name":"value","expression":"draft","expressionPlan":{"source":"draft","ast":{"kind":"id","name":"draft"},"dependencies":["draft"]}},{"kind":"attribute","name":"aria-label","expression":"label","expressionPlan":{"source":"label","ast":{"kind":"id","name":"label"},"dependencies":["label"]}},{"kind":"attribute","name":"disabled","expression":"disabled or not internalEdit","expressionPlan":{"source":"disabled or not internalEdit","ast":{"kind":"binary","op":"or","left":{"kind":"id","name":"disabled"},"right":{"kind":"unary","op":"not","operand":{"kind":"id","name":"internalEdit"}}},"dependencies":["disabled","internalEdit"]}}],"children":[],"ref":"input"}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"actions"}],"children":[{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"class","value":"save"},{"kind":"literal","name":"type","value":"button"}],"children":[{"kind":"text","value":"Save"}]},{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"class","value":"cancel"},{"kind":"literal","name":"type","value":"button"}],"children":[{"kind":"text","value":"Cancel"}]}],"flow":{"kind":"if","test":"actions","testPlan":{"source":"actions","ast":{"kind":"id","name":"actions"},"dependencies":["actions"]}}}]},"css":":host {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--ui-space-2);\n min-inline-size: 0;\n color: var(--ui-text-primary);\n }\n\n /* The value and the input share one grid cell with identical box metrics, so switching between\n * display and edit never changes the control's size or moves the text. */\n .field {\n display: inline-grid;\n min-inline-size: 8rem;\n max-inline-size: 100%;\n }\n\n .preview,\n .input {\n grid-area: 1 / 1;\n box-sizing: border-box;\n min-block-size: var(--ui-control-size-sm);\n margin: 0;\n padding: var(--ui-space-1) var(--ui-space-2);\n border: 1px solid transparent;\n border-radius: var(--ui-radius-md);\n font: inherit;\n line-height: var(--ui-line-height-md);\n color: inherit;\n transition:\n background-color var(--ui-motion-fast) var(--ui-motion-ease),\n border-color var(--ui-motion-fast) var(--ui-motion-ease),\n box-shadow var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n .preview {\n display: inline-flex;\n gap: var(--ui-space-2);\n align-items: center;\n background: transparent;\n text-align: start;\n cursor: pointer;\n }\n\n .preview:hover:not(:disabled) {\n background: var(--ui-surface-muted);\n }\n\n .preview:focus-visible {\n outline: none;\n box-shadow: var(--ui-focus-halo);\n }\n\n .hint {\n color: var(--ui-text-secondary);\n font-size: var(--ui-font-size-sm);\n }\n\n /* Contained so it takes the value's width instead of its own default input width. */\n .input {\n contain: inline-size;\n inline-size: 100%;\n min-inline-size: 0;\n visibility: hidden;\n background: var(--ui-control-surface, var(--ui-surface-elevated));\n }\n\n .input:focus {\n outline: none;\n border-color: var(--ui-control-focus, var(--ui-accent-solid));\n box-shadow:\n var(--ui-control-inset),\n var(--ui-control-focus-halo-shadow);\n }\n\n .input::selection {\n background: color-mix(in srgb, var(--ui-accent-solid) 20%, transparent);\n }\n\n :host-state([internalEdit]) .preview {\n visibility: hidden;\n }\n :host-state([internalEdit]) .input {\n visibility: visible;\n }\n\n .actions {\n display: none;\n gap: var(--ui-space-1);\n }\n :host-state([internalEdit]) .actions {\n display: inline-flex;\n }\n\n .actions button {\n min-block-size: var(--ui-control-size-sm);\n padding: 0 var(--ui-space-3);\n border: 1px solid var(--ui-border-strong);\n border-radius: var(--ui-radius-md);\n background: var(--ui-surface-elevated);\n background-image: var(--ui-raised-highlight);\n box-shadow: var(--ui-raised);\n color: inherit;\n font: inherit;\n font-size: var(--ui-font-size-sm);\n cursor: pointer;\n }\n\n .actions .save {\n border-color: var(--ui-accent-solid);\n background: var(--ui-accent-solid);\n color: var(--ui-text-on-accent);\n }\n\n .actions button:focus-visible {\n outline: none;\n box-shadow: var(--ui-focus-halo);\n }\n\n :host-state([disabled]) .preview {\n color: var(--ui-disabled-text);\n cursor: not-allowed;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"internalEdit","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"internalValue","expression":{"source":"''","ast":{"kind":"literal","value":""},"dependencies":[]}},{"kind":"state","name":"draft","expression":{"source":"''","ast":{"kind":"literal","value":""},"dependencies":[]}},{"kind":"event","name":"input","type":"object({ value: string, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"change","type":"object({ value: string, previousValue: string, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"edit-change","type":"object({ edit: boolean, reason: activate | commit | cancel | light-dismiss | escape | programmatic, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false}],"slots":[],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-editable/ui-editable.js"},{"source":{"file":"./components/ui-editor-insert-table-grid/ui-editor-insert-table-grid.html"},"contract":{"version":1,"name":"UiEditorInsertTableGrid","tag":"ui-editor-insert-table-grid","nativeElement":"div","props":{"headerRow":{"type":"boolean","required":false,"target":{"attribute":"headerrow"},"description":"Whether table insertion initially includes a header row.","default":false},"maxCols":{"type":{"kind":"terminal","name":"integer"},"required":false,"target":{"attribute":"maxcols"},"description":"The most columns the grid offers (at most 10).","default":8},"maxRows":{"type":{"kind":"terminal","name":"integer"},"required":false,"target":{"attribute":"maxrows"},"description":"The most rows the grid offers (at most 10).","default":8},"open":{"type":"boolean","required":false,"target":{"attribute":"open"},"description":"Whether the grid is shown.","default":false}}},"template":{"kind":"element","name":"div","attributes":[{"kind":"attribute","name":"hidden","expression":"not open","expressionPlan":{"source":"not open","ast":{"kind":"unary","op":"not","operand":{"kind":"id","name":"open"}},"dependencies":["open"]}}],"children":[{"kind":"element","name":"p","attributes":[{"kind":"literal","name":"class","value":"hint"},{"kind":"directive","name":"value","expression":"hint","expressionPlan":{"source":"hint","ast":{"kind":"id","name":"hint"},"dependencies":["hint"]}}],"children":[]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"grid"},{"kind":"literal","name":"role","value":"group"},{"kind":"literal","name":"aria-label","value":"Table dimensions"},{"kind":"attribute","name":"--_rows","expression":"rows","expressionPlan":{"source":"rows","ast":{"kind":"id","name":"rows"},"dependencies":["rows"]},"target":"style"},{"kind":"attribute","name":"--_cols","expression":"cols","expressionPlan":{"source":"cols","ast":{"kind":"id","name":"cols"},"dependencies":["cols"]},"target":"style"}],"children":[{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"class","value":"cell"},{"kind":"attribute","name":"selected","expression":"cell.selected","expressionPlan":{"source":"cell.selected","ast":{"kind":"member","object":{"kind":"id","name":"cell"},"key":"selected"},"dependencies":["cell.selected"]},"target":"class"},{"kind":"attribute","name":"data-row","expression":"cell.row","expressionPlan":{"source":"cell.row","ast":{"kind":"member","object":{"kind":"id","name":"cell"},"key":"row"},"dependencies":["cell.row"]}},{"kind":"attribute","name":"data-col","expression":"cell.col","expressionPlan":{"source":"cell.col","ast":{"kind":"member","object":{"kind":"id","name":"cell"},"key":"col"},"dependencies":["cell.col"]}},{"kind":"attribute","name":"aria-label","expression":"cell.label","expressionPlan":{"source":"cell.label","ast":{"kind":"member","object":{"kind":"id","name":"cell"},"key":"label"},"dependencies":["cell.label"]}},{"kind":"attribute","name":"aria-pressed","expression":"cell.selected","expressionPlan":{"source":"cell.selected","ast":{"kind":"member","object":{"kind":"id","name":"cell"},"key":"selected"},"dependencies":["cell.selected"]}}],"children":[],"flow":{"kind":"each","item":"cell","list":"cells","listPlan":{"source":"cells","ast":{"kind":"id","name":"cells"},"dependencies":["cells"]},"key":"cell.key","keyPlan":{"source":"cell.key","ast":{"kind":"member","object":{"kind":"id","name":"cell"},"key":"key"},"dependencies":["cell.key"]}}}]},{"kind":"element","name":"label","attributes":[{"kind":"literal","name":"class","value":"header"}],"children":[{"kind":"element","name":"input","attributes":[{"kind":"literal","name":"type","value":"checkbox"},{"kind":"property","key":"checked","name":"checked","expression":"withHeaderRow","expressionPlan":{"source":"withHeaderRow","ast":{"kind":"id","name":"withHeaderRow"},"dependencies":["withHeaderRow"]}}],"children":[],"ref":"header"},{"kind":"text","value":" Header row"}]},{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"class","value":"insert"}],"children":[{"kind":"text","value":"Insert table"}],"ref":"insert"}]},"css":":host {\n padding: var(--ui-space-3);\n background: var(--ui-surface);\n border: 1px solid var(--ui-border);\n border-radius: var(--ui-radius-md);\n box-shadow: var(--ui-shadow-lg, 0 10px 15px -3px rgb(0 0 0 / 0.1));\n }\n\n .hint {\n margin: 0 0 var(--ui-space-2);\n font-size: var(--ui-font-size-sm);\n color: var(--ui-text-muted);\n }\n\n .grid {\n display: grid;\n grid-template-columns: repeat(var(--_cols, 8), 1.25rem);\n grid-template-rows: repeat(var(--_rows, 8), 1.25rem);\n gap: 2px;\n margin-bottom: var(--ui-space-2);\n }\n\n .cell {\n width: 1.25rem;\n height: 1.25rem;\n padding: 0;\n border: 1px solid var(--ui-border);\n border-radius: 2px;\n background: var(--ui-surface);\n cursor: pointer;\n }\n\n .cell.selected {\n background: var(--ui-accent-solid, var(--ui-accent));\n border-color: var(--ui-accent-solid, var(--ui-accent));\n }\n\n .header {\n display: block;\n margin-bottom: var(--ui-space-2);\n font-size: var(--ui-font-size-sm);\n cursor: pointer;\n }\n\n :host .insert {\n width: 100%;\n padding: var(--ui-space-2) var(--ui-space-3);\n border: 1px solid var(--ui-border);\n border-radius: var(--ui-radius-sm);\n background: var(--ui-accent-solid, var(--ui-accent));\n color: var(--ui-accent-contrast);\n font-size: var(--ui-font-size-sm);\n cursor: pointer;\n }\n\n :host .insert:hover {\n filter: brightness(1.05);\n }\n\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"cells","type":"list(object({ key: string, row: integer, col: integer, label: string, selected: boolean }))","expression":{"source":"[]","ast":{"kind":"array","items":[]},"dependencies":[]}},{"kind":"state","name":"rows","expression":{"source":"8","ast":{"kind":"literal","value":8},"dependencies":[]}},{"kind":"state","name":"cols","expression":{"source":"8","ast":{"kind":"literal","value":8},"dependencies":[]}},{"kind":"state","name":"hint","expression":{"source":"''","ast":{"kind":"literal","value":""},"dependencies":[]}},{"kind":"state","name":"withHeaderRow","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"event","name":"insert","type":"object({ rows: integer, cols: integer, withHeaderRow: boolean })","bubbles":true,"composed":true,"cancelable":false}],"slots":[],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-editor-insert-table-grid/ui-editor-insert-table-grid.js"},{"source":{"file":"./components/ui-editor-mention-menu/ui-editor-mention-menu.html"},"contract":{"version":1,"name":"UiEditorMentionMenu","tag":"ui-editor-mention-menu","nativeElement":"div","props":{"anchorRect":{"type":{"kind":"union","members":[{"kind":"object","fields":[{"name":"left","type":{"kind":"terminal","name":"number"},"optional":true},{"name":"top","type":{"kind":"terminal","name":"number"},"optional":true},{"name":"right","type":{"kind":"terminal","name":"number"},"optional":true},{"name":"bottom","type":{"kind":"terminal","name":"number"},"optional":true},{"name":"x","type":{"kind":"terminal","name":"number"},"optional":true},{"name":"y","type":{"kind":"terminal","name":"number"},"optional":true},{"name":"width","type":{"kind":"terminal","name":"number"},"optional":true},{"name":"height","type":{"kind":"terminal","name":"number"},"optional":true}],"open":false},{"kind":"terminal","name":"null"}]},"required":false,"target":{"attribute":"anchorrect"},"description":"Where the @ was typed, in viewport coordinates."},"items":{"type":{"kind":"list","item":{"kind":"object","fields":[{"name":"id","type":{"kind":"terminal","name":"string"},"optional":false},{"name":"label","type":{"kind":"terminal","name":"string"},"optional":false},{"name":"detail","type":{"kind":"terminal","name":"string"},"optional":true},{"name":"initials","type":{"kind":"terminal","name":"string"},"optional":true}],"open":false}},"required":false,"target":{"attribute":"items"},"description":"The people the menu offers."},"loading":{"type":"boolean","required":false,"target":{"attribute":"aria-busy"},"description":"Whether a search is in progress.","default":false},"open":{"type":"boolean","required":false,"target":{"attribute":"open"},"description":"Whether the menu is open.","default":false},"query":{"type":"string","required":false,"target":{"attribute":"query"},"description":"The text typed after the @.","default":""},"selectedIndex":{"type":{"kind":"terminal","name":"integer"},"required":false,"target":{"attribute":"selectedindex"},"description":"The zero-based index of the highlighted person, capped at the last one shown, and announced through aria-activedescendant. The menu does not handle arrow\n keys itself: the editor sets this as the user moves, while hovering a person highlights them and reports a highlight event.","default":0}}},"template":{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"role","value":"listbox"},{"kind":"literal","name":"aria-label","value":"Mention a person"},{"kind":"attribute","name":"aria-busy","expression":"loading","expressionPlan":{"source":"loading","ast":{"kind":"id","name":"loading"},"dependencies":["loading"]}},{"kind":"attribute","name":"hidden","expression":"not visible","expressionPlan":{"source":"not visible","ast":{"kind":"unary","op":"not","operand":{"kind":"id","name":"visible"}},"dependencies":["visible"]}}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"header"}],"children":[{"kind":"element","name":"span","attributes":[],"children":[{"kind":"text","value":"People"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"hint"}],"children":[{"kind":"text","value":"Type after @ to search"}]}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"loading"},{"kind":"literal","name":"role","value":"status"}],"children":[{"kind":"text","value":"Searching…"}],"flow":{"kind":"if","test":"searching","testPlan":{"source":"searching","ast":{"kind":"id","name":"searching"},"dependencies":["searching"]}}},{"kind":"element","name":"ul","attributes":[{"kind":"literal","name":"class","value":"list"},{"kind":"literal","name":"role","value":"presentation"}],"children":[{"kind":"element","name":"li","attributes":[{"kind":"attribute","name":"id","expression":"format('%s-option-%s', prefix, index)","expressionPlan":{"source":"format('%s-option-%s', prefix, index)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s-option-%s"},{"kind":"id","name":"prefix"},{"kind":"id","name":"index"}]},"dependencies":["index","prefix"]}},{"kind":"literal","name":"class","value":"item"},{"kind":"attribute","name":"active","expression":"index = active","expressionPlan":{"source":"index = active","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"index"},"right":{"kind":"id","name":"active"}},"dependencies":["active","index"]},"target":"class"},{"kind":"literal","name":"role","value":"option"},{"kind":"attribute","name":"aria-selected","expression":"index = active","expressionPlan":{"source":"index = active","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"index"},"right":{"kind":"id","name":"active"}},"dependencies":["active","index"]}},{"kind":"attribute","name":"data-index","expression":"index","expressionPlan":{"source":"index","ast":{"kind":"id","name":"index"},"dependencies":["index"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"avatar"},{"kind":"literal","name":"aria-hidden","value":"true"},{"kind":"directive","name":"value","expression":"row.initials","expressionPlan":{"source":"row.initials","ast":{"kind":"member","object":{"kind":"id","name":"row"},"key":"initials"},"dependencies":["row.initials"]}}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"body"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"label"},{"kind":"directive","name":"value","expression":"row.label","expressionPlan":{"source":"row.label","ast":{"kind":"member","object":{"kind":"id","name":"row"},"key":"label"},"dependencies":["row.label"]}}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"detail"},{"kind":"directive","name":"value","expression":"row.detail","expressionPlan":{"source":"row.detail","ast":{"kind":"member","object":{"kind":"id","name":"row"},"key":"detail"},"dependencies":["row.detail"]}}],"children":[],"flow":{"kind":"if","test":"row.detail","testPlan":{"source":"row.detail","ast":{"kind":"member","object":{"kind":"id","name":"row"},"key":"detail"},"dependencies":["row.detail"]}}}]}],"flow":{"kind":"each","item":"row","list":"rows","listPlan":{"source":"rows","ast":{"kind":"id","name":"rows"},"dependencies":["rows"]},"index":"index"}}],"flow":{"kind":"if","test":"not searching","testPlan":{"source":"not searching","ast":{"kind":"unary","op":"not","operand":{"kind":"id","name":"searching"}},"dependencies":["searching"]}}}]},"css":":host {\n user-select: none;\n }\n\n :host {\n display: flex;\n overflow: hidden;\n flex-direction: column;\n background: var(--ui-surface);\n border: 1px solid var(--ui-border);\n border-radius: var(--ui-radius-dialog);\n box-shadow: var(--ui-shadow-lg, 0 8px 24px rgb(0 0 0 / 0.12));\n }\n\n .header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--ui-space-3);\n padding: var(--ui-space-2) var(--ui-space-3);\n color: var(--ui-text-secondary);\n border-bottom: 1px solid var(--ui-border);\n font-size: var(--ui-font-size-xs);\n font-weight: var(--ui-font-semibold);\n }\n\n .hint {\n overflow: hidden;\n color: var(--ui-text-muted);\n font-weight: var(--ui-font-normal);\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .list {\n max-height: 280px;\n padding: var(--ui-space-1) 0;\n margin: 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n list-style: none;\n /* Each edge that hides content fades: the scroll fade every Looma scroller uses (see ui-scroll-area). */\n --_ui-scroll-fade-direction: to bottom;\n --_ui-scroll-fade-size: var(--ui-scroll-fade-size, 24px);\n mask-image: linear-gradient(\n var(--_ui-scroll-fade-direction),\n transparent,\n #000 var(--_ui-scroll-fade-start),\n #000 calc(100% - var(--_ui-scroll-fade-end)),\n transparent\n );\n animation: ui-scroll-fade-start linear, ui-scroll-fade-start-hold linear, ui-scroll-fade-end-hold linear, ui-scroll-fade-end linear;\n animation-timeline: scroll(self block);\n animation-range:\n 0 var(--_ui-scroll-fade-size),\n var(--_ui-scroll-fade-size) calc(100% + 1px),\n -1px calc(100% - var(--_ui-scroll-fade-size)),\n calc(100% - var(--_ui-scroll-fade-size)) 100%;\n }\n\n .item {\n display: flex;\n align-items: center;\n min-height: 44px;\n padding: var(--ui-space-2) var(--ui-space-3);\n gap: var(--ui-space-3);\n cursor: pointer;\n }\n\n .item.active {\n background: var(--ui-accent-subtle, rgb(59 130 246 / 0.1));\n }\n\n .avatar {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n flex: 0 0 auto;\n color: var(--ui-accent-active, var(--ui-accent-solid));\n background: var(--ui-accent-soft, var(--ui-accent-subtle));\n border-radius: 999px;\n font-size: var(--ui-font-size-xs);\n font-weight: var(--ui-font-semibold);\n }\n\n .body {\n display: flex;\n min-width: 0;\n flex-direction: column;\n }\n\n .label,\n .detail {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .label {\n color: var(--ui-text-primary);\n font-size: var(--ui-font-size-sm);\n font-weight: var(--ui-font-medium);\n }\n\n .detail,\n .loading {\n color: var(--ui-text-muted);\n font-size: var(--ui-font-size-xs);\n }\n\n .loading {\n min-height: 44px;\n padding: var(--ui-space-3);\n }\n\n @media (max-width: 767px) {\n :host {\n border-bottom: 0;\n border-radius: var(--ui-radius-dialog) var(--ui-radius-dialog) 0 0;\n }\n\n .list {\n max-height: calc(60dvh - 48px);\n }\n }\n\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"visible","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"rows","type":"list(object({ id: string, label: string, detail?: string, initials: string }))","expression":{"source":"[]","ast":{"kind":"array","items":[]},"dependencies":[]}},{"kind":"state","name":"searching","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"active","expression":{"source":"0","ast":{"kind":"literal","value":0},"dependencies":[]}},{"kind":"state","name":"prefix","expression":{"source":"'ui-editor-mention-menu'","ast":{"kind":"literal","value":"ui-editor-mention-menu"},"dependencies":[]}},{"kind":"event","name":"highlight","type":"object({ index: integer })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"select","type":"object({ index: integer })","bubbles":true,"composed":true,"cancelable":false}],"slots":[],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-editor-mention-menu/ui-editor-mention-menu.js"},{"source":{"file":"./components/ui-editor-slash-menu/ui-editor-slash-menu.html"},"contract":{"version":1,"name":"UiEditorSlashMenu","tag":"ui-editor-slash-menu","nativeElement":"div","props":{"anchorRect":{"type":{"kind":"union","members":[{"kind":"object","fields":[{"name":"left","type":{"kind":"terminal","name":"number"},"optional":true},{"name":"top","type":{"kind":"terminal","name":"number"},"optional":true},{"name":"right","type":{"kind":"terminal","name":"number"},"optional":true},{"name":"bottom","type":{"kind":"terminal","name":"number"},"optional":true},{"name":"x","type":{"kind":"terminal","name":"number"},"optional":true},{"name":"y","type":{"kind":"terminal","name":"number"},"optional":true},{"name":"width","type":{"kind":"terminal","name":"number"},"optional":true},{"name":"height","type":{"kind":"terminal","name":"number"},"optional":true}],"open":false},{"kind":"terminal","name":"null"}]},"required":false,"target":{"attribute":"anchorrect"},"description":"Where the slash was typed, in viewport coordinates."},"items":{"type":{"kind":"list","item":{"kind":"object","fields":[{"name":"title","type":{"kind":"terminal","name":"string"},"optional":false},{"name":"description","type":{"kind":"terminal","name":"string"},"optional":false},{"name":"icon","type":{"kind":"terminal","name":"string"},"optional":false}],"open":false}},"required":false,"target":{"attribute":"items"},"description":"The blocks the menu offers."},"open":{"type":"boolean","required":false,"target":{"attribute":"open"},"description":"Whether the menu is open.","default":false},"query":{"type":"string","required":false,"target":{"attribute":"query"},"description":"The text typed after the slash.","default":""},"selectedIndex":{"type":{"kind":"terminal","name":"integer"},"required":false,"target":{"attribute":"selectedindex"},"description":"The zero-based index of the highlighted item. The menu does not handle arrow keys itself: the editor sets this as the user moves, while hovering an item\n highlights it and reports a highlight event.","default":0}}},"template":{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"role","value":"listbox"},{"kind":"literal","name":"aria-label","value":"Insert block"},{"kind":"attribute","name":"hidden","expression":"not visible","expressionPlan":{"source":"not visible","ast":{"kind":"unary","op":"not","operand":{"kind":"id","name":"visible"}},"dependencies":["visible"]}}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"header"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"header-label"}],"children":[{"kind":"text","value":"Insert"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"header-query"},{"kind":"directive","name":"value","expression":"query","expressionPlan":{"source":"query","ast":{"kind":"id","name":"query"},"dependencies":["query"]}}],"children":[],"flow":{"kind":"if","test":"query","testPlan":{"source":"query","ast":{"kind":"id","name":"query"},"dependencies":["query"]}}}]},{"kind":"element","name":"ul","attributes":[{"kind":"literal","name":"class","value":"list"},{"kind":"literal","name":"role","value":"presentation"}],"children":[{"kind":"element","name":"li","attributes":[{"kind":"literal","name":"class","value":"item"},{"kind":"attribute","name":"active","expression":"index = active","expressionPlan":{"source":"index = active","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"index"},"right":{"kind":"id","name":"active"}},"dependencies":["active","index"]},"target":"class"},{"kind":"literal","name":"role","value":"option"},{"kind":"attribute","name":"aria-selected","expression":"index = active","expressionPlan":{"source":"index = active","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"index"},"right":{"kind":"id","name":"active"}},"dependencies":["active","index"]}},{"kind":"attribute","name":"data-index","expression":"index","expressionPlan":{"source":"index","ast":{"kind":"id","name":"index"},"dependencies":["index"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"icon"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[{"kind":"element","name":"ui-icon","attributes":[{"kind":"attribute","name":"name","expression":"item.icon","expressionPlan":{"source":"item.icon","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"icon"},"dependencies":["item.icon"]}}],"children":[]}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"body"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"title"},{"kind":"directive","name":"value","expression":"item.title","expressionPlan":{"source":"item.title","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"title"},"dependencies":["item.title"]}}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"description"},{"kind":"directive","name":"value","expression":"item.description","expressionPlan":{"source":"item.description","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"description"},"dependencies":["item.description"]}}],"children":[]}]}],"flow":{"kind":"each","item":"item","list":"items","listPlan":{"source":"items","ast":{"kind":"id","name":"items"},"dependencies":["items"]},"index":"index"}}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"footer"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[{"kind":"element","name":"kbd","attributes":[],"children":[{"kind":"text","value":"↑↓"}]},{"kind":"text","value":" navigate · "},{"kind":"element","name":"kbd","attributes":[],"children":[{"kind":"text","value":"↵"}]},{"kind":"text","value":" insert · "},{"kind":"element","name":"kbd","attributes":[],"children":[{"kind":"text","value":"Esc"}]},{"kind":"text","value":" close\n "}]}]},"css":":host {\n user-select: none;\n }\n\n :host {\n background: var(--ui-surface);\n border: 1px solid var(--ui-border);\n border-radius: var(--ui-radius-dialog);\n box-shadow: var(--ui-shadow-lg, 0 8px 24px rgb(0 0 0 / 0.12));\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n\n @media (max-width: 767px) {\n :host {\n border-radius: var(--ui-radius-dialog) var(--ui-radius-dialog) 0 0;\n border-bottom: none;\n }\n }\n\n .header {\n display: none;\n align-items: center;\n gap: var(--ui-space-2);\n padding: var(--ui-space-3) var(--ui-space-4);\n border-bottom: 1px solid var(--ui-border);\n font-size: var(--ui-font-size-xs);\n color: var(--ui-text-muted);\n font-weight: var(--ui-font-semibold);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n }\n\n @media (max-width: 767px) {\n .header {\n display: flex;\n }\n }\n\n .header-query {\n background: var(--ui-surface-hover);\n border-radius: var(--ui-radius-sm);\n padding: 0.1em 0.4em;\n font-family: var(--ui-font-family-mono, ui-monospace, monospace);\n font-size: var(--ui-font-size-xs);\n color: var(--ui-accent);\n text-transform: none;\n letter-spacing: 0;\n }\n\n .list {\n list-style: none;\n margin: 0;\n padding: var(--ui-space-1) 0;\n overflow-y: auto;\n max-height: 280px;\n overscroll-behavior: contain;\n /* Each edge that hides content fades: the scroll fade every Looma scroller uses (see ui-scroll-area). */\n --_ui-scroll-fade-direction: to bottom;\n --_ui-scroll-fade-size: var(--ui-scroll-fade-size, 24px);\n mask-image: linear-gradient(\n var(--_ui-scroll-fade-direction),\n transparent,\n #000 var(--_ui-scroll-fade-start),\n #000 calc(100% - var(--_ui-scroll-fade-end)),\n transparent\n );\n animation: ui-scroll-fade-start linear, ui-scroll-fade-start-hold linear, ui-scroll-fade-end-hold linear, ui-scroll-fade-end linear;\n animation-timeline: scroll(self block);\n animation-range:\n 0 var(--_ui-scroll-fade-size),\n var(--_ui-scroll-fade-size) calc(100% + 1px),\n -1px calc(100% - var(--_ui-scroll-fade-size)),\n calc(100% - var(--_ui-scroll-fade-size)) 100%;\n }\n\n @media (max-width: 767px) {\n .list {\n max-height: calc(60dvh - 80px);\n padding: var(--ui-space-1) 0 var(--ui-space-2);\n }\n }\n\n .item {\n display: flex;\n align-items: center;\n gap: var(--ui-space-3);\n padding: var(--ui-space-2) var(--ui-space-3);\n min-height: 44px;\n cursor: pointer;\n transition: background-color 120ms ease;\n }\n\n .item.active {\n background: var(--ui-accent-subtle, rgb(59 130 246 / 0.1));\n }\n\n .icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n background: var(--ui-surface-hover);\n border: 1px solid var(--ui-border);\n border-radius: var(--ui-radius-md);\n font-size: var(--ui-font-size-sm);\n font-weight: var(--ui-font-bold);\n color: var(--ui-text-secondary);\n font-family: var(--ui-font-family-mono, ui-monospace, monospace);\n flex-shrink: 0;\n line-height: 1;\n }\n\n .item.active .icon {\n background: var(--ui-accent);\n border-color: var(--ui-accent);\n color: var(--ui-accent-contrast);\n }\n\n .icon {\n --_ui-default-icon-size: 1rem;\n --_ui-default-icon-stroke-width: var(--ui-editor-toolbar-icon-stroke-width, 1.75);\n }\n\n .body {\n display: flex;\n min-width: 0;\n flex-direction: column;\n gap: 1px;\n }\n\n .title {\n font-size: var(--ui-font-size-sm);\n font-weight: var(--ui-font-medium);\n color: var(--ui-text);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .description {\n font-size: var(--ui-font-size-xs);\n color: var(--ui-text-muted);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .footer {\n display: none;\n padding: var(--ui-space-2) var(--ui-space-3);\n border-top: 1px solid var(--ui-border);\n font-size: var(--ui-font-size-xs);\n color: var(--ui-text-muted);\n }\n\n @media (min-width: 768px) {\n .footer {\n display: block;\n }\n }\n\n :host kbd {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-family: var(--ui-font-family-mono, ui-monospace, monospace);\n font-size: var(--ui-font-size-2xs);\n background: var(--ui-surface-hover);\n border: 1px solid var(--ui-border);\n border-radius: 3px;\n padding: 0 3px;\n color: var(--ui-text-secondary);\n }\n\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"visible","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"active","expression":{"source":"0","ast":{"kind":"literal","value":0},"dependencies":[]}},{"kind":"event","name":"highlight","type":"object({ index: integer })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"select","type":"object({ index: integer })","bubbles":true,"composed":true,"cancelable":false}],"slots":[],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-editor-slash-menu/ui-editor-slash-menu.js"},{"source":{"file":"./components/ui-editor-table-context-menu/ui-editor-table-context-menu.html"},"contract":{"version":1,"name":"UiEditorTableContextMenu","tag":"ui-editor-table-context-menu","nativeElement":"div","props":{"actions":{"type":{"kind":"list","item":{"kind":"union","members":[{"kind":"keyword","value":"align-left"},{"kind":"keyword","value":"align-center"},{"kind":"keyword","value":"align-right"},{"kind":"keyword","value":"background-none"},{"kind":"keyword","value":"background-gray"},{"kind":"keyword","value":"background-yellow"},{"kind":"keyword","value":"background-blue"},{"kind":"keyword","value":"background-green"},{"kind":"keyword","value":"background-red"},{"kind":"keyword","value":"add-row-before"},{"kind":"keyword","value":"add-row-after"},{"kind":"keyword","value":"add-column-before"},{"kind":"keyword","value":"add-column-after"},{"kind":"keyword","value":"clear-cells"},{"kind":"keyword","value":"merge-cells"},{"kind":"keyword","value":"split-cell"},{"kind":"keyword","value":"delete-row"},{"kind":"keyword","value":"delete-column"},{"kind":"keyword","value":"delete-table"}]}},"required":false,"target":{"attribute":"actions"},"description":"The complete set of commands the current selection permits."},"cellBackground":{"type":"string","required":false,"target":{"attribute":"cellbackground"},"description":"Identifies the background choice that is active for the current cell.","default":""},"open":{"type":"boolean","required":false,"target":{"attribute":"open"},"description":"Shows the menu at the position owned by the editor integration.","default":false}}},"template":{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"role","value":"menu"},{"kind":"attribute","name":"hidden","expression":"not open","expressionPlan":{"source":"not open","ast":{"kind":"unary","op":"not","operand":{"kind":"id","name":"open"}},"dependencies":["open"]}}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"section"},{"kind":"literal","name":"role","value":"none"}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"heading"},{"kind":"literal","name":"role","value":"presentation"}],"children":[{"kind":"text","value":"Cell background"}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"swatches"},{"kind":"literal","name":"role","value":"group"},{"kind":"literal","name":"aria-label","value":"Cell background"}],"children":[{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"class","value":"swatch-button"},{"kind":"attribute","name":"selected","expression":"swatch.selected","expressionPlan":{"source":"swatch.selected","ast":{"kind":"member","object":{"kind":"id","name":"swatch"},"key":"selected"},"dependencies":["swatch.selected"]},"target":"class"},{"kind":"literal","name":"role","value":"menuitemradio"},{"kind":"attribute","name":"aria-checked","expression":"swatch.selected","expressionPlan":{"source":"swatch.selected","ast":{"kind":"member","object":{"kind":"id","name":"swatch"},"key":"selected"},"dependencies":["swatch.selected"]}},{"kind":"attribute","name":"data-action","expression":"swatch.action","expressionPlan":{"source":"swatch.action","ast":{"kind":"member","object":{"kind":"id","name":"swatch"},"key":"action"},"dependencies":["swatch.action"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"swatch"},{"kind":"attribute","name":"default","expression":"not swatch.color","expressionPlan":{"source":"not swatch.color","ast":{"kind":"unary","op":"not","operand":{"kind":"member","object":{"kind":"id","name":"swatch"},"key":"color"}},"dependencies":["swatch.color"]},"target":"class"},{"kind":"attribute","name":"--_swatch","expression":"swatch.color","expressionPlan":{"source":"swatch.color","ast":{"kind":"member","object":{"kind":"id","name":"swatch"},"key":"color"},"dependencies":["swatch.color"]},"target":"style"}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"swatch-label"},{"kind":"directive","name":"value","expression":"swatch.label","expressionPlan":{"source":"swatch.label","ast":{"kind":"member","object":{"kind":"id","name":"swatch"},"key":"label"},"dependencies":["swatch.label"]}}],"children":[]}],"flow":{"kind":"each","item":"swatch","list":"swatches","listPlan":{"source":"swatches","ast":{"kind":"id","name":"swatches"},"dependencies":["swatches"]},"key":"swatch.action","keyPlan":{"source":"swatch.action","ast":{"kind":"member","object":{"kind":"id","name":"swatch"},"key":"action"},"dependencies":["swatch.action"]}}}]}],"flow":{"kind":"if","test":"swatches","testPlan":{"source":"swatches","ast":{"kind":"id","name":"swatches"},"dependencies":["swatches"]}}},{"kind":"element","name":"template","attributes":[],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"sep"}],"children":[]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"section"},{"kind":"literal","name":"role","value":"none"}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"heading"},{"kind":"literal","name":"role","value":"presentation"},{"kind":"directive","name":"value","expression":"section.heading","expressionPlan":{"source":"section.heading","ast":{"kind":"member","object":{"kind":"id","name":"section"},"key":"heading"},"dependencies":["section.heading"]}}],"children":[]},{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"role","value":"menuitem"},{"kind":"attribute","name":"danger","expression":"item.danger","expressionPlan":{"source":"item.danger","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"danger"},"dependencies":["item.danger"]},"target":"class"},{"kind":"attribute","name":"data-action","expression":"item.action","expressionPlan":{"source":"item.action","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"action"},"dependencies":["item.action"]}}],"children":[{"kind":"element","name":"ui-icon","attributes":[{"kind":"attribute","name":"name","expression":"item.icon","expressionPlan":{"source":"item.icon","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"icon"},"dependencies":["item.icon"]}}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"directive","name":"value","expression":"item.label","expressionPlan":{"source":"item.label","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"label"},"dependencies":["item.label"]}}],"children":[]}],"flow":{"kind":"each","item":"item","list":"section.items","listPlan":{"source":"section.items","ast":{"kind":"member","object":{"kind":"id","name":"section"},"key":"items"},"dependencies":["section.items"]},"key":"item.action","keyPlan":{"source":"item.action","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"action"},"dependencies":["item.action"]}}}]}],"flow":{"kind":"each","item":"section","list":"sections","listPlan":{"source":"sections","ast":{"kind":"id","name":"sections"},"dependencies":["sections"]},"key":"section.heading","keyPlan":{"source":"section.heading","ast":{"kind":"member","object":{"kind":"id","name":"section"},"key":"heading"},"dependencies":["section.heading"]}}}]},"css":":host {\n /* The max-width is a promise about the menu's footprint, so it counts padding and border. */\n box-sizing: border-box;\n min-width: 14rem;\n max-width: min(17rem, calc(100vw - 24px));\n max-height: min(28rem, calc(100vh - 24px));\n padding: var(--ui-space-2);\n background: var(--ui-surface);\n border: 1px solid var(--ui-border);\n border-radius: var(--ui-radius-lg);\n box-shadow: var(--ui-shadow-lg, 0 10px 15px -3px rgb(0 0 0 / 0.1));\n display: flex;\n flex-direction: column;\n gap: 2px;\n overflow-y: auto;\n overscroll-behavior: contain;\n scrollbar-width: thin;\n }\n\n .section {\n display: flex;\n flex-direction: column;\n gap: 3px;\n }\n\n :host button {\n display: flex;\n align-items: center;\n gap: var(--ui-space-2);\n width: 100%;\n text-align: left;\n min-height: 32px;\n padding: var(--ui-space-2) var(--ui-space-2);\n border: none;\n border-radius: var(--ui-radius-sm);\n background: none;\n font-size: var(--ui-font-size-sm);\n cursor: pointer;\n color: var(--ui-text);\n }\n\n :host button {\n --_ui-default-icon-size: 1rem;\n --_ui-default-icon-stroke-width: var(--ui-editor-toolbar-icon-stroke-width, 1.75);\n }\n\n :host button:hover:not(:disabled) {\n background: var(--ui-surface-hover);\n }\n\n :host button.selected {\n background: var(--ui-accent-subtle, rgb(59 130 246 / 0.1));\n }\n\n :host button.danger {\n color: var(--ui-danger);\n }\n\n .swatches {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 3px;\n }\n\n .swatch-button {\n display: inline-flex;\n align-items: center;\n gap: var(--ui-space-2);\n }\n\n .swatch {\n display: inline-flex;\n width: 1rem;\n height: 1rem;\n border-radius: 999px;\n border: 1px solid var(--ui-border);\n background: var(--_swatch, #fff);\n box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.35);\n flex-shrink: 0;\n }\n\n .swatch.default {\n position: relative;\n background:\n linear-gradient(\n 135deg,\n transparent calc(50% - 1px),\n var(--ui-text-muted) calc(50% - 1px),\n var(--ui-text-muted) calc(50% + 1px),\n transparent calc(50% + 1px)\n ),\n var(--ui-surface);\n }\n\n .swatch-label {\n min-width: 0;\n white-space: nowrap;\n }\n\n .heading {\n padding: var(--ui-space-1) var(--ui-space-2);\n font-size: var(--ui-font-size-2xs);\n font-weight: 700;\n letter-spacing: 0.05em;\n text-transform: uppercase;\n color: var(--ui-text-muted);\n }\n\n .sep {\n height: 1px;\n background: var(--ui-border);\n margin: var(--ui-space-1) 0;\n }\n\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"swatches","type":"list(object({ action: string, label: string, color: string, selected: boolean })) | null","expression":{"source":"[]","ast":{"kind":"array","items":[]},"dependencies":[]}},{"kind":"state","name":"sections","type":"list(object({ heading: string, items: list(object({ action: string, label: string, icon: string, danger: boolean })) }))","expression":{"source":"[]","ast":{"kind":"array","items":[]},"dependencies":[]}},{"kind":"event","name":"action","type":"object({ action: align-left | align-center | align-right | background-none | background-gray | background-yellow | background-blue | background-green | background-red | add-row-before | add-row-after | add-column-before | add-column-after | clear-cells | merge-cells | split-cell | delete-row | delete-column | delete-table })","bubbles":true,"composed":true,"cancelable":false}],"slots":[],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-editor-table-context-menu/ui-editor-table-context-menu.js"},{"source":{"file":"./components/ui-editor-table-overlay/ui-editor-table-overlay.html"},"contract":{"version":1,"name":"UiEditorTableOverlay","tag":"ui-editor-table-overlay","nativeElement":"div","props":{"geometry":{"type":{"kind":"union","members":[{"kind":"object","fields":[{"name":"rowBoundaries","type":{"kind":"list","item":{"kind":"terminal","name":"number"}},"optional":false},{"name":"columnBoundaries","type":{"kind":"list","item":{"kind":"terminal","name":"number"}},"optional":false},{"name":"activeCell","type":{"kind":"union","members":[{"kind":"object","fields":[{"name":"left","type":{"kind":"terminal","name":"number"},"optional":false},{"name":"top","type":{"kind":"terminal","name":"number"},"optional":false},{"name":"width","type":{"kind":"terminal","name":"number"},"optional":false},{"name":"height","type":{"kind":"terminal","name":"number"},"optional":false},{"name":"rowIndex","type":{"kind":"terminal","name":"integer"},"optional":false},{"name":"columnIndex","type":{"kind":"terminal","name":"integer"},"optional":false}],"open":false},{"kind":"terminal","name":"null"}]},"optional":false},{"name":"hoveredCell","type":{"kind":"union","members":[{"kind":"object","fields":[{"name":"left","type":{"kind":"terminal","name":"number"},"optional":false},{"name":"top","type":{"kind":"terminal","name":"number"},"optional":false},{"name":"width","type":{"kind":"terminal","name":"number"},"optional":false},{"name":"height","type":{"kind":"terminal","name":"number"},"optional":false},{"name":"rowIndex","type":{"kind":"terminal","name":"integer"},"optional":false},{"name":"columnIndex","type":{"kind":"terminal","name":"integer"},"optional":false}],"open":false},{"kind":"terminal","name":"null"}]},"optional":true}],"open":false},{"kind":"terminal","name":"null"}]},"required":false,"target":{"attribute":"geometry"},"description":"The authoritative editor-measured table boundaries and active or hovered cell rectangles."},"open":{"type":"boolean","required":false,"target":{"attribute":"open"},"description":"Shows the controls after the editor has supplied current geometry.","default":false}}},"template":{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"aria-label","value":"Table controls"},{"kind":"attribute","name":"hidden","expression":"not open","expressionPlan":{"source":"not open","ast":{"kind":"unary","op":"not","operand":{"kind":"id","name":"open"}},"dependencies":["open"]}}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"rows"}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"control row"},{"kind":"attribute","name":"active","expression":"control.key = activeKey","expressionPlan":{"source":"control.key = activeKey","ast":{"kind":"binary","op":"=","left":{"kind":"member","object":{"kind":"id","name":"control"},"key":"key"},"right":{"kind":"id","name":"activeKey"}},"dependencies":["activeKey","control.key"]},"target":"class"},{"kind":"attribute","name":"top","expression":"control.offset","expressionPlan":{"source":"control.offset","ast":{"kind":"member","object":{"kind":"id","name":"control"},"key":"offset"},"dependencies":["control.offset"]},"target":"style"},{"kind":"attribute","name":"data-control-key","expression":"control.key","expressionPlan":{"source":"control.key","ast":{"kind":"member","object":{"kind":"id","name":"control"},"key":"key"},"dependencies":["control.key"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"line"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"guide"},{"kind":"literal","name":"data-ui-guide","value":""},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[]},{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"class","value":"handle"},{"kind":"attribute","name":"data-ui-affordance","expression":"control.affordance","expressionPlan":{"source":"control.affordance","ast":{"kind":"member","object":{"kind":"id","name":"control"},"key":"affordance"},"dependencies":["control.affordance"]}},{"kind":"attribute","name":"data-action","expression":"control.action","expressionPlan":{"source":"control.action","ast":{"kind":"member","object":{"kind":"id","name":"control"},"key":"action"},"dependencies":["control.action"]}},{"kind":"attribute","name":"data-boundary-index","expression":"control.index","expressionPlan":{"source":"control.index","ast":{"kind":"member","object":{"kind":"id","name":"control"},"key":"index"},"dependencies":["control.index"]}},{"kind":"attribute","name":"aria-label","expression":"control.label","expressionPlan":{"source":"control.label","ast":{"kind":"member","object":{"kind":"id","name":"control"},"key":"label"},"dependencies":["control.label"]}}],"children":[{"kind":"element","name":"ui-icon","attributes":[{"kind":"literal","name":"name","value":"plus"}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"tooltip"},{"kind":"literal","name":"role","value":"tooltip"},{"kind":"directive","name":"value","expression":"control.label","expressionPlan":{"source":"control.label","ast":{"kind":"member","object":{"kind":"id","name":"control"},"key":"label"},"dependencies":["control.label"]}}],"children":[]}]}],"flow":{"kind":"each","item":"control","list":"rows","listPlan":{"source":"rows","ast":{"kind":"id","name":"rows"},"dependencies":["rows"]},"key":"control.key","keyPlan":{"source":"control.key","ast":{"kind":"member","object":{"kind":"id","name":"control"},"key":"key"},"dependencies":["control.key"]}}}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"cols"}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"control col"},{"kind":"attribute","name":"active","expression":"control.key = activeKey","expressionPlan":{"source":"control.key = activeKey","ast":{"kind":"binary","op":"=","left":{"kind":"member","object":{"kind":"id","name":"control"},"key":"key"},"right":{"kind":"id","name":"activeKey"}},"dependencies":["activeKey","control.key"]},"target":"class"},{"kind":"attribute","name":"left","expression":"control.offset","expressionPlan":{"source":"control.offset","ast":{"kind":"member","object":{"kind":"id","name":"control"},"key":"offset"},"dependencies":["control.offset"]},"target":"style"},{"kind":"attribute","name":"data-control-key","expression":"control.key","expressionPlan":{"source":"control.key","ast":{"kind":"member","object":{"kind":"id","name":"control"},"key":"key"},"dependencies":["control.key"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"line"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"guide"},{"kind":"literal","name":"data-ui-guide","value":""},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[]},{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"class","value":"handle"},{"kind":"attribute","name":"data-ui-affordance","expression":"control.affordance","expressionPlan":{"source":"control.affordance","ast":{"kind":"member","object":{"kind":"id","name":"control"},"key":"affordance"},"dependencies":["control.affordance"]}},{"kind":"attribute","name":"data-action","expression":"control.action","expressionPlan":{"source":"control.action","ast":{"kind":"member","object":{"kind":"id","name":"control"},"key":"action"},"dependencies":["control.action"]}},{"kind":"attribute","name":"data-boundary-index","expression":"control.index","expressionPlan":{"source":"control.index","ast":{"kind":"member","object":{"kind":"id","name":"control"},"key":"index"},"dependencies":["control.index"]}},{"kind":"attribute","name":"aria-label","expression":"control.label","expressionPlan":{"source":"control.label","ast":{"kind":"member","object":{"kind":"id","name":"control"},"key":"label"},"dependencies":["control.label"]}}],"children":[{"kind":"element","name":"ui-icon","attributes":[{"kind":"literal","name":"name","value":"plus"}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"tooltip"},{"kind":"literal","name":"role","value":"tooltip"},{"kind":"directive","name":"value","expression":"control.label","expressionPlan":{"source":"control.label","ast":{"kind":"member","object":{"kind":"id","name":"control"},"key":"label"},"dependencies":["control.label"]}}],"children":[]}]}],"flow":{"kind":"each","item":"control","list":"cols","listPlan":{"source":"cols","ast":{"kind":"id","name":"cols"},"dependencies":["cols"]},"key":"control.key","keyPlan":{"source":"control.key","ast":{"kind":"member","object":{"kind":"id","name":"control"},"key":"key"},"dependencies":["control.key"]}}}]},{"kind":"element","name":"template","attributes":[],"children":[{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"class","value":"selector row"},{"kind":"attribute","name":"top","expression":"hovered.rowOffset","expressionPlan":{"source":"hovered.rowOffset","ast":{"kind":"member","object":{"kind":"id","name":"hovered"},"key":"rowOffset"},"dependencies":["hovered.rowOffset"]},"target":"style"},{"kind":"literal","name":"data-action","value":"select-row"},{"kind":"attribute","name":"data-row-index","expression":"hovered.rowIndex","expressionPlan":{"source":"hovered.rowIndex","ast":{"kind":"member","object":{"kind":"id","name":"hovered"},"key":"rowIndex"},"dependencies":["hovered.rowIndex"]}},{"kind":"attribute","name":"data-column-index","expression":"hovered.columnIndex","expressionPlan":{"source":"hovered.columnIndex","ast":{"kind":"member","object":{"kind":"id","name":"hovered"},"key":"columnIndex"},"dependencies":["hovered.columnIndex"]}},{"kind":"literal","name":"title","value":"Select row"},{"kind":"literal","name":"aria-label","value":"Select row"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"glyph"}],"children":[{"kind":"element","name":"ui-icon","attributes":[{"kind":"literal","name":"name","value":"grip-vertical"}],"children":[]}]}]},{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"class","value":"selector column"},{"kind":"attribute","name":"left","expression":"hovered.columnOffset","expressionPlan":{"source":"hovered.columnOffset","ast":{"kind":"member","object":{"kind":"id","name":"hovered"},"key":"columnOffset"},"dependencies":["hovered.columnOffset"]},"target":"style"},{"kind":"literal","name":"data-action","value":"select-column"},{"kind":"attribute","name":"data-row-index","expression":"hovered.rowIndex","expressionPlan":{"source":"hovered.rowIndex","ast":{"kind":"member","object":{"kind":"id","name":"hovered"},"key":"rowIndex"},"dependencies":["hovered.rowIndex"]}},{"kind":"attribute","name":"data-column-index","expression":"hovered.columnIndex","expressionPlan":{"source":"hovered.columnIndex","ast":{"kind":"member","object":{"kind":"id","name":"hovered"},"key":"columnIndex"},"dependencies":["hovered.columnIndex"]}},{"kind":"literal","name":"title","value":"Select column"},{"kind":"literal","name":"aria-label","value":"Select column"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"glyph"}],"children":[{"kind":"element","name":"ui-icon","attributes":[{"kind":"literal","name":"name","value":"grip-horizontal"}],"children":[]}]}]}],"flow":{"kind":"if","test":"hovered","testPlan":{"source":"hovered","ast":{"kind":"id","name":"hovered"},"dependencies":["hovered"]}}},{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"class","value":"cell-menu"},{"kind":"attribute","name":"left","expression":"active.menuLeft","expressionPlan":{"source":"active.menuLeft","ast":{"kind":"member","object":{"kind":"id","name":"active"},"key":"menuLeft"},"dependencies":["active.menuLeft"]},"target":"style"},{"kind":"attribute","name":"top","expression":"active.menuTop","expressionPlan":{"source":"active.menuTop","ast":{"kind":"member","object":{"kind":"id","name":"active"},"key":"menuTop"},"dependencies":["active.menuTop"]},"target":"style"},{"kind":"literal","name":"data-action","value":"open-cell-menu"},{"kind":"attribute","name":"data-row-index","expression":"active.rowIndex","expressionPlan":{"source":"active.rowIndex","ast":{"kind":"member","object":{"kind":"id","name":"active"},"key":"rowIndex"},"dependencies":["active.rowIndex"]}},{"kind":"attribute","name":"data-column-index","expression":"active.columnIndex","expressionPlan":{"source":"active.columnIndex","ast":{"kind":"member","object":{"kind":"id","name":"active"},"key":"columnIndex"},"dependencies":["active.columnIndex"]}},{"kind":"literal","name":"title","value":"Cell actions"},{"kind":"literal","name":"aria-label","value":"Cell actions"}],"children":[{"kind":"element","name":"ui-icon","attributes":[{"kind":"literal","name":"name","value":"chevron-down"}],"children":[]}],"flow":{"kind":"if","test":"active","testPlan":{"source":"active","ast":{"kind":"id","name":"active"},"dependencies":["active"]}}}]},"css":":host {\n display: block;\n width: 100%;\n height: 100%;\n overflow: visible;\n pointer-events: none;\n }\n\n :host {\n position: relative;\n width: 100%;\n height: 100%;\n overflow: visible;\n pointer-events: none;\n }\n\n .rows,\n .cols {\n pointer-events: none;\n position: absolute;\n }\n\n .rows {\n inset: 0;\n width: 100%;\n }\n\n .cols {\n inset: 0;\n height: 100%;\n }\n\n .control {\n position: absolute;\n z-index: 1;\n pointer-events: none;\n }\n\n .handle {\n position: absolute;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n padding: 0;\n border: 1px solid var(--ui-affordance-near-color, var(--ui-border-strong));\n border-radius: var(--ui-radius-round);\n background: color-mix(in srgb, var(--ui-surface-elevated) 96%, transparent);\n color: var(--ui-affordance-near-color, var(--ui-text-secondary));\n font: inherit;\n font-size: 16px;\n line-height: 1;\n box-shadow: var(--ui-shadow-xs, 0 1px 2px rgb(0 0 0 / 0.05));\n opacity: 0;\n scale: 0.72;\n transition:\n opacity var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease),\n scale var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease),\n color var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease),\n background-color var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease),\n border-color var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease);\n pointer-events: auto;\n cursor: pointer;\n }\n\n .handle {\n --_ui-default-icon-size: 14px;\n --_ui-default-icon-stroke-width: 2;\n }\n\n .handle[data-ui-proximity=\"near\"],\n .control.active .handle,\n .handle:focus-visible {\n opacity: 1;\n scale: 1;\n }\n\n .control.active .handle,\n .handle:focus-visible {\n border-color: var(--ui-affordance-direct-color, var(--ui-accent-solid));\n background: var(--ui-affordance-direct-color, var(--ui-accent-solid));\n color: var(--ui-text-on-accent);\n box-shadow: var(--ui-shadow-sm, 0 1px 3px rgb(0 0 0 / 0.1));\n }\n\n .handle:focus-visible,\n .selector:focus-visible,\n .cell-menu:focus-visible {\n outline: 2px solid var(--ui-focus-ring);\n outline-offset: 2px;\n }\n\n .control.row {\n left: 0;\n width: 100%;\n height: 0;\n }\n\n .control.row .handle {\n top: -12px;\n left: -30px;\n }\n\n .control.col {\n top: 0;\n width: 0;\n height: 100%;\n }\n\n .control.col .handle {\n top: -30px;\n left: -12px;\n }\n\n .line {\n position: absolute;\n background: var(--ui-affordance-direct-color, var(--ui-accent-solid));\n opacity: 0;\n transition: opacity var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease);\n }\n\n .control.row .line {\n inset: -1px 0 auto;\n height: 2px;\n }\n\n .control.col .line {\n inset: 0 auto 0 -1px;\n width: 2px;\n }\n\n .control.active .line {\n opacity: 0.8;\n }\n\n .guide {\n position: absolute;\n width: var(--ui-affordance-guide-size);\n height: var(--ui-affordance-guide-size);\n border-radius: var(--ui-radius-round);\n background: var(--ui-affordance-guide-color, var(--ui-border-strong));\n opacity: calc(var(--ui-affordance-guide-opacity) * var(--ui-affordance-scope-guide, 1));\n transition: opacity var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease);\n }\n\n .control.row .guide {\n left: -10px;\n top: -2px;\n }\n\n .control.col .guide {\n left: -2px;\n top: -10px;\n }\n\n .control:has(.handle[data-ui-proximity=\"near\"]) .guide,\n .control.active .guide {\n opacity: 0;\n }\n\n .tooltip {\n position: absolute;\n z-index: 2;\n top: calc(100% + 6px);\n left: 50%;\n width: max-content;\n max-width: 14rem;\n padding: var(--ui-space-1) var(--ui-space-2);\n border-radius: var(--ui-radius-sm);\n background: var(--ui-text-primary);\n color: var(--ui-surface-elevated);\n font-size: var(--ui-font-size-xs);\n font-weight: var(--ui-font-medium);\n line-height: var(--ui-line-height-md);\n opacity: 0;\n transform: translateX(-50%);\n transition: opacity var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease);\n pointer-events: none;\n }\n\n .control.row .tooltip {\n top: 50%;\n left: auto;\n right: calc(100% + 8px);\n transform: translateY(-50%);\n }\n\n .control.active .tooltip,\n .handle:focus-visible .tooltip {\n opacity: 1;\n }\n\n .selector,\n .cell-menu {\n position: absolute;\n z-index: 2;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n border: 1px solid transparent;\n background: transparent;\n color: var(--ui-text-secondary);\n box-shadow: none;\n pointer-events: auto;\n cursor: pointer;\n transition:\n color var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease),\n background-color var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease),\n border-color var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease),\n box-shadow var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease);\n }\n\n .selector:hover,\n .cell-menu:hover {\n background: var(--ui-surface-muted);\n color: var(--ui-text-primary);\n box-shadow: var(--ui-shadow-xs, 0 1px 2px rgb(0 0 0 / 0.05));\n }\n\n .selector {\n border-radius: var(--ui-radius-round);\n }\n\n .selector::before {\n content: \"\";\n position: absolute;\n inset: 50% auto auto 50%;\n border-radius: var(--ui-radius-round);\n background: var(--ui-affordance-guide-color, var(--ui-border-strong));\n opacity: calc(var(--ui-affordance-guide-opacity) * var(--ui-affordance-scope-guide, 1));\n transform: translate(-50%, -50%);\n transition: opacity var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease);\n pointer-events: none;\n }\n\n .selector .glyph {\n display: block;\n width: 14px;\n height: 14px;\n --_ui-default-icon-size: 14px;\n --_ui-default-icon-stroke-width: 2;\n opacity: 0;\n transform: scale(0.72);\n transition:\n opacity var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease),\n transform var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease);\n }\n\n .selector:hover::before,\n .selector:focus-visible::before {\n opacity: 0;\n }\n\n .selector:hover .glyph,\n .selector:focus-visible .glyph {\n opacity: 1;\n transform: scale(1);\n }\n\n .selector.row {\n left: -9px;\n width: 18px;\n height: 32px;\n transform: translateY(-50%);\n }\n\n .selector.row::before {\n width: 2px;\n height: 16px;\n }\n\n .selector.column {\n top: -9px;\n width: 32px;\n height: 18px;\n transform: translateX(-50%);\n }\n\n .selector.column::before {\n width: 16px;\n height: 2px;\n }\n\n @media (hover: none), (pointer: coarse) {\n .selector::before {\n opacity: 0;\n }\n\n .selector .glyph {\n opacity: 1;\n transform: none;\n }\n }\n\n .cell-menu {\n width: 24px;\n height: 24px;\n border-radius: var(--ui-radius-sm);\n background: color-mix(in srgb, var(--ui-surface-muted) 78%, transparent);\n }\n\n .cell-menu {\n --_ui-default-icon-size: 15px;\n --_ui-default-icon-stroke-width: 2;\n }\n\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"rows","type":"list(object({ key: string, index: integer, offset: string, affordance: insert-row | insert-column, action: add-row-before | add-row-after | add-column-before | add-column-after, label: string }))","expression":{"source":"[]","ast":{"kind":"array","items":[]},"dependencies":[]}},{"kind":"state","name":"cols","type":"list(object({ key: string, index: integer, offset: string, affordance: insert-row | insert-column, action: add-row-before | add-row-after | add-column-before | add-column-after, label: string }))","expression":{"source":"[]","ast":{"kind":"array","items":[]},"dependencies":[]}},{"kind":"state","name":"hovered","type":"object({ left: number, top: number, width: number, height: number, rowIndex: integer, columnIndex: integer, rowOffset: string, columnOffset: string }) | null","expression":{"source":"null","ast":{"kind":"literal","value":null},"dependencies":[]}},{"kind":"state","name":"active","type":"object({ left: number, top: number, width: number, height: number, rowIndex: integer, columnIndex: integer, menuLeft: string, menuTop: string }) | null","expression":{"source":"null","ast":{"kind":"literal","value":null},"dependencies":[]}},{"kind":"state","name":"activeKey","expression":{"source":"''","ast":{"kind":"literal","value":""},"dependencies":[]}},{"kind":"event","name":"action","type":"object({ action: add-row-before | add-row-after | add-column-before | add-column-after, boundaryIndex: integer }) | object({ action: select-row | select-column, rowIndex: integer, columnIndex: integer }) | object({ action: open-cell-menu, rowIndex: integer, columnIndex: integer, anchor: object({ left: number, top: number, right: number, bottom: number }) })","bubbles":true,"composed":true,"cancelable":false}],"slots":[],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-editor-table-overlay/ui-editor-table-overlay.js"},{"source":{"file":"./components/ui-editor-table-toolbar/ui-editor-table-toolbar.html"},"contract":{"version":1,"name":"UiEditorTableToolbar","tag":"ui-editor-table-toolbar","nativeElement":"div","props":{"actions":{"type":{"kind":"list","item":{"kind":"union","members":[{"kind":"keyword","value":"align-left"},{"kind":"keyword","value":"align-center"},{"kind":"keyword","value":"align-right"},{"kind":"keyword","value":"background-none"},{"kind":"keyword","value":"background-gray"},{"kind":"keyword","value":"background-yellow"},{"kind":"keyword","value":"background-blue"},{"kind":"keyword","value":"background-green"},{"kind":"keyword","value":"background-red"},{"kind":"keyword","value":"add-row-before"},{"kind":"keyword","value":"add-row-after"},{"kind":"keyword","value":"add-column-before"},{"kind":"keyword","value":"add-column-after"},{"kind":"keyword","value":"clear-cells"},{"kind":"keyword","value":"merge-cells"},{"kind":"keyword","value":"split-cell"},{"kind":"keyword","value":"delete-row"},{"kind":"keyword","value":"delete-column"},{"kind":"keyword","value":"delete-table"}]}},"required":false,"target":{"attribute":"actions"},"description":"The complete set of commands the current selection permits."},"cellAlignment":{"type":{"enum":["left","center","right"]},"required":false,"target":{"attribute":"cellalignment"},"description":"Marks the alignment command that is active for the current cell.","default":"left"},"cellBackground":{"type":"string","required":false,"target":{"attribute":"cellbackground"},"description":"Identifies the background choice that is active for the current cell.","default":""},"open":{"type":"boolean","required":false,"target":{"attribute":"open"},"description":"Shows the toolbar while a table selection is active.","default":false}}},"template":{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"role","value":"toolbar"},{"kind":"literal","name":"aria-label","value":"Table actions"},{"kind":"attribute","name":"hidden","expression":"not open","expressionPlan":{"source":"not open","ast":{"kind":"unary","op":"not","operand":{"kind":"id","name":"open"}},"dependencies":["open"]}}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"group"},{"kind":"literal","name":"role","value":"group"},{"kind":"literal","name":"aria-label","value":"Cell alignment"}],"children":[{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"class","value":"icon-button"},{"kind":"attribute","name":"active","expression":"item.active","expressionPlan":{"source":"item.active","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"active"},"dependencies":["item.active"]},"target":"class"},{"kind":"attribute","name":"data-action","expression":"item.action","expressionPlan":{"source":"item.action","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"action"},"dependencies":["item.action"]}},{"kind":"attribute","name":"aria-label","expression":"item.label","expressionPlan":{"source":"item.label","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"label"},"dependencies":["item.label"]}},{"kind":"attribute","name":"title","expression":"item.label","expressionPlan":{"source":"item.label","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"label"},"dependencies":["item.label"]}},{"kind":"attribute","name":"aria-pressed","expression":"item.active","expressionPlan":{"source":"item.active","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"active"},"dependencies":["item.active"]}}],"children":[{"kind":"element","name":"ui-icon","attributes":[{"kind":"attribute","name":"name","expression":"item.action","expressionPlan":{"source":"item.action","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"action"},"dependencies":["item.action"]}}],"children":[]}],"flow":{"kind":"each","item":"item","list":"alignments","listPlan":{"source":"alignments","ast":{"kind":"id","name":"alignments"},"dependencies":["alignments"]},"key":"item.action","keyPlan":{"source":"item.action","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"action"},"dependencies":["item.action"]}}}],"flow":{"kind":"if","test":"alignments","testPlan":{"source":"alignments","ast":{"kind":"id","name":"alignments"},"dependencies":["alignments"]}}},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"sep"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[],"flow":{"kind":"if","test":"alignments and structure","testPlan":{"source":"alignments and structure","ast":{"kind":"binary","op":"and","left":{"kind":"id","name":"alignments"},"right":{"kind":"id","name":"structure"}},"dependencies":["alignments","structure"]}}},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"group"},{"kind":"literal","name":"role","value":"group"},{"kind":"literal","name":"aria-label","value":"Table structure"}],"children":[{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"attribute","name":"data-action","expression":"item.action","expressionPlan":{"source":"item.action","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"action"},"dependencies":["item.action"]}}],"children":[{"kind":"element","name":"ui-icon","attributes":[{"kind":"attribute","name":"name","expression":"item.icon","expressionPlan":{"source":"item.icon","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"icon"},"dependencies":["item.icon"]}}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"directive","name":"value","expression":"item.label","expressionPlan":{"source":"item.label","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"label"},"dependencies":["item.label"]}}],"children":[]}],"flow":{"kind":"each","item":"item","list":"structure","listPlan":{"source":"structure","ast":{"kind":"id","name":"structure"},"dependencies":["structure"]},"key":"item.action","keyPlan":{"source":"item.action","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"action"},"dependencies":["item.action"]}}}],"flow":{"kind":"if","test":"structure","testPlan":{"source":"structure","ast":{"kind":"id","name":"structure"},"dependencies":["structure"]}}},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"sep"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[],"flow":{"kind":"if","test":"(alignments or structure) and hasOverflow","testPlan":{"source":"(alignments or structure) and hasOverflow","ast":{"kind":"binary","op":"and","left":{"kind":"binary","op":"or","left":{"kind":"id","name":"alignments"},"right":{"kind":"id","name":"structure"}},"right":{"kind":"id","name":"hasOverflow"}},"dependencies":["alignments","hasOverflow","structure"]}}},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"overflow"}],"children":[{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"class","value":"more"},{"kind":"literal","name":"data-action","value":"toggle-overflow"},{"kind":"literal","name":"aria-haspopup","value":"menu"},{"kind":"attribute","name":"aria-expanded","expression":"overflowOpen","expressionPlan":{"source":"overflowOpen","ast":{"kind":"id","name":"overflowOpen"},"dependencies":["overflowOpen"]}}],"children":[{"kind":"element","name":"ui-icon","attributes":[{"kind":"literal","name":"name","value":"table"}],"children":[]},{"kind":"element","name":"span","attributes":[],"children":[{"kind":"text","value":"Table options"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"chevron"}],"children":[{"kind":"element","name":"ui-icon","attributes":[{"kind":"literal","name":"name","value":"chevron-down"}],"children":[]}]}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"menu"},{"kind":"literal","name":"role","value":"menu"},{"kind":"literal","name":"aria-label","value":"More table actions"}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"menu-section"},{"kind":"literal","name":"role","value":"none"}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"menu-heading"},{"kind":"literal","name":"role","value":"presentation"}],"children":[{"kind":"text","value":"Background"}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"swatches"},{"kind":"literal","name":"role","value":"group"},{"kind":"literal","name":"aria-label","value":"Cell background"}],"children":[{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"class","value":"swatch-button"},{"kind":"attribute","name":"selected","expression":"swatch.selected","expressionPlan":{"source":"swatch.selected","ast":{"kind":"member","object":{"kind":"id","name":"swatch"},"key":"selected"},"dependencies":["swatch.selected"]},"target":"class"},{"kind":"literal","name":"role","value":"menuitemradio"},{"kind":"attribute","name":"aria-checked","expression":"swatch.selected","expressionPlan":{"source":"swatch.selected","ast":{"kind":"member","object":{"kind":"id","name":"swatch"},"key":"selected"},"dependencies":["swatch.selected"]}},{"kind":"attribute","name":"data-action","expression":"swatch.action","expressionPlan":{"source":"swatch.action","ast":{"kind":"member","object":{"kind":"id","name":"swatch"},"key":"action"},"dependencies":["swatch.action"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"swatch"},{"kind":"attribute","name":"default","expression":"not swatch.color","expressionPlan":{"source":"not swatch.color","ast":{"kind":"unary","op":"not","operand":{"kind":"member","object":{"kind":"id","name":"swatch"},"key":"color"}},"dependencies":["swatch.color"]},"target":"class"},{"kind":"attribute","name":"--_swatch","expression":"swatch.color","expressionPlan":{"source":"swatch.color","ast":{"kind":"member","object":{"kind":"id","name":"swatch"},"key":"color"},"dependencies":["swatch.color"]},"target":"style"}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"directive","name":"value","expression":"swatch.label","expressionPlan":{"source":"swatch.label","ast":{"kind":"member","object":{"kind":"id","name":"swatch"},"key":"label"},"dependencies":["swatch.label"]}}],"children":[]}],"flow":{"kind":"each","item":"swatch","list":"swatches","listPlan":{"source":"swatches","ast":{"kind":"id","name":"swatches"},"dependencies":["swatches"]},"key":"swatch.action","keyPlan":{"source":"swatch.action","ast":{"kind":"member","object":{"kind":"id","name":"swatch"},"key":"action"},"dependencies":["swatch.action"]}}}]}],"flow":{"kind":"if","test":"swatches","testPlan":{"source":"swatches","ast":{"kind":"id","name":"swatches"},"dependencies":["swatches"]}}},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"menu-section divided"},{"kind":"literal","name":"role","value":"none"}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"menu-heading"},{"kind":"literal","name":"role","value":"presentation"},{"kind":"directive","name":"value","expression":"section.heading","expressionPlan":{"source":"section.heading","ast":{"kind":"member","object":{"kind":"id","name":"section"},"key":"heading"},"dependencies":["section.heading"]}}],"children":[]},{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"role","value":"menuitem"},{"kind":"attribute","name":"danger","expression":"item.danger","expressionPlan":{"source":"item.danger","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"danger"},"dependencies":["item.danger"]},"target":"class"},{"kind":"attribute","name":"data-action","expression":"item.action","expressionPlan":{"source":"item.action","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"action"},"dependencies":["item.action"]}}],"children":[{"kind":"element","name":"ui-icon","attributes":[{"kind":"attribute","name":"name","expression":"item.icon","expressionPlan":{"source":"item.icon","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"icon"},"dependencies":["item.icon"]}}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"directive","name":"value","expression":"item.label","expressionPlan":{"source":"item.label","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"label"},"dependencies":["item.label"]}}],"children":[]}],"flow":{"kind":"each","item":"item","list":"section.items","listPlan":{"source":"section.items","ast":{"kind":"member","object":{"kind":"id","name":"section"},"key":"items"},"dependencies":["section.items"]},"key":"item.action","keyPlan":{"source":"item.action","ast":{"kind":"member","object":{"kind":"id","name":"item"},"key":"action"},"dependencies":["item.action"]}}}],"flow":{"kind":"each","item":"section","list":"sections","listPlan":{"source":"sections","ast":{"kind":"id","name":"sections"},"dependencies":["sections"]},"key":"section.heading","keyPlan":{"source":"section.heading","ast":{"kind":"member","object":{"kind":"id","name":"section"},"key":"heading"},"dependencies":["section.heading"]}}}],"flow":{"kind":"if","test":"overflowOpen","testPlan":{"source":"overflowOpen","ast":{"kind":"id","name":"overflowOpen"},"dependencies":["overflowOpen"]}}}],"flow":{"kind":"if","test":"hasOverflow","testPlan":{"source":"hasOverflow","ast":{"kind":"id","name":"hasOverflow"},"dependencies":["hasOverflow"]}}}]},"css":".looma-editor__mobile-toolbar-shell :host {\n min-width: max-content;\n min-height: 100%;\n padding: 0;\n background: transparent;\n border: 0;\n border-radius: 0;\n box-shadow: none;\n backdrop-filter: none;\n }\n\n .looma-editor__mobile-toolbar-shell :host button {\n min-height: 44px;\n background: transparent;\n }\n\n .looma-editor__mobile-toolbar-shell :host button.active,\n .looma-editor__mobile-toolbar-shell :host button.selected {\n background: var(--ui-accent-soft, var(--ui-accent-subtle));\n }\n\n .looma-editor__mobile-toolbar-shell :host .menu {\n top: auto;\n right: 0;\n bottom: calc(100% + var(--ui-space-2));\n max-height: min(50dvh, 22rem);\n overflow-y: auto;\n overscroll-behavior: contain;\n }\n :host {\n display: inline-flex;\n align-items: center;\n gap: var(--ui-space-1);\n padding: var(--ui-space-1);\n background: color-mix(in srgb, var(--ui-surface) 94%, transparent);\n border: 1px solid var(--ui-border);\n border-radius: calc(var(--ui-radius-md) + 2px);\n box-shadow: var(--ui-shadow-lg, 0 10px 15px -3px rgb(0 0 0 / 0.1));\n backdrop-filter: blur(10px);\n }\n\n .group {\n display: inline-flex;\n align-items: center;\n gap: 2px;\n overflow: hidden;\n }\n\n .sep {\n width: 1px;\n align-self: stretch;\n background: var(--ui-border);\n }\n\n .overflow {\n position: relative;\n }\n\n :host button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--ui-space-2);\n min-height: 32px;\n border: 0;\n border-radius: var(--ui-radius-sm);\n background: transparent;\n color: var(--ui-text-primary);\n cursor: pointer;\n font-size: var(--ui-font-size-sm);\n font-weight: 500;\n line-height: 1;\n padding: var(--ui-space-2) var(--ui-space-2);\n white-space: nowrap;\n }\n\n :host button:hover {\n background: var(--ui-surface-hover);\n }\n\n :host button.active {\n background: var(--ui-accent-soft, var(--ui-accent-subtle));\n color: var(--ui-accent-active);\n }\n\n .group button {\n border-radius: var(--ui-radius-sm);\n }\n\n .group button + button {\n border-left: 0;\n }\n\n :host .more {\n border: 0;\n border-radius: var(--ui-radius-sm);\n }\n\n :host button.danger {\n color: var(--ui-danger);\n }\n\n :host {\n --_ui-default-icon-size: var(--ui-editor-toolbar-icon-size, 1rem);\n --_ui-default-icon-stroke-width: var(--ui-editor-toolbar-icon-stroke-width, 1.75);\n }\n\n .chevron {\n display: inline-flex;\n --_ui-default-icon-size: 0.875rem;\n }\n\n :host .icon-button {\n width: 32px;\n padding-inline: 0;\n }\n\n .menu {\n position: absolute;\n top: calc(100% + var(--ui-space-2));\n right: 0;\n min-width: 12rem;\n padding: var(--ui-space-1);\n background: var(--ui-surface);\n border: 1px solid var(--ui-border);\n border-radius: var(--ui-radius-md);\n box-shadow: var(--ui-shadow-lg, 0 10px 15px -3px rgb(0 0 0 / 0.1));\n display: flex;\n flex-direction: column;\n gap: 2px;\n z-index: 2;\n }\n\n .menu-section + .menu-section {\n margin-top: var(--ui-space-1);\n padding-top: var(--ui-space-1);\n border-top: 1px solid color-mix(in srgb, var(--ui-border) 80%, transparent);\n }\n\n .menu-heading {\n padding: var(--ui-space-1) var(--ui-space-2);\n font-size: var(--ui-font-size-2xs);\n font-weight: 700;\n letter-spacing: 0.05em;\n text-transform: uppercase;\n color: var(--ui-text-muted);\n }\n\n .menu button {\n display: flex;\n justify-content: flex-start;\n width: 100%;\n text-align: left;\n }\n\n .swatches {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 2px;\n }\n\n :host .swatch-button {\n gap: var(--ui-space-1);\n justify-content: flex-start;\n }\n\n .swatch {\n width: 14px;\n height: 14px;\n flex: 0 0 14px;\n border: 1px solid color-mix(in srgb, var(--ui-border) 80%, #000);\n border-radius: 3px;\n background: var(--_swatch);\n }\n\n .swatch.default {\n background:\n linear-gradient(135deg, transparent 44%, var(--ui-danger) 46% 54%, transparent 56%),\n var(--ui-surface);\n }\n\n .swatch-button.selected {\n background: var(--ui-accent-soft, var(--ui-accent-subtle));\n }\n\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"alignments","type":"list(object({ action: align-left | align-center | align-right, label: string, active: boolean }))","expression":{"source":"[]","ast":{"kind":"array","items":[]},"dependencies":[]}},{"kind":"state","name":"structure","type":"list(object({ action: add-row-after | add-column-after, label: string, icon: string }))","expression":{"source":"[]","ast":{"kind":"array","items":[]},"dependencies":[]}},{"kind":"state","name":"swatches","type":"list(object({ action: string, label: string, color: string, selected: boolean }))","expression":{"source":"[]","ast":{"kind":"array","items":[]},"dependencies":[]}},{"kind":"state","name":"sections","type":"list(object({ heading: string, items: list(object({ action: string, label: string, icon: string, danger: boolean })) }))","expression":{"source":"[]","ast":{"kind":"array","items":[]},"dependencies":[]}},{"kind":"state","name":"hasOverflow","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"overflowOpen","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"event","name":"action","type":"object({ action: align-left | align-center | align-right | background-none | background-gray | background-yellow | background-blue | background-green | background-red | add-row-before | add-row-after | add-column-before | add-column-after | clear-cells | merge-cells | split-cell | delete-row | delete-column | delete-table })","bubbles":true,"composed":true,"cancelable":false}],"slots":[],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-editor-table-toolbar/ui-editor-table-toolbar.js"},{"source":{"file":"./components/ui-editor-toolbar/ui-editor-toolbar.html"},"contract":{"version":1,"name":"UiEditorToolbar","tag":"ui-editor-toolbar","nativeElement":"div","props":{"floating":{"type":"boolean","required":false,"target":{"attribute":"floating"},"description":"Shows the toolbar as a floating bar beside the selection rather than pinned to the editor.","default":false}}},"template":{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"role","value":"toolbar"},{"kind":"literal","name":"aria-label","value":"Editor toolbar"}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"strip"}],"children":[{"kind":"slot"}],"ref":"strip"}]},"css":":host {\n position: sticky;\n top: 0;\n z-index: var(--ui-editor-toolbar-z-index, 10);\n display: flex;\n align-items: center;\n padding: var(--ui-editor-toolbar-padding-block, 6px) var(--ui-editor-toolbar-padding-inline, 12px);\n min-height: var(--ui-editor-toolbar-min-height, 48px);\n background: var(--ui-editor-toolbar-surface, var(--ui-surface));\n border-bottom: 1px solid var(--ui-editor-toolbar-border, var(--ui-border));\n }\n\n /* One row, always. When the controls outgrow the space, the row scrolls sideways rather than\n wrapping into several lines, and a fade at each edge that has more to show says so. */\n .strip {\n display: flex;\n flex: 1 1 auto;\n align-items: center;\n justify-content: flex-start;\n gap: var(--ui-editor-toolbar-gap, 2px);\n min-width: 0;\n overflow-x: auto;\n overflow-y: hidden;\n overscroll-behavior-inline: contain;\n scrollbar-width: none;\n }\n\n .strip::-webkit-scrollbar {\n display: none;\n }\n\n .strip > :slotted(*) {\n flex: 0 0 auto;\n }\n\n /* The edge fades are the scroll fade every Looma scroller uses (see ui-scroll-area), a mask on the\n strip, so a floating toolbar's border and shadow stay whole. */\n .strip {\n --_ui-scroll-fade-direction: to right;\n --_ui-scroll-fade-size: var(--ui-editor-toolbar-fade-size, var(--ui-scroll-fade-size, 24px));\n mask-image: linear-gradient(\n var(--_ui-scroll-fade-direction),\n transparent,\n #000 var(--_ui-scroll-fade-start),\n #000 calc(100% - var(--_ui-scroll-fade-end)),\n transparent\n );\n animation: ui-scroll-fade-start linear, ui-scroll-fade-start-hold linear, ui-scroll-fade-end-hold linear, ui-scroll-fade-end linear;\n animation-timeline: scroll(self inline);\n animation-range:\n 0 var(--_ui-scroll-fade-size),\n var(--_ui-scroll-fade-size) calc(100% + 1px),\n -1px calc(100% - var(--_ui-scroll-fade-size)),\n calc(100% - var(--_ui-scroll-fade-size)) 100%;\n }\n\n :host:dir(rtl) .strip {\n --_ui-scroll-fade-direction: to left;\n }\n\n :slotted(.divider) {\n width: 1px;\n height: 20px;\n background: var(--ui-editor-toolbar-divider, var(--ui-border));\n flex-shrink: 0;\n margin: 0 var(--ui-editor-toolbar-divider-margin, 4px);\n }\n\n :host-state([floating]) {\n position: relative;\n top: auto;\n width: max-content;\n max-width: min(calc(100vw - 24px), 100%);\n min-height: auto;\n padding: var(--ui-editor-toolbar-floating-padding, 4px);\n background: color-mix(in srgb, var(--ui-editor-toolbar-surface, var(--ui-surface)) 96%, transparent);\n border: 1px solid var(--ui-editor-toolbar-border, var(--ui-border));\n border-radius: var(--ui-editor-toolbar-floating-radius, var(--ui-radius-lg));\n box-shadow: var(--ui-editor-toolbar-floating-shadow, var(--ui-shadow-lg, 0 10px 24px rgb(0 0 0 / 0.12)));\n backdrop-filter: blur(10px);\n }\n\n @media (max-width: 767px) {\n :host {\n position: fixed;\n top: auto;\n bottom: env(safe-area-inset-bottom);\n left: 0;\n right: 0;\n min-height: var(--ui-editor-toolbar-mobile-min-height, 56px);\n border-top: 1px solid var(--ui-editor-toolbar-border, var(--ui-border));\n border-bottom: none;\n box-shadow: var(--ui-editor-toolbar-mobile-shadow, 0 -2px 8px rgb(0 0 0 / 0.06));\n }\n\n :host-state([floating]) {\n position: relative;\n inset: auto;\n min-height: auto;\n border: 1px solid var(--ui-editor-toolbar-border, var(--ui-border));\n border-radius: var(--ui-editor-toolbar-floating-radius, var(--ui-radius-lg));\n box-shadow: var(--ui-editor-toolbar-floating-shadow, var(--ui-shadow-lg, 0 10px 24px rgb(0 0 0 / 0.12)));\n }\n }\n\n /* Inside LoomaEditor's sticky shell, the shell is the sticky surface. */\n .looma-editor__sticky-toolbar-shell :host {\n position: relative;\n min-height: var(--ui-editor-toolbar-min-height, 48px);\n background: transparent;\n border: 0;\n box-shadow: none;\n }\n\n /* Inside LoomaEditor's mobile shell, the toolbar is a scroll-snapping strip. */\n .looma-editor__mobile-toolbar-shell :host-state([floating]) {\n width: 100%;\n max-width: none;\n min-height: 100%;\n padding: 0;\n background: transparent;\n border: 0;\n border-radius: 0;\n box-shadow: none;\n backdrop-filter: none;\n }\n\n .looma-editor__mobile-toolbar-shell :host-state([floating]) .strip {\n scroll-snap-type: x mandatory;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]}},{"source":{"file":"./components/ui-floating-action-button/ui-floating-action-button.html"},"contract":{"version":1,"name":"UiFloatingActionButton","tag":"ui-floating-action-button","nativeElement":"button","props":{"disabled":{"type":"boolean","required":false,"target":{"attribute":"disabled"},"description":"Disables the button, so it cannot be pressed or focused, and fades it to 60% opacity.","default":false},"label":{"type":"string","required":false,"target":{"attribute":"aria-label"},"description":"The button's accessible name. The button usually holds only an icon, so name the action it performs.","default":""},"mobileOnly":{"type":"boolean","required":false,"target":{"attribute":"mobileonly"},"description":"Hides the button on viewports 768px wide and wider, for a shortcut that only phones need. Make sure the action is reachable another way at those\n widths.","default":false}}},"template":{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"attribute","name":"aria-label","expression":"label","expressionPlan":{"source":"label","ast":{"kind":"id","name":"label"},"dependencies":["label"]}},{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}}],"children":[{"kind":"slot"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-floating-action-button-inset-block-end {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-floating-action-button-inset-inline-end {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-floating-action-button-z-index {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n position: fixed;\n inset-block-end: calc(var(--ui-floating-action-button-inset-block-end, var(--ui-space-6)) + env(safe-area-inset-bottom));\n inset-inline-end: max(\n var(--ui-floating-action-button-inset-inline-end, var(--ui-space-5)),\n env(safe-area-inset-right)\n );\n inline-size: var(--ui-control-min-block-size);\n block-size: var(--ui-control-min-block-size);\n display: inline-flex;\n z-index: var(--ui-floating-action-button-z-index, 100);\n }\n\n :host {\n appearance: none;\n border: none;\n border-radius: 999px;\n margin: 0;\n padding: 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: var(--ui-accent);\n color: var(--ui-on-accent);\n box-shadow: 0 4px 12px color-mix(in srgb, var(--ui-accent) 40%, transparent);\n cursor: pointer;\n transition:\n background-color var(--ui-motion-fast) var(--ui-motion-ease),\n transform var(--ui-motion-fast) var(--ui-motion-ease),\n box-shadow var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n :host:hover:enabled {\n background: var(--ui-accent-hover);\n box-shadow: 0 6px 16px color-mix(in srgb, var(--ui-accent) 50%, transparent);\n }\n\n :host:active:enabled {\n transform: scale(0.94);\n }\n\n :host:focus-visible {\n outline: 2px solid var(--ui-focus-ring);\n outline-offset: 2px;\n }\n\n :host:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n }\n\n :slotted(svg) {\n inline-size: var(--ui-icon-size-lg);\n block-size: var(--ui-icon-size-lg);\n flex-shrink: 0;\n }\n\n @media (min-width: 768px) {\n :host-state([mobileOnly]) {\n display: none;\n }\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"button","choices":["button"]}},{"source":{"file":"./components/ui-form-field/ui-form-field.html"},"contract":{"version":1,"name":"UiFormField","tag":"ui-form-field","nativeElement":"div","props":{"disabled":{"type":"boolean","required":false,"target":{"attribute":"disabled"},"description":"Disables the field's control: the first input, textarea, or select inside it. The field writes this to the control whenever it updates, so set it here\n rather than on the control.","default":false},"invalid":{"type":"boolean","required":false,"target":{"attribute":"invalid"},"description":"Marks the field's control invalid by setting aria-invalid on it. Pair it with content in the error slot, which the field already links to the control as\n its description.","default":false},"required":{"type":"boolean","required":false,"target":{"attribute":"required"},"description":"Marks the field's control required, for native form validation. Like disabled, it is written to the control, so set it here rather than on the control. It\n adds no visual marker; show one in the label if the form needs it.","default":false}}},"template":{"kind":"element","name":"div","attributes":[],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"label"}],"children":[{"kind":"slot","fallback":[],"name":"label"}]},{"kind":"slot"},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"help"}],"children":[{"kind":"slot","fallback":[],"name":"help"}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"error"}],"children":[{"kind":"slot","fallback":[],"name":"error"}]}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-form-field-help-min-block-size {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-form-field-help-min-block-size: var(--ui-form-field-help-min-block-size);\n\n display: grid;\n gap: var(--ui-space-2);\n min-inline-size: 0;\n align-content: start;\n color: var(--ui-text-primary);\n }\n\n /* Each named region styles whatever fills it, however it was slotted (slot=\"…\" in HTML, #label\n in Vue), and generates no box of its own, so an empty region adds no gap. */\n .label,\n .help,\n .error {\n display: contents;\n }\n\n .label {\n color: var(--ui-text-secondary);\n font-size: var(--ui-font-size-sm);\n }\n\n .help {\n color: var(--ui-text-muted);\n font-size: var(--ui-font-size-sm);\n line-height: var(--ui-line-height-md);\n }\n\n .help > :slotted(*) {\n min-block-size: var(--_ui-form-field-help-min-block-size, 0);\n }\n\n /* An error reads in the danger colour, the one the invalid control's border takes. */\n .error,\n :slotted([role=\"alert\"]) {\n color: var(--ui-danger);\n font-size: var(--ui-font-size-sm);\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true,"name":"label"},{"dynamic":false,"required":true},{"dynamic":false,"required":true,"name":"help"},{"dynamic":false,"required":true,"name":"error"}],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-form-field/ui-form-field.js"},{"source":{"file":"./components/ui-grid/ui-grid.html"},"contract":{"version":1,"name":"UiGrid","tag":"ui-grid","nativeElement":"div","props":{"gap":{"type":{"enum":["xs","s","m","l","xl"]},"required":false,"target":{"attribute":"gap"},"description":"Space between cells, on the spacing scale: xs is 0.5rem, s 0.75rem, m 1rem (also the default), l 1.5rem, and xl 2rem. The --ui-grid-gap custom property,\n set on the grid itself, overrides it; set on an ancestor, it does nothing."},"min":{"type":{"enum":["sm","md","lg"]},"required":false,"target":{"attribute":"min"},"description":"The narrowest a column may get before the grid drops to fewer columns: sm is 12rem (also the default), md is 16rem, and lg is 20rem. The grid fits as many\n equal columns as its width allows, and a single column never overflows a narrower container."}}},"template":{"kind":"element","name":"div","attributes":[],"children":[{"kind":"slot"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-grid-gap {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-grid-min {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n --_grid-gap: var(--ui-space-4);\n --_grid-min: 12rem;\n display: grid;\n gap: var(--ui-grid-gap, var(--_grid-gap));\n grid-template-columns: repeat(auto-fit, minmax(min(var(--ui-grid-min, var(--_grid-min)), 100%), 1fr));\n min-inline-size: 0;\n max-inline-size: 100%;\n margin: 0;\n }\n\n :host-state([gap=\"xs\"]) {\n --_grid-gap: var(--ui-space-2);\n }\n :host-state([gap=\"s\"]) {\n --_grid-gap: var(--ui-space-3);\n }\n :host-state([gap=\"m\"]) {\n --_grid-gap: var(--ui-space-4);\n }\n :host-state([gap=\"l\"]) {\n --_grid-gap: var(--ui-space-5);\n }\n :host-state([gap=\"xl\"]) {\n --_grid-gap: var(--ui-space-6);\n }\n :host-state([min=\"md\"]) {\n --_grid-min: 16rem;\n }\n :host-state([min=\"lg\"]) {\n --_grid-min: 20rem;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]}},{"source":{"file":"./components/ui-icon-button/ui-icon-button.html"},"contract":{"version":1,"name":"UiIconButton","tag":"ui-icon-button","nativeElement":"button","props":{"anticipatory":{"type":"boolean","required":false,"target":{"attribute":"anticipatory"},"description":"Keeps the button out of sight until it is wanted: at rest a fine pointer sees only a small guide dot, and the button appears on hover, on focus, or when\n the pointer comes near inside a ui-affordance-scope. Touch devices and the solid variant always show it.","default":false},"disabled":{"type":"boolean","required":false,"target":{"attribute":"disabled"},"description":"Disables the button, so it cannot be pressed or focused, and washes it out: the same shape, with less colour and contrast (--ui-disabled-filter).","default":false},"label":{"type":"string","required":false,"target":{"attribute":"aria-label"},"description":"Accessible name for the icon."},"round":{"type":"boolean","required":false,"target":{"attribute":"round"},"description":"Use a fully circular shape.","default":false},"size":{"type":{"enum":["sm","md","lg"]},"required":false,"target":{"attribute":"size"},"description":"Button and icon size together: sm is 1.75rem with a small icon, md is 2rem, and lg is 2.5rem with a large icon. On touch, every size gets an invisible hit\n area of at least 44px.","default":"md"},"variant":{"type":{"enum":["ghost","outline","solid"]},"required":false,"target":{"attribute":"variant"},"description":"Emphasis. ghost shows only the icon until it is hovered, for toolbars and dense rows; outline adds a border on the default surface; solid fills with the\n accent colour, for the one primary action in a group.","default":"ghost"}}},"template":{"kind":"element","name":"button","attributes":[{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}},{"kind":"literal","name":"type","value":"button"},{"kind":"attribute","name":"aria-label","expression":"label","expressionPlan":{"source":"label","ast":{"kind":"id","name":"label"},"dependencies":["label"]}}],"children":[{"kind":"slot"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-icon-button-active-scale {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-button-border {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-button-disabled-filter {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-button-disabled-opacity {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-button-hover-border {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-button-hover-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-button-hover-text {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-button-icon-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-button-icon-stroke-width {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-button-outline-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-button-outline-text {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-button-radius {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-button-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-button-solid-hover-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-button-solid-shadow {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-button-solid-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-button-solid-text {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-button-surface {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-icon-button-icon-size: var(--ui-icon-button-icon-size);\n --_ui-icon-button-icon-stroke-width: var(--ui-icon-button-icon-stroke-width);\n\n display: inline-flex;\n color: var(--ui-text-secondary);\n }\n\n :host-state([anticipatory]) {\n position: relative;\n }\n\n :host-state([anticipatory])::before {\n content: \"\";\n position: absolute;\n inset: 50% auto auto 50%;\n z-index: 1;\n inline-size: var(--ui-affordance-guide-size);\n block-size: var(--ui-affordance-guide-size);\n border-radius: var(--ui-radius-round);\n background: var(--ui-affordance-guide-color, var(--ui-border-strong));\n opacity: calc(var(--ui-affordance-guide-opacity) * var(--ui-affordance-scope-guide, 1));\n transform: translate(-50%, -50%);\n transition: opacity var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease);\n pointer-events: none;\n }\n\n /* At rest an anticipatory button shows only its guide dot; proximity, hover, or focus reveals the\n * surface and icon. The root is the native button, so hiding it outright would hide the dot\n * too, and slotted icons sit outside this scope; `color: transparent` hides currentColor icons. */\n @media (hover: hover) and (pointer: fine) {\n :host-state([anticipatory]):not(:host-state([variant=\"solid\"]), [data-ui-proximity=\"near\"], :hover, :focus-visible) {\n border-color: transparent;\n background: transparent;\n box-shadow: none;\n color: transparent;\n }\n }\n\n :host-state([anticipatory]):is(:host-state([variant=\"solid\"]), [data-ui-proximity=\"near\"], :hover, :focus-visible)::before {\n opacity: 0;\n }\n\n :host {\n /* The size prop resolves here; --ui-icon-button-size overrides it on an element. */\n --_size: 2rem;\n appearance: none;\n inline-size: var(--ui-icon-button-size, var(--_size));\n block-size: var(--ui-icon-button-size, var(--_size));\n min-inline-size: var(--ui-icon-button-size, var(--_size));\n min-block-size: var(--ui-icon-button-size, var(--_size));\n padding: 0;\n margin: 0;\n border: 1px solid transparent;\n border-radius: var(--ui-icon-button-radius, var(--ui-radius-md));\n background: var(--ui-icon-button-surface, transparent);\n color: inherit;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition:\n background-color var(--ui-motion-fast) var(--ui-motion-ease),\n border-color var(--ui-motion-fast) var(--ui-motion-ease),\n color var(--ui-motion-fast) var(--ui-motion-ease),\n box-shadow var(--ui-motion-fast) var(--ui-motion-ease),\n transform var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n @media (hover: none), (pointer: coarse) {\n :host-state([anticipatory])::before {\n opacity: 0;\n }\n }\n\n /* A touch target without a bigger button: an invisible hit area, at least the control\n minimum, centred on the button (::before is the anticipatory guide). */\n @media (pointer: coarse) {\n :host {\n position: relative;\n }\n\n :host::after {\n content: \"\";\n position: absolute;\n inset: 50% auto auto 50%;\n inline-size: max(100%, var(--ui-control-min-block-size));\n block-size: max(100%, var(--ui-control-min-block-size));\n transform: translate(-50%, -50%);\n }\n }\n\n html[data-ui-input-modality=\"touch\"] :host {\n position: relative;\n }\n\n html[data-ui-input-modality=\"touch\"] :host::after {\n content: \"\";\n position: absolute;\n inset: 50% auto auto 50%;\n inline-size: max(100%, var(--ui-control-min-block-size));\n block-size: max(100%, var(--ui-control-min-block-size));\n transform: translate(-50%, -50%);\n }\n\n :host-state([size=\"sm\"]) {\n --_size: 1.75rem;\n inline-size: var(--ui-icon-button-size, var(--_size));\n block-size: var(--ui-icon-button-size, var(--_size));\n min-inline-size: var(--ui-icon-button-size, var(--_size));\n min-block-size: var(--ui-icon-button-size, var(--_size));\n }\n\n :host-state([size=\"lg\"]) {\n --_size: 2.5rem;\n inline-size: var(--ui-icon-button-size, var(--_size));\n block-size: var(--ui-icon-button-size, var(--_size));\n min-inline-size: var(--ui-icon-button-size, var(--_size));\n min-block-size: var(--ui-icon-button-size, var(--_size));\n }\n\n :host-state([round]) {\n border-radius: var(--ui-radius-round);\n }\n\n :host-state([variant=\"outline\"]) {\n border-color: var(--ui-icon-button-border, var(--ui-border-default));\n background: var(--ui-icon-button-outline-surface, var(--ui-surface-default));\n color: var(--ui-icon-button-outline-text, var(--ui-text-primary));\n }\n\n :host-state([variant=\"solid\"]) {\n background: var(--ui-icon-button-solid-surface, var(--ui-accent-solid));\n color: var(--ui-icon-button-solid-text, var(--ui-text-on-accent));\n box-shadow: var(\n --ui-icon-button-solid-shadow,\n 0 1px 2px color-mix(in srgb, var(--ui-accent-solid) 18%, transparent)\n );\n }\n\n :host:hover:enabled {\n /* Derived from the text colour so the ghost hover shows on any background. */\n background: var(--ui-icon-button-hover-surface, color-mix(in srgb, currentColor 8%, transparent));\n color: var(--ui-icon-button-hover-text, var(--ui-text-primary));\n }\n\n :host-state([variant=\"outline\"]):hover:enabled {\n border-color: var(--ui-icon-button-hover-border, var(--ui-border-strong));\n }\n\n :host-state([variant=\"solid\"]):hover:enabled {\n background: var(--ui-icon-button-solid-hover-surface, var(--ui-accent-hover));\n }\n\n :host:active:enabled {\n transform: scale(var(--ui-icon-button-active-scale, 0.96));\n }\n\n :host:focus-visible {\n outline: none;\n box-shadow: var(--ui-focus-halo);\n }\n\n /* Disabled colours fall back to each variant's own; ghost takes only the icon colour. */\n /* Disabled washes the button out the way Button does: the same shape, one filter. */\n :host:disabled {\n filter: var(--ui-icon-button-disabled-filter, var(--ui-disabled-filter));\n opacity: var(--ui-icon-button-disabled-opacity, 1);\n cursor: not-allowed;\n box-shadow: none;\n }\n\n :host {\n --_icon-button-icon-default: var(--ui-icon-size-md);\n /* A slotted ui-icon is its own component, out of reach of the svg rule below; these are its\n defaults, which its own --ui-icon-* hooks still override. */\n --_ui-default-icon-size: var(--_ui-icon-button-icon-size, var(--_icon-button-icon-default));\n --_ui-default-icon-stroke-width: var(--_ui-icon-button-icon-stroke-width, 1.75);\n }\n\n :host-state([size=\"sm\"]) {\n --_icon-button-icon-default: var(--ui-icon-size-sm);\n }\n\n :host-state([size=\"lg\"]) {\n --_icon-button-icon-default: var(--ui-icon-size-lg);\n }\n\n :slotted(svg) {\n inline-size: var(--_ui-icon-button-icon-size, var(--_icon-button-icon-default));\n block-size: var(--_ui-icon-button-icon-size, var(--_icon-button-icon-default));\n flex-shrink: 0;\n stroke-width: var(--_ui-icon-button-icon-stroke-width, 1.75);\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"button","choices":["button"]},"controller":"./components/ui-icon-button/ui-icon-button.js"},{"source":{"file":"./components/ui-icon/ui-icon.html"},"contract":{"version":1,"name":"UiIcon","tag":"ui-icon","nativeElement":"span","props":{"name":{"type":"string","required":false,"target":{"attribute":"name"},"description":"Which icon to draw, by its name in Looma's icon set (LOOMA_ICONS), such as \"align-left\". An unknown or empty name draws nothing. The icon is hidden from\n assistive technology, so name the control it sits in.","default":""}}},"template":{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[{"kind":"element","name":"svg","attributes":[{"kind":"literal","name":"viewBox","value":"0 0 24 24"},{"kind":"literal","name":"fill","value":"none"},{"kind":"literal","name":"stroke","value":"currentColor"},{"kind":"literal","name":"stroke-width","value":"2"},{"kind":"literal","name":"stroke-linecap","value":"round"},{"kind":"literal","name":"stroke-linejoin","value":"round"},{"kind":"literal","name":"focusable","value":"false"}],"children":[{"kind":"element","name":"g","attributes":[],"children":[{"kind":"element","name":"path","attributes":[{"kind":"attribute","name":"d","expression":"shape.d","expressionPlan":{"source":"shape.d","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"d"},"dependencies":["shape.d"]}}],"children":[],"flow":{"kind":"if","test":"shape.tag = 'path'","testPlan":{"source":"shape.tag = 'path'","ast":{"kind":"binary","op":"=","left":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"tag"},"right":{"kind":"literal","value":"path"}},"dependencies":["shape.tag"]}}},{"kind":"element","name":"circle","attributes":[{"kind":"attribute","name":"cx","expression":"shape.cx","expressionPlan":{"source":"shape.cx","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"cx"},"dependencies":["shape.cx"]}},{"kind":"attribute","name":"cy","expression":"shape.cy","expressionPlan":{"source":"shape.cy","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"cy"},"dependencies":["shape.cy"]}},{"kind":"attribute","name":"r","expression":"shape.r","expressionPlan":{"source":"shape.r","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"r"},"dependencies":["shape.r"]}}],"children":[],"flow":{"kind":"if","test":"shape.tag = 'circle'","testPlan":{"source":"shape.tag = 'circle'","ast":{"kind":"binary","op":"=","left":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"tag"},"right":{"kind":"literal","value":"circle"}},"dependencies":["shape.tag"]}}},{"kind":"element","name":"rect","attributes":[{"kind":"attribute","name":"x","expression":"shape.x","expressionPlan":{"source":"shape.x","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"x"},"dependencies":["shape.x"]}},{"kind":"attribute","name":"y","expression":"shape.y","expressionPlan":{"source":"shape.y","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"y"},"dependencies":["shape.y"]}},{"kind":"attribute","name":"width","expression":"shape.width","expressionPlan":{"source":"shape.width","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"width"},"dependencies":["shape.width"]}},{"kind":"attribute","name":"height","expression":"shape.height","expressionPlan":{"source":"shape.height","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"height"},"dependencies":["shape.height"]}},{"kind":"attribute","name":"rx","expression":"shape.rx","expressionPlan":{"source":"shape.rx","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"rx"},"dependencies":["shape.rx"]}},{"kind":"attribute","name":"ry","expression":"shape.ry","expressionPlan":{"source":"shape.ry","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"ry"},"dependencies":["shape.ry"]}}],"children":[],"flow":{"kind":"if","test":"shape.tag = 'rect'","testPlan":{"source":"shape.tag = 'rect'","ast":{"kind":"binary","op":"=","left":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"tag"},"right":{"kind":"literal","value":"rect"}},"dependencies":["shape.tag"]}}},{"kind":"element","name":"line","attributes":[{"kind":"attribute","name":"x1","expression":"shape.x1","expressionPlan":{"source":"shape.x1","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"x1"},"dependencies":["shape.x1"]}},{"kind":"attribute","name":"y1","expression":"shape.y1","expressionPlan":{"source":"shape.y1","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"y1"},"dependencies":["shape.y1"]}},{"kind":"attribute","name":"x2","expression":"shape.x2","expressionPlan":{"source":"shape.x2","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"x2"},"dependencies":["shape.x2"]}},{"kind":"attribute","name":"y2","expression":"shape.y2","expressionPlan":{"source":"shape.y2","ast":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"y2"},"dependencies":["shape.y2"]}}],"children":[],"flow":{"kind":"if","test":"shape.tag = 'line'","testPlan":{"source":"shape.tag = 'line'","ast":{"kind":"binary","op":"=","left":{"kind":"member","object":{"kind":"id","name":"shape"},"key":"tag"},"right":{"kind":"literal","value":"line"}},"dependencies":["shape.tag"]}}}],"flow":{"kind":"each","item":"shape","list":"shapes","listPlan":{"source":"shapes","ast":{"kind":"id","name":"shapes"},"dependencies":["shapes"]}}}]}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-icon-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-icon-stroke-width {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the svg reads the stroke from the root. A Looma component that\n sizes the icons it renders sets --_ui-default-icon-*, which the icon's own hooks override. */\n --_ui-icon-stroke-width: var(--ui-icon-stroke-width, var(--_ui-default-icon-stroke-width));\n\n display: inline-flex;\n flex: none;\n inline-size: var(--ui-icon-size, var(--_ui-default-icon-size, 1em));\n block-size: var(--ui-icon-size, var(--_ui-default-icon-size, 1em));\n }\n\n svg {\n inline-size: 100%;\n block-size: 100%;\n stroke-width: var(--_ui-icon-stroke-width, 2);\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"computed","name":"shapes","expression":{"source":"{\n 'align-center': [{ tag: 'path', d: 'M21 5H3' }, { tag: 'path', d: 'M17 12H7' }, { tag: 'path', d: 'M19 19H5' }],\n 'align-left': [{ tag: 'path', d: 'M21 5H3' }, { tag: 'path', d: 'M15 12H3' }, { tag: 'path', d: 'M17 19H3' }],\n 'align-right': [{ tag: 'path', d: 'M21 5H3' }, { tag: 'path', d: 'M21 12H9' }, { tag: 'path', d: 'M21 19H7' }],\n 'arrow-left': [{ tag: 'path', d: 'm12 19-7-7 7-7' }, { tag: 'path', d: 'M19 12H5' }],\n 'bold': [{ tag: 'path', d: 'M6 12h9a4 4 0 0 1 0 8H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h7a4 4 0 0 1 0 8' }],\n 'book-user': [{ tag: 'path', d: 'M15 13a3 3 0 1 0-6 0' }, { tag: 'path', d: 'M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20' }, { tag: 'circle', cx: '12', cy: '8', r: '2' }],\n 'braces': [{ tag: 'path', d: 'M8 3H7a2 2 0 0 0-2 2v5a2 2 0 0 1-2 2 2 2 0 0 1 2 2v5c0 1.1.9 2 2 2h1' }, { tag: 'path', d: 'M16 21h1a2 2 0 0 0 2-2v-5c0-1.1.9-2 2-2a2 2 0 0 1-2-2V5a2 2 0 0 0-2-2h-1' }],\n 'calculator': [{ tag: 'rect', width: '16', height: '20', x: '4', y: '2', rx: '2' }, { tag: 'line', x1: '8', x2: '16', y1: '6', y2: '6' }, { tag: 'line', x1: '16', x2: '16', y1: '14', y2: '18' }, { tag: 'path', d: 'M16 10h.01' }, { tag: 'path', d: 'M12 10h.01' }, { tag: 'path', d: 'M8 10h.01' }, { tag: 'path', d: 'M12 14h.01' }, { tag: 'path', d: 'M8 14h.01' }, { tag: 'path', d: 'M12 18h.01' }, { tag: 'path', d: 'M8 18h.01' }],\n 'chevron-down': [{ tag: 'path', d: 'm6 9 6 6 6-6' }],\n 'chevron-left': [{ tag: 'path', d: 'm15 18-6-6 6-6' }],\n 'chevron-right': [{ tag: 'path', d: 'm9 18 6-6-6-6' }],\n 'circle-check': [{ tag: 'circle', cx: '12', cy: '12', r: '10' }, { tag: 'path', d: 'm9 12 2 2 4-4' }],\n 'circle-x': [{ tag: 'circle', cx: '12', cy: '12', r: '10' }, { tag: 'path', d: 'm15 9-6 6' }, { tag: 'path', d: 'm9 9 6 6' }],\n 'code-xml': [{ tag: 'path', d: 'm18 16 4-4-4-4' }, { tag: 'path', d: 'm6 8-4 4 4 4' }, { tag: 'path', d: 'm14.5 4-5 16' }],\n 'columns': [{ tag: 'rect', width: '18', height: '18', x: '3', y: '3', rx: '2' }, { tag: 'path', d: 'M9 3v18' }, { tag: 'path', d: 'M15 3v18' }],\n 'credit-card': [{ tag: 'rect', width: '20', height: '14', x: '2', y: '5', rx: '2' }, { tag: 'line', x1: '2', x2: '22', y1: '10', y2: '10' }],\n 'ellipsis': [{ tag: 'circle', cx: '12', cy: '12', r: '1' }, { tag: 'circle', cx: '19', cy: '12', r: '1' }, { tag: 'circle', cx: '5', cy: '12', r: '1' }],\n 'eraser': [{ tag: 'path', d: 'M21 21H8a2 2 0 0 1-1.42-.587l-3.994-3.999a2 2 0 0 1 0-2.828l10-10a2 2 0 0 1 2.829 0l5.999 6a2 2 0 0 1 0 2.828L12.834 21' }, { tag: 'path', d: 'm5.082 11.09 8.828 8.828' }],\n 'file-text': [{ tag: 'path', d: 'M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z' }, { tag: 'path', d: 'M14 2v5a1 1 0 0 0 1 1h5' }, { tag: 'path', d: 'M10 9H8' }, { tag: 'path', d: 'M16 13H8' }, { tag: 'path', d: 'M16 17H8' }],\n 'folder': [{ tag: 'path', d: 'M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z' }],\n 'grip-horizontal': [{ tag: 'circle', cx: '12', cy: '9', r: '1' }, { tag: 'circle', cx: '19', cy: '9', r: '1' }, { tag: 'circle', cx: '5', cy: '9', r: '1' }, { tag: 'circle', cx: '12', cy: '15', r: '1' }, { tag: 'circle', cx: '19', cy: '15', r: '1' }, { tag: 'circle', cx: '5', cy: '15', r: '1' }],\n 'grip-vertical': [{ tag: 'circle', cx: '9', cy: '12', r: '1' }, { tag: 'circle', cx: '9', cy: '5', r: '1' }, { tag: 'circle', cx: '9', cy: '19', r: '1' }, { tag: 'circle', cx: '15', cy: '12', r: '1' }, { tag: 'circle', cx: '15', cy: '5', r: '1' }, { tag: 'circle', cx: '15', cy: '19', r: '1' }],\n 'heading-1': [{ tag: 'path', d: 'M4 12h8' }, { tag: 'path', d: 'M4 18V6' }, { tag: 'path', d: 'M12 18V6' }, { tag: 'path', d: 'm17 12 3-2v8' }],\n 'heading-2': [{ tag: 'path', d: 'M4 12h8' }, { tag: 'path', d: 'M4 18V6' }, { tag: 'path', d: 'M12 18V6' }, { tag: 'path', d: 'M21 18h-4c0-4 4-3 4-6 0-1.5-2-2.5-4-1' }],\n 'heading-3': [{ tag: 'path', d: 'M4 12h8' }, { tag: 'path', d: 'M4 18V6' }, { tag: 'path', d: 'M12 18V6' }, { tag: 'path', d: 'M17.5 10.5c1.7-1 3.5 0 3.5 1.5a2 2 0 0 1-2 2' }, { tag: 'path', d: 'M17 17.5c2 1.5 4 .3 4-1.5a2 2 0 0 0-2-2' }],\n 'help': [{ tag: 'circle', cx: '12', cy: '12', r: '10' }, { tag: 'path', d: 'M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3' }, { tag: 'path', d: 'M12 17h.01' }],\n 'highlighter': [{ tag: 'path', d: 'm9 11-6 6v3h9l3-3' }, { tag: 'path', d: 'm22 12-4.6 4.6a2 2 0 0 1-2.8 0l-5.2-5.2a2 2 0 0 1 0-2.8L14 4' }],\n 'image': [{ tag: 'rect', width: '18', height: '18', x: '3', y: '3', rx: '2', ry: '2' }, { tag: 'circle', cx: '9', cy: '9', r: '2' }, { tag: 'path', d: 'm21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21' }],\n 'info': [{ tag: 'circle', cx: '12', cy: '12', r: '10' }, { tag: 'path', d: 'M12 16v-4' }, { tag: 'path', d: 'M12 8h.01' }],\n 'italic': [{ tag: 'line', x1: '19', x2: '10', y1: '4', y2: '4' }, { tag: 'line', x1: '14', x2: '5', y1: '20', y2: '20' }, { tag: 'line', x1: '15', x2: '9', y1: '4', y2: '20' }],\n 'layout-dashboard': [{ tag: 'rect', width: '7', height: '9', x: '3', y: '3', rx: '1' }, { tag: 'rect', width: '7', height: '5', x: '14', y: '3', rx: '1' }, { tag: 'rect', width: '7', height: '9', x: '14', y: '12', rx: '1' }, { tag: 'rect', width: '7', height: '5', x: '3', y: '16', rx: '1' }],\n 'list': [{ tag: 'path', d: 'M3 5h.01' }, { tag: 'path', d: 'M3 12h.01' }, { tag: 'path', d: 'M3 19h.01' }, { tag: 'path', d: 'M8 5h13' }, { tag: 'path', d: 'M8 12h13' }, { tag: 'path', d: 'M8 19h13' }],\n 'list-ordered': [{ tag: 'path', d: 'M11 5h10' }, { tag: 'path', d: 'M11 12h10' }, { tag: 'path', d: 'M11 19h10' }, { tag: 'path', d: 'M4 4h1v5' }, { tag: 'path', d: 'M4 9h2' }, { tag: 'path', d: 'M6.5 20H3.4c0-1 2.6-1.925 2.6-3.5a1.5 1.5 0 0 0-2.6-1.02' }],\n 'list-todo': [{ tag: 'path', d: 'M13 5h8' }, { tag: 'path', d: 'M13 12h8' }, { tag: 'path', d: 'M13 19h8' }, { tag: 'path', d: 'm3 17 2 2 4-4' }, { tag: 'rect', x: '3', y: '4', width: '6', height: '6', rx: '1' }],\n 'loader': [{ tag: 'path', d: 'M21 12a9 9 0 1 1-6.219-8.56' }],\n 'merge': [{ tag: 'path', d: 'm8 6 4-4 4 4' }, { tag: 'path', d: 'M12 2v10.3a4 4 0 0 1-1.172 2.872L4 22' }, { tag: 'path', d: 'm20 22-5-5' }],\n 'minus': [{ tag: 'path', d: 'M5 12h14' }],\n 'notebook-pen': [{ tag: 'path', d: 'M13.4 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-7.4' }, { tag: 'path', d: 'M2 6h4' }, { tag: 'path', d: 'M2 10h4' }, { tag: 'path', d: 'M2 14h4' }, { tag: 'path', d: 'M2 18h4' }, { tag: 'path', d: 'M21.378 5.626a1 1 0 1 0-3.004-3.004l-5.01 5.012a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506z' }],\n 'paint-bucket': [{ tag: 'path', d: 'm19 11-8-8-8.6 8.6a2 2 0 0 0 0 2.8l5.2 5.2c.8.8 2 .8 2.8 0L19 11Z' }, { tag: 'path', d: 'm5 2 5 5' }, { tag: 'path', d: 'M2 13h15' }, { tag: 'path', d: 'M22 20a2 2 0 1 1-4 0c0-1.6 1.7-2.4 2-4 .3 1.6 2 2.4 2 4Z' }],\n 'panel-bottom': [{ tag: 'rect', width: '18', height: '18', x: '3', y: '3', rx: '2' }, { tag: 'path', d: 'M3 15h18' }],\n 'panel-left': [{ tag: 'rect', width: '18', height: '18', x: '3', y: '3', rx: '2' }, { tag: 'path', d: 'M9 3v18' }],\n 'panel-right': [{ tag: 'rect', width: '18', height: '18', x: '3', y: '3', rx: '2' }, { tag: 'path', d: 'M15 3v18' }],\n 'panel-top': [{ tag: 'rect', width: '18', height: '18', x: '3', y: '3', rx: '2' }, { tag: 'path', d: 'M3 9h18' }],\n 'pilcrow': [{ tag: 'path', d: 'M13 4v16' }, { tag: 'path', d: 'M17 4v16' }, { tag: 'path', d: 'M19 4H9.5a4.5 4.5 0 0 0 0 9H13' }],\n 'plus': [{ tag: 'path', d: 'M5 12h14' }, { tag: 'path', d: 'M12 5v14' }],\n 'quote': [{ tag: 'path', d: 'M16 3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2 1 1 0 0 1 1 1v1a2 2 0 0 1-2 2 1 1 0 0 0-1 1v2a1 1 0 0 0 1 1 6 6 0 0 0 6-6V5a2 2 0 0 0-2-2z' }, { tag: 'path', d: 'M5 3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2 1 1 0 0 1 1 1v1a2 2 0 0 1-2 2 1 1 0 0 0-1 1v2a1 1 0 0 0 1 1 6 6 0 0 0 6-6V5a2 2 0 0 0-2-2z' }],\n 'receipt': [{ tag: 'path', d: 'M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1Z' }, { tag: 'path', d: 'M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8' }, { tag: 'path', d: 'M12 17.5v-11' }],\n 'redo': [{ tag: 'path', d: 'm15 14 5-5-5-5' }, { tag: 'path', d: 'M20 9H9.5A5.5 5.5 0 0 0 4 14.5A5.5 5.5 0 0 0 9.5 20H13' }],\n 'rows': [{ tag: 'rect', width: '18', height: '18', x: '3', y: '3', rx: '2' }, { tag: 'path', d: 'M21 9H3' }, { tag: 'path', d: 'M21 15H3' }],\n 'settings': [{ tag: 'path', d: 'M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915' }, { tag: 'circle', cx: '12', cy: '12', r: '3' }],\n 'split': [{ tag: 'path', d: 'M16 3h5v5' }, { tag: 'path', d: 'M8 3H3v5' }, { tag: 'path', d: 'M12 22v-8.3a4 4 0 0 0-1.172-2.872L3 3' }, { tag: 'path', d: 'm15 9 6-6' }],\n 'strikethrough': [{ tag: 'path', d: 'M16 4H9a3 3 0 0 0-2.83 4' }, { tag: 'path', d: 'M14 12a4 4 0 0 1 0 8H6' }, { tag: 'line', x1: '4', x2: '20', y1: '12', y2: '12' }],\n 'table': [{ tag: 'path', d: 'M9 3H5a2 2 0 0 0-2 2v4m6-6h10a2 2 0 0 1 2 2v4M9 3v18m0 0h10a2 2 0 0 0 2-2V9M9 21H5a2 2 0 0 1-2-2V9m0 0h18' }],\n 'trash': [{ tag: 'path', d: 'M10 11v6' }, { tag: 'path', d: 'M14 11v6' }, { tag: 'path', d: 'M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6' }, { tag: 'path', d: 'M3 6h18' }, { tag: 'path', d: 'M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2' }],\n 'triangle-alert': [{ tag: 'path', d: 'm21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3' }, { tag: 'path', d: 'M12 9v4' }, { tag: 'path', d: 'M12 17h.01' }],\n 'truck': [{ tag: 'path', d: 'M14 18V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v11a1 1 0 0 0 1 1h2' }, { tag: 'path', d: 'M15 18H9' }, { tag: 'path', d: 'M19 18h2a1 1 0 0 0 1-1v-3.65a1 1 0 0 0-.22-.624l-3.48-4.35A1 1 0 0 0 17.52 8H14' }, { tag: 'circle', cx: '17', cy: '18', r: '2' }, { tag: 'circle', cx: '7', cy: '18', r: '2' }],\n 'underline': [{ tag: 'path', d: 'M6 4v6a6 6 0 0 0 12 0V4' }, { tag: 'line', x1: '4', x2: '20', y1: '20', y2: '20' }],\n 'undo': [{ tag: 'path', d: 'M9 14 4 9l5-5' }, { tag: 'path', d: 'M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5a5.5 5.5 0 0 1-5.5 5.5H11' }],\n 'users': [{ tag: 'path', d: 'M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2' }, { tag: 'path', d: 'M16 3.128a4 4 0 0 1 0 7.744' }, { tag: 'path', d: 'M22 21v-2a4 4 0 0 0-3-3.87' }, { tag: 'circle', cx: '9', cy: '7', r: '4' }],\n }[name]","ast":{"kind":"index","object":{"kind":"object","pairs":[{"key":"align-center","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M21 5H3"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M17 12H7"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M19 19H5"}}]}]}},{"key":"align-left","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M21 5H3"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M15 12H3"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M17 19H3"}}]}]}},{"key":"align-right","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M21 5H3"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M21 12H9"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M21 19H7"}}]}]}},{"key":"arrow-left","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"m12 19-7-7 7-7"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M19 12H5"}}]}]}},{"key":"bold","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M6 12h9a4 4 0 0 1 0 8H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h7a4 4 0 0 1 0 8"}}]}]}},{"key":"book-user","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M15 13a3 3 0 1 0-6 0"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"circle"}},{"key":"cx","value":{"kind":"literal","value":"12"}},{"key":"cy","value":{"kind":"literal","value":"8"}},{"key":"r","value":{"kind":"literal","value":"2"}}]}]}},{"key":"braces","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M8 3H7a2 2 0 0 0-2 2v5a2 2 0 0 1-2 2 2 2 0 0 1 2 2v5c0 1.1.9 2 2 2h1"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M16 21h1a2 2 0 0 0 2-2v-5c0-1.1.9-2 2-2a2 2 0 0 1-2-2V5a2 2 0 0 0-2-2h-1"}}]}]}},{"key":"calculator","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"rect"}},{"key":"width","value":{"kind":"literal","value":"16"}},{"key":"height","value":{"kind":"literal","value":"20"}},{"key":"x","value":{"kind":"literal","value":"4"}},{"key":"y","value":{"kind":"literal","value":"2"}},{"key":"rx","value":{"kind":"literal","value":"2"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"line"}},{"key":"x1","value":{"kind":"literal","value":"8"}},{"key":"x2","value":{"kind":"literal","value":"16"}},{"key":"y1","value":{"kind":"literal","value":"6"}},{"key":"y2","value":{"kind":"literal","value":"6"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"line"}},{"key":"x1","value":{"kind":"literal","value":"16"}},{"key":"x2","value":{"kind":"literal","value":"16"}},{"key":"y1","value":{"kind":"literal","value":"14"}},{"key":"y2","value":{"kind":"literal","value":"18"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M16 10h.01"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M12 10h.01"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M8 10h.01"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M12 14h.01"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M8 14h.01"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M12 18h.01"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M8 18h.01"}}]}]}},{"key":"chevron-down","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"m6 9 6 6 6-6"}}]}]}},{"key":"chevron-left","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"m15 18-6-6 6-6"}}]}]}},{"key":"chevron-right","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"m9 18 6-6-6-6"}}]}]}},{"key":"circle-check","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"circle"}},{"key":"cx","value":{"kind":"literal","value":"12"}},{"key":"cy","value":{"kind":"literal","value":"12"}},{"key":"r","value":{"kind":"literal","value":"10"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"m9 12 2 2 4-4"}}]}]}},{"key":"circle-x","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"circle"}},{"key":"cx","value":{"kind":"literal","value":"12"}},{"key":"cy","value":{"kind":"literal","value":"12"}},{"key":"r","value":{"kind":"literal","value":"10"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"m15 9-6 6"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"m9 9 6 6"}}]}]}},{"key":"code-xml","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"m18 16 4-4-4-4"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"m6 8-4 4 4 4"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"m14.5 4-5 16"}}]}]}},{"key":"columns","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"rect"}},{"key":"width","value":{"kind":"literal","value":"18"}},{"key":"height","value":{"kind":"literal","value":"18"}},{"key":"x","value":{"kind":"literal","value":"3"}},{"key":"y","value":{"kind":"literal","value":"3"}},{"key":"rx","value":{"kind":"literal","value":"2"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M9 3v18"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M15 3v18"}}]}]}},{"key":"credit-card","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"rect"}},{"key":"width","value":{"kind":"literal","value":"20"}},{"key":"height","value":{"kind":"literal","value":"14"}},{"key":"x","value":{"kind":"literal","value":"2"}},{"key":"y","value":{"kind":"literal","value":"5"}},{"key":"rx","value":{"kind":"literal","value":"2"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"line"}},{"key":"x1","value":{"kind":"literal","value":"2"}},{"key":"x2","value":{"kind":"literal","value":"22"}},{"key":"y1","value":{"kind":"literal","value":"10"}},{"key":"y2","value":{"kind":"literal","value":"10"}}]}]}},{"key":"ellipsis","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"circle"}},{"key":"cx","value":{"kind":"literal","value":"12"}},{"key":"cy","value":{"kind":"literal","value":"12"}},{"key":"r","value":{"kind":"literal","value":"1"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"circle"}},{"key":"cx","value":{"kind":"literal","value":"19"}},{"key":"cy","value":{"kind":"literal","value":"12"}},{"key":"r","value":{"kind":"literal","value":"1"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"circle"}},{"key":"cx","value":{"kind":"literal","value":"5"}},{"key":"cy","value":{"kind":"literal","value":"12"}},{"key":"r","value":{"kind":"literal","value":"1"}}]}]}},{"key":"eraser","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M21 21H8a2 2 0 0 1-1.42-.587l-3.994-3.999a2 2 0 0 1 0-2.828l10-10a2 2 0 0 1 2.829 0l5.999 6a2 2 0 0 1 0 2.828L12.834 21"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"m5.082 11.09 8.828 8.828"}}]}]}},{"key":"file-text","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M14 2v5a1 1 0 0 0 1 1h5"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M10 9H8"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M16 13H8"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M16 17H8"}}]}]}},{"key":"folder","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"}}]}]}},{"key":"grip-horizontal","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"circle"}},{"key":"cx","value":{"kind":"literal","value":"12"}},{"key":"cy","value":{"kind":"literal","value":"9"}},{"key":"r","value":{"kind":"literal","value":"1"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"circle"}},{"key":"cx","value":{"kind":"literal","value":"19"}},{"key":"cy","value":{"kind":"literal","value":"9"}},{"key":"r","value":{"kind":"literal","value":"1"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"circle"}},{"key":"cx","value":{"kind":"literal","value":"5"}},{"key":"cy","value":{"kind":"literal","value":"9"}},{"key":"r","value":{"kind":"literal","value":"1"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"circle"}},{"key":"cx","value":{"kind":"literal","value":"12"}},{"key":"cy","value":{"kind":"literal","value":"15"}},{"key":"r","value":{"kind":"literal","value":"1"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"circle"}},{"key":"cx","value":{"kind":"literal","value":"19"}},{"key":"cy","value":{"kind":"literal","value":"15"}},{"key":"r","value":{"kind":"literal","value":"1"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"circle"}},{"key":"cx","value":{"kind":"literal","value":"5"}},{"key":"cy","value":{"kind":"literal","value":"15"}},{"key":"r","value":{"kind":"literal","value":"1"}}]}]}},{"key":"grip-vertical","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"circle"}},{"key":"cx","value":{"kind":"literal","value":"9"}},{"key":"cy","value":{"kind":"literal","value":"12"}},{"key":"r","value":{"kind":"literal","value":"1"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"circle"}},{"key":"cx","value":{"kind":"literal","value":"9"}},{"key":"cy","value":{"kind":"literal","value":"5"}},{"key":"r","value":{"kind":"literal","value":"1"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"circle"}},{"key":"cx","value":{"kind":"literal","value":"9"}},{"key":"cy","value":{"kind":"literal","value":"19"}},{"key":"r","value":{"kind":"literal","value":"1"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"circle"}},{"key":"cx","value":{"kind":"literal","value":"15"}},{"key":"cy","value":{"kind":"literal","value":"12"}},{"key":"r","value":{"kind":"literal","value":"1"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"circle"}},{"key":"cx","value":{"kind":"literal","value":"15"}},{"key":"cy","value":{"kind":"literal","value":"5"}},{"key":"r","value":{"kind":"literal","value":"1"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"circle"}},{"key":"cx","value":{"kind":"literal","value":"15"}},{"key":"cy","value":{"kind":"literal","value":"19"}},{"key":"r","value":{"kind":"literal","value":"1"}}]}]}},{"key":"heading-1","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M4 12h8"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M4 18V6"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M12 18V6"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"m17 12 3-2v8"}}]}]}},{"key":"heading-2","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M4 12h8"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M4 18V6"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M12 18V6"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M21 18h-4c0-4 4-3 4-6 0-1.5-2-2.5-4-1"}}]}]}},{"key":"heading-3","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M4 12h8"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M4 18V6"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M12 18V6"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M17.5 10.5c1.7-1 3.5 0 3.5 1.5a2 2 0 0 1-2 2"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M17 17.5c2 1.5 4 .3 4-1.5a2 2 0 0 0-2-2"}}]}]}},{"key":"help","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"circle"}},{"key":"cx","value":{"kind":"literal","value":"12"}},{"key":"cy","value":{"kind":"literal","value":"12"}},{"key":"r","value":{"kind":"literal","value":"10"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M12 17h.01"}}]}]}},{"key":"highlighter","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"m9 11-6 6v3h9l3-3"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"m22 12-4.6 4.6a2 2 0 0 1-2.8 0l-5.2-5.2a2 2 0 0 1 0-2.8L14 4"}}]}]}},{"key":"image","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"rect"}},{"key":"width","value":{"kind":"literal","value":"18"}},{"key":"height","value":{"kind":"literal","value":"18"}},{"key":"x","value":{"kind":"literal","value":"3"}},{"key":"y","value":{"kind":"literal","value":"3"}},{"key":"rx","value":{"kind":"literal","value":"2"}},{"key":"ry","value":{"kind":"literal","value":"2"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"circle"}},{"key":"cx","value":{"kind":"literal","value":"9"}},{"key":"cy","value":{"kind":"literal","value":"9"}},{"key":"r","value":{"kind":"literal","value":"2"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"}}]}]}},{"key":"info","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"circle"}},{"key":"cx","value":{"kind":"literal","value":"12"}},{"key":"cy","value":{"kind":"literal","value":"12"}},{"key":"r","value":{"kind":"literal","value":"10"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M12 16v-4"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M12 8h.01"}}]}]}},{"key":"italic","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"line"}},{"key":"x1","value":{"kind":"literal","value":"19"}},{"key":"x2","value":{"kind":"literal","value":"10"}},{"key":"y1","value":{"kind":"literal","value":"4"}},{"key":"y2","value":{"kind":"literal","value":"4"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"line"}},{"key":"x1","value":{"kind":"literal","value":"14"}},{"key":"x2","value":{"kind":"literal","value":"5"}},{"key":"y1","value":{"kind":"literal","value":"20"}},{"key":"y2","value":{"kind":"literal","value":"20"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"line"}},{"key":"x1","value":{"kind":"literal","value":"15"}},{"key":"x2","value":{"kind":"literal","value":"9"}},{"key":"y1","value":{"kind":"literal","value":"4"}},{"key":"y2","value":{"kind":"literal","value":"20"}}]}]}},{"key":"layout-dashboard","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"rect"}},{"key":"width","value":{"kind":"literal","value":"7"}},{"key":"height","value":{"kind":"literal","value":"9"}},{"key":"x","value":{"kind":"literal","value":"3"}},{"key":"y","value":{"kind":"literal","value":"3"}},{"key":"rx","value":{"kind":"literal","value":"1"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"rect"}},{"key":"width","value":{"kind":"literal","value":"7"}},{"key":"height","value":{"kind":"literal","value":"5"}},{"key":"x","value":{"kind":"literal","value":"14"}},{"key":"y","value":{"kind":"literal","value":"3"}},{"key":"rx","value":{"kind":"literal","value":"1"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"rect"}},{"key":"width","value":{"kind":"literal","value":"7"}},{"key":"height","value":{"kind":"literal","value":"9"}},{"key":"x","value":{"kind":"literal","value":"14"}},{"key":"y","value":{"kind":"literal","value":"12"}},{"key":"rx","value":{"kind":"literal","value":"1"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"rect"}},{"key":"width","value":{"kind":"literal","value":"7"}},{"key":"height","value":{"kind":"literal","value":"5"}},{"key":"x","value":{"kind":"literal","value":"3"}},{"key":"y","value":{"kind":"literal","value":"16"}},{"key":"rx","value":{"kind":"literal","value":"1"}}]}]}},{"key":"list","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M3 5h.01"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M3 12h.01"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M3 19h.01"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M8 5h13"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M8 12h13"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M8 19h13"}}]}]}},{"key":"list-ordered","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M11 5h10"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M11 12h10"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M11 19h10"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M4 4h1v5"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M4 9h2"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M6.5 20H3.4c0-1 2.6-1.925 2.6-3.5a1.5 1.5 0 0 0-2.6-1.02"}}]}]}},{"key":"list-todo","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M13 5h8"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M13 12h8"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M13 19h8"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"m3 17 2 2 4-4"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"rect"}},{"key":"x","value":{"kind":"literal","value":"3"}},{"key":"y","value":{"kind":"literal","value":"4"}},{"key":"width","value":{"kind":"literal","value":"6"}},{"key":"height","value":{"kind":"literal","value":"6"}},{"key":"rx","value":{"kind":"literal","value":"1"}}]}]}},{"key":"loader","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M21 12a9 9 0 1 1-6.219-8.56"}}]}]}},{"key":"merge","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"m8 6 4-4 4 4"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M12 2v10.3a4 4 0 0 1-1.172 2.872L4 22"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"m20 22-5-5"}}]}]}},{"key":"minus","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M5 12h14"}}]}]}},{"key":"notebook-pen","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M13.4 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-7.4"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M2 6h4"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M2 10h4"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M2 14h4"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M2 18h4"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M21.378 5.626a1 1 0 1 0-3.004-3.004l-5.01 5.012a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506z"}}]}]}},{"key":"paint-bucket","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"m19 11-8-8-8.6 8.6a2 2 0 0 0 0 2.8l5.2 5.2c.8.8 2 .8 2.8 0L19 11Z"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"m5 2 5 5"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M2 13h15"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M22 20a2 2 0 1 1-4 0c0-1.6 1.7-2.4 2-4 .3 1.6 2 2.4 2 4Z"}}]}]}},{"key":"panel-bottom","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"rect"}},{"key":"width","value":{"kind":"literal","value":"18"}},{"key":"height","value":{"kind":"literal","value":"18"}},{"key":"x","value":{"kind":"literal","value":"3"}},{"key":"y","value":{"kind":"literal","value":"3"}},{"key":"rx","value":{"kind":"literal","value":"2"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M3 15h18"}}]}]}},{"key":"panel-left","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"rect"}},{"key":"width","value":{"kind":"literal","value":"18"}},{"key":"height","value":{"kind":"literal","value":"18"}},{"key":"x","value":{"kind":"literal","value":"3"}},{"key":"y","value":{"kind":"literal","value":"3"}},{"key":"rx","value":{"kind":"literal","value":"2"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M9 3v18"}}]}]}},{"key":"panel-right","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"rect"}},{"key":"width","value":{"kind":"literal","value":"18"}},{"key":"height","value":{"kind":"literal","value":"18"}},{"key":"x","value":{"kind":"literal","value":"3"}},{"key":"y","value":{"kind":"literal","value":"3"}},{"key":"rx","value":{"kind":"literal","value":"2"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M15 3v18"}}]}]}},{"key":"panel-top","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"rect"}},{"key":"width","value":{"kind":"literal","value":"18"}},{"key":"height","value":{"kind":"literal","value":"18"}},{"key":"x","value":{"kind":"literal","value":"3"}},{"key":"y","value":{"kind":"literal","value":"3"}},{"key":"rx","value":{"kind":"literal","value":"2"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M3 9h18"}}]}]}},{"key":"pilcrow","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M13 4v16"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M17 4v16"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M19 4H9.5a4.5 4.5 0 0 0 0 9H13"}}]}]}},{"key":"plus","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M5 12h14"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M12 5v14"}}]}]}},{"key":"quote","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M16 3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2 1 1 0 0 1 1 1v1a2 2 0 0 1-2 2 1 1 0 0 0-1 1v2a1 1 0 0 0 1 1 6 6 0 0 0 6-6V5a2 2 0 0 0-2-2z"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M5 3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2 1 1 0 0 1 1 1v1a2 2 0 0 1-2 2 1 1 0 0 0-1 1v2a1 1 0 0 0 1 1 6 6 0 0 0 6-6V5a2 2 0 0 0-2-2z"}}]}]}},{"key":"receipt","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1Z"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M12 17.5v-11"}}]}]}},{"key":"redo","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"m15 14 5-5-5-5"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M20 9H9.5A5.5 5.5 0 0 0 4 14.5A5.5 5.5 0 0 0 9.5 20H13"}}]}]}},{"key":"rows","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"rect"}},{"key":"width","value":{"kind":"literal","value":"18"}},{"key":"height","value":{"kind":"literal","value":"18"}},{"key":"x","value":{"kind":"literal","value":"3"}},{"key":"y","value":{"kind":"literal","value":"3"}},{"key":"rx","value":{"kind":"literal","value":"2"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M21 9H3"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M21 15H3"}}]}]}},{"key":"settings","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"circle"}},{"key":"cx","value":{"kind":"literal","value":"12"}},{"key":"cy","value":{"kind":"literal","value":"12"}},{"key":"r","value":{"kind":"literal","value":"3"}}]}]}},{"key":"split","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M16 3h5v5"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M8 3H3v5"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M12 22v-8.3a4 4 0 0 0-1.172-2.872L3 3"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"m15 9 6-6"}}]}]}},{"key":"strikethrough","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M16 4H9a3 3 0 0 0-2.83 4"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M14 12a4 4 0 0 1 0 8H6"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"line"}},{"key":"x1","value":{"kind":"literal","value":"4"}},{"key":"x2","value":{"kind":"literal","value":"20"}},{"key":"y1","value":{"kind":"literal","value":"12"}},{"key":"y2","value":{"kind":"literal","value":"12"}}]}]}},{"key":"table","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M9 3H5a2 2 0 0 0-2 2v4m6-6h10a2 2 0 0 1 2 2v4M9 3v18m0 0h10a2 2 0 0 0 2-2V9M9 21H5a2 2 0 0 1-2-2V9m0 0h18"}}]}]}},{"key":"trash","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M10 11v6"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M14 11v6"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M3 6h18"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"}}]}]}},{"key":"triangle-alert","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M12 9v4"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M12 17h.01"}}]}]}},{"key":"truck","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M14 18V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v11a1 1 0 0 0 1 1h2"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M15 18H9"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M19 18h2a1 1 0 0 0 1-1v-3.65a1 1 0 0 0-.22-.624l-3.48-4.35A1 1 0 0 0 17.52 8H14"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"circle"}},{"key":"cx","value":{"kind":"literal","value":"17"}},{"key":"cy","value":{"kind":"literal","value":"18"}},{"key":"r","value":{"kind":"literal","value":"2"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"circle"}},{"key":"cx","value":{"kind":"literal","value":"7"}},{"key":"cy","value":{"kind":"literal","value":"18"}},{"key":"r","value":{"kind":"literal","value":"2"}}]}]}},{"key":"underline","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M6 4v6a6 6 0 0 0 12 0V4"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"line"}},{"key":"x1","value":{"kind":"literal","value":"4"}},{"key":"x2","value":{"kind":"literal","value":"20"}},{"key":"y1","value":{"kind":"literal","value":"20"}},{"key":"y2","value":{"kind":"literal","value":"20"}}]}]}},{"key":"undo","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M9 14 4 9l5-5"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5a5.5 5.5 0 0 1-5.5 5.5H11"}}]}]}},{"key":"users","value":{"kind":"array","items":[{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M16 3.128a4 4 0 0 1 0 7.744"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"path"}},{"key":"d","value":{"kind":"literal","value":"M22 21v-2a4 4 0 0 0-3-3.87"}}]},{"kind":"object","pairs":[{"key":"tag","value":{"kind":"literal","value":"circle"}},{"key":"cx","value":{"kind":"literal","value":"9"}},{"key":"cy","value":{"kind":"literal","value":"7"}},{"key":"r","value":{"kind":"literal","value":"4"}}]}]}}]},"index":{"kind":"id","name":"name"}},"dependencies":["name"]}}],"slots":[],"root":{"kind":"native","element":"span","choices":["span"]}},{"source":{"file":"./components/ui-input-group/ui-input-group.html"},"contract":{"version":1,"name":"UiInputGroup","tag":"ui-input-group","nativeElement":"div","props":{"disabled":{"type":"boolean","required":false,"target":{"attribute":"disabled"},"description":"Fades the group's framing to match a disabled input inside it. Disable the input itself too.","default":false}}},"template":{"kind":"element","name":"div","attributes":[],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"affix"}],"children":[{"kind":"slot","fallback":[],"name":"prefix"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"field"}],"children":[{"kind":"slot"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"affix"}],"children":[{"kind":"slot","fallback":[],"name":"suffix"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"action"}],"children":[{"kind":"slot","fallback":[],"name":"action"}]}]},"css":"/* An input with fixed text before or after it, such as a domain after a site's name\n (\"acme\" + \".example.com\") or slashes around a path. The group draws the field's border and\n focus ring around the input and its affixes together; the input inside drops its own through\n its custom properties, so it is still the one ui-input, with its form behaviour intact. The\n affixes are plain text beside the input, so name the input with a label that says what the\n whole value is. The action slot takes one button at the end, inside the border, for the one\n thing the field is for (\"Continue\" after a site's address), so it reads as the field's action\n and not the form's. */\n :host {\n /* The group's own border and height stand for the input's, so the group is a lone Input's height.\n Hooks do not inherit, so these are defaults for the input; its own hooks still win. */\n --_ui-default-input-border-width: 0;\n --_ui-default-input-min-block-size: 0;\n --_ui-default-input-border: transparent;\n --_ui-default-input-border-hover: transparent;\n --_ui-default-input-focus-border: transparent;\n --_ui-default-input-invalid-border: transparent;\n --_ui-default-input-invalid-focus-shadow: none;\n --_ui-default-input-shadow: none;\n --_ui-default-input-focus-shadow: none;\n --_ui-default-input-focus-outline: none;\n --_ui-default-input-radius: 0;\n --_ui-default-input-surface: transparent;\n\n display: flex;\n align-items: stretch;\n box-sizing: border-box;\n inline-size: 100%;\n min-inline-size: 0;\n min-block-size: var(--ui-control-size-md);\n /* The frame reads the shared control tokens with a lone Input's fallbacks, so the two match. */\n border: 1px solid var(--ui-control-border, var(--ui-border-strong));\n border-radius: var(--ui-radius-md);\n background: var(--ui-control-surface, var(--ui-surface-elevated));\n box-shadow: var(--ui-control-inset);\n overflow: hidden;\n /* A press anywhere in the frame focuses the input. */\n cursor: text;\n transition: border-color var(--ui-motion-fast) var(--ui-motion-ease), box-shadow var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n :host:hover:not(:has(input:focus, input:disabled)) {\n border-color: var(--ui-control-border-hover, var(--ui-text-secondary));\n }\n\n /* The ring shows when the field's input would show its own: when it is focus-visible, which a\n text input is for a pointer as well as a keyboard. A focused action button draws its own. */\n :host:has(.field input:focus-visible) {\n border-color: var(--ui-control-focus, var(--ui-accent-solid));\n box-shadow:\n var(--ui-control-inset),\n var(--ui-control-focus-halo-shadow);\n }\n\n :host:has([aria-invalid=\"true\"], :user-invalid) {\n border-color: var(--ui-danger-solid);\n }\n\n :host:has(input:is([aria-invalid=\"true\"], :user-invalid):focus-visible) {\n box-shadow:\n var(--ui-control-inset),\n 0 0 0 3px color-mix(in srgb, var(--ui-danger-solid) 22%, transparent);\n }\n\n /* Forced colors drop box shadows, so the focus ring becomes an outline. */\n @media (forced-colors: active) {\n :host:has(input:focus-visible) {\n outline: 2px solid Highlight;\n outline-offset: 1px;\n }\n }\n\n :host-state([disabled]),\n :host:has(input:disabled) {\n background: var(--ui-control-surface-disabled, var(--ui-surface-muted));\n box-shadow: none;\n cursor: not-allowed;\n }\n\n .field {\n display: flex;\n flex: 1;\n min-inline-size: 0;\n }\n\n .affix {\n display: inline-flex;\n flex: none;\n align-items: center;\n padding-inline: var(--ui-space-2);\n color: var(--ui-text-secondary);\n font-family: var(--ui-font-family-mono);\n font-size: var(--ui-font-size-sm);\n white-space: nowrap;\n }\n\n /* Centred rather than padded above and below: the group is exactly a lone Input's height, so a\n small button sits inside it with the difference split evenly, and the field keeps its height. */\n .action {\n display: flex;\n flex: none;\n align-items: center;\n padding-inline: var(--ui-space-1);\n }\n\n .affix:empty,\n .action:empty {\n display: none;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true,"name":"prefix"},{"dynamic":false,"required":true},{"dynamic":false,"required":true,"name":"suffix"},{"dynamic":false,"required":true,"name":"action"}],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-input-group/ui-input-group.js"},{"source":{"file":"./components/ui-input/ui-input.html"},"contract":{"version":1,"name":"UiInput","tag":"ui-input","nativeElement":"input","props":{"disabled":{"type":"boolean","required":false,"target":{"attribute":"disabled"},"description":"Prevents editing and form submission.","default":false},"invalid":{"type":"boolean","required":false,"target":{"attribute":"aria-invalid"},"description":"Exposes invalid state to assistive technology and styling.","default":false},"readonly":{"type":"boolean","required":false,"target":{"attribute":"readonly"},"description":"Allows selection without allowing edits.","default":false},"required":{"type":"boolean","required":false,"target":{"attribute":"required"},"description":"Marks the control as required for form validation.","default":false},"value":{"type":"string","required":false,"target":{"attribute":"value"},"description":"The input's text. Setting or changing it replaces the live text; between changes the user's typing stands, so follow input events to keep it in step. It is\n also the input's default, so a form reset returns to it."}}},"template":{"kind":"element","name":"input","attributes":[{"kind":"attribute","name":"value","expression":"value","expressionPlan":{"source":"value","ast":{"kind":"id","name":"value"},"dependencies":["value"]}},{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}},{"kind":"attribute","name":"readonly","expression":"readonly","expressionPlan":{"source":"readonly","ast":{"kind":"id","name":"readonly"},"dependencies":["readonly"]}},{"kind":"attribute","name":"required","expression":"required","expressionPlan":{"source":"required","ast":{"kind":"id","name":"required"},"dependencies":["required"]}},{"kind":"attribute","name":"aria-invalid","expression":"invalid","expressionPlan":{"source":"invalid","ast":{"kind":"id","name":"invalid"},"dependencies":["invalid"]}}],"children":[]},"css":"/* This component's hooks style the element they are set on, and never a nested one. An Input\n Group sets --_ui-default-input-* for the input inside it, below the input's own hooks. */\n @property --ui-input-border {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-input-border-hover {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-input-border-width {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-input-focus-border {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-input-focus-outline {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-input-focus-shadow {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-input-invalid-border {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-input-invalid-focus-shadow {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-input-min-block-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-input-radius {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-input-shadow {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-input-surface {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n box-sizing: border-box;\n display: inline-block;\n inline-size: 100%;\n min-inline-size: 0;\n min-block-size: var(--ui-input-min-block-size, var(--_ui-default-input-min-block-size, var(--ui-control-size-md)));\n margin: 0;\n padding: var(--ui-space-2) var(--ui-space-3);\n appearance: none;\n border: var(--ui-input-border-width, var(--_ui-default-input-border-width, 1px)) solid\n var(--ui-input-border, var(--_ui-default-input-border, var(--ui-control-border, var(--ui-border-strong))));\n border-radius: var(--ui-input-radius, var(--_ui-default-input-radius, var(--ui-radius-md)));\n background: var(--ui-input-surface, var(--_ui-default-input-surface, var(--ui-control-surface, var(--ui-surface-elevated))));\n color: var(--ui-text-primary);\n font: inherit;\n line-height: var(--ui-line-height-md);\n box-shadow: var(--ui-input-shadow, var(--_ui-default-input-shadow, var(--ui-control-inset)));\n transition:\n border-color var(--ui-motion-fast) var(--ui-motion-ease),\n box-shadow var(--ui-motion-fast) var(--ui-motion-ease),\n background-color var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n /* Tabbing into a field selects its text; tint that selection softly instead of the page highlight. */\n :host::selection {\n background: color-mix(in srgb, var(--ui-accent-solid) 20%, transparent);\n color: inherit;\n }\n\n :host::placeholder {\n color: var(--ui-control-placeholder, var(--ui-text-secondary));\n opacity: 1;\n }\n\n :host:hover:not(:focus):not(:disabled) {\n border-color: var(--ui-input-border-hover, var(--_ui-default-input-border-hover, var(--ui-control-border-hover, var(--ui-text-secondary))));\n }\n\n :host:focus-visible {\n border-color: var(--ui-input-focus-border, var(--_ui-default-input-focus-border, var(--ui-control-focus, var(--ui-accent-solid))));\n outline: none;\n box-shadow: var(--ui-input-focus-shadow, var(--_ui-default-input-focus-shadow, var(--ui-control-inset), var(--ui-control-focus-halo-shadow)));\n }\n\n /* The app's invalid flag, or the browser's own verdict once the user has left an invalid field. */\n :host[aria-invalid=\"true\"],\n :host:user-invalid {\n border-color: var(--ui-input-invalid-border, var(--_ui-default-input-invalid-border, var(--ui-danger-solid)));\n }\n\n :host:is([aria-invalid=\"true\"], :user-invalid):focus-visible {\n box-shadow: var(\n --ui-input-invalid-focus-shadow,\n var(\n --_ui-default-input-invalid-focus-shadow,\n var(--ui-control-inset),\n 0 0 0 3px color-mix(in srgb, var(--ui-danger-solid) 22%, transparent)\n )\n );\n }\n\n :host:disabled {\n background: var(--ui-control-surface-disabled, var(--ui-surface-muted));\n color: var(--ui-disabled-text);\n box-shadow: none;\n cursor: not-allowed;\n }\n\n /* Forced colors drop box shadows, so the focus ring becomes an outline. */\n @media (forced-colors: active) {\n :host:focus-visible {\n outline: var(--ui-input-focus-outline, var(--_ui-default-input-focus-outline, 2px solid Highlight));\n outline-offset: 1px;\n }\n }\n\n /* No text-box-trim here: trimming a native input's line box below its line height lets the text\n * scroll vertically inside the field. Native inputs already center their single line. */\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[],"root":{"kind":"native","element":"input","choices":["input"]},"controller":"./components/ui-input/ui-input.js"},{"source":{"file":"./components/ui-list-item/ui-list-item.html"},"contract":{"version":1,"name":"UiListItem","tag":"ui-list-item","nativeElement":"li","props":{"current":{"type":"boolean","required":false,"target":{"attribute":"aria-current"},"description":"Marks the item as the current one, such as the site you are in: it takes the selected surface and aria-current=\"true\", which assistive technology\n announces. Set it on one item at a time.","default":false},"variant":{"type":{"enum":["row","card"]},"required":false,"target":{"attribute":"variant"},"description":"How the item is drawn. A row is flat and takes a hover surface when it is a link, for items read down a list. A card sits on a raised, bordered surface,\n for items set in a grid (a List with layout=\"grid\"). Both have the same parts: leading, title, description, and trailing.","default":"row"}}},"template":{"kind":"element","name":"li","attributes":[{"kind":"attribute","name":"aria-current","expression":"current","expressionPlan":{"source":"current","ast":{"kind":"id","name":"current"},"dependencies":["current"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"leading"}],"children":[{"kind":"slot","fallback":[],"name":"leading"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"content"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"title"}],"children":[{"kind":"slot"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"description"}],"children":[{"kind":"slot","fallback":[],"name":"description"}]}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"trailing"}],"children":[{"kind":"slot","fallback":[],"name":"trailing"}]}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-list-item-gap {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-list-item-icon-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-list-item-padding-block {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-list-item-padding-inline {\n syntax: \"*\";\n inherits: false;\n }\n\n /* One entry in a list: something to recognise (leading, usually an icon), its name (the default\n slot), one line about it (description), and what it offers (trailing, such as a button or a\n badge). The title and description are one line each and end in an ellipsis, so every item in a\n list has the same height.\n\n A link in the title is the whole item: its hit area stretches over the item, so the icon and the\n padding follow it too, and the item takes the link's focus ring. The link stays a real link, so\n a router, a modified click, and \"open in new tab\" all work. Trailing controls sit above it and\n stay their own. */\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-list-item-icon-size: var(--ui-list-item-icon-size);\n\n position: relative;\n box-sizing: border-box;\n display: flex;\n align-items: center;\n gap: var(--ui-list-item-gap, var(--ui-space-3));\n min-inline-size: 0;\n min-block-size: var(--_ui-list-item-min-size, var(--ui-control-size, 2.5rem));\n padding-block: var(--ui-list-item-padding-block, var(--_ui-list-item-padding-block, var(--ui-space-2)));\n padding-inline: var(--ui-list-item-padding-inline, var(--_ui-list-item-padding-inline, var(--ui-space-3)));\n border-radius: var(--ui-radius-md);\n color: var(--ui-text-primary);\n transition: background-color var(--ui-motion-fast) var(--ui-motion-ease), border-color var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n :host-state([variant=\"card\"]) {\n padding-block: var(--ui-list-item-padding-block, var(--ui-space-3));\n padding-inline: var(--ui-list-item-padding-inline, var(--ui-space-4));\n border: 1px solid var(--ui-border-default);\n border-radius: var(--ui-radius-lg);\n background: var(--ui-surface-raised);\n }\n\n :host:has(.title a[href]:hover) {\n background: var(--ui-surface-hover);\n }\n\n :host-state([variant=\"card\"]):has(.title a[href]:hover) {\n border-color: var(--ui-border-strong);\n }\n\n :host-state([current]) {\n background: var(--ui-surface-hover);\n }\n\n :host:has(.title a[href]:focus-visible) {\n box-shadow: 0 0 0 2px var(--ui-focus-ring);\n }\n\n .leading,\n .trailing {\n display: inline-flex;\n flex: none;\n align-items: center;\n gap: var(--ui-space-2);\n }\n\n .leading {\n color: var(--ui-text-muted);\n font-size: var(--_ui-list-item-icon-size, var(--ui-font-size-lg));\n }\n\n /* Trailing controls take their own clicks, above the title link's stretched hit area. */\n .trailing {\n position: relative;\n z-index: 1;\n color: var(--ui-text-muted);\n font-size: var(--ui-font-size-sm);\n }\n\n .content {\n display: flex;\n flex: 1;\n flex-direction: column;\n gap: var(--ui-space-0-5, 2px);\n min-inline-size: 0;\n }\n\n .title,\n .description {\n display: block;\n min-inline-size: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .title {\n font-size: var(--ui-font-size-md);\n font-weight: var(--_ui-list-item-title-weight, var(--ui-font-medium));\n line-height: var(--ui-line-height-tight);\n }\n\n .description {\n color: var(--ui-text-muted);\n font-size: var(--ui-font-size-sm);\n line-height: var(--ui-line-height-tight);\n }\n\n .title > :slotted(a) {\n color: inherit;\n text-decoration: none;\n }\n\n .title > :slotted(a:focus-visible) {\n outline: none;\n box-shadow: none;\n }\n\n .title > :slotted(a[href])::after {\n position: absolute;\n inset: 0;\n border-radius: inherit;\n content: \"\";\n }\n\n /* An unused region takes no space. */\n .leading:empty,\n .description:empty,\n .trailing:empty {\n display: none;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true,"name":"leading"},{"dynamic":false,"required":true},{"dynamic":false,"required":true,"name":"description"},{"dynamic":false,"required":true,"name":"trailing"}],"root":{"kind":"native","element":"li","choices":["li"]}},{"source":{"file":"./components/ui-list/ui-list.html"},"contract":{"version":1,"name":"UiList","tag":"ui-list","nativeElement":"ul","props":{"density":{"type":{"enum":["comfortable","compact"]},"required":false,"target":{"attribute":"density"},"description":"How much room each item takes. comfortable is a full row, easy to point at, for lists of things to open; compact sets items close together with no row\n padding, for a short list of facts inside other content, such as the features a plan includes.","default":"comfortable"},"layout":{"type":{"enum":["rows","grid"]},"required":false,"target":{"attribute":"layout"},"description":"How the items are laid out. Rows stack the items one per line, for a list read top to bottom. Grid sets them in as many columns as fit, each at least\n --ui-list-min-item-width (14rem) wide, for card items such as pinned or featured entries.","default":"rows"}}},"template":{"kind":"element","name":"ul","attributes":[{"kind":"literal","name":"role","value":"list"}],"children":[{"kind":"slot"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-list-gap {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-list-min-item-width {\n syntax: \"*\";\n inherits: false;\n }\n\n /* A list of items (ui-list-item). It owns the spacing between them, so a view never sets it. The\n explicit list role keeps the list announced as one: some browsers drop it from a list with no\n markers. */\n :host {\n display: flex;\n flex-direction: column;\n gap: var(--ui-list-gap, var(--ui-space-1));\n min-inline-size: 0;\n margin: 0;\n padding: 0;\n list-style: none;\n }\n\n /* Compact passes its size to the items through private properties, which cross into each item. */\n :host-state([density=\"compact\"]) {\n --_ui-list-item-min-size: 0;\n --_ui-list-item-padding-block: 0;\n --_ui-list-item-padding-inline: 0;\n --_ui-list-item-title-weight: var(--ui-font-normal);\n gap: var(--ui-list-gap, var(--ui-space-2));\n }\n\n :host-state([layout=\"grid\"]) {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(min(100%, var(--ui-list-min-item-width, 14rem)), 1fr));\n gap: var(--ui-list-gap, var(--ui-space-3));\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"ul","choices":["ul"]}},{"source":{"file":"./components/ui-menu-item/ui-menu-item.html"},"contract":{"version":1,"name":"UiMenuItem","tag":"ui-menu-item","nativeElement":"div","props":{"disabled":{"type":"boolean","required":false,"target":{"attribute":"aria-disabled"},"description":"Makes the item unavailable: it is faded, skipped by the arrow keys, and choosing it does nothing. It stays visible and is announced as disabled.","default":false},"value":{"type":"string","required":false,"target":{"attribute":"data-value"},"description":"The value the enclosing menu reports in its select event when this item is chosen. Give each item a distinct value so one handler can tell them\n apart.","default":""}}},"template":{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"role","value":"menuitem"},{"kind":"literal","name":"tabindex","value":"-1"},{"kind":"attribute","name":"aria-disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}},{"kind":"attribute","name":"data-value","expression":"value","expressionPlan":{"source":"value","ast":{"kind":"id","name":"value"},"dependencies":["value"]}}],"children":[{"kind":"slot"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-menu-item-font-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-menu-item-hover-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-menu-item-min-block-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-menu-item-padding-block {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-menu-item-padding-inline {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-menu-item-radius {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n display: block;\n box-sizing: border-box;\n width: 100%;\n padding: var(--ui-menu-item-padding-block, var(--_ui-default-menu-item-padding-block, var(--ui-space-2)))\n var(--ui-menu-item-padding-inline, var(--_ui-default-menu-item-padding-inline, var(--ui-space-3)));\n text-align: left;\n border-radius: var(--ui-menu-item-radius, var(--_ui-default-menu-item-radius, var(--ui-radius-md)));\n color: var(--ui-text-primary);\n font-size: var(--ui-menu-item-font-size, var(--_ui-default-menu-item-font-size, var(--ui-font-size-md)));\n font-weight: var(--ui-font-medium);\n cursor: pointer;\n outline: none;\n transition: background-color var(--ui-motion-fast) var(--ui-motion-ease), color var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n /* Centre the glyphs, not the line box: a label without descenders otherwise reads high. */\n /* Centre the glyphs, not the line box: a label without descenders otherwise reads high.\n * Trimming applies to block containers, so the box is a block with centred content. */\n @supports (text-box-trim: trim-both) {\n :host {\n display: block;\n min-block-size: var(--ui-menu-item-min-block-size, var(--ui-control-size-md, 2.5rem));\n align-content: center;\n text-box-trim: trim-both;\n text-box-edge: cap alphabetic;\n }\n }\n\n :host:is(:hover, :focus-visible):not([aria-disabled=\"true\"]) {\n background: var(--ui-menu-item-hover-surface, var(--ui-surface-subtle));\n }\n\n :host[aria-disabled=\"true\"] {\n opacity: 0.6;\n cursor: not-allowed;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]}},{"source":{"file":"./components/ui-menu/ui-menu.html"},"contract":{"version":1,"name":"UiMenu","tag":"ui-menu","nativeElement":"div","props":{"density":{"type":{"enum":["comfortable","compact"]},"required":false,"target":{"attribute":"density"},"description":"Compact trades padding and type size for rows that fit more on screen.","default":"comfortable"},"for":{"type":"string","required":false,"target":{"attribute":"for"},"description":"ID of the control that toggles and anchors the menu.","default":""},"open":{"type":"boolean","required":false,"target":{"attribute":"open"},"description":"Whether the menu is open initially or when set externally.","default":false},"placement":{"type":"string","required":false,"target":{"attribute":"placement"},"description":"Positions an associated menu relative to its trigger.","default":"bottom-start"}}},"template":{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"role","value":"menu"},{"kind":"literal","name":"aria-orientation","value":"vertical"}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"surface"}],"children":[{"kind":"slot"}]}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-menu-viewport-gap {\n syntax: \"*\";\n inherits: false;\n }\n\n /* Compact sets its items' defaults, so nothing has to rescale a global; an item's own hooks\n still win. */\n :host-state([density=\"compact\"]) {\n --_ui-default-menu-item-padding-block: var(--ui-space-1);\n --_ui-default-menu-item-padding-inline: var(--ui-space-2);\n --_ui-default-menu-item-font-size: var(--ui-font-size-sm);\n --_ui-default-menu-item-radius: var(--ui-radius-sm);\n padding: var(--ui-space-1);\n gap: 0;\n }\n\n :host {\n /* A menu nested in a compact one starts again from its own density. */\n --_ui-default-menu-item-padding-block: initial;\n --_ui-default-menu-item-padding-inline: initial;\n --_ui-default-menu-item-font-size: initial;\n --_ui-default-menu-item-radius: initial;\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n inline-size: max-content;\n min-inline-size: min(12rem, calc(100vw - var(--ui-menu-viewport-gap, var(--ui-space-2)) * 2));\n max-inline-size: calc(100vw - var(--ui-menu-viewport-gap, var(--ui-space-2)) * 2);\n padding: 0;\n border: 0;\n outline: 0;\n border-radius: 0;\n background: transparent;\n box-shadow: none;\n overflow: visible;\n }\n\n .surface {\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n max-inline-size: inherit;\n padding: var(--ui-space-1);\n background: var(--ui-surface-elevated);\n border: 1px solid var(--ui-border-default);\n border-radius: var(--ui-radius-lg);\n box-shadow: var(--ui-elevation-overlay, var(--ui-shadow-lg));\n max-block-size: inherit;\n overflow: auto;\n }\n\n :host:not(:host-state([internalOpen])) {\n display: none;\n }\n\n :host[popover] {\n position: fixed;\n inset: auto;\n margin: 0;\n overflow: visible;\n max-block-size: calc(100dvh - var(--ui-menu-viewport-gap, var(--ui-space-2)) * 2);\n opacity: 0;\n transform: translateY(-4px) scale(0.99);\n transition:\n opacity var(--ui-motion-fast) var(--ui-motion-ease),\n transform var(--ui-motion-fast) var(--ui-motion-ease),\n display var(--ui-motion-fast) allow-discrete,\n overlay var(--ui-motion-fast) allow-discrete;\n }\n\n :host[popover]:popover-open {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n\n @starting-style {\n :host[popover]:popover-open {\n opacity: 0;\n transform: translateY(-4px) scale(0.99);\n }\n }\n\n :host[hidden] {\n display: none;\n }\n\n @media (prefers-reduced-motion: reduce) {\n :host[popover] {\n transition: none;\n }\n }","declarations":[{"kind":"state","name":"internalOpen","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"event","name":"select","type":"object({ value: string, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"open","type":"object({ open: boolean, reason: action | programmatic, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"close","type":"object({ open: boolean, reason: action | programmatic | light-dismiss | escape, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false}],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-menu/ui-menu.js"},{"source":{"file":"./components/ui-nav-item/ui-nav-item.html"},"contract":{"version":1,"name":"UiNavItem","tag":"ui-nav-item","nativeElement":"button","props":{"as":{"type":{"enum":["button","a"]},"required":false,"target":{"attribute":"as"},"description":"The native element the item renders: a button, or a link (a) that navigates to href.","default":"button"},"current":{"type":{"kind":"union","members":[{"kind":"terminal","name":"boolean"},{"kind":"keyword","value":"page"},{"kind":"keyword","value":"step"},{"kind":"keyword","value":"location"}]},"required":false,"target":{"attribute":"current"},"description":"Marks the item as where you are: it takes the selected surface, a stronger label, and a bar on its start edge, and states aria-current, which assistive\n technology announces. true means the current page (aria-current=\"page\"); step marks the current step of a process, and location the current place in a\n set, such as a section of a record. Set it on one item at a time.","default":false},"href":{"type":"string","required":false,"target":{"attribute":"href"},"description":"The link's destination. Pair it with as=\"a\" so the item renders as a real link: a router, a modified click, and \"open in new tab\" all work. Without it the\n item is a button, for switching views inside the app."},"rel":{"type":"string","required":false,"target":{"attribute":"rel"},"description":"The link's relationship to its destination, as on a native link. Only meaningful with as=\"a\"."},"target":{"type":"string","required":false,"target":{"attribute":"target"},"description":"Where a link opens, as on a native link. Only meaningful with as=\"a\"."}}},"template":{"kind":"element","name":"template","attributes":[],"children":[{"kind":"element","name":"a","attributes":[{"kind":"attribute","name":"href","expression":"href","expressionPlan":{"source":"href","ast":{"kind":"id","name":"href"},"dependencies":["href"]}},{"kind":"attribute","name":"target","expression":"target","expressionPlan":{"source":"target","ast":{"kind":"id","name":"target"},"dependencies":["target"]}},{"kind":"attribute","name":"rel","expression":"rel","expressionPlan":{"source":"rel","ast":{"kind":"id","name":"rel"},"dependencies":["rel"]}},{"kind":"attribute","name":"aria-current","expression":"{ true: 'page', false: null, page: 'page', step: 'step', location: 'location' }[format('%s', current)]","expressionPlan":{"source":"{ true: 'page', false: null, page: 'page', step: 'step', location: 'location' }[format('%s', current)]","ast":{"kind":"index","object":{"kind":"object","pairs":[{"key":"true","value":{"kind":"literal","value":"page"}},{"key":"false","value":{"kind":"literal","value":null}},{"key":"page","value":{"kind":"literal","value":"page"}},{"key":"step","value":{"kind":"literal","value":"step"}},{"key":"location","value":{"kind":"literal","value":"location"}}]},"index":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s"},{"kind":"id","name":"current"}]}},"dependencies":["current"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"indicator"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"leading"}],"children":[{"kind":"slot","fallback":[],"name":"leading"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"content"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"label"}],"children":[{"kind":"slot"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"description"}],"children":[{"kind":"slot","fallback":[],"name":"description"}]}]}],"flow":{"kind":"when","test":"as = 'a'","testPlan":{"source":"as = 'a'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"a"}},"dependencies":["as"]}}},{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"attribute","name":"aria-current","expression":"{ true: 'page', false: null, page: 'page', step: 'step', location: 'location' }[format('%s', current)]","expressionPlan":{"source":"{ true: 'page', false: null, page: 'page', step: 'step', location: 'location' }[format('%s', current)]","ast":{"kind":"index","object":{"kind":"object","pairs":[{"key":"true","value":{"kind":"literal","value":"page"}},{"key":"false","value":{"kind":"literal","value":null}},{"key":"page","value":{"kind":"literal","value":"page"}},{"key":"step","value":{"kind":"literal","value":"step"}},{"key":"location","value":{"kind":"literal","value":"location"}}]},"index":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s"},{"kind":"id","name":"current"}]}},"dependencies":["current"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"indicator"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"leading"}],"children":[{"kind":"slot","fallback":[],"name":"leading"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"content"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"label"}],"children":[{"kind":"slot"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"description"}],"children":[{"kind":"slot","fallback":[],"name":"description"}]}]}],"flow":{"kind":"else"}}],"flow":{"kind":"match"}},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-nav-item-current-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-nav-item-indicator-color {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-nav-item-indicator-width {\n syntax: \"*\";\n inherits: false;\n }\n\n /* One destination in a side or rail navigation: an icon to find it by (leading), its name (the\n default slot), and an optional line under it (description), such as the record a section\n belongs to. Label and description are one line each and end in an ellipsis, so every item in a\n navigation has the same height and the rail never grows sideways. */\n :host {\n --_indicator-width: var(--ui-nav-item-indicator-width, 3px);\n --_indicator-color: var(--ui-nav-item-indicator-color, var(--ui-accent));\n position: relative;\n box-sizing: border-box;\n display: flex;\n align-items: center;\n gap: var(--ui-space-3);\n inline-size: 100%;\n min-inline-size: 0;\n min-block-size: var(--ui-control-size, 2.5rem);\n margin: 0;\n padding-block: var(--ui-space-2);\n padding-inline: var(--ui-space-3);\n border: 0;\n border-radius: var(--ui-radius-md);\n background: transparent;\n color: var(--ui-text-secondary);\n font: inherit;\n font-weight: var(--ui-font-medium);\n text-align: start;\n text-decoration: none;\n cursor: pointer;\n appearance: none;\n transition: background-color var(--ui-motion-fast) var(--ui-motion-ease), color var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n :host:hover:not([aria-current]) {\n background: var(--ui-surface-hover);\n color: var(--ui-text-primary);\n }\n\n /* The ring is an outline, drawn inside the item: forced colors keep an outline where they drop a\n box shadow, and a scrolling rail cannot clip a ring that stays within the item. */\n :host:focus-visible {\n outline: 2px solid var(--ui-focus-ring);\n outline-offset: -2px;\n }\n\n :host[aria-current] {\n background: var(--ui-nav-item-current-surface, var(--ui-accent-soft));\n color: var(--ui-accent-subtle-text, var(--ui-text-primary));\n font-weight: var(--ui-font-semibold);\n }\n\n /* The bar on the start edge is a border, not a fill: forced colors replace backgrounds but keep a\n border, so the current item stays marked in high contrast. Logical edges mirror it in a\n right-to-left page. */\n .indicator {\n position: absolute;\n inset-block: var(--ui-space-2);\n inset-inline-start: 0;\n display: none;\n border-inline-start: var(--_indicator-width) solid var(--_indicator-color);\n border-radius: var(--ui-radius-round);\n }\n\n :host[aria-current] .indicator {\n display: block;\n }\n\n @media (forced-colors: active) {\n .indicator {\n border-inline-start-color: Highlight;\n }\n }\n\n .leading {\n display: inline-flex;\n flex: none;\n align-items: center;\n color: inherit;\n font-size: var(--ui-font-size-lg);\n }\n\n .content {\n display: flex;\n flex: 1;\n flex-direction: column;\n gap: var(--ui-space-0-5, 2px);\n min-inline-size: 0;\n }\n\n .label,\n .description {\n display: block;\n min-inline-size: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .label {\n font-size: var(--ui-font-size-md);\n line-height: var(--ui-line-height-tight);\n }\n\n .description {\n color: var(--ui-text-muted);\n font-size: var(--ui-font-size-sm);\n font-weight: var(--ui-font-normal);\n line-height: var(--ui-line-height-tight);\n }\n\n /* An unused region takes no space. */\n .leading:empty,\n .description:empty {\n display: none;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true,"name":"leading"},{"dynamic":false,"required":true},{"dynamic":false,"required":true,"name":"description"}],"root":{"kind":"native","element":"button","choices":["a","button"]}},{"source":{"file":"./components/ui-page-header/ui-page-header.html"},"contract":{"version":1,"name":"UiPageHeader","tag":"ui-page-header","nativeElement":"header","props":{"align":{"type":{"enum":["start","center"]},"required":false,"target":{"attribute":"align"},"description":"Where the header sits. start runs along the page's start edge with actions at the end; center stacks everything centred, for a standalone card such as\n sign-in.","default":"start"}}},"template":{"kind":"element","name":"header","attributes":[],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"leading"}],"children":[{"kind":"slot","fallback":[],"name":"leading"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"copy"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"eyebrow"}],"children":[{"kind":"slot","fallback":[],"name":"eyebrow"}]},{"kind":"element","name":"h1","attributes":[{"kind":"literal","name":"class","value":"title"}],"children":[{"kind":"slot"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"description"}],"children":[{"kind":"slot","fallback":[],"name":"description"}]}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"actions"}],"children":[{"kind":"slot","fallback":[],"name":"actions"}]}]},"css":"/* The top of a view: its title (the page's one h1), with an optional icon or mark before it, a\n short eyebrow above it, a line or two of description under it, and the view's own actions at\n the end. Every view titles itself the same way, at the same size. */\n :host {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--ui-space-3) var(--ui-space-4);\n min-inline-size: 0;\n }\n\n .leading {\n display: inline-flex;\n flex: none;\n align-self: center;\n color: var(--ui-text-muted);\n font-size: var(--ui-font-size-2xl);\n }\n\n .copy {\n display: flex;\n flex: 1 1 16rem;\n flex-direction: column;\n gap: var(--ui-space-1);\n min-inline-size: 0;\n }\n\n .eyebrow {\n color: var(--ui-text-muted);\n font-size: var(--ui-font-size-xs);\n font-weight: var(--ui-font-semibold);\n letter-spacing: 0.06em;\n text-transform: uppercase;\n }\n\n .title {\n margin: 0;\n color: var(--ui-text-primary);\n font-size: var(--ui-font-size-2xl);\n font-weight: var(--ui-font-bold, 700);\n line-height: var(--ui-line-height-tight);\n overflow-wrap: anywhere;\n }\n\n .description {\n color: var(--ui-text-secondary);\n font-size: var(--ui-font-size-md);\n line-height: var(--ui-line-height);\n }\n\n .actions {\n display: inline-flex;\n flex: none;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--ui-space-2);\n }\n\n :host-state([align=\"center\"]) {\n flex-direction: column;\n text-align: center;\n }\n\n :host-state([align=\"center\"]) .copy {\n align-items: center;\n flex-basis: auto;\n }\n\n .leading:empty,\n .eyebrow:empty,\n .description:empty,\n .actions:empty {\n display: none;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true,"name":"leading"},{"dynamic":false,"required":true,"name":"eyebrow"},{"dynamic":false,"required":true},{"dynamic":false,"required":true,"name":"description"},{"dynamic":false,"required":true,"name":"actions"}],"root":{"kind":"native","element":"header","choices":["header"]}},{"source":{"file":"./components/ui-popover/ui-popover.html"},"contract":{"version":1,"name":"UiPopover","tag":"ui-popover","nativeElement":"span","props":{"for":{"type":"string","required":false,"target":{"attribute":"for"},"description":"ID of the control that toggles and anchors the popover.","default":""},"open":{"type":"boolean","required":false,"target":{"attribute":"open"},"description":"Whether the popover is open initially or when set externally.","default":false},"placement":{"type":"string","required":false,"target":{"attribute":"placement"},"description":"Positions the surface relative to its trigger.","default":"bottom-start"}}},"template":{"kind":"element","name":"span","attributes":[],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"surface"}],"children":[{"kind":"slot"}]}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-popover-viewport-gap {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n box-sizing: border-box;\n max-inline-size: min(\n 20rem,\n calc(100vw - var(--ui-popover-viewport-gap, var(--ui-space-2)) * 2)\n );\n max-block-size: calc(100dvh - var(--ui-popover-viewport-gap, var(--ui-space-2)) * 2);\n overflow: visible;\n padding: 0;\n border: 0;\n outline: 0;\n border-radius: 0;\n background: transparent;\n box-shadow: none;\n }\n\n .surface {\n box-sizing: border-box;\n max-inline-size: inherit;\n max-block-size: inherit;\n overflow: auto;\n padding: var(--ui-space-3);\n background: var(--ui-surface-elevated);\n border: 1px solid var(--ui-border-default);\n border-radius: var(--ui-radius-lg);\n box-shadow: var(--ui-elevation-overlay, var(--ui-shadow-lg));\n }\n\n :host:not(:host-state([internalOpen])) {\n display: none;\n }\n\n :host[popover] {\n position: fixed;\n inset: auto;\n margin: 0;\n opacity: 0;\n transform: translateY(-4px) scale(0.99);\n transition:\n opacity var(--ui-motion-fast) var(--ui-motion-ease),\n transform var(--ui-motion-fast) var(--ui-motion-ease),\n display var(--ui-motion-fast) allow-discrete,\n overlay var(--ui-motion-fast) allow-discrete;\n }\n\n :host[popover]:popover-open {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n\n @starting-style {\n :host[popover]:popover-open {\n opacity: 0;\n transform: translateY(-4px) scale(0.99);\n }\n }\n\n :host[hidden] {\n display: none;\n }\n\n @media (prefers-reduced-motion: reduce) {\n :host[popover] {\n transition: none;\n }\n }","declarations":[{"kind":"state","name":"internalOpen","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"event","name":"open","type":"object({ open: boolean, reason: action | programmatic | light-dismiss | escape, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"close","type":"object({ open: boolean, reason: action | programmatic | light-dismiss | escape, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false}],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"span","choices":["span"]},"controller":"./components/ui-popover/ui-popover.js"},{"source":{"file":"./components/ui-radio-group/ui-radio-group.html"},"contract":{"version":1,"name":"UiRadioGroup","tag":"ui-radio-group","nativeElement":"fieldset","props":{"disabled":{"type":"boolean","required":false,"target":{"attribute":"disabled"},"description":"Disables every radio in the group through the native fieldset, so no choice can be made and the group submits nothing with its form. A radio disabled on\n its own stays disabled when the group is enabled.","default":false},"label":{"type":"string","required":false,"target":{"attribute":"label"},"description":"The group's legend, shown above the radios and announced as the group's name. Phrase it as the question the radios answer.","default":"Options"},"name":{"type":"string","required":false,"target":{"attribute":"name"},"description":"The native name given to every radio in the group, under which a form submits the chosen value. Left empty, the group generates a unique name that keeps\n the radios together, so set it when the choice submits with a form.","default":""},"orientation":{"type":{"enum":["horizontal","vertical"]},"required":false,"target":{"attribute":"orientation"},"description":"horizontal lays the radios out in a row; vertical stacks them in a column. The arrow keys move between radios either way.","default":"horizontal"},"required":{"type":"boolean","required":false,"target":{"attribute":"aria-required"},"description":"Makes a choice required, as a required native radio does for its group: the group states aria-required, every radio in it is marked required, and native\n form validation fails until one is checked.","default":false},"value":{"type":"string","required":false,"target":{"attribute":"value"},"description":"The value of the checked radio, initially or when set externally; empty checks none. The user's choice updates it from there and is reported as select and\n change events, and a form reset returns the group to it.","default":""}}},"template":{"kind":"element","name":"fieldset","attributes":[{"kind":"literal","name":"role","value":"radiogroup"},{"kind":"attribute","name":"aria-required","expression":"required","expressionPlan":{"source":"required","ast":{"kind":"id","name":"required"},"dependencies":["required"]}},{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}}],"children":[{"kind":"element","name":"legend","attributes":[],"children":[{"kind":"element","name":"template","attributes":[{"kind":"directive","name":"value","expression":"label","expressionPlan":{"source":"label","ast":{"kind":"id","name":"label"},"dependencies":["label"]}}],"children":[]}]},{"kind":"slot"}]},"css":":host {\n display: inline-flex;\n align-items: center;\n gap: var(--ui-space-2);\n min-inline-size: 0;\n margin: 0;\n padding: 0;\n border: 0;\n }\n\n legend {\n float: inline-start;\n inline-size: 100%;\n margin: 0 0 var(--ui-space-2);\n padding: 0;\n color: var(--ui-text-primary);\n font-weight: var(--ui-font-medium);\n }\n\n legend + * {\n clear: both;\n }\n\n :host-state([orientation=\"vertical\"]) {\n display: inline-grid;\n justify-items: start;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"internalValue","expression":{"source":"''","ast":{"kind":"literal","value":""},"dependencies":[]}},{"kind":"event","name":"select","type":"object({ value: string, previousValue: string, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"change","type":"object({ checked: boolean, value: string, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false}],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"fieldset","choices":["fieldset"]},"controller":"./components/ui-radio-group/ui-radio-group.js"},{"source":{"file":"./components/ui-radio/ui-radio.html"},"contract":{"version":1,"name":"UiRadio","tag":"ui-radio","nativeElement":"label","props":{"checked":{"type":"boolean","required":false,"target":{"attribute":"checked"},"description":"Whether the radio is checked initially or when set externally. A form reset returns it to this. Inside a ui-radio-group the group's value decides\n instead.","default":false},"disabled":{"type":"boolean","required":false,"target":{"attribute":"disabled"},"description":"Disables the native radio, so it cannot be chosen, focused, or reached with the arrow keys.","default":false},"name":{"type":"string","required":false,"target":{"attribute":"name"},"description":"The native name that groups radios: of the radios that share a name, only one can be checked, and the arrow keys move between them. Inside a ui-radio-group\n the group sets the name, so leave this empty there.","default":""},"required":{"type":"boolean","required":false,"target":{"attribute":"required"},"description":"Marks the native radio required, so native form validation fails until a radio with the same name is checked.","default":false},"value":{"type":"string","required":false,"target":{"attribute":"value"},"description":"The value this radio stands for: submitted with a form, reported in its change event, and matched against a ui-radio-group's value to decide which radio is\n checked.","default":"on"}}},"template":{"kind":"element","name":"label","attributes":[],"children":[{"kind":"element","name":"input","attributes":[{"kind":"literal","name":"type","value":"radio"},{"kind":"property","key":"checked","name":"checked","expression":"internalChecked","expressionPlan":{"source":"internalChecked","ast":{"kind":"id","name":"internalChecked"},"dependencies":["internalChecked"]}},{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}},{"kind":"attribute","name":"required","expression":"required","expressionPlan":{"source":"required","ast":{"kind":"id","name":"required"},"dependencies":["required"]}},{"kind":"attribute","name":"value","expression":"value","expressionPlan":{"source":"value","ast":{"kind":"id","name":"value"},"dependencies":["value"]}},{"kind":"attribute","name":"name","expression":"name","expressionPlan":{"source":"name","ast":{"kind":"id","name":"name"},"dependencies":["name"]}}],"children":[],"ref":"input"},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"text"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"label"}],"children":[{"kind":"slot"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"description"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[{"kind":"slot","fallback":[],"name":"description"}],"ref":"description"}]}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-radio-gap {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-radio-size {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-radio-size: var(--ui-radio-size);\n\n display: inline-flex;\n align-items: flex-start;\n gap: var(--ui-radio-gap, var(--ui-space-2));\n max-inline-size: 100%;\n color: var(--ui-text-primary);\n cursor: pointer;\n }\n\n /* The label, and under it an optional line saying what the choice means. */\n .text {\n display: flex;\n flex-direction: column;\n gap: var(--ui-space-1);\n min-inline-size: 0;\n }\n\n .label {\n min-inline-size: 0;\n line-height: var(--ui-line-height-md);\n }\n\n .description {\n color: var(--ui-text-secondary);\n font-size: var(--ui-font-size-sm);\n line-height: var(--ui-line-height);\n }\n\n .description:empty {\n display: none;\n }\n\n input {\n flex: 0 0 auto;\n inline-size: var(--_ui-radio-size, 1.125rem);\n block-size: var(--_ui-radio-size, 1.125rem);\n margin: 0.125em 0 0;\n accent-color: var(--ui-accent-solid);\n cursor: pointer;\n }\n\n input:focus-visible {\n outline: 2px solid var(--ui-focus-ring, var(--ui-accent-solid));\n outline-offset: 2px;\n }\n\n :host-state([disabled]) {\n color: var(--ui-disabled-text);\n cursor: not-allowed;\n }\n :host-state([disabled]) input {\n cursor: not-allowed;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"internalChecked","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"event","name":"change","type":"object({ checked: boolean, value: string, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false}],"slots":[{"dynamic":false,"required":true},{"dynamic":false,"required":true,"name":"description"}],"root":{"kind":"native","element":"label","choices":["label"]},"controller":"./components/ui-radio/ui-radio.js"},{"source":{"file":"./components/ui-reel/ui-reel.html"},"contract":{"version":1,"name":"UiReel","tag":"ui-reel","nativeElement":"div","props":{"gap":{"type":{"enum":["xs","s","m","l","xl"]},"required":false,"target":{"attribute":"gap"},"description":"Space between items, on the spacing scale: xs is 0.5rem, s 0.75rem, m 1rem (also the default), l 1.5rem, and xl 2rem. The --ui-reel-gap custom property,\n set on the reel itself, overrides it; set on an ancestor, it does nothing."},"itemWidth":{"type":{"enum":["sm","md","lg"]},"required":false,"target":{"attribute":"itemwidth"},"description":"A fixed width for every item: sm is 12rem, md is 16rem, and lg is 20rem. Unset, each item keeps its content's width. Items never shrink to fit, so the reel\n scrolls sideways once they overflow."},"snap":{"type":{"enum":["start","center"]},"required":false,"target":{"attribute":"snap"},"description":"Snaps scrolling to items: start comes to rest with an item's start edge at the reel's start, and center with an item centred in the reel. Unset, the reel\n scrolls freely."}}},"template":{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"role","value":"region"},{"kind":"literal","name":"tabindex","value":"0"}],"children":[{"kind":"slot"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-reel-gap {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-reel-item-width {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-reel-item-width: var(--ui-reel-item-width);\n\n --_reel-gap: var(--ui-space-4);\n --_reel-item-width: auto;\n display: flex;\n inline-size: 100%;\n gap: var(--ui-reel-gap, var(--_reel-gap));\n min-inline-size: 0;\n max-inline-size: 100%;\n margin: 0;\n overflow-x: auto;\n overflow-y: hidden;\n overscroll-behavior-inline: contain;\n }\n\n /* Each end that hides items fades: the scroll fade every Looma scroller uses (see ui-scroll-area). */\n :host {\n --_ui-scroll-fade-direction: to right;\n --_ui-scroll-fade-size: var(--ui-scroll-fade-size, 24px);\n mask-image: linear-gradient(\n var(--_ui-scroll-fade-direction),\n transparent,\n #000 var(--_ui-scroll-fade-start),\n #000 calc(100% - var(--_ui-scroll-fade-end)),\n transparent\n );\n animation: ui-scroll-fade-start linear, ui-scroll-fade-start-hold linear, ui-scroll-fade-end-hold linear, ui-scroll-fade-end linear;\n animation-timeline: scroll(self inline);\n animation-range:\n 0 var(--_ui-scroll-fade-size),\n var(--_ui-scroll-fade-size) calc(100% + 1px),\n -1px calc(100% - var(--_ui-scroll-fade-size)),\n calc(100% - var(--_ui-scroll-fade-size)) 100%;\n }\n\n :host:dir(rtl) {\n --_ui-scroll-fade-direction: to left;\n }\n\n :host > :slotted(*) {\n min-inline-size: 0;\n flex: 0 0 var(--_ui-reel-item-width, var(--_reel-item-width));\n }\n\n :host-state([gap=\"xs\"]) {\n --_reel-gap: var(--ui-space-2);\n }\n :host-state([gap=\"s\"]) {\n --_reel-gap: var(--ui-space-3);\n }\n :host-state([gap=\"m\"]) {\n --_reel-gap: var(--ui-space-4);\n }\n :host-state([gap=\"l\"]) {\n --_reel-gap: var(--ui-space-5);\n }\n :host-state([gap=\"xl\"]) {\n --_reel-gap: var(--ui-space-6);\n }\n :host-state([itemWidth=\"sm\"]) {\n --_reel-item-width: 12rem;\n }\n :host-state([itemWidth=\"md\"]) {\n --_reel-item-width: 16rem;\n }\n :host-state([itemWidth=\"lg\"]) {\n --_reel-item-width: 20rem;\n }\n :host-state([snap]) {\n scroll-snap-type: inline mandatory;\n }\n :host-state([snap=\"start\"]) > :slotted(*) {\n scroll-snap-align: start;\n }\n :host-state([snap=\"center\"]) > :slotted(*) {\n scroll-snap-align: center;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]}},{"source":{"file":"./components/ui-scroll-area/ui-scroll-area.html"},"contract":{"version":1,"name":"UiScrollArea","tag":"ui-scroll-area","nativeElement":"div","props":{"orientation":{"type":{"enum":["vertical","horizontal"]},"required":false,"target":{"attribute":"orientation"},"description":"The direction the content scrolls. Vertical scrolls up and down and clips sideways overflow; horizontal scrolls sideways and clips vertical\n overflow.","default":"vertical"}}},"template":{"kind":"element","name":"div","attributes":[],"children":[{"kind":"slot"}]},"css":"/* A region that scrolls when its content outgrows it. Each edge that hides content fades, growing\n in as the content leaves that edge (the scroll fade in tokens.css), so the reader can tell there\n is more; an edge with nothing past it stays crisp, and content that fits shows no fade. The\n fade is a mask, so it blends into whatever is behind the area without knowing its colour. */\n :host {\n display: block;\n box-sizing: border-box;\n min-block-size: 0;\n min-inline-size: 0;\n overflow-x: hidden;\n overflow-y: auto;\n overscroll-behavior: contain;\n --_ui-scroll-fade-direction: to bottom;\n --_ui-scroll-fade-inline: to right;\n --_ui-scroll-fade-size: var(--ui-scroll-fade-size, 24px);\n mask-image: linear-gradient(\n var(--_ui-scroll-fade-direction),\n transparent,\n #000 var(--_ui-scroll-fade-start),\n #000 calc(100% - var(--_ui-scroll-fade-end)),\n transparent\n );\n animation: ui-scroll-fade-start linear, ui-scroll-fade-start-hold linear, ui-scroll-fade-end-hold linear, ui-scroll-fade-end linear;\n animation-timeline: scroll(self block);\n animation-range:\n 0 var(--_ui-scroll-fade-size),\n var(--_ui-scroll-fade-size) calc(100% + 1px),\n -1px calc(100% - var(--_ui-scroll-fade-size)),\n calc(100% - var(--_ui-scroll-fade-size)) 100%;\n }\n\n :host-state([orientation=\"horizontal\"]) {\n overflow-x: auto;\n overflow-y: hidden;\n --_ui-scroll-fade-direction: var(--_ui-scroll-fade-inline);\n animation-timeline: scroll(self inline);\n }\n\n :host:dir(rtl) {\n --_ui-scroll-fade-inline: to left;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]}},{"source":{"file":"./components/ui-search-result-row/ui-search-result-row.html"},"contract":{"version":1,"name":"UiSearchResultRow","tag":"ui-search-result-row","nativeElement":"button","props":{"disabled":{"type":"boolean","required":false,"target":{"attribute":"disabled"},"description":"Disables the row's button, so it cannot be chosen or focused, and fades it to 60% opacity.","default":false},"selected":{"type":"boolean","required":false,"target":{"attribute":"aria-current"},"description":"Marks the row as the current result: it gets the hover surface and aria-current=\"true\", which assistive technology announces as current. Set it on one row\n at a time, such as the result the arrow keys have moved to.","default":false}}},"template":{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}},{"kind":"attribute","name":"aria-current","expression":"selected","expressionPlan":{"source":"selected","ast":{"kind":"id","name":"selected"},"dependencies":["selected"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"leading"}],"children":[{"kind":"slot","fallback":[],"name":"leading"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"content"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"title"}],"children":[{"kind":"slot","fallback":[],"name":"title"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"meta"}],"children":[{"kind":"slot","fallback":[],"name":"meta"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"excerpt"}],"children":[{"kind":"slot","fallback":[],"name":"excerpt"}]}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"trailing"}],"children":[{"kind":"slot","fallback":[],"name":"trailing"}]}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-search-result-row-border {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-search-result-row-gap {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-search-result-row-hover-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-search-result-row-min-height {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-search-result-row-padding-block {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-search-result-row-padding-inline {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-search-result-row-selected-bg {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-search-result-row-surface {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n appearance: none;\n inline-size: 100%;\n min-block-size: var(--ui-search-result-row-min-height, 56px);\n margin: 0;\n padding-block: var(--ui-search-result-row-padding-block, var(--ui-space-3));\n padding-inline: var(--ui-search-result-row-padding-inline, var(--ui-space-4));\n display: flex;\n align-items: flex-start;\n gap: var(--ui-search-result-row-gap, var(--ui-space-3));\n background: var(--ui-search-result-row-surface, transparent);\n border: none;\n border-block-end: 1px solid var(--ui-search-result-row-border, var(--ui-border));\n color: inherit;\n cursor: pointer;\n text-align: left;\n transition: background-color var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n :host:last-child {\n border-block-end: none;\n }\n\n :host:hover:enabled {\n background: var(--ui-search-result-row-hover-surface, color-mix(in srgb, var(--ui-surface) 85%, black 3%));\n }\n\n :host-state([selected]) {\n background: var(\n --ui-search-result-row-selected-bg,\n var(--ui-search-result-row-hover-surface, color-mix(in srgb, var(--ui-surface) 85%, black 3%))\n );\n }\n\n :host:focus-visible {\n outline: 2px solid var(--ui-focus-ring);\n outline-offset: -2px;\n }\n\n :host:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n }\n\n .leading,\n .trailing {\n display: inline-flex;\n align-items: flex-start;\n flex-shrink: 0;\n }\n\n .content {\n min-inline-size: 0;\n flex: 1;\n display: flex;\n flex-direction: column;\n }\n\n .title,\n .meta,\n .excerpt {\n display: block;\n min-inline-size: 0;\n }\n\n /* An unused region takes no space. */\n .leading:empty,\n .meta:empty,\n .excerpt:empty,\n .trailing:empty {\n display: none;\n }\n\n :slotted([slot=\"title\"]),\n :slotted([slot=\"meta\"]),\n :slotted([slot=\"excerpt\"]) {\n display: block;\n margin: 0;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true,"name":"leading"},{"dynamic":false,"required":true,"name":"title"},{"dynamic":false,"required":true,"name":"meta"},{"dynamic":false,"required":true,"name":"excerpt"},{"dynamic":false,"required":true,"name":"trailing"}],"root":{"kind":"native","element":"button","choices":["button"]}},{"source":{"file":"./components/ui-search-shell/ui-search-shell.html"},"contract":{"version":1,"name":"UiSearchShell","tag":"ui-search-shell","nativeElement":"div","props":{"dismissible":{"type":"boolean","required":false,"target":{"attribute":"dismissible"},"description":"Allows Escape and backdrop activation to close the search surface.","default":false},"label":{"type":"string","required":false,"target":{"attribute":"aria-label"},"description":"Provides the native dialog's accessible name.","default":"Search"},"modal":{"type":"boolean","required":false,"target":{"attribute":"modal"},"description":"Makes the rest of the page inert while the search surface is open.","default":false},"open":{"type":"boolean","required":false,"target":{"attribute":"open"},"description":"Shows the search surface.","default":false}}},"template":{"kind":"element","name":"div","attributes":[],"children":[{"kind":"element","name":"dialog","attributes":[{"kind":"attribute","name":"aria-label","expression":"label","expressionPlan":{"source":"label","ast":{"kind":"id","name":"label"},"dependencies":["label"]}}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"panel"}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"search"}],"children":[{"kind":"slot","fallback":[],"name":"search"}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"status"}],"children":[{"kind":"slot","fallback":[],"name":"status"}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"body"}],"children":[{"kind":"slot","fallback":[],"name":"body"}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"footer"}],"children":[{"kind":"slot","fallback":[],"name":"footer"}]}]}],"ref":"dialog"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-search-shell-border {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-search-shell-focus-color {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-search-shell-max-height {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-search-shell-max-width {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-search-shell-padding-top {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-search-shell-radius {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-search-shell-shadow {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-search-shell-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-search-shell-viewport-gap {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-search-shell-z-index {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-search-shell-z-index: var(--ui-search-shell-z-index);\n --_ui-search-shell-padding-top: var(--ui-search-shell-padding-top);\n --_ui-search-shell-viewport-gap: var(--ui-search-shell-viewport-gap);\n --_ui-search-shell-max-width: var(--ui-search-shell-max-width);\n --_ui-search-shell-max-height: var(--ui-search-shell-max-height);\n --_ui-search-shell-surface: var(--ui-search-shell-surface);\n --_ui-search-shell-border: var(--ui-search-shell-border);\n --_ui-search-shell-radius: var(--ui-search-shell-radius);\n --_ui-search-shell-shadow: var(--ui-search-shell-shadow);\n --_ui-search-shell-focus-color: var(--ui-search-shell-focus-color);\n\n display: contents;\n }\n\n dialog {\n position: fixed;\n inset: 0;\n z-index: var(--_ui-search-shell-z-index, 400);\n box-sizing: border-box;\n inline-size: 100%;\n max-inline-size: none;\n block-size: 100%;\n max-block-size: none;\n margin: 0;\n padding: var(--_ui-search-shell-padding-top, 10vh) var(--_ui-search-shell-viewport-gap, var(--ui-space-4))\n var(--_ui-search-shell-viewport-gap, var(--ui-space-4));\n overflow: auto;\n border: 0;\n background: var(--ui-overlay-backdrop);\n color: var(--ui-text-primary);\n }\n\n dialog::backdrop {\n background: var(--ui-overlay-backdrop);\n }\n\n .panel {\n position: relative;\n display: flex;\n flex-direction: column;\n inline-size: min(100%, var(--_ui-search-shell-max-width, 40rem));\n max-block-size: var(--_ui-search-shell-max-height, 80vh);\n margin-inline: auto;\n overflow: hidden;\n background: var(--_ui-search-shell-surface, var(--ui-surface-elevated));\n border: 1px solid var(--_ui-search-shell-border, var(--ui-border-default));\n border-radius: var(--_ui-search-shell-radius, var(--ui-radius-dialog));\n box-shadow: var(--_ui-search-shell-shadow, var(--ui-elevation-dialog, var(--ui-shadow-xl)));\n }\n\n .search {\n padding: var(--ui-space-3);\n border-block-end: 1px solid var(--ui-border-default);\n transition: border-color var(--ui-motion-fast) var(--ui-motion-ease), box-shadow var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n /* The search region shows where typing goes, whatever the author put in it. */\n .search:focus-within {\n border-block-end-color: var(--_ui-search-shell-focus-color, var(--ui-control-focus));\n box-shadow: inset 0 -1px 0 var(--_ui-search-shell-focus-color, var(--ui-control-focus));\n }\n\n :slotted(input[slot=\"search\"]) {\n box-sizing: border-box;\n inline-size: 100%;\n min-block-size: var(--ui-control-min-block-size);\n padding: var(--ui-space-2) var(--ui-space-3);\n border: 1px solid var(--ui-control-border);\n border-radius: var(--ui-radius-md);\n background: var(--ui-control-surface);\n color: var(--ui-text-primary);\n font: inherit;\n box-shadow: var(--ui-shadow-xs);\n }\n\n :slotted(input[slot=\"search\"]:focus-visible) {\n border-color: var(--ui-control-focus);\n outline: 2px solid var(--ui-focus-ring);\n outline-offset: 2px;\n }\n\n .status,\n .footer {\n flex-shrink: 0;\n padding: var(--ui-space-2) var(--ui-space-4);\n color: var(--ui-text-secondary);\n font-size: var(--ui-font-size-sm);\n }\n\n .status {\n border-block-end: 1px solid var(--ui-border-default);\n }\n\n /* Laid out like the dialog's action row: actions right-aligned, spaced as buttons, no fill. */\n .footer {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: flex-end;\n gap: var(--ui-space-2);\n padding: var(--ui-space-3) var(--ui-space-4);\n border-block-start: 1px solid var(--ui-border-default);\n }\n\n .status:empty,\n .footer:empty {\n display: none;\n }\n\n .body {\n flex: 1;\n min-block-size: 0;\n overflow: auto;\n padding: var(--ui-space-2);\n /* Each edge that hides content fades: the scroll fade every Looma scroller uses (see ui-scroll-area). */\n --_ui-scroll-fade-direction: to bottom;\n --_ui-scroll-fade-size: var(--ui-scroll-fade-size, 24px);\n mask-image: linear-gradient(\n var(--_ui-scroll-fade-direction),\n transparent,\n #000 var(--_ui-scroll-fade-start),\n #000 calc(100% - var(--_ui-scroll-fade-end)),\n transparent\n );\n animation: ui-scroll-fade-start linear, ui-scroll-fade-start-hold linear, ui-scroll-fade-end-hold linear, ui-scroll-fade-end linear;\n animation-timeline: scroll(self block);\n animation-range:\n 0 var(--_ui-scroll-fade-size),\n var(--_ui-scroll-fade-size) calc(100% + 1px),\n -1px calc(100% - var(--_ui-scroll-fade-size)),\n calc(100% - var(--_ui-scroll-fade-size)) 100%;\n }\n\n @media (max-width: 47.9375rem) {\n dialog {\n padding: 0;\n }\n\n .panel {\n inline-size: 100%;\n min-block-size: 100dvh;\n max-block-size: none;\n border: 0;\n border-radius: 0;\n }\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"internalOpen","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"event","name":"close","type":"object({ open: boolean, reason: action | programmatic | light-dismiss | escape, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false}],"slots":[{"dynamic":false,"required":true,"name":"search"},{"dynamic":false,"required":true,"name":"status"},{"dynamic":false,"required":true,"name":"body"},{"dynamic":false,"required":true,"name":"footer"}],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-search-shell/ui-search-shell.js"},{"source":{"file":"./components/ui-section/ui-section.html"},"contract":{"version":1,"name":"UiSection","tag":"ui-section","nativeElement":"section","props":{"heading":{"type":"string","required":false,"target":{"attribute":"heading"},"description":"The section's heading, an h2. Leave it empty for a section with no visible heading, and name the section with aria-label.","default":""},"tone":{"type":{"enum":["neutral","danger"]},"required":false,"target":{"attribute":"tone"},"description":"danger marks a section of destructive actions (a danger zone): its heading and a card's border take the danger colour.","default":"neutral"},"variant":{"type":{"enum":["plain","card","divided"]},"required":false,"target":{"attribute":"variant"},"description":"How the section is set apart. plain is a heading and content in the flow of the page; card sits it on a bordered surface, for a settings group; divided\n rules it off from the section before it, for a long form.","default":"plain"}}},"template":{"kind":"element","name":"section","attributes":[],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"head"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"copy"}],"children":[{"kind":"element","name":"h2","attributes":[{"kind":"literal","name":"class","value":"heading"},{"kind":"attribute","name":"hidden","expression":"not heading","expressionPlan":{"source":"not heading","ast":{"kind":"unary","op":"not","operand":{"kind":"id","name":"heading"}},"dependencies":["heading"]}}],"children":[{"kind":"element","name":"template","attributes":[{"kind":"directive","name":"value","expression":"heading","expressionPlan":{"source":"heading","ast":{"kind":"id","name":"heading"},"dependencies":["heading"]}}],"children":[]}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"description"}],"children":[{"kind":"slot","fallback":[],"name":"description"}]}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"actions"}],"children":[{"kind":"slot","fallback":[],"name":"actions"}]}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"body"}],"children":[{"kind":"slot"}]}]},"css":"/* A part of a view: a heading, an optional line under it, actions for the whole section at its\n end, and the content. Sections space themselves out through the Stack around them. */\n :host {\n display: flex;\n flex-direction: column;\n gap: var(--ui-space-4);\n min-inline-size: 0;\n }\n\n :host-state([variant=\"card\"]) {\n padding: var(--ui-space-5);\n border: 1px solid var(--ui-border-default);\n border-radius: var(--ui-radius-lg);\n background: var(--ui-surface-raised);\n }\n\n :host-state([variant=\"divided\"]) {\n padding-block-start: var(--ui-space-6);\n border-block-start: 1px solid var(--ui-border-default);\n }\n\n :host-state([variant=\"card\"][tone=\"danger\"]) {\n border-color: var(--ui-danger);\n }\n\n .head {\n display: flex;\n flex-wrap: wrap;\n align-items: flex-start;\n justify-content: space-between;\n gap: var(--ui-space-2) var(--ui-space-4);\n }\n\n .copy {\n display: flex;\n flex: 1 1 16rem;\n flex-direction: column;\n gap: var(--ui-space-1);\n min-inline-size: 0;\n }\n\n .heading {\n margin: 0;\n color: var(--ui-text-primary);\n font-size: var(--ui-font-size-lg);\n font-weight: var(--ui-font-semibold);\n line-height: var(--ui-line-height-tight);\n }\n\n :host-state([tone=\"danger\"]) .heading {\n color: var(--ui-danger);\n }\n\n .description {\n color: var(--ui-text-secondary);\n font-size: var(--ui-font-size-sm);\n line-height: var(--ui-line-height);\n }\n\n .actions {\n display: inline-flex;\n flex-wrap: wrap;\n gap: var(--ui-space-2);\n }\n\n .body {\n display: flex;\n flex-direction: column;\n gap: var(--ui-space-4);\n min-inline-size: 0;\n }\n\n .description:empty,\n .actions:empty {\n display: none;\n }\n\n .head:has(.heading[hidden]):has(.description:empty):has(.actions:empty) {\n display: none;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true,"name":"description"},{"dynamic":false,"required":true,"name":"actions"},{"dynamic":false,"required":true}],"root":{"kind":"native","element":"section","choices":["section"]}},{"source":{"file":"./components/ui-select/ui-select.html"},"contract":{"version":1,"name":"UiSelect","tag":"ui-select","nativeElement":"select","props":{"disabled":{"type":"boolean","required":false,"target":{"attribute":"disabled"},"description":"Prevents selection and form submission.","default":false},"invalid":{"type":"boolean","required":false,"target":{"attribute":"aria-invalid"},"description":"Exposes invalid state to assistive technology and styling.","default":false},"required":{"type":"boolean","required":false,"target":{"attribute":"required"},"description":"Requires a non-empty option for form validation.","default":false},"value":{"type":"string","required":false,"target":{"attribute":"value"},"description":"The value of the selected option, initially or when set externally. It is also the default, so a form reset returns to it rather than to the first\n option."}}},"template":{"kind":"element","name":"select","attributes":[{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}},{"kind":"attribute","name":"required","expression":"required","expressionPlan":{"source":"required","ast":{"kind":"id","name":"required"},"dependencies":["required"]}},{"kind":"attribute","name":"aria-invalid","expression":"invalid","expressionPlan":{"source":"invalid","ast":{"kind":"id","name":"invalid"},"dependencies":["invalid"]}}],"children":[{"kind":"slot"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-select-focus-shadow {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-select-radius {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-select-shadow {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n box-sizing: border-box;\n display: inline-block;\n inline-size: 100%;\n min-inline-size: 0;\n min-block-size: var(--ui-control-size-md);\n margin: 0;\n padding: var(--ui-space-2) var(--ui-space-3);\n border: 1px solid var(--ui-control-border, var(--ui-border-strong));\n border-radius: var(--ui-select-radius, var(--ui-radius-md));\n background-color: var(--ui-control-surface, var(--ui-surface-elevated));\n color: var(--ui-text-primary);\n color-scheme: light dark;\n font: inherit;\n line-height: var(--ui-line-height-md);\n box-shadow: var(--ui-select-shadow, var(--ui-control-inset));\n transition:\n border-color var(--ui-motion-fast) var(--ui-motion-ease),\n box-shadow var(--ui-motion-fast) var(--ui-motion-ease),\n background-color var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n /* The select draws its own chevron: the native caret cannot be inset or sized consistently.\n * The root stays a native <s-lect>, so the icon is a background image rather than an element. */\n :host {\n appearance: none;\n padding-inline-end: calc(var(--ui-space-3) + 1.5rem);\n background-image: var(\n --ui-select-chevron,\n url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235c5c58' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E\")\n );\n background-repeat: no-repeat;\n background-position: right var(--ui-space-3) center;\n background-size: 1.125rem 1.125rem;\n }\n\n :host:hover:not(:focus):not(:disabled) {\n border-color: var(--ui-control-border-hover, var(--ui-text-secondary));\n }\n\n :host:focus-visible {\n border-color: var(--ui-control-focus, var(--ui-accent-solid));\n outline: none;\n box-shadow: var(--ui-select-focus-shadow, var(--ui-control-inset), var(--ui-control-focus-halo-shadow));\n }\n\n /* The app's invalid flag, or the browser's own verdict once the user has left an invalid field. */\n :host[aria-invalid=\"true\"],\n :host:user-invalid {\n border-color: var(--ui-danger-solid);\n }\n\n :host:is([aria-invalid=\"true\"], :user-invalid):focus-visible {\n box-shadow:\n var(--ui-control-inset),\n 0 0 0 3px color-mix(in srgb, var(--ui-danger-solid) 22%, transparent);\n }\n\n :host:disabled {\n background-color: var(--ui-control-surface-disabled, var(--ui-surface-muted));\n color: var(--ui-disabled-text);\n box-shadow: none;\n cursor: not-allowed;\n }\n\n :host[size]:not([size=\"1\"]) {\n min-block-size: 7rem;\n padding: var(--ui-space-2);\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"select","choices":["select"]},"controller":"./components/ui-select/ui-select.js"},{"source":{"file":"./components/ui-separator/ui-separator.html"},"contract":{"version":1,"name":"UiSeparator","tag":"ui-separator","nativeElement":"hr","props":{"orientation":{"type":{"enum":["horizontal","vertical"]},"required":false,"target":{"attribute":"aria-orientation"},"description":"Whether the separator divides stacked content (horizontal) or inline content (vertical).","default":"horizontal"}}},"template":{"kind":"element","name":"hr","attributes":[{"kind":"attribute","name":"aria-orientation","expression":"orientation","expressionPlan":{"source":"orientation","ast":{"kind":"id","name":"orientation"},"dependencies":["orientation"]}}],"children":[]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-separator-color {\n syntax: \"*\";\n inherits: false;\n }\n\n /* The root is the hr, so the rules name :host; a bare hr matches only a descendant. */\n :host {\n box-sizing: border-box;\n align-self: stretch;\n margin: 0;\n border: 0;\n border-block-start: 1px solid var(--ui-separator-color, var(--ui-border-default));\n }\n\n :host[aria-orientation=\"vertical\"] {\n block-size: auto;\n border-block-start: 0;\n border-inline-start: 1px solid var(--ui-separator-color, var(--ui-border-default));\n }","declarations":[],"slots":[],"root":{"kind":"native","element":"hr","choices":["hr"]}},{"source":{"file":"./components/ui-sidebar/ui-sidebar.html"},"contract":{"version":1,"name":"UiSidebar","tag":"ui-sidebar","nativeElement":"aside","props":{"breakpoint":{"type":{"enum":["sm","md","lg"]},"required":false,"target":{"attribute":"breakpoint"},"description":"Below this viewport width (40rem, 48rem, 64rem) the sidebar becomes an off-canvas drawer, closed until toggled.","default":"md"},"collapsed":{"type":"boolean","required":false,"target":{"attribute":"collapsed"},"description":"Whether the docked sidebar is collapsed.","default":false},"maxWidth":{"type":"number","required":false,"target":{"attribute":"maxwidth"},"description":"The widest width the resize handle allows, in pixels.","default":480},"minWidth":{"type":"number","required":false,"target":{"attribute":"minwidth"},"description":"The narrowest width the resize handle allows, in pixels.","default":200},"resizable":{"type":"boolean","required":false,"target":{"attribute":"resizable"},"description":"Adds a resize handle on the inner edge (drag, or arrow keys, Home, and End).","default":false},"resizeLabel":{"type":"string","required":false,"target":{"attribute":"aria-label"},"description":"Accessible name of the resize handle.","default":"Resize sidebar"},"resizeStep":{"type":"number","required":false,"target":{"attribute":"resizestep"},"description":"Arrow-key resize step in pixels.","default":16},"side":{"type":{"enum":["start","end"]},"required":false,"target":{"attribute":"side"},"description":"The edge the sidebar sits on. The page places it beside its main content.","default":"start"},"width":{"type":"number","required":false,"target":{"attribute":"width"},"description":"Docked width in pixels. 0 uses --ui-sidebar-width (280px by default); dragging the handle updates it.","default":0}}},"template":{"kind":"element","name":"aside","attributes":[],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"content"}],"children":[{"kind":"slot"}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"resizer"},{"kind":"literal","name":"role","value":"separator"},{"kind":"literal","name":"aria-orientation","value":"vertical"},{"kind":"literal","name":"tabindex","value":"0"},{"kind":"literal","name":"data-ui-affordance","value":"resize"},{"kind":"attribute","name":"aria-label","expression":"resizeLabel","expressionPlan":{"source":"resizeLabel","ast":{"kind":"id","name":"resizeLabel"},"dependencies":["resizeLabel"]}},{"kind":"attribute","name":"hidden","expression":"not resizable or drawer or internalCollapsed","expressionPlan":{"source":"not resizable or drawer or internalCollapsed","ast":{"kind":"binary","op":"or","left":{"kind":"binary","op":"or","left":{"kind":"unary","op":"not","operand":{"kind":"id","name":"resizable"}},"right":{"kind":"id","name":"drawer"}},"right":{"kind":"id","name":"internalCollapsed"}},"dependencies":["drawer","internalCollapsed","resizable"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"guide"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[]}],"ref":"resizer"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-sidebar-backdrop {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-sidebar-border {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-sidebar-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-sidebar-width {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-sidebar-backdrop: var(--ui-sidebar-backdrop);\n\n position: relative;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n flex: none;\n inline-size: var(--_sidebar-width, var(--ui-sidebar-width, 280px));\n max-inline-size: 100%;\n min-block-size: 0;\n background: var(--ui-sidebar-surface, var(--ui-surface-default));\n border-inline-end: 1px solid var(--ui-sidebar-border, var(--ui-border-default));\n }\n\n :host-state([side=\"end\"]) {\n border-inline-end: 0;\n border-inline-start: 1px solid var(--ui-sidebar-border, var(--ui-border-default));\n }\n\n /* The panel's content scrolls, and each edge that hides content fades: the scroll fade every\n Looma scroller uses (see ui-scroll-area). */\n .content {\n flex: 1;\n min-block-size: 0;\n overflow: auto;\n --_ui-scroll-fade-direction: to bottom;\n --_ui-scroll-fade-size: var(--ui-scroll-fade-size, 24px);\n mask-image: linear-gradient(\n var(--_ui-scroll-fade-direction),\n transparent,\n #000 var(--_ui-scroll-fade-start),\n #000 calc(100% - var(--_ui-scroll-fade-end)),\n transparent\n );\n animation: ui-scroll-fade-start linear, ui-scroll-fade-start-hold linear, ui-scroll-fade-end-hold linear, ui-scroll-fade-end linear;\n animation-timeline: scroll(self block);\n animation-range:\n 0 var(--_ui-scroll-fade-size),\n var(--_ui-scroll-fade-size) calc(100% + 1px),\n -1px calc(100% - var(--_ui-scroll-fade-size)),\n calc(100% - var(--_ui-scroll-fade-size)) 100%;\n }\n\n /* Collapsed while docked. */\n :host-state([internalCollapsed]):not([popover]) {\n display: none;\n }\n\n .resizer {\n position: absolute;\n z-index: 1;\n inset-block: 0;\n /* On the panel's inner edge: the end edge of a start sidebar. */\n inset-inline-end: 0;\n inline-size: 8px;\n min-inline-size: 8px;\n transform: translateX(50%);\n cursor: col-resize;\n touch-action: none;\n outline: none;\n }\n\n .resizer[hidden] {\n display: none;\n }\n\n :host-state([side=\"end\"]) .resizer {\n inset-inline-end: auto;\n inset-inline-start: 0;\n transform: translateX(-50%);\n }\n\n .resizer::after {\n content: \"\";\n position: absolute;\n inset-block: 0;\n inset-inline-start: 3px;\n inline-size: 2px;\n background: color-mix(in srgb, var(--ui-affordance-guide-color, var(--ui-border-strong)) 45%, transparent);\n opacity: calc(var(--ui-affordance-guide-opacity) * var(--ui-affordance-scope-guide, 1));\n transition:\n background-color var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease),\n opacity var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease);\n }\n\n .guide {\n position: absolute;\n inset-block-start: 50%;\n inset-inline-start: 50%;\n inline-size: 6px;\n block-size: 22px;\n border: 1px solid var(--ui-border-strong);\n border-radius: var(--ui-radius-round);\n background: var(--ui-surface-elevated);\n opacity: 0;\n transform: translate(-50%, -50%);\n transition: opacity var(--ui-affordance-motion, var(--ui-motion-fast)) var(--ui-motion-ease);\n pointer-events: none;\n }\n\n .resizer:is(:hover, :focus-visible)::after {\n background: var(--ui-affordance-direct-color, var(--ui-accent-solid, var(--ui-focus-ring)));\n opacity: 1;\n }\n\n .resizer:is(:hover, :focus-visible) > .guide {\n opacity: 1;\n }\n\n /* Drawer: a popover in the top layer, sliding in from its edge. Closed popovers are hidden by the UA. */\n :host[popover] {\n position: fixed;\n inset-block: 0;\n inset-inline-start: 0;\n inset-inline-end: auto;\n margin: 0;\n padding: 0;\n inline-size: min(var(--_sidebar-width, var(--ui-sidebar-width, 280px)), 85vw);\n max-block-size: none;\n block-size: 100dvh;\n border-block: 0;\n box-shadow: var(--ui-elevation-overlay, var(--ui-shadow-lg));\n transform: translateX(0);\n transition:\n transform var(--ui-motion-base) var(--ui-motion-ease-out),\n display var(--ui-motion-base) allow-discrete,\n overlay var(--ui-motion-base) allow-discrete;\n }\n\n /* The author display above would otherwise override the UA rule that hides a closed popover. */\n :host[popover]:not(:popover-open) {\n display: none;\n transform: translateX(-100%);\n }\n\n :host-state([side=\"end\"])[popover] {\n inset-inline-start: auto;\n inset-inline-end: 0;\n }\n\n :host-state([side=\"end\"])[popover]:not(:popover-open) {\n transform: translateX(100%);\n }\n\n @starting-style {\n :host[popover]:popover-open {\n transform: translateX(-100%);\n }\n :host-state([side=\"end\"])[popover]:popover-open {\n transform: translateX(100%);\n }\n }\n\n :host[popover]::backdrop {\n background: var(--_ui-sidebar-backdrop, rgb(0 0 0 / 0.32));\n }\n\n @media (prefers-reduced-motion: reduce) {\n :host[popover] {\n transition: none;\n }\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"internalCollapsed","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"drawer","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"event","name":"resize","type":"object({ width: number, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"toggle","type":"object({ open: boolean, mode: docked | drawer, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false}],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"aside","choices":["aside"]},"controller":"./components/ui-sidebar/ui-sidebar.js"},{"source":{"file":"./components/ui-spinner/ui-spinner.html"},"contract":{"version":1,"name":"UiSpinner","tag":"ui-spinner","nativeElement":"span","props":{"label":{"type":"string","required":false,"target":{"attribute":"label"},"description":"What is loading, for assistive technology (\"Loading pages\"). With a label the spinner is a status that is announced; without one it is decoration, for a\n spinner beside visible text that already says so.","default":""},"size":{"type":{"enum":["sm","md"]},"required":false,"target":{"attribute":"size"},"description":"sm fits inside a button or a line of small text; md sits beside body text.","default":"md"}}},"template":{"kind":"element","name":"span","attributes":[{"kind":"attribute","name":"role","expression":"{ true: 'status', false: null }[format('%s', label != '')]","expressionPlan":{"source":"{ true: 'status', false: null }[format('%s', label != '')]","ast":{"kind":"index","object":{"kind":"object","pairs":[{"key":"true","value":{"kind":"literal","value":"status"}},{"key":"false","value":{"kind":"literal","value":null}}]},"index":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s"},{"kind":"binary","op":"!=","left":{"kind":"id","name":"label"},"right":{"kind":"literal","value":""}}]}},"dependencies":["label"]}},{"kind":"attribute","name":"aria-label","expression":"{ true: label, false: null }[format('%s', label != '')]","expressionPlan":{"source":"{ true: label, false: null }[format('%s', label != '')]","ast":{"kind":"index","object":{"kind":"object","pairs":[{"key":"true","value":{"kind":"id","name":"label"}},{"key":"false","value":{"kind":"literal","value":null}}]},"index":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s"},{"kind":"binary","op":"!=","left":{"kind":"id","name":"label"},"right":{"kind":"literal","value":""}}]}},"dependencies":["label"]}},{"kind":"attribute","name":"aria-hidden","expression":"{ true: null, false: 'true' }[format('%s', label != '')]","expressionPlan":{"source":"{ true: null, false: 'true' }[format('%s', label != '')]","ast":{"kind":"index","object":{"kind":"object","pairs":[{"key":"true","value":{"kind":"literal","value":null}},{"key":"false","value":{"kind":"literal","value":"true"}}]},"index":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s"},{"kind":"binary","op":"!=","left":{"kind":"id","name":"label"},"right":{"kind":"literal","value":""}}]}},"dependencies":["label"]}}],"children":[{"kind":"element","name":"ui-icon","attributes":[{"kind":"literal","name":"name","value":"loader"}],"children":[]}]},"css":"/* Something is on its way. It turns in the current text colour; with reduced motion it holds still,\n and the label (or the text beside it) still says what is happening. */\n :host {\n display: inline-flex;\n flex: none;\n color: currentColor;\n font-size: var(--ui-font-size-lg);\n line-height: 1;\n animation: ui-spinner-turn 0.8s linear infinite;\n }\n\n :host-state([size=\"sm\"]) {\n font-size: var(--ui-font-size-md);\n }\n\n @keyframes ui-spinner-turn {\n to {\n transform: rotate(1turn);\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n :host {\n animation: none;\n }\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[],"root":{"kind":"native","element":"span","choices":["span"]}},{"source":{"file":"./components/ui-stack/ui-stack.html"},"contract":{"version":1,"name":"UiStack","tag":"ui-stack","nativeElement":"div","props":{"align":{"type":{"enum":["start","center","end","stretch"]},"required":false,"target":{"attribute":"align"},"description":"How items sit across the stack: stretch (the default) makes each fill the stack's width; start, center, and end keep each at its own width, against the\n start, in the middle, or against the end."},"gap":{"type":{"enum":["xs","s","m","l","xl"]},"required":false,"target":{"attribute":"gap"},"description":"Space between items, on the spacing scale: xs is 0.5rem, s 0.75rem, m 1rem (also the default), l 1.5rem, and xl 2rem. The --ui-stack-gap custom property,\n set on the stack itself, overrides it; set on an ancestor, it does nothing."},"justify":{"type":{"enum":["start","center","end","between"]},"required":false,"target":{"attribute":"justify"},"description":"Where items sit along a stack that is taller than its content: start (the default), center, end, or between, which spreads the spare space between items.\n It has no effect unless the stack is given a height or stretched to one."}}},"template":{"kind":"element","name":"div","attributes":[],"children":[{"kind":"slot"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-stack-gap {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n --_layout-gap: var(--ui-space-4);\n display: flex;\n flex-direction: column;\n align-items: stretch;\n gap: var(--ui-stack-gap, var(--_layout-gap));\n min-inline-size: 0;\n max-inline-size: 100%;\n margin: 0;\n }\n\n :host-state([gap=\"xs\"]) {\n --_layout-gap: var(--ui-space-2);\n }\n :host-state([gap=\"s\"]) {\n --_layout-gap: var(--ui-space-3);\n }\n :host-state([gap=\"m\"]) {\n --_layout-gap: var(--ui-space-4);\n }\n :host-state([gap=\"l\"]) {\n --_layout-gap: var(--ui-space-5);\n }\n :host-state([gap=\"xl\"]) {\n --_layout-gap: var(--ui-space-6);\n }\n :host-state([align=\"start\"]) {\n align-items: flex-start;\n }\n :host-state([align=\"center\"]) {\n align-items: center;\n }\n :host-state([align=\"end\"]) {\n align-items: flex-end;\n }\n :host-state([justify=\"center\"]) {\n justify-content: center;\n }\n :host-state([justify=\"end\"]) {\n justify-content: flex-end;\n }\n :host-state([justify=\"between\"]) {\n justify-content: space-between;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]}},{"source":{"file":"./components/ui-status-message/ui-status-message.html"},"contract":{"version":1,"name":"UiStatusMessage","tag":"ui-status-message","nativeElement":"div","props":{"heading":{"type":"string","required":false,"target":{"attribute":"heading"},"description":"A short heading above the message, such as \"No pages yet\". Optional.","default":""},"kind":{"type":{"enum":["empty","loading","error"]},"required":false,"target":{"attribute":"kind"},"description":"What the view is saying. empty: there is nothing here yet (announced politely); loading: it is on its way, with a spinner (announced politely); error: it\n could not be shown, in the danger tone (announced at once).","default":"empty"},"layout":{"type":{"enum":["inline","panel","fill"]},"required":false,"target":{"attribute":"layout"},"description":"Where it sits. inline takes its place in the view's flow; panel sits it on a dashed surface, for an empty area in a page; fill centres it in all the space\n it is given, for a whole view that is loading or failed.","default":"inline"}}},"template":{"kind":"element","name":"div","attributes":[{"kind":"attribute","name":"role","expression":"{ true: 'alert', false: 'status' }[format('%s', kind = 'error')]","expressionPlan":{"source":"{ true: 'alert', false: 'status' }[format('%s', kind = 'error')]","ast":{"kind":"index","object":{"kind":"object","pairs":[{"key":"true","value":{"kind":"literal","value":"alert"}},{"key":"false","value":{"kind":"literal","value":"status"}}]},"index":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s"},{"kind":"binary","op":"=","left":{"kind":"id","name":"kind"},"right":{"kind":"literal","value":"error"}}]}},"dependencies":["kind"]}}],"children":[{"kind":"element","name":"ui-spinner","attributes":[{"kind":"literal","name":"size","value":"sm"},{"kind":"attribute","name":"hidden","expression":"kind != 'loading'","expressionPlan":{"source":"kind != 'loading'","ast":{"kind":"binary","op":"!=","left":{"kind":"id","name":"kind"},"right":{"kind":"literal","value":"loading"}},"dependencies":["kind"]}}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"copy"}],"children":[{"kind":"element","name":"strong","attributes":[{"kind":"literal","name":"class","value":"heading"},{"kind":"attribute","name":"hidden","expression":"not heading","expressionPlan":{"source":"not heading","ast":{"kind":"unary","op":"not","operand":{"kind":"id","name":"heading"}},"dependencies":["heading"]}}],"children":[{"kind":"element","name":"template","attributes":[{"kind":"directive","name":"value","expression":"heading","expressionPlan":{"source":"heading","ast":{"kind":"id","name":"heading"},"dependencies":["heading"]}}],"children":[]}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"message"}],"children":[{"kind":"slot"}]}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"action"}],"children":[{"kind":"slot","fallback":[],"name":"action"}]}]},"css":"/* The one way a view says it is loading, has nothing yet, or failed, with an optional next step.\n Every view says it the same way, in the same place, at the same size. */\n :host {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--ui-space-2) var(--ui-space-4);\n padding-block: var(--ui-space-4);\n color: var(--ui-text-muted);\n font-size: var(--ui-font-size-md);\n line-height: var(--ui-line-height);\n }\n\n :host-state([kind=\"error\"]) {\n color: var(--ui-danger);\n }\n\n :host-state([layout=\"panel\"]) {\n padding: var(--ui-space-6);\n border: 1px dashed var(--ui-border-default);\n border-radius: var(--ui-radius-lg);\n }\n\n :host-state([layout=\"fill\"]) {\n flex: 1;\n flex-direction: column;\n justify-content: center;\n min-block-size: 50vh;\n text-align: center;\n }\n\n .copy {\n display: flex;\n flex: 1 1 12rem;\n flex-direction: column;\n gap: var(--ui-space-1);\n min-inline-size: 0;\n }\n\n :host-state([layout=\"fill\"]) .copy {\n flex: none;\n align-items: center;\n }\n\n .heading {\n color: var(--ui-text-primary);\n font-weight: var(--ui-font-semibold);\n }\n\n .action {\n display: inline-flex;\n flex-wrap: wrap;\n gap: var(--ui-space-2);\n }\n\n .action:empty {\n display: none;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true},{"dynamic":false,"required":true,"name":"action"}],"root":{"kind":"native","element":"div","choices":["div"]}},{"source":{"file":"./components/ui-switch/ui-switch.html"},"contract":{"version":1,"name":"UiSwitch","tag":"ui-switch","nativeElement":"label","props":{"checked":{"type":"boolean","required":false,"target":{"attribute":"checked"},"description":"Whether the switch is checked initially or when set externally. A form reset returns it to this.","default":false},"disabled":{"type":"boolean","required":false,"target":{"attribute":"disabled"},"description":"Disables the native switch, so it cannot be toggled or focused.","default":false},"name":{"type":"string","required":false,"target":{"attribute":"name"},"description":"The native name the switch submits under: a form that contains it sends name=value while it is on, and nothing while it is off, as a native checkbox does.\n Left empty, it takes no part in form submission.","default":""},"required":{"type":"boolean","required":false,"target":{"attribute":"required"},"description":"Marks the native switch required, so native form validation treats it as invalid until it is on.","default":false},"value":{"type":"string","required":false,"target":{"attribute":"value"},"description":"The value a form submits under name while the switch is on, also reported in the change event's detail so one handler can tell switches apart. on by\n default, as on a native checkbox.","default":"on"}}},"template":{"kind":"element","name":"label","attributes":[],"children":[{"kind":"element","name":"input","attributes":[{"kind":"literal","name":"type","value":"checkbox"},{"kind":"literal","name":"role","value":"switch"},{"kind":"property","key":"checked","name":"checked","expression":"internalChecked","expressionPlan":{"source":"internalChecked","ast":{"kind":"id","name":"internalChecked"},"dependencies":["internalChecked"]}},{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}},{"kind":"attribute","name":"required","expression":"required","expressionPlan":{"source":"required","ast":{"kind":"id","name":"required"},"dependencies":["required"]}},{"kind":"attribute","name":"name","expression":"name","expressionPlan":{"source":"name","ast":{"kind":"id","name":"name"},"dependencies":["name"]}},{"kind":"attribute","name":"value","expression":"value","expressionPlan":{"source":"value","ast":{"kind":"id","name":"value"},"dependencies":["value"]}}],"children":[],"ref":"input"},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"text"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"label"}],"children":[{"kind":"slot"}]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"description"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[{"kind":"slot","fallback":[],"name":"description"}],"ref":"description"}]}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-switch-gap {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-switch-track-height {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-switch-track-width {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-switch-track-width: var(--ui-switch-track-width);\n --_ui-switch-track-height: var(--ui-switch-track-height);\n\n display: inline-flex;\n align-items: flex-start;\n gap: var(--ui-switch-gap, var(--ui-space-2));\n max-inline-size: 100%;\n color: var(--ui-text-primary);\n cursor: pointer;\n }\n\n /* The label, and under it an optional line saying what the choice means. */\n .text {\n display: flex;\n flex-direction: column;\n gap: var(--ui-space-1);\n min-inline-size: 0;\n }\n\n .label {\n min-inline-size: 0;\n line-height: var(--ui-line-height-md);\n }\n\n .description {\n color: var(--ui-text-secondary);\n font-size: var(--ui-font-size-sm);\n line-height: var(--ui-line-height);\n }\n\n .description:empty {\n display: none;\n }\n\n input {\n appearance: none;\n -webkit-appearance: none;\n position: relative;\n flex: 0 0 auto;\n width: var(--_ui-switch-track-width, 2.5rem);\n height: var(--_ui-switch-track-height, 1.5rem);\n padding: 0;\n border: 1px solid var(--ui-control-border-hover, var(--ui-border-strong));\n border-radius: 999px;\n background: var(--ui-control-surface, var(--ui-surface-default));\n box-shadow: inset 0 1px 2px color-mix(in srgb, var(--ui-text-primary) 10%, transparent);\n cursor: pointer;\n transition: background-color var(--ui-motion-fast) var(--ui-motion-ease), border-color var(--ui-motion-fast) var(--ui-motion-ease);\n margin: 0;\n }\n\n input::after {\n content: \"\";\n position: absolute;\n top: 3px;\n left: 3px;\n width: 1rem;\n height: 1rem;\n border-radius: 999px;\n background: var(--ui-text-secondary);\n box-shadow: var(--ui-shadow-xs);\n transition: transform var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n input:checked {\n background: var(--ui-accent-solid);\n border-color: var(--ui-accent-solid);\n }\n\n input:checked::after {\n transform: translateX(1rem);\n background: var(--ui-text-on-accent);\n }\n\n input:focus-visible {\n outline: 2px solid var(--ui-focus-ring, var(--ui-accent-solid));\n outline-offset: 2px;\n }\n\n :host-state([disabled]) {\n color: var(--ui-disabled-text);\n cursor: not-allowed;\n }\n :host-state([disabled]) input {\n border-color: var(--ui-border-default);\n background: var(--ui-control-surface-disabled, var(--ui-surface-muted));\n cursor: not-allowed;\n }\n\n @media (prefers-reduced-motion: reduce) {\n input, input::after {\n transition: none;\n }\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"internalChecked","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"event","name":"change","type":"object({ checked: boolean, value: string, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false}],"slots":[{"dynamic":false,"required":true},{"dynamic":false,"required":true,"name":"description"}],"root":{"kind":"native","element":"label","choices":["label"]},"controller":"./components/ui-switch/ui-switch.js"},{"source":{"file":"./components/ui-switcher/ui-switcher.html"},"contract":{"version":1,"name":"UiSwitcher","tag":"ui-switcher","nativeElement":"div","props":{"align":{"type":{"enum":["start","center","end","stretch"]},"required":false,"target":{"attribute":"align"},"description":"How items line up while they sit in a row: stretch (the default) makes them equally tall; start, center, and end align their tops, middles, or\n bottoms."},"gap":{"type":{"enum":["xs","s","m","l","xl"]},"required":false,"target":{"attribute":"gap"},"description":"Space between items, on the spacing scale: xs is 0.5rem, s 0.75rem, m 1rem (also the default), l 1.5rem, and xl 2rem. The --ui-switcher-gap custom\n property, set on the switcher itself, overrides it; set on an ancestor, it does nothing."},"threshold":{"type":{"enum":["xs","sm","md","lg"]},"required":false,"target":{"attribute":"threshold"},"description":"The container width at which items switch between a row and a stack: wider, they all sit side by side; narrower, each takes the full width. xs is 20rem, sm\n is 30rem (also the default), md is 45rem, and lg is 60rem."}}},"template":{"kind":"element","name":"div","attributes":[],"children":[{"kind":"slot"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-switcher-gap {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-switcher-threshold {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-switcher-threshold: var(--ui-switcher-threshold);\n\n --_switcher-gap: var(--ui-space-4);\n display: flex;\n flex-wrap: wrap;\n gap: var(--ui-switcher-gap, var(--_switcher-gap));\n min-inline-size: 0;\n max-inline-size: 100%;\n margin: 0;\n }\n\n :host > :slotted(*) {\n min-inline-size: 0;\n flex-grow: 1;\n /* The large multiplier makes the basis flip as a group at the intrinsic threshold. */\n flex-basis: calc((var(--_ui-switcher-threshold, 30rem) - 100%) * 999);\n }\n\n :host-state([gap=\"xs\"]) {\n --_switcher-gap: var(--ui-space-2);\n }\n :host-state([gap=\"s\"]) {\n --_switcher-gap: var(--ui-space-3);\n }\n :host-state([gap=\"m\"]) {\n --_switcher-gap: var(--ui-space-4);\n }\n :host-state([gap=\"l\"]) {\n --_switcher-gap: var(--ui-space-5);\n }\n :host-state([gap=\"xl\"]) {\n --_switcher-gap: var(--ui-space-6);\n }\n :host-state([threshold=\"xs\"]) > :slotted(*) {\n flex-basis: calc((var(--_ui-switcher-threshold, 20rem) - 100%) * 999);\n }\n :host-state([threshold=\"md\"]) > :slotted(*) {\n flex-basis: calc((var(--_ui-switcher-threshold, 45rem) - 100%) * 999);\n }\n :host-state([threshold=\"lg\"]) > :slotted(*) {\n flex-basis: calc((var(--_ui-switcher-threshold, 60rem) - 100%) * 999);\n }\n :host-state([align=\"start\"]) {\n align-items: flex-start;\n }\n :host-state([align=\"center\"]) {\n align-items: center;\n }\n :host-state([align=\"end\"]) {\n align-items: flex-end;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]}},{"source":{"file":"./components/ui-tabs/ui-tabs.html"},"contract":{"version":1,"name":"UiTabs","tag":"ui-tabs","nativeElement":"div","props":{"density":{"type":{"enum":["comfortable","compact"]},"required":false,"target":{"attribute":"density"},"description":"Compact trades padding and type size for rows that fit more on screen.","default":"comfortable"},"label":{"type":"string","required":false,"target":{"attribute":"aria-label"},"description":"The tab list's accessible name, announced when focus enters the list. Name what the tabs switch between.","default":"Tabs"},"orientation":{"type":{"enum":["horizontal","vertical"]},"required":false,"target":{"attribute":"aria-orientation"},"description":"horizontal puts the tabs in a row above the panels, moved between with the Left and Right arrow keys; vertical puts them in a column beside the panels,\n moved between with Up and Down.","default":"horizontal"},"stretch":{"type":"boolean","required":false,"target":{"attribute":"stretch"},"description":"Share the full width of the tab list equally between tabs instead of sizing each to its label.","default":false},"value":{"type":"string","required":false,"target":{"attribute":"value"},"description":"The id of the selected panel, initially or when set externally; empty selects the first panel. Choosing a tab updates it from there and reports a select\n event. A panel without an id is given a generated one.","default":""}}},"template":{"kind":"element","name":"div","attributes":[],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"list"},{"kind":"literal","name":"role","value":"tablist"},{"kind":"attribute","name":"aria-label","expression":"label","expressionPlan":{"source":"label","ast":{"kind":"id","name":"label"},"dependencies":["label"]}},{"kind":"attribute","name":"aria-orientation","expression":"orientation","expressionPlan":{"source":"orientation","ast":{"kind":"id","name":"orientation"},"dependencies":["orientation"]}}],"children":[{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"role","value":"tab"},{"kind":"attribute","name":"id","expression":"format('%s-tab', tab.id)","expressionPlan":{"source":"format('%s-tab', tab.id)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s-tab"},{"kind":"member","object":{"kind":"id","name":"tab"},"key":"id"}]},"dependencies":["tab.id"]}},{"kind":"attribute","name":"value","expression":"tab.id","expressionPlan":{"source":"tab.id","ast":{"kind":"member","object":{"kind":"id","name":"tab"},"key":"id"},"dependencies":["tab.id"]}},{"kind":"attribute","name":"aria-controls","expression":"tab.id","expressionPlan":{"source":"tab.id","ast":{"kind":"member","object":{"kind":"id","name":"tab"},"key":"id"},"dependencies":["tab.id"]}},{"kind":"attribute","name":"aria-selected","expression":"tab.id = internalValue","expressionPlan":{"source":"tab.id = internalValue","ast":{"kind":"binary","op":"=","left":{"kind":"member","object":{"kind":"id","name":"tab"},"key":"id"},"right":{"kind":"id","name":"internalValue"}},"dependencies":["internalValue","tab.id"]}},{"kind":"directive","name":"value","expression":"tab.label","expressionPlan":{"source":"tab.label","ast":{"kind":"member","object":{"kind":"id","name":"tab"},"key":"label"},"dependencies":["tab.label"]}}],"children":[],"flow":{"kind":"each","item":"tab","list":"tabs","listPlan":{"source":"tabs","ast":{"kind":"id","name":"tabs"},"dependencies":["tabs"]},"key":"tab.id","keyPlan":{"source":"tab.id","ast":{"kind":"member","object":{"kind":"id","name":"tab"},"key":"id"},"dependencies":["tab.id"]}}}],"ref":"list"},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"panels"}],"children":[{"kind":"slot"}],"ref":"panels"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-tabs-tab-min-block-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-tabs-tab-padding-block {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-tabs-tab-padding-inline {\n syntax: \"*\";\n inherits: false;\n }\n\n /* Density resolves into the tab row's own values; the public tokens still override them. */\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-tabs-tab-min-block-size: var(--ui-tabs-tab-min-block-size);\n --_ui-tabs-tab-padding-block: var(--ui-tabs-tab-padding-block);\n --_ui-tabs-tab-padding-inline: var(--ui-tabs-tab-padding-inline);\n\n --_tab-min-block-size: var(--ui-control-size);\n --_tab-padding-block: var(--ui-space-2);\n --_tab-padding-inline: var(--ui-space-3);\n }\n\n :host-state([density=\"compact\"]) {\n --_tab-min-block-size: var(--ui-control-size-sm);\n --_tab-padding-block: var(--ui-space-1);\n --_tab-padding-inline: var(--ui-space-2);\n }\n\n :host {\n display: grid;\n inline-size: 100%;\n min-inline-size: 0;\n }\n\n .list {\n display: grid;\n grid-auto-flow: column;\n grid-auto-columns: max-content;\n justify-content: start;\n inline-size: 100%;\n max-inline-size: 100%;\n /* Tabs that do not fit scroll sideways rather than wrapping or squeezing. */\n overflow-x: auto;\n /* overflow-x: auto would make the block axis scrollable too; a sideways swipe must not scroll the\n strip or the page vertically. */\n overflow-y: hidden;\n overscroll-behavior: contain;\n scrollbar-width: thin;\n border-block-end: 1px solid var(--ui-border-default);\n }\n\n .list button {\n min-block-size: var(--_ui-tabs-tab-min-block-size, var(--_tab-min-block-size));\n margin: 0 0 -1px;\n padding: var(--_ui-tabs-tab-padding-block, var(--_tab-padding-block)) var(--_ui-tabs-tab-padding-inline, var(--_tab-padding-inline));\n border: 0;\n border-block-end: 2px solid transparent;\n background: transparent;\n color: var(--ui-text-secondary);\n font: inherit;\n font-size: var(--ui-font-size-sm);\n font-weight: var(--ui-font-medium);\n cursor: pointer;\n transition:\n color var(--ui-motion-fast) var(--ui-motion-ease),\n background-color var(--ui-motion-fast) var(--ui-motion-ease),\n border-color var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n /* Centre the glyphs, not the line box: a label without descenders otherwise reads high. */\n /* Centre the glyphs, not the line box: a label without descenders otherwise reads high.\n * Trimming applies to block containers, so the box is a block with centred content. */\n @supports (text-box-trim: trim-both) {\n .list button {\n display: block;\n text-align: center;\n align-content: center;\n text-box-trim: trim-both;\n text-box-edge: cap alphabetic;\n }\n }\n\n :host-state([stretch]) .list {\n grid-auto-columns: minmax(max-content, 1fr);\n }\n\n .list button {\n white-space: nowrap;\n }\n\n .list button:hover {\n color: var(--ui-text-primary);\n background: var(--ui-surface-muted);\n }\n .list button[aria-selected=\"true\"] {\n color: var(--ui-accent-solid);\n border-block-end-color: var(--ui-accent-solid);\n }\n .list button:focus-visible {\n position: relative;\n outline: none;\n box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--ui-focus-ring) 45%, transparent);\n border-radius: var(--ui-radius-sm);\n }\n\n .panels {\n min-inline-size: 0;\n }\n :slotted(*) {\n padding: var(--ui-space-4);\n }\n\n :host-state([orientation=\"vertical\"]) {\n grid-template-columns: max-content minmax(0, 1fr);\n align-items: start;\n }\n\n :host-state([orientation=\"vertical\"]) .list {\n grid-auto-flow: row;\n grid-auto-columns: auto;\n border-block-end: 0;\n border-inline-end: 1px solid var(--ui-border-default);\n }\n\n :host-state([orientation=\"vertical\"]) .list button {\n margin: 0 -1px 0 0;\n border-block-end: 0;\n border-inline-end: 2px solid transparent;\n text-align: start;\n }\n\n :host-state([orientation=\"vertical\"]) .list button[aria-selected=\"true\"] {\n border-inline-end-color: var(--ui-accent-solid);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .list button {\n transition: none;\n }\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"internalValue","expression":{"source":"''","ast":{"kind":"literal","value":""},"dependencies":[]}},{"kind":"state","name":"tabs","type":"list(object({ id: string, label: string }))","expression":{"source":"[]","ast":{"kind":"array","items":[]},"dependencies":[]}},{"kind":"event","name":"select","type":"object({ value: string, previousValue: string, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false}],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-tabs/ui-tabs.js"},{"source":{"file":"./components/ui-text/ui-text.html"},"contract":{"version":1,"name":"UiText","tag":"ui-text","nativeElement":"p","props":{"align":{"type":{"enum":["start","center"]},"required":false,"target":{"attribute":"align"},"description":"Aligns the text within its line.","default":"start"},"as":{"type":{"enum":["p","span","div","small","strong","label"]},"required":false,"target":{"attribute":"as"},"description":"The native element the text renders: a paragraph by default, inline span, small, or strong within a line, a div for a block, or a label for a\n control.","default":"p"},"size":{"type":{"enum":["inherit","xs","sm","md","lg"]},"required":false,"target":{"attribute":"size"},"description":"The step on the type scale. inherit (the default) keeps the size of the text around it; xs is for fine print, sm for supporting text such as help and\n metadata, md is body text, and lg is a lead paragraph.","default":"inherit"},"tone":{"type":{"enum":["default","secondary","muted","accent","danger","success"]},"required":false,"target":{"attribute":"tone"},"description":"The text's colour, by meaning. secondary is supporting prose such as a description; muted is quieter still, for metadata and hints; accent draws the eye;\n danger states an error; success confirms one.","default":"default"},"truncate":{"type":"boolean","required":false,"target":{"attribute":"truncate"},"description":"Keeps the text on one line, ending in an ellipsis when it does not fit.","default":false},"variant":{"type":{"enum":["body","eyebrow","code"]},"required":false,"target":{"attribute":"variant"},"description":"body is running text. eyebrow is a short, uppercase, tracked label that names what follows, such as a group of links; code sets a value to copy or read\n exactly, such as an address, in the monospace face.","default":"body"},"weight":{"type":{"enum":["inherit","normal","medium","semibold"]},"required":false,"target":{"attribute":"weight"},"description":"The weight. inherit keeps the surrounding weight; medium and semibold emphasise a name or a figure.","default":"inherit"}}},"template":{"kind":"element","name":"template","attributes":[],"children":[{"kind":"element","name":"span","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'span'","testPlan":{"source":"as = 'span'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"span"}},"dependencies":["as"]}}},{"kind":"element","name":"div","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'div'","testPlan":{"source":"as = 'div'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"div"}},"dependencies":["as"]}}},{"kind":"element","name":"small","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'small'","testPlan":{"source":"as = 'small'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"small"}},"dependencies":["as"]}}},{"kind":"element","name":"strong","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'strong'","testPlan":{"source":"as = 'strong'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"strong"}},"dependencies":["as"]}}},{"kind":"element","name":"label","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'label'","testPlan":{"source":"as = 'label'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"label"}},"dependencies":["as"]}}},{"kind":"element","name":"p","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"else"}}],"flow":{"kind":"match"}},"css":"/* Running text, set on the type scale and in a tone that says what it is, so a view never styles\n text of its own. The root is a paragraph unless as= names a span, div, small, strong, or label. */\n :host {\n margin: 0;\n min-inline-size: 0;\n color: var(--ui-text-primary);\n text-align: start;\n }\n\n :host-state([size=\"xs\"]) {\n font-size: var(--ui-font-size-xs);\n line-height: var(--ui-line-height);\n }\n :host-state([size=\"sm\"]) {\n font-size: var(--ui-font-size-sm);\n line-height: var(--ui-line-height);\n }\n :host-state([size=\"md\"]) {\n font-size: var(--ui-font-size-md);\n line-height: var(--ui-line-height);\n }\n :host-state([size=\"lg\"]) {\n font-size: var(--ui-font-size-lg);\n line-height: var(--ui-line-height-relaxed);\n }\n\n :host-state([tone=\"secondary\"]) {\n color: var(--ui-text-secondary);\n }\n :host-state([tone=\"muted\"]) {\n color: var(--ui-text-muted);\n }\n :host-state([tone=\"accent\"]) {\n color: var(--ui-accent-active);\n }\n :host-state([tone=\"danger\"]) {\n color: var(--ui-danger);\n }\n :host-state([tone=\"success\"]) {\n color: var(--ui-success);\n }\n\n :host-state([weight=\"normal\"]) {\n font-weight: var(--ui-font-normal);\n }\n :host-state([weight=\"medium\"]) {\n font-weight: var(--ui-font-medium);\n }\n :host-state([weight=\"semibold\"]) {\n font-weight: var(--ui-font-semibold);\n }\n\n :host-state([variant=\"eyebrow\"]) {\n font-size: var(--ui-font-size-xs);\n font-weight: var(--ui-font-semibold);\n letter-spacing: 0.06em;\n text-transform: uppercase;\n }\n :host-state([variant=\"code\"]) {\n font-family: var(--ui-font-family-mono);\n }\n\n /* A link in running text is underlined, so it stands apart from the words around it by more than\n colour. */\n :host :slotted(a) {\n color: var(--ui-accent-active);\n text-decoration: underline;\n text-decoration-thickness: 0.06em;\n text-underline-offset: 0.18em;\n }\n\n :host-state([truncate]) {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n :host-state([align=\"center\"]) {\n text-align: center;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"p","choices":["span","div","small","strong","label","p"]}},{"source":{"file":"./components/ui-textarea/ui-textarea.html"},"contract":{"version":1,"name":"UiTextarea","tag":"ui-textarea","nativeElement":"textarea","props":{"disabled":{"type":"boolean","required":false,"target":{"attribute":"disabled"},"description":"Prevents editing and form submission.","default":false},"invalid":{"type":"boolean","required":false,"target":{"attribute":"aria-invalid"},"description":"Exposes invalid state to assistive technology and styling.","default":false},"readonly":{"type":"boolean","required":false,"target":{"attribute":"readonly"},"description":"Allows selection without allowing edits.","default":false},"required":{"type":"boolean","required":false,"target":{"attribute":"required"},"description":"Marks the control as required for form validation.","default":false},"rows":{"type":{"kind":"terminal","name":"integer"},"required":false,"target":{"attribute":"rows"},"description":"Initial number of visible text rows.","default":4},"value":{"type":"string","required":false,"target":{"attribute":"value"},"description":"The textarea's text. Setting or changing it replaces the live text; between changes the user's typing stands, so follow input events to keep it in step. It\n is also the textarea's default, so a form reset returns to it."}}},"template":{"kind":"element","name":"textarea","attributes":[{"kind":"attribute","name":"value","expression":"value","expressionPlan":{"source":"value","ast":{"kind":"id","name":"value"},"dependencies":["value"]}},{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}},{"kind":"attribute","name":"readonly","expression":"readonly","expressionPlan":{"source":"readonly","ast":{"kind":"id","name":"readonly"},"dependencies":["readonly"]}},{"kind":"attribute","name":"required","expression":"required","expressionPlan":{"source":"required","ast":{"kind":"id","name":"required"},"dependencies":["required"]}},{"kind":"attribute","name":"aria-invalid","expression":"invalid","expressionPlan":{"source":"invalid","ast":{"kind":"id","name":"invalid"},"dependencies":["invalid"]}},{"kind":"attribute","name":"rows","expression":"rows","expressionPlan":{"source":"rows","ast":{"kind":"id","name":"rows"},"dependencies":["rows"]}}],"children":[]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-textarea-focus-shadow {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-textarea-radius {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-textarea-shadow {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n box-sizing: border-box;\n display: inline-block;\n inline-size: 100%;\n min-inline-size: 0;\n min-block-size: calc(3rem * 2);\n margin: 0;\n padding: var(--ui-space-2) var(--ui-space-3);\n appearance: none;\n resize: vertical;\n border: 1px solid var(--ui-control-border, var(--ui-border-strong));\n border-radius: var(--ui-textarea-radius, var(--ui-radius-md));\n background: var(--ui-control-surface, var(--ui-surface-elevated));\n color: var(--ui-text-primary);\n font: inherit;\n line-height: var(--ui-line-height-md);\n box-shadow: var(--ui-textarea-shadow, var(--ui-control-inset));\n transition:\n border-color var(--ui-motion-fast) var(--ui-motion-ease),\n box-shadow var(--ui-motion-fast) var(--ui-motion-ease),\n background-color var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n /* Tabbing into a field selects its text; tint that selection softly instead of the page highlight. */\n :host::selection {\n background: color-mix(in srgb, var(--ui-accent-solid) 20%, transparent);\n color: inherit;\n }\n\n :host::placeholder {\n color: var(--ui-control-placeholder, var(--ui-text-secondary));\n opacity: 1;\n }\n\n :host:hover:not(:focus):not(:disabled) {\n border-color: var(--ui-control-border-hover, var(--ui-text-secondary));\n }\n\n :host:focus-visible {\n border-color: var(--ui-control-focus, var(--ui-accent-solid));\n outline: none;\n box-shadow: var(--ui-textarea-focus-shadow, var(--ui-control-inset), var(--ui-control-focus-halo-shadow));\n }\n\n /* The app's invalid flag, or the browser's own verdict once the user has left an invalid field. */\n :host[aria-invalid=\"true\"],\n :host:user-invalid {\n border-color: var(--ui-danger-solid);\n }\n\n :host:is([aria-invalid=\"true\"], :user-invalid):focus-visible {\n box-shadow:\n var(--ui-control-inset),\n 0 0 0 3px color-mix(in srgb, var(--ui-danger-solid) 22%, transparent);\n }\n\n :host:disabled {\n background: var(--ui-control-surface-disabled, var(--ui-surface-muted));\n color: var(--ui-disabled-text);\n box-shadow: none;\n cursor: not-allowed;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[],"root":{"kind":"native","element":"textarea","choices":["textarea"]},"controller":"./components/ui-textarea/ui-textarea.js"},{"source":{"file":"./components/ui-toast-region/ui-toast-region.html"},"contract":{"version":1,"name":"UiToastRegion","tag":"ui-toast-region","nativeElement":"div","props":{"auto":{"type":"boolean","required":false,"target":{"attribute":"auto"},"description":"Dismiss each message automatically after its duration. Timers pause while the pointer or focus is on a message.","default":false},"duration":{"type":"number","required":false,"target":{"attribute":"duration"},"description":"Milliseconds an automatically dismissed message stays visible.","default":5000},"message":{"type":"string","required":false,"target":{"attribute":"message"},"description":"Fallback message used by the declarative show command.","default":"Notification"},"open":{"type":"boolean","required":false,"target":{"attribute":"open"},"description":"Whether the messages authored inside the region are visible.","default":false}}},"template":{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"role","value":"region"},{"kind":"literal","name":"aria-label","value":"Notifications"},{"kind":"literal","name":"aria-live","value":"polite"},{"kind":"literal","name":"popover","value":"manual"}],"children":[{"kind":"slot"},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"toast"},{"kind":"attribute","name":"closing","expression":"toast.closing","expressionPlan":{"source":"toast.closing","ast":{"kind":"member","object":{"kind":"id","name":"toast"},"key":"closing"},"dependencies":["toast.closing"]},"target":"class"},{"kind":"attribute","name":"id","expression":"toast.id","expressionPlan":{"source":"toast.id","ast":{"kind":"member","object":{"kind":"id","name":"toast"},"key":"id"},"dependencies":["toast.id"]}},{"kind":"attribute","name":"role","expression":"toast.role","expressionPlan":{"source":"toast.role","ast":{"kind":"member","object":{"kind":"id","name":"toast"},"key":"role"},"dependencies":["toast.role"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"message"},{"kind":"directive","name":"value","expression":"toast.message","expressionPlan":{"source":"toast.message","ast":{"kind":"member","object":{"kind":"id","name":"toast"},"key":"message"},"dependencies":["toast.message"]}}],"children":[]},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"dismiss"},{"kind":"attribute","name":"data-toast","expression":"toast.id","expressionPlan":{"source":"toast.id","ast":{"kind":"member","object":{"kind":"id","name":"toast"},"key":"id"},"dependencies":["toast.id"]}}],"children":[{"kind":"element","name":"ui-icon-button","attributes":[{"kind":"literal","name":"size","value":"sm"},{"kind":"literal","name":"variant","value":"ghost"},{"kind":"attribute","name":"round","expression":"true","expressionPlan":{"source":"true","ast":{"kind":"literal","value":true},"dependencies":[]}},{"kind":"attribute","name":"label","expression":"format('Dismiss %s', toast.message)","expressionPlan":{"source":"format('Dismiss %s', toast.message)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"Dismiss %s"},{"kind":"member","object":{"kind":"id","name":"toast"},"key":"message"}]},"dependencies":["toast.message"]}}],"children":[{"kind":"element","name":"svg","attributes":[{"kind":"literal","name":"viewBox","value":"0 0 24 24"},{"kind":"literal","name":"fill","value":"none"},{"kind":"literal","name":"stroke","value":"currentColor"},{"kind":"literal","name":"stroke-width","value":"2"},{"kind":"literal","name":"stroke-linecap","value":"round"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[{"kind":"element","name":"path","attributes":[{"kind":"literal","name":"d","value":"M18 6 6 18M6 6l12 12"}],"children":[]}]}]}]}],"flow":{"kind":"each","item":"toast","list":"toasts","listPlan":{"source":"toasts","ast":{"kind":"id","name":"toasts"},"dependencies":["toasts"]},"key":"toast.id","keyPlan":{"source":"toast.id","ast":{"kind":"member","object":{"kind":"id","name":"toast"},"key":"id"},"dependencies":["toast.id"]}}}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-toast-region-enter-duration {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-toast-region-exit-duration {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-toast-region-enter-duration: var(--ui-toast-region-enter-duration);\n --_ui-toast-region-exit-duration: var(--ui-toast-region-exit-duration);\n\n position: fixed;\n top: calc(var(--ui-space-4) + env(safe-area-inset-top));\n right: auto;\n bottom: auto;\n left: 50%;\n transform: translateX(-50%);\n z-index: 9999;\n display: grid;\n gap: var(--ui-space-2);\n inline-size: min(24rem, calc(100vw - var(--ui-space-4) * 2));\n max-inline-size: 100%;\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n overflow: visible;\n border: 0;\n outline: 0;\n background: transparent;\n box-shadow: none;\n pointer-events: none;\n }\n\n :host:not(:popover-open) {\n display: none;\n }\n\n :host > .toast,\n :host > :slotted(*) {\n pointer-events: auto;\n }\n\n .toast {\n display: grid;\n grid-template-columns: 1fr auto;\n gap: var(--ui-space-2);\n align-items: start;\n border: 1px solid var(--ui-border-default);\n border-radius: var(--ui-radius-lg);\n padding: var(--ui-space-3) var(--ui-space-4);\n background: var(--ui-surface-elevated);\n color: var(--ui-text-primary);\n box-shadow: var(--ui-elevation-overlay, var(--ui-shadow-lg));\n animation: ui-toast-enter var(--_ui-toast-region-enter-duration, 0.32s) var(--ui-motion-ease-out, cubic-bezier(0.16, 1, 0.3, 1)) both;\n }\n\n /* Leaving slides on down and fades; the controller removes the toast when this ends. */\n .toast.closing {\n animation: ui-toast-exit var(--_ui-toast-region-exit-duration, 0.22s) var(--ui-motion-ease) both;\n pointer-events: none;\n }\n\n @keyframes ui-toast-enter {\n from {\n opacity: 0;\n transform: translateY(-1rem);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n @keyframes ui-toast-exit {\n from {\n opacity: 1;\n transform: translateY(0);\n }\n to {\n opacity: 0;\n transform: translateY(0.75rem);\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .toast, .toast.closing {\n animation: none;\n }\n }\n\n .message {\n min-inline-size: 0;\n align-self: center;\n }\n\n .dismiss {\n align-self: center;\n margin-inline-end: calc(var(--ui-space-2) * -1);\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"internalOpen","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"toasts","type":"list(object({ id: string, message: string, role: alert | status, closing: boolean }))","expression":{"source":"[]","ast":{"kind":"array","items":[]},"dependencies":[]}},{"kind":"event","name":"close","type":"object({ open: boolean, reason: action | timeout | programmatic | light-dismiss | escape, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"dismiss","type":"object({ id: string, reason: action | timeout, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"method","name":"show","exportName":"show","returns":"promise(string)"}],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-toast-region/ui-toast-region.js"},{"source":{"file":"./components/ui-tooltip/ui-tooltip.html"},"contract":{"version":1,"name":"UiTooltip","tag":"ui-tooltip","nativeElement":"span","props":{"for":{"type":"string","required":false,"target":{"attribute":"for"},"description":"ID of the control described and visually anchored by the tooltip.","default":""},"hideDelay":{"type":"number","required":false,"target":{"attribute":"hidedelay"},"description":"Waits this many milliseconds before hiding after pointer exit.","default":100},"inverse":{"type":"boolean","required":false,"target":{"attribute":"inverse"},"description":"Use the high-contrast inverse surface (dark on light themes, light on dark themes).","default":false},"open":{"type":"boolean","required":false,"target":{"attribute":"open"},"description":"Whether the tooltip is open initially or when set externally.","default":false},"placement":{"type":"string","required":false,"target":{"attribute":"placement"},"description":"Positions the description relative to its trigger.","default":"top-start"},"showDelay":{"type":"number","required":false,"target":{"attribute":"showdelay"},"description":"Waits this many milliseconds before showing after pointer entry.","default":500},"trigger":{"type":{"enum":["hover","click","focus"]},"required":false,"target":{"attribute":"trigger"},"description":"How the trigger opens it. hover also opens on keyboard focus; click toggles it and suits a help button, where hovering a question mark says nothing; focus\n opens only while the trigger holds focus.","default":"hover"}}},"template":{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"role","value":"tooltip"},{"kind":"attribute","name":"hidden","expression":"not internalOpen","expressionPlan":{"source":"not internalOpen","ast":{"kind":"unary","op":"not","operand":{"kind":"id","name":"internalOpen"}},"dependencies":["internalOpen"]}}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"surface"}],"children":[{"kind":"slot"}]}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-tooltip-arrow-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-tooltip-border {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-tooltip-inverse-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-tooltip-inverse-text {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-tooltip-max-inline-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-tooltip-radius {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-tooltip-shadow {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-tooltip-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-tooltip-text {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-tooltip-border: var(--ui-tooltip-border);\n --_ui-tooltip-max-inline-size: var(--ui-tooltip-max-inline-size);\n --_ui-tooltip-radius: var(--ui-tooltip-radius);\n --_ui-tooltip-surface: var(--ui-tooltip-surface);\n --_ui-tooltip-text: var(--ui-tooltip-text);\n --_ui-tooltip-shadow: var(--ui-tooltip-shadow);\n --_ui-tooltip-inverse-surface: var(--ui-tooltip-inverse-surface);\n --_ui-tooltip-inverse-text: var(--ui-tooltip-inverse-text);\n --_ui-tooltip-arrow-size: var(--ui-tooltip-arrow-size);\n\n position: fixed;\n inset: auto;\n margin: 0;\n display: inline-block;\n box-sizing: border-box;\n padding: 0;\n border: 0;\n outline: 0;\n border-radius: 0;\n background: transparent;\n /* The UA popover default (overflow: auto) would clip the arrow. */\n overflow: visible;\n opacity: 0;\n transform: translateY(4px);\n transition:\n opacity var(--ui-motion-fast) var(--ui-motion-ease),\n transform var(--ui-motion-fast) var(--ui-motion-ease),\n display var(--ui-motion-fast) allow-discrete,\n overlay var(--ui-motion-fast) allow-discrete;\n }\n\n .surface {\n --_tooltip-line: var(--_ui-tooltip-border, var(--ui-border-default));\n position: relative;\n box-sizing: border-box;\n max-inline-size: var(--_ui-tooltip-max-inline-size, 18rem);\n border: 1px solid var(--_tooltip-line);\n border-radius: var(--_ui-tooltip-radius, var(--ui-radius-sm));\n background: var(--_ui-tooltip-surface, var(--ui-surface-elevated));\n color: var(--_ui-tooltip-text, var(--ui-text-primary));\n padding: var(--ui-space-1) var(--ui-space-2);\n font-family: var(--ui-font-family-sans);\n font-size: var(--ui-font-size-sm);\n line-height: var(--ui-line-height-tight);\n box-shadow: var(--_ui-tooltip-shadow, var(--ui-elevation-tooltip, var(--ui-shadow-md)));\n }\n\n :host-state([inverse]) .surface {\n --_tooltip-line: var(--_ui-tooltip-inverse-surface, var(--ui-text-primary));\n background: var(--_ui-tooltip-inverse-surface, var(--ui-text-primary));\n color: var(--_ui-tooltip-inverse-text, var(--ui-surface-default));\n }\n\n /* A rotated square shares the surface fill and draws the two outward border edges. Its centre sits on\n * the surface border line, so the fill covers that stretch of border and the outline runs unbroken. */\n .surface::after {\n content: \"\";\n position: absolute;\n z-index: 1;\n inset-inline-start: var(--ui-space-3);\n inset-block-end: calc(var(--_ui-tooltip-arrow-size, 0.5rem) / -2 - 0.5px);\n inline-size: var(--_ui-tooltip-arrow-size, 0.5rem);\n block-size: var(--_ui-tooltip-arrow-size, 0.5rem);\n box-sizing: border-box;\n background: inherit;\n border: 0 solid var(--_tooltip-line);\n border-inline-end-width: 1px;\n border-block-end-width: 1px;\n border-end-end-radius: 1px;\n transform: rotate(45deg);\n }\n\n :is(:host-state([placement=\"bottom\"]), :host-state([placement=\"bottom-start\"]), :host-state([placement=\"bottom-end\"])) .surface::after {\n inset-block-start: calc(var(--_ui-tooltip-arrow-size, 0.5rem) / -2 - 0.5px);\n inset-block-end: auto;\n border-inline-end-width: 0;\n border-block-end-width: 0;\n border-inline-start-width: 1px;\n border-block-start-width: 1px;\n border-end-end-radius: 0;\n border-start-start-radius: 1px;\n }\n\n :is(:host-state([placement=\"top-end\"]), :host-state([placement=\"bottom-end\"])) .surface::after {\n inset-inline-start: auto;\n inset-inline-end: var(--ui-space-3);\n }\n\n :host:popover-open {\n opacity: 1;\n transform: translateY(0);\n }\n\n @starting-style {\n :host:popover-open {\n opacity: 0;\n transform: translateY(4px);\n }\n }\n\n :host[hidden] {\n display: none;\n }\n\n @media (prefers-reduced-motion: reduce) {\n :host {\n transition: none;\n }\n }","declarations":[{"kind":"state","name":"internalOpen","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"event","name":"open","type":"object({ open: boolean, reason: action | programmatic | light-dismiss | escape, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"close","type":"object({ open: boolean, reason: action | programmatic | light-dismiss | escape, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false}],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"span","choices":["span"]},"controller":"./components/ui-tooltip/ui-tooltip.js"},{"source":{"file":"./components/ui-top-bar/ui-top-bar.html"},"contract":{"version":1,"name":"UiTopBar","tag":"ui-top-bar","nativeElement":"header","props":{}},"template":{"kind":"element","name":"header","attributes":[],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"leading"}],"children":[{"kind":"slot","fallback":[],"name":"leading"}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"title"}],"children":[{"kind":"slot"}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"search"}],"children":[{"kind":"slot","fallback":[],"name":"search"}]},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"actions"}],"children":[{"kind":"slot","fallback":[],"name":"actions"}]}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-top-bar-actions-gap {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-top-bar-border {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-top-bar-gap {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-top-bar-height {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-top-bar-padding-inline {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-top-bar-surface {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-top-bar-z-index {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. */\n --_ui-top-bar-actions-gap: var(--ui-top-bar-actions-gap);\n\n position: sticky;\n inset-block-start: 0;\n z-index: var(--ui-top-bar-z-index, 100);\n min-block-size: calc(var(--ui-top-bar-height, 56px) + env(safe-area-inset-top));\n display: flex;\n align-items: center;\n gap: var(--ui-top-bar-gap, var(--ui-space-3));\n padding-block-start: env(safe-area-inset-top);\n padding-inline-start: max(var(--ui-top-bar-padding-inline, var(--ui-space-4)), env(safe-area-inset-left));\n padding-inline-end: max(var(--ui-top-bar-padding-inline, var(--ui-space-4)), env(safe-area-inset-right));\n background: var(--ui-top-bar-surface, var(--ui-surface-elevated));\n border-block-end: 1px solid var(--ui-top-bar-border, var(--ui-border-default));\n }\n\n .leading,\n .search,\n .actions {\n display: flex;\n align-items: center;\n flex-shrink: 0;\n }\n\n .actions {\n gap: var(--_ui-top-bar-actions-gap, var(--ui-space-1));\n }\n\n .title {\n min-inline-size: 0;\n flex: 1;\n }\n\n /* An unused region takes no space, so it adds no gap. */\n .leading:empty,\n .search:empty,\n .actions:empty {\n display: none;\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[],"slots":[{"dynamic":false,"required":true,"name":"leading"},{"dynamic":false,"required":true},{"dynamic":false,"required":true,"name":"search"},{"dynamic":false,"required":true,"name":"actions"}],"root":{"kind":"native","element":"header","choices":["header"]}},{"source":{"file":"./components/ui-tree-item/ui-tree-item.html"},"contract":{"version":1,"name":"UiTreeItem","tag":"ui-tree-item","nativeElement":"div","props":{"accepts":{"type":"string","required":false,"target":{"attribute":"data-accepts"},"description":"A comma-separated list of the dragType values this branch accepts dropped inside it. Empty accepts any type. It does not affect drops before or after the\n item.","default":""},"container":{"type":"boolean","required":false,"target":{"attribute":"container"},"description":"Makes the item a branch even before it has children: it gets the expand button and aria-expanded, and accepts drops inside it. An item with nested items is\n a branch without it.","default":false},"disabled":{"type":"boolean","required":false,"target":{"attribute":"aria-disabled"},"description":"Makes the item unavailable: faded, skipped by keyboard navigation, unable to expand or be dragged, and closed to drops inside it.","default":false},"dragType":{"type":"string","required":false,"target":{"attribute":"data-drag-type"},"description":"The item's kind, for drag rules: it can be dropped before or after only items of the same type, and inside a branch only if that branch's accepts allows\n it. Reported as sourceType and targetType.","default":"item"},"dropDepth":{"type":"number","required":false,"target":{"attribute":"data-drop-depth"},"description":"Overrides the level this item counts as when the tree checks maxDepth for a drop onto it. Unset, its level in the rendered tree is used; set it when the\n item sits deeper in the real hierarchy than the rendered tree shows."},"dropScope":{"type":"string","required":false,"target":{"attribute":"data-drop-scope"},"description":"Names the list the item sits in, such as its parent's id, and is reported as sourceScope and targetScope in the tree's reorder events, so a handler can\n tell a reorder within one list from a move between lists. It never restricts where an item can be dropped; dragType and accepts do that.","default":""},"expanded":{"type":"boolean","required":false,"target":{"attribute":"expanded"},"description":"Whether the branch shows its children, initially or when set externally. The expand button, a click on the row, and the arrow keys toggle it from there,\n each reported as an expand event. Only meaningful for a branch.","default":false},"itemId":{"type":"string","required":false,"target":{"attribute":"data-item-id"},"description":"The item's identifier, reported as sourceId and targetId in the tree's reorder events and as id in its expand event. A sortable item needs one to be\n dragged, and a drop onto an item without one is not reported.","default":""},"label":{"type":"string","required":false,"target":{"attribute":"aria-label"},"description":"The item's accessible name, also shown as the row text unless the label slot supplies content.","default":""},"marquee":{"type":"boolean","required":false,"target":{"attribute":"marquee"},"description":"Scrolls a name too long for its row while the row is hovered or focused, then puts it back. Off by default: a tree of short names should not move, and a\n product decides whether reading the whole name matters more than a still list.","default":false},"selected":{"type":"boolean","required":false,"target":{"attribute":"aria-selected"},"description":"Marks the item selected: it sets aria-selected and gives the row the highlighted surface. The tree does not select on click, so drive it from your own\n state.","default":false},"sortable":{"type":"boolean","required":false,"target":{"attribute":"sortable"},"description":"Gives the item a drag handle, shown on hover, so it can be dragged to a new place in the tree. The tree reports the drop as a reorder event and leaves\n moving the item to you. Needs itemId; a disabled item, and any item under touch input, shows no handle.","default":false},"subtreeDepth":{"type":"number","required":false,"target":{"attribute":"data-subtree-depth"},"description":"Overrides how many levels sit beneath this item when the tree checks maxDepth for a drag of it. Unset, the tree counts the rendered descendants; set it\n when some are not rendered, such as children that load later."}}},"template":{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"role","value":"treeitem"},{"kind":"attribute","name":"aria-label","expression":"label","expressionPlan":{"source":"label","ast":{"kind":"id","name":"label"},"dependencies":["label"]}},{"kind":"attribute","name":"aria-level","expression":"structuralLevel","expressionPlan":{"source":"structuralLevel","ast":{"kind":"id","name":"structuralLevel"},"dependencies":["structuralLevel"]}},{"kind":"attribute","name":"aria-selected","expression":"selected","expressionPlan":{"source":"selected","ast":{"kind":"id","name":"selected"},"dependencies":["selected"]}},{"kind":"attribute","name":"aria-disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}},{"kind":"attribute","name":"data-item-id","expression":"itemId","expressionPlan":{"source":"itemId","ast":{"kind":"id","name":"itemId"},"dependencies":["itemId"]}},{"kind":"attribute","name":"data-drag-type","expression":"dragType","expressionPlan":{"source":"dragType","ast":{"kind":"id","name":"dragType"},"dependencies":["dragType"]}},{"kind":"attribute","name":"data-drop-scope","expression":"dropScope","expressionPlan":{"source":"dropScope","ast":{"kind":"id","name":"dropScope"},"dependencies":["dropScope"]}},{"kind":"attribute","name":"data-accepts","expression":"accepts","expressionPlan":{"source":"accepts","ast":{"kind":"id","name":"accepts"},"dependencies":["accepts"]}},{"kind":"attribute","name":"data-drop-depth","expression":"dropDepth","expressionPlan":{"source":"dropDepth","ast":{"kind":"id","name":"dropDepth"},"dependencies":["dropDepth"]}},{"kind":"attribute","name":"data-subtree-depth","expression":"subtreeDepth","expressionPlan":{"source":"subtreeDepth","ast":{"kind":"id","name":"subtreeDepth"},"dependencies":["subtreeDepth"]}}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"row"}],"children":[{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"class","value":"drag-handle"},{"kind":"literal","name":"type","value":"button"},{"kind":"literal","name":"draggable","value":"true"},{"kind":"attribute","name":"aria-label","expression":"format('Drag %s to reorder', label)","expressionPlan":{"source":"format('Drag %s to reorder', label)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"Drag %s to reorder"},{"kind":"id","name":"label"}]},"dependencies":["label"]}}],"children":[{"kind":"element","name":"svg","attributes":[{"kind":"literal","name":"aria-hidden","value":"true"},{"kind":"literal","name":"focusable","value":"false"},{"kind":"literal","name":"viewBox","value":"0 0 24 24"},{"kind":"literal","name":"fill","value":"none"},{"kind":"literal","name":"stroke","value":"currentColor"},{"kind":"literal","name":"stroke-width","value":"2"},{"kind":"literal","name":"stroke-linecap","value":"round"},{"kind":"literal","name":"stroke-linejoin","value":"round"}],"children":[{"kind":"element","name":"circle","attributes":[{"kind":"literal","name":"cx","value":"9"},{"kind":"literal","name":"cy","value":"12"},{"kind":"literal","name":"r","value":"1"}],"children":[]},{"kind":"element","name":"circle","attributes":[{"kind":"literal","name":"cx","value":"9"},{"kind":"literal","name":"cy","value":"5"},{"kind":"literal","name":"r","value":"1"}],"children":[]},{"kind":"element","name":"circle","attributes":[{"kind":"literal","name":"cx","value":"9"},{"kind":"literal","name":"cy","value":"19"},{"kind":"literal","name":"r","value":"1"}],"children":[]},{"kind":"element","name":"circle","attributes":[{"kind":"literal","name":"cx","value":"15"},{"kind":"literal","name":"cy","value":"12"},{"kind":"literal","name":"r","value":"1"}],"children":[]},{"kind":"element","name":"circle","attributes":[{"kind":"literal","name":"cx","value":"15"},{"kind":"literal","name":"cy","value":"5"},{"kind":"literal","name":"r","value":"1"}],"children":[]},{"kind":"element","name":"circle","attributes":[{"kind":"literal","name":"cx","value":"15"},{"kind":"literal","name":"cy","value":"19"},{"kind":"literal","name":"r","value":"1"}],"children":[]}]}],"flow":{"kind":"if","test":"sortable and not disabled","testPlan":{"source":"sortable and not disabled","ast":{"kind":"binary","op":"and","left":{"kind":"id","name":"sortable"},"right":{"kind":"unary","op":"not","operand":{"kind":"id","name":"disabled"}}},"dependencies":["disabled","sortable"]}},"ref":"dragHandle"},{"kind":"element","name":"button","attributes":[{"kind":"literal","name":"class","value":"disclosure"},{"kind":"literal","name":"type","value":"button"},{"kind":"attribute","name":"disabled","expression":"disabled","expressionPlan":{"source":"disabled","ast":{"kind":"id","name":"disabled"},"dependencies":["disabled"]}},{"kind":"attribute","name":"hidden","expression":"not isContainer","expressionPlan":{"source":"not isContainer","ast":{"kind":"unary","op":"not","operand":{"kind":"id","name":"isContainer"}},"dependencies":["isContainer"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"disclosure-icon"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[]}],"ref":"disclosure"},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"leading"}],"children":[{"kind":"slot","fallback":[],"name":"leading"}],"ref":"leading"},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"label"}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"label-text"}],"children":[{"kind":"slot","fallback":[{"kind":"element","name":"template","attributes":[{"kind":"directive","name":"value","expression":"label","expressionPlan":{"source":"label","ast":{"kind":"id","name":"label"},"dependencies":["label"]}}],"children":[]}],"name":"label"}],"ref":"labelText"}],"ref":"label"},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"actions"}],"children":[{"kind":"slot","fallback":[],"name":"actions"}],"ref":"actions"},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"drop-indicator row-drop-indicator"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[]}],"ref":"row"},{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"children"},{"kind":"literal","name":"role","value":"group"},{"kind":"attribute","name":"hidden","expression":"not (isContainer and internalExpanded)","expressionPlan":{"source":"not (isContainer and internalExpanded)","ast":{"kind":"unary","op":"not","operand":{"kind":"binary","op":"and","left":{"kind":"id","name":"isContainer"},"right":{"kind":"id","name":"internalExpanded"}}},"dependencies":["internalExpanded","isContainer"]}}],"children":[{"kind":"slot"}],"ref":"children"},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"drop-indicator subtree-drop-indicator"},{"kind":"literal","name":"aria-hidden","value":"true"}],"children":[]}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-tree-item-depth {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-tree-item-font-size {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-tree-item-label-padding-block {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-tree-item-label-padding-inline {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-tree-item-min-block-size {\n syntax: \"*\";\n inherits: false;\n }\n\n :host {\n /* Hooks do not inherit, so the parts below read them from the root. The tree's density\n sets the defaults, in --_ui-default-*. */\n --_ui-tree-item-min-block-size: var(--ui-tree-item-min-block-size, var(--_ui-default-tree-item-min-block-size));\n --_ui-tree-item-font-size: var(--ui-tree-item-font-size, var(--_ui-default-tree-item-font-size));\n --_ui-tree-item-label-padding-block: var(--ui-tree-item-label-padding-block, var(--_ui-default-tree-item-label-padding-block));\n --_ui-tree-item-label-padding-inline: var(--ui-tree-item-label-padding-inline);\n\n --_tree-row-min-height: 32px;\n --_tree-disclosure-size: 16px;\n\n position: relative;\n display: block;\n min-inline-size: 0;\n margin-inline-start: calc(var(--ui-tree-item-depth, 0) * var(--_ui-tree-indent, 16px));\n }\n\n .row {\n position: relative;\n display: grid;\n grid-template-columns: var(--_tree-disclosure-size) auto minmax(0, 1fr);\n align-items: center;\n min-block-size: var(--_ui-tree-item-min-block-size, var(--_tree-row-min-height));\n min-inline-size: 0;\n font-size: var(--_ui-tree-item-font-size, var(--ui-font-size-sm));\n border-radius: var(--ui-radius-md);\n color: var(--ui-text-secondary);\n transition:\n background-color var(--ui-motion-fast) var(--ui-motion-ease),\n color var(--ui-motion-fast) var(--ui-motion-ease),\n opacity var(--ui-motion-fast) var(--ui-motion-ease),\n box-shadow var(--ui-motion-fast) var(--ui-motion-ease),\n min-block-size var(--ui-motion-base) var(--ui-motion-ease);\n }\n\n .row:hover,\n :host-state([selected]) .row,\n .row:focus-within {\n color: var(--ui-text-primary);\n background: var(--ui-surface-muted);\n }\n\n :host-state([disabled]) .row {\n opacity: 0.55;\n }\n\n :host[data-dragging] .row {\n opacity: 0.42;\n }\n\n :host:focus {\n outline: none;\n }\n\n :host:focus-visible .row {\n box-shadow: 0 0 0 2px var(--ui-focus-ring);\n }\n\n /* Child combinators: drop feedback belongs to this item's own row, not the rows nested in it. */\n :host[data-drop-position=\"inside\"] > .row {\n background: var(--ui-accent-subtle);\n box-shadow: inset 0 0 0 1px var(--_ui-tree-drop-color, var(--ui-accent-solid));\n }\n\n .disclosure,\n .disclosure-spacer {\n grid-column: 1;\n grid-row: 1;\n inline-size: var(--_tree-disclosure-size);\n block-size: 28px;\n }\n\n .disclosure {\n display: grid;\n /* Start-aligned: the chevron's ink, not its hit area, aligns with the content above it. */\n place-items: center start;\n padding: 0;\n color: var(--ui-text-muted);\n background: transparent;\n border: 0;\n border-radius: var(--ui-radius-sm);\n cursor: pointer;\n }\n\n .disclosure[hidden] {\n display: none;\n }\n\n .disclosure:hover {\n color: var(--ui-text-primary);\n background: var(--ui-surface-elevated);\n }\n\n .disclosure-icon {\n display: grid;\n place-items: center;\n inline-size: 12px;\n block-size: 12px;\n transform: rotate(-90deg);\n transition: transform var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n .disclosure-icon::before {\n display: block;\n inline-size: 0.375rem;\n block-size: 0.375rem;\n border-inline-end: 1.5px solid currentColor;\n border-block-end: 1.5px solid currentColor;\n content: \"\";\n /* A chevron's ink sits below its box centre; lift it so it centres optically (in either rotation). */\n transform: translateY(-20%) rotate(45deg);\n }\n\n :host[aria-expanded=\"true\"] .disclosure-icon {\n transform: rotate(0deg);\n }\n\n /* Lucide grip-vertical, filling the handle as in Looma 0.2. */\n .drag-handle svg {\n display: block;\n inline-size: 100%;\n block-size: 100%;\n }\n\n /* Slotted content is outside this scope, so :has() cannot see it; hide only a truly empty slot. */\n .leading {\n display: inline-grid;\n place-items: center;\n grid-column: 2;\n grid-row: 1;\n inline-size: 1em;\n block-size: 1em;\n margin-inline-start: var(--ui-space-1);\n color: var(--ui-text-muted);\n /* Above the label, so a sliding name passes under the icon. */\n position: relative;\n z-index: 1;\n }\n\n .leading:empty {\n display: none;\n }\n\n /* Icons match the label's size (as in Knit's tree): an unsized SVG would otherwise render 300×150. */\n :slotted(svg),\n :slotted(img) {\n display: block;\n inline-size: 1em;\n block-size: 1em;\n flex: none;\n }\n\n /* The label spans the row's height and centres its content, so slotted content (a link) can\n stretch to fill the row as its own hit area; the padding tokens remove the inset. */\n .label {\n grid-column: 3;\n grid-row: 1;\n align-self: stretch;\n display: flex;\n align-items: center;\n min-inline-size: 0;\n /* The cell clips: a name longer than the row slides inside it rather than over its icons. */\n overflow: hidden;\n padding: var(--_ui-tree-item-label-padding-block, var(--ui-space-1)) var(--_ui-tree-item-label-padding-inline, var(--ui-space-2));\n /* The length of the fade before the controls. The label's one flex child lays out no gap; this\n is where the controller reads the length in pixels to stop a sliding name before the fade. */\n column-gap: var(--ui-space-3);\n }\n\n /* Slotted label content fills the cell, so a link is the row's hit area rather than sizing to\n its own text and reading as overflow. */\n .label-text {\n display: flex;\n align-items: center;\n /* Stretches, so slotted content can still be the row's full-height hit area. */\n align-self: stretch;\n block-size: 100%;\n min-inline-size: 0;\n inline-size: 100%;\n white-space: nowrap;\n }\n\n .label-text > :slotted(*) {\n flex: 1 1 auto;\n min-inline-size: 0;\n }\n\n /* The controls sit over the label's end, so the text fades out where they begin. The fade is\n the truncation mark while it shows: an ellipsis under it would read as a second one. */\n .row:hover > .label,\n .row:focus-within > .label {\n text-overflow: clip;\n mask-image: linear-gradient(\n to right,\n #000 calc(100% - var(--_tree-actions-width, 1.75rem) - var(--ui-space-3)),\n transparent calc(100% - var(--_tree-actions-width, 1.75rem))\n );\n }\n\n .row:hover > .label:dir(rtl),\n .row:focus-within > .label:dir(rtl) {\n mask-image: linear-gradient(\n to left,\n #000 calc(100% - var(--_tree-actions-width, 1.75rem) - var(--ui-space-3)),\n transparent calc(100% - var(--_tree-actions-width, 1.75rem))\n );\n }\n\n /* A hovered row reads its whole name: the label slides far enough to show the end, waits\n there, and comes back. Only when it actually overflows — the controller measures by how\n much — after the controls have taken their place over its end — and hands over the distance\n and a duration from it, so every name moves at the same speed. */\n .row[data-ui-marquee] > .label > .label-text {\n /* Once, and it stays at the end while the pointer is there: a name that keeps sliding back\n and forth under the pointer is harder to read than one that arrives and holds. */\n animation: ui-tree-item-marquee var(--_marquee-duration) linear 0.5s 1 normal forwards;\n will-change: transform;\n }\n\n /* This comes after the hover fade, which it replaces at the same specificity. While the name\n slides, the label reaches back under the icon (the controller measures how far) with its text\n where it was, and fades out across that stretch, gone by the icon's middle: the name slips\n under the icon rather than stopping at a hard edge beside it. */\n .row[data-ui-marquee] > .label {\n margin-inline-start: calc(-1 * var(--_marquee-lead, 0px));\n padding-inline-start: calc(var(--_marquee-lead, 0px) + var(--_ui-tree-item-label-padding-inline, var(--ui-space-2)));\n mask-image: linear-gradient(\n to right,\n transparent calc(var(--_marquee-lead, 0px) / 2),\n #000 calc(var(--_marquee-lead, 0px) + var(--_ui-tree-item-label-padding-inline, var(--ui-space-2))),\n #000 calc(100% - var(--_tree-actions-width, 1.75rem) - var(--ui-space-3)),\n transparent calc(100% - var(--_tree-actions-width, 1.75rem))\n );\n }\n\n .row[data-ui-marquee] > .label:dir(rtl) {\n mask-image: linear-gradient(\n to left,\n transparent calc(var(--_marquee-lead, 0px) / 2),\n #000 calc(var(--_marquee-lead, 0px) + var(--_ui-tree-item-label-padding-inline, var(--ui-space-2))),\n #000 calc(100% - var(--_tree-actions-width, 1.75rem) - var(--ui-space-3)),\n transparent calc(100% - var(--_tree-actions-width, 1.75rem))\n );\n }\n\n @keyframes ui-tree-item-marquee {\n from {\n transform: translateX(0);\n }\n\n to {\n transform: translateX(var(--_marquee-distance));\n }\n }\n\n /* Reduced motion keeps the fade, which already says the name continues. */\n @media (prefers-reduced-motion: reduce) {\n .row[data-ui-marquee] > .label > .label-text {\n animation: none;\n }\n }\n\n .row:hover > .label > :slotted(*),\n .row:focus-within > .label > :slotted(*) {\n text-overflow: clip;\n }\n\n .actions {\n position: absolute;\n z-index: 1;\n inset-block: 0;\n inset-inline-end: 0;\n display: inline-flex;\n align-items: center;\n min-inline-size: 0;\n opacity: 0;\n pointer-events: none;\n transition: opacity var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n .row:hover > .actions,\n .row:focus-within > .actions {\n opacity: 1;\n pointer-events: auto;\n }\n\n /* Without hover there is no reveal, so the controls keep their own column. */\n @media (hover: none) {\n .row {\n grid-template-columns: var(--_tree-disclosure-size) auto minmax(0, 1fr) auto;\n }\n\n .actions {\n position: static;\n grid-column: 4;\n grid-row: 1;\n padding-inline-start: 0;\n background: none;\n opacity: 1;\n pointer-events: auto;\n }\n }\n\n /* The handle sits beside what it drags. A leaf row has no disclosure, so the handle takes that\n empty column, right before the icon; a branch's disclosure is there, so its handle sits just\n outside the row. It is bare until pointed at: a resting surface behind it read as a faint\n patch rather than as a control. */\n .drag-handle {\n position: absolute;\n z-index: 2;\n inset-block-start: 50%;\n inset-inline-start: 0;\n inline-size: var(--_tree-disclosure-size);\n block-size: 24px;\n display: grid;\n place-items: center;\n padding: 5px 2px;\n color: var(--ui-text-muted);\n background: transparent;\n border: 0;\n border-radius: var(--ui-radius-sm);\n cursor: grab;\n /* Hidden until the row is hovered, but always hittable: the handle sits outside the row, and moving\n the pointer onto it must not hide it on the way. */\n opacity: 0;\n transform: translateY(-50%);\n transition: opacity var(--ui-motion-fast) var(--ui-motion-ease);\n }\n\n .row:hover .drag-handle,\n .drag-handle:hover,\n .drag-handle:focus-visible,\n :host[data-dragging] > .row > .drag-handle {\n opacity: 1;\n }\n\n :host-state([isContainer]) > .row > .drag-handle {\n inset-inline-start: calc(-1 * var(--_tree-disclosure-size) - 2px);\n }\n\n .drag-handle:hover,\n .drag-handle:focus-visible {\n color: var(--ui-text-primary);\n background: var(--ui-surface-hover);\n }\n\n .drag-handle:active {\n cursor: grabbing;\n }\n\n .drop-indicator {\n position: absolute;\n z-index: 3;\n inset-inline: 1px;\n display: none;\n block-size: 2px;\n border-radius: 999px;\n background: var(--_ui-tree-drop-color, var(--ui-accent-solid));\n pointer-events: none;\n }\n\n .drop-indicator::before,\n .drop-indicator::after {\n content: \"\";\n position: absolute;\n inset-block-start: 50%;\n inline-size: 7px;\n block-size: 7px;\n border: 2px solid var(--_ui-tree-drop-color, var(--ui-accent-solid));\n border-radius: 999px;\n background: var(--ui-surface-elevated);\n transform: translateY(-50%);\n }\n\n .drop-indicator::before {\n inset-inline-start: -1px;\n }\n .drop-indicator::after {\n inset-inline-end: -1px;\n }\n\n :host[data-drop-position=\"before\"] > .row > .row-drop-indicator {\n display: block;\n inset-block-start: -1px;\n }\n\n :host[data-drop-position=\"after\"] > .subtree-drop-indicator {\n display: block;\n inset-block-end: -1px;\n }\n\n .children[hidden] {\n display: none;\n }\n\n html[data-ui-input-modality=\"touch\"] :host {\n --_tree-row-min-height: 44px;\n }\n\n html[data-ui-input-modality=\"touch\"] :host .drag-handle {\n display: none;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .row,\n .disclosure-icon,\n .drag-handle {\n transition: none;\n }\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"state","name":"internalExpanded","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"structuralLevel","expression":{"source":"1","ast":{"kind":"literal","value":1},"dependencies":[]}},{"kind":"state","name":"tabStop","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"isContainer","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"event","name":"expand","type":"object({ id: string, expanded: boolean, trigger: keyboard | pointer | programmatic })","bubbles":false,"composed":true,"cancelable":false}],"slots":[{"dynamic":false,"required":true,"name":"leading"},{"dynamic":false,"required":false,"name":"label"},{"dynamic":false,"required":true,"name":"actions"},{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-tree-item/ui-tree-item.js"},{"source":{"file":"./components/ui-tree/ui-tree.html"},"contract":{"version":1,"name":"UiTree","tag":"ui-tree","nativeElement":"div","props":{"density":{"type":{"enum":["comfortable","compact"]},"required":false,"target":{"attribute":"density"},"description":"Compact trades padding and type size for rows that fit more on screen.","default":"comfortable"},"hoverExpandDelay":{"type":"number","required":false,"target":{"attribute":"hoverexpanddelay"},"description":"How long, in milliseconds, a dragged item must hover over the middle of a collapsed branch before the branch opens to receive it. 0 opens it at\n once.","default":700},"label":{"type":"string","required":false,"target":{"attribute":"label"},"description":"The tree's accessible name, announced when focus enters it. Name what the tree holds.","default":"Tree"},"marquee":{"type":"boolean","required":false,"target":{"attribute":"marquee"},"description":"Scrolls a name too long for its row while that row is hovered or focused, then puts it back. Off by default: a tree of names that fit should not move. An\n item may set its own marquee to opt in or out on its own.","default":false},"maxDepth":{"type":"number","required":false,"target":{"attribute":"maxdepth"},"description":"The deepest level a drag may produce, counting the top level as 1. A drop that would place the dragged item, or any item beneath it, deeper than this is\n refused and reported as reorder-rejected. 0 means no limit.","default":0}}},"template":{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"role","value":"tree"}],"children":[{"kind":"slot"}]},"css":"/* This component's hooks style the element they are set on, and never a nested one. */\n @property --ui-tree-drop-color {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-tree-gutter {\n syntax: \"*\";\n inherits: false;\n }\n @property --ui-tree-indent {\n syntax: \"*\";\n inherits: false;\n }\n\n /* Reaches the items the way density does, so the setting lives on the tree the way a reader\n thinks about it: this list scrolls its long names. */\n :host-state([marquee]) {\n --_ui-default-tree-item-marquee: 1;\n }\n\n /* The items' defaults for this density: an item's own hook still wins. */\n :host-state([density=\"compact\"]) {\n --_ui-default-tree-item-min-block-size: var(--ui-control-size-sm);\n --_ui-default-tree-item-font-size: var(--ui-font-size-sm);\n --_ui-default-tree-item-label-padding-block: 0;\n }\n\n :host {\n /* Hooks do not inherit: the tree hands its own to its items here, and a tree nested in an item\n starts again from its own settings. */\n --_ui-tree-indent: var(--ui-tree-indent);\n --_ui-tree-drop-color: var(--ui-tree-drop-color);\n --_ui-default-tree-item-marquee: initial;\n --_ui-default-tree-item-min-block-size: initial;\n --_ui-default-tree-item-font-size: initial;\n --_ui-default-tree-item-label-padding-block: initial;\n display: block;\n min-inline-size: 0;\n padding-inline-start: var(--ui-tree-gutter, 0px);\n }\n\n /* A component that sets its display still honours the hidden attribute on its root. */\n :host[hidden] {\n display: none;\n }","declarations":[{"kind":"event","name":"reorder","type":"object({ sourceId: string, targetId: string, position: before | inside | after, sourceType: string, targetType: string, sourceScope: string, targetScope: string, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"reorder-rejected","type":"object({ sourceId: string, targetId: string, position: before | inside | after, reason: max-depth, maxDepth: integer, resultingDepth: integer, trigger: keyboard | pointer | programmatic })","bubbles":true,"composed":true,"cancelable":false}],"slots":[{"dynamic":false,"required":true}],"root":{"kind":"native","element":"div","choices":["div"]},"controller":"./components/ui-tree/ui-tree.js"}];
|
|
4
4
|
const controllerImports = {
|
|
5
5
|
"ui-affordance-scope": () => import("../components/ui-affordance-scope/ui-affordance-scope.js"), // controller 1
|
|
6
6
|
"ui-avatar-group": () => import("../components/ui-avatar-group/ui-avatar-group.js"), // controller 2
|
|
@@ -19,23 +19,22 @@ const controllerImports = {
|
|
|
19
19
|
"ui-editor-table-toolbar": () => import("../components/ui-editor-table-toolbar/ui-editor-table-toolbar.js"), // controller 15
|
|
20
20
|
"ui-form-field": () => import("../components/ui-form-field/ui-form-field.js"), // controller 16
|
|
21
21
|
"ui-icon-button": () => import("../components/ui-icon-button/ui-icon-button.js"), // controller 17
|
|
22
|
-
"ui-
|
|
23
|
-
"ui-input
|
|
24
|
-
"ui-
|
|
25
|
-
"ui-
|
|
26
|
-
"ui-
|
|
27
|
-
"ui-radio
|
|
28
|
-
"ui-
|
|
29
|
-
"ui-
|
|
30
|
-
"ui-
|
|
31
|
-
"ui-
|
|
32
|
-
"ui-
|
|
33
|
-
"ui-
|
|
34
|
-
"ui-
|
|
35
|
-
"ui-
|
|
36
|
-
"ui-
|
|
37
|
-
"ui-tree
|
|
38
|
-
"ui-tree": () => import("../components/ui-tree/ui-tree.js"), // controller 34
|
|
22
|
+
"ui-input-group": () => import("../components/ui-input-group/ui-input-group.js"), // controller 18
|
|
23
|
+
"ui-input": () => import("../components/ui-input/ui-input.js"), // controller 19
|
|
24
|
+
"ui-menu": () => import("../components/ui-menu/ui-menu.js"), // controller 20
|
|
25
|
+
"ui-popover": () => import("../components/ui-popover/ui-popover.js"), // controller 21
|
|
26
|
+
"ui-radio-group": () => import("../components/ui-radio-group/ui-radio-group.js"), // controller 22
|
|
27
|
+
"ui-radio": () => import("../components/ui-radio/ui-radio.js"), // controller 23
|
|
28
|
+
"ui-search-shell": () => import("../components/ui-search-shell/ui-search-shell.js"), // controller 24
|
|
29
|
+
"ui-select": () => import("../components/ui-select/ui-select.js"), // controller 25
|
|
30
|
+
"ui-sidebar": () => import("../components/ui-sidebar/ui-sidebar.js"), // controller 26
|
|
31
|
+
"ui-switch": () => import("../components/ui-switch/ui-switch.js"), // controller 27
|
|
32
|
+
"ui-tabs": () => import("../components/ui-tabs/ui-tabs.js"), // controller 28
|
|
33
|
+
"ui-textarea": () => import("../components/ui-textarea/ui-textarea.js"), // controller 29
|
|
34
|
+
"ui-toast-region": () => import("../components/ui-toast-region/ui-toast-region.js"), // controller 30
|
|
35
|
+
"ui-tooltip": () => import("../components/ui-tooltip/ui-tooltip.js"), // controller 31
|
|
36
|
+
"ui-tree-item": () => import("../components/ui-tree-item/ui-tree-item.js"), // controller 32
|
|
37
|
+
"ui-tree": () => import("../components/ui-tree/ui-tree.js"), // controller 33
|
|
39
38
|
};
|
|
40
39
|
|
|
41
40
|
const active = new WeakMap();
|