@session-services/web-elements 0.1.22 → 0.1.23

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.
@@ -23613,18 +23613,16 @@ const sessionServicesTicketingCss = () => `:host{--background:transparent;--fore
23613
23613
  in srgb,
23614
23614
  oklch(0.21 0.006 285.885) 80%,
23615
23615
  oklch(0.141 0.005 285.823)
23616
- );--card-foreground:oklch(0.967 0.001 286.375);--popover:oklch(0.21 0.006 285.885);--popover-foreground:oklch(0.967 0.001 286.375);--primary:oklch(0.537 0.1554 255);--primary-foreground:oklch(0.985 0 0);--secondary:oklch(1 0 0 / 6%);--secondary-foreground:oklch(0.967 0.001 286.375);--muted:oklch(1 0 0 / 6%);--muted-foreground:oklch(0.705 0.015 286.067);--accent:oklch(1 0 0 / 6%);--accent-foreground:oklch(0.967 0.001 286.375);--destructive:oklch(0.637 0.237 25.331);--destructive-foreground:oklch(0.704 0.191 22.216);--border:oklch(1 0 0 / 12%);--input:oklch(1 0 0 / 12%);--ring:oklch(0.552 0.016 285.938);--success:oklch(0.696 0.17 162.48);--warning:oklch(0.769 0.188 70.08);--info:oklch(0.623 0.214 259.815);--info-foreground:oklch(0.707 0.165 254.624)}.tickets-wrapper{padding:0;width:100%}.tickets-heading{color:var(--internal-foreground);font-size:var(--internal-font-size-lg);font-weight:var(--internal-font-weight-semibold);margin:0 0 var(--internal-spacing-md)}.door-alert,.empty-ticketing-state,.passcode-form,.passcode-form input,.ticket-section,.more-info-badge,.quantity-controls,.sold-out-controls,.coupon-row,.coupon-apply,.coupon-remove{border:1px solid var(--internal-input);box-shadow:var(--internal-shadow-edge-light)}.external-ticket-button,.checkout-btn{display:inline-flex;align-items:center;justify-content:center;background:var(--internal-primary);color:var(--internal-primary-foreground);border:1px solid oklch(from var(--internal-primary) calc(l - 0.08) c h);border-radius:calc(var(--internal-radius) - 2px);cursor:pointer;box-shadow:var(--internal-shadow-edge-light);transition:all var(--internal-transition-fast)}.external-ticket-button:hover,.checkout-btn:hover:not(:disabled){background:oklch(from var(--internal-primary) calc(l - 0.08) c h);transform:translateY(-1px)}.door-alert,.empty-ticketing-state,.passcode-form{display:flex;flex-direction:column;gap:var(--internal-spacing-sm);padding:var(--internal-spacing-lg);margin-bottom:var(--internal-spacing-md);background:var(--internal-card);border-radius:var(--internal-radius)}.door-alert{background:oklch(from var(--internal-success) l c h / 0.1);border-color:oklch(from var(--internal-success) l c h / 0.48)}.door-alert strong,.empty-ticketing-state strong,.passcode-form h2{color:var(--internal-foreground);font-size:var(--internal-font-size-base);font-weight:var(--internal-font-weight-semibold);line-height:1.3}.door-alert span,.empty-ticketing-state span,.passcode-form p{color:var(--internal-muted-foreground);font-size:var(--internal-font-size-sm);line-height:1.5}.external-ticket-button{width:100%;padding:calc(var(--internal-spacing-sm) + var(--internal-spacing-xs))
23617
- var(--internal-spacing-lg);font-size:var(--internal-font-size-base);font-weight:var(--internal-font-weight-bold);text-decoration:none}.passcode-form input{width:100%;min-width:0;padding:calc(var(--internal-spacing-sm) + 0.125rem)
23618
- var(--internal-spacing-sm);background:var(--internal-card);color:var(--internal-foreground);border-radius:calc(var(--internal-radius) - 2px);font:inherit}.passcode-form input:disabled{opacity:0.6;cursor:not-allowed}.ticket-section{background:var(--internal-card);border-radius:var(--internal-radius);margin:0 0 var(--internal-spacing-lg) 0;overflow:hidden;width:100%;transition:all var(--internal-transition-base)}.tickets-wrapper>.ticket-section:last-child{margin-bottom:0}.ticket-section.section-sold-out{position:relative}.ticket-section.section-sold-out .section-header{padding-bottom:var(--internal-spacing-md)}.ticket-section.section-sold-out .section-name,.ticket-section.section-sold-out .section-time,.ticket-section.section-sold-out .section-venue{opacity:0.8}.ticket-section.section-sold-out .admissions-list{opacity:0.6;pointer-events:none;filter:grayscale(0.3)}.ticket-section.section-sold-out .admission-card{background:var(--internal-card)}.ticket-section.section-sold-out .quantity-controls,.ticket-section.section-sold-out .sold-out-controls{opacity:0.7}.section-header{padding:var(--internal-spacing-md) var(--internal-spacing-lg);border-bottom:1px solid var(--internal-border);background:var(--internal-card)}.section-name{color:var(--internal-foreground);font-size:var(--internal-font-size-lg);font-weight:var(--internal-font-weight-semibold);letter-spacing:-0.025em;margin:0 0 var(--internal-spacing-xs) 0;display:flex;align-items:center;gap:var(--internal-spacing-sm)}.section-time,.section-venue{color:var(--internal-muted-foreground);font-size:var(--internal-font-size-sm);display:flex;align-items:center;gap:var(--internal-spacing-xs)}.section-time,.admission-time{margin-bottom:var(--internal-spacing-xs)}.section-time svg,.section-venue svg,.admission-time svg,.admission-venue svg{width:calc(var(--internal-spacing-sm) + var(--internal-spacing-xs));height:calc(var(--internal-spacing-sm) + var(--internal-spacing-xs));flex-shrink:0;opacity:0.8}.admissions-list{padding:0}.admission-card{border-bottom:1px solid var(--internal-border);padding:var(--internal-spacing-md) var(--internal-spacing-lg);position:relative;transition:background-color var(--internal-transition-base);cursor:default}.admission-card:focus-visible{outline:2px solid var(--internal-ring);outline-offset:-2px;z-index:1}.admission-card.sold-out{background:var(--internal-card)}.admission-card.unavailable{opacity:0.72}.admission-card.sold-out .admission-price{opacity:0.5}.admission-card:last-child{border-bottom:none}.admission-content{display:flex;justify-content:space-between;align-items:center}.admission-details{flex:1}.admission-header{display:flex;justify-content:space-between;align-items:flex-start;gap:var(--internal-spacing-md);margin-bottom:var(--internal-spacing-sm)}.admission-header-text{flex:1;min-width:0}.admission-title{color:var(--internal-foreground);font-size:var(--internal-font-size-lg);font-weight:var(--internal-font-weight-semibold);margin-bottom:0;display:flex;align-items:center;gap:var(--internal-spacing-sm)}.admission-subtitle{color:var(--internal-muted-foreground);font-size:var(--internal-font-size-sm);margin-top:var(--internal-spacing-xs);line-height:1.4}.more-info-badge{display:inline-flex;align-items:center;gap:calc(var(--internal-spacing-xs) * 1.5);padding:calc(var(--internal-spacing-xs) * 1.5) var(--internal-spacing-sm);background:oklch(from var(--internal-info) l c h / 0.08);color:var(--internal-info-foreground);border-radius:calc(var(--internal-radius) - 2px);font-size:var(--internal-font-size-xs);font-weight:var(--internal-font-weight-medium);cursor:pointer;transition:all var(--internal-transition-fast);white-space:nowrap;flex-shrink:0}.more-info-badge:hover{background:oklch(from var(--internal-info) l c h / 0.16)}.more-info-badge:focus-visible{outline:2px solid var(--internal-ring);outline-offset:2px}.more-info-badge svg{flex-shrink:0}.admission-time,.admission-venue{color:var(--internal-muted-foreground);font-size:var(--internal-font-size-sm);display:flex;align-items:center;gap:var(--internal-spacing-xs)}.admission-venue{margin-bottom:var(--internal-spacing-sm)}.solo-admission .admission-content{flex-direction:column;align-items:stretch}.solo-admission .admission-details{width:100%}.solo-admission .admission-price-info{margin-top:var(--internal-spacing-md);display:flex;justify-content:space-between;align-items:center;width:100%}.solo-admission .quantity-controls{margin-left:auto;flex-shrink:0}.sold-out-badge{display:inline-flex;align-items:center;justify-content:center;padding:0;background:transparent;color:var(--internal-destructive);border:none;font-size:var(--internal-font-size-sm);font-weight:var(--internal-font-weight-medium);text-transform:uppercase;letter-spacing:0.05em;margin-left:auto;opacity:0.7}.admission-price-info{display:flex;align-items:center;justify-content:space-between;gap:var(--internal-spacing-sm);margin-bottom:var(--internal-spacing-sm);width:100%}.admission-price-wrapper{display:flex;flex-direction:column;row-gap:calc(var(--internal-spacing-xs) * 0.5)}.admission-price{color:var(--internal-foreground);font-size:var(--internal-font-size-xl);font-weight:var(--internal-font-weight-bold);letter-spacing:-0.025em;line-height:1.1}.admission-price-row{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--internal-spacing-sm)}.admission-price-original{color:var(--internal-muted-foreground);font-size:var(--internal-font-size-base);text-decoration:line-through}.admission-booking-fee{color:var(--internal-muted-foreground);font-size:var(--internal-font-size-xs);font-weight:var(--internal-font-weight-medium);line-height:1.2}.admission-savings,.admission-availability{font-size:var(--internal-font-size-xs);font-weight:var(--internal-font-weight-medium);line-height:1.2}.admission-savings{color:var(--internal-success)}.admission-availability{color:var(--internal-warning)}.admission-sale-label{display:block;margin-top:var(--internal-spacing-xs);color:var(--internal-muted-foreground);font-size:var(--internal-font-size-sm);font-weight:var(--internal-font-weight-medium);line-height:1.35}.admission-sale-label.success{color:var(--internal-success)}.quantity-controls{display:inline-flex;align-items:center;gap:0;background:var(--internal-secondary);border-radius:calc(var(--internal-radius) - 2px);overflow:hidden;transition:all var(--internal-transition-fast)}.quantity-controls:has(.quantity-value:focus-visible){box-shadow:0 0 0 2px var(--internal-ring)}.quantity-btn{width:calc(var(--internal-spacing-lg) * 1.5);height:calc(var(--internal-spacing-lg) * 1.5);border:none;background:transparent;color:var(--internal-muted-foreground);font-size:var(--internal-font-size-base);font-weight:var(--internal-font-weight-medium);cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all var(--internal-transition-fast);position:relative}.quantity-btn:focus-visible{outline:2px solid var(--internal-ring);outline-offset:-2px;z-index:1}.quantity-btn:hover:not(:disabled){background:var(--internal-accent);color:var(--internal-accent-foreground)}.quantity-btn:active:not(:disabled){transform:scale(0.95)}.quantity-btn:disabled{opacity:0.6;cursor:not-allowed;background:var(--internal-secondary);color:var(--internal-muted-foreground);border-color:var(--internal-border)}.quantity-btn.decrease{border-right:1px solid var(--internal-input)}.quantity-btn.increase{border-left:1px solid var(--internal-input)}.quantity-value{appearance:textfield;width:2.75rem;height:calc(var(--internal-spacing-lg) * 1.5);border:none;background:transparent;min-width:2.5rem;text-align:center;font-size:var(--internal-font-size-sm);font-weight:var(--internal-font-weight-semibold);color:var(--internal-foreground);padding:0 var(--internal-spacing-xs)}.quantity-value:focus-visible{outline:none}.quantity-value::-webkit-inner-spin-button,.quantity-value::-webkit-outer-spin-button{appearance:none;margin:0}.quantity-value:disabled{opacity:0.6;cursor:not-allowed}.sold-out-controls{display:inline-flex;align-items:center;justify-content:center;min-width:calc(var(--internal-spacing-lg) * 1.5 * 2 + 2.5rem);height:calc(var(--internal-spacing-lg) * 1.5);padding:0;background:transparent;border:none;box-shadow:none}.sold-out-controls,.sold-out-text{color:var(--internal-destructive);font-size:var(--internal-font-size-xs);font-weight:var(--internal-font-weight-medium);letter-spacing:0.025em;text-transform:uppercase}.sold-out-controls.success,.sold-out-controls.success .sold-out-text{color:var(--internal-success)}.checkout-actions{margin:var(--internal-spacing-lg) 0 0 0;width:100%}.coupon-panel{margin-bottom:var(--internal-spacing-md)}.coupon-row{position:relative;display:flex;align-items:center;width:100%;min-width:0;overflow:hidden;background:var(--internal-background);background-clip:padding-box;border-radius:var(--internal-radius);transition:border-color var(--internal-transition-fast)}.coupon-row:focus-within{border-color:var(--internal-ring)}.coupon-row:has(input[aria-invalid="true"]){border-color:var(--internal-destructive)}.coupon-row:has(input:disabled){opacity:0.64}.coupon-row input{width:100%;min-width:0;padding:calc(var(--internal-spacing-sm) - 1px)
23616
+ );--card-foreground:oklch(0.967 0.001 286.375);--popover:oklch(0.21 0.006 285.885);--popover-foreground:oklch(0.967 0.001 286.375);--primary:oklch(0.537 0.1554 255);--primary-foreground:oklch(0.985 0 0);--secondary:oklch(1 0 0 / 6%);--secondary-foreground:oklch(0.967 0.001 286.375);--muted:oklch(1 0 0 / 6%);--muted-foreground:oklch(0.705 0.015 286.067);--accent:oklch(1 0 0 / 6%);--accent-foreground:oklch(0.967 0.001 286.375);--destructive:oklch(0.637 0.237 25.331);--destructive-foreground:oklch(0.704 0.191 22.216);--border:oklch(1 0 0 / 12%);--input:oklch(1 0 0 / 12%);--ring:oklch(0.552 0.016 285.938);--success:oklch(0.696 0.17 162.48);--warning:oklch(0.769 0.188 70.08);--info:oklch(0.623 0.214 259.815);--info-foreground:oklch(0.707 0.165 254.624)}.tickets-wrapper{padding:0;width:100%}.tickets-heading{color:var(--internal-foreground);font-size:var(--internal-font-size-lg);font-weight:var(--internal-font-weight-semibold);margin:0 0 var(--internal-spacing-md)}.ticket-section.loading-ticket-section{overflow:visible;background:transparent;border:0;box-shadow:none}.loading-ticket-section .admissions-list{display:flex;flex-direction:column;gap:var(--internal-spacing-sm)}.admission-card.loading-admission{min-height:5.25rem;padding:0;background:oklch(from var(--internal-foreground) l c h / 0.07);border:0;border-radius:var(--internal-radius);box-shadow:none;pointer-events:none;animation:loading-card 1.6s ease-out infinite}@keyframes loading-card{0%,100%{opacity:0.48}50%{opacity:0.74}}.passcode-form,.passcode-form input,.ticket-section,.more-info-badge,.quantity-controls,.sold-out-controls,.coupon-row,.coupon-apply,.coupon-remove{border:1px solid var(--internal-input);box-shadow:var(--internal-shadow-edge-light)}.external-ticket-button,.checkout-btn{display:inline-flex;align-items:center;justify-content:center;background:var(--internal-primary);color:var(--internal-primary-foreground);border:1px solid oklch(from var(--internal-primary) calc(l - 0.08) c h);border-radius:calc(var(--internal-radius) - 2px);cursor:pointer;box-shadow:var(--internal-shadow-edge-light);transition:all var(--internal-transition-fast)}.external-ticket-button:hover,.checkout-btn:hover:not(:disabled){background:oklch(from var(--internal-primary) calc(l - 0.08) c h);transform:translateY(-1px)}.external-ticket-button:focus-visible{outline:2px solid var(--internal-ring);outline-offset:2px}.passcode-form{display:flex;flex-direction:column;gap:var(--internal-spacing-sm);padding:var(--internal-spacing-lg);margin-bottom:var(--internal-spacing-md);background:var(--internal-card);border-radius:var(--internal-radius)}.passcode-form h2{color:var(--internal-foreground);font-size:var(--internal-font-size-base);font-weight:var(--internal-font-weight-semibold);line-height:1.3}.passcode-form p{color:var(--internal-muted-foreground);font-size:var(--internal-font-size-sm);line-height:1.5}.door-alert,.empty-ticketing-state,.message-state{display:flex;flex-direction:column;gap:calc(var(--internal-spacing-xs) * 1.5);margin-bottom:var(--internal-spacing-md);padding:0;background:transparent;border:none;border-radius:0;box-shadow:none}.door-alert strong,.empty-ticketing-state strong,.message-state strong{color:var(--internal-foreground);font-size:var(--internal-font-size-base);font-weight:var(--internal-font-weight-semibold);line-height:1.3}.door-alert span,.empty-ticketing-state span,.message-state span{color:var(--internal-muted-foreground);font-size:var(--internal-font-size-sm);line-height:1.4}.external-ticket-button{flex-direction:column;gap:calc(var(--internal-spacing-xs) * 0.5);width:100%;padding:calc(var(--internal-spacing-sm) + var(--internal-spacing-xs))
23617
+ var(--internal-spacing-lg);text-decoration:none}.external-ticket-panel{display:flex;flex-direction:column;gap:var(--internal-spacing-md)}.external-ticket-warning{color:var(--internal-muted-foreground);font-size:var(--internal-font-size-sm);font-weight:var(--internal-font-weight-medium);line-height:1.35}.external-ticket-label{font-size:var(--internal-font-size-base);font-weight:var(--internal-font-weight-bold);line-height:1.2}.external-ticket-domain{font-size:var(--internal-font-size-xs);font-weight:var(--internal-font-weight-medium);line-height:1.2;opacity:0.82}.passcode-form input{width:100%;min-width:0;padding:calc(var(--internal-spacing-sm) + 0.125rem)
23618
+ var(--internal-spacing-sm);background:var(--internal-card);color:var(--internal-foreground);border-radius:calc(var(--internal-radius) - 2px);font:inherit}.passcode-form input:disabled{opacity:0.6;cursor:not-allowed}.ticket-section{background:var(--internal-card);border-radius:var(--internal-radius);margin:0 0 var(--internal-spacing-lg) 0;overflow:hidden;width:100%;transition:all var(--internal-transition-base)}.tickets-wrapper>.ticket-section:last-child{margin-bottom:0}.ticket-section.section-sold-out{position:relative}.ticket-section.section-sold-out .section-header{padding-bottom:var(--internal-spacing-md)}.ticket-section.section-sold-out .section-name,.ticket-section.section-sold-out .section-time,.ticket-section.section-sold-out .section-venue{opacity:0.8}.ticket-section.section-sold-out .admissions-list{opacity:0.6;pointer-events:none;filter:grayscale(0.3)}.ticket-section.section-sold-out .admission-card{background:var(--internal-card)}.ticket-section.section-sold-out .quantity-controls,.ticket-section.section-sold-out .sold-out-controls{opacity:0.7}.section-header{padding:var(--internal-spacing-md) var(--internal-spacing-lg);border-bottom:1px solid var(--internal-border);background:var(--internal-card)}.section-name{color:var(--internal-foreground);font-size:var(--internal-font-size-lg);font-weight:var(--internal-font-weight-semibold);letter-spacing:-0.025em;margin:0 0 var(--internal-spacing-xs) 0;display:flex;align-items:center;gap:var(--internal-spacing-sm)}.section-time,.section-venue{color:var(--internal-muted-foreground);font-size:var(--internal-font-size-sm);display:flex;align-items:center;gap:var(--internal-spacing-xs)}.section-time,.admission-time{margin-bottom:var(--internal-spacing-xs)}.section-time svg,.section-venue svg,.admission-time svg,.admission-venue svg{width:calc(var(--internal-spacing-sm) + var(--internal-spacing-xs));height:calc(var(--internal-spacing-sm) + var(--internal-spacing-xs));flex-shrink:0;opacity:0.8}.admissions-list{padding:0}.admission-card{border-bottom:1px solid var(--internal-border);padding:var(--internal-spacing-md) var(--internal-spacing-lg);position:relative;transition:background-color var(--internal-transition-base);cursor:default}.admission-card:focus-visible{outline:2px solid var(--internal-ring);outline-offset:-2px;z-index:1}.admission-card.sold-out{background:var(--internal-card)}.admission-card.unavailable{opacity:0.72}.admission-card.sold-out .admission-price{opacity:0.5}.admission-card:last-child{border-bottom:none}.admission-content{display:flex;justify-content:space-between;align-items:center}.admission-details{flex:1}.admission-header{display:flex;justify-content:space-between;align-items:flex-start;gap:var(--internal-spacing-md);margin-bottom:var(--internal-spacing-sm)}.admission-header-text{flex:1;min-width:0}.admission-title{color:var(--internal-foreground);font-size:var(--internal-font-size-lg);font-weight:var(--internal-font-weight-semibold);margin-bottom:0;display:flex;align-items:center;gap:var(--internal-spacing-sm)}.admission-subtitle{color:var(--internal-muted-foreground);font-size:var(--internal-font-size-sm);margin-top:var(--internal-spacing-xs);line-height:1.4}.more-info-badge{display:inline-flex;align-items:center;gap:calc(var(--internal-spacing-xs) * 1.5);padding:calc(var(--internal-spacing-xs) * 1.5) var(--internal-spacing-sm);background:oklch(from var(--internal-info) l c h / 0.08);color:var(--internal-info-foreground);border-radius:calc(var(--internal-radius) - 2px);font-size:var(--internal-font-size-xs);font-weight:var(--internal-font-weight-medium);cursor:pointer;transition:all var(--internal-transition-fast);white-space:nowrap;flex-shrink:0}.more-info-badge:hover{background:oklch(from var(--internal-info) l c h / 0.16)}.more-info-badge:focus-visible{outline:2px solid var(--internal-ring);outline-offset:2px}.more-info-badge svg{flex-shrink:0}.admission-time,.admission-venue{color:var(--internal-muted-foreground);font-size:var(--internal-font-size-sm);display:flex;align-items:center;gap:var(--internal-spacing-xs)}.admission-venue{margin-bottom:var(--internal-spacing-sm)}.solo-admission .admission-content{flex-direction:column;align-items:stretch}.solo-admission .admission-details{width:100%}.solo-admission .admission-price-info{margin-top:var(--internal-spacing-md);display:flex;justify-content:space-between;align-items:center;width:100%}.solo-admission .quantity-controls{margin-left:auto;flex-shrink:0}.admission-price-info{display:flex;align-items:center;justify-content:space-between;gap:var(--internal-spacing-sm);margin-bottom:var(--internal-spacing-sm);width:100%}.admission-price-wrapper{display:flex;flex-direction:column;row-gap:calc(var(--internal-spacing-xs) * 0.5)}.admission-price{color:var(--internal-foreground);font-size:var(--internal-font-size-xl);font-weight:var(--internal-font-weight-bold);letter-spacing:-0.025em;line-height:1.1}.admission-price-row{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--internal-spacing-sm)}.admission-price-original{color:var(--internal-muted-foreground);font-size:var(--internal-font-size-base);text-decoration:line-through}.admission-booking-fee{color:var(--internal-muted-foreground);font-size:var(--internal-font-size-xs);font-weight:var(--internal-font-weight-medium);line-height:1.2}.admission-savings,.admission-availability{font-size:var(--internal-font-size-xs);font-weight:var(--internal-font-weight-medium);line-height:1.2}.admission-savings{color:var(--internal-success)}.admission-availability{color:var(--internal-warning)}.admission-sale-label{display:block;margin-top:var(--internal-spacing-xs);color:var(--internal-muted-foreground);font-size:var(--internal-font-size-sm);font-weight:var(--internal-font-weight-medium);line-height:1.35}.admission-sale-label.success{color:var(--internal-success)}.quantity-controls{display:inline-flex;align-items:center;gap:0;background:var(--internal-secondary);border-radius:calc(var(--internal-radius) - 2px);overflow:hidden;transition:all var(--internal-transition-fast)}.quantity-controls:has(.quantity-value:focus-visible){box-shadow:0 0 0 2px var(--internal-ring)}.quantity-btn{width:calc(var(--internal-spacing-lg) * 1.5);height:calc(var(--internal-spacing-lg) * 1.5);border:none;background:transparent;color:var(--internal-muted-foreground);font-size:var(--internal-font-size-base);font-weight:var(--internal-font-weight-medium);cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all var(--internal-transition-fast);position:relative}.quantity-btn:focus-visible{outline:2px solid var(--internal-ring);outline-offset:-2px;z-index:1}.quantity-btn:hover:not(:disabled){background:var(--internal-accent);color:var(--internal-accent-foreground)}.quantity-btn:active:not(:disabled){transform:scale(0.95)}.quantity-btn:disabled{opacity:0.6;cursor:not-allowed;background:var(--internal-secondary);color:var(--internal-muted-foreground);border-color:var(--internal-border)}.quantity-btn.decrease{border-right:1px solid var(--internal-input)}.quantity-btn.increase{border-left:1px solid var(--internal-input)}.quantity-value{appearance:textfield;width:2.75rem;height:calc(var(--internal-spacing-lg) * 1.5);border:none;background:transparent;min-width:2.5rem;text-align:center;font-size:var(--internal-font-size-sm);font-weight:var(--internal-font-weight-semibold);color:var(--internal-foreground);padding:0 var(--internal-spacing-xs)}.quantity-value:focus-visible{outline:none}.quantity-value::-webkit-inner-spin-button,.quantity-value::-webkit-outer-spin-button{appearance:none;margin:0}.quantity-value:disabled{opacity:0.6;cursor:not-allowed}.sold-out-controls{display:inline-flex;align-items:center;justify-content:center;min-width:calc(var(--internal-spacing-lg) * 1.5 * 2 + 2.5rem);height:calc(var(--internal-spacing-lg) * 1.5);padding:0;background:transparent;border:none;box-shadow:none}.sold-out-controls,.sold-out-text{color:var(--internal-destructive);font-size:var(--internal-font-size-xs);font-weight:var(--internal-font-weight-medium);letter-spacing:0.025em;text-transform:uppercase}.sold-out-controls.success,.sold-out-controls.success .sold-out-text{color:var(--internal-success)}.checkout-actions{margin:var(--internal-spacing-lg) 0 0 0;width:100%}.coupon-panel{margin-bottom:var(--internal-spacing-md)}.coupon-row{position:relative;display:flex;align-items:center;width:100%;min-width:0;overflow:hidden;background:var(--internal-background);background-clip:padding-box;border-radius:var(--internal-radius);transition:border-color var(--internal-transition-fast)}.coupon-row:focus-within{border-color:var(--internal-ring)}.coupon-row:has(input[aria-invalid="true"]){border-color:var(--internal-destructive)}.coupon-row:has(input:disabled){opacity:0.64}.coupon-row input{width:100%;min-width:0;padding:calc(var(--internal-spacing-sm) - 1px)
23619
23619
  calc(var(--internal-spacing-xl) * 2.75)
23620
23620
  calc(var(--internal-spacing-sm) - 1px)
23621
23621
  calc(var(--internal-spacing-md) - 1px);background:var(--internal-card);color:var(--internal-foreground);border:none;border-radius:inherit;font:inherit;font-size:var(--internal-font-size-sm);line-height:1.25rem;outline:none}.coupon-row input::placeholder{color:oklch(from var(--internal-muted-foreground) l c h / 0.64)}.coupon-row input:disabled{cursor:not-allowed}.coupon-apply,.coupon-remove{position:absolute;right:calc((var(--internal-spacing-xs) * 1.5) - 3px);top:50%;transform:translateY(-50%);padding:calc(var(--internal-spacing-xs) * 1.25) var(--internal-spacing-sm);background:var(--internal-secondary);color:var(--internal-foreground);border-radius:calc(var(--internal-radius) - 2px);font-size:var(--internal-font-size-xs);font-weight:var(--internal-font-weight-medium);cursor:pointer;transition:all var(--internal-transition-fast)}.coupon-apply:hover:not(:disabled),.coupon-remove:hover:not(:disabled){background:oklch(from var(--internal-accent) l c h / 0.8)}.coupon-apply:focus-visible,.coupon-remove:focus-visible{outline:2px solid var(--internal-ring);outline-offset:-1px}.coupon-apply:disabled,.coupon-remove:disabled{opacity:0.6;cursor:not-allowed}.checkout-btn{width:100%;padding:calc(var(--internal-spacing-sm) + var(--internal-spacing-xs))
23622
- var(--internal-spacing-lg);font-size:var(--internal-font-size-base);font-weight:var(--internal-font-weight-bold);line-height:1.25;position:relative;overflow:hidden}.checkout-btn:focus-visible{outline:2px solid var(--internal-ring);outline-offset:2px}.checkout-btn:active:not(:disabled){transform:translateY(0)}.checkout-btn:disabled{opacity:0.5;cursor:not-allowed}.checkout-spinner-wrapper{display:inline-flex;align-items:center;justify-content:center;height:1.25em;vertical-align:middle}.checkout-spinner{width:1.125em;height:1.125em;animation:checkout-spinner 0.8s linear infinite}@keyframes checkout-spinner{to{transform:rotate(360deg)}}.sticky-checkout-bar{position:fixed;right:0;bottom:0;left:0;z-index:40;display:none;padding:var(--internal-spacing-md);background:var(--internal-card);border-top:1px solid var(--internal-border);box-shadow:var(--internal-shadow-lg)}.sticky-checkout-btn.selection-prompt{animation:selection-prompt-shake 400ms ease-in-out}@keyframes selection-prompt-shake{0%,100%{transform:translateX(0)}25%{transform:translateX(-4px)}75%{transform:translateX(4px)}}.loading-state{display:flex;justify-content:center;align-items:center;padding:var(--internal-spacing-xl);text-align:center;min-height:200px}.error-banner{background:oklch(
23623
- from var(--internal-destructive) calc(l + 0.4) calc(c * 0.2) h / 0.05
23624
- );border:1px solid oklch(from var(--internal-destructive) l c h / 0.2);border-radius:var(--internal-radius);padding:var(--internal-spacing-lg);margin:var(--internal-spacing-lg);text-align:center}.error-banner strong{display:block;color:var(--internal-destructive);font-size:var(--internal-font-size-lg);margin-bottom:var(--internal-spacing-sm)}.error-banner p{color:var(--internal-muted-foreground);margin-bottom:var(--internal-spacing-md)}.retry-button{background:var(--internal-primary);color:var(--internal-primary-foreground);border:1px solid oklch(from var(--internal-primary) calc(l - 0.08) c h);padding:calc(var(--internal-spacing-sm) + var(--internal-spacing-xs))
23622
+ var(--internal-spacing-lg);font-size:var(--internal-font-size-base);font-weight:var(--internal-font-weight-bold);line-height:1.25;position:relative;overflow:hidden}.checkout-btn:focus-visible{outline:2px solid var(--internal-ring);outline-offset:2px}.checkout-btn:active:not(:disabled){transform:translateY(0)}.checkout-btn:disabled{opacity:0.5;cursor:not-allowed}.checkout-spinner-wrapper{display:inline-flex;align-items:center;justify-content:center;height:1.25em;vertical-align:middle}.checkout-spinner{width:1.125em;height:1.125em;animation:checkout-spinner 0.8s linear infinite}@keyframes checkout-spinner{to{transform:rotate(360deg)}}.sticky-checkout-bar{position:fixed;right:0;bottom:0;left:0;z-index:40;display:none;padding:var(--internal-spacing-md);background:var(--internal-card);border-top:1px solid var(--internal-border);box-shadow:var(--internal-shadow-lg)}.sticky-checkout-btn.selection-prompt{animation:selection-prompt-shake 400ms ease-in-out}@keyframes selection-prompt-shake{0%,100%{transform:translateX(0)}25%{transform:translateX(-4px)}75%{transform:translateX(4px)}}.retry-button{align-self:flex-start;margin-top:var(--internal-spacing-xs);background:var(--internal-primary);color:var(--internal-primary-foreground);border:1px solid oklch(from var(--internal-primary) calc(l - 0.08) c h);padding:calc(var(--internal-spacing-sm) + var(--internal-spacing-xs))
23625
23623
  var(--internal-spacing-lg);border-radius:calc(var(--internal-radius) - 2px);font-size:var(--internal-font-size-sm);font-weight:var(--internal-font-weight-medium);cursor:pointer;transition:all var(--internal-transition-fast);box-shadow:var(--internal-shadow-edge-light)}.retry-button:focus-visible{outline:2px solid var(--internal-ring);outline-offset:2px}.retry-button:hover{background:oklch(from var(--internal-primary) calc(l - 0.08) c h);transform:translateY(-1px)}.retry-button:active{transform:translateY(0)}.error-message{background:oklch(
23626
23624
  from var(--internal-destructive) calc(l + 0.4) calc(c * 0.2) h / 0.05
23627
- );border:1px solid oklch(from var(--internal-destructive) l c h / 0.2);color:var(--internal-destructive);padding:var(--internal-spacing-sm) var(--internal-spacing-md);border-radius:var(--internal-radius);margin-bottom:var(--internal-spacing-md);font-size:var(--internal-font-size-sm)}@media (min-width: 768px){.ticket-section{border-radius:var(--internal-radius);margin:0 0 var(--internal-spacing-md) 0}}@media (max-width: 767px){:host([data-sticky-checkout="true"]) .session-services-ticketing-container{padding-bottom:calc(var(--internal-spacing-xl) * 3)}.sticky-checkout-bar{display:block}}.modal-backdrop{position:fixed;inset:0;z-index:50;display:flex;align-items:center;justify-content:center;padding:var(--internal-spacing-md);background:var(--internal-backdrop);backdrop-filter:blur(4px);animation:modal-backdrop-fade-in var(--internal-transition-base) ease-out}@keyframes modal-backdrop-fade-in{from{opacity:0}to{opacity:1}}.modal-content{position:relative;width:100%;max-width:32rem;max-height:calc(100vh - var(--internal-spacing-xl) * 2);overflow-y:auto;background:var(--internal-popover);color:var(--internal-popover-foreground);border:1px solid var(--internal-border);border-radius:var(--internal-radius);padding:var(--internal-spacing-lg);box-shadow:var(--internal-shadow-xl);animation:modal-content-scale-in var(--internal-transition-base) ease-out}@keyframes modal-content-scale-in{from{opacity:0;transform:scale(0.98)}to{opacity:1;transform:scale(1)}}.modal-close-btn{position:absolute;top:var(--internal-spacing-sm);right:var(--internal-spacing-sm);display:flex;align-items:center;justify-content:center;width:1.75rem;height:1.75rem;padding:0;background:transparent;border:1px solid transparent;border-radius:calc(var(--internal-radius) - 4px);color:var(--internal-muted-foreground);cursor:pointer;opacity:0.72;transition:all var(--internal-transition-fast)}.modal-close-btn:hover{opacity:1;background:var(--internal-accent)}.modal-close-btn:focus-visible{outline:2px solid var(--internal-ring);outline-offset:1px;opacity:1}.modal-header{margin-bottom:var(--internal-spacing-md);padding-right:var(--internal-spacing-xl)}.modal-title{font-size:var(--internal-font-size-xl);font-weight:var(--internal-font-weight-semibold);color:var(--internal-foreground);margin:0;line-height:1.2}.modal-subtitle{color:var(--internal-muted-foreground);font-size:var(--internal-font-size-sm);margin-top:var(--internal-spacing-xs);line-height:1.4}.modal-description{color:var(--internal-foreground);font-size:var(--internal-font-size-base);line-height:1.6;white-space:pre-wrap;margin:0}`;
23625
+ );border:1px solid oklch(from var(--internal-destructive) l c h / 0.2);color:var(--internal-destructive);padding:var(--internal-spacing-sm) var(--internal-spacing-md);border-radius:var(--internal-radius);margin-bottom:var(--internal-spacing-md);font-size:var(--internal-font-size-sm)}@media (min-width: 768px){.ticket-section{border-radius:var(--internal-radius);margin:0 0 var(--internal-spacing-md) 0}}@media (max-width: 767px){:host([data-sticky-checkout="true"]) .session-services-ticketing-container{padding-bottom:calc(var(--internal-spacing-xl) * 3)}:host([data-sticky-checkout="true"]) .checkout-actions>.checkout-btn,:host([data-sticky-checkout="true"]) .inline-external-ticket-button{display:none}.sticky-checkout-bar{display:block}}.modal-backdrop{position:fixed;inset:0;z-index:50;display:flex;align-items:center;justify-content:center;padding:var(--internal-spacing-md);background:var(--internal-backdrop);backdrop-filter:blur(4px);animation:modal-backdrop-fade-in var(--internal-transition-base) ease-out}@keyframes modal-backdrop-fade-in{from{opacity:0}to{opacity:1}}.modal-content{position:relative;width:100%;max-width:32rem;max-height:calc(100vh - var(--internal-spacing-xl) * 2);overflow-y:auto;background:var(--internal-popover);color:var(--internal-popover-foreground);border:1px solid var(--internal-border);border-radius:var(--internal-radius);padding:var(--internal-spacing-lg);box-shadow:var(--internal-shadow-xl);animation:modal-content-scale-in var(--internal-transition-base) ease-out}@keyframes modal-content-scale-in{from{opacity:0;transform:scale(0.98)}to{opacity:1;transform:scale(1)}}.modal-close-btn{position:absolute;top:var(--internal-spacing-sm);right:var(--internal-spacing-sm);display:flex;align-items:center;justify-content:center;width:1.75rem;height:1.75rem;padding:0;background:transparent;border:1px solid transparent;border-radius:calc(var(--internal-radius) - 4px);color:var(--internal-muted-foreground);cursor:pointer;opacity:0.72;transition:all var(--internal-transition-fast)}.modal-close-btn:hover{opacity:1;background:var(--internal-accent)}.modal-close-btn:focus-visible{outline:2px solid var(--internal-ring);outline-offset:1px;opacity:1}.modal-header{margin-bottom:var(--internal-spacing-md);padding-right:var(--internal-spacing-xl)}.modal-title{font-size:var(--internal-font-size-xl);font-weight:var(--internal-font-weight-semibold);color:var(--internal-foreground);margin:0;line-height:1.2}.modal-subtitle{color:var(--internal-muted-foreground);font-size:var(--internal-font-size-sm);margin-top:var(--internal-spacing-xs);line-height:1.4}.modal-description{color:var(--internal-foreground);font-size:var(--internal-font-size-base);line-height:1.6;white-space:pre-wrap;margin:0}`;
23628
23626
 
23629
23627
  const quoteTotal = (quote) => quote.price?.total ?? 0;
23630
23628
  const QUOTE_DEBOUNCE_MS = 150;
@@ -23663,6 +23661,16 @@ function eventVenueName(event) {
23663
23661
  function optionalId(id) {
23664
23662
  return id || undefined;
23665
23663
  }
23664
+ function urlDomain(url) {
23665
+ if (!url)
23666
+ return "external site";
23667
+ try {
23668
+ return new URL(url).hostname.replace(/^www\./, "");
23669
+ }
23670
+ catch {
23671
+ return "external site";
23672
+ }
23673
+ }
23666
23674
  function admissionAriaLabel(admission, section, status) {
23667
23675
  if (section)
23668
23676
  return `${admission.name} in ${section.name} - ${status}`;
@@ -24660,29 +24668,29 @@ const SessionsTicketing = class {
24660
24668
  }
24661
24669
  return (index.h(index.h.Fragment, null, this.renderEventTimeAndLocation(event), this.renderPriceAndControls(admission, sectionId, state, mode)));
24662
24670
  }
24663
- renderSectionHeader(section, admissions, isSectionSoldOut) {
24664
- return (index.h("div", { class: "section-header" }, index.h("h2", { class: "section-name" }, section.name, isSectionSoldOut && index.h("span", { class: "sold-out-badge" }, "Sold Out")), this.renderAdmissionTime(admissions[0], "section-time"), this.renderSectionLocation(section)));
24671
+ renderSectionHeader(section, admissions) {
24672
+ return (index.h("div", { class: "section-header" }, index.h("h2", { class: "section-name" }, section.name), this.renderAdmissionTime(admissions[0], "section-time"), this.renderSectionLocation(section)));
24665
24673
  }
24666
24674
  renderSectionWithAdmissions(section, admissions, event, mode) {
24667
24675
  const soldOut = isSectionSoldOut({
24668
24676
  admissions,
24669
24677
  section,
24670
24678
  });
24671
- return (index.h("div", { class: `ticket-section ${soldOut ? "section-sold-out" : ""}`, key: section.id }, this.renderSectionHeader(section, admissions, soldOut), index.h("div", { class: "admissions-list" }, admissions.map((admission) => this.renderAdmission(admission, event, section, soldOut, mode)))));
24679
+ return (index.h("div", { class: `ticket-section ${soldOut ? "section-sold-out" : ""}`, key: section.id }, this.renderSectionHeader(section, admissions), index.h("div", { class: "admissions-list" }, admissions.map((admission) => this.renderAdmission(admission, event, section, soldOut, mode)))));
24672
24680
  }
24673
24681
  renderLoadingState() {
24674
- return (index.h(index.Host, { "data-theme": this.currentTheme }, index.h("div", { class: "loading-state" }, "Loading event details...")));
24682
+ return (index.h(index.Host, { "data-theme": this.currentTheme }, index.h("div", { class: "session-services-ticketing-container" }, index.h("div", { class: "tickets-wrapper" }, index.h("h2", { class: "tickets-heading" }, "Get Tickets"), index.h("div", { class: "ticket-section loading-ticket-section" }, index.h("div", { class: "admissions-list" }, [0, 1, 2].map((item) => (index.h("div", { "aria-hidden": "true", class: "admission-card loading-admission", key: item })))))))));
24675
24683
  }
24676
24684
  renderErrorState() {
24677
24685
  if (this.passcodeDenied)
24678
24686
  return this.renderPasscodeState();
24679
- return (index.h(index.Host, { "data-theme": this.currentTheme }, index.h("div", { class: "session-services-ticketing-container" }, index.h("div", { class: "error-banner" }, index.h("strong", null, "Unable to load event"), index.h("p", null, this.error), index.h("button", { type: "button", class: "retry-button", onClick: () => this.loadEventData() }, "Try Again")))));
24687
+ return (index.h(index.Host, { "data-theme": this.currentTheme }, index.h("div", { class: "session-services-ticketing-container" }, index.h("div", { class: "message-state" }, index.h("strong", null, "Tickets Couldn\u2019t Load"), index.h("span", null, "We couldn\u2019t load ticket details. Try again in a moment."), index.h("button", { type: "button", class: "retry-button", onClick: () => this.loadEventData() }, "Try Again")))));
24680
24688
  }
24681
24689
  renderPasscodeState() {
24682
24690
  return (index.h(index.Host, { "data-theme": this.currentTheme }, index.h("div", { class: "session-services-ticketing-container" }, index.h("form", { class: "passcode-form", onSubmit: (e) => this.submitPasscode(e) }, index.h("h2", null, "Enter passcode"), index.h("p", null, "Enter the event passcode to view tickets and event details."), index.h("input", { type: "text", name: "passcode", value: this.passcodeInput, onInput: this.handlePasscodeInput, autocomplete: "one-time-code", placeholder: "Passcode", "aria-label": "Passcode" }), this.passcodeDenied && this.activePasscode && (index.h("span", { class: "error-message" }, "Incorrect passcode")), index.h("button", { type: "submit", class: "checkout-btn", disabled: !this.passcodeInput.trim() }, "Unlock event")))));
24683
24691
  }
24684
24692
  renderNotFoundState() {
24685
- return (index.h(index.Host, { "data-theme": this.currentTheme }, index.h("div", { class: "session-services-ticketing-container" }, index.h("div", { class: "error-banner" }, index.h("strong", null, "Event not found"), index.h("p", null, "The requested event could not be found.")))));
24693
+ return (index.h(index.Host, { "data-theme": this.currentTheme }, index.h("div", { class: "session-services-ticketing-container" }, index.h("div", { class: "message-state" }, index.h("strong", null, "Event not found"), index.h("span", null, "We couldn\u2019t find this event. The link may be incorrect or expired.")))));
24686
24694
  }
24687
24695
  renderCouponPanel() {
24688
24696
  const hasInput = this.couponInput.trim().length > 0;
@@ -24764,6 +24772,13 @@ const SessionsTicketing = class {
24764
24772
  return null;
24765
24773
  return (index.h("div", { class: "sticky-checkout-bar" }, index.h("button", { type: "button", class: `checkout-btn sticky-checkout-btn ${this.selectionPrompt ? "selection-prompt" : ""}`, onClick: () => this.handleStickyCheckoutClick(state), disabled: this.isStickyCheckoutDisabled(state), "aria-label": this.quoteLoading ? "Updating" : undefined }, this.renderStickyCheckoutButtonContent(state))));
24766
24774
  }
24775
+ renderStickyExternalTicketing(state) {
24776
+ if (!this.stickyCheckout)
24777
+ return null;
24778
+ if (!state.externalTicketUrl)
24779
+ return null;
24780
+ return (index.h("div", { class: "sticky-checkout-bar" }, index.h("a", { class: "external-ticket-button sticky-checkout-btn", href: state.externalTicketUrl, target: "_blank", rel: "noreferrer" }, index.h("span", { class: "external-ticket-label" }, "Get tickets"))));
24781
+ }
24767
24782
  renderModal() {
24768
24783
  if (!this.openModalAdmissionId)
24769
24784
  return null;
@@ -24790,7 +24805,7 @@ const SessionsTicketing = class {
24790
24805
  if (mode !== "door")
24791
24806
  return null;
24792
24807
  const location = event.location?.name?.trim() || "the venue";
24793
- return (index.h("div", { class: "door-alert" }, index.h("strong", null, "Tickets are available at ", location), index.h("span", null, "Online sales are closed. Buy these tickets at the door when you arrive.")));
24808
+ return (index.h("div", { class: "door-alert" }, index.h("strong", null, "Tickets are available at ", location), index.h("span", null, "Online sales are closed. Tickets are available at the venue when you arrive.")));
24794
24809
  }
24795
24810
  loadingView() {
24796
24811
  return this.loading ? this.renderLoadingState() : undefined;
@@ -24810,7 +24825,7 @@ const SessionsTicketing = class {
24810
24825
  return this.renderNotFoundState();
24811
24826
  const state = getTicketingState(event);
24812
24827
  if (state.showExternalTicketing) {
24813
- return this.renderExternalTicketing(state.externalTicketUrl);
24828
+ return (index.h(index.Host, { "data-theme": this.currentTheme, "data-sticky-checkout": this.stickyCheckout ? "true" : undefined }, index.h("div", { class: "session-services-ticketing-container" }, this.renderExternalTicketing(state)), this.renderStickyExternalTicketing(state)));
24814
24829
  }
24815
24830
  return (index.h(index.Host, { "data-theme": this.currentTheme, "data-sticky-checkout": this.stickyCheckout ? "true" : undefined }, index.h("div", { class: "session-services-ticketing-container" }, state.showTicketing
24816
24831
  ? this.renderTicketSections(event)
@@ -24818,13 +24833,16 @@ const SessionsTicketing = class {
24818
24833
  state.showTicketing &&
24819
24834
  this.renderCheckoutActions()), this.renderStickyCheckout(state), this.renderModal()));
24820
24835
  }
24821
- renderExternalTicketing(url) {
24822
- return (index.h(index.Host, { "data-theme": this.currentTheme }, index.h("div", { class: "session-services-ticketing-container" }, index.h("a", { class: "external-ticket-button", href: url, target: "_blank", rel: "noreferrer" }, "Get tickets"))));
24836
+ renderExternalTicketing(state) {
24837
+ const domain = urlDomain(state.externalTicketUrl);
24838
+ if (!state.externalTicketUrl)
24839
+ return null;
24840
+ return (index.h("div", { class: "tickets-wrapper" }, index.h("h2", { class: "tickets-heading" }, state.ticketHeading), index.h("div", { class: "external-ticket-panel" }, index.h("p", { class: "external-ticket-warning" }, "This event sells through an external ticketing site. Checkout, tickets, and support are handled there."), index.h("a", { class: "external-ticket-button inline-external-ticket-button", href: state.externalTicketUrl, target: "_blank", rel: "noreferrer" }, index.h("span", { class: "external-ticket-label" }, "Get tickets"), index.h("span", { class: "external-ticket-domain" }, "via ", domain)))));
24823
24841
  }
24824
24842
  renderUnavailableState(state) {
24825
- return (index.h("div", { class: "empty-ticketing-state" }, index.h("strong", null, state.isEnded ? "Event ended" : "Tickets unavailable"), index.h("span", null, state.isEnded
24826
- ? "Ticket sales are closed for this event."
24827
- : "Tickets are not currently available for this event.")));
24843
+ return (index.h("div", { class: "empty-ticketing-state" }, index.h("strong", null, "Tickets Unavailable"), index.h("span", null, state.isEnded
24844
+ ? "This event has ended, so tickets are no longer available."
24845
+ : "Tickets are not available for this event right now.")));
24828
24846
  }
24829
24847
  render() {
24830
24848
  return this.pendingView() ?? this.renderReadyState();
@@ -251,8 +251,40 @@ textarea {
251
251
  margin: 0 0 var(--internal-spacing-md);
252
252
  }
253
253
 
254
- .door-alert,
255
- .empty-ticketing-state,
254
+ .ticket-section.loading-ticket-section {
255
+ overflow: visible;
256
+ background: transparent;
257
+ border: 0;
258
+ box-shadow: none;
259
+ }
260
+
261
+ .loading-ticket-section .admissions-list {
262
+ display: flex;
263
+ flex-direction: column;
264
+ gap: var(--internal-spacing-sm);
265
+ }
266
+
267
+ .admission-card.loading-admission {
268
+ min-height: 5.25rem;
269
+ padding: 0;
270
+ background: oklch(from var(--internal-foreground) l c h / 0.07);
271
+ border: 0;
272
+ border-radius: var(--internal-radius);
273
+ box-shadow: none;
274
+ pointer-events: none;
275
+ animation: loading-card 1.6s ease-out infinite;
276
+ }
277
+
278
+ @keyframes loading-card {
279
+ 0%,
280
+ 100% {
281
+ opacity: 0.48;
282
+ }
283
+ 50% {
284
+ opacity: 0.74;
285
+ }
286
+ }
287
+
256
288
  .passcode-form,
257
289
  .passcode-form input,
258
290
  .ticket-section,
@@ -286,8 +318,11 @@ textarea {
286
318
  transform: translateY(-1px);
287
319
  }
288
320
 
289
- .door-alert,
290
- .empty-ticketing-state,
321
+ .external-ticket-button:focus-visible {
322
+ outline: 2px solid var(--internal-ring);
323
+ outline-offset: 2px;
324
+ }
325
+
291
326
  .passcode-form {
292
327
  display: flex;
293
328
  flex-direction: column;
@@ -298,14 +333,36 @@ textarea {
298
333
  border-radius: var(--internal-radius);
299
334
  }
300
335
 
301
- .door-alert {
302
- background: oklch(from var(--internal-success) l c h / 0.1);
303
- border-color: oklch(from var(--internal-success) l c h / 0.48);
336
+ .passcode-form h2 {
337
+ color: var(--internal-foreground);
338
+ font-size: var(--internal-font-size-base);
339
+ font-weight: var(--internal-font-weight-semibold);
340
+ line-height: 1.3;
341
+ }
342
+
343
+ .passcode-form p {
344
+ color: var(--internal-muted-foreground);
345
+ font-size: var(--internal-font-size-sm);
346
+ line-height: 1.5;
347
+ }
348
+
349
+ .door-alert,
350
+ .empty-ticketing-state,
351
+ .message-state {
352
+ display: flex;
353
+ flex-direction: column;
354
+ gap: calc(var(--internal-spacing-xs) * 1.5);
355
+ margin-bottom: var(--internal-spacing-md);
356
+ padding: 0;
357
+ background: transparent;
358
+ border: none;
359
+ border-radius: 0;
360
+ box-shadow: none;
304
361
  }
305
362
 
306
363
  .door-alert strong,
307
364
  .empty-ticketing-state strong,
308
- .passcode-form h2 {
365
+ .message-state strong {
309
366
  color: var(--internal-foreground);
310
367
  font-size: var(--internal-font-size-base);
311
368
  font-weight: var(--internal-font-weight-semibold);
@@ -314,19 +371,45 @@ textarea {
314
371
 
315
372
  .door-alert span,
316
373
  .empty-ticketing-state span,
317
- .passcode-form p {
374
+ .message-state span {
318
375
  color: var(--internal-muted-foreground);
319
376
  font-size: var(--internal-font-size-sm);
320
- line-height: 1.5;
377
+ line-height: 1.4;
321
378
  }
322
379
 
323
380
  .external-ticket-button {
381
+ flex-direction: column;
382
+ gap: calc(var(--internal-spacing-xs) * 0.5);
324
383
  width: 100%;
325
384
  padding: calc(var(--internal-spacing-sm) + var(--internal-spacing-xs))
326
385
  var(--internal-spacing-lg);
386
+ text-decoration: none;
387
+ }
388
+
389
+ .external-ticket-panel {
390
+ display: flex;
391
+ flex-direction: column;
392
+ gap: var(--internal-spacing-md);
393
+ }
394
+
395
+ .external-ticket-warning {
396
+ color: var(--internal-muted-foreground);
397
+ font-size: var(--internal-font-size-sm);
398
+ font-weight: var(--internal-font-weight-medium);
399
+ line-height: 1.35;
400
+ }
401
+
402
+ .external-ticket-label {
327
403
  font-size: var(--internal-font-size-base);
328
404
  font-weight: var(--internal-font-weight-bold);
329
- text-decoration: none;
405
+ line-height: 1.2;
406
+ }
407
+
408
+ .external-ticket-domain {
409
+ font-size: var(--internal-font-size-xs);
410
+ font-weight: var(--internal-font-weight-medium);
411
+ line-height: 1.2;
412
+ opacity: 0.82;
330
413
  }
331
414
 
332
415
  .passcode-form input {
@@ -569,22 +652,6 @@ textarea {
569
652
  flex-shrink: 0;
570
653
  }
571
654
 
572
- .sold-out-badge {
573
- display: inline-flex;
574
- align-items: center;
575
- justify-content: center;
576
- padding: 0;
577
- background: transparent;
578
- color: var(--internal-destructive);
579
- border: none;
580
- font-size: var(--internal-font-size-sm);
581
- font-weight: var(--internal-font-weight-medium);
582
- text-transform: uppercase;
583
- letter-spacing: 0.05em;
584
- margin-left: auto;
585
- opacity: 0.7;
586
- }
587
-
588
655
  .admission-price-info {
589
656
  display: flex;
590
657
  align-items: center;
@@ -941,40 +1008,9 @@ textarea {
941
1008
  }
942
1009
  }
943
1010
 
944
- /* Loading & Error States */
945
- .loading-state {
946
- display: flex;
947
- justify-content: center;
948
- align-items: center;
949
- padding: var(--internal-spacing-xl);
950
- text-align: center;
951
- min-height: 200px;
952
- }
953
-
954
- .error-banner {
955
- background: oklch(
956
- from var(--internal-destructive) calc(l + 0.4) calc(c * 0.2) h / 0.05
957
- );
958
- border: 1px solid oklch(from var(--internal-destructive) l c h / 0.2);
959
- border-radius: var(--internal-radius);
960
- padding: var(--internal-spacing-lg);
961
- margin: var(--internal-spacing-lg);
962
- text-align: center;
963
- }
964
-
965
- .error-banner strong {
966
- display: block;
967
- color: var(--internal-destructive);
968
- font-size: var(--internal-font-size-lg);
969
- margin-bottom: var(--internal-spacing-sm);
970
- }
971
-
972
- .error-banner p {
973
- color: var(--internal-muted-foreground);
974
- margin-bottom: var(--internal-spacing-md);
975
- }
976
-
977
1011
  .retry-button {
1012
+ align-self: flex-start;
1013
+ margin-top: var(--internal-spacing-xs);
978
1014
  background: var(--internal-primary);
979
1015
  color: var(--internal-primary-foreground);
980
1016
  border: 1px solid oklch(from var(--internal-primary) calc(l - 0.08) c h);
@@ -1027,6 +1063,11 @@ textarea {
1027
1063
  padding-bottom: calc(var(--internal-spacing-xl) * 3);
1028
1064
  }
1029
1065
 
1066
+ :host([data-sticky-checkout="true"]) .checkout-actions > .checkout-btn,
1067
+ :host([data-sticky-checkout="true"]) .inline-external-ticket-button {
1068
+ display: none;
1069
+ }
1070
+
1030
1071
  .sticky-checkout-bar {
1031
1072
  display: block;
1032
1073
  }
@@ -44,6 +44,16 @@ function eventVenueName(event) {
44
44
  function optionalId(id) {
45
45
  return id || undefined;
46
46
  }
47
+ function urlDomain(url) {
48
+ if (!url)
49
+ return "external site";
50
+ try {
51
+ return new URL(url).hostname.replace(/^www\./, "");
52
+ }
53
+ catch {
54
+ return "external site";
55
+ }
56
+ }
47
57
  function admissionAriaLabel(admission, section, status) {
48
58
  if (section)
49
59
  return `${admission.name} in ${section.name} - ${status}`;
@@ -1036,29 +1046,29 @@ export class SessionsTicketing {
1036
1046
  }
1037
1047
  return (h(h.Fragment, null, this.renderEventTimeAndLocation(event), this.renderPriceAndControls(admission, sectionId, state, mode)));
1038
1048
  }
1039
- renderSectionHeader(section, admissions, isSectionSoldOut) {
1040
- return (h("div", { class: "section-header" }, h("h2", { class: "section-name" }, section.name, isSectionSoldOut && h("span", { class: "sold-out-badge" }, "Sold Out")), this.renderAdmissionTime(admissions[0], "section-time"), this.renderSectionLocation(section)));
1049
+ renderSectionHeader(section, admissions) {
1050
+ return (h("div", { class: "section-header" }, h("h2", { class: "section-name" }, section.name), this.renderAdmissionTime(admissions[0], "section-time"), this.renderSectionLocation(section)));
1041
1051
  }
1042
1052
  renderSectionWithAdmissions(section, admissions, event, mode) {
1043
1053
  const soldOut = isSectionSoldOut({
1044
1054
  admissions,
1045
1055
  section,
1046
1056
  });
1047
- return (h("div", { class: `ticket-section ${soldOut ? "section-sold-out" : ""}`, key: section.id }, this.renderSectionHeader(section, admissions, soldOut), h("div", { class: "admissions-list" }, admissions.map((admission) => this.renderAdmission(admission, event, section, soldOut, mode)))));
1057
+ return (h("div", { class: `ticket-section ${soldOut ? "section-sold-out" : ""}`, key: section.id }, this.renderSectionHeader(section, admissions), h("div", { class: "admissions-list" }, admissions.map((admission) => this.renderAdmission(admission, event, section, soldOut, mode)))));
1048
1058
  }
1049
1059
  renderLoadingState() {
1050
- return (h(Host, { "data-theme": this.currentTheme }, h("div", { class: "loading-state" }, "Loading event details...")));
1060
+ return (h(Host, { "data-theme": this.currentTheme }, h("div", { class: "session-services-ticketing-container" }, h("div", { class: "tickets-wrapper" }, h("h2", { class: "tickets-heading" }, "Get Tickets"), h("div", { class: "ticket-section loading-ticket-section" }, h("div", { class: "admissions-list" }, [0, 1, 2].map((item) => (h("div", { "aria-hidden": "true", class: "admission-card loading-admission", key: item })))))))));
1051
1061
  }
1052
1062
  renderErrorState() {
1053
1063
  if (this.passcodeDenied)
1054
1064
  return this.renderPasscodeState();
1055
- return (h(Host, { "data-theme": this.currentTheme }, h("div", { class: "session-services-ticketing-container" }, h("div", { class: "error-banner" }, h("strong", null, "Unable to load event"), h("p", null, this.error), h("button", { type: "button", class: "retry-button", onClick: () => this.loadEventData() }, "Try Again")))));
1065
+ return (h(Host, { "data-theme": this.currentTheme }, h("div", { class: "session-services-ticketing-container" }, h("div", { class: "message-state" }, h("strong", null, "Tickets Couldn\u2019t Load"), h("span", null, "We couldn\u2019t load ticket details. Try again in a moment."), h("button", { type: "button", class: "retry-button", onClick: () => this.loadEventData() }, "Try Again")))));
1056
1066
  }
1057
1067
  renderPasscodeState() {
1058
1068
  return (h(Host, { "data-theme": this.currentTheme }, h("div", { class: "session-services-ticketing-container" }, h("form", { class: "passcode-form", onSubmit: (e) => this.submitPasscode(e) }, h("h2", null, "Enter passcode"), h("p", null, "Enter the event passcode to view tickets and event details."), h("input", { type: "text", name: "passcode", value: this.passcodeInput, onInput: this.handlePasscodeInput, autocomplete: "one-time-code", placeholder: "Passcode", "aria-label": "Passcode" }), this.passcodeDenied && this.activePasscode && (h("span", { class: "error-message" }, "Incorrect passcode")), h("button", { type: "submit", class: "checkout-btn", disabled: !this.passcodeInput.trim() }, "Unlock event")))));
1059
1069
  }
1060
1070
  renderNotFoundState() {
1061
- return (h(Host, { "data-theme": this.currentTheme }, h("div", { class: "session-services-ticketing-container" }, h("div", { class: "error-banner" }, h("strong", null, "Event not found"), h("p", null, "The requested event could not be found.")))));
1071
+ return (h(Host, { "data-theme": this.currentTheme }, h("div", { class: "session-services-ticketing-container" }, h("div", { class: "message-state" }, h("strong", null, "Event not found"), h("span", null, "We couldn\u2019t find this event. The link may be incorrect or expired.")))));
1062
1072
  }
1063
1073
  renderCouponPanel() {
1064
1074
  const hasInput = this.couponInput.trim().length > 0;
@@ -1140,6 +1150,13 @@ export class SessionsTicketing {
1140
1150
  return null;
1141
1151
  return (h("div", { class: "sticky-checkout-bar" }, h("button", { type: "button", class: `checkout-btn sticky-checkout-btn ${this.selectionPrompt ? "selection-prompt" : ""}`, onClick: () => this.handleStickyCheckoutClick(state), disabled: this.isStickyCheckoutDisabled(state), "aria-label": this.quoteLoading ? "Updating" : undefined }, this.renderStickyCheckoutButtonContent(state))));
1142
1152
  }
1153
+ renderStickyExternalTicketing(state) {
1154
+ if (!this.stickyCheckout)
1155
+ return null;
1156
+ if (!state.externalTicketUrl)
1157
+ return null;
1158
+ return (h("div", { class: "sticky-checkout-bar" }, h("a", { class: "external-ticket-button sticky-checkout-btn", href: state.externalTicketUrl, target: "_blank", rel: "noreferrer" }, h("span", { class: "external-ticket-label" }, "Get tickets"))));
1159
+ }
1143
1160
  renderModal() {
1144
1161
  if (!this.openModalAdmissionId)
1145
1162
  return null;
@@ -1166,7 +1183,7 @@ export class SessionsTicketing {
1166
1183
  if (mode !== "door")
1167
1184
  return null;
1168
1185
  const location = event.location?.name?.trim() || "the venue";
1169
- return (h("div", { class: "door-alert" }, h("strong", null, "Tickets are available at ", location), h("span", null, "Online sales are closed. Buy these tickets at the door when you arrive.")));
1186
+ return (h("div", { class: "door-alert" }, h("strong", null, "Tickets are available at ", location), h("span", null, "Online sales are closed. Tickets are available at the venue when you arrive.")));
1170
1187
  }
1171
1188
  loadingView() {
1172
1189
  return this.loading ? this.renderLoadingState() : undefined;
@@ -1186,7 +1203,7 @@ export class SessionsTicketing {
1186
1203
  return this.renderNotFoundState();
1187
1204
  const state = getTicketingState(event);
1188
1205
  if (state.showExternalTicketing) {
1189
- return this.renderExternalTicketing(state.externalTicketUrl);
1206
+ return (h(Host, { "data-theme": this.currentTheme, "data-sticky-checkout": this.stickyCheckout ? "true" : undefined }, h("div", { class: "session-services-ticketing-container" }, this.renderExternalTicketing(state)), this.renderStickyExternalTicketing(state)));
1190
1207
  }
1191
1208
  return (h(Host, { "data-theme": this.currentTheme, "data-sticky-checkout": this.stickyCheckout ? "true" : undefined }, h("div", { class: "session-services-ticketing-container" }, state.showTicketing
1192
1209
  ? this.renderTicketSections(event)
@@ -1194,13 +1211,16 @@ export class SessionsTicketing {
1194
1211
  state.showTicketing &&
1195
1212
  this.renderCheckoutActions()), this.renderStickyCheckout(state), this.renderModal()));
1196
1213
  }
1197
- renderExternalTicketing(url) {
1198
- return (h(Host, { "data-theme": this.currentTheme }, h("div", { class: "session-services-ticketing-container" }, h("a", { class: "external-ticket-button", href: url, target: "_blank", rel: "noreferrer" }, "Get tickets"))));
1214
+ renderExternalTicketing(state) {
1215
+ const domain = urlDomain(state.externalTicketUrl);
1216
+ if (!state.externalTicketUrl)
1217
+ return null;
1218
+ return (h("div", { class: "tickets-wrapper" }, h("h2", { class: "tickets-heading" }, state.ticketHeading), h("div", { class: "external-ticket-panel" }, h("p", { class: "external-ticket-warning" }, "This event sells through an external ticketing site. Checkout, tickets, and support are handled there."), h("a", { class: "external-ticket-button inline-external-ticket-button", href: state.externalTicketUrl, target: "_blank", rel: "noreferrer" }, h("span", { class: "external-ticket-label" }, "Get tickets"), h("span", { class: "external-ticket-domain" }, "via ", domain)))));
1199
1219
  }
1200
1220
  renderUnavailableState(state) {
1201
- return (h("div", { class: "empty-ticketing-state" }, h("strong", null, state.isEnded ? "Event ended" : "Tickets unavailable"), h("span", null, state.isEnded
1202
- ? "Ticket sales are closed for this event."
1203
- : "Tickets are not currently available for this event.")));
1221
+ return (h("div", { class: "empty-ticketing-state" }, h("strong", null, "Tickets Unavailable"), h("span", null, state.isEnded
1222
+ ? "This event has ended, so tickets are no longer available."
1223
+ : "Tickets are not available for this event right now.")));
1204
1224
  }
1205
1225
  render() {
1206
1226
  return this.pendingView() ?? this.renderReadyState();
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, it, vi } from "vitest";
2
2
  import { SessionsTicketing } from "./session-services-ticketing";
3
- import { selectionKey, } from "./session-services-ticketing.logic";
3
+ import { getTicketingState, selectionKey, } from "./session-services-ticketing.logic";
4
4
  vi.mock("@stencil/core", () => ({
5
5
  Component: () => () => undefined,
6
6
  Element: () => () => undefined,
@@ -9,7 +9,7 @@ vi.mock("@stencil/core", () => ({
9
9
  Prop: () => () => undefined,
10
10
  State: () => () => undefined,
11
11
  Watch: () => () => undefined,
12
- h: () => undefined,
12
+ h: (tag, props, ...children) => ({ tag, props: props ?? {}, children }),
13
13
  }));
14
14
  const futureStart = "2030-01-01T20:00:00";
15
15
  const futureEnd = "2030-01-01T23:00:00";
@@ -115,6 +115,25 @@ function deferred() {
115
115
  });
116
116
  return { promise, resolve };
117
117
  }
118
+ function isRenderNode(value) {
119
+ if (!value || typeof value !== "object")
120
+ return false;
121
+ return "tag" in value && "props" in value && "children" in value;
122
+ }
123
+ function rendered(value, predicate) {
124
+ if (Array.isArray(value)) {
125
+ return value.flatMap((item) => rendered(item, predicate));
126
+ }
127
+ if (!isRenderNode(value))
128
+ return [];
129
+ const matches = predicate(value) ? [value] : [];
130
+ return matches.concat(value.children.flatMap((item) => rendered(item, predicate)));
131
+ }
132
+ function hasClass(node, name) {
133
+ return String(node.props.class ?? "")
134
+ .split(/\s+/)
135
+ .includes(name);
136
+ }
118
137
  function widget() {
119
138
  const item = new SessionsTicketing();
120
139
  item.eventId = "evt_1";
@@ -131,6 +150,7 @@ function widget() {
131
150
  item.quoteLoading = false;
132
151
  item.previewLoading = false;
133
152
  item.passcodeDenied = false;
153
+ item.stickyCheckout = false;
134
154
  item.error = null;
135
155
  item.activePasscode = "";
136
156
  item.cartUpdate = { emit: vi.fn() };
@@ -246,6 +266,30 @@ describe("session-services-ticketing component", () => {
246
266
  });
247
267
  expect(item.getCheckoutButtonText()).toBe("Continue");
248
268
  });
269
+ it("renders external ticketing in the sticky checkout bar", () => {
270
+ const item = widget();
271
+ item.event = event({ url: "https://tickets.example" });
272
+ item.stickyCheckout = true;
273
+ const state = getTicketingState(item.event);
274
+ const links = rendered(item.renderStickyExternalTicketing(state), (node) => node.tag === "a");
275
+ expect(links).toHaveLength(1);
276
+ expect(links[0].props.href).toBe("https://tickets.example");
277
+ expect(hasClass(links[0], "external-ticket-button")).toBe(true);
278
+ expect(hasClass(links[0], "sticky-checkout-btn")).toBe(true);
279
+ });
280
+ it("keeps external ticketing under the sticky checkout host state", () => {
281
+ const item = widget();
282
+ item.event = event({ url: "https://tickets.example" });
283
+ item.stickyCheckout = true;
284
+ const view = item.renderReadyState();
285
+ const hosts = rendered(view, (node) => node.tag === "mock-host");
286
+ const links = rendered(view, (node) => node.tag === "a");
287
+ expect(getTicketingState(item.event).showExternalTicketing).toBe(true);
288
+ expect(hosts[0].props["data-sticky-checkout"]).toBe("true");
289
+ expect(links).toHaveLength(2);
290
+ expect(links.some((link) => hasClass(link, "inline-external-ticket-button"))).toBe(true);
291
+ expect(links.some((link) => hasClass(link, "sticky-checkout-btn"))).toBe(true);
292
+ });
249
293
  it("classifies only passcode access failures as passcode errors", async () => {
250
294
  const item = widget();
251
295
  item.client.event.get = vi