@rdlabo/ionic-theme-ios27 2.0.0 → 2.0.1-beta.pr320.sha1504df298a37

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.
@@ -1 +1 @@
1
- @property --ios-theme-split-pane-width{syntax:"<length>";inherits:false;initial-value:320px}ion-app.ios-theme-fold-half-opened ion-split-pane.split-pane-fold-layout,ion-split-pane.ios-theme-split-pane-half-open{--ios-theme-split-pane-width: 50vw}ion-app.ios-theme-vertical-bars{--ios-theme-vertical-bars-safe-area-left-resolved: var(--ios-theme-vertical-bars-safe-area-left, 0px);--ios-theme-vertical-bars-safe-area-right-resolved: var( --ios-theme-vertical-bars-safe-area-right, var(--ios-theme-vertical-bars-native-inset, max(80px, env(safe-area-inset-right, 0px))) )}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-left{--ios-theme-vertical-bars-safe-area-left-resolved: var( --ios-theme-vertical-bars-safe-area-left, var(--ios-theme-vertical-bars-native-inset, max(80px, env(safe-area-inset-left, 0px))) );--ios-theme-vertical-bars-safe-area-right-resolved: var(--ios-theme-vertical-bars-safe-area-right, 0px)}ion-app.ios-theme-vertical-bars ion-modal:not(.ios-theme-vertical-bars-modal){--ios-theme-vertical-bars-safe-area-left-resolved: 0px;--ios-theme-vertical-bars-safe-area-right-resolved: 0px}ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal{--ios-theme-vertical-bars-modal-toolbar-top: max( 24px, calc(var(--ios-theme-vertical-bars-toolbar-top, 220px) - var(--ios-theme-vertical-bars-modal-offset-top, 0px)) )}:is(ion-app.ios-theme-vertical-bars,ion-modal.ios-theme-vertical-bars-modal).ios-theme-vertical-bars-toolbar-ready>:is(ion-menu-button,ion-button).ios-theme-vertical-bars-toolbar-projection{--ios26-glass-background-rgb: var(--ion-background-color-rgb, 255, 255, 255);--ios26-glass-border-color-rgb: var(--ion-background-color-rgb, 255, 255, 255);--ios26-glass-box-shadow-color-rgb: var(--ion-text-color-rgb, 0, 0, 0)}ion-app.ios-theme-vertical-bars .ios-transition-shade{clip-path:inset(0 var(--ios-theme-vertical-bars-safe-area-right-resolved) 0 var(--ios-theme-vertical-bars-safe-area-left-resolved))}ion-app.ios-theme-vertical-bars ion-header.ios:not(.header-collapse-condense,.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)){--ion-safe-area-top: max(24px, env(safe-area-inset-top, 0px))}ion-app.ios-theme-vertical-bars ion-content:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)){--ion-safe-area-left: 0px;--ion-safe-area-right: 0px}ion-app.ios-theme-vertical-bars ion-content:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *))::part(scroll){padding-inline-start:calc(var(--padding-start, 0px) + var(--ios-theme-vertical-bars-safe-area-left-resolved));padding-inline-end:calc(var(--padding-end, 0px) + var(--ios-theme-vertical-bars-safe-area-right-resolved))}ion-app.ios-theme-vertical-bars ion-content:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)):dir(rtl)::part(scroll){padding-inline-start:calc(var(--padding-start, 0px) + var(--ios-theme-vertical-bars-safe-area-right-resolved));padding-inline-end:calc(var(--padding-end, 0px) + var(--ios-theme-vertical-bars-safe-area-left-resolved))}ion-app.ios-theme-vertical-bars ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)){--ion-safe-area-left: 0px;--ion-safe-area-right: 0px}ion-app.ios-theme-vertical-bars ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)):not([data-native-ui-toolbar-text]):has(>.native-ui-prehidden,>ion-buttons>.native-ui-prehidden):not(:has(>:not(ion-buttons,.native-ui-prehidden))):not(:has(>ion-buttons:not(.native-ui-prehidden)>:not(.native-ui-prehidden))){display:none}ion-app.ios-theme-vertical-bars ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)):not(:where(ion-header.header-collapse-condense *,ion-footer.footer-collapse-fade *))>ion-title.ios.title-default:not(.ios-theme-disabled,.ios26-disabled){inset-inline-start:var(--ios-theme-vertical-bars-safe-area-left-resolved);width:calc(100% - var(--ios-theme-vertical-bars-safe-area-left-resolved) - var(--ios-theme-vertical-bars-safe-area-right-resolved))}ion-app.ios-theme-vertical-bars ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)):not(:where(ion-header.header-collapse-condense *,ion-footer.footer-collapse-fade *))>ion-title.ios.title-default:not(.ios-theme-disabled,.ios26-disabled):dir(rtl){inset-inline-start:var(--ios-theme-vertical-bars-safe-area-right-resolved)}ion-app.ios-theme-vertical-bars ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)):not(:where(ion-header.header-collapse-condense *,ion-footer.footer-collapse-fade *))::part(container){padding-inline-start:calc(var(--padding-start, 0px) + var(--ios-theme-vertical-bars-safe-area-left-resolved));padding-inline-end:calc(var(--padding-end, 0px) + var(--ios-theme-vertical-bars-safe-area-right-resolved))}ion-app.ios-theme-vertical-bars ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)):not(:where(ion-header.header-collapse-condense *,ion-footer.footer-collapse-fade *)):dir(rtl)::part(container){padding-inline-start:calc(var(--padding-start, 0px) + var(--ios-theme-vertical-bars-safe-area-right-resolved));padding-inline-end:calc(var(--padding-end, 0px) + var(--ios-theme-vertical-bars-safe-area-left-resolved))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)){--ion-safe-area-left: 0px;--ion-safe-area-right: 0px;--ios-theme-vertical-bars-fab-edge-gap: 16px;--ios-theme-vertical-bars-fab-start-offset: var(--ios-theme-menu-width, var(--ios26-menu-width, 0px))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)).fab-horizontal-start{inset-inline-start:calc(var(--ios-theme-vertical-bars-fab-edge-gap) + var(--ios-theme-vertical-bars-fab-start-offset) + var(--ios-theme-vertical-bars-safe-area-left-resolved))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)).fab-horizontal-end{inset-inline-end:calc(var(--ios-theme-vertical-bars-fab-edge-gap) + var(--ios-theme-vertical-bars-safe-area-right-resolved))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)):dir(rtl).fab-horizontal-start{inset-inline-start:calc(var(--ios-theme-vertical-bars-fab-edge-gap) + var(--ios-theme-vertical-bars-fab-start-offset) + var(--ios-theme-vertical-bars-safe-area-right-resolved))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)):dir(rtl).fab-horizontal-end{inset-inline-end:calc(var(--ios-theme-vertical-bars-fab-edge-gap) + var(--ios-theme-vertical-bars-safe-area-left-resolved))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)):has(.fab-button-small){--ios-theme-vertical-bars-fab-edge-gap: 10px}ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-end:not(:dir(rtl)):not(.ios-theme-disabled,.ios26-disabled),ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-start:dir(rtl):not(.ios-theme-disabled,.ios26-disabled){--ion-safe-area-right: 0px}ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-end:not(:dir(rtl)):not(.ios-theme-disabled,.ios26-disabled)::part(container),ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-start:dir(rtl):not(.ios-theme-disabled,.ios26-disabled)::part(container){margin-right:var(--ios-theme-vertical-bars-safe-area-right-resolved)}ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-start:not(:dir(rtl)):not(.ios-theme-disabled,.ios26-disabled),ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-end:dir(rtl):not(.ios-theme-disabled,.ios26-disabled){--ion-safe-area-left: 0px}ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-start:not(:dir(rtl)):not(.ios-theme-disabled,.ios26-disabled)::part(container),ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-end:dir(rtl):not(.ios-theme-disabled,.ios26-disabled)::part(container){margin-left:var(--ios-theme-vertical-bars-safe-area-left-resolved)}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled){--ios-theme-side-tab-bar-width: 48px;--ios-theme-side-tab-content-width: 44px;--ios-theme-side-tab-bar-gap: 24px;contain:layout style;position:absolute;z-index:2;display:flex;flex-direction:column;width:44px;min-width:44px;max-width:44px;height:fit-content;min-height:0;padding:2px;border-radius:24px;left:auto;right:calc(24px + (48px - var(--ios-theme-side-tab-bar-width))/2);margin:0;top:auto;bottom:var(--ios-theme-side-tab-bar-gap)}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled).ios27-enable-gesture{touch-action:pan-x pinch-zoom}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled)>ion-tab-button:not(.ion-cloned-element){display:block;flex:none;width:44px;min-width:44px;height:58px;min-height:58px;border-radius:22px}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled)>ion-tab-button:not(.ion-cloned-element)::part(native){justify-content:center;min-height:58px;padding:0}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled)>ion-tab-button:not(.ion-cloned-element) ion-label{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border:0}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled)>ion-tab-button:not(.ion-cloned-element) ion-icon{margin:0;font-size:28px}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled)>ion-tab-button.ion-activated{transform:scale(1.16)}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled)>ion-tab-button:not(.ion-cloned-element)~ion-tab-button:not(.ion-cloned-element){margin-block-start:-8px;margin-inline-start:0}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):is(.ios27-animated,:has(>ion-tab-button:is(.ion-activated,:active))){--ios-theme-side-tab-bar-width: 72px;--ios-theme-side-tab-content-width: 64px;--ios-theme-side-tab-bar-gap: 20px;width:64px;min-width:64px;max-width:64px;padding:4px;border-radius:36px;transform:none;-webkit-transform:none}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):is(.ios27-animated,:has(>ion-tab-button:is(.ion-activated,:active)))>ion-tab-button:not(.ion-cloned-element){width:64px;min-width:64px;height:64px;min-height:64px;border-radius:32px}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):is(.ios27-animated,:has(>ion-tab-button:is(.ion-activated,:active)))>ion-tab-button:not(.ion-cloned-element)::part(native){flex-direction:column;min-height:64px;padding-block:11px}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):is(.ios27-animated,:has(>ion-tab-button:is(.ion-activated,:active)))>ion-tab-button:not(.ion-cloned-element) ion-label{position:static;width:auto;height:auto;max-width:64px;padding:0;margin:1px 0 0;overflow:hidden;clip:auto;font-size:10px;line-height:12px;text-overflow:ellipsis;white-space:nowrap}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):is(.ios27-animated,:has(>ion-tab-button:is(.ion-activated,:active)))>ion-tab-button:not(.ion-cloned-element) ion-icon{margin:0;font-size:28px}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-left ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled){right:auto;left:calc(24px + (48px - var(--ios-theme-side-tab-bar-width))/2)}.native-ui-prehidden{position:absolute !important;visibility:hidden !important}html.native-ui-prehide ion-app.ios-theme-vertical-bars ion-back-button:not([icon],[color],.ios-theme-vertical-bars-back-web-owned,.native-ui-disabled,[data-native-ui=disabled],.ios-theme-disabled,.ios26-disabled,.ios-theme-vertical-bars-back-button-projection):not(:where(ion-menu *,ion-modal *,ion-popover *,ion-header[collapse] *,ion-footer[collapse] *,ion-buttons.ios-theme-horizontal-only *,.native-ui-disabled *,[data-native-ui=disabled] *,.ios-theme-disabled *,.ios26-disabled *)){position:absolute !important;visibility:hidden !important}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)) ion-back-button:is(.ios,.md)[data-native-ui-projected]:not(.ios-theme-disabled,.ios26-disabled,.ios-theme-vertical-bars-back-button-projection),ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)) ion-back-button:is(.ios,.md)[data-native-ui-projected]:not(.ios-theme-disabled,.ios26-disabled,.ios-theme-vertical-bars-back-button-projection){display:none}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)) ion-buttons:is(.ios,.md)>:is(ion-button,ion-menu-button):is(.ios,.md)[data-native-ui-projected]:not(.ios-theme-disabled,.ios26-disabled,.ios-theme-vertical-bars-toolbar-action),ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)) ion-buttons:is(.ios,.md)>:is(ion-button,ion-menu-button):is(.ios,.md)[data-native-ui-projected]:not(.ios-theme-disabled,.ios26-disabled,.ios-theme-vertical-bars-toolbar-action){display:none}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)) ion-buttons:is(.ios,.md):has(>:is(ion-back-button,ion-button,ion-menu-button)[data-native-ui-projected]):not(:has(>:is(ion-back-button,ion-button,ion-menu-button):not([data-native-ui-projected]))),ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)) ion-buttons:is(.ios,.md):has(>:is(ion-back-button,ion-button,ion-menu-button)[data-native-ui-projected]):not(:has(>:is(ion-back-button,ion-button,ion-menu-button):not([data-native-ui-projected]))){display:none}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-back-button.ios-theme-vertical-bars-back-button-projection,ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-back-button.ios-theme-vertical-bars-back-button-projection{position:fixed;z-index:1001;top:var(--ios-theme-vertical-bars-modal-toolbar-top, var(--ios-theme-vertical-bars-toolbar-top, 220px));right:max(4px,(var(--ios-theme-vertical-bars-safe-area-right-resolved) - 46px)/2);display:block;width:46px;height:46px;margin:0}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection,ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{position:fixed;z-index:1001;top:calc(var(--ios-theme-vertical-bars-modal-toolbar-top, var(--ios-theme-vertical-bars-toolbar-top, 220px)) + var(--ios-theme-vertical-bars-toolbar-offset, 0px));right:max(4px,(var(--ios-theme-vertical-bars-safe-area-right-resolved) - 46px)/2);width:46px;min-width:46px;height:46px;min-height:46px;margin:0}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection :is(ion-icon,svg),ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection :is(ion-icon,svg){width:22px;height:22px;margin:0;font-size:22px}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-menu-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection,ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-menu-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{backdrop-filter:blur(2px) saturate(360%);transform:translateZ(0);-webkit-transform:translateZ(0);-webkit-backface-visibility:hidden;backface-visibility:hidden;background-color:rgba(var(--ios-theme-glass-background-rgb, var(--ios26-glass-background-rgb)), 0.72);box-shadow:inset 0 1px 2px rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.25),inset 0 -1px 2px rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.3),0 -0.5px 0 rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.65),0 .5px 0 rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.65),0 0 0 .5px rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.22),0 .5px 1px rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.08);border:.5px solid rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)));background-image:linear-gradient(180deg, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 4%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.01) 8%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 16%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.027) 22%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.026) 28%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.018) 36%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 44%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 50%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 58%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.008) 80%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.006) 88%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 94%);background-origin:padding-box;background-clip:border-box;border-inline-color:rgba(0,0,0,0)}@supports(background-clip: border-area){ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-menu-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection,ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-menu-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{border-color:rgba(0,0,0,0);background-image:linear-gradient(180deg, rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb))), transparent 50%, rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)))),linear-gradient(180deg, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 4%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.01) 8%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 16%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.027) 22%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.026) 28%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.018) 36%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 44%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 50%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 58%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.008) 80%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.006) 88%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 94%),linear-gradient(transparent, transparent);background-origin:border-box,padding-box,border-box;background-clip:border-area,padding-box,border-box}}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-menu-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection,ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-menu-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{border-radius:50%}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection:not(.button-solid):not(.button-outline),ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection:not(.button-solid):not(.button-outline){--background: rgba(var(--ios-theme-glass-background-rgb, var(--ios26-glass-background-rgb)), 0.72)}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection,ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{--border-radius: 50%;--box-shadow:inset 0 1px 2px rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.25),inset 0 -1px 2px rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.3),0 -0.5px 0 rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.65),0 .5px 0 rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.65),0 0 0 .5px rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.22),0 .5px 1px rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.08)}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection:not(.button-outline)::part(native),ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection:not(.button-outline)::part(native){backdrop-filter:blur(2px) saturate(360%);transform:translateZ(0);-webkit-transform:translateZ(0);-webkit-backface-visibility:hidden;backface-visibility:hidden;box-shadow:var(--box-shadow);border:.5px solid rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)));background-image:linear-gradient(180deg, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 4%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.01) 8%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 16%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.027) 22%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.026) 28%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.018) 36%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 44%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 50%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 58%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.008) 80%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.006) 88%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 94%);background-origin:padding-box;background-clip:border-box;border-inline-color:rgba(0,0,0,0)}@supports(background-clip: border-area){ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection:not(.button-outline)::part(native),ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection:not(.button-outline)::part(native){border-color:rgba(0,0,0,0);background-image:linear-gradient(180deg, rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb))), transparent 50%, rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)))),linear-gradient(180deg, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 4%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.01) 8%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 16%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.027) 22%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.026) 28%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.018) 36%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 44%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 50%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 58%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.008) 80%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.006) 88%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 94%),linear-gradient(transparent, transparent);background-origin:border-box,padding-box,border-box;background-clip:border-area,padding-box,border-box}}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-buttons:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection,ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-buttons:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{display:flex;flex-direction:column;height:auto;min-height:0}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-buttons:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection>:is(ion-button,ion-menu-button):is(.ios,.md).ios-theme-vertical-bars-toolbar-action,ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-buttons:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection>:is(ion-button,ion-menu-button):is(.ios,.md).ios-theme-vertical-bars-toolbar-action{display:block;width:44px;min-width:44px;height:46px;min-height:46px;margin:0 1px}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-buttons:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection>:is(ion-button,ion-menu-button):is(.ios,.md).ios-theme-vertical-bars-toolbar-action::part(native),ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-buttons:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection>:is(ion-button,ion-menu-button):is(.ios,.md).ios-theme-vertical-bars-toolbar-action::part(native){margin-inline:auto}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-left>ion-back-button.ios-theme-vertical-bars-back-button-projection,ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-left>:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection,ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-left ion-modal.ios-theme-vertical-bars-modal>ion-back-button.ios-theme-vertical-bars-back-button-projection,ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-left ion-modal.ios-theme-vertical-bars-modal>:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{right:auto;left:max(4px,(var(--ios-theme-vertical-bars-safe-area-left-resolved) - 46px)/2)}ion-tab-button.ios.ion-cloned-element.ios27-vertical-tab-effect{border-radius:32px}ion-tab-button.ios.ion-cloned-element.ios27-vertical-tab-effect::part(native){min-height:0;height:100%}:is(ion-app.ios-theme-vertical-bars,ion-modal.ios-theme-vertical-bars-modal)>ion-fab.ios-theme-vertical-bars-search-projection{position:fixed;left:auto;right:25px;top:auto;bottom:24px;z-index:3;width:46px;height:46px;margin:0}:is(ion-app.ios-theme-vertical-bars,ion-modal.ios-theme-vertical-bars-modal)>ion-fab.ios-theme-vertical-bars-search-projection>ion-fab-button{width:46px;height:46px;margin:0}ion-app.ios-theme-vertical-bars ion-fab>ion-fab-button[data-native-ui-projected]{visibility:hidden !important}.ios-theme-vertical-bars-search-projection[hidden]{display:none !important}ion-app.ios-theme-vertical-bars-left>ion-fab.ios-theme-vertical-bars-search-projection,ion-app.ios-theme-vertical-bars-left ion-modal.ios-theme-vertical-bars-modal>ion-fab.ios-theme-vertical-bars-search-projection{left:25px;right:auto}
1
+ @property --ios-theme-split-pane-width{syntax:"<length>";inherits:false;initial-value:320px}ion-app.ios-theme-fold-half-opened ion-split-pane.split-pane-fold-layout,ion-split-pane.ios-theme-split-pane-half-open{--ios-theme-split-pane-width: 50vw}ion-app.ios-theme-vertical-bars{--ios-theme-vertical-bars-safe-area-left-resolved: var(--ios-theme-vertical-bars-safe-area-left, 0px);--ios-theme-vertical-bars-safe-area-right-resolved: var( --ios-theme-vertical-bars-safe-area-right, var(--ios-theme-vertical-bars-native-inset, max(80px, env(safe-area-inset-right, 0px))) )}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-left{--ios-theme-vertical-bars-safe-area-left-resolved: var( --ios-theme-vertical-bars-safe-area-left, var(--ios-theme-vertical-bars-native-inset, max(80px, env(safe-area-inset-left, 0px))) );--ios-theme-vertical-bars-safe-area-right-resolved: var(--ios-theme-vertical-bars-safe-area-right, 0px)}ion-app.ios-theme-vertical-bars ion-modal:not(.ios-theme-vertical-bars-modal){--ios-theme-vertical-bars-safe-area-left-resolved: 0px;--ios-theme-vertical-bars-safe-area-right-resolved: 0px}ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal{--ios-theme-vertical-bars-modal-toolbar-top: max( 24px, calc(var(--ios-theme-vertical-bars-toolbar-top, 220px) - var(--ios-theme-vertical-bars-modal-offset-top, 0px)) )}:is(ion-app.ios-theme-vertical-bars,ion-modal.ios-theme-vertical-bars-modal).ios-theme-vertical-bars-toolbar-ready>:is(ion-menu-button,ion-button).ios-theme-vertical-bars-toolbar-projection{--ios26-glass-background-rgb: var(--ion-background-color-rgb, 255, 255, 255);--ios26-glass-border-color-rgb: var(--ion-background-color-rgb, 255, 255, 255);--ios26-glass-box-shadow-color-rgb: var(--ion-text-color-rgb, 0, 0, 0)}ion-app.ios-theme-vertical-bars .ios-transition-shade{clip-path:inset(0 var(--ios-theme-vertical-bars-safe-area-right-resolved) 0 var(--ios-theme-vertical-bars-safe-area-left-resolved))}ion-app.ios-theme-vertical-bars ion-header.ios:not(.header-collapse-condense,.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)){--ion-safe-area-top: max(24px, env(safe-area-inset-top, 0px))}ion-app.ios-theme-vertical-bars ion-content:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)){--ion-safe-area-left: 0px;--ion-safe-area-right: 0px}ion-app.ios-theme-vertical-bars ion-content:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *))::part(scroll){padding-inline-start:calc(var(--padding-start, 0px) + var(--ios-theme-vertical-bars-safe-area-left-resolved));padding-inline-end:calc(var(--padding-end, 0px) + var(--ios-theme-vertical-bars-safe-area-right-resolved))}ion-app.ios-theme-vertical-bars ion-content:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)):dir(rtl)::part(scroll){padding-inline-start:calc(var(--padding-start, 0px) + var(--ios-theme-vertical-bars-safe-area-right-resolved));padding-inline-end:calc(var(--padding-end, 0px) + var(--ios-theme-vertical-bars-safe-area-left-resolved))}ion-app.ios-theme-vertical-bars ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)){--ion-safe-area-left: 0px;--ion-safe-area-right: 0px}ion-app.ios-theme-vertical-bars ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)):not([data-native-ui-toolbar-text]):has(>.native-ui-prehidden,>ion-buttons>.native-ui-prehidden):not(:has(>:not(ion-buttons,.native-ui-prehidden))):not(:has(>ion-buttons:not(.native-ui-prehidden)>:not(.native-ui-prehidden))){display:none}ion-app.ios-theme-vertical-bars ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)):not(:where(ion-content *))>ion-title.ios.title-default:not(.ios-theme-disabled,.ios26-disabled){inset-inline-start:var(--ios-theme-vertical-bars-safe-area-left-resolved);width:calc(100% - var(--ios-theme-vertical-bars-safe-area-left-resolved) - var(--ios-theme-vertical-bars-safe-area-right-resolved))}ion-app.ios-theme-vertical-bars ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)):not(:where(ion-content *))>ion-title.ios.title-default:not(.ios-theme-disabled,.ios26-disabled):dir(rtl){inset-inline-start:var(--ios-theme-vertical-bars-safe-area-right-resolved)}ion-app.ios-theme-vertical-bars ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)):not(:where(ion-content *))::part(container){padding-inline-start:calc(var(--padding-start, 0px) + var(--ios-theme-vertical-bars-safe-area-left-resolved));padding-inline-end:calc(var(--padding-end, 0px) + var(--ios-theme-vertical-bars-safe-area-right-resolved))}ion-app.ios-theme-vertical-bars ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)):not(:where(ion-content *)):dir(rtl)::part(container){padding-inline-start:calc(var(--padding-start, 0px) + var(--ios-theme-vertical-bars-safe-area-right-resolved));padding-inline-end:calc(var(--padding-end, 0px) + var(--ios-theme-vertical-bars-safe-area-left-resolved))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)){--ion-safe-area-left: 0px;--ion-safe-area-right: 0px;--ios-theme-vertical-bars-fab-edge-gap: 16px;--ios-theme-vertical-bars-fab-start-offset: var(--ios-theme-menu-width, var(--ios26-menu-width, 0px))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)).fab-horizontal-start{inset-inline-start:calc(var(--ios-theme-vertical-bars-fab-edge-gap) + var(--ios-theme-vertical-bars-fab-start-offset) + var(--ios-theme-vertical-bars-safe-area-left-resolved))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)).fab-horizontal-end{inset-inline-end:calc(var(--ios-theme-vertical-bars-fab-edge-gap) + var(--ios-theme-vertical-bars-safe-area-right-resolved))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)):dir(rtl).fab-horizontal-start{inset-inline-start:calc(var(--ios-theme-vertical-bars-fab-edge-gap) + var(--ios-theme-vertical-bars-fab-start-offset) + var(--ios-theme-vertical-bars-safe-area-right-resolved))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)):dir(rtl).fab-horizontal-end{inset-inline-end:calc(var(--ios-theme-vertical-bars-fab-edge-gap) + var(--ios-theme-vertical-bars-safe-area-left-resolved))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)):has(.fab-button-small){--ios-theme-vertical-bars-fab-edge-gap: 10px}ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-end:not(:dir(rtl)):not(.ios-theme-disabled,.ios26-disabled),ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-start:dir(rtl):not(.ios-theme-disabled,.ios26-disabled){--ion-safe-area-right: 0px}ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-end:not(:dir(rtl)):not(.ios-theme-disabled,.ios26-disabled)::part(container),ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-start:dir(rtl):not(.ios-theme-disabled,.ios26-disabled)::part(container){margin-right:var(--ios-theme-vertical-bars-safe-area-right-resolved)}ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-start:not(:dir(rtl)):not(.ios-theme-disabled,.ios26-disabled),ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-end:dir(rtl):not(.ios-theme-disabled,.ios26-disabled){--ion-safe-area-left: 0px}ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-start:not(:dir(rtl)):not(.ios-theme-disabled,.ios26-disabled)::part(container),ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-end:dir(rtl):not(.ios-theme-disabled,.ios26-disabled)::part(container){margin-left:var(--ios-theme-vertical-bars-safe-area-left-resolved)}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled){--ios-theme-side-tab-bar-width: 48px;--ios-theme-side-tab-content-width: 44px;--ios-theme-side-tab-bar-gap: 24px;contain:layout style;position:absolute;z-index:2;display:flex;flex-direction:column;width:44px;min-width:44px;max-width:44px;height:fit-content;min-height:0;padding:2px;border-radius:24px;left:auto;right:calc(24px + (48px - var(--ios-theme-side-tab-bar-width))/2);margin:0;top:auto;bottom:var(--ios-theme-side-tab-bar-gap)}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled).ios27-enable-gesture{touch-action:pan-x pinch-zoom}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled)>ion-tab-button:not(.ion-cloned-element){display:block;flex:none;width:44px;min-width:44px;height:58px;min-height:58px;border-radius:22px}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled)>ion-tab-button:not(.ion-cloned-element)::part(native){justify-content:center;min-height:58px;padding:0}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled)>ion-tab-button:not(.ion-cloned-element) ion-label{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border:0}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled)>ion-tab-button:not(.ion-cloned-element) ion-icon{margin:0;font-size:28px}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled)>ion-tab-button.ion-activated{transform:scale(1.16)}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled)>ion-tab-button:not(.ion-cloned-element)~ion-tab-button:not(.ion-cloned-element){margin-block-start:-8px;margin-inline-start:0}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):is(.ios27-animated,:has(>ion-tab-button:is(.ion-activated,:active))){--ios-theme-side-tab-bar-width: 72px;--ios-theme-side-tab-content-width: 64px;--ios-theme-side-tab-bar-gap: 20px;width:64px;min-width:64px;max-width:64px;padding:4px;border-radius:36px;transform:none;-webkit-transform:none}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):is(.ios27-animated,:has(>ion-tab-button:is(.ion-activated,:active)))>ion-tab-button:not(.ion-cloned-element){width:64px;min-width:64px;height:64px;min-height:64px;border-radius:32px}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):is(.ios27-animated,:has(>ion-tab-button:is(.ion-activated,:active)))>ion-tab-button:not(.ion-cloned-element)::part(native){flex-direction:column;min-height:64px;padding-block:11px}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):is(.ios27-animated,:has(>ion-tab-button:is(.ion-activated,:active)))>ion-tab-button:not(.ion-cloned-element) ion-label{position:static;width:auto;height:auto;max-width:64px;padding:0;margin:1px 0 0;overflow:hidden;clip:auto;font-size:10px;line-height:12px;text-overflow:ellipsis;white-space:nowrap}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):is(.ios27-animated,:has(>ion-tab-button:is(.ion-activated,:active)))>ion-tab-button:not(.ion-cloned-element) ion-icon{margin:0;font-size:28px}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-left ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled){right:auto;left:calc(24px + (48px - var(--ios-theme-side-tab-bar-width))/2)}.native-ui-prehidden{position:absolute !important;visibility:hidden !important}html.native-ui-prehide ion-app.ios-theme-vertical-bars ion-back-button:not([icon],[color],.ios-theme-vertical-bars-back-web-owned,.native-ui-disabled,[data-native-ui=disabled],.ios-theme-disabled,.ios26-disabled,.ios-theme-vertical-bars-back-button-projection):not(:where(ion-menu *,ion-modal *,ion-popover *,ion-header[collapse=condense] *,ion-header.header-collapse-condense *,ion-content ion-header *,ion-content ion-footer *,ion-buttons.ios-theme-horizontal-only *,.native-ui-disabled *,[data-native-ui=disabled] *,.ios-theme-disabled *,.ios26-disabled *)){position:absolute !important;visibility:hidden !important}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)) ion-back-button:is(.ios,.md)[data-native-ui-projected]:not(.ios-theme-disabled,.ios26-disabled,.ios-theme-vertical-bars-back-button-projection),ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)) ion-back-button:is(.ios,.md)[data-native-ui-projected]:not(.ios-theme-disabled,.ios26-disabled,.ios-theme-vertical-bars-back-button-projection){display:none}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)) ion-buttons:is(.ios,.md)>:is(ion-button,ion-menu-button):is(.ios,.md)[data-native-ui-projected]:not(.ios-theme-disabled,.ios26-disabled,.ios-theme-vertical-bars-toolbar-action),ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)) ion-buttons:is(.ios,.md)>:is(ion-button,ion-menu-button):is(.ios,.md)[data-native-ui-projected]:not(.ios-theme-disabled,.ios26-disabled,.ios-theme-vertical-bars-toolbar-action){display:none}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)) ion-buttons:is(.ios,.md):has(>:is(ion-back-button,ion-button,ion-menu-button)[data-native-ui-projected]):not(:has(>:is(ion-back-button,ion-button,ion-menu-button):not([data-native-ui-projected]))),ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)) ion-buttons:is(.ios,.md):has(>:is(ion-back-button,ion-button,ion-menu-button)[data-native-ui-projected]):not(:has(>:is(ion-back-button,ion-button,ion-menu-button):not([data-native-ui-projected]))){display:none}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-back-button.ios-theme-vertical-bars-back-button-projection,ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-back-button.ios-theme-vertical-bars-back-button-projection{position:fixed;z-index:1001;top:var(--ios-theme-vertical-bars-modal-toolbar-top, var(--ios-theme-vertical-bars-toolbar-top, 220px));right:max(4px,(var(--ios-theme-vertical-bars-safe-area-right-resolved) - 46px)/2);display:block;width:46px;height:46px;margin:0}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection,ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{position:fixed;z-index:1001;top:calc(var(--ios-theme-vertical-bars-modal-toolbar-top, var(--ios-theme-vertical-bars-toolbar-top, 220px)) + var(--ios-theme-vertical-bars-toolbar-offset, 0px));right:max(4px,(var(--ios-theme-vertical-bars-safe-area-right-resolved) - 46px)/2);width:46px;min-width:46px;height:46px;min-height:46px;margin:0}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection :is(ion-icon,svg),ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection :is(ion-icon,svg){width:22px;height:22px;margin:0;font-size:22px}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-menu-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection,ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-menu-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{backdrop-filter:blur(2px) saturate(360%);transform:translateZ(0);-webkit-transform:translateZ(0);-webkit-backface-visibility:hidden;backface-visibility:hidden;background-color:rgba(var(--ios-theme-glass-background-rgb, var(--ios26-glass-background-rgb)), 0.72);box-shadow:inset 0 1px 2px rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.25),inset 0 -1px 2px rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.3),0 -0.5px 0 rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.65),0 .5px 0 rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.65),0 0 0 .5px rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.22),0 .5px 1px rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.08);border:.5px solid rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)));background-image:linear-gradient(180deg, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 4%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.01) 8%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 16%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.027) 22%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.026) 28%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.018) 36%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 44%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 50%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 58%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.008) 80%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.006) 88%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 94%);background-origin:padding-box;background-clip:border-box;border-inline-color:rgba(0,0,0,0)}@supports(background-clip: border-area){ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-menu-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection,ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-menu-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{border-color:rgba(0,0,0,0);background-image:linear-gradient(180deg, rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb))), transparent 50%, rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)))),linear-gradient(180deg, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 4%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.01) 8%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 16%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.027) 22%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.026) 28%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.018) 36%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 44%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 50%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 58%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.008) 80%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.006) 88%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 94%),linear-gradient(transparent, transparent);background-origin:border-box,padding-box,border-box;background-clip:border-area,padding-box,border-box}}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-menu-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection,ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-menu-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{border-radius:50%}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection:not(.button-solid):not(.button-outline),ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection:not(.button-solid):not(.button-outline){--background: rgba(var(--ios-theme-glass-background-rgb, var(--ios26-glass-background-rgb)), 0.72)}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection,ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{--border-radius: 50%;--box-shadow:inset 0 1px 2px rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.25),inset 0 -1px 2px rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.3),0 -0.5px 0 rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.65),0 .5px 0 rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.65),0 0 0 .5px rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.22),0 .5px 1px rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.08)}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection:not(.button-outline)::part(native),ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection:not(.button-outline)::part(native){backdrop-filter:blur(2px) saturate(360%);transform:translateZ(0);-webkit-transform:translateZ(0);-webkit-backface-visibility:hidden;backface-visibility:hidden;box-shadow:var(--box-shadow);border:.5px solid rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)));background-image:linear-gradient(180deg, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 4%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.01) 8%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 16%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.027) 22%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.026) 28%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.018) 36%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 44%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 50%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 58%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.008) 80%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.006) 88%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 94%);background-origin:padding-box;background-clip:border-box;border-inline-color:rgba(0,0,0,0)}@supports(background-clip: border-area){ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection:not(.button-outline)::part(native),ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection:not(.button-outline)::part(native){border-color:rgba(0,0,0,0);background-image:linear-gradient(180deg, rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb))), transparent 50%, rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)))),linear-gradient(180deg, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 4%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.01) 8%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 16%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.027) 22%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.026) 28%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.018) 36%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 44%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 50%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 58%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.008) 80%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.006) 88%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 94%),linear-gradient(transparent, transparent);background-origin:border-box,padding-box,border-box;background-clip:border-area,padding-box,border-box}}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-buttons:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection,ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-buttons:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{display:flex;flex-direction:column;height:auto;min-height:0}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-buttons:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection>:is(ion-button,ion-menu-button):is(.ios,.md).ios-theme-vertical-bars-toolbar-action,ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-buttons:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection>:is(ion-button,ion-menu-button):is(.ios,.md).ios-theme-vertical-bars-toolbar-action{display:block;width:44px;min-width:44px;height:46px;min-height:46px;margin:0 1px}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-buttons:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection>:is(ion-button,ion-menu-button):is(.ios,.md).ios-theme-vertical-bars-toolbar-action::part(native),ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-buttons:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection>:is(ion-button,ion-menu-button):is(.ios,.md).ios-theme-vertical-bars-toolbar-action::part(native){margin-inline:auto}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-left>ion-back-button.ios-theme-vertical-bars-back-button-projection,ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-left>:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection,ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-left ion-modal.ios-theme-vertical-bars-modal>ion-back-button.ios-theme-vertical-bars-back-button-projection,ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-left ion-modal.ios-theme-vertical-bars-modal>:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{right:auto;left:max(4px,(var(--ios-theme-vertical-bars-safe-area-left-resolved) - 46px)/2)}ion-tab-button.ios.ion-cloned-element.ios27-vertical-tab-effect{border-radius:32px}ion-tab-button.ios.ion-cloned-element.ios27-vertical-tab-effect::part(native){min-height:0;height:100%}:is(ion-app.ios-theme-vertical-bars,ion-modal.ios-theme-vertical-bars-modal)>ion-fab.ios-theme-vertical-bars-search-projection{position:fixed;left:auto;right:25px;top:auto;bottom:24px;z-index:3;width:46px;height:46px;margin:0}:is(ion-app.ios-theme-vertical-bars,ion-modal.ios-theme-vertical-bars-modal)>ion-fab.ios-theme-vertical-bars-search-projection>ion-fab-button{width:46px;height:46px;margin:0}ion-app.ios-theme-vertical-bars ion-fab>ion-fab-button[data-native-ui-projected]{visibility:hidden !important}.ios-theme-vertical-bars-search-projection[hidden]{display:none !important}ion-app.ios-theme-vertical-bars-left>ion-fab.ios-theme-vertical-bars-search-projection,ion-app.ios-theme-vertical-bars-left ion-modal.ios-theme-vertical-bars-modal>ion-fab.ios-theme-vertical-bars-search-projection{left:25px;right:auto}
@@ -1 +1 @@
1
- {"version":3,"file":"ios.transition.d.ts","names":[],"sources":["../../src/transition/ios.transition.ts"],"mappings":";;;;iBASiB;EACf;;qBAYW,YAAa,QAAQ,QAAQ;qBAI7B,yBAAyB,OAAO,aAAa,MAAM,sBAAsB"}
1
+ {"version":3,"file":"ios.transition.d.ts","names":[],"sources":["../../src/transition/ios.transition.ts"],"mappings":";;;;iBAUiB;EACf;;qBAYW,YAAa,QAAQ,QAAQ;qBAK7B,yBAAyB,OAAO,aAAa,MAAM,sBAAsB"}
@@ -1,5 +1,6 @@
1
1
  import { getIonPageElement } from "./index.js";
2
2
  import { withNativeUITransition } from "./native-ui.js";
3
+ import { createAnimation } from "@ionic/core/components/index.js";
3
4
  import { nativeWebViewMetrics } from "@rdlabo/capacitor-native-ui/integration";
4
5
  import { createIosTransitionAnimation, shadow } from "@rdlabo/ionic-theme-utils";
5
6
  //#region src/transition/ios.transition.ts
@@ -14,7 +15,46 @@ const transitionConfig = {
14
15
  const setConfig = (config) => {
15
16
  if (config.radius !== void 0) nativeWebViewMetrics.radius = config.radius;
16
17
  };
17
- const iosTransitionAnimation = withNativeUITransition(createIosTransitionAnimation(transitionConfig));
18
+ const buildTransition = createIosTransitionAnimation(transitionConfig);
19
+ const iosTransitionAnimation = withNativeUITransition((navEl, opts) => {
20
+ const animation = buildTransition(navEl, opts);
21
+ const backing = "var(--ion-background-color, #fff)";
22
+ let ownsBacking = false;
23
+ animation.beforeAddWrite(() => {
24
+ if (navEl.style.backgroundColor) return;
25
+ const style = navEl.ownerDocument.defaultView?.getComputedStyle(navEl);
26
+ if (!style || !["transparent", "rgba(0, 0, 0, 0)"].includes(style.backgroundColor)) return;
27
+ if (style.backgroundImage && style.backgroundImage !== "none") return;
28
+ navEl.style.backgroundColor = backing;
29
+ ownsBacking = true;
30
+ });
31
+ const restoreBacking = () => {
32
+ if (ownsBacking && navEl.style.backgroundColor === backing && !navEl.style.getPropertyPriority("background-color")) navEl.style.removeProperty("background-color");
33
+ ownsBacking = false;
34
+ };
35
+ animation.afterAddWrite(restoreBacking);
36
+ const destroy = animation.destroy.bind(animation);
37
+ animation.destroy = (...args) => {
38
+ restoreBacking();
39
+ return destroy(...args);
40
+ };
41
+ const buttons = opts.leavingEl?.querySelectorAll(":scope > ion-header.header-translucent ion-buttons, :scope > ion-header.header-translucent ion-toolbar > ion-button");
42
+ if (buttons?.length) animation.addAnimation(createAnimation().addElement(buttons).keyframes([
43
+ {
44
+ offset: 0,
45
+ opacity: 1
46
+ },
47
+ {
48
+ offset: .5,
49
+ opacity: 0
50
+ },
51
+ {
52
+ offset: 1,
53
+ opacity: 0
54
+ }
55
+ ]));
56
+ return animation;
57
+ });
18
58
  //#endregion
19
59
  export { iosTransitionAnimation, setConfig, shadow };
20
60
 
@@ -1 +1 @@
1
- {"version":3,"file":"ios.transition.js","names":[],"sources":["../../src/transition/ios.transition.ts"],"sourcesContent":["import { createIosTransitionAnimation, shadow } from '@rdlabo/ionic-theme-utils';\nimport type { Animation } from '@ionic/core/components';\nimport type { TransitionOptions } from './index';\nimport { getIonPageElement } from './index';\nimport { nativeWebViewMetrics } from '@rdlabo/capacitor-native-ui/integration';\nimport { withNativeUITransition } from './native-ui';\n\nexport { shadow };\n\nexport interface IosTransitionConfig {\n radius: number;\n}\n\nconst transitionConfig = {\n offLeftPercent: 30,\n getIonPageElement,\n shouldAnimateFixedBackButton: (navEl: HTMLElement) => !navEl.closest('ion-app.ios-theme-vertical-bars'),\n get radius() {\n return nativeWebViewMetrics.radius;\n },\n};\n\nexport const setConfig = (config: Partial<IosTransitionConfig>): void => {\n if (config.radius !== undefined) nativeWebViewMetrics.radius = config.radius;\n};\n\nexport const iosTransitionAnimation: (navEl: HTMLElement, opts: TransitionOptions) => Animation = withNativeUITransition(\n createIosTransitionAnimation<TransitionOptions>(transitionConfig),\n);\n"],"mappings":";;;;;AAaA,MAAM,mBAAmB;CACvB,gBAAgB;CAChB;CACA,+BAA+B,UAAuB,CAAC,MAAM,QAAQ,iCAAiC;CACtG,IAAI,SAAS;EACX,OAAO,qBAAqB;CAC9B;AACF;AAEA,MAAa,aAAa,WAA+C;CACvE,IAAI,OAAO,WAAW,KAAA,GAAW,qBAAqB,SAAS,OAAO;AACxE;AAEA,MAAa,yBAAqF,uBAChG,6BAAgD,gBAAgB,CAClE"}
1
+ {"version":3,"file":"ios.transition.js","names":[],"sources":["../../src/transition/ios.transition.ts"],"sourcesContent":["import { createIosTransitionAnimation, shadow } from '@rdlabo/ionic-theme-utils';\nimport { createAnimation } from '@ionic/core/components/index.js';\nimport type { Animation } from '@ionic/core/components';\nimport type { TransitionOptions } from './index';\nimport { getIonPageElement } from './index';\nimport { nativeWebViewMetrics } from '@rdlabo/capacitor-native-ui/integration';\nimport { withNativeUITransition } from './native-ui';\n\nexport { shadow };\n\nexport interface IosTransitionConfig {\n radius: number;\n}\n\nconst transitionConfig = {\n offLeftPercent: 30,\n getIonPageElement,\n shouldAnimateFixedBackButton: (navEl: HTMLElement) => !navEl.closest('ion-app.ios-theme-vertical-bars'),\n get radius() {\n return nativeWebViewMetrics.radius;\n },\n};\n\nexport const setConfig = (config: Partial<IosTransitionConfig>): void => {\n if (config.radius !== undefined) nativeWebViewMetrics.radius = config.radius;\n};\n\nconst buildTransition = createIosTransitionAnimation<TransitionOptions>(transitionConfig);\nexport const iosTransitionAnimation: (navEl: HTMLElement, opts: TransitionOptions) => Animation = withNativeUITransition((navEl, opts) => {\n const animation = buildTransition(navEl, opts);\n const backing = 'var(--ion-background-color, #fff)';\n let ownsBacking = false;\n // Translucent pages expose the outlet as they move. Keep that backing surface\n // in the page theme instead of exposing WKWebView's transparent native backing.\n animation.beforeAddWrite(() => {\n if (navEl.style.backgroundColor) return;\n const style = navEl.ownerDocument.defaultView?.getComputedStyle(navEl);\n if (!style || !['transparent', 'rgba(0, 0, 0, 0)'].includes(style.backgroundColor)) return;\n if (style.backgroundImage && style.backgroundImage !== 'none') return;\n navEl.style.backgroundColor = backing;\n ownsBacking = true;\n });\n const restoreBacking = () => {\n if (ownsBacking && navEl.style.backgroundColor === backing && !navEl.style.getPropertyPriority('background-color'))\n navEl.style.removeProperty('background-color');\n ownsBacking = false;\n };\n animation.afterAddWrite(restoreBacking);\n // Ionic destroy does not run after-write hooks when playback is interrupted.\n const destroy = animation.destroy.bind(animation);\n animation.destroy = (...args) => {\n restoreBacking();\n return destroy(...args);\n };\n // Translucent pages move as a whole, but outgoing toolbar actions still need\n // the same exit fade as opaque headers when they return from native to Web.\n const buttons = opts.leavingEl?.querySelectorAll(\n ':scope > ion-header.header-translucent ion-buttons, :scope > ion-header.header-translucent ion-toolbar > ion-button',\n );\n if (buttons?.length)\n animation.addAnimation(\n createAnimation()\n .addElement(buttons)\n .keyframes([\n { offset: 0, opacity: 1 },\n // Finish the exit before the incoming title occupies this toolbar.\n { offset: 0.5, opacity: 0 },\n { offset: 1, opacity: 0 },\n ]),\n );\n return animation;\n});\n"],"mappings":";;;;;;AAcA,MAAM,mBAAmB;CACvB,gBAAgB;CAChB;CACA,+BAA+B,UAAuB,CAAC,MAAM,QAAQ,iCAAiC;CACtG,IAAI,SAAS;EACX,OAAO,qBAAqB;CAC9B;AACF;AAEA,MAAa,aAAa,WAA+C;CACvE,IAAI,OAAO,WAAW,KAAA,GAAW,qBAAqB,SAAS,OAAO;AACxE;AAEA,MAAM,kBAAkB,6BAAgD,gBAAgB;AACxF,MAAa,yBAAqF,wBAAwB,OAAO,SAAS;CACxI,MAAM,YAAY,gBAAgB,OAAO,IAAI;CAC7C,MAAM,UAAU;CAChB,IAAI,cAAc;CAGlB,UAAU,qBAAqB;EAC7B,IAAI,MAAM,MAAM,iBAAiB;EACjC,MAAM,QAAQ,MAAM,cAAc,aAAa,iBAAiB,KAAK;EACrE,IAAI,CAAC,SAAS,CAAC,CAAC,eAAe,kBAAkB,CAAC,CAAC,SAAS,MAAM,eAAe,GAAG;EACpF,IAAI,MAAM,mBAAmB,MAAM,oBAAoB,QAAQ;EAC/D,MAAM,MAAM,kBAAkB;EAC9B,cAAc;CAChB,CAAC;CACD,MAAM,uBAAuB;EAC3B,IAAI,eAAe,MAAM,MAAM,oBAAoB,WAAW,CAAC,MAAM,MAAM,oBAAoB,kBAAkB,GAC/G,MAAM,MAAM,eAAe,kBAAkB;EAC/C,cAAc;CAChB;CACA,UAAU,cAAc,cAAc;CAEtC,MAAM,UAAU,UAAU,QAAQ,KAAK,SAAS;CAChD,UAAU,WAAW,GAAG,SAAS;EAC/B,eAAe;EACf,OAAO,QAAQ,GAAG,IAAI;CACxB;CAGA,MAAM,UAAU,KAAK,WAAW,iBAC9B,qHACF;CACA,IAAI,SAAS,QACX,UAAU,aACR,gBAAgB,CAAC,CACd,WAAW,OAAO,CAAC,CACnB,UAAU;EACT;GAAE,QAAQ;GAAG,SAAS;EAAE;EAExB;GAAE,QAAQ;GAAK,SAAS;EAAE;EAC1B;GAAE,QAAQ;GAAG,SAAS;EAAE;CAC1B,CAAC,CACL;CACF,OAAO;AACT,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import { Animation, AnimationBuilder } from "@ionic/core/components";
2
2
  //#region src/transition/native-ui.d.ts
3
3
  export declare const withNativeUITransition: (builder: AnimationBuilder) => AnimationBuilder;
4
- export declare const connectNativeUITransition: (animation: Animation, entering: HTMLElement, leaving?: HTMLElement) => void;
4
+ export declare const connectNativeUITransition: (animation: Animation, entering: HTMLElement, leaving?: HTMLElement, direction?: "forward" | "back" | "root") => void;
5
5
  //#endregion
6
6
  //# sourceMappingURL=native-ui.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"native-ui.d.ts","names":[],"sources":["../../src/transition/native-ui.ts"],"mappings":";;qBASa,yBACV,SAAS,qBAAmB;qBAWlB,4BAA6B,WAAW,WAAW,UAAU,aAAa,UAAU"}
1
+ {"version":3,"file":"native-ui.d.ts","names":[],"sources":["../../src/transition/native-ui.ts"],"mappings":";;qBAUa,yBACV,SAAS,qBAAmB;qBAWlB,4BACX,WAAW,WACX,UAAU,aACV,UAAU,aACV"}
@@ -7,13 +7,13 @@ import { VERTICAL_BARS_TRANSITION_CANCELED, hasNativeUIIntegration, suspendNativ
7
7
  */
8
8
  const withNativeUITransition = (builder) => (baseEl, opts) => {
9
9
  const animation = builder(baseEl, opts);
10
- if (opts?.enteringEl) connectNativeUITransition(animation, opts.enteringEl, opts.leavingEl);
10
+ if (opts?.enteringEl) connectNativeUITransition(animation, opts.enteringEl, opts.leavingEl, opts.direction);
11
11
  return animation;
12
12
  };
13
13
  const connectedTransitions = /* @__PURE__ */ new WeakSet();
14
14
  const cancellationTransitions = /* @__PURE__ */ new WeakSet();
15
15
  /** Ionic write hooks cannot await the bridge. Gate playback, including interactive playback. */
16
- const connectNativeUITransition = (animation, entering, leaving) => {
16
+ const connectNativeUITransition = (animation, entering, leaving, direction) => {
17
17
  if (leaving && !cancellationTransitions.has(animation)) {
18
18
  cancellationTransitions.add(animation);
19
19
  animation.onFinish((step) => {
@@ -32,16 +32,35 @@ const connectNativeUITransition = (animation, entering, leaving) => {
32
32
  const progressEnd = animation.progressEnd.bind(animation);
33
33
  const destroy = animation.destroy.bind(animation);
34
34
  let release;
35
+ let frame = 0;
36
+ const win = entering.ownerDocument.defaultView;
37
+ const webAnimations = (value) => [...value.getWebAnimations(), ...value.childAnimations.flatMap(webAnimations)];
38
+ const track = () => {
39
+ if (!release?.progress || !win) return;
40
+ const sample = () => {
41
+ const progress = webAnimations(animation).map((value) => value.effect?.getComputedTiming().progress).find((value) => value != null);
42
+ if (progress != null) release?.progress?.(progress);
43
+ frame = win.requestAnimationFrame(sample);
44
+ };
45
+ frame = win.requestAnimationFrame(sample);
46
+ };
35
47
  let preparation;
36
48
  let disposed = false;
37
49
  let interactiveReady = false;
38
50
  let step;
39
51
  let end;
40
- const prepare = () => preparation ?? (preparation = suspendNativeUI(scopes).then((resume) => {
52
+ const prepare = (interactive = false) => preparation ?? (preparation = suspendNativeUI(scopes, {
53
+ navigation: true,
54
+ ...direction ? { direction } : {},
55
+ ...interactive ? { interactive: true } : {}
56
+ }).then((resume) => {
41
57
  if (disposed) resume(true);
42
58
  else release = resume;
43
59
  }));
44
60
  const finish = (canceled = false) => {
61
+ if (frame) win?.cancelAnimationFrame(frame);
62
+ frame = 0;
63
+ release?.progress?.(canceled ? 0 : 1);
45
64
  release?.(canceled);
46
65
  release = void 0;
47
66
  preparation = void 0;
@@ -51,7 +70,9 @@ const connectNativeUITransition = (animation, entering, leaving) => {
51
70
  await prepare();
52
71
  if (disposed) return;
53
72
  try {
54
- await play(options);
73
+ const playing = play(options);
74
+ track();
75
+ await playing;
55
76
  } finally {
56
77
  finish();
57
78
  }
@@ -60,23 +81,36 @@ const connectNativeUITransition = (animation, entering, leaving) => {
60
81
  interactiveReady = false;
61
82
  step = void 0;
62
83
  end = void 0;
63
- prepare().then(() => {
84
+ prepare(true).then(() => {
64
85
  if (disposed) return;
65
86
  progressStart(...args);
87
+ track();
66
88
  interactiveReady = true;
67
- if (step !== void 0) progressStep(step);
68
- if (end) progressEnd(...end);
89
+ if (step !== void 0) {
90
+ progressStep(step);
91
+ release?.progress?.(step);
92
+ }
93
+ if (end) {
94
+ release?.finishGesture?.(end[0] === 1);
95
+ progressEnd(...end);
96
+ }
69
97
  });
70
98
  return animation;
71
99
  };
72
100
  animation.progressStep = (value) => {
73
101
  step = value;
74
- if (interactiveReady) progressStep(value);
102
+ if (interactiveReady) {
103
+ progressStep(value);
104
+ release?.progress?.(value);
105
+ }
75
106
  return animation;
76
107
  };
77
108
  animation.progressEnd = (...args) => {
78
109
  end = args;
79
- if (interactiveReady) progressEnd(...args);
110
+ if (interactiveReady) {
111
+ release?.finishGesture?.(args[0] === 1);
112
+ progressEnd(...args);
113
+ }
80
114
  return animation;
81
115
  };
82
116
  animation.destroy = (...args) => {
@@ -1 +1 @@
1
- {"version":3,"file":"native-ui.js","names":[],"sources":["../../src/transition/native-ui.ts"],"sourcesContent":["import type { Animation } from '@ionic/core/components';\nimport { hasNativeUIIntegration, suspendNativeUI, VERTICAL_BARS_TRANSITION_CANCELED } from '@rdlabo/capacitor-native-ui/integration';\nimport type { AnimationBuilder } from '@ionic/core/components';\n\n/**\n * Keeps an existing Ionic navigation animation and coordinates native control handoff.\n * Register the returned builder as navAnimation. Do not use it for overlay animations.\n * The builder must return a fresh Animation for each navigation; Ionic destroys it afterward.\n */\nexport const withNativeUITransition =\n (builder: AnimationBuilder): AnimationBuilder =>\n (baseEl, opts) => {\n const animation = builder(baseEl, opts);\n if (opts?.enteringEl) connectNativeUITransition(animation, opts.enteringEl, opts.leavingEl);\n return animation;\n };\n\nconst connectedTransitions = new WeakSet<Animation>();\nconst cancellationTransitions = new WeakSet<Animation>();\n\n/** Ionic write hooks cannot await the bridge. Gate playback, including interactive playback. */\nexport const connectNativeUITransition = (animation: Animation, entering: HTMLElement, leaving?: HTMLElement) => {\n if (leaving && !cancellationTransitions.has(animation)) {\n cancellationTransitions.add(animation);\n animation.onFinish((step) => {\n if (step === 0) leaving.dispatchEvent(new CustomEvent(VERTICAL_BARS_TRANSITION_CANCELED, { bubbles: true, detail: { entering } }));\n });\n }\n if (connectedTransitions.has(animation) || !hasNativeUIIntegration(entering.ownerDocument)) return;\n connectedTransitions.add(animation);\n const scopes = leaving ? [entering, leaving] : [entering];\n const play = animation.play.bind(animation);\n const progressStart = animation.progressStart.bind(animation);\n const progressStep = animation.progressStep.bind(animation);\n const progressEnd = animation.progressEnd.bind(animation);\n const destroy = animation.destroy.bind(animation);\n let release: ((canceled?: boolean) => void) | undefined;\n let preparation: Promise<void> | undefined;\n let disposed = false;\n let interactiveReady = false;\n let step: number | undefined;\n let end: Parameters<Animation['progressEnd']> | undefined;\n const prepare = () =>\n (preparation ??= suspendNativeUI(scopes).then((resume) => {\n if (disposed) resume(true);\n else release = resume;\n }));\n const finish = (canceled = false) => {\n release?.(canceled);\n release = undefined;\n preparation = undefined;\n };\n animation.onFinish((step) => finish(step === 0));\n animation.play = async (options) => {\n await prepare();\n if (disposed) return;\n try {\n await play(options);\n } finally {\n finish();\n }\n };\n animation.progressStart = (...args) => {\n interactiveReady = false;\n step = undefined;\n end = undefined;\n void prepare().then(() => {\n if (disposed) return;\n progressStart(...args);\n interactiveReady = true;\n if (step !== undefined) progressStep(step);\n if (end) progressEnd(...end);\n });\n return animation;\n };\n animation.progressStep = (value) => {\n step = value;\n if (interactiveReady) progressStep(value);\n return animation;\n };\n animation.progressEnd = (...args) => {\n end = args;\n if (interactiveReady) progressEnd(...args);\n return animation;\n };\n animation.destroy = (...args) => {\n disposed = true;\n finish(true);\n return destroy(...args);\n };\n};\n"],"mappings":";;;;;;;AASA,MAAa,0BACV,aACA,QAAQ,SAAS;CAChB,MAAM,YAAY,QAAQ,QAAQ,IAAI;CACtC,IAAI,MAAM,YAAY,0BAA0B,WAAW,KAAK,YAAY,KAAK,SAAS;CAC1F,OAAO;AACT;AAEF,MAAM,uCAAuB,IAAI,QAAmB;AACpD,MAAM,0CAA0B,IAAI,QAAmB;;AAGvD,MAAa,6BAA6B,WAAsB,UAAuB,YAA0B;CAC/G,IAAI,WAAW,CAAC,wBAAwB,IAAI,SAAS,GAAG;EACtD,wBAAwB,IAAI,SAAS;EACrC,UAAU,UAAU,SAAS;GAC3B,IAAI,SAAS,GAAG,QAAQ,cAAc,IAAI,YAAY,mCAAmC;IAAE,SAAS;IAAM,QAAQ,EAAE,SAAS;GAAE,CAAC,CAAC;EACnI,CAAC;CACH;CACA,IAAI,qBAAqB,IAAI,SAAS,KAAK,CAAC,uBAAuB,SAAS,aAAa,GAAG;CAC5F,qBAAqB,IAAI,SAAS;CAClC,MAAM,SAAS,UAAU,CAAC,UAAU,OAAO,IAAI,CAAC,QAAQ;CACxD,MAAM,OAAO,UAAU,KAAK,KAAK,SAAS;CAC1C,MAAM,gBAAgB,UAAU,cAAc,KAAK,SAAS;CAC5D,MAAM,eAAe,UAAU,aAAa,KAAK,SAAS;CAC1D,MAAM,cAAc,UAAU,YAAY,KAAK,SAAS;CACxD,MAAM,UAAU,UAAU,QAAQ,KAAK,SAAS;CAChD,IAAI;CACJ,IAAI;CACJ,IAAI,WAAW;CACf,IAAI,mBAAmB;CACvB,IAAI;CACJ,IAAI;CACJ,MAAM,gBACH,gBAAA,cAAgB,gBAAgB,MAAM,CAAC,CAAC,MAAM,WAAW;EACxD,IAAI,UAAU,OAAO,IAAI;OACpB,UAAU;CACjB,CAAC;CACH,MAAM,UAAU,WAAW,UAAU;EACnC,UAAU,QAAQ;EAClB,UAAU,KAAA;EACV,cAAc,KAAA;CAChB;CACA,UAAU,UAAU,SAAS,OAAO,SAAS,CAAC,CAAC;CAC/C,UAAU,OAAO,OAAO,YAAY;EAClC,MAAM,QAAQ;EACd,IAAI,UAAU;EACd,IAAI;GACF,MAAM,KAAK,OAAO;EACpB,UAAU;GACR,OAAO;EACT;CACF;CACA,UAAU,iBAAiB,GAAG,SAAS;EACrC,mBAAmB;EACnB,OAAO,KAAA;EACP,MAAM,KAAA;EACN,QAAa,CAAC,CAAC,WAAW;GACxB,IAAI,UAAU;GACd,cAAc,GAAG,IAAI;GACrB,mBAAmB;GACnB,IAAI,SAAS,KAAA,GAAW,aAAa,IAAI;GACzC,IAAI,KAAK,YAAY,GAAG,GAAG;EAC7B,CAAC;EACD,OAAO;CACT;CACA,UAAU,gBAAgB,UAAU;EAClC,OAAO;EACP,IAAI,kBAAkB,aAAa,KAAK;EACxC,OAAO;CACT;CACA,UAAU,eAAe,GAAG,SAAS;EACnC,MAAM;EACN,IAAI,kBAAkB,YAAY,GAAG,IAAI;EACzC,OAAO;CACT;CACA,UAAU,WAAW,GAAG,SAAS;EAC/B,WAAW;EACX,OAAO,IAAI;EACX,OAAO,QAAQ,GAAG,IAAI;CACxB;AACF"}
1
+ {"version":3,"file":"native-ui.js","names":[],"sources":["../../src/transition/native-ui.ts"],"sourcesContent":["import type { NativeUITransitionRelease } from '@rdlabo/capacitor-native-ui/integration';\nimport type { Animation } from '@ionic/core/components';\nimport { hasNativeUIIntegration, suspendNativeUI, VERTICAL_BARS_TRANSITION_CANCELED } from '@rdlabo/capacitor-native-ui/integration';\nimport type { AnimationBuilder } from '@ionic/core/components';\n\n/**\n * Keeps an existing Ionic navigation animation and coordinates native control handoff.\n * Register the returned builder as navAnimation. Do not use it for overlay animations.\n * The builder must return a fresh Animation for each navigation; Ionic destroys it afterward.\n */\nexport const withNativeUITransition =\n (builder: AnimationBuilder): AnimationBuilder =>\n (baseEl, opts) => {\n const animation = builder(baseEl, opts);\n if (opts?.enteringEl) connectNativeUITransition(animation, opts.enteringEl, opts.leavingEl, opts.direction);\n return animation;\n };\n\nconst connectedTransitions = new WeakSet<Animation>();\nconst cancellationTransitions = new WeakSet<Animation>();\n\n/** Ionic write hooks cannot await the bridge. Gate playback, including interactive playback. */\nexport const connectNativeUITransition = (\n animation: Animation,\n entering: HTMLElement,\n leaving?: HTMLElement,\n direction?: 'forward' | 'back' | 'root',\n) => {\n if (leaving && !cancellationTransitions.has(animation)) {\n cancellationTransitions.add(animation);\n animation.onFinish((step) => {\n if (step === 0) leaving.dispatchEvent(new CustomEvent(VERTICAL_BARS_TRANSITION_CANCELED, { bubbles: true, detail: { entering } }));\n });\n }\n if (connectedTransitions.has(animation) || !hasNativeUIIntegration(entering.ownerDocument)) return;\n connectedTransitions.add(animation);\n const scopes = leaving ? [entering, leaving] : [entering];\n const play = animation.play.bind(animation);\n const progressStart = animation.progressStart.bind(animation);\n const progressStep = animation.progressStep.bind(animation);\n const progressEnd = animation.progressEnd.bind(animation);\n const destroy = animation.destroy.bind(animation);\n let release: NativeUITransitionRelease | undefined;\n let frame = 0;\n const win = entering.ownerDocument.defaultView;\n const webAnimations = (value: Animation): globalThis.Animation[] => [\n ...value.getWebAnimations(),\n ...value.childAnimations.flatMap(webAnimations),\n ];\n const track = () => {\n if (!release?.progress || !win) return;\n const sample = () => {\n const progress = webAnimations(animation)\n .map((value) => value.effect?.getComputedTiming().progress)\n .find((value) => value != null);\n if (progress != null) release?.progress?.(progress);\n frame = win.requestAnimationFrame(sample);\n };\n frame = win.requestAnimationFrame(sample);\n };\n let preparation: Promise<void> | undefined;\n let disposed = false;\n let interactiveReady = false;\n let step: number | undefined;\n let end: Parameters<Animation['progressEnd']> | undefined;\n const prepare = (interactive = false) =>\n (preparation ??= suspendNativeUI(scopes, {\n navigation: true,\n ...(direction ? { direction } : {}),\n ...(interactive ? { interactive: true } : {}),\n }).then((resume) => {\n if (disposed) resume(true);\n else release = resume;\n }));\n const finish = (canceled = false) => {\n if (frame) win?.cancelAnimationFrame(frame);\n frame = 0;\n release?.progress?.(canceled ? 0 : 1);\n release?.(canceled);\n release = undefined;\n preparation = undefined;\n };\n animation.onFinish((step) => finish(step === 0));\n animation.play = async (options) => {\n await prepare();\n if (disposed) return;\n try {\n const playing = play(options);\n track();\n await playing;\n } finally {\n finish();\n }\n };\n animation.progressStart = (...args) => {\n interactiveReady = false;\n step = undefined;\n end = undefined;\n void prepare(true).then(() => {\n if (disposed) return;\n progressStart(...args);\n track();\n interactiveReady = true;\n if (step !== undefined) {\n progressStep(step);\n release?.progress?.(step);\n }\n if (end) {\n release?.finishGesture?.(end[0] === 1);\n progressEnd(...end);\n }\n });\n return animation;\n };\n animation.progressStep = (value) => {\n step = value;\n if (interactiveReady) {\n progressStep(value);\n release?.progress?.(value);\n }\n return animation;\n };\n animation.progressEnd = (...args) => {\n end = args;\n if (interactiveReady) {\n release?.finishGesture?.(args[0] === 1);\n progressEnd(...args);\n }\n return animation;\n };\n animation.destroy = (...args) => {\n disposed = true;\n finish(true);\n return destroy(...args);\n };\n};\n"],"mappings":";;;;;;;AAUA,MAAa,0BACV,aACA,QAAQ,SAAS;CAChB,MAAM,YAAY,QAAQ,QAAQ,IAAI;CACtC,IAAI,MAAM,YAAY,0BAA0B,WAAW,KAAK,YAAY,KAAK,WAAW,KAAK,SAAS;CAC1G,OAAO;AACT;AAEF,MAAM,uCAAuB,IAAI,QAAmB;AACpD,MAAM,0CAA0B,IAAI,QAAmB;;AAGvD,MAAa,6BACX,WACA,UACA,SACA,cACG;CACH,IAAI,WAAW,CAAC,wBAAwB,IAAI,SAAS,GAAG;EACtD,wBAAwB,IAAI,SAAS;EACrC,UAAU,UAAU,SAAS;GAC3B,IAAI,SAAS,GAAG,QAAQ,cAAc,IAAI,YAAY,mCAAmC;IAAE,SAAS;IAAM,QAAQ,EAAE,SAAS;GAAE,CAAC,CAAC;EACnI,CAAC;CACH;CACA,IAAI,qBAAqB,IAAI,SAAS,KAAK,CAAC,uBAAuB,SAAS,aAAa,GAAG;CAC5F,qBAAqB,IAAI,SAAS;CAClC,MAAM,SAAS,UAAU,CAAC,UAAU,OAAO,IAAI,CAAC,QAAQ;CACxD,MAAM,OAAO,UAAU,KAAK,KAAK,SAAS;CAC1C,MAAM,gBAAgB,UAAU,cAAc,KAAK,SAAS;CAC5D,MAAM,eAAe,UAAU,aAAa,KAAK,SAAS;CAC1D,MAAM,cAAc,UAAU,YAAY,KAAK,SAAS;CACxD,MAAM,UAAU,UAAU,QAAQ,KAAK,SAAS;CAChD,IAAI;CACJ,IAAI,QAAQ;CACZ,MAAM,MAAM,SAAS,cAAc;CACnC,MAAM,iBAAiB,UAA6C,CAClE,GAAG,MAAM,iBAAiB,GAC1B,GAAG,MAAM,gBAAgB,QAAQ,aAAa,CAChD;CACA,MAAM,cAAc;EAClB,IAAI,CAAC,SAAS,YAAY,CAAC,KAAK;EAChC,MAAM,eAAe;GACnB,MAAM,WAAW,cAAc,SAAS,CAAC,CACtC,KAAK,UAAU,MAAM,QAAQ,kBAAkB,CAAC,CAAC,QAAQ,CAAC,CAC1D,MAAM,UAAU,SAAS,IAAI;GAChC,IAAI,YAAY,MAAM,SAAS,WAAW,QAAQ;GAClD,QAAQ,IAAI,sBAAsB,MAAM;EAC1C;EACA,QAAQ,IAAI,sBAAsB,MAAM;CAC1C;CACA,IAAI;CACJ,IAAI,WAAW;CACf,IAAI,mBAAmB;CACvB,IAAI;CACJ,IAAI;CACJ,MAAM,WAAW,cAAc,UAC5B,gBAAA,cAAgB,gBAAgB,QAAQ;EACvC,YAAY;EACZ,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;EACjC,GAAI,cAAc,EAAE,aAAa,KAAK,IAAI,CAAC;CAC7C,CAAC,CAAC,CAAC,MAAM,WAAW;EAClB,IAAI,UAAU,OAAO,IAAI;OACpB,UAAU;CACjB,CAAC;CACH,MAAM,UAAU,WAAW,UAAU;EACnC,IAAI,OAAO,KAAK,qBAAqB,KAAK;EAC1C,QAAQ;EACR,SAAS,WAAW,WAAW,IAAI,CAAC;EACpC,UAAU,QAAQ;EAClB,UAAU,KAAA;EACV,cAAc,KAAA;CAChB;CACA,UAAU,UAAU,SAAS,OAAO,SAAS,CAAC,CAAC;CAC/C,UAAU,OAAO,OAAO,YAAY;EAClC,MAAM,QAAQ;EACd,IAAI,UAAU;EACd,IAAI;GACF,MAAM,UAAU,KAAK,OAAO;GAC5B,MAAM;GACN,MAAM;EACR,UAAU;GACR,OAAO;EACT;CACF;CACA,UAAU,iBAAiB,GAAG,SAAS;EACrC,mBAAmB;EACnB,OAAO,KAAA;EACP,MAAM,KAAA;EACN,QAAa,IAAI,CAAC,CAAC,WAAW;GAC5B,IAAI,UAAU;GACd,cAAc,GAAG,IAAI;GACrB,MAAM;GACN,mBAAmB;GACnB,IAAI,SAAS,KAAA,GAAW;IACtB,aAAa,IAAI;IACjB,SAAS,WAAW,IAAI;GAC1B;GACA,IAAI,KAAK;IACP,SAAS,gBAAgB,IAAI,OAAO,CAAC;IACrC,YAAY,GAAG,GAAG;GACpB;EACF,CAAC;EACD,OAAO;CACT;CACA,UAAU,gBAAgB,UAAU;EAClC,OAAO;EACP,IAAI,kBAAkB;GACpB,aAAa,KAAK;GAClB,SAAS,WAAW,KAAK;EAC3B;EACA,OAAO;CACT;CACA,UAAU,eAAe,GAAG,SAAS;EACnC,MAAM;EACN,IAAI,kBAAkB;GACpB,SAAS,gBAAgB,KAAK,OAAO,CAAC;GACtC,YAAY,GAAG,IAAI;EACrB;EACA,OAAO;CACT;CACA,UAAU,WAAW,GAAG,SAAS;EAC/B,WAAW;EACX,OAAO,IAAI;EACX,OAAO,QAAQ,GAAG,IAAI;CACxB;AACF"}
package/docs/features.md CHANGED
@@ -31,9 +31,9 @@ ion-textarea label.textarea-wrapper {
31
31
  }
32
32
  ```
33
33
 
34
- ## Native UI (Preview)
34
+ ## Native UI
35
35
 
36
- Once your theme is working, [add Native UI](add-native-ui.md) to render supported fixed controls with UIKit and SwiftUI on iOS. Keep theme styles for Web content and fallback controls. Native UI is an optional preview; adding styles alone does not enable it.
36
+ Once your theme is working, [add Native UI](add-native-ui.md) to render supported fixed controls with UIKit and SwiftUI on iOS. Keep theme styles for Web content and fallback controls. Native UI is officially supported starting with 2.0.0 and remains opt-in; adding styles alone does not enable it.
37
37
 
38
38
  ## Selective component imports
39
39
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rdlabo/ionic-theme-ios27",
3
3
  "private": false,
4
- "version": "2.0.0",
4
+ "version": "2.0.1-beta.pr320.sha1504df298a37",
5
5
  "description": "iOS27 Theme for Ionic Framework",
6
6
  "main": "./dist/index.js",
7
7
  "module": "./dist/index.js",
@@ -46,7 +46,7 @@
46
46
  },
47
47
  "homepage": "https://docs.rdlabo.dev/projects/ionic-theme-ios27",
48
48
  "dependencies": {
49
- "@rdlabo/capacitor-native-ui": "2.0.0",
49
+ "@rdlabo/capacitor-native-ui": "2.0.1-beta.pr320.sha1504df298a37",
50
50
  "@rdlabo/ionic-theme-utils": "0.1.5",
51
51
  "@stencil/core": "^4.43.5",
52
52
  "ionicons": "^8.1.0"
@@ -101,8 +101,8 @@ ion-app.ios-theme-vertical-bars
101
101
  display: none;
102
102
  }
103
103
 
104
- // Collapse headers already sit inside the padded ion-content scroll area.
105
- &:not(:where(ion-header.header-collapse-condense *, ion-footer.footer-collapse-fade *)) {
104
+ // Scrolling toolbars already sit inside the padded ion-content scroll area.
105
+ &:not(:where(ion-content *)) {
106
106
  // Ionic's centered iOS title is absolute and does not follow container padding.
107
107
  // Center it within the same foreground width as the page content.
108
108
  > ion-title.ios.title-default:not(.ios-theme-disabled, .ios26-disabled) {
@@ -313,8 +313,10 @@ html.native-ui-prehide
313
313
  ion-menu *,
314
314
  ion-modal *,
315
315
  ion-popover *,
316
- ion-header[collapse] *,
317
- ion-footer[collapse] *,
316
+ ion-header[collapse='condense'] *,
317
+ ion-header.header-collapse-condense *,
318
+ ion-content ion-header *,
319
+ ion-content ion-footer *,
318
320
  ion-buttons.ios-theme-horizontal-only *,
319
321
  .native-ui-disabled *,
320
322
  [data-native-ui='disabled'] *,
@@ -1,4 +1,5 @@
1
1
  import { createIosTransitionAnimation, shadow } from '@rdlabo/ionic-theme-utils';
2
+ import { createAnimation } from '@ionic/core/components/index.js';
2
3
  import type { Animation } from '@ionic/core/components';
3
4
  import type { TransitionOptions } from './index';
4
5
  import { getIonPageElement } from './index';
@@ -24,6 +25,48 @@ export const setConfig = (config: Partial<IosTransitionConfig>): void => {
24
25
  if (config.radius !== undefined) nativeWebViewMetrics.radius = config.radius;
25
26
  };
26
27
 
27
- export const iosTransitionAnimation: (navEl: HTMLElement, opts: TransitionOptions) => Animation = withNativeUITransition(
28
- createIosTransitionAnimation<TransitionOptions>(transitionConfig),
29
- );
28
+ const buildTransition = createIosTransitionAnimation<TransitionOptions>(transitionConfig);
29
+ export const iosTransitionAnimation: (navEl: HTMLElement, opts: TransitionOptions) => Animation = withNativeUITransition((navEl, opts) => {
30
+ const animation = buildTransition(navEl, opts);
31
+ const backing = 'var(--ion-background-color, #fff)';
32
+ let ownsBacking = false;
33
+ // Translucent pages expose the outlet as they move. Keep that backing surface
34
+ // in the page theme instead of exposing WKWebView's transparent native backing.
35
+ animation.beforeAddWrite(() => {
36
+ if (navEl.style.backgroundColor) return;
37
+ const style = navEl.ownerDocument.defaultView?.getComputedStyle(navEl);
38
+ if (!style || !['transparent', 'rgba(0, 0, 0, 0)'].includes(style.backgroundColor)) return;
39
+ if (style.backgroundImage && style.backgroundImage !== 'none') return;
40
+ navEl.style.backgroundColor = backing;
41
+ ownsBacking = true;
42
+ });
43
+ const restoreBacking = () => {
44
+ if (ownsBacking && navEl.style.backgroundColor === backing && !navEl.style.getPropertyPriority('background-color'))
45
+ navEl.style.removeProperty('background-color');
46
+ ownsBacking = false;
47
+ };
48
+ animation.afterAddWrite(restoreBacking);
49
+ // Ionic destroy does not run after-write hooks when playback is interrupted.
50
+ const destroy = animation.destroy.bind(animation);
51
+ animation.destroy = (...args) => {
52
+ restoreBacking();
53
+ return destroy(...args);
54
+ };
55
+ // Translucent pages move as a whole, but outgoing toolbar actions still need
56
+ // the same exit fade as opaque headers when they return from native to Web.
57
+ const buttons = opts.leavingEl?.querySelectorAll(
58
+ ':scope > ion-header.header-translucent ion-buttons, :scope > ion-header.header-translucent ion-toolbar > ion-button',
59
+ );
60
+ if (buttons?.length)
61
+ animation.addAnimation(
62
+ createAnimation()
63
+ .addElement(buttons)
64
+ .keyframes([
65
+ { offset: 0, opacity: 1 },
66
+ // Finish the exit before the incoming title occupies this toolbar.
67
+ { offset: 0.5, opacity: 0 },
68
+ { offset: 1, opacity: 0 },
69
+ ]),
70
+ );
71
+ return animation;
72
+ });
@@ -1,3 +1,4 @@
1
+ import type { NativeUITransitionRelease } from '@rdlabo/capacitor-native-ui/integration';
1
2
  import type { Animation } from '@ionic/core/components';
2
3
  import { hasNativeUIIntegration, suspendNativeUI, VERTICAL_BARS_TRANSITION_CANCELED } from '@rdlabo/capacitor-native-ui/integration';
3
4
  import type { AnimationBuilder } from '@ionic/core/components';
@@ -11,7 +12,7 @@ export const withNativeUITransition =
11
12
  (builder: AnimationBuilder): AnimationBuilder =>
12
13
  (baseEl, opts) => {
13
14
  const animation = builder(baseEl, opts);
14
- if (opts?.enteringEl) connectNativeUITransition(animation, opts.enteringEl, opts.leavingEl);
15
+ if (opts?.enteringEl) connectNativeUITransition(animation, opts.enteringEl, opts.leavingEl, opts.direction);
15
16
  return animation;
16
17
  };
17
18
 
@@ -19,7 +20,12 @@ const connectedTransitions = new WeakSet<Animation>();
19
20
  const cancellationTransitions = new WeakSet<Animation>();
20
21
 
21
22
  /** Ionic write hooks cannot await the bridge. Gate playback, including interactive playback. */
22
- export const connectNativeUITransition = (animation: Animation, entering: HTMLElement, leaving?: HTMLElement) => {
23
+ export const connectNativeUITransition = (
24
+ animation: Animation,
25
+ entering: HTMLElement,
26
+ leaving?: HTMLElement,
27
+ direction?: 'forward' | 'back' | 'root',
28
+ ) => {
23
29
  if (leaving && !cancellationTransitions.has(animation)) {
24
30
  cancellationTransitions.add(animation);
25
31
  animation.onFinish((step) => {
@@ -34,18 +40,42 @@ export const connectNativeUITransition = (animation: Animation, entering: HTMLEl
34
40
  const progressStep = animation.progressStep.bind(animation);
35
41
  const progressEnd = animation.progressEnd.bind(animation);
36
42
  const destroy = animation.destroy.bind(animation);
37
- let release: ((canceled?: boolean) => void) | undefined;
43
+ let release: NativeUITransitionRelease | undefined;
44
+ let frame = 0;
45
+ const win = entering.ownerDocument.defaultView;
46
+ const webAnimations = (value: Animation): globalThis.Animation[] => [
47
+ ...value.getWebAnimations(),
48
+ ...value.childAnimations.flatMap(webAnimations),
49
+ ];
50
+ const track = () => {
51
+ if (!release?.progress || !win) return;
52
+ const sample = () => {
53
+ const progress = webAnimations(animation)
54
+ .map((value) => value.effect?.getComputedTiming().progress)
55
+ .find((value) => value != null);
56
+ if (progress != null) release?.progress?.(progress);
57
+ frame = win.requestAnimationFrame(sample);
58
+ };
59
+ frame = win.requestAnimationFrame(sample);
60
+ };
38
61
  let preparation: Promise<void> | undefined;
39
62
  let disposed = false;
40
63
  let interactiveReady = false;
41
64
  let step: number | undefined;
42
65
  let end: Parameters<Animation['progressEnd']> | undefined;
43
- const prepare = () =>
44
- (preparation ??= suspendNativeUI(scopes).then((resume) => {
66
+ const prepare = (interactive = false) =>
67
+ (preparation ??= suspendNativeUI(scopes, {
68
+ navigation: true,
69
+ ...(direction ? { direction } : {}),
70
+ ...(interactive ? { interactive: true } : {}),
71
+ }).then((resume) => {
45
72
  if (disposed) resume(true);
46
73
  else release = resume;
47
74
  }));
48
75
  const finish = (canceled = false) => {
76
+ if (frame) win?.cancelAnimationFrame(frame);
77
+ frame = 0;
78
+ release?.progress?.(canceled ? 0 : 1);
49
79
  release?.(canceled);
50
80
  release = undefined;
51
81
  preparation = undefined;
@@ -55,7 +85,9 @@ export const connectNativeUITransition = (animation: Animation, entering: HTMLEl
55
85
  await prepare();
56
86
  if (disposed) return;
57
87
  try {
58
- await play(options);
88
+ const playing = play(options);
89
+ track();
90
+ await playing;
59
91
  } finally {
60
92
  finish();
61
93
  }
@@ -64,23 +96,36 @@ export const connectNativeUITransition = (animation: Animation, entering: HTMLEl
64
96
  interactiveReady = false;
65
97
  step = undefined;
66
98
  end = undefined;
67
- void prepare().then(() => {
99
+ void prepare(true).then(() => {
68
100
  if (disposed) return;
69
101
  progressStart(...args);
102
+ track();
70
103
  interactiveReady = true;
71
- if (step !== undefined) progressStep(step);
72
- if (end) progressEnd(...end);
104
+ if (step !== undefined) {
105
+ progressStep(step);
106
+ release?.progress?.(step);
107
+ }
108
+ if (end) {
109
+ release?.finishGesture?.(end[0] === 1);
110
+ progressEnd(...end);
111
+ }
73
112
  });
74
113
  return animation;
75
114
  };
76
115
  animation.progressStep = (value) => {
77
116
  step = value;
78
- if (interactiveReady) progressStep(value);
117
+ if (interactiveReady) {
118
+ progressStep(value);
119
+ release?.progress?.(value);
120
+ }
79
121
  return animation;
80
122
  };
81
123
  animation.progressEnd = (...args) => {
82
124
  end = args;
83
- if (interactiveReady) progressEnd(...args);
125
+ if (interactiveReady) {
126
+ release?.finishGesture?.(args[0] === 1);
127
+ progressEnd(...args);
128
+ }
84
129
  return animation;
85
130
  };
86
131
  animation.destroy = (...args) => {