/* District Frame - motion layer.
   v3: reduced to scroll reveals only. The former ambient effects
   (orbs, grain, vignette, particles, tilt, parallax, custom cursor,
   scroll progress bar) were removed in the 2026-06 editorial redesign. */

html {
    scroll-padding-top: 92px; /* anchored links clear the fixed nav */
}

/* ============================================================
   REVEAL ON SCROLL - fade + small rise, settled by JS adding .is-visible
   ============================================================ */
.df-reveal {
    opacity: 0;
    transform: translateY(24px);
    transition:
        opacity var(--df-reveal-dur) var(--df-ease),
        transform var(--df-reveal-dur) var(--df-ease);
    will-change: opacity, transform;
}
.df-reveal.is-visible {
    opacity: 1;
    transform: none;
    will-change: auto;
}

/* Stagger children of a [data-stagger] container */
[data-stagger] > .df-reveal:nth-child(1) { transition-delay: 0s; }
[data-stagger] > .df-reveal:nth-child(2) { transition-delay: 0.08s; }
[data-stagger] > .df-reveal:nth-child(3) { transition-delay: 0.16s; }
[data-stagger] > .df-reveal:nth-child(4) { transition-delay: 0.24s; }
[data-stagger] > .df-reveal:nth-child(5) { transition-delay: 0.32s; }
[data-stagger] > .df-reveal:nth-child(6) { transition-delay: 0.4s; }
[data-stagger] > .df-reveal:nth-child(n+7) { transition-delay: 0.48s; }

/* Reduced-motion suppression intentionally DISABLED 2026-07-05 (owner: play
   animations for everyone; many users have OS reduced-motion on unknowingly).
   Restore this block to respect the setting again:
   @media (prefers-reduced-motion: reduce) { .df-reveal { opacity:1; transform:none; transition:none; } } */

/* ============================================================
   PHOTO LIGHTBOX (site-wide)
   Any element with data-df-lightbox opens the shared #footer modal.
   Rules are global (the modal lives in footer.php, one per page).
   ============================================================ */
.df-lightbox-trigger {
    cursor: zoom-in;
}
.df-lightbox-trigger:focus-visible {
    outline: 2px solid var(--df-ink);
    outline-offset: 3px;
}
/* Photos auto-attached to the lightbox by initCardLightbox() (team avatars,
   the Home craft band, project BTS grids, journal images, the About carousel)
   get the same zoom affordance and focus ring as explicit triggers. */
.df-photo-zoomable {
    cursor: zoom-in;
}
.df-photo-zoomable:focus-visible {
    outline: 2px solid var(--df-ink);
    outline-offset: 3px;
}

.df-os-lightbox {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: clamp(16px, 4vw, 56px);
}
.df-os-lightbox[hidden] {
    display: none;
}
.df-os-lightbox-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(8, 8, 8, 0.9);
    -webkit-backdrop-filter: blur(4px);
    backdrop-filter: blur(4px);
    cursor: zoom-out;
}
.df-os-lightbox-dialog {
    position: relative;
    z-index: 1;
    max-width: min(1180px, 100%);
    max-height: 90vh;
    animation: dfOsLightboxIn 0.3s var(--df-ease);
}
@keyframes dfOsLightboxIn {
    from { opacity: 0; transform: translateY(12px); }
    to   { opacity: 1; transform: none; }
}
.df-os-lightbox-dialog img {
    display: block;
    max-width: 100%;
    max-height: 90vh;
    width: auto;
    height: auto;
    object-fit: contain;
    border-radius: 4px;
    box-shadow: 0 30px 80px -30px rgba(0, 0, 0, 0.7);
}
.df-os-lightbox-close {
    position: absolute;
    top: -14px;
    right: -14px;
    z-index: 2;
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: var(--df-paper);
    border: 1px solid var(--df-hairline);
    color: var(--df-ink);
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
    transition: background 0.25s ease, color 0.25s ease, border-color 0.25s ease;
}
.df-os-lightbox-close .df-icon {
    width: 20px;
    height: 20px;
}
.df-os-lightbox-close:hover {
    background: var(--df-ink);
    color: var(--df-paper);
    border-color: var(--df-ink);
}
.df-os-lightbox-close:focus-visible {
    outline: 2px solid var(--df-paper);
    outline-offset: 2px;
}
@media (max-width: 600px) {
    .df-os-lightbox-close {
        top: 8px;
        right: 8px;
        background: rgba(14, 14, 14, 0.65);
        border-color: rgba(241, 238, 231, 0.5);
        color: var(--df-paper);
    }
}
@media (prefers-reduced-motion: reduce) {
    .df-os-lightbox-dialog { animation: none; }
}

/* ============================================================
   ANIMATED CODE EDITOR (Website Design)
   Component styles for df_code_animation() (functions.php); the
   typing loop is initCodeAnimation() in js/df-effects.js. Global
   (unscoped) on purpose so the same editor renders in BOTH the
   Website Design landing hero and the Website Design row on the
   main Services page. Hero-only LAYOUT rules (grid share, title
   clamp, hero max-width) stay in css/template-service-detail.css.
   Colours reuse the warm service-illustration palette.
   ============================================================ */
.df-sd-code-wrap {
    max-width: 760px;
    margin: 0 auto;
}
.df-sd-code {
    border: 1px solid #ddd4c4;
    border-radius: 12px;
    background: #f3eee2;
    overflow: hidden;
    box-shadow: 0 30px 70px -44px rgba(44, 34, 24, 0.5);
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Courier New", monospace;
    -webkit-font-smoothing: antialiased;
}
/* Title bar: traffic-light dots + file tabs */
.df-code-bar {
    display: flex;
    align-items: flex-end;
    gap: 14px;
    padding: 12px 15px 0;
    background: #ece4d3;
    border-bottom: 1px solid #ddd4c4;
}
.df-code-dots {
    display: flex;
    gap: 7px;
    padding-bottom: 11px;
    flex: 0 0 auto;
}
.df-code-dots i {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: #cdbfa9;
}
/* Tab strip scrolls horizontally; the active tab is scrolled into view by JS.
   position:relative makes this the offsetParent so a tab's offsetLeft is
   measured inside the strip (keeps the scroll-into-view math correct). */
.df-code-tabs {
    position: relative;
    display: flex;
    gap: 4px;
    flex: 1 1 auto;
    min-width: 0;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
    -ms-overflow-style: none;
    scroll-behavior: smooth;
}
.df-code-tabs::-webkit-scrollbar {
    display: none;
}
.df-code-tab {
    display: inline-flex;
    align-items: center;
    flex: 0 0 auto;
    white-space: nowrap;
    padding: 7px 13px;
    margin-bottom: -1px;
    border: 1px solid transparent;
    border-radius: 7px 7px 0 0;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: #9a8b78;
    transition: color 0.25s ease, background 0.25s ease;
}
.df-code-tab.is-active {
    color: #3a2c25;
    background: #f3eee2;
    border-color: #ddd4c4;
    border-bottom-color: #f3eee2;
}
/* Editor body: gutter + code */
.df-code-body {
    display: flex;
    min-height: 248px;
    font-size: clamp(12px, 1.55vw, 15px);
    line-height: 1.9;
}
.df-code-gutter {
    margin: 0;
    padding: 18px 12px 18px 18px;
    text-align: right;
    color: #9a8b78;
    opacity: 0.55;
    background: #ece4d3;
    border-right: 1px solid #ddd4c4;
    user-select: none;
    white-space: pre;
}
.df-code-text {
    margin: 0;
    padding: 18px;
    flex: 1;
    min-width: 0;
    overflow: hidden;
    white-space: pre;
    color: #3a2c25;
}
/* Status bar */
.df-code-status {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    padding: 10px 15px;
    background: #ece4d3;
    border-top: 1px solid #ddd4c4;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: #6f685b;
}
.df-code-building {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}
/* "Building" label rendered as CSS content, not an HTML text node, so the
   decorative status word stays out of the crawlable/indexable page text
   (SEO cleanup 2026-07-06). Visually identical to the old inline label. */
.df-code-building::after {
    content: "Building";
}
.df-code-pulse {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: #bf9b53;
    animation: df-code-pulse 2.6s ease-in-out infinite;
}
.df-code-meta {
    color: #9a8b78;
}
/* Syntax colours (set by JS via .df-c-* classes) */
.df-c-p { color: #9a8b78; }
.df-c-t { color: #3a2c25; font-weight: 700; }
.df-c-a { color: #8a3340; }
.df-c-v { color: #6e2a36; }
.df-c-x { color: #3a2c25; }
.df-c-s { color: #3a2c25; font-weight: 700; }
.df-c-r { color: #8a3340; }
.df-c-c { color: #5c4b40; }
.df-c-k { color: #8a3340; font-weight: 700; }
.df-c-n { color: #7c5a34; }
.df-c-f { color: #5c4b40; }
.df-c-m { color: #a2937f; font-style: italic; }
/* Blinking caret */
.df-code-caret {
    display: inline-block;
    width: 7px;
    height: 1.05em;
    margin-left: 1px;
    background: #bf9b53;
    vertical-align: -2px;
    animation: df-code-caret 1.05s steps(1) infinite;
}
/* Process strip under the editor (hero only; the Services row omits it) */
.df-sd-steps {
    display: flex;
    align-items: center;
    justify-content: center;
    max-width: 760px;
    margin: 22px auto 0;
}
.df-sd-step {
    display: flex;
    align-items: center;
    gap: 9px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--df-ink-muted);
    white-space: nowrap;
}
.df-sd-step-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: #bf9b53;
    animation: df-code-pulse 3s ease-in-out infinite;
}
.df-sd-step-line {
    flex: 1;
    height: 1px;
    margin: 0 12px;
    background: var(--df-hairline);
}
@keyframes df-code-caret {
    0%, 49% { opacity: 1; }
    50%, 100% { opacity: 0; }
}
@keyframes df-code-pulse {
    0%, 100% { transform: scale(1); opacity: 0.9; }
    50% { transform: scale(1.3); opacity: 1; }
}
@media (max-width: 560px) {
    .df-code-body { min-height: 200px; }
    .df-sd-steps { font-size: 10px; }
    .df-sd-step-line { margin: 0 7px; }
}
/* Reduced-motion suppression DISABLED 2026-07-05 (owner: animations for all).
   Restore to respect the setting:
   @media (prefers-reduced-motion: reduce) {
       .df-code-caret, .df-code-pulse, .df-sd-step-dot { animation: none !important; }
       .df-code-tabs { scroll-behavior: auto; }
   } */

/* ============================================================
   SERVICE ILLUSTRATIONS - subtle, slow motion for the animated
   df_service_illustration() SVG art (df-service-art.php).
   Keyframes are namespaced df-sa-* and gated per element by
   animation-play-state: var(--df-sa-pstate, running); js/df-effects.js
   flips that var to 'paused' while the art is off-screen. Reduced-
   motion disables it entirely (each element has a sensible base state).
   ============================================================ */
@keyframes df-sa-glow { 0%, 100% { opacity: 0.42; } 50% { opacity: 0.85; } }
@keyframes df-sa-screen-glow { 0%, 100% { opacity: 0.05; } 50% { opacity: 0.22; } }
@keyframes df-sa-blink { 0%, 100% { opacity: 1; } 50% { opacity: 0.2; } }
@keyframes df-sa-spin { to { transform: rotate(360deg); } }
@keyframes df-sa-grow { 0%, 100% { transform: scaleY(0.5); } 50% { transform: scaleY(1); } }
@keyframes df-sa-twinkle { 0%, 100% { opacity: 0.18; transform: scale(0.65); } 50% { opacity: 1; transform: scale(1.15); } }
@keyframes df-sa-dash { to { stroke-dashoffset: -16; } }
@keyframes df-sa-scan { 0% { transform: translateY(0); opacity: 0; } 18% { opacity: 0.5; } 80% { opacity: 0.5; } 100% { transform: translateY(64px); opacity: 0; } }
@keyframes df-sa-ring { 0% { transform: scale(0.5); opacity: 0.7; } 100% { transform: scale(2); opacity: 0; } }
@keyframes df-sa-cone { 0%, 100% { opacity: 0.14; } 50% { opacity: 0.4; } }
@keyframes df-sa-draw-check { 0% { stroke-dashoffset: 42; } 45% { stroke-dashoffset: 0; } 88% { stroke-dashoffset: 0; } 100% { stroke-dashoffset: 42; } }

/* Reduced-motion suppression DISABLED 2026-07-05 (owner: animations for all).
   Restore to respect the setting:
   @media (prefers-reduced-motion: reduce) { .df-sv-art * { animation: none !important; } } */
