/* =============================================================
 * STRAFZA system.css
 * Ships with binaries. Non-removable, never theme-editable.
 * Owns structural primitives that public/admin views and the
 * media-helper rely on: placeholder fallback, screen-reader
 * utility, animation classes, reduced-motion + print rules,
 * and the lazy-image loader pattern.
 *
 * Defensive var() fallbacks throughout — if the active theme
 * is missing a token, the rule still produces a sensible visual.
 *
 * Phases that touch this file:
 *   5e-c1  — .media-placeholder, .sr-only
 *   5e-d-2 — .reveal / .stagger primitives, image-loader, motion + print
 *
 * Keep this file conservative. Theme aesthetics belong in site.css,
 * which loads after this and consumes tokens.
 * ============================================================= */

/* ---- Reset (minimal — site.css extends, never resets again) ---- */
*, *::before, *::after { box-sizing: border-box; }

/* ---- Screen-reader only ----------------------------------------- */
.sr-only {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    padding: 0 !important;
    margin: -1px !important;
    overflow: hidden !important;
    clip: rect(0, 0, 0, 0) !important;
    white-space: nowrap !important;
    border: 0 !important;
}

/* ---- Media placeholder ----------------------------------------- *
 * Rendered by Html.MediaImage(null, slotClass) when no asset is
 * bound, when the bound asset is soft-deleted, or when PublicUrl
 * is null. Fills its container; receives any extra slot class
 * (e.g. .card-image) so card-shaped slots get the right
 * aspect-ratio / radius / borders from site.css.
 *
 * Visual: subtle slate fill + accent left border + faint inner
 * grid + decorative camera glyph. Reads as "image goes here"
 * without being noisy.
 * ---------------------------------------------------------------- */
.media-placeholder {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    min-height: 120px;
    overflow: hidden;
    background-color: var(--color-surface-elevated, #ece7dc);
    background-image:
        linear-gradient(135deg,
            transparent 0%,
            transparent 49%,
            rgba(107, 91, 71, 0.06) 50%,
            transparent 51%,
            transparent 100%);
    border: 1px solid var(--color-line, rgba(107, 91, 71, 0.15));
    border-left: 3px solid var(--color-accent, #B58542);
    border-radius: var(--radius-sm, 4px);
}
[dir="rtl"] .media-placeholder {
    border-left: 1px solid var(--color-line, rgba(107, 91, 71, 0.15));
    border-right: 3px solid var(--color-accent, #B58542);
}
.media-placeholder::after {
    content: '';
    width: 32px;
    height: 24px;
    border: 2px solid var(--color-ink-muted, #6B5B47);
    border-radius: 2px;
    opacity: 0.35;
    background:
        radial-gradient(circle at 50% 50%,
            var(--color-ink-muted, #6B5B47) 0,
            var(--color-ink-muted, #6B5B47) 5px,
            transparent 6px),
        linear-gradient(180deg,
            transparent 0%,
            transparent 18%,
            var(--color-ink-muted, #6B5B47) 18%,
            var(--color-ink-muted, #6B5B47) 26%,
            transparent 26%);
    background-size: 100% 100%, 8px 4px;
    background-position: center, 4px 1px;
    background-repeat: no-repeat;
}
.media-placeholder[role="img"] { cursor: default; }

/* ---- Reveal animation primitives ------------------------------- *
 * theme.js scans .home-section descendants on DOMContentLoaded and
 * tags relevant elements with .reveal (and groups with .stagger).
 * These rules are the visual contract: opacity + small Y-translate,
 * then animated to their natural state when the element is observed
 * intersecting the viewport.
 *
 * Rules are written so a JS-disabled or reduced-motion environment
 * shows everything immediately — see the override block below.
 * ---------------------------------------------------------------- */
.reveal {
    opacity: 0;
    transform: translateY(24px);
    transition:
        opacity 0.7s cubic-bezier(0.16, 1, 0.3, 1),
        transform 0.7s cubic-bezier(0.16, 1, 0.3, 1);
    will-change: opacity, transform;
}
.reveal.visible {
    opacity: 1;
    transform: translateY(0);
}

.stagger > * {
    opacity: 0;
    transform: translateY(20px);
    transition:
        opacity 0.55s cubic-bezier(0.16, 1, 0.3, 1),
        transform 0.55s cubic-bezier(0.16, 1, 0.3, 1);
}
.stagger.visible > *:nth-child(1) { transition-delay: 0.05s; }
.stagger.visible > *:nth-child(2) { transition-delay: 0.12s; }
.stagger.visible > *:nth-child(3) { transition-delay: 0.19s; }
.stagger.visible > *:nth-child(4) { transition-delay: 0.26s; }
.stagger.visible > *:nth-child(5) { transition-delay: 0.33s; }
.stagger.visible > *:nth-child(6) { transition-delay: 0.40s; }
.stagger.visible > * {
    opacity: 1;
    transform: translateY(0);
}

/* ---- Lazy image loader (data-img-src pattern) ------------------ *
 * Optional progressive-enhancement path used by theme.js when a
 * future view wants client-side lazy loading without a server-side
 * <img>. The current public site renders <img> directly via
 * Html.MediaImage; this block exists so any view that opts into
 * data-img-src gets a clean fade-in.
 * ---------------------------------------------------------------- */
[data-img-src] {
    position: relative;
}
[data-img-src] > img {
    opacity: 0;
    transition: opacity 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}
[data-img-src].loaded > img { opacity: 1; }

/* ---- Reduced motion -------------------------------------------- *
 * Respect OS-level preference. Strips every non-essential
 * transition/animation across the site, including reveal/stagger
 * and any decorative motion. Critical for vestibular users.
 * ---------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
    .reveal,
    .stagger > * {
        opacity: 1 !important;
        transform: none !important;
        transition: none !important;
    }
    [data-img-src] > img { opacity: 1 !important; transition: none !important; }
}

/* ---- Print ----------------------------------------------------- *
 * Strip backgrounds, gradients, glow, animation. Reset to
 * black-on-white print legibility. Hide UI-only chrome.
 * ---------------------------------------------------------------- */
@media print {
    *, *::before, *::after {
        background: transparent !important;
        box-shadow: none !important;
        text-shadow: none !important;
        animation: none !important;
        transition: none !important;
        backdrop-filter: none !important;
        -webkit-backdrop-filter: none !important;
    }
    body { color: #000 !important; background: #fff !important; }
    .site-header, .site-footer, .theme-toggle, .nav .sep,
    .lang-switch, .logout-form { display: none !important; }
    .home-section, .legal-body { padding: 1rem 0 !important; max-width: none !important; }
    a { color: #000 !important; text-decoration: underline !important; }
    a::after { display: none !important; }
    img { max-width: 100% !important; page-break-inside: avoid; }
    h1, h2, h3 { page-break-after: avoid; }
    p, li { page-break-inside: avoid; }
}
