/* ---------------------------------------------------------------------------
 * Learning Library
 *
 * Same tokens as kf-about.css — brand yellow #FED208, the neutral ramp, slate #212C34 for the
 * thumbnail well. Buttons are pills at 30px and cards square at 0, both measured off the live site.
 *
 * Two columns above the l breakpoint: an 880 card column and a 280 filter rail inside the house
 * 1200 measure. Below it the rail moves above the grid, because a sidebar that becomes a full-width
 * block at the top of a long list is worse than one you scroll past.
 * ------------------------------------------------------------------------- */

.kf-library {
    --kf-yellow: #FED208;
    /* Slate is the site's real heading colour and the colour of the fixture bodies themselves.
       It replaces the derived "text-safe yellow" #846C01, which passed AA at 5.09:1 but read as
       mud — the style guide's own rule is that yellow is a FILL, not a text colour, so a link
       should not be trying to be yellow in the first place. Yellow returns on hover, as an
       underline, where it is decoration rather than the thing being read. */
    --kf-slate: #212C34;
    --kf-link: #212C34;
    --kf-link-hover: #161616;
    --kf-ink: #161616;
    --kf-ink-3: #414243;
    --kf-mute: #717275;
    --kf-line: #E5E5E5;
    --kf-paper: #F9F9F9;
    --kf-display: 'Roboto Condensed', 'Roboto', system-ui, sans-serif;
    --kf-body: 'Roboto', system-ui, sans-serif;
    font-family: var(--kf-body);
}

.kf-sr { position:absolute; width:1px; height:1px; overflow:hidden; clip-path:inset(50%); white-space:nowrap; }

.kf-library__cols { display: grid; grid-template-columns: 1fr 280px; gap: 40px; align-items: start; }
.kf-library__empty, .kf-library__none { font-size: 15px; line-height: 23px; color: var(--kf-mute); }

/* --- sections ------------------------------------------------------------ */
.kf-vsection + .kf-vsection { margin-top: 56px; }
.kf-vsection__head { display: flex; align-items: baseline; justify-content: space-between; gap: 20px; }
.kf-vsection__title {
    font-family: var(--kf-display); font-weight: 700; text-transform: uppercase;
    font-size: 24px; line-height: 30px; color: var(--kf-ink); margin: 0;
}
.kf-vsection__all {
    font-size: 12px; line-height: 18px; font-weight: 500; color: var(--kf-link);
    text-decoration: none; white-space: nowrap;
    border-bottom: 2px solid transparent; transition: border-color .12s ease-out;
}
.kf-vsection__all:hover { color: var(--kf-link-hover); border-bottom-color: var(--kf-yellow); }
.kf-vgrid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 32px; margin-top: 22px; }

/* --- card ---------------------------------------------------------------- */
.kf-vcard { display: flex; flex-direction: column; }
.kf-vcard[hidden] { display: none; }
.kf-vcard__thumb {
    position: relative; display: block; width: 100%; aspect-ratio: 16 / 9; padding: 0;
    border: 0; background: var(--kf-slate); overflow: hidden; cursor: pointer;
}
.kf-vcard__thumb img { width: 100%; height: 100%; object-fit: cover; display: block;
    transition: transform .2s ease-out; }
.kf-vcard__thumb:hover img { transform: scale(1.05); }
.kf-vcard__thumb-empty { display: block; width: 100%; height: 100%; background: var(--kf-slate); }
.kf-vcard__badge {
    position: absolute; left: 10px; top: 10px; background: var(--kf-yellow); color: var(--kf-ink);
    font-size: 10px; line-height: 22px; letter-spacing: .6px; font-weight: 500;
    text-transform: uppercase; padding-inline: 9px; border-radius: 2px;
}
.kf-vcard__duration {
    position: absolute; right: 10px; bottom: 10px; background: rgba(0,0,0,.72); color: #fff;
    font-size: 11px; line-height: 22px; padding-inline: 8px; border-radius: 2px;
    font-variant-numeric: tabular-nums;
}
.kf-vcard__play {
    position: absolute; inset: 0; display: grid; place-items: center; pointer-events: none;
    opacity: .92; transition: transform .15s ease-out;
}
.kf-vcard__thumb:hover .kf-vcard__play { transform: scale(1.08); }
.kf-vcard__title {
    font-family: var(--kf-display); font-weight: 700; text-transform: uppercase;
    font-size: 16px; line-height: 21px; color: var(--kf-ink); margin: 14px 0 0;
}
.kf-vcard__meta {
    font-size: 11px; line-height: 16px; font-weight: 500; color: var(--kf-mute);
    margin: 10px 0 0; text-transform: uppercase; letter-spacing: .4px;
}
.kf-vcard__dot { color: var(--kf-mute); }

/* --- filter rail --------------------------------------------------------- */
/*
 * Sticky belongs on the GRID ITEM, not on .kf-rail inside it.
 *
 * A sticky element travels within its containing block, and .kf-rail's containing block is
 * .kf-library__rail -- which, under the grid's `align-items: start`, hugs the rail exactly. Both
 * boxes measured 720px, so there was zero room to move and the rail never stuck despite carrying
 * position: sticky the whole time. A grid item's containing block is its GRID AREA instead, which
 * spans the full row (1764px of card column here), so the travel room is real.
 *
 * align-self: start keeps the item content-height rather than stretching the paper background down
 * the whole column.
 */
/* --kf-rail-top is written by kf-library.js from the live height of the theme's sticky nav. The
   24px fallback is correct when nothing is stuck above; without it the rail pins UNDER the fixed
   header and its title and search box are hidden behind the nav. */
.kf-library__rail { position: sticky; top: var(--kf-rail-top, 24px); align-self: start; }
.kf-rail { background: var(--kf-paper); padding: 20px; }

/* A rail taller than the viewport would otherwise pin its top and hide its lower facets with no way
   to reach them. Scrolls itself only when it has to. */
@media (min-width: 1200px) {
    .kf-library__rail {
        max-height: calc(100vh - var(--kf-rail-top, 24px) - 24px);
        overflow-y: auto;
        overscroll-behavior: contain;
    }
}
.kf-rail__head { display: flex; align-items: baseline; justify-content: space-between; }
.kf-rail__title {
    font-family: var(--kf-display); font-weight: 700; text-transform: uppercase;
    font-size: 15px; line-height: 20px; margin: 0; color: var(--kf-ink);
}
.kf-rail__clear {
    background: none; border: 0; cursor: pointer; padding: 0;
    font-size: 12px; line-height: 18px; font-weight: 500; color: var(--kf-link);
}
.kf-rail__clear:hover { color: var(--kf-link-hover); text-decoration: underline;
    text-decoration-color: var(--kf-yellow); text-decoration-thickness: 2px; }
.kf-rail__search { display: block; margin-top: 14px; }
.kf-rail__search input {
    width: 100%; box-sizing: border-box; height: 38px; padding-inline: 12px;
    border: 1px solid #D3D4D5; background: #fff; border-radius: 2px;
    font-family: var(--kf-body); font-size: 13px; color: var(--kf-ink);
}
.kf-facet { border-top: 1px solid var(--kf-line); margin-top: 16px; padding-top: 14px; }
.kf-facet:first-of-type { border-top: 0; }
.kf-facet__head { margin: 0; }
/* justify-content: space-between spread THREE children -- label, count, chevron -- which parked the
   count in the middle of the row. Label left, count and chevron together on the right, so the counts
   also line up in a column down the rail regardless of label length. */
.kf-facet__toggle {
    display: flex; width: 100%; justify-content: flex-start; align-items: center;
    background: none; border: 0; padding: 0; cursor: pointer;
    font-family: var(--kf-body); font-size: 12px; line-height: 16px; font-weight: 500;
    letter-spacing: .6px; text-transform: uppercase; color: var(--kf-ink);
}
.kf-facet__n { color: var(--kf-mute); font-weight: 400; margin-left: auto; }
/* Now that four of the five facets start closed, the heading has to advertise that it opens --
   without a marker a collapsed facet reads as a heading with nothing under it. Drawn from two
   borders rather than shipped as an icon: it inherits colour and needs no asset. */
.kf-facet__toggle::after {
    content: ""; flex: none; width: 7px; height: 7px; margin-left: 10px;
    border-right: 1.5px solid var(--kf-mute);
    border-bottom: 1.5px solid var(--kf-mute);
    transform: translateY(2px) rotate(-135deg);   /* open: pointing up */
    transition: transform .18s ease;
}
.kf-facet__toggle[aria-expanded="false"]::after {
    transform: translateY(-2px) rotate(45deg);    /* closed: pointing down */
}
@media (prefers-reduced-motion: reduce) {
    .kf-facet__toggle::after { transition: none; }
}

/* Not `.kf-facet__toggle[aria-expanded="false"] + .kf-facet__list`, which is what this used to say
   and never once matched: the toggle lives inside .kf-facet__head, so the list is a sibling of the
   HEADING, not of the button. It went unnoticed while every facet defaulted open. State lives on
   the wrapper now, which also avoids depending on :has(). */
.kf-facet[data-open="0"] .kf-facet__list { display: none; }
.kf-facet__list { list-style: none; margin: 12px 0 0; padding: 0; }
.kf-facet__list li + li { margin-top: 8px; }
.kf-facet__list label { display: flex; gap: 9px; align-items: flex-start; cursor: pointer;
    font-size: 13px; line-height: 18px; color: var(--kf-ink-3); }
.kf-facet__list input { margin: 1px 0 0; accent-color: var(--kf-ink); }

/* --- focus --------------------------------------------------------------- */
.kf-library :is(button, a, input):focus-visible { outline: 2px solid var(--kf-ink); outline-offset: 3px; }
/* The sheet takes focus on open so the dialog is announced; it is not a control and must not
   look like one. Its children keep their focus rings. */
.kf-library__rail:focus { outline: none; }

/* The sheet chrome and the FAB only exist below 1200; above it the rail is a plain sidebar. */
.kf-rail__close, .kf-rail__ctas, .kf-fab, .kf-sheet-backdrop { display: none; }

/* --- reflow -------------------------------------------------------------- */
@media (max-width: 1199px) {
    .kf-library__cols { grid-template-columns: 1fr; }
    .kf-facet__list { columns: 2; }
    .kf-vgrid { grid-template-columns: repeat(2, 1fr); gap: 30px; }
}
@media (max-width: 639px) {
    .kf-vgrid { grid-template-columns: 1fr; }
    .kf-facet__list { columns: 1; }
    .kf-vsection + .kf-vsection { margin-top: 40px; }
}
@media (prefers-reduced-motion: reduce) {
    .kf-library * { transition: none !important; }
}

/* Filtered view: one flat grid. The heading carries the count so the result set reads as an
   answer to what was asked, not as another browsable section. */
.kf-vresults[hidden] { display: none; }
.kf-vresults .kf-vsection__title { color: var(--kf-ink); }

/* --- library hero -------------------------------------------------------- */
/*
 * The About hero puts its photograph in the right half (.kf-hero__media, inset 0 0 0 50%). This one
 * is full-bleed video instead, so the media rules are replaced rather than extended.
 *
 * The scrim is doing real work here, not tastefulness. The loop is graded footage that swings from
 * a near-black fire interior to a blown cyan-magenta panel sweep inside 15 seconds, so there is no
 * single overlay opacity that suits every frame. Two gradients: a horizontal one anchoring the text
 * column against the left edge, and a gentle vertical one so the bottom of the band does not fight
 * the section that follows.
 *
 * Measured, not assumed: compositing this scrim over the decoded video and sampling the actual
 * GLYPH rects (not the h1's block box, which runs the full 1200 measure and picks up bright pixels
 * where no text sits) across 37 frames at 0.4s intervals gives a worst case of 10.1:1 for the
 * headline and 9.0:1 for the lede. Both clear AAA. Re-measure if the loop is ever recut -- the
 * margin is comfortable, but it is a property of this footage, not of the gradients alone.
 */
/*
 * box-sizing matters here and is not boilerplate. min-height resolves against the CONTENT box by
 * default, so `min-height: 420px` on top of .kf-band's 140px padding-block produced a 700px band --
 * a 1.7:1 box for a 3.81:1 video, which made object-fit: cover throw most of every frame away. The
 * reel is composed for the band, so the band has to keep the reel's proportions: border-box plus a
 * smaller padding lands ~440px at desktop, close enough to 3.81:1 that cover trims only the edges.
 */
.kf-hero--library {
    box-sizing: border-box;
    min-height: 440px;
    padding-block: 64px;
    display: flex; align-items: center;
}
.kf-hero--library .kf-hero__inner { width: 100%; }

.kf-hero__video {
    position: absolute; inset: 0; width: 100%; height: 100%;
    object-fit: cover; object-position: center;
    /* The source is 1600x420; object-fit handles every band height without letterboxing. */
    pointer-events: none; border: 0; display: block;
}

.kf-hero__scrim {
    position: absolute; inset: 0; pointer-events: none;
    background:
        linear-gradient(90deg, rgba(0,0,0,.92) 0%, rgba(0,0,0,.78) 34%, rgba(0,0,0,.35) 72%, rgba(0,0,0,.28) 100%),
        linear-gradient(180deg, rgba(0,0,0,.30) 0%, rgba(0,0,0,0) 38%, rgba(0,0,0,.42) 100%);
}

/* Below the m breakpoint the loop is mostly hidden behind the scrim and the text stack anyway, so
   it is bandwidth with nothing to show for it. The poster carries the same image at ~17KB. */
@media (max-width: 639px) {
    .kf-hero--library { min-height: 320px; }
    .kf-hero__video { display: none; }
    .kf-hero--library {
        background: #141414 url("../images/library-hero-loop-poster.jpg") center / cover no-repeat;
    }
}

/* Motion is the whole point of the element, so there is no reduced version to fall back to --
   it stops being a video and becomes its own poster frame. */
@media (prefers-reduced-motion: reduce) {
    .kf-hero__video { display: none; }
    .kf-hero--library {
        background: #141414 url("../images/library-hero-loop-poster.jpg") center / cover no-repeat;
    }
}

/*
 * The archive at /videos/ renders into tm-main's own .uk-container, so its hero starts life one
 * container narrower than the page. .kf-bleed cannot help -- that collapses a Builder section's
 * container INWARD, and here the section is a child OF the container and has to escape OUTWARD.
 *
 * calc(50% - 50vw) is exactly the distance to the viewport edge at every width, because 50% resolves
 * against the container's content box: at 1440 that is 600 - 720 = -120px, which is precisely the
 * container's 80px auto margin plus its 40px padding; at 1000 it is 460 - 500 = -40px, matching the
 * padding once the auto margin has collapsed. No breakpoint table needed.
 *
 * Caveat: vw counts the scrollbar, so on a platform with classic (space-taking) scrollbars this runs
 * ~15px wide and can introduce a horizontal scrollbar. Overlay scrollbars (macOS default) are
 * unaffected. If that shows up on Windows, clip it on the section rather than reaching for 100vw.
 */
.uk-container > .kf-bleed-out { margin-inline: calc(50% - 50vw); }

/*
 * /videos/ renders through the theme's tm-main wrapper, which is a .uk-section and therefore brings
 * 70px of vertical padding with it. /learning-library/ has no tm-main at all -- the Builder emits
 * its sections straight into the page -- so the same hero sat 70px lower on the archive and the two
 * URLs did not line up. Zeroing it here is safe: archive-videos.php wraps the library in its own
 * .uk-section-large, so the spacing below the band is unaffected.
 */
.post-type-archive-videos .tm-main.uk-section { padding-block: 0; }

/* ---------------------------------------------------------------------------
 * Mobile / tablet: the rail becomes a bottom sheet
 *
 * Below 1200 a 280px sidebar has nowhere to go, and stacking it above the grid pushes the videos --
 * the thing the page is for -- under a screenful of checkboxes. LynTec's learning library solves
 * this with a floating Filters button that raises a bottom sheet, and this follows that pattern.
 *
 * Where it differs: LynTec clones its filter markup into the sheet and then mirrors every checkbox
 * change between the two copies. This moves the same element instead, so there is one set of inputs,
 * the existing filter JS keeps working untouched, and there is no sync to fall out of step.
 *
 * A sheet rather than UIkit's offcanvas because offcanvas only slides from the sides; filters
 * reached by thumb belong at the bottom of the screen.
 * ------------------------------------------------------------------------- */
@media (max-width: 1199px) {
    .kf-fab {
        display: inline-flex; align-items: center; gap: 8px;
        position: fixed; right: 16px; bottom: 16px; z-index: 1090;
        padding: 12px 20px; border: 0; border-radius: 30px; cursor: pointer;
        background: var(--kf-slate); color: #fff;
        font-family: var(--kf-body); font-size: 13px; font-weight: 500;
        letter-spacing: .6px; text-transform: uppercase;
        box-shadow: 0 6px 20px rgba(0,0,0,.28);
    }
    .kf-fab__count {
        display: inline-flex; align-items: center; justify-content: center;
        min-width: 20px; height: 20px; padding: 0 6px; border-radius: 10px;
        background: var(--kf-yellow); color: var(--kf-ink);
        font-size: 11px; font-weight: 700; letter-spacing: 0;
    }
    .kf-fab__count[hidden] { display: none; }

    .kf-sheet-backdrop {
        display: block; position: fixed; inset: 0; z-index: 1095;
        background: rgba(22,22,22,.5);
        opacity: 0; transition: opacity .28s ease;
    }
    .kf-sheet-backdrop[hidden] { display: none; }
    .kf-library[data-filters-open="1"] .kf-sheet-backdrop { opacity: 1; }

    .kf-library__rail {
        position: fixed; inset: auto 0 0 0; z-index: 1100;
        max-height: 85vh; overflow: hidden;
        background: var(--kf-paper);
        border-radius: 16px 16px 0 0;
        box-shadow: 0 -8px 40px rgba(0,0,0,.28);
        transform: translateY(100%);
        visibility: hidden;
        transition: transform .28s cubic-bezier(.32,.72,0,1), visibility .28s;
    }
    .kf-library[data-filters-open="1"] .kf-library__rail {
        transform: translateY(0); visibility: visible;
    }
    /* The drag handle is decoration -- it signals "this pulls up from the bottom". */
    .kf-library__rail::before {
        content: ""; position: absolute; top: 8px; left: 50%; transform: translateX(-50%);
        width: 36px; height: 4px; border-radius: 2px; background: #cfcfd1; z-index: 3;
    }

    /* .kf-rail scrolls, and head/CTAs stick to its edges. Doing it this way rather than with a
       flex column means no extra wrapper element around the facets. */
    .kf-rail {
        max-height: 85vh; overflow-y: auto; overscroll-behavior: contain;
        -webkit-overflow-scrolling: touch;
        padding: 0 20px; background: var(--kf-paper);
    }
    .kf-rail__head {
        position: sticky; top: 0; z-index: 2;
        background: var(--kf-paper); padding: 22px 0 12px;
    }
    /* Redundant inside the sheet -- the CTA bar carries Clear all where a thumb can reach it. */
    .kf-rail__head .kf-rail__clear { display: none; }
    .kf-rail__close {
        display: inline-flex; align-items: center; justify-content: center;
        margin-left: auto; width: 32px; height: 32px;
        background: none; border: 0; padding: 0; cursor: pointer; color: var(--kf-ink-3);
    }
    .kf-rail__ctas {
        display: flex; gap: 10px; position: sticky; bottom: 0; z-index: 2;
        background: var(--kf-paper); padding: 14px 0 18px; margin-top: 6px;
        border-top: 1px solid var(--kf-line);
    }
    .kf-rail__ctas button {
        flex: 1 1 0; min-height: 46px; border-radius: 30px; cursor: pointer;
        font-family: var(--kf-body); font-size: 13px; font-weight: 500;
        letter-spacing: .6px; text-transform: uppercase;
    }
    .kf-btn-ghost { background: none; border: 1px solid var(--kf-line); color: var(--kf-ink); }
    .kf-btn-solid { background: var(--kf-slate); border: 1px solid var(--kf-slate); color: #fff; }

    /* One column inside the sheet: two columns of checkboxes in a 85vh panel is a lot of scanning. */
    .kf-facet__list { columns: 1; }
}

@media (prefers-reduced-motion: reduce) {
    .kf-library__rail, .kf-sheet-backdrop { transition: none; }
}
