/* The components the site and the dashboard share: icons, buttons, chips, menus and popovers, sheets, toasts,
   tabs, the modal, the empty state, tags, and their motion. Both layouts load it after tokens.css and before their own
   stylesheet (site.css, the dashboard's admin.css), so a fix here shows on both. Every colour is a --ld-* token. */

/* Icons (icons.json, Twig's icon() and the Icon component) */
svg.i { width: 20px; height: 20px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; }
svg.i-16 { width: 16px; height: 16px; }
svg.i-24 { width: 24px; height: 24px; }
svg.i-32 { width: 32px; height: 32px; }
svg.i-14 { width: 14px; height: 14px; }
svg.i-18 { width: 18px; height: 18px; }

/* Buttons */
.btn { position: relative; display: inline-flex; align-items: center; justify-content: center; gap: 8px; height: 40px; padding: 0 16px; border-radius: var(--ld-radius-md); border: 1px solid transparent; font: 600 13px/16px var(--font-sans); cursor: pointer; white-space: nowrap; transition: transform var(--ld-ease), background-color var(--ld-ease), box-shadow var(--ld-ease), border-color var(--ld-ease), color var(--ld-ease); }
.btn:hover { transform: translateY(-1px); }
.btn:active, .btn.is-pressed { transform: scale(.97); }
.btn:hover .arrow { transform: translateX(3px); }
.btn-lg { height: 48px; padding: 0 20px; font: 700 15px/20px var(--font-sans); }
.btn-sm { height: 32px; padding: 0 12px; }
.btn-primary { background: var(--ld-green); color: var(--ld-on-green); }
.btn-primary:hover, .btn-primary.is-hover { background: var(--ld-green-hover); color: var(--ld-on-green); box-shadow: var(--ld-shadow-cta); }
.btn-secondary { background: var(--ld-surface-4); border-color: var(--ld-line-strong); color: var(--ld-text); }
.btn-secondary:hover, .btn-secondary.is-hover { border-color: rgba(255,255,255,.28); color: var(--ld-text-strong); }
.btn-ghost { background: transparent; color: var(--ld-text); }
.btn-ghost:hover, .btn-ghost.is-hover { background: var(--ld-fill-hover); }
.btn-danger { background: transparent; border-color: rgba(255,138,156,.5); color: var(--ld-danger); }
.btn-danger:hover, .btn-danger.is-hover { background: rgba(255,138,156,.08); }
.btn.is-hover { transform: translateY(-1px); }
.btn.is-focus { outline: 2px solid var(--ld-green); outline-offset: 2px; }
.btn-block { width: 100%; }
.btn-icon { width: 40px; padding: 0; }
.spinner { width: 16px; height: 16px; border-radius: 50%; border: 2px solid currentColor; border-right-color: transparent; animation: ld-spin .7s linear infinite; }
a[data-load-more] .spinner { width: 14px; height: 14px; }
.btn.is-success { background: var(--ld-green-surface); border-color: var(--ld-green-line); color: var(--ld-green); animation: ld-flash .6s ease-out; }
.btn.is-error { animation: ld-shake .3s ease-in-out; }
.btn-error-line { margin-top: 6px; color: var(--ld-danger); font: 400 12px/16px var(--font-sans); animation: ld-fade .25s ease-out both; }
.btn-danger-solid { background: var(--ld-danger); color: #2b0910; }
.btn-danger-solid:hover, .btn-danger-solid.is-hover { background: #ffa3b1; box-shadow: 0 8px 24px rgba(255,138,156,.22); }
@media (max-width: 760px) {
  .btn { min-height: 48px; }
  .btn-sm { min-height: 32px; }
}

/* Chips */
.chip { display: inline-flex; align-items: center; gap: 6px; height: 24px; padding: 0 10px; border-radius: var(--ld-radius-full); background: var(--ld-surface-4); border: 1px solid var(--ld-line); color: var(--ld-text-secondary); font: 600 12px/16px var(--font-sans); white-space: nowrap; }
.chip-tier { background: color-mix(in srgb, var(--tier) 16%, transparent); border-color: color-mix(in srgb, var(--tier) 55%, transparent); color: var(--ld-text-strong); }
.chip-warning { background: rgba(251,176,31,.1); border-color: rgba(251,176,31,.45); color: var(--ld-warning); }
.chip-green { background: var(--ld-green-surface); border-color: var(--ld-green-line); color: var(--ld-green); }
.chip-danger { background: rgba(255,138,156,.1); border-color: rgba(255,138,156,.45); color: var(--ld-danger); }
.chip img { width: 16px; height: 16px; }

/* Popovers, menus, sheets */
.pop { background: var(--ld-surface-2); border: 1px solid var(--ld-line-strong); border-radius: var(--ld-radius-lg); box-shadow: var(--ld-shadow-pop); animation: ld-pop-in var(--ld-ease-enter) both; transform-origin: top right; }
.menu-item { display: flex; align-items: center; gap: 12px; height: 40px; padding: 0 12px; border-radius: var(--ld-radius-md); color: var(--ld-text); font: 600 13px/16px var(--font-sans); }
.menu-item:hover { background: var(--ld-fill-hover); color: var(--ld-text-strong); }
.menu-item svg { color: var(--ld-text-muted); }
.menu-item:hover svg { color: var(--ld-green); }
.sheet { background: var(--ld-surface-2); border: 1px solid var(--ld-line-strong); border-bottom: 0; border-radius: 20px 20px 0 0; box-shadow: var(--ld-shadow-modal); animation: ld-sheet-in var(--ld-ease-enter) both; }
.handle { width: 40px; height: 4px; border-radius: 2px; background: var(--ld-line-strong); margin: 10px auto 6px; }
.scrim { background: var(--ld-scrim); animation: ld-fade var(--ld-ease-enter) both; }
.menu-sep { height: 1px; background: var(--ld-line); margin: 6px 4px; }
button.menu-item, form > button.menu-item { width: 100%; border: 0; background: none; cursor: pointer; text-align: left; }
.pop.is-closing { animation: ld-pop-out 160ms ease-in both; }
.sheet.is-closing { animation: ld-sheet-out 220ms ease-in both; }
.scrim.is-closing { animation: ld-fade-out 220ms ease-in both; }

/* Toast */
.toast { position: relative; overflow: hidden; display: flex; align-items: center; gap: 12px; width: 360px; max-width: 100%; padding: 14px 16px; border-radius: var(--ld-radius-md); background: var(--ld-surface-3); border: 1px solid var(--ld-line-strong); box-shadow: var(--ld-shadow-pop); animation: ld-toast-in var(--ld-ease-enter) both; }
.toast .bar { position: absolute; left: 0; bottom: 0; height: 2px; width: 100%; background: var(--ld-green); transform-origin: left; animation: ld-shrink 5s linear infinite; }
.toast.warn .bar { background: var(--ld-warning); }
/* Toasts: bottom right on desktop, above the selection bar on phones */
.toasts { position: fixed; right: 24px; bottom: 24px; z-index: 60; display: flex; flex-direction: column; gap: 8px; align-items: flex-end; pointer-events: none; }
/* As a popover (above modal dialogs): none of the browser's own popover box. */
.toasts:where([popover]) { top: auto; left: auto; width: auto; height: auto; margin: 0; padding: 0; border: 0; background: none; color: inherit; overflow: visible; }
.toasts.has-bar { bottom: 88px; }
.toasts .toast { pointer-events: auto; animation: ld-toast-in var(--ld-ease-enter) both; box-shadow: var(--ld-shadow-modal); }
.toasts .toast.is-closing { animation: ld-toast-out 200ms ease-in both; }
.toast .bar { animation-iteration-count: 1; }
.toast .act { margin-left: auto; background: none; border: 0; color: var(--ld-green); font: 700 13px/16px var(--font-sans); cursor: pointer; padding: 4px 6px; border-radius: var(--ld-radius-sm); }
.toast .act:hover { background: var(--ld-fill-hover); }
@media (max-width: 760px) {
  .toasts { left: 16px; right: 16px; bottom: 16px; align-items: stretch; }
  .toasts.has-bar { bottom: 84px; }
  .toasts .toast { width: auto; }
}
.toast.is-bad { border-color: rgba(255,138,156,.4); }
.toast.is-bad .bar { background: var(--ld-danger); }
.toast .bar.bar-long { animation-duration: 8s; }
.toast .t-label { font: 600 13px/16px var(--font-sans); }
.toast .t-detail { display: block; margin-top: 2px; font: 400 12px/16px var(--font-sans); color: var(--ld-text-secondary); }
.toast .t-left { flex: none; font: 600 12px/16px var(--font-sans); color: var(--ld-text-dim); font-variant-numeric: tabular-nums; }

/* Tabs with a sliding underline */
.tab { position: relative; display: inline-flex; align-items: center; gap: 8px; height: 52px; padding: 0 14px; color: var(--ld-text-muted); font: 600 14px/20px var(--font-sans); white-space: nowrap; transition: color var(--ld-ease); }
.tab:hover { color: var(--ld-text-strong); }
.tab .count { font: 600 12px/16px var(--font-sans); color: var(--ld-text-dim); font-variant-numeric: tabular-nums; }
.tab[aria-current="page"] { color: var(--ld-text-strong); }
.tab[aria-current="page"] .count { color: var(--ld-green); }
.tab::after { content: ""; position: absolute; left: 14px; right: 14px; bottom: -1px; height: 2px; border-radius: 2px; background: var(--ld-green); transform: scaleX(0); transition: transform var(--ld-ease-enter); }
.tab[aria-current="page"]::after { transform: scaleX(1); animation: ld-tab-in var(--ld-ease-enter) both; }
@keyframes ld-tab-in { from { transform: scaleX(0); } to { transform: scaleX(1); } }

/* Modal */
.modal-scrim { position: fixed; inset: 0; z-index: 50; background: var(--ld-scrim); display: flex; align-items: center; justify-content: center; padding: 16px; animation: ld-fade var(--ld-ease-enter) both; }
.modal { width: 640px; max-width: 100%; background: var(--ld-surface-2); border: 1px solid var(--ld-line-strong); border-radius: var(--ld-radius-xl); box-shadow: var(--ld-shadow-modal); padding: 24px; display: flex; flex-direction: column; gap: 16px; animation: ld-pop-in var(--ld-ease-enter) both; transform-origin: center; }
.modal-scrim.is-closing { animation: ld-fade-out 200ms ease-in both; }
.modal-scrim.is-closing .modal { animation: ld-pop-out 200ms ease-in both; }

/* Dialogs are <dialog> elements styled as the design system's modal; the browser keeps focus inside and Esc closes them */
dialog.modal { position: fixed; inset: 0; margin: auto; max-height: calc(100vh - 32px); overflow: auto; color: var(--ld-text); }
dialog.modal::backdrop { background: var(--ld-scrim); animation: ld-fade var(--ld-ease-enter) both; }
dialog.modal[open] { animation: ld-pop-in var(--ld-ease-enter) both; }
dialog.modal.is-closing { animation: ld-pop-out 200ms ease-in both; }
dialog.modal.is-closing::backdrop { animation: ld-fade-out 200ms ease-in both; }
@media (max-width: 599px) {
  dialog.modal { margin: auto 0 0; width: 100% !important; max-width: none; max-height: 88vh; border-radius: 20px 20px 0 0; }
  dialog.modal[open] { animation: ld-sheet-in var(--ld-ease-enter) both; }
  dialog.modal.is-closing { animation: ld-sheet-out 220ms ease-in both; }
}

/* Empty state */
.empty { display: flex; flex-direction: column; align-items: center; gap: 12px; padding: 64px 16px; text-align: center; }
.empty-art { width: 56px !important; height: 56px !important; color: var(--ld-green); animation: ld-aperture 6s ease-in-out infinite; }

/* While a dialog or a sheet is open the page behind it stays still; only what is open scrolls. The gutter keeps the
   page from shifting sideways when its scroll bar goes. */
html:has(dialog:modal), html:has(.ld-sheet) { overflow: hidden; scrollbar-gutter: stable; }
dialog:modal, .ld-sheet-body { overscroll-behavior: contain; }

/* The phone bottom sheet (ui/sheet.tsx). It moves by height, so menus inside it stay where they open. */
.ld-sheet { position: fixed; inset: 0; z-index: 75; }
.ld-sheet-scrim { position: absolute; inset: 0; background: rgba(0, 0, 0, .35); animation: ld-fade var(--ld-ease-enter) both; }
.ld-sheet-panel { position: absolute; left: 0; right: 0; display: flex; flex-direction: column; background: var(--ld-surface-2); border-radius: 16px 16px 0 0; box-shadow: 0 -12px 40px rgba(0, 0, 0, .45); transition: height 240ms cubic-bezier(.22, .8, .26, 1), bottom 120ms ease; animation: ld-sheet-in 240ms cubic-bezier(.22, .8, .26, 1) backwards; overflow: hidden; }
.ld-sheet-panel.is-full { border-radius: 0; }
.ld-sheet-panel.is-fit { height: auto; padding-bottom: env(safe-area-inset-bottom); }
.ld-sheet-panel.is-dragging { transition: none; }
.ld-sheet.is-closing .ld-sheet-panel { animation: ld-sheet-out 200ms ease-in both; }
.ld-sheet.is-closing .ld-sheet-scrim { animation: ld-fade-out 200ms ease-in both; }
.ld-sheet-grab { flex: none; display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 10px 16px 12px; border-bottom: 1px solid var(--ld-line); touch-action: none; cursor: grab; user-select: none; }
.ld-sheet-handle { width: 36px; height: 4px; border-radius: 2px; background: var(--ld-line-strong); }
.ld-sheet-title { text-align: center; }
.ld-sheet-body { flex: 1; min-height: 0; display: flex; flex-direction: column; }
@media (prefers-reduced-motion: reduce) { .ld-sheet-panel, .ld-sheet-scrim, .ld-sheet.is-closing .ld-sheet-panel, .ld-sheet.is-closing .ld-sheet-scrim { transition: none; animation: none; } }

/* Tags as "#tag" text (partials/site/tags.html.twig, ui/tags.tsx), on the site and in the dashboard: links that fold
   past two lines, the filter row's toggles, and the tag field with its list. Pills are for chips that aren't tags. */
.ld-tg { display: flex; flex-wrap: wrap; gap: 2px 10px; margin: 0; font: 500 14px/22px var(--font-sans); }
.ld-tag { color: var(--ld-green); font-weight: 500; text-decoration: none; border-radius: 4px; overflow-wrap: anywhere; }
a.ld-tag:hover { color: var(--ld-green); text-decoration: underline; text-underline-offset: 3px; }
a.ld-tag:focus-visible, .ld-tg-more:focus-visible { outline: 2px solid var(--ld-green); outline-offset: 2px; }
.ld-tg-more { position: relative; padding: 0; border: 0; background: none; color: var(--ld-text-muted); font: 500 14px/22px var(--font-sans); cursor: pointer; }
.ld-tg-more:hover { color: var(--ld-text-strong); }
.ld-tg-more::after { content: ""; position: absolute; inset: -11px -6px; }
.ld-tf { display: flex; flex-wrap: wrap; align-items: center; gap: 0 14px; min-width: 0; padding: 0 2px; }
.ld-tf-t { position: relative; flex: none; display: inline-flex; align-items: center; gap: 4px; min-height: 44px; padding: 0 2px; color: var(--ld-text-secondary); font: 500 14px/20px var(--font-sans); white-space: nowrap; text-decoration: none; transition: color 150ms ease-out; }
.ld-tf-t:hover { color: var(--ld-text-strong); }
.ld-tf-t .n { margin-left: 2px; font: 500 12px/16px var(--font-sans); color: var(--ld-text-dim); font-variant-numeric: tabular-nums; }
.ld-tf-t.is-on, .ld-tf-t.is-on:hover { color: var(--ld-green); font-weight: 600; }
.ld-tf-t:focus-visible, .ld-tf-clear:focus-visible { outline: 2px solid var(--ld-green); outline-offset: 2px; border-radius: 4px; }
.ld-tf-clear { flex: none; display: inline-flex; align-items: center; min-height: 44px; padding: 0 4px; color: var(--ld-text-muted); font: 600 13px/16px var(--font-sans); text-decoration: underline; text-underline-offset: 3px; animation: ld-fade 150ms ease-out both; }
.ld-tf-clear:hover { color: var(--ld-text-strong); }
.ld-ti { position: relative; display: flex; flex-wrap: wrap; align-items: center; gap: 2px 10px; min-height: 48px; box-sizing: border-box; padding: 4px 12px; border: 1px solid var(--ld-line-strong); border-radius: var(--ld-radius-md); background: var(--ld-surface-3); transition: border-color 150ms ease-out, box-shadow 150ms ease-out; }
.ld-ti:focus-within { border-color: var(--ld-green); box-shadow: var(--ld-focus-ring); }
.ld-ti.is-off { opacity: .55; }
.ld-ti-k { display: inline-flex; align-items: center; gap: 2px; min-width: 0; font: 500 14px/20px var(--font-sans); color: var(--ld-text-strong); overflow-wrap: anywhere; animation: ld-fade 150ms ease-out both; }
.ld-ti-k button { position: relative; flex: none; width: 20px; height: 20px; padding: 0; border: 0; border-radius: 50%; background: none; color: var(--ld-text-muted); display: inline-flex; align-items: center; justify-content: center; cursor: pointer; }
.ld-ti-k button::after { content: ""; position: absolute; inset: -12px -8px; }
.ld-ti-k button:hover { color: var(--ld-text-strong); }
.ld-ti-k button:focus-visible { outline: 2px solid var(--ld-green); outline-offset: 1px; }
.ld-ti-k button:disabled { cursor: default; }
.ld-ti-box { position: relative; flex: 1 1 90px; min-width: 90px; display: flex; }
/* Above .fld's input rules, which the field sits inside */
.ld-ti .ld-ti-box input, .ld-ti .ld-ti-box input:focus { position: relative; z-index: 1; width: 100%; height: 38px; padding: 0; border: 0; border-radius: 0; outline: none; box-shadow: none; background: transparent; color: var(--ld-text); font: 400 15px/20px var(--font-sans); transition: none; }
.ld-ti-ghost { position: absolute; inset: 0; display: flex; align-items: center; color: var(--ld-text-dim); font: 400 15px/20px var(--font-sans); white-space: pre; pointer-events: none; }
.ld-ti-ghost span { color: transparent; }
.ld-pick-row { cursor: pointer; flex: none; height: auto; min-height: 40px; }
.ld-pick-row.is-active { background: var(--ld-fill-hover); color: var(--ld-text-strong); }
.ld-pick-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; }
.ld-pick-label b { color: var(--ld-green); font-weight: 700; }
.ld-ti-pick { position: absolute; z-index: 40; left: 0; right: 0; top: calc(100% + 6px); max-height: 260px; overflow-y: auto; padding: 6px; transform-origin: top center; }
.ld-ti-pick .ld-pick-group { display: flex; align-items: center; justify-content: space-between; }
.ld-ti-forget { font-size: 12px; }
@media (prefers-reduced-motion: reduce) { .ld-tf-t, .ld-ti { transition: none; } .ld-tf-clear, .ld-ti-k { animation: none; } }

/* Site banners under the header (partials/site/banners.html.twig), also drawn by the dashboard's "View as" */
.ld-banners { display: flex; flex-direction: column; border-bottom: 1px solid var(--ld-line); }
.ld-banner { display: flex; align-items: flex-start; gap: 12px; padding: 12px 16px; border-bottom: 1px solid var(--ld-line); background: var(--ld-surface-3); color: var(--ld-text); font: 400 14px/20px var(--font-sans); }
.ld-banners > .ld-banner:last-child, .ld-banners-more .ld-banner:last-child { border-bottom: 0; }
.ld-banner > .i { margin-top: 1px; color: var(--ld-text-muted); }
.ld-banner__t { flex: 1; min-width: 0; margin: 0; overflow-wrap: anywhere; }
.ld-banner__t a { margin-left: 2px; color: var(--ld-text-strong); font-weight: 600; text-decoration: underline; text-underline-offset: 3px; white-space: nowrap; }
.ld-banner__x { flex: none; display: grid; place-items: center; width: 44px; height: 44px; margin: -12px -12px -12px 0; padding: 0; border: 0; border-radius: var(--ld-radius-sm); background: none; color: var(--ld-text-muted); cursor: pointer; }
.ld-banner__x:hover { color: var(--ld-text-strong); background: var(--ld-fill-hover); }
.ld-banner__x:focus-visible { outline: 2px solid var(--ld-green); outline-offset: -2px; }
.ld-banner--critical { background: color-mix(in srgb, var(--ld-warning) 9%, var(--ld-surface-3)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ld-warning) 60%, transparent); }
.ld-banner--critical > .i { color: var(--ld-warning); }
.ld-banner--pinned > .i { color: var(--ld-info); }
.ld-banners-more { background: var(--ld-surface-2); border-bottom: 1px solid var(--ld-line); }
.ld-banners > .ld-banners-more:last-child { border-bottom: 0; }
.ld-banners-more > summary { display: flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 16px; list-style: none; cursor: pointer; color: var(--ld-text-secondary); font: 600 13px/18px var(--font-sans); }
.ld-banners-more > summary::-webkit-details-marker { display: none; }
.ld-banners-more > summary:focus-visible { outline: 2px solid var(--ld-green); outline-offset: -2px; }
.ld-banners-more > summary .i { transition: transform 160ms ease; }
.ld-banners-more[open] > summary .i { transform: rotate(180deg); }
.ld-banners-more .ld-banner { border-top: 1px solid var(--ld-line); border-bottom: 0; }
.ld-banners .is-phone { display: none; }
@media (max-width: 760px) {
  .ld-banners .is-wide { display: none; }
  .ld-banners .ld-banner.is-phone { display: flex; }
  .ld-banners summary .is-phone { display: inline; }
  .ld-banners .ld-banners-more.is-phone { display: block; }
}
@media (prefers-reduced-motion: reduce) { .ld-banners-more > summary .i { transition: none; } }

/* Keyframes */
@keyframes ld-spin { to { transform: rotate(360deg); } }
@keyframes ld-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes ld-pop-in { from { opacity: 0; transform: scale(.96); } to { opacity: 1; transform: none; } }
@keyframes ld-sheet-in { from { transform: translateY(100%); } to { transform: none; } }
@keyframes ld-toast-in { from { opacity: 0; transform: translateX(24px); } to { opacity: 1; transform: none; } }
@keyframes ld-shrink { from { transform: scaleX(1); } to { transform: scaleX(0); } }
@keyframes ld-shake { 0%, 100% { transform: translateX(0); } 20%, 60% { transform: translateX(-6px); } 40%, 80% { transform: translateX(6px); } }
@keyframes ld-flash { 0% { box-shadow: 0 0 0 0 rgba(14,229,155,.55); } 100% { box-shadow: 0 0 0 12px rgba(14,229,155,0); } }
@keyframes ld-aperture { 0%, 100% { transform: rotate(0) scale(.86); } 50% { transform: rotate(30deg) scale(1); } }
@keyframes ld-fade-out { from { opacity: 1; } to { opacity: 0; } }
@keyframes ld-pop-out { from { opacity: 1; transform: none; } to { opacity: 0; transform: scale(.96) translateY(6px); } }
@keyframes ld-sheet-out { from { transform: none; } to { transform: translateY(100%); } }
@keyframes ld-toast-out { from { opacity: 1; transform: none; } to { opacity: 0; transform: translateX(24px); } }

/* Skeletons: grey shapes where content is coming, with a slow shine. */
.ld-skel { display: block; border-radius: 6px; background: linear-gradient(110deg, var(--ld-surface-2) 30%, var(--ld-surface-3) 50%, var(--ld-surface-2) 70%) 0 0 / 300% 100%; animation: ld-skel 1.4s linear infinite; }
@keyframes ld-skel { from { background-position: 150% 0; } to { background-position: -50% 0; } }
@media (prefers-reduced-motion: reduce) { .ld-skel { animation: none; } }
.ld-skel-avatar { width: 32px; height: 32px; border-radius: 50%; flex: none; }
.ld-skel-line { height: 12px; }
/* A feed card's skeleton is drawn by its stylesheet alone: the name line over the picture, the caption under it. So is
   a tile in an album grid, as an album card: the 4:3 cover, the name under it. */
.ld-skel-feed { list-style: none; padding: 16px; display: flex; flex-direction: column; gap: 14px; }
.ld-skel-feed::before, .ld-skel-feed::after, .grid-albums > .ld-skel-tile::before, .grid-albums > .ld-skel-tile::after { content: ''; display: block; border-radius: 6px; background: linear-gradient(110deg, var(--ld-surface-2) 30%, var(--ld-surface-3) 50%, var(--ld-surface-2) 70%) 0 0 / 300% 100%; animation: ld-skel 1.4s linear infinite; }
.ld-skel-feed::before { width: 45%; height: 32px; }
.ld-skel-feed::after { aspect-ratio: 4 / 5; }
@media (prefers-reduced-motion: reduce) { .ld-skel-feed::before, .ld-skel-feed::after, .grid-albums > .ld-skel-tile::before, .grid-albums > .ld-skel-tile::after { animation: none; } }
.ld-skel-tile { list-style: none; aspect-ratio: 1; border-radius: var(--ld-radius-md); }
.grid-albums > .ld-skel-tile { aspect-ratio: auto; background: none; animation: none; display: flex; flex-direction: column; gap: 12px; }
.grid-albums > .ld-skel-tile::before { aspect-ratio: 4 / 3; border-radius: var(--ld-radius-md); }
.grid-albums > .ld-skel-tile::after { width: 60%; height: 16px; }
