@jant/core 0.5.2 → 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jant/core",
3
- "version": "0.5.2",
3
+ "version": "0.5.3",
4
4
  "description": "A modern, open-source microblogging platform built on Cloudflare Workers",
5
5
  "type": "module",
6
6
  "exports": {
@@ -4127,7 +4127,9 @@ export class JantComposeDialog extends LitElement {
4127
4127
 
4128
4128
  private _getSubmitLabel(): string {
4129
4129
  if (this._editPostId) return this.labels.update;
4130
- if (this._replyToId) return this.labels.reply;
4130
+ if (this._replyToId) {
4131
+ return this._quietReply ? this.labels.quietReplyLabel : this.labels.reply;
4132
+ }
4131
4133
  if (this._visibility === "latest_hidden") {
4132
4134
  return this.labels.postHiddenFromLatest;
4133
4135
  }
@@ -5015,16 +5017,35 @@ export class JantComposeDialog extends LitElement {
5015
5017
  `;
5016
5018
  }
5017
5019
 
5018
- private _renderHideFromLatestQuickToggleRow() {
5019
- if (this._visibilityLocked) return nothing;
5020
- if (this._visibility === "private") return nothing;
5020
+ private _renderQuickActionsRow() {
5021
+ const hideFromLatest = this._renderHideFromLatestQuickToggle();
5022
+ const quietReply = this._renderQuietReplyQuickToggle();
5023
+ if (hideFromLatest === nothing && quietReply === nothing) return nothing;
5021
5024
  return html`
5022
5025
  <div class="compose-quick-actions-row">
5023
- ${this._renderHideFromLatestQuickToggle()}
5026
+ ${hideFromLatest} ${quietReply}
5024
5027
  </div>
5025
5028
  `;
5026
5029
  }
5027
5030
 
5031
+ private _renderQuietReplyQuickToggle() {
5032
+ if (!this._replyToId) return nothing;
5033
+ return html`
5034
+ <label class="compose-publish-quick-toggle">
5035
+ <input
5036
+ type="checkbox"
5037
+ class="input compose-publish-quick-toggle-input"
5038
+ .checked=${this._quietReply}
5039
+ ?disabled=${this._loading}
5040
+ @change=${(e: Event) => {
5041
+ this._quietReply = (e.target as HTMLInputElement).checked;
5042
+ }}
5043
+ />
5044
+ <span>${this.labels.quietReplyLabel}</span>
5045
+ </label>
5046
+ `;
5047
+ }
5048
+
5028
5049
  private _renderHideFromLatestQuickToggle() {
5029
5050
  if (this._visibilityLocked) return nothing;
5030
5051
  if (this._visibility === "private") return nothing;
@@ -5439,7 +5460,7 @@ export class JantComposeDialog extends LitElement {
5439
5460
  ${this._renderCollectionSelector()}
5440
5461
  ${this._renderPublishButton()}
5441
5462
  </div>
5442
- ${this._renderHideFromLatestQuickToggleRow()}`}
5463
+ ${this._renderQuickActionsRow()}`}
5443
5464
  ${this._renderMobilePublishPanel()} ${this._renderAttachedPanel()}
5444
5465
  ${this._renderAltPanel()} ${this._renderDraftsPanel()}
5445
5466
  ${this._renderConfirmPanel()}
@@ -280,46 +280,130 @@ export class JantMediaLightbox extends LitElement {
280
280
  #handleKeydown = (e: Event) => {
281
281
  const ke = e as globalThis.KeyboardEvent;
282
282
  const target = e.target as HTMLElement | null;
283
+
283
284
  if (ke.key === "Escape") {
284
285
  e.preventDefault();
285
286
  this.close();
286
287
  return;
287
288
  }
288
- if (ke.key !== "ArrowLeft" && ke.key !== "ArrowRight") return;
289
289
 
290
- // Let the progress slider's native arrow-key seeking through.
291
- if (target?.classList.contains("media-lightbox-short-progress")) return;
290
+ // Don't hijack keys aimed at a focused control — the short-video progress
291
+ // slider, the mute/close/nav buttons, or the <video> itself (when focused,
292
+ // its native shortcuts already handle these keys). Let their native
293
+ // behavior run instead of double-handling.
294
+ if (
295
+ target instanceof HTMLInputElement ||
296
+ target instanceof HTMLButtonElement ||
297
+ target instanceof HTMLVideoElement
298
+ ) {
299
+ return;
300
+ }
292
301
 
293
- // On videos, arrow keys scrub the playhead. Item switching happens via
294
- // the on-screen prev/next buttons — matches YouTube/native player conventions.
295
302
  const currentImage = this._images[this._currentIndex];
296
- if (currentImage?.mimeType?.startsWith("video/")) {
297
- const video = this.querySelector<HTMLVideoElement>(
298
- ".media-lightbox-video",
299
- );
300
- if (video) {
303
+ if (!currentImage?.mimeType?.startsWith("video/")) {
304
+ // Image galleries: arrow keys switch items.
305
+ if (ke.key === "ArrowLeft") {
306
+ e.preventDefault();
307
+ this.#prev();
308
+ } else if (ke.key === "ArrowRight") {
301
309
  e.preventDefault();
302
- const step = 5;
303
- const delta = ke.key === "ArrowLeft" ? -step : step;
304
- const duration =
305
- Number.isFinite(video.duration) && video.duration > 0
306
- ? video.duration
307
- : null;
308
- const nextTime =
309
- duration != null
310
- ? Math.max(0, Math.min(video.currentTime + delta, duration))
311
- : Math.max(0, video.currentTime + delta);
312
- video.currentTime = nextTime;
313
- this._videoCurrentTime = nextTime;
310
+ this.#next();
314
311
  }
315
312
  return;
316
313
  }
317
314
 
318
- e.preventDefault();
319
- if (ke.key === "ArrowLeft") this.#prev();
320
- else this.#next();
315
+ const video = this.querySelector<HTMLVideoElement>(".media-lightbox-video");
316
+ if (video) this.#handleVideoKeydown(ke, video);
321
317
  };
322
318
 
319
+ // Video shortcuts — play/pause, seek, volume, mute, fullscreen — handled at
320
+ // the dialog level so they work regardless of what's focused. Item switching
321
+ // happens via the on-screen prev/next buttons, matching YouTube/native
322
+ // player conventions.
323
+ #handleVideoKeydown(ke: globalThis.KeyboardEvent, video: HTMLVideoElement) {
324
+ const duration =
325
+ Number.isFinite(video.duration) && video.duration > 0
326
+ ? video.duration
327
+ : null;
328
+ const seekTo = (time: number) => {
329
+ const next =
330
+ duration != null
331
+ ? Math.max(0, Math.min(time, duration))
332
+ : Math.max(0, time);
333
+ video.currentTime = next;
334
+ this._videoCurrentTime = next;
335
+ };
336
+ const key = ke.key;
337
+ const lower = key.toLowerCase();
338
+
339
+ if (key === " " || lower === "k") {
340
+ ke.preventDefault();
341
+ if (video.paused) void video.play().catch(() => {});
342
+ else video.pause();
343
+ } else if (key === "ArrowLeft") {
344
+ ke.preventDefault();
345
+ seekTo(video.currentTime - 5);
346
+ } else if (key === "ArrowRight") {
347
+ ke.preventDefault();
348
+ seekTo(video.currentTime + 5);
349
+ } else if (key === "Home") {
350
+ ke.preventDefault();
351
+ seekTo(0);
352
+ } else if (key === "End") {
353
+ if (duration != null) {
354
+ ke.preventDefault();
355
+ seekTo(duration);
356
+ }
357
+ } else if (key.length === 1 && key >= "0" && key <= "9") {
358
+ if (duration != null) {
359
+ ke.preventDefault();
360
+ seekTo((Number(key) / 10) * duration);
361
+ }
362
+ } else if (key === "ArrowUp") {
363
+ ke.preventDefault();
364
+ video.volume = Math.min(1, video.volume + 0.05);
365
+ } else if (key === "ArrowDown") {
366
+ ke.preventDefault();
367
+ video.volume = Math.max(0, video.volume - 0.05);
368
+ } else if (lower === "m") {
369
+ ke.preventDefault();
370
+ const muted = !video.muted;
371
+ video.muted = muted;
372
+ this._videoMuted = muted;
373
+ } else if (lower === "f") {
374
+ ke.preventDefault();
375
+ this.#toggleVideoFullscreen(video);
376
+ }
377
+ }
378
+
379
+ #toggleVideoFullscreen(video: HTMLVideoElement) {
380
+ const doc = document as globalThis.Document & {
381
+ webkitFullscreenElement?: globalThis.Element | null;
382
+ webkitExitFullscreen?: () => void;
383
+ };
384
+ const el = video as HTMLVideoElement & {
385
+ webkitRequestFullscreen?: () => void;
386
+ webkitEnterFullscreen?: () => void;
387
+ };
388
+
389
+ if (document.fullscreenElement ?? doc.webkitFullscreenElement) {
390
+ if (document.exitFullscreen) {
391
+ void document.exitFullscreen().catch(() => {});
392
+ } else {
393
+ doc.webkitExitFullscreen?.();
394
+ }
395
+ return;
396
+ }
397
+
398
+ if (video.requestFullscreen) {
399
+ void video.requestFullscreen().catch(() => {});
400
+ } else if (el.webkitRequestFullscreen) {
401
+ el.webkitRequestFullscreen();
402
+ } else if (el.webkitEnterFullscreen) {
403
+ el.webkitEnterFullscreen();
404
+ }
405
+ }
406
+
323
407
  #handleDialogClick = (e: Event) => {
324
408
  const target = e.target as HTMLElement;
325
409
  // Close on backdrop click (dialog itself or the content wrapper, not media/buttons)
@@ -365,24 +449,23 @@ export class JantMediaLightbox extends LitElement {
365
449
  this.querySelector<HTMLVideoElement>(".media-lightbox-video")?.pause();
366
450
  }
367
451
 
368
- // Focus the active video so space/native shortcuts work without an extra
369
- // click. Falls back to the content wrapper for images focusing the close
370
- // button would show a focus ring during arrow-key nav.
452
+ // Move focus to the content wrapper on open / item change not the close
453
+ // button (its focus ring would show during arrow-key nav) and not the
454
+ // <video> (a focused <video> routes keydown to its own native handler,
455
+ // bypassing the dialog-level shortcuts in #handleVideoKeydown).
371
456
  #focusCurrentMedia() {
372
- const currentImage = this._images[this._currentIndex];
373
- const isVideo = currentImage?.mimeType?.startsWith("video/");
374
- if (isVideo) {
375
- const video = this.querySelector<HTMLVideoElement>(
376
- ".media-lightbox-video",
377
- );
378
- if (video) {
379
- video.focus();
380
- return;
381
- }
382
- }
383
457
  this.querySelector<HTMLElement>(".media-lightbox-content")?.focus();
384
458
  }
385
459
 
460
+ // Browsers focus a <video> when it's clicked. Bounce focus back to the
461
+ // content wrapper so keydown keeps reaching the dialog-level shortcut
462
+ // handler instead of the video's native key handling.
463
+ #handleVideoFocus = () => {
464
+ this.querySelector<HTMLElement>(".media-lightbox-content")?.focus({
465
+ preventScroll: true,
466
+ });
467
+ };
468
+
386
469
  #resetShortVideoState(image?: LightboxImage) {
387
470
  this._videoCurrentTime = 0;
388
471
  this._videoDuration =
@@ -543,6 +626,7 @@ export class JantMediaLightbox extends LitElement {
543
626
  playsinline
544
627
  loop
545
628
  ?muted=${this._videoMuted}
629
+ @focus=${this.#handleVideoFocus}
546
630
  @loadedmetadata=${this.#handleShortVideoLoadedMetadata}
547
631
  @timeupdate=${this.#handleShortVideoTimeUpdate}
548
632
  ></video>
@@ -596,6 +680,7 @@ export class JantMediaLightbox extends LitElement {
596
680
  controls
597
681
  autoplay
598
682
  playsinline
683
+ @focus=${this.#handleVideoFocus}
599
684
  ></video>`
600
685
  : html`<img
601
686
  class=${`media-lightbox-img${isScrollableImage ? " media-lightbox-img-scroll" : ""}`}
@@ -1,10 +1,10 @@
1
1
  var e=null,t=0,n=!1,r=null,i=null,a=0;function o(e){return!isFinite(e)||e<0?`0:00`:`${Math.floor(e/60)}:${String(Math.floor(e%60)).padStart(2,`0`)}`}function s(e){return e.querySelector(`audio.media-audio-el`)}function c(e){return e.querySelector(`[data-audio-range]`)}function l(e){return e.querySelector(`[data-audio-waveform]`)}function u(e,t){let n=`${(t*100).toFixed(1)}%`;e.style.background=`linear-gradient(to right, var(--site-text-primary) ${n}, transparent ${n})`}var d=new WeakMap,f=new WeakSet;async function p(e,t){let n=await(await fetch(e)).arrayBuffer(),r=new AudioContext;try{let e=(await r.decodeAudioData(n)).getChannelData(0),i=Math.max(1,Math.floor(e.length/t)),a=Array(t);for(let n=0;n<t;n++){let t=0,r=n*i,o=Math.min(r+i,e.length);for(let n=r;n<o;n++){let r=Math.abs(e[n]);r>t&&(t=r)}a[n]=t}let o=0;for(let e of a)e>o&&(o=e);if(o>0)for(let e=0;e<t;e++)a[e]/=o;return a}finally{await r.close()}}function m(){let e=document.querySelectorAll(`[data-audio-peaks]`),t=[];for(let n of e){let e=n.dataset.audioPeaks;if(!e)continue;let r=n.closest(`.media-audio-card`);if(!(!r||d.has(r)))try{let n=JSON.parse(e);if(!Array.isArray(n))continue;d.set(r,n),r.classList.add(`has-waveform`),t.push(r)}catch{}}t.length>0&&requestAnimationFrame(()=>{for(let e of t)g(e,0)})}async function h(e){if(d.has(e)||f.has(e))return;f.add(e);let t=e.querySelector(`audio.media-audio-el source`),n=l(e);if(!t?.src||!n)return;let r=n.getBoundingClientRect().width,i=Math.max(20,Math.floor(r/3));try{let n=await p(t.src,i);d.set(e,n),e.classList.add(`has-waveform`);let r=s(e),a=r?.duration??0;g(e,r&&isFinite(a)&&a>0?r.currentTime/a:0)}catch{}}function g(e,t){let n=d.get(e),r=l(e);if(!n||!r)return;let i=window.devicePixelRatio||1,a=r.getBoundingClientRect(),o=Math.round(a.width*i),s=Math.round(a.height*i);if(o===0||s===0)return;(r.width!==o||r.height!==s)&&(r.width=o,r.height=s);let c=r.getContext(`2d`);if(!c)return;c.clearRect(0,0,o,s);let u=n.length,f=o/u,p=Math.max(1,Math.round(f*.6)),m=Math.round(2*i),h=s*.85,g=getComputedStyle(r).getPropertyValue(`--site-text-primary`).trim()||`#000`;for(let e=0;e<u;e++){let r=Math.round(e*f+(f-p)/2),a=Math.max(m,Math.round(n[e]*h)),o=Math.round((s-a)/2);c.globalAlpha=(e+.5)/u<=t?.9:.2,c.fillStyle=g;let l=Math.min(p/2,i);c.beginPath(),c.roundRect(r,o,p,a,l),c.fill()}c.globalAlpha=1}function ee(e,t){let{currentTime:r,duration:i}=t,a=isFinite(i)&&i>0,s=a?r/i:0;if(!n){let t=c(e);t&&a&&(t.value=String(Math.round(s*1e3)),u(t,s)),d.has(e)&&g(e,s);let n=e.querySelector(`[data-audio-time]`);n&&(n.textContent=a?`${o(r)} / ${o(i)}`:o(r))}}function _(){if(!e)return;let n=s(e);!n||n.paused||(ee(e,n),t=requestAnimationFrame(_))}function te(){if(e){let t=s(e);t&&!t.paused&&t.pause(),e.classList.remove(`is-playing`),e=null}cancelAnimationFrame(t)}async function ne(n){let r=s(n);if(r)if(e&&e!==n&&te(),r.paused){e=n,n.classList.add(`is-playing`);try{await r.play()}catch{n.classList.remove(`is-playing`),e=null;return}t=requestAnimationFrame(_),h(n)}else r.pause(),n.classList.remove(`is-playing`),cancelAnimationFrame(t),e=null}function re(e){let t=e.closest(`.media-audio-card`);if(!t)return;let n=s(t);if(!n)return;let r=Number(e.value)/1e3,i=n.duration;isFinite(i)&&i>0&&(n.currentTime=r*i)}function ie(e,t){let n=e.getBoundingClientRect();a=Math.max(0,Math.min(1,(t.clientX-n.left)/n.width));let r=e.closest(`.media-audio-card`);if(!r)return;g(r,a);let i=s(r),c=r.querySelector(`[data-audio-time]`);if(i&&c){let e=i.duration;isFinite(e)&&e>0&&(c.textContent=`${o(a*e)} / ${o(e)}`)}}async function ae(n){let r=n.closest(`.media-audio-card`);if(!r)return;let i=s(r);if(i)if(i.paused){e&&e!==r&&te(),e=r,r.classList.add(`is-playing`);try{await i.play()}catch{r.classList.remove(`is-playing`),e=null;return}let n=i.duration;isFinite(n)&&n>0&&(i.currentTime=a*n),t=requestAnimationFrame(_),h(r)}else{let e=i.duration;isFinite(e)&&e>0&&(i.currentTime=a*e)}}document.addEventListener(`pointerdown`,e=>{let t=e.target;t.matches(`[data-audio-range]`)?(n=!0,r=t):t.matches(`[data-audio-waveform]`)&&(n=!0,i=t,ie(t,e))},!0),document.addEventListener(`pointermove`,e=>{n&&i&&ie(i,e)},!0),document.addEventListener(`pointerup`,()=>{n&&(r?(re(r),r=null):i&&=(ae(i),null)),n=!1},!0),document.addEventListener(`pointercancel`,()=>{r=null,i=null,n=!1},!0),document.addEventListener(`click`,e=>{let t=e.target.closest(`[data-audio-play]`);if(!t)return;e.preventDefault();let n=t.closest(`.media-audio-card`);n&&ne(n)}),document.addEventListener(`input`,e=>{let t=e.target;if(!t.matches(`[data-audio-range]`))return;let n=t.closest(`.media-audio-card`);if(!n)return;let r=s(n);if(!r)return;let i=Number(t.value)/1e3;u(t,i);let a=r.duration,c=n.querySelector(`[data-audio-time]`);c&&isFinite(a)&&a>0&&(c.textContent=`${o(i*a)} / ${o(a)}`)},!0),document.addEventListener(`ended`,n=>{let r=n.target;if(!r.closest)return;let i=r.closest(`.media-audio-card`);if(!i)return;i.classList.remove(`is-playing`),cancelAnimationFrame(t),e=null;let a=c(i);a&&(a.value=`0`,u(a,0)),d.has(i)&&g(i,0);let o=i.querySelector(`[data-audio-time]`);o&&(o.textContent=`0:00`)},!0),document.readyState===`loading`?document.addEventListener(`DOMContentLoaded`,m):m();var v=`jant:media-lightbox-toggle`,oe=`75% 0px`,se=.6,y=.25,ce=160,b=new Set,le=new WeakMap,ue=new WeakSet,x=null,S=null,C=null,de=!1,w=null,T=null,E=null;function fe(e){return e.length===0?null:[...e].sort((e,t)=>t.visibleArea===e.visibleArea?e.centerDistance===t.centerDistance?t.intersectionRatio-e.intersectionRatio:e.centerDistance-t.centerDistance:t.visibleArea-e.visibleArea)[0]??null}function pe(){return{x:(globalThis.innerWidth||document.documentElement.clientWidth||0)/2,y:(globalThis.innerHeight||document.documentElement.clientHeight||0)/2}}function me(e){return le.get(e)}function he(e){return e.closest(`.media-video-wrap`)?.querySelector(`[data-feed-video-mute-toggle]`)??null}function D(e){let t=he(e);if(!t)return;let n=C!==e||e.muted;t.dataset.muted=n?`true`:`false`,t.setAttribute(`aria-label`,n?`Play with sound`:`Mute video`)}function ge(){for(let e of b)D(e)}function _e(e){if(ue.has(e))return;let t=e.dataset.videoSrc;t&&(e.getAttribute(`src`)!==t&&(e.src=t),e.load(),ue.add(e))}function O(e){e?.pause()}function ve(e){_e(e),e.muted=C!==e,e.playsInline=!0,e.loop=!0,D(e),e.play().catch(()=>{})}function ye(){for(let e of b)e.isConnected||(T?.unobserve(e),E?.unobserve(e),b.delete(e),e===x&&(x=null),e===S&&(S=null),e===C&&(C=null))}function be(){if(w=null,ye(),document.hidden||de){O(x);return}let e=[];for(let t of b){let n=me(t);n&&(n.intersectionRatio<se||e.push({video:t,...n}))}let t=null;if(S?.isConnected){let e=me(S);e&&e.intersectionRatio>y?t=S:(!e||e.intersectionRatio<=y)&&(S=null)}if(t||=fe(e)?.video??null,!t){let e=x?me(x):void 0;if(x&&e&&e.intersectionRatio>y)return;O(x),x=null;return}t!==x&&(O(x),x=t),ve(t);for(let e of b)e!==t&&(O(e),D(e))}function k(){w!==null&&globalThis.clearTimeout(w),w=globalThis.setTimeout(be,ce)}function xe(e){let t=pe();for(let n of e){let e=n.target,r=n.boundingClientRect,i=r.left+r.width/2,a=r.top+r.height/2,o=n.intersectionRect.width*n.intersectionRect.height,s=Math.hypot(i-t.x,a-t.y);le.set(e,{intersectionRatio:n.intersectionRatio,visibleArea:o,centerDistance:s})}k()}function Se(e){for(let t of e)t.isIntersecting&&_e(t.target)}function Ce(){T&&E||globalThis.IntersectionObserver!==void 0&&(T=new globalThis.IntersectionObserver(xe,{threshold:[0,y,se,1]}),E=new globalThis.IntersectionObserver(Se,{rootMargin:oe,threshold:0}))}function we(e){b.has(e)||(Ce(),!(!T||!E)&&(b.add(e),T.observe(e),E.observe(e),he(e)?.addEventListener(`click`,Te),D(e)))}function Te(e){e.preventDefault(),e.stopPropagation();let t=e.currentTarget.closest(`.media-video-wrap`)?.querySelector(`[data-feed-short-video]`);t&&(S=t,C!==t||t.muted?(C&&C!==t&&(C.muted=!0),C=t,x!==t&&(O(x),x=t),ve(t)):(C=null,t.muted=!0,D(t)),ge(),k())}function Ee(e=document){let t=e.querySelectorAll(`[data-feed-short-video]`);for(let e of t)we(e);k()}document.addEventListener(v,e=>{de=e.detail?.open===!0,de&&O(x),k()}),document.addEventListener(`visibilitychange`,()=>{document.hidden&&O(x),k()}),document.readyState===`loading`?document.addEventListener(`DOMContentLoaded`,()=>Ee(),{once:!0}):queueMicrotask(()=>Ee());var De=4;function Oe(e){let t=e.querySelector(`[data-post-media]`);if(!t)return;let{scrollLeft:n,scrollWidth:r,clientWidth:i}=t;e.classList.toggle(`can-scroll-start`,n>De),e.classList.toggle(`can-scroll-end`,n+i<r-De)}function A(e){let t=e.querySelector(`[data-post-media]`);t&&(Oe(e),t.addEventListener(`scroll`,()=>Oe(e),{passive:!0}))}function ke(){document.querySelectorAll(`.media-gallery-scroll-wrap`).forEach(A)}var Ae=new globalThis.MutationObserver(e=>{for(let t of e)for(let e of t.addedNodes)e instanceof HTMLElement&&(e.matches(`.media-gallery-scroll-wrap`)&&A(e),e.querySelectorAll(`.media-gallery-scroll-wrap`).forEach(A))});document.readyState===`loading`?document.addEventListener(`DOMContentLoaded`,()=>{ke(),Ae.observe(document.body,{childList:!0,subtree:!0})}):(ke(),Ae.observe(document.body,{childList:!0,subtree:!0}));function je(e){let t=e.querySelector(`.site-header-more-btn`),n=e.querySelector(`.site-header-more-popover`);if(!t||!n||t.dataset.moreInitialized===`true`)return;t.dataset.moreInitialized=`true`;function r(){n.setAttribute(`aria-hidden`,`false`),t.setAttribute(`aria-expanded`,`true`),document.dispatchEvent(new CustomEvent(`basecoat:popover`,{detail:{source:t.parentElement}}))}function i(e=!1){n.setAttribute(`aria-hidden`,`true`),t.setAttribute(`aria-expanded`,`false`),e&&t.focus()}t.addEventListener(`click`,e=>{e.preventDefault(),e.stopPropagation(),t.getAttribute(`aria-expanded`)===`true`?i():r()}),document.addEventListener(`click`,e=>{e.target instanceof Node&&(t.parentElement?.contains(e.target)||i())}),document.addEventListener(`keydown`,e=>{e.key===`Escape`&&n.getAttribute(`aria-hidden`)===`false`&&i(!0)}),document.addEventListener(`basecoat:popover`,e=>{e.detail?.source!==t.parentElement&&i()})}var Me=`jant:nav-fresh-visits`;function Ne(){let e=document.createElement(`span`);return e.className=`site-header-link-fresh`,e.setAttribute(`aria-hidden`,`true`),e.textContent=`*`,e}function Pe(e){try{let t=JSON.parse(localStorage.getItem(Me)||`{}`),n=location.pathname,r=e.querySelectorAll(`[data-fresh-at]`);for(let e of r){let r=new URL(e.href).pathname,i=parseInt(e.dataset.freshAt,10);if(r===n)t[r]=Math.floor(Date.now()/1e3);else{let n=t[r];if(!n||n<i){let t=e.querySelector(`svg`);e.insertBefore(Ne(),t)}}}localStorage.setItem(Me,JSON.stringify(t))}catch{}}function Fe(e=document){let t=e.querySelector(`.site-header-hamburger`),n=e.querySelector(`#site-nav-drawer`),r=e.querySelector(`.site-nav-drawer-backdrop`),i=n?.querySelector(`.site-nav-drawer-close`);if(Pe(e),je(e),!t||!n||!r||t.dataset.drawerInitialized===`true`)return;t.dataset.drawerInitialized=`true`;function a(){n.setAttribute(`aria-hidden`,`false`),n.removeAttribute(`inert`),r.setAttribute(`aria-hidden`,`false`),t.setAttribute(`aria-expanded`,`true`),document.documentElement.classList.add(`drawer-open`);let e=n.querySelector(`.site-nav-drawer-close`)??n.querySelector(`a[href], button`);e&&e.focus()}function o(e=!0){n.setAttribute(`aria-hidden`,`true`),r.setAttribute(`aria-hidden`,`true`),t.setAttribute(`aria-expanded`,`false`),document.documentElement.classList.remove(`drawer-open`),n.addEventListener(`transitionend`,()=>{n.getAttribute(`aria-hidden`)===`true`&&n.setAttribute(`inert`,``)},{once:!0}),e&&t.focus()}t.addEventListener(`click`,()=>{t.getAttribute(`aria-expanded`)===`true`?o():a()}),i?.addEventListener(`click`,()=>o()),r.addEventListener(`click`,()=>o()),n.addEventListener(`click`,e=>{e.target instanceof Element&&e.target.closest(`a[href]`)&&o(!1)}),n.addEventListener(`keydown`,e=>{e.key===`Escape`&&(e.preventDefault(),o())})}Fe();var j=globalThis,M=j.ShadowRoot&&(j.ShadyCSS===void 0||j.ShadyCSS.nativeShadow)&&`adoptedStyleSheets`in Document.prototype&&`replace`in CSSStyleSheet.prototype,Ie=Symbol(),Le=new WeakMap,Re=class{constructor(e,t,n){if(this._$cssResult$=!0,n!==Ie)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=e,this.t=t}get styleSheet(){let e=this.o,t=this.t;if(M&&e===void 0){let n=t!==void 0&&t.length===1;n&&(e=Le.get(t)),e===void 0&&((this.o=e=new CSSStyleSheet).replaceSync(this.cssText),n&&Le.set(t,e))}return e}toString(){return this.cssText}},ze=e=>new Re(typeof e==`string`?e:e+``,void 0,Ie),Be=(e,t)=>{if(M)e.adoptedStyleSheets=t.map(e=>e instanceof CSSStyleSheet?e:e.styleSheet);else for(let n of t){let t=document.createElement(`style`),r=j.litNonce;r!==void 0&&t.setAttribute(`nonce`,r),t.textContent=n.cssText,e.appendChild(t)}},Ve=M?e=>e:e=>e instanceof CSSStyleSheet?(e=>{let t=``;for(let n of e.cssRules)t+=n.cssText;return ze(t)})(e):e,{is:He,defineProperty:Ue,getOwnPropertyDescriptor:We,getOwnPropertyNames:Ge,getOwnPropertySymbols:Ke,getPrototypeOf:qe}=Object,N=globalThis,Je=N.trustedTypes,Ye=Je?Je.emptyScript:``,Xe=N.reactiveElementPolyfillSupport,P=(e,t)=>e,F={toAttribute(e,t){switch(t){case Boolean:e=e?Ye:null;break;case Object:case Array:e=e==null?e:JSON.stringify(e)}return e},fromAttribute(e,t){let n=e;switch(t){case Boolean:n=e!==null;break;case Number:n=e===null?null:Number(e);break;case Object:case Array:try{n=JSON.parse(e)}catch{n=null}}return n}},Ze=(e,t)=>!He(e,t),Qe={attribute:!0,type:String,converter:F,reflect:!1,useDefault:!1,hasChanged:Ze};Symbol.metadata??=Symbol(`metadata`),N.litPropertyMetadata??=new WeakMap;var I=class extends HTMLElement{static addInitializer(e){this._$Ei(),(this.l??=[]).push(e)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(e,t=Qe){if(t.state&&(t.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(e)&&((t=Object.create(t)).wrapped=!0),this.elementProperties.set(e,t),!t.noAccessor){let n=Symbol(),r=this.getPropertyDescriptor(e,n,t);r!==void 0&&Ue(this.prototype,e,r)}}static getPropertyDescriptor(e,t,n){let{get:r,set:i}=We(this.prototype,e)??{get(){return this[t]},set(e){this[t]=e}};return{get:r,set(t){let a=r?.call(this);i?.call(this,t),this.requestUpdate(e,a,n)},configurable:!0,enumerable:!0}}static getPropertyOptions(e){return this.elementProperties.get(e)??Qe}static _$Ei(){if(this.hasOwnProperty(P(`elementProperties`)))return;let e=qe(this);e.finalize(),e.l!==void 0&&(this.l=[...e.l]),this.elementProperties=new Map(e.elementProperties)}static finalize(){if(this.hasOwnProperty(P(`finalized`)))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(P(`properties`))){let e=this.properties,t=[...Ge(e),...Ke(e)];for(let n of t)this.createProperty(n,e[n])}let e=this[Symbol.metadata];if(e!==null){let t=litPropertyMetadata.get(e);if(t!==void 0)for(let[e,n]of t)this.elementProperties.set(e,n)}this._$Eh=new Map;for(let[e,t]of this.elementProperties){let n=this._$Eu(e,t);n!==void 0&&this._$Eh.set(n,e)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(e){let t=[];if(Array.isArray(e)){let n=new Set(e.flat(1/0).reverse());for(let e of n)t.unshift(Ve(e))}else e!==void 0&&t.push(Ve(e));return t}static _$Eu(e,t){let n=t.attribute;return!1===n?void 0:typeof n==`string`?n:typeof e==`string`?e.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise(e=>this.enableUpdating=e),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(e=>e(this))}addController(e){(this._$EO??=new Set).add(e),this.renderRoot!==void 0&&this.isConnected&&e.hostConnected?.()}removeController(e){this._$EO?.delete(e)}_$E_(){let e=new Map,t=this.constructor.elementProperties;for(let n of t.keys())this.hasOwnProperty(n)&&(e.set(n,this[n]),delete this[n]);e.size>0&&(this._$Ep=e)}createRenderRoot(){let e=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return Be(e,this.constructor.elementStyles),e}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(e=>e.hostConnected?.())}enableUpdating(e){}disconnectedCallback(){this._$EO?.forEach(e=>e.hostDisconnected?.())}attributeChangedCallback(e,t,n){this._$AK(e,n)}_$ET(e,t){let n=this.constructor.elementProperties.get(e),r=this.constructor._$Eu(e,n);if(r!==void 0&&!0===n.reflect){let i=(n.converter?.toAttribute===void 0?F:n.converter).toAttribute(t,n.type);this._$Em=e,i==null?this.removeAttribute(r):this.setAttribute(r,i),this._$Em=null}}_$AK(e,t){let n=this.constructor,r=n._$Eh.get(e);if(r!==void 0&&this._$Em!==r){let e=n.getPropertyOptions(r),i=typeof e.converter==`function`?{fromAttribute:e.converter}:e.converter?.fromAttribute===void 0?F:e.converter;this._$Em=r;let a=i.fromAttribute(t,e.type);this[r]=a??this._$Ej?.get(r)??a,this._$Em=null}}requestUpdate(e,t,n,r=!1,i){if(e!==void 0){let a=this.constructor;if(!1===r&&(i=this[e]),n??=a.getPropertyOptions(e),!((n.hasChanged??Ze)(i,t)||n.useDefault&&n.reflect&&i===this._$Ej?.get(e)&&!this.hasAttribute(a._$Eu(e,n))))return;this.C(e,t,n)}!1===this.isUpdatePending&&(this._$ES=this._$EP())}C(e,t,{useDefault:n,reflect:r,wrapped:i},a){n&&!(this._$Ej??=new Map).has(e)&&(this._$Ej.set(e,a??t??this[e]),!0!==i||a!==void 0)||(this._$AL.has(e)||(this.hasUpdated||n||(t=void 0),this._$AL.set(e,t)),!0===r&&this._$Em!==e&&(this._$Eq??=new Set).add(e))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(e){Promise.reject(e)}let e=this.scheduleUpdate();return e!=null&&await e,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(let[e,t]of this._$Ep)this[e]=t;this._$Ep=void 0}let e=this.constructor.elementProperties;if(e.size>0)for(let[t,n]of e){let{wrapped:e}=n,r=this[t];!0!==e||this._$AL.has(t)||r===void 0||this.C(t,void 0,n,r)}}let e=!1,t=this._$AL;try{e=this.shouldUpdate(t),e?(this.willUpdate(t),this._$EO?.forEach(e=>e.hostUpdate?.()),this.update(t)):this._$EM()}catch(t){throw e=!1,this._$EM(),t}e&&this._$AE(t)}willUpdate(e){}_$AE(e){this._$EO?.forEach(e=>e.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(e)),this.updated(e)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(e){return!0}update(e){this._$Eq&&=this._$Eq.forEach(e=>this._$ET(e,this[e])),this._$EM()}updated(e){}firstUpdated(e){}};I.elementStyles=[],I.shadowRootOptions={mode:`open`},I[P(`elementProperties`)]=new Map,I[P(`finalized`)]=new Map,Xe?.({ReactiveElement:I}),(N.reactiveElementVersions??=[]).push(`2.1.2`);var L=globalThis,$e=e=>e,R=L.trustedTypes,et=R?R.createPolicy(`lit-html`,{createHTML:e=>e}):void 0,tt=`$lit$`,z=`lit$${Math.random().toFixed(9).slice(2)}$`,nt=`?`+z,rt=`<${nt}>`,B=document,V=()=>B.createComment(``),H=e=>e===null||typeof e!=`object`&&typeof e!=`function`,U=Array.isArray,it=e=>U(e)||typeof e?.[Symbol.iterator]==`function`,at=`[
2
- \f\r]`,W=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,ot=/-->/g,st=/>/g,G=RegExp(`>|${at}(?:([^\\s"'>=/]+)(${at}*=${at}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,`g`),ct=/'/g,lt=/"/g,ut=/^(?:script|style|textarea|title)$/i,dt=e=>(t,...n)=>({_$litType$:e,strings:t,values:n}),K=dt(1),ft=dt(2),q=Symbol.for(`lit-noChange`),J=Symbol.for(`lit-nothing`),pt=new WeakMap,Y=B.createTreeWalker(B,129);function mt(e,t){if(!U(e)||!e.hasOwnProperty(`raw`))throw Error(`invalid template strings array`);return et===void 0?t:et.createHTML(t)}var ht=(e,t)=>{let n=e.length-1,r=[],i,a=t===2?`<svg>`:t===3?`<math>`:``,o=W;for(let t=0;t<n;t++){let n=e[t],s,c,l=-1,u=0;for(;u<n.length&&(o.lastIndex=u,c=o.exec(n),c!==null);)u=o.lastIndex,o===W?c[1]===`!--`?o=ot:c[1]===void 0?c[2]===void 0?c[3]!==void 0&&(o=G):(ut.test(c[2])&&(i=RegExp(`</`+c[2],`g`)),o=G):o=st:o===G?c[0]===`>`?(o=i??W,l=-1):c[1]===void 0?l=-2:(l=o.lastIndex-c[2].length,s=c[1],o=c[3]===void 0?G:c[3]===`"`?lt:ct):o===lt||o===ct?o=G:o===ot||o===st?o=W:(o=G,i=void 0);let d=o===G&&e[t+1].startsWith(`/>`)?` `:``;a+=o===W?n+rt:l>=0?(r.push(s),n.slice(0,l)+tt+n.slice(l)+z+d):n+z+(l===-2?t:d)}return[mt(e,a+(e[n]||`<?>`)+(t===2?`</svg>`:t===3?`</math>`:``)),r]},gt=class e{constructor({strings:t,_$litType$:n},r){let i;this.parts=[];let a=0,o=0,s=t.length-1,c=this.parts,[l,u]=ht(t,n);if(this.el=e.createElement(l,r),Y.currentNode=this.el.content,n===2||n===3){let e=this.el.content.firstChild;e.replaceWith(...e.childNodes)}for(;(i=Y.nextNode())!==null&&c.length<s;){if(i.nodeType===1){if(i.hasAttributes())for(let e of i.getAttributeNames())if(e.endsWith(tt)){let t=u[o++],n=i.getAttribute(e).split(z),r=/([.?@])?(.*)/.exec(t);c.push({type:1,index:a,name:r[2],strings:n,ctor:r[1]===`.`?yt:r[1]===`?`?bt:r[1]===`@`?xt:Z}),i.removeAttribute(e)}else e.startsWith(z)&&(c.push({type:6,index:a}),i.removeAttribute(e));if(ut.test(i.tagName)){let e=i.textContent.split(z),t=e.length-1;if(t>0){i.textContent=R?R.emptyScript:``;for(let n=0;n<t;n++)i.append(e[n],V()),Y.nextNode(),c.push({type:2,index:++a});i.append(e[t],V())}}}else if(i.nodeType===8)if(i.data===nt)c.push({type:2,index:a});else{let e=-1;for(;(e=i.data.indexOf(z,e+1))!==-1;)c.push({type:7,index:a}),e+=z.length-1}a++}}static createElement(e,t){let n=B.createElement(`template`);return n.innerHTML=e,n}};function X(e,t,n=e,r){if(t===q)return t;let i=r===void 0?n._$Cl:n._$Co?.[r],a=H(t)?void 0:t._$litDirective$;return i?.constructor!==a&&(i?._$AO?.(!1),a===void 0?i=void 0:(i=new a(e),i._$AT(e,n,r)),r===void 0?n._$Cl=i:(n._$Co??=[])[r]=i),i!==void 0&&(t=X(e,i._$AS(e,t.values),i,r)),t}var _t=class{constructor(e,t){this._$AV=[],this._$AN=void 0,this._$AD=e,this._$AM=t}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(e){let{el:{content:t},parts:n}=this._$AD,r=(e?.creationScope??B).importNode(t,!0);Y.currentNode=r;let i=Y.nextNode(),a=0,o=0,s=n[0];for(;s!==void 0;){if(a===s.index){let t;s.type===2?t=new vt(i,i.nextSibling,this,e):s.type===1?t=new s.ctor(i,s.name,s.strings,this,e):s.type===6&&(t=new St(i,this,e)),this._$AV.push(t),s=n[++o]}a!==s?.index&&(i=Y.nextNode(),a++)}return Y.currentNode=B,r}p(e){let t=0;for(let n of this._$AV)n!==void 0&&(n.strings===void 0?n._$AI(e[t]):(n._$AI(e,n,t),t+=n.strings.length-2)),t++}},vt=class e{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(e,t,n,r){this.type=2,this._$AH=J,this._$AN=void 0,this._$AA=e,this._$AB=t,this._$AM=n,this.options=r,this._$Cv=r?.isConnected??!0}get parentNode(){let e=this._$AA.parentNode,t=this._$AM;return t!==void 0&&e?.nodeType===11&&(e=t.parentNode),e}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(e,t=this){e=X(this,e,t),H(e)?e===J||e==null||e===``?(this._$AH!==J&&this._$AR(),this._$AH=J):e!==this._$AH&&e!==q&&this._(e):e._$litType$===void 0?e.nodeType===void 0?it(e)?this.k(e):this._(e):this.T(e):this.$(e)}O(e){return this._$AA.parentNode.insertBefore(e,this._$AB)}T(e){this._$AH!==e&&(this._$AR(),this._$AH=this.O(e))}_(e){this._$AH!==J&&H(this._$AH)?this._$AA.nextSibling.data=e:this.T(B.createTextNode(e)),this._$AH=e}$(e){let{values:t,_$litType$:n}=e,r=typeof n==`number`?this._$AC(e):(n.el===void 0&&(n.el=gt.createElement(mt(n.h,n.h[0]),this.options)),n);if(this._$AH?._$AD===r)this._$AH.p(t);else{let e=new _t(r,this),n=e.u(this.options);e.p(t),this.T(n),this._$AH=e}}_$AC(e){let t=pt.get(e.strings);return t===void 0&&pt.set(e.strings,t=new gt(e)),t}k(t){U(this._$AH)||(this._$AH=[],this._$AR());let n=this._$AH,r,i=0;for(let a of t)i===n.length?n.push(r=new e(this.O(V()),this.O(V()),this,this.options)):r=n[i],r._$AI(a),i++;i<n.length&&(this._$AR(r&&r._$AB.nextSibling,i),n.length=i)}_$AR(e=this._$AA.nextSibling,t){for(this._$AP?.(!1,!0,t);e!==this._$AB;){let t=$e(e).nextSibling;$e(e).remove(),e=t}}setConnected(e){this._$AM===void 0&&(this._$Cv=e,this._$AP?.(e))}},Z=class{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(e,t,n,r,i){this.type=1,this._$AH=J,this._$AN=void 0,this.element=e,this.name=t,this._$AM=r,this.options=i,n.length>2||n[0]!==``||n[1]!==``?(this._$AH=Array(n.length-1).fill(new String),this.strings=n):this._$AH=J}_$AI(e,t=this,n,r){let i=this.strings,a=!1;if(i===void 0)e=X(this,e,t,0),a=!H(e)||e!==this._$AH&&e!==q,a&&(this._$AH=e);else{let r=e,o,s;for(e=i[0],o=0;o<i.length-1;o++)s=X(this,r[n+o],t,o),s===q&&(s=this._$AH[o]),a||=!H(s)||s!==this._$AH[o],s===J?e=J:e!==J&&(e+=(s??``)+i[o+1]),this._$AH[o]=s}a&&!r&&this.j(e)}j(e){e===J?this.element.removeAttribute(this.name):this.element.setAttribute(this.name,e??``)}},yt=class extends Z{constructor(){super(...arguments),this.type=3}j(e){this.element[this.name]=e===J?void 0:e}},bt=class extends Z{constructor(){super(...arguments),this.type=4}j(e){this.element.toggleAttribute(this.name,!!e&&e!==J)}},xt=class extends Z{constructor(e,t,n,r,i){super(e,t,n,r,i),this.type=5}_$AI(e,t=this){if((e=X(this,e,t,0)??J)===q)return;let n=this._$AH,r=e===J&&n!==J||e.capture!==n.capture||e.once!==n.once||e.passive!==n.passive,i=e!==J&&(n===J||r);r&&this.element.removeEventListener(this.name,this,n),i&&this.element.addEventListener(this.name,this,e),this._$AH=e}handleEvent(e){typeof this._$AH==`function`?this._$AH.call(this.options?.host??this.element,e):this._$AH.handleEvent(e)}},St=class{constructor(e,t,n){this.element=e,this.type=6,this._$AN=void 0,this._$AM=t,this.options=n}get _$AU(){return this._$AM._$AU}_$AI(e){X(this,e)}},Ct=L.litHtmlPolyfillSupport;Ct?.(gt,vt),(L.litHtmlVersions??=[]).push(`3.3.2`);var wt=(e,t,n)=>{let r=n?.renderBefore??t,i=r._$litPart$;if(i===void 0){let e=n?.renderBefore??null;r._$litPart$=i=new vt(t.insertBefore(V(),e),e,void 0,n??{})}return i._$AI(e),i},Tt=globalThis,Q=class extends I{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){let e=super.createRenderRoot();return this.renderOptions.renderBefore??=e.firstChild,e}update(e){let t=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(e),this._$Do=wt(t,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return q}};Q._$litElement$=!0,Q.finalized=!0,Tt.litElementHydrateSupport?.({LitElement:Q});var Et=Tt.litElementPolyfillSupport;Et?.({LitElement:Q}),(Tt.litElementVersions??=[]).push(`4.2.2`);function Dt(e){if(!e.mimeType?.startsWith(`video/`)||!Number.isFinite(e.durationSeconds)||!e.durationSeconds||e.durationSeconds<=0||e.durationSeconds>15)return!1;let t=e.size;return!(typeof t==`number`&&t>12582912)}var Ot=640,kt=8,At=72,jt=16,Mt=704,Nt=.9,Pt=.85;function $(e){if(!(!Number.isFinite(e)||!e||e<=0))return e}function Ft(){return{width:globalThis.innerWidth||document.documentElement.clientWidth||0,height:globalThis.innerHeight||document.documentElement.clientHeight||0}}function It(e,t){let n=e<=Ot?kt:At;return{width:Math.max(0,e-n*2),height:Math.max(0,t-jt*2)}}function Lt(e,t,n){let r=$(e?.width),i=$(e?.height);if(!r||!i)return null;let a=It(t,n);if(a.width<=0||a.height<=0)return null;let o=Math.min(a.width/r,a.height/i);return{width:Math.max(1,Math.round(r*o)),height:Math.max(1,Math.round(i*o))}}function Rt(e,t,n){if(!e||e.mimeType?.startsWith(`video/`)||!$(e.width)||!$(e.height)||t<=0||n<=0)return!1;let r=$(e.width),i=$(e.height);if(!r||!i)return!1;let a=t<=Ot,o=It(t,n),s=o.width,c=o.height;if(s<=0||c<=0)return!1;let l=r/i,u=Math.min(s,c*l);return l<Nt&&u<(a?s:Math.min(s,Mt))*Pt}var zt=class extends Q{static properties={_images:{state:!0},_currentIndex:{state:!0},_open:{state:!0},_viewportWidth:{state:!0},_viewportHeight:{state:!0},_videoCurrentTime:{state:!0},_videoDuration:{state:!0},_videoMuted:{state:!0}};createRenderRoot(){return this.innerHTML=``,this}constructor(){super();let e=Ft();this._images=[],this._currentIndex=0,this._open=!1,this._viewportWidth=e.width,this._viewportHeight=e.height,this._videoCurrentTime=0,this._videoDuration=0,this._videoMuted=!1}connectedCallback(){super.connectedCallback(),document.addEventListener(`click`,this.#e),window.addEventListener(`resize`,this.#o),this.#s()}disconnectedCallback(){super.disconnectedCallback(),document.removeEventListener(`click`,this.#e),window.removeEventListener(`resize`,this.#o)}open(e,t){this.#s(),this.#c(),this._images=e,this._currentIndex=Math.max(0,Math.min(t,e.length-1)),this.#u(this._images[this._currentIndex]),this._open=!0,document.dispatchEvent(new CustomEvent(v,{detail:{open:!0}})),this.updateComplete.then(()=>{this.querySelector(`.media-lightbox`)?.showModal(),this.#l()})}close(){this.#c(),this.querySelector(`.media-lightbox`)?.close(),this._open=!1,document.dispatchEvent(new CustomEvent(v,{detail:{open:!1}}))}#e=e=>{let t=e.target,n=t.closest(`[data-post-media] a[data-lightbox-index]`);if(n){let t=n.closest(`[data-lightbox-group]`);if(!t)return;e.preventDefault();let r=parseInt(n.dataset.lightboxIndex??`0`,10);try{let e=JSON.parse(t.dataset.lightboxGroup??`[]`);e.length>0&&this.open(e,r)}catch{}return}let r=t.closest(`[data-post-body] img`);if(r){e.preventDefault();let t=r.closest(`[data-post-body]`);if(!t)return;let n=Array.from(t.querySelectorAll(`img`)),i=n.map(e=>({url:e.src,alt:e.alt||``,width:$(e.naturalWidth||Number(e.getAttribute(`width`))),height:$(e.naturalHeight||Number(e.getAttribute(`height`)))})),a=n.indexOf(r);i.length>0&&this.open(i,Math.max(0,a))}};#t(){this._images.length<=1||(this.#c(),this._currentIndex=(this._currentIndex-1+this._images.length)%this._images.length)}#n(){this._images.length<=1||(this.#c(),this._currentIndex=(this._currentIndex+1)%this._images.length)}#r=e=>{let t=e,n=e.target;if(t.key===`Escape`){e.preventDefault(),this.close();return}if(!(t.key!==`ArrowLeft`&&t.key!==`ArrowRight`)&&!n?.classList.contains(`media-lightbox-short-progress`)){if(this._images[this._currentIndex]?.mimeType?.startsWith(`video/`)){let n=this.querySelector(`.media-lightbox-video`);if(n){e.preventDefault();let r=t.key===`ArrowLeft`?-5:5,i=Number.isFinite(n.duration)&&n.duration>0?n.duration:null,a=i==null?Math.max(0,n.currentTime+r):Math.max(0,Math.min(n.currentTime+r,i));n.currentTime=a,this._videoCurrentTime=a}return}e.preventDefault(),t.key===`ArrowLeft`?this.#t():this.#n()}};#i=e=>{let t=e.target;(t===e.currentTarget||t.classList.contains(`media-lightbox-content`)||t.classList.contains(`media-lightbox-stage`))&&this.close()};#a=()=>{this.#c(),this._open&&document.dispatchEvent(new CustomEvent(v,{detail:{open:!1}})),this._open=!1};#o=()=>{this.#s()};#s(){let e=Ft();e.width===this._viewportWidth&&e.height===this._viewportHeight||(this._viewportWidth=e.width,this._viewportHeight=e.height)}#c(){this.querySelector(`.media-lightbox-video`)?.pause()}#l(){if(this._images[this._currentIndex]?.mimeType?.startsWith(`video/`)){let e=this.querySelector(`.media-lightbox-video`);if(e){e.focus();return}}this.querySelector(`.media-lightbox-content`)?.focus()}#u(e){this._videoCurrentTime=0,this._videoDuration=e?.durationSeconds&&e.durationSeconds>0?e.durationSeconds:0,this._videoMuted=!1}#d(){let e=this._images[this._currentIndex];if(!Dt(e)){this.#u(e);return}let t=this.querySelector(`.media-lightbox-video`);t&&(t.currentTime=0,t.muted=this._videoMuted,t.play().catch(()=>{}))}#f=e=>{let t=e.currentTarget;Number.isFinite(t.duration)&&t.duration>0&&(this._videoDuration=t.duration),this._videoCurrentTime=t.currentTime,t.muted=this._videoMuted};#p=e=>{let t=e.currentTarget;this._videoCurrentTime=t.currentTime,Number.isFinite(t.duration)&&t.duration>0&&(this._videoDuration=t.duration)};#m=e=>{let t=e.currentTarget,n=this.querySelector(`.media-lightbox-video`),r=Number.parseFloat(t.value);!n||!Number.isFinite(r)||r<0||(n.currentTime=r,this._videoCurrentTime=r)};#h=()=>{this._videoMuted=!this._videoMuted;let e=this.querySelector(`.media-lightbox-video`);e&&(e.muted=this._videoMuted)};updated(e){if(super.updated(e),!this._open||!e.has(`_currentIndex`)&&!e.has(`_open`))return;let t=this.querySelector(`.media-lightbox-stage`);t&&(t.scrollTop=0,t.scrollLeft=0,this.#d(),this.#l())}render(){if(!this._open)return J;let e=this._images[this._currentIndex],t=this._images.length>1,n=e?.mimeType?.startsWith(`video/`),r=Dt(e),i=Rt(e,this._viewportWidth,this._viewportHeight),a=r?Lt(e,this._viewportWidth,this._viewportHeight):null,o=r&&!!a&&a.height>a.width,s=a?`width:${a.width}px;height:${a.height}px;`:J,c=this._videoDuration>0?this._videoDuration:e?.durationSeconds??1,l=Math.min(this._videoCurrentTime,c),u=c>0?l/c*100:0;return K`
2
+ \f\r]`,W=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,ot=/-->/g,st=/>/g,G=RegExp(`>|${at}(?:([^\\s"'>=/]+)(${at}*=${at}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,`g`),ct=/'/g,lt=/"/g,ut=/^(?:script|style|textarea|title)$/i,dt=e=>(t,...n)=>({_$litType$:e,strings:t,values:n}),K=dt(1),ft=dt(2),q=Symbol.for(`lit-noChange`),J=Symbol.for(`lit-nothing`),pt=new WeakMap,Y=B.createTreeWalker(B,129);function mt(e,t){if(!U(e)||!e.hasOwnProperty(`raw`))throw Error(`invalid template strings array`);return et===void 0?t:et.createHTML(t)}var ht=(e,t)=>{let n=e.length-1,r=[],i,a=t===2?`<svg>`:t===3?`<math>`:``,o=W;for(let t=0;t<n;t++){let n=e[t],s,c,l=-1,u=0;for(;u<n.length&&(o.lastIndex=u,c=o.exec(n),c!==null);)u=o.lastIndex,o===W?c[1]===`!--`?o=ot:c[1]===void 0?c[2]===void 0?c[3]!==void 0&&(o=G):(ut.test(c[2])&&(i=RegExp(`</`+c[2],`g`)),o=G):o=st:o===G?c[0]===`>`?(o=i??W,l=-1):c[1]===void 0?l=-2:(l=o.lastIndex-c[2].length,s=c[1],o=c[3]===void 0?G:c[3]===`"`?lt:ct):o===lt||o===ct?o=G:o===ot||o===st?o=W:(o=G,i=void 0);let d=o===G&&e[t+1].startsWith(`/>`)?` `:``;a+=o===W?n+rt:l>=0?(r.push(s),n.slice(0,l)+tt+n.slice(l)+z+d):n+z+(l===-2?t:d)}return[mt(e,a+(e[n]||`<?>`)+(t===2?`</svg>`:t===3?`</math>`:``)),r]},gt=class e{constructor({strings:t,_$litType$:n},r){let i;this.parts=[];let a=0,o=0,s=t.length-1,c=this.parts,[l,u]=ht(t,n);if(this.el=e.createElement(l,r),Y.currentNode=this.el.content,n===2||n===3){let e=this.el.content.firstChild;e.replaceWith(...e.childNodes)}for(;(i=Y.nextNode())!==null&&c.length<s;){if(i.nodeType===1){if(i.hasAttributes())for(let e of i.getAttributeNames())if(e.endsWith(tt)){let t=u[o++],n=i.getAttribute(e).split(z),r=/([.?@])?(.*)/.exec(t);c.push({type:1,index:a,name:r[2],strings:n,ctor:r[1]===`.`?yt:r[1]===`?`?bt:r[1]===`@`?xt:Z}),i.removeAttribute(e)}else e.startsWith(z)&&(c.push({type:6,index:a}),i.removeAttribute(e));if(ut.test(i.tagName)){let e=i.textContent.split(z),t=e.length-1;if(t>0){i.textContent=R?R.emptyScript:``;for(let n=0;n<t;n++)i.append(e[n],V()),Y.nextNode(),c.push({type:2,index:++a});i.append(e[t],V())}}}else if(i.nodeType===8)if(i.data===nt)c.push({type:2,index:a});else{let e=-1;for(;(e=i.data.indexOf(z,e+1))!==-1;)c.push({type:7,index:a}),e+=z.length-1}a++}}static createElement(e,t){let n=B.createElement(`template`);return n.innerHTML=e,n}};function X(e,t,n=e,r){if(t===q)return t;let i=r===void 0?n._$Cl:n._$Co?.[r],a=H(t)?void 0:t._$litDirective$;return i?.constructor!==a&&(i?._$AO?.(!1),a===void 0?i=void 0:(i=new a(e),i._$AT(e,n,r)),r===void 0?n._$Cl=i:(n._$Co??=[])[r]=i),i!==void 0&&(t=X(e,i._$AS(e,t.values),i,r)),t}var _t=class{constructor(e,t){this._$AV=[],this._$AN=void 0,this._$AD=e,this._$AM=t}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(e){let{el:{content:t},parts:n}=this._$AD,r=(e?.creationScope??B).importNode(t,!0);Y.currentNode=r;let i=Y.nextNode(),a=0,o=0,s=n[0];for(;s!==void 0;){if(a===s.index){let t;s.type===2?t=new vt(i,i.nextSibling,this,e):s.type===1?t=new s.ctor(i,s.name,s.strings,this,e):s.type===6&&(t=new St(i,this,e)),this._$AV.push(t),s=n[++o]}a!==s?.index&&(i=Y.nextNode(),a++)}return Y.currentNode=B,r}p(e){let t=0;for(let n of this._$AV)n!==void 0&&(n.strings===void 0?n._$AI(e[t]):(n._$AI(e,n,t),t+=n.strings.length-2)),t++}},vt=class e{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(e,t,n,r){this.type=2,this._$AH=J,this._$AN=void 0,this._$AA=e,this._$AB=t,this._$AM=n,this.options=r,this._$Cv=r?.isConnected??!0}get parentNode(){let e=this._$AA.parentNode,t=this._$AM;return t!==void 0&&e?.nodeType===11&&(e=t.parentNode),e}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(e,t=this){e=X(this,e,t),H(e)?e===J||e==null||e===``?(this._$AH!==J&&this._$AR(),this._$AH=J):e!==this._$AH&&e!==q&&this._(e):e._$litType$===void 0?e.nodeType===void 0?it(e)?this.k(e):this._(e):this.T(e):this.$(e)}O(e){return this._$AA.parentNode.insertBefore(e,this._$AB)}T(e){this._$AH!==e&&(this._$AR(),this._$AH=this.O(e))}_(e){this._$AH!==J&&H(this._$AH)?this._$AA.nextSibling.data=e:this.T(B.createTextNode(e)),this._$AH=e}$(e){let{values:t,_$litType$:n}=e,r=typeof n==`number`?this._$AC(e):(n.el===void 0&&(n.el=gt.createElement(mt(n.h,n.h[0]),this.options)),n);if(this._$AH?._$AD===r)this._$AH.p(t);else{let e=new _t(r,this),n=e.u(this.options);e.p(t),this.T(n),this._$AH=e}}_$AC(e){let t=pt.get(e.strings);return t===void 0&&pt.set(e.strings,t=new gt(e)),t}k(t){U(this._$AH)||(this._$AH=[],this._$AR());let n=this._$AH,r,i=0;for(let a of t)i===n.length?n.push(r=new e(this.O(V()),this.O(V()),this,this.options)):r=n[i],r._$AI(a),i++;i<n.length&&(this._$AR(r&&r._$AB.nextSibling,i),n.length=i)}_$AR(e=this._$AA.nextSibling,t){for(this._$AP?.(!1,!0,t);e!==this._$AB;){let t=$e(e).nextSibling;$e(e).remove(),e=t}}setConnected(e){this._$AM===void 0&&(this._$Cv=e,this._$AP?.(e))}},Z=class{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(e,t,n,r,i){this.type=1,this._$AH=J,this._$AN=void 0,this.element=e,this.name=t,this._$AM=r,this.options=i,n.length>2||n[0]!==``||n[1]!==``?(this._$AH=Array(n.length-1).fill(new String),this.strings=n):this._$AH=J}_$AI(e,t=this,n,r){let i=this.strings,a=!1;if(i===void 0)e=X(this,e,t,0),a=!H(e)||e!==this._$AH&&e!==q,a&&(this._$AH=e);else{let r=e,o,s;for(e=i[0],o=0;o<i.length-1;o++)s=X(this,r[n+o],t,o),s===q&&(s=this._$AH[o]),a||=!H(s)||s!==this._$AH[o],s===J?e=J:e!==J&&(e+=(s??``)+i[o+1]),this._$AH[o]=s}a&&!r&&this.j(e)}j(e){e===J?this.element.removeAttribute(this.name):this.element.setAttribute(this.name,e??``)}},yt=class extends Z{constructor(){super(...arguments),this.type=3}j(e){this.element[this.name]=e===J?void 0:e}},bt=class extends Z{constructor(){super(...arguments),this.type=4}j(e){this.element.toggleAttribute(this.name,!!e&&e!==J)}},xt=class extends Z{constructor(e,t,n,r,i){super(e,t,n,r,i),this.type=5}_$AI(e,t=this){if((e=X(this,e,t,0)??J)===q)return;let n=this._$AH,r=e===J&&n!==J||e.capture!==n.capture||e.once!==n.once||e.passive!==n.passive,i=e!==J&&(n===J||r);r&&this.element.removeEventListener(this.name,this,n),i&&this.element.addEventListener(this.name,this,e),this._$AH=e}handleEvent(e){typeof this._$AH==`function`?this._$AH.call(this.options?.host??this.element,e):this._$AH.handleEvent(e)}},St=class{constructor(e,t,n){this.element=e,this.type=6,this._$AN=void 0,this._$AM=t,this.options=n}get _$AU(){return this._$AM._$AU}_$AI(e){X(this,e)}},Ct=L.litHtmlPolyfillSupport;Ct?.(gt,vt),(L.litHtmlVersions??=[]).push(`3.3.2`);var wt=(e,t,n)=>{let r=n?.renderBefore??t,i=r._$litPart$;if(i===void 0){let e=n?.renderBefore??null;r._$litPart$=i=new vt(t.insertBefore(V(),e),e,void 0,n??{})}return i._$AI(e),i},Tt=globalThis,Q=class extends I{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){let e=super.createRenderRoot();return this.renderOptions.renderBefore??=e.firstChild,e}update(e){let t=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(e),this._$Do=wt(t,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return q}};Q._$litElement$=!0,Q.finalized=!0,Tt.litElementHydrateSupport?.({LitElement:Q});var Et=Tt.litElementPolyfillSupport;Et?.({LitElement:Q}),(Tt.litElementVersions??=[]).push(`4.2.2`);function Dt(e){if(!e.mimeType?.startsWith(`video/`)||!Number.isFinite(e.durationSeconds)||!e.durationSeconds||e.durationSeconds<=0||e.durationSeconds>15)return!1;let t=e.size;return!(typeof t==`number`&&t>12582912)}var Ot=640,kt=8,At=72,jt=16,Mt=704,Nt=.9,Pt=.85;function $(e){if(!(!Number.isFinite(e)||!e||e<=0))return e}function Ft(){return{width:globalThis.innerWidth||document.documentElement.clientWidth||0,height:globalThis.innerHeight||document.documentElement.clientHeight||0}}function It(e,t){let n=e<=Ot?kt:At;return{width:Math.max(0,e-n*2),height:Math.max(0,t-jt*2)}}function Lt(e,t,n){let r=$(e?.width),i=$(e?.height);if(!r||!i)return null;let a=It(t,n);if(a.width<=0||a.height<=0)return null;let o=Math.min(a.width/r,a.height/i);return{width:Math.max(1,Math.round(r*o)),height:Math.max(1,Math.round(i*o))}}function Rt(e,t,n){if(!e||e.mimeType?.startsWith(`video/`)||!$(e.width)||!$(e.height)||t<=0||n<=0)return!1;let r=$(e.width),i=$(e.height);if(!r||!i)return!1;let a=t<=Ot,o=It(t,n),s=o.width,c=o.height;if(s<=0||c<=0)return!1;let l=r/i,u=Math.min(s,c*l);return l<Nt&&u<(a?s:Math.min(s,Mt))*Pt}var zt=class extends Q{static properties={_images:{state:!0},_currentIndex:{state:!0},_open:{state:!0},_viewportWidth:{state:!0},_viewportHeight:{state:!0},_videoCurrentTime:{state:!0},_videoDuration:{state:!0},_videoMuted:{state:!0}};createRenderRoot(){return this.innerHTML=``,this}constructor(){super();let e=Ft();this._images=[],this._currentIndex=0,this._open=!1,this._viewportWidth=e.width,this._viewportHeight=e.height,this._videoCurrentTime=0,this._videoDuration=0,this._videoMuted=!1}connectedCallback(){super.connectedCallback(),document.addEventListener(`click`,this.#e),window.addEventListener(`resize`,this.#c),this.#l()}disconnectedCallback(){super.disconnectedCallback(),document.removeEventListener(`click`,this.#e),window.removeEventListener(`resize`,this.#c)}open(e,t){this.#l(),this.#u(),this._images=e,this._currentIndex=Math.max(0,Math.min(t,e.length-1)),this.#p(this._images[this._currentIndex]),this._open=!0,document.dispatchEvent(new CustomEvent(v,{detail:{open:!0}})),this.updateComplete.then(()=>{this.querySelector(`.media-lightbox`)?.showModal(),this.#d()})}close(){this.#u(),this.querySelector(`.media-lightbox`)?.close(),this._open=!1,document.dispatchEvent(new CustomEvent(v,{detail:{open:!1}}))}#e=e=>{let t=e.target,n=t.closest(`[data-post-media] a[data-lightbox-index]`);if(n){let t=n.closest(`[data-lightbox-group]`);if(!t)return;e.preventDefault();let r=parseInt(n.dataset.lightboxIndex??`0`,10);try{let e=JSON.parse(t.dataset.lightboxGroup??`[]`);e.length>0&&this.open(e,r)}catch{}return}let r=t.closest(`[data-post-body] img`);if(r){e.preventDefault();let t=r.closest(`[data-post-body]`);if(!t)return;let n=Array.from(t.querySelectorAll(`img`)),i=n.map(e=>({url:e.src,alt:e.alt||``,width:$(e.naturalWidth||Number(e.getAttribute(`width`))),height:$(e.naturalHeight||Number(e.getAttribute(`height`)))})),a=n.indexOf(r);i.length>0&&this.open(i,Math.max(0,a))}};#t(){this._images.length<=1||(this.#u(),this._currentIndex=(this._currentIndex-1+this._images.length)%this._images.length)}#n(){this._images.length<=1||(this.#u(),this._currentIndex=(this._currentIndex+1)%this._images.length)}#r=e=>{let t=e,n=e.target;if(t.key===`Escape`){e.preventDefault(),this.close();return}if(n instanceof HTMLInputElement||n instanceof HTMLButtonElement||n instanceof HTMLVideoElement)return;if(!this._images[this._currentIndex]?.mimeType?.startsWith(`video/`)){t.key===`ArrowLeft`?(e.preventDefault(),this.#t()):t.key===`ArrowRight`&&(e.preventDefault(),this.#n());return}let r=this.querySelector(`.media-lightbox-video`);r&&this.#i(t,r)};#i(e,t){let n=Number.isFinite(t.duration)&&t.duration>0?t.duration:null,r=e=>{let r=n==null?Math.max(0,e):Math.max(0,Math.min(e,n));t.currentTime=r,this._videoCurrentTime=r},i=e.key,a=i.toLowerCase();if(i===` `||a===`k`)e.preventDefault(),t.paused?t.play().catch(()=>{}):t.pause();else if(i===`ArrowLeft`)e.preventDefault(),r(t.currentTime-5);else if(i===`ArrowRight`)e.preventDefault(),r(t.currentTime+5);else if(i===`Home`)e.preventDefault(),r(0);else if(i===`End`)n!=null&&(e.preventDefault(),r(n));else if(i.length===1&&i>=`0`&&i<=`9`)n!=null&&(e.preventDefault(),r(Number(i)/10*n));else if(i===`ArrowUp`)e.preventDefault(),t.volume=Math.min(1,t.volume+.05);else if(i===`ArrowDown`)e.preventDefault(),t.volume=Math.max(0,t.volume-.05);else if(a===`m`){e.preventDefault();let n=!t.muted;t.muted=n,this._videoMuted=n}else a===`f`&&(e.preventDefault(),this.#a(t))}#a(e){let t=document,n=e;if(document.fullscreenElement??t.webkitFullscreenElement){document.exitFullscreen?document.exitFullscreen().catch(()=>{}):t.webkitExitFullscreen?.();return}e.requestFullscreen?e.requestFullscreen().catch(()=>{}):n.webkitRequestFullscreen?n.webkitRequestFullscreen():n.webkitEnterFullscreen&&n.webkitEnterFullscreen()}#o=e=>{let t=e.target;(t===e.currentTarget||t.classList.contains(`media-lightbox-content`)||t.classList.contains(`media-lightbox-stage`))&&this.close()};#s=()=>{this.#u(),this._open&&document.dispatchEvent(new CustomEvent(v,{detail:{open:!1}})),this._open=!1};#c=()=>{this.#l()};#l(){let e=Ft();e.width===this._viewportWidth&&e.height===this._viewportHeight||(this._viewportWidth=e.width,this._viewportHeight=e.height)}#u(){this.querySelector(`.media-lightbox-video`)?.pause()}#d(){this.querySelector(`.media-lightbox-content`)?.focus()}#f=()=>{this.querySelector(`.media-lightbox-content`)?.focus({preventScroll:!0})};#p(e){this._videoCurrentTime=0,this._videoDuration=e?.durationSeconds&&e.durationSeconds>0?e.durationSeconds:0,this._videoMuted=!1}#m(){let e=this._images[this._currentIndex];if(!Dt(e)){this.#p(e);return}let t=this.querySelector(`.media-lightbox-video`);t&&(t.currentTime=0,t.muted=this._videoMuted,t.play().catch(()=>{}))}#h=e=>{let t=e.currentTarget;Number.isFinite(t.duration)&&t.duration>0&&(this._videoDuration=t.duration),this._videoCurrentTime=t.currentTime,t.muted=this._videoMuted};#g=e=>{let t=e.currentTarget;this._videoCurrentTime=t.currentTime,Number.isFinite(t.duration)&&t.duration>0&&(this._videoDuration=t.duration)};#_=e=>{let t=e.currentTarget,n=this.querySelector(`.media-lightbox-video`),r=Number.parseFloat(t.value);!n||!Number.isFinite(r)||r<0||(n.currentTime=r,this._videoCurrentTime=r)};#v=()=>{this._videoMuted=!this._videoMuted;let e=this.querySelector(`.media-lightbox-video`);e&&(e.muted=this._videoMuted)};updated(e){if(super.updated(e),!this._open||!e.has(`_currentIndex`)&&!e.has(`_open`))return;let t=this.querySelector(`.media-lightbox-stage`);t&&(t.scrollTop=0,t.scrollLeft=0,this.#m(),this.#d())}render(){if(!this._open)return J;let e=this._images[this._currentIndex],t=this._images.length>1,n=e?.mimeType?.startsWith(`video/`),r=Dt(e),i=Rt(e,this._viewportWidth,this._viewportHeight),a=r?Lt(e,this._viewportWidth,this._viewportHeight):null,o=r&&!!a&&a.height>a.width,s=a?`width:${a.width}px;height:${a.height}px;`:J,c=this._videoDuration>0?this._videoDuration:e?.durationSeconds??1,l=Math.min(this._videoCurrentTime,c),u=c>0?l/c*100:0;return K`
3
3
  <dialog
4
4
  class=${`media-lightbox${r?` media-lightbox-short`:``}`}
5
5
  @keydown=${this.#r}
6
- @click=${this.#i}
7
- @close=${this.#a}
6
+ @click=${this.#o}
7
+ @close=${this.#s}
8
8
  >
9
9
  <div class="media-lightbox-content" tabindex="-1">
10
10
  <button
@@ -46,8 +46,9 @@ var e=null,t=0,n=!1,r=null,i=null,a=0;function o(e){return!isFinite(e)||e<0?`0:0
46
46
  playsinline
47
47
  loop
48
48
  ?muted=${this._videoMuted}
49
- @loadedmetadata=${this.#f}
50
- @timeupdate=${this.#p}
49
+ @focus=${this.#f}
50
+ @loadedmetadata=${this.#h}
51
+ @timeupdate=${this.#g}
51
52
  ></video>
52
53
  <div
53
54
  class=${`media-lightbox-short-controls${o?` media-lightbox-short-controls-portrait`:``}`}
@@ -61,12 +62,12 @@ var e=null,t=0,n=!1,r=null,i=null,a=0;function o(e){return!isFinite(e)||e<0?`0:0
61
62
  .value=${String(l)}
62
63
  style=${`--media-progress:${u}%`}
63
64
  aria-label="Video progress"
64
- @input=${this.#m}
65
+ @input=${this.#_}
65
66
  />
66
67
  <button
67
68
  type="button"
68
69
  class="media-lightbox-short-mute"
69
- @click=${this.#h}
70
+ @click=${this.#v}
70
71
  aria-label=${this._videoMuted?`Unmute video`:`Mute video`}
71
72
  >
72
73
  <svg
@@ -94,6 +95,7 @@ var e=null,t=0,n=!1,r=null,i=null,a=0;function o(e){return!isFinite(e)||e<0?`0:0
94
95
  controls
95
96
  autoplay
96
97
  playsinline
98
+ @focus=${this.#f}
97
99
  ></video>`:K`<img
98
100
  class=${`media-lightbox-img${i?` media-lightbox-img-scroll`:``}`}
99
101
  src=${e?.url??``}
@@ -130,6 +130,46 @@
130
130
  --site-padding: 1.5rem;
131
131
  --content-gap: 1rem;
132
132
  --space-xl: 2rem;
133
+ --space-2xl: 4rem;
134
+ /*
135
+ * Home timeline vertical rhythm — the single source of truth for the gaps
136
+ * between stacked sections on the home page:
137
+ *
138
+ * site description → separator → first post → divider → post → ...
139
+ *
140
+ * where "separator" is the description hairline (logged out) or the compose
141
+ * prompt (logged in). Every one of those gaps derives from this token, and
142
+ * the individual pieces (compose prompt, description hairline, post cards)
143
+ * carry no rhythm margin of their own — the structural wrappers
144
+ * (.site-home-header, hr.feed-divider) own the spacing. Retune the whole
145
+ * feed cadence by changing this one value.
146
+ *
147
+ * Note: per-format card padding (.feed-quote-post, thread previews) is the
148
+ * card's own internal spacing and is intentionally NOT part of this rhythm.
149
+ *
150
+ * Kept as a free-standing value (not pinned to the --space-* scale) so the
151
+ * feed cadence can be tuned independently.
152
+ */
153
+ --site-feed-rhythm: 4.4rem;
154
+ /*
155
+ * The post footer's action row (reply / menu buttons) is a taller tap
156
+ * target than its visible content, leaving a few px of dead space below
157
+ * the last visible element of every post (~5.9px logged out from the
158
+ * footer min-height, ~6.8px logged in from the menu button). hr.feed-divider
159
+ * subtracts this from its top margin so the VISIBLE gap between posts equals
160
+ * --site-feed-rhythm — the same as the header spacing. Re-measure if the
161
+ * footer button size or meta font changes.
162
+ */
163
+ --post-footer-overshoot: 6px;
164
+ /*
165
+ * The site intro (description) block is deliberately tighter than
166
+ * --site-feed-rhythm so it reads as a compact header unit rather than a
167
+ * full feed section. -top: gap from the header nav down to the intro.
168
+ * -bottom: gap from the intro down to its separator — the hairline (logged
169
+ * out) or the compose prompt text (logged in). Same values in both states.
170
+ */
171
+ --site-intro-gap-top: 24px;
172
+ --site-intro-gap-bottom: 36px;
133
173
 
134
174
  /* Sidebar layout (admin + site sidebar pages) */
135
175
  --sidebar-width: 12rem;
package/src/styles/ui.css CHANGED
@@ -954,11 +954,15 @@
954
954
 
955
955
  /* --- Home header wrapper (compose-prompt + browse-nav) ------------------ */
956
956
 
957
+ /* Owns both the gap between the site description and its separator
958
+ (hairline / compose prompt) and the gap from that separator down to the
959
+ first post. Both use --site-feed-rhythm so the home page keeps one
960
+ uniform cadence regardless of how the site intro is customized. */
957
961
  .site-home-header {
958
962
  display: flex;
959
963
  flex-direction: column;
960
- gap: 2rem;
961
- margin-bottom: var(--space-xl);
964
+ gap: var(--site-feed-rhythm);
965
+ margin-bottom: var(--site-feed-rhythm);
962
966
  }
963
967
 
964
968
  .site-description :where(p) {
@@ -2099,7 +2103,12 @@
2099
2103
  border: none;
2100
2104
  width: 30px;
2101
2105
  height: 9px;
2102
- margin: 4rem 0;
2106
+ /* Inter-post gap. The top margin subtracts --post-footer-overshoot so the
2107
+ VISIBLE gap (last footer content → divider) equals --site-feed-rhythm,
2108
+ matching the header spacing; the bottom margin is the full rhythm since
2109
+ the next post has no leading dead space. */
2110
+ margin: calc(var(--site-feed-rhythm) - var(--post-footer-overshoot)) 0
2111
+ var(--site-feed-rhythm);
2103
2112
  /* Center over the post-body column. On desktop the body column is
2104
2113
  `var(--layout-content-width)` (55%). Between 760-1024px it switches
2105
2114
  to `min(100%, 35rem)` via preset.css, so the hr must track that
@@ -2717,8 +2726,9 @@
2717
2726
  }
2718
2727
 
2719
2728
  .feed-quote-post {
2729
+ /* No vertical padding: like every other feed card, the quote article hugs
2730
+ its content so the inter-post gap stays on --site-feed-rhythm. */
2720
2731
  position: relative;
2721
- padding: 0.45rem 0 0.35rem;
2722
2732
  }
2723
2733
 
2724
2734
  .feed-quote-post .post-status-badges {
@@ -3944,16 +3954,31 @@
3944
3954
  * ========================================================================= */
3945
3955
 
3946
3956
  .compose-prompt {
3957
+ /* Vertical click-target padding on the inner trigger button. Tokenized
3958
+ so the rhythm compensation below stays in sync if it changes. */
3959
+ --compose-trigger-pad: 24px;
3947
3960
  position: relative;
3948
3961
  display: flex;
3949
3962
  align-items: center;
3950
3963
  gap: 12px;
3951
3964
  padding: 0;
3952
- margin-bottom: 10px;
3965
+ /* No rhythm margin — .site-home-header owns the gap below this. */
3953
3966
  border-bottom: 0.5px solid oklch(from var(--site-divider) l c h / 0.5);
3954
3967
  transition: border-color 0.15s;
3955
3968
  }
3956
3969
 
3970
+ /* When a site description sits above the prompt, pull the prompt up so the
3971
+ trigger text lands --site-intro-gap-bottom below the description. The
3972
+ negative margin cancels both the home rhythm gap (--site-feed-rhythm)
3973
+ inherited from .site-home-header and the trigger's own top click-target
3974
+ padding. */
3975
+ .site-description + .compose-prompt {
3976
+ margin-top: calc(
3977
+ var(--site-intro-gap-bottom) - var(--site-feed-rhythm) -
3978
+ var(--compose-trigger-pad)
3979
+ );
3980
+ }
3981
+
3957
3982
  .compose-prompt:hover {
3958
3983
  border-bottom-color: var(--site-divider);
3959
3984
  }
@@ -3966,7 +3991,7 @@
3966
3991
  min-width: 0;
3967
3992
  width: 100%;
3968
3993
  min-height: 64px;
3969
- padding: 24px 0;
3994
+ padding: var(--compose-trigger-pad) 0;
3970
3995
  border: none;
3971
3996
  outline: none;
3972
3997
  background: none;
@@ -5756,6 +5781,7 @@
5756
5781
  .compose-quick-actions-row {
5757
5782
  display: flex;
5758
5783
  justify-content: flex-end;
5784
+ gap: 0.5rem;
5759
5785
  padding: 2px 12px 12px;
5760
5786
  background-color: var(--compose-paper-bg);
5761
5787
  border-bottom-left-radius: inherit;
@@ -11496,7 +11522,7 @@
11496
11522
  * ------------------------------------------------------------------------- */
11497
11523
 
11498
11524
  .site-description {
11499
- margin-top: 2.5rem;
11525
+ margin-top: var(--site-intro-gap-top);
11500
11526
  font-family: var(--font-serif);
11501
11527
  font-size: var(--type-body);
11502
11528
  line-height: 1.55;
@@ -11518,6 +11544,16 @@
11518
11544
  margin: 0;
11519
11545
  }
11520
11546
 
11547
+ /*
11548
+ * Tighten the intro → hairline gap to --site-intro-gap-bottom, mirroring the
11549
+ * logged-in .site-description + .compose-prompt rule. The negative margin
11550
+ * cancels the home rhythm gap (--site-feed-rhythm) inherited from
11551
+ * .site-home-header down to the intended intro spacing.
11552
+ */
11553
+ .site-description + .site-description-divider {
11554
+ margin-top: calc(var(--site-intro-gap-bottom) - var(--site-feed-rhythm));
11555
+ }
11556
+
11521
11557
  /*
11522
11558
  * Collection descriptions (directory cards + collection detail header).
11523
11559
  * Same cascade fix as .site-description: layered color rules lose to the
@@ -1,6 +0,0 @@
1
- import "./url-umUptr5z.js";
2
- import { t as createApp } from "./app-CPVwpmb3.js";
3
- import "./export-I9XFTWyO.js";
4
- import "./env-CgaH9Mut.js";
5
- import "./github-sync-DBAwA3H9.js";
6
- export { createApp };