/* Skeleton loading, website and admin dashboard. Instead of spinners and loading bars, anything still loading is
   shown as soft grey shimmering shapes in its own layout, like an app:
   1. the shimmer   2. photos   3. search results   4. the next page (page-loader.js)   5. dashboard pages
   6. the booking calendar   7. buttons that are working (no spinning icons anywhere)
   Neutral see-through colours, so it works on both light pages and dark sections. */

/* 1. The shimmer */
.sk-img, .sk-line, .sk-dot, .sk-block {
    background: linear-gradient(100deg, rgba(148, 163, 184, .14) 30%, rgba(148, 163, 184, .34) 50%, rgba(148, 163, 184, .14) 70%) 0 0 / 220% 100% !important;
    animation: skShimmer 1.25s linear infinite;
}
@keyframes skShimmer { from { background-position: 110% 0; } to { background-position: -110% 0; } }
.sk-line, .sk-dot { display: block; border-radius: 999px; }
.sk-block { display: block; border-radius: 18px; }

/* 2. Photos: main.js adds .sk-img to a photo until it has loaded; the photo paints over its own shimmer */

/* 3. Search results (navbar search, search page, dashboard search) */
.ss-sk { display: flex; align-items: center; gap: .85rem; padding: .7rem .85rem; }
.ss-sk .sk-dot { flex: none; width: 38px; height: 38px; border-radius: 12px; }
.ss-sk > span:last-child { flex: 1; display: grid; gap: .45rem; }
.ss-sk .sk-line { height: 11px; }
.ss-sk .sk-line + .sk-line { width: 60%; height: 9px; }
.ss-spinner, .sp-spinner, .lsx-spinner { display: none !important; }
.lsx.is-loading .lsx-glass { opacity: 1 !important; }
/* 4. The next page: if a page takes a moment, the area under the navbar turns into the layout of the page being opened (post, list, contact, default); markup from page-loader.js */
.pl-skel { position: absolute; left: 0; right: 0; top: var(--nav-height, 76px); bottom: 0; overflow: hidden; background: #FAFAFE;
    opacity: 0; transition: opacity .25s; }
.page-loader.is-slow .pl-skel:not(:empty) { opacity: 1; }
.sk-block { display: block; border-radius: 18px; }
.sk-wrap { width: min(1200px, calc(100% - 32px)); margin: 0 auto; padding: clamp(2rem, 6vw, 4.5rem) 0 2rem; }
.sk-narrow { width: min(760px, calc(100% - 32px)); }
.sk-hero { display: grid; gap: .9rem; justify-items: start; max-width: 760px; }
.sk-center { justify-items: center; margin: 0 auto; text-align: center; }
.sk-chip { width: 150px; height: 28px; }
.sk-h1 { height: clamp(30px, 5vw, 52px); border-radius: 14px; }
.sk-h3 { height: 20px; width: 80%; }
.sk-p { height: 14px; }
.sk-card-body .sk-line, .sk-meta .sk-line { height: 12px; }
.sk-card-body .sk-h3 { height: 20px; }
.sk-btns { display: flex; gap: .75rem; margin-top: .6rem; }
.sk-btn { width: 160px; height: 48px; }
.sk-btn-2 { width: 130px; }
.sk-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr)); gap: 1.4rem; margin-top: clamp(2rem, 5vw, 3.5rem); }
.sk-card { border-radius: 22px; overflow: hidden; background: #fff; box-shadow: 0 12px 30px -20px rgba(15, 23, 42, .25), 0 0 0 1px rgba(15, 23, 42, .05); }
.sk-media { aspect-ratio: 16 / 10; border-radius: 0; }
.sk-card-body { display: grid; gap: .7rem; padding: 1.2rem 1.3rem 1.5rem; }
.sk-meta { display: flex; align-items: center; gap: .75rem; margin: .4rem 0 .6rem; }
.sk-avatar { width: 40px; height: 40px; border-radius: 50%; flex: none; }
.sk-cover { aspect-ratio: 16 / 9; margin: .6rem 0 1.6rem; border-radius: 22px; }
.sk-narrow > .sk-p { margin-bottom: .85rem; }
.sk-narrow > .sk-h1 { margin: .9rem 0 .2rem; }
.sk-split { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(1.5rem, 5vw, 4rem); align-items: start; }
.sk-form { display: grid; gap: .65rem; padding: 1.6rem; border-radius: 24px; background: #fff; box-shadow: 0 12px 30px -20px rgba(15, 23, 42, .25), 0 0 0 1px rgba(15, 23, 42, .05); }
.sk-label { width: 110px; height: 11px; margin-top: .4rem; }
.sk-field { height: 50px; border-radius: 14px; }
.sk-area { height: 120px; }
.sk-form .sk-btn { width: 100%; margin-top: .6rem; }
@media (max-width: 860px) {
    .sk-split { grid-template-columns: 1fr; }
    .sk-btn { width: 130px; height: 44px; }
    .sk-grid .sk-card:nth-child(n+3) { display: none; }
}

/* 5. Admin dashboard: only the content area turns into a skeleton (sidebar and top bar stay) */
.dashboard-body .pl-skel { right: 0; background: #F6F7FB; }
.sk-dash { padding: 1.75rem; display: grid; gap: 1.4rem; }
.sk-dash-head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.sk-kpis { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 200px), 1fr)); gap: 1rem; }
.sk-kpi, .sk-table { border-radius: 16px; background: #fff; box-shadow: 0 0 0 1px rgba(15, 23, 42, .06), 0 10px 24px -20px rgba(15, 23, 42, .3); }
.sk-kpi { display: grid; gap: .7rem; padding: 1.2rem; }
.sk-kpi .sk-line { height: 11px; }
.sk-kpi .sk-h3 { height: 26px; }
.sk-table { padding: .4rem 1.2rem; }
.sk-row { display: flex; align-items: center; gap: 1rem; padding: .95rem 0; border-bottom: 1px solid rgba(15, 23, 42, .05); }
.sk-row:last-child { border-bottom: 0; }
.sk-row .sk-avatar { width: 34px; height: 34px; }
.sk-row .sk-line { height: 12px; }
.sk-row .sk-pill { width: 80px; height: 24px; margin-left: auto; }
.sk-row .sk-pill-2 { width: 60px; margin-left: 0; }
@media (max-width: 860px) { .sk-row .sk-pill-2 { display: none; } .sk-dash { padding: 1.1rem; } }

/* 6. Booking pop-up: a skeleton calendar while the available times load */
.bk-loading > span { display: none !important; }
.bk-sk { display: grid; gap: .9rem; width: min(560px, 92%); }
.bk-sk .sk-h3 { height: 22px; width: 55%; }
.bk-sk-days { display: grid; grid-template-columns: repeat(7, 1fr); gap: .5rem; }
.bk-sk-days .sk-block { aspect-ratio: 1; border-radius: 12px; }
.bk-sk-times { display: grid; grid-template-columns: repeat(3, 1fr); gap: .6rem; }
.bk-sk-times .sk-block { height: 42px; border-radius: 12px; }

/* 7. Buttons that are working: no spinning icons; the button itself shimmers and can't be pressed twice */
.fa-spinner, .fa-circle-notch, .fa-spin { display: none !important; }
button:has(.fa-spinner, .fa-circle-notch, .fa-spin), a:has(.fa-spinner, .fa-circle-notch, .fa-spin),
.contact-submit-btn.is-loading, button.is-loading, button.is-busy, .is-busy > button[type="submit"] {
    position: relative; overflow: hidden; pointer-events: none;
}
button:has(.fa-spinner, .fa-circle-notch, .fa-spin)::after, a:has(.fa-spinner, .fa-circle-notch, .fa-spin)::after,
.contact-submit-btn.is-loading::after, button.is-loading::after, button.is-busy::after {
    content: ''; position: absolute; inset: 0; pointer-events: none;
    background: linear-gradient(100deg, transparent 30%, rgba(255, 255, 255, .45) 50%, transparent 70%) 0 0 / 220% 100%;
    animation: skShimmer 1.1s linear infinite;
}

@media (prefers-reduced-motion: reduce) {
    .sk-img, .sk-line, .sk-dot, .sk-block, button::after, a::after { animation: none !important; }
}

/* Page loader container (also on the dashboard, which doesn't load rachyet.css) */
.page-loader { position: fixed; inset: 0; z-index: 4000; pointer-events: none; }
.pl-pressed { opacity: .65 !important; transform: scale(.98); transition: opacity .15s, transform .15s; }
.page-loader:not(.is-on) .pl-skel { display: none; }

/* 8. Page skeleton, Instagram style. While a page is still getting ready (fonts and the first photos), every
   section shows its OWN layout as skeletons: every piece of text becomes a bar (one bar per line in paragraphs and
   headings), buttons and fields become pills, photos and videos blocks, in their real places and on the section's
   real background. Then the content fades in. The inline script in <head> (base.html, dashboard/base.html) sets
   html.sk-boot, marks each element that holds text with .skt while the page is read, and removes sk-boot when
   ready. Only the page content (main / dashboard content) is affected; navbar, sidebar and footer stay. */
.sk-boot :is(main, .dashboard-content) :is(.skt, .btn, button, input, textarea, select, img, video, canvas, iframe) {
    color: transparent !important; -webkit-text-fill-color: transparent !important; text-shadow: none !important;
    /* one wave of light sweeps across the whole screen through every bar (the gradient is fixed to the screen, not to each bar) */
    background: linear-gradient(105deg, rgba(148, 163, 184, .17) 0%, rgba(148, 163, 184, .17) 38%, rgba(203, 213, 225, .55) 48%,
                rgba(255, 255, 255, .6) 50%, rgba(203, 213, 225, .55) 52%, rgba(148, 163, 184, .17) 62%, rgba(148, 163, 184, .17) 100%) !important;
    background-size: 250vw 100vh !important; background-attachment: fixed !important; background-repeat: no-repeat !important;
    -webkit-background-clip: border-box !important; background-clip: border-box !important;
    border-color: transparent !important; box-shadow: none !important; outline: 0 !important;
    animation: skWave 1.6s cubic-bezier(.45, .05, .55, .95) infinite !important; border-radius: 8px;
}
@keyframes skWave { from { background-position: 100vw 0; } to { background-position: -150vw 0; } }
/* the skeleton itself fades in softly instead of snapping on */
.sk-boot main { animation: skAppear .25s ease both; }
@keyframes skAppear { from { opacity: .6; } to { opacity: 1; } }
/* everything inside a skeleton block is hidden but keeps its size, so the block matches the real content */
.sk-boot :is(main, .dashboard-content) :is(.skt, .btn, button) * { visibility: hidden !important; }
/* paragraphs and headings: one bar per line, like Instagram */
.sk-boot :is(main, .dashboard-content) :is(h1, h2, h3, h4, h5, h6, p, li, dd, blockquote, figcaption).skt {
    -webkit-mask-image: repeating-linear-gradient(180deg, #000 0, #000 calc(1lh - .4em), transparent calc(1lh - .4em), transparent 1lh);
    mask-image: repeating-linear-gradient(180deg, #000 0, #000 calc(1lh - .4em), transparent calc(1lh - .4em), transparent 1lh);
    border-radius: 6px;
}
.sk-boot :is(main, .dashboard-content) :is(.btn, button, input, select) { border-radius: 999px; }
.sk-boot :is(main, .dashboard-content) img { object-position: -99999px 0 !important; }   /* hide the pixels, keep the block */
.sk-boot :is(main, .dashboard-content) svg { visibility: hidden !important; }
/* parts that normally fade or slide in (entrance animations, reveal on scroll) are shown as skeletons straight away */
/* (not parts that are meant to stay hidden, like the hero's waiting rotating words: aria-hidden) */
.sk-boot main :is(.skt, img, input, textarea, select, button, .btn):not([aria-hidden="true"]),
.sk-boot main :has(> .skt, > img, > input, > button, > .btn, .skt):not([aria-hidden="true"]) { opacity: 1 !important; visibility: visible; }
/* icons become soft round dots in their place */
.sk-boot :is(main, .dashboard-content) i[class*="fa-"] { color: transparent !important; -webkit-text-fill-color: transparent !important;
    background: rgba(148, 163, 184, .28) !important; border-radius: 50% !important; box-shadow: none !important; animation: skDot 1.6s ease-in-out infinite !important; }
@keyframes skDot { 50% { background-color: rgba(148, 163, 184, .45); } }
.sk-boot :is(main, .dashboard-content) :is(.skt, .btn, button) i[class*="fa-"] { visibility: hidden !important; }
/* decorative motion waits until the content is shown; the page doesn't jump around under the skeleton */
.sk-boot main :is(canvas, video) { opacity: 1 !important; }
/* content fades in when ready: page-wide in the dashboard; on the website the inline script fades in what's on screen */
.sk-in .dashboard-content { animation: skIn .45s ease both; }
@keyframes skIn { from { opacity: .35; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
    .sk-boot :is(main, .dashboard-content) * { animation: none !important; }
    .sk-in .dashboard-content { animation: none; }
}
