/* =====================================================================
   Woulfe's K9 — Mosaic
   Depends on tokens.css and reveal.css.

   A zig-zag: photographs hold the middle column the whole way down while the
   copy cards alternate left and right around them. That is the whole idea —
   the pictures give the section a spine, and the cards step either side of
   it. See DESIGN-SYSTEM.md §9.

   Placement is explicit (--col / --row set per item in PHP) rather than left
   to auto-placement. Auto-placement walks forward only: on the second row the
   card sits in column 1, which is *behind* the picture in column 2, so the
   cursor would push it down to a row of its own and the zig-zag would fall
   apart. `dense` would fix that by reordering, which is worse — it decides
   the reading order for you.
   ===================================================================== */

.wk9-mos {
    /* Anchor target — the sticky bar would otherwise land on the heading. */
    scroll-margin-top: calc(var(--wk9-header-offset, 108px) + var(--k9-space-4));
    position: relative;
    box-sizing: border-box;
    padding: var(--k9-section-y) 0;
    background: var(--k9-surface);
    color: var(--k9-text);
    font-family: var(--k9-font-body);
    isolation: isolate;
    overflow: hidden;

    /* Full-bleed out of whatever container it is dropped into. */
    width: 100vw;
    max-width: 100vw;
    left: 50%;
    right: 50%;
    margin-left: -50vw;
    margin-right: -50vw;
}

.wk9-mos *,
.wk9-mos *::before,
.wk9-mos *::after { box-sizing: border-box; }

.wk9-mos__glow {
    position: absolute;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    background: radial-gradient(62% 45% at 50% 0%, var(--k9-ink-800) 0%, transparent 70%);
}

.wk9-mos__intro,
.wk9-mos__grid {
    width: min(var(--k9-container), calc(100% - (var(--k9-gutter) * 2)));
    margin-left: auto;
    margin-right: auto;
}

/* Rule between this section and the next ---------------------------------

   The sections on this page all butt straight together — 112px of padding
   either side and no border anywhere — so a boundary only reads where the
   section happens to end on a bordered panel. This draws a real one.

   The adjacent-sibling selector is what makes it a single switch: one class
   on this section closes the gap on BOTH sides of the rule, so the hairline
   sits centred in the space rather than pinned to the bottom of one section
   with the next one's full padding underneath it. The two are true siblings
   in the builder's output, which is what makes `+` safe here. */

.wk9-mos.has-rule-after { padding-bottom: 0; }

.wk9-mos.has-rule-after::after {
    content: "";
    display: block;
    width: min(var(--k9-container), calc(100% - (var(--k9-gutter) * 2)));
    height: 1px;
    margin: var(--k9-space-16) auto 0;
    background: var(--k9-line);
}

.wk9-mos.has-rule-after + section { padding-top: var(--k9-space-16); }

/* Intro ---------------------------------------------------------------- */

.wk9-mos__intro {
    max-width: 760px;
    margin-bottom: var(--k9-space-16);
    text-align: center;
}

.wk9-mos__eyebrow {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--k9-space-3);
    margin: 0 0 var(--k9-space-4);
    font-size: var(--k9-text-micro);
    font-weight: var(--k9-weight-bold);
    letter-spacing: var(--k9-tracking-micro);
    text-transform: uppercase;
    color: var(--k9-text-muted);
}

.wk9-mos__eyebrow-rule {
    display: block;
    width: 32px;
    height: 1px;
    flex: 0 0 32px;
    background: var(--k9-text-faint);
}

.wk9-mos__heading {
    margin: 0;
    font-family: var(--k9-font-display);
    font-weight: var(--k9-weight-display);
    font-size: var(--k9-text-display-lg);
    line-height: var(--k9-leading-display);
    letter-spacing: var(--k9-tracking-display);
    text-transform: uppercase;
    color: var(--k9-text);
    text-wrap: balance;
}

.wk9-mos__lede {
    margin: var(--k9-space-4) auto 0;
    max-width: 56ch;
    font-size: var(--k9-text-body-lg);
    line-height: var(--k9-leading-snug);
    color: var(--k9-text-muted);
}

/* Grid ----------------------------------------------------------------- */

.wk9-mos .wk9-mos__grid {
    margin-left: auto;
    margin-right: auto;
    padding: 0;
    list-style: none;
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: clamp(var(--k9-space-4), 2vw, var(--k9-space-8));
    align-items: stretch;
}

.wk9-mos__cell {
    margin: 0;
    min-width: 0;
    grid-column: var(--col);
    grid-row: var(--row);
}

/* Entrance ---------------------------------------------------------------

   The shared reveal primitive only rises straight up. Here each cell comes in
   from the side it actually sits on — the right-hand cards drift in from the
   right, the left-hand ones from the left — so the entrance describes the
   zig-zag instead of fighting it. Direction is a custom property set per cell
   in PHP, because CSS cannot branch on the value of --col.

   Longer and softer than the default 700ms: this is the calmest section on
   the page and it should arrive rather than snap. The spring easing overshoots
   very slightly, which is what stops a long fade feeling like a dissolve.

   Specificity beats reveal.css on purpose — (0,3,1) against its (0,2,1) — so
   the transform below replaces the primitive's rather than racing it. Under
   prefers-reduced-motion the primitive's !important reset still wins, and
   reveal.js never adds the .wk9-reveal class at all. */

html.wk9-reveal .wk9-mos__cell[data-wk9-reveal] {
    opacity: 0;
    transform: translate3d(var(--from-x, 0), var(--from-y, 30px), 0);
    transition:
        opacity 900ms var(--k9-ease-spring),
        transform 900ms var(--k9-ease-spring);
    transition-delay: var(--wk9-reveal-delay, 0ms);
    will-change: opacity, transform;
}

html.wk9-reveal .wk9-mos__cell[data-wk9-reveal].is-revealed {
    opacity: 1;
    transform: none;
}

/* Stop claiming a compositor layer once it has played. */
html.wk9-reveal .wk9-mos__cell[data-wk9-reveal].is-settled { will-change: auto; }

/* One column: the cards are full width, so a sideways drift reads as a wobble
   rather than as direction. They rise like everything else. */
@media (max-width: 720px) {
    html.wk9-reveal .wk9-mos__cell[data-wk9-reveal] { --from-x: 0; }
}

/* Media ---------------------------------------------------------------- */

.wk9-mos__media {
    position: relative;
    overflow: hidden;
    border-radius: var(--k9-radius-xl);
    border: 1px solid var(--k9-line);
    background: var(--k9-surface-card);
    box-shadow: var(--k9-shadow-3);
    aspect-ratio: 1 / 1;
}

/* Scoped to two classes — BeTheme's img:not([src$=".svg"]) is (0,1,1) and
   beats a single class. See DESIGN-SYSTEM.md §12, rule 9. */
.wk9-mos__media .wk9-mos__img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transform: scale(1.001);
    transition: transform var(--k9-duration-slow) var(--k9-ease);
}

.wk9-mos__cell:hover .wk9-mos__media .wk9-mos__img { transform: scale(1.045); }

.wk9-mos__media .wk9-mos__img--empty {
    background: repeating-linear-gradient(
        135deg,
        var(--k9-surface-inset) 0 12px,
        var(--k9-surface-card) 12px 24px
    );
}

.wk9-mos__shade {
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(
        to top,
        rgba(var(--k9-black-rgb), 0.5) 0%,
        rgba(var(--k9-black-rgb), 0) 55%
    );
}

/* Card ----------------------------------------------------------------- */

/* The icon rides at the top and the words sit at the foot, with the gap left
   open between them — that space is the card's whole composition, so nothing
   should be added to fill it. */
.wk9-mos__card {
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: var(--k9-space-8);
    padding: clamp(var(--k9-space-5), 2vw, var(--k9-space-8));
    border-radius: var(--k9-radius-xl);
    border: 1px solid var(--k9-line);
    background:
        linear-gradient(180deg, rgba(255, 255, 255, 0.05) 0%, transparent 44%),
        var(--k9-surface-card);
    box-shadow: var(--k9-shadow-3), var(--k9-shadow-inset);
    transition: border-color var(--k9-duration-fast) var(--k9-ease);
}

.wk9-mos__cell:hover .wk9-mos__card { border-color: var(--k9-line-strong); }

.wk9-mos__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 62px;
    height: 62px;
    border-radius: var(--k9-radius-pill);
    border: 1px solid rgba(255, 255, 255, 0.16);
    background: rgba(255, 255, 255, 0.06);
    -webkit-backdrop-filter: blur(18px) saturate(140%);
    backdrop-filter: blur(18px) saturate(140%);
    box-shadow: var(--k9-shadow-inset);
    color: var(--k9-text);
}

.wk9-mos__title {
    margin: 0 0 var(--k9-space-3);
    font-family: var(--k9-font-display);
    font-weight: var(--k9-weight-display);
    font-size: var(--k9-text-title-lg);
    line-height: var(--k9-leading-display);
    letter-spacing: var(--k9-tracking-display);
    text-transform: uppercase;
    color: var(--k9-text);
    text-wrap: balance;
}

.wk9-mos__text {
    margin: 0;
    font-size: var(--k9-text-body-sm);
    line-height: 1.65;
    color: var(--k9-text-muted);
}

.wk9-mos__link {
    display: inline-flex;
    align-items: center;
    gap: var(--k9-space-3);
    margin-top: var(--k9-space-5);
    font-size: var(--k9-text-micro);
    font-weight: var(--k9-weight-bold);
    letter-spacing: var(--k9-tracking-micro);
    text-transform: uppercase;
    text-decoration: none;
    color: var(--k9-text);
    border-bottom: 1px solid var(--k9-line-strong);
    padding-bottom: 4px;
    transition: border-color var(--k9-duration-fast) var(--k9-ease);
}

.wk9-mos__link svg { transition: transform var(--k9-duration) var(--k9-ease); }
.wk9-mos__link:hover { border-bottom-color: var(--k9-text); }
.wk9-mos__link:hover svg,
.wk9-mos__cell:hover .wk9-mos__link svg { transform: translate(3px, -3px); }

.wk9-mos__link:focus-visible {
    outline: none;
    box-shadow: var(--k9-focus-ring);
    border-radius: var(--k9-radius-xs);
}

/* Responsive ------------------------------------------------------------ */

/* Two columns: the picture keeps one side and the card takes the other,
   still alternating. The centre spine only works while there are three. */
@media (max-width: 1080px) {
    .wk9-mos .wk9-mos__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .wk9-mos__cell { grid-column: var(--col-md, auto); }
    .wk9-mos__intro { margin-bottom: var(--k9-space-10); }
}

@media (max-width: 720px) {
    .wk9-mos .wk9-mos__grid { grid-template-columns: minmax(0, 1fr); }

    /* One column: picture then its card, in order, all the way down. Any
       alternation is meaningless here and explicit rows would fight it. */
    .wk9-mos__cell {
        grid-column: 1;
        grid-row: auto;
    }

    .wk9-mos__media { aspect-ratio: 16 / 11; }
    .wk9-mos__card { gap: var(--k9-space-6); }
}

@media (prefers-reduced-motion: reduce) {
    .wk9-mos__media .wk9-mos__img,
    .wk9-mos__card,
    .wk9-mos__link,
    .wk9-mos__link svg { transition: none; }
    .wk9-mos__cell:hover .wk9-mos__media .wk9-mos__img { transform: scale(1.001); }
}
