/*
 * The shared section parts — shell, header, link, button.
 *
 * Paired with LFCP_Design_Parts (the fields) and LFCP_Design_Render (the
 * markup). A part is styled once here and never restyled per design; a section
 * that wants it to look different sets a *role token* (see tokens.css), which is
 * what makes a skin a few lines instead of a fork.
 *
 * Breakpoints are hardcoded at 767/1024 to match Elementor's defaults, because
 * media queries cannot read custom properties. Per-instance values arrive as
 * properties on the section root and each query picks the one it wants.
 */

/* ------------------------------------------------------------------ shell */

/*
 * The family is declared on the section root AND on every text part, and the
 * reason it has to be both is worth knowing before anyone "tidies" it.
 *
 * The theme ships `* { font-family: Poppins, sans-serif }`. A universal
 * selector matches every element *directly*, and a matching declaration —
 * even at (0,0,0) — always beats an inherited value, because inheritance only
 * applies where nothing matches. So declaring the family on `.pk-sec` styles
 * the root and nothing inside it. Found by walking document.styleSheets on the
 * local site for rules matching the link; the link was the last part still
 * rendering in Poppins after the section root was set.
 *
 * The consequence: **inheritance cannot be relied on for font-family in this
 * layer at all.** Every text part states its own, and the rich-text containers
 * force their generated children back to `inherit` (see the rule after this
 * one) since `wp_kses_post` output is full of elements we never see.
 *
 * Nothing here inherits a usable font otherwise: the theme sets its own family
 * on `body` (Poppins on this install), so any part that specifies only a size
 * silently rendered in it — the intro copy, every card body, and the link,
 * measured on the local site. Declaring it once here means a part has to opt
 * *out* to be wrong, instead of opting in to be right. Headings override it
 * with --pk-display.
 *
 * An inherited value loses to any matching declaration regardless of
 * specificity, so a single class is enough to win here.
 */
.pk-sec {
    font-family: var(--pk-sans);
    box-sizing: border-box;
    position: relative;
    margin-top: var(--pk-mt-desktop, 50px);
    margin-bottom: var(--pk-mb-desktop, 50px);
    padding: var(--pk-pad-desktop, 100px);
    color: var(--pk-fg);
    font-family: var(--pk-sans);
}

.pk-sec *,
.pk-sec *::before,
.pk-sec *::after {
    box-sizing: border-box;
}

/*
 * Width modes. The inner is capped at --pk-max in every mode (see
 * .pk-sec__inner); what the mode decides is whether the *band* — the padding
 * box that carries the colour and the background image — is capped with it.
 *
 *   boxed / custom   band capped at --pk-max, so the colour ends where the
 *                    content ends
 *   full             band released, so the colour runs edge to edge while the
 *                    heading and the cards stay on the same measure
 *
 * `full` therefore changes only the background, which is what a full-bleed
 * section is for. It does not widen the content: a row of four cards spread
 * across 1440px is a different design, not a wider one.
 *
 * A section can still be no wider than the Elementor container it sits in — see
 * academics.MD. This governs our own capping, not the page's.
 */
.pk-sec--width-boxed,
.pk-sec--width-custom {
    max-width: var(--pk-max, 1170px);
    margin-left: auto;
    margin-right: auto;
}

.pk-sec--has-bg {
    background-color: var(--pk-bg, transparent);
}

/*
 * The backdrop is its own layer rather than a background on the section, so a
 * colour and a photograph can coexist — the design uses a tinted photo in
 * several sections — and so the photo can be positioned independently.
 */
.pk-sec--has-backdrop::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    background-image: var(--pk-backdrop);
    background-size: cover;
    background-position: center center;
    pointer-events: none;
}

/*
 * Corner dots — the 5x5 grids the file overlays on its dark bands (356:2162
 * places one group top-right and one bottom-left). A CSS effect rather than
 * baked into the background image, so the same texture serves sections with
 * and without them, on any page. One asset, positioned twice; painted on
 * ::after so it sits above the backdrop (::before) and below the content.
 */
/* Desktop only, like every dot ornament: the mobile frames draw plain
 * bands, and two 236px grids on a 420px band would sit under the content. */
@media (min-width: 1025px) {
    /*
     * `html:not(.pk-dots-js)` on every rule in this block: these painted
     * grids are the NO-JAVASCRIPT fallback. parts.js stamps the class
     * synchronously and rebuilds the same grids as inline SVG children of the
     * section, because the wave animation needs a phase per dot derived from
     * its section's document order — something a background image can never
     * carry (its internal timeline is shared per URL, not per use). Geometry
     * here and in parts.js' builder must stay in step: same assets, two
     * renderers.
     */
    html:not(.pk-dots-js) .pk-sec--dots::after {
        content: "";
        position: absolute;
        inset: 0;
        z-index: 0;
        pointer-events: none;
        background-image: url('../img/dots.svg'), url('../img/dots.svg');
        background-repeat: no-repeat, no-repeat;
        /*
         * The insets are per-page fields (Top/Bottom Dots Inset), because where
         * the grids sit depends on the page's layout around the band. The
         * fallbacks are the comps' own values.
         */
        background-position:
            right var(--pk-dots-a-x, 38px) top var(--pk-dots-a-y, 42px),
            left var(--pk-dots-b-x, 48px) bottom var(--pk-dots-b-y, 30px);
        background-size: 236px 236px, 236px 236px;
    }

    /*
     * The graded variant (Graded Dots toggle): rows shrink and fade toward
     * the section's CENTRE, so each corner needs its own asset — the
     * top-right group is largest at its top row, the bottom-left at its
     * bottom row. Same grid geometry as dots.svg; only per-row radius
     * (8.55 -> 3.4) and opacity (.10 -> .04) change, so switching the toggle
     * never moves a dot. Position/size stay inherited from the rule above.
     */
    html:not(.pk-dots-js) .pk-sec--dots.pk-sec--dots-graded::after {
        background-image: url('../img/dots-grade-tr.svg'), url('../img/dots-grade-bl.svg');
    }

    /*
     * The MIRRORED corner pair (Dots Corners: top left + bottom right —
     * Curriculum, 482:1239, against Why Parker's default, 482:1135). The
     * first background-image pairs with the first position, so the order in
     * both lists flips together; the graded variant needs its own mirrored
     * assets because each grid's grade falls toward the section centre from
     * ITS corner.
     */
    html:not(.pk-dots-js) .pk-sec--dots.pk-sec--dots-tlbr::after {
        background-position:
            left var(--pk-dots-a-x, 38px) top var(--pk-dots-a-y, 42px),
            right var(--pk-dots-b-x, 48px) bottom var(--pk-dots-b-y, 30px);
    }

    html:not(.pk-dots-js) .pk-sec--dots.pk-sec--dots-graded.pk-sec--dots-tlbr::after {
        background-image: url('../img/dots-grade-tl.svg'), url('../img/dots-grade-br.svg');
    }
}

/*
 * The page design's light dot grid (393:3222 — the corner-dots group in
 * accent orange at 10%), STRADDLING a section's bottom boundary: the
 * assembled page places it half in one section's whitespace and half in the
 * next one's, centred 29px left of the page axis at 1440, sliding behind
 * both neighbours' images. Anchored to the section ABOVE and allowed to
 * overflow, because a decoration between two sections has to belong to one
 * of them and the upper one is the one whose author placed it. Under the
 * z-index:1 inner so this section's content paints over it; the next section
 * is later in the DOM and paints over it for free. Desktop only — the
 * mobile comps never draw it. content-media's stylesheet supplies the
 * root positioning and inner stacking this rule assumes.
 */
@media (min-width: 1025px) {
    html:not(.pk-dots-js) .acad-cm.acad-cm--dots-bottom::after {
        content: "";
        position: absolute;
        /*
         * Placement comes from the row's own Dots Offset X/Y fields
         * (--cm-dots-x/y, emitted by content-media's renderer) — content,
         * not style, so one template serves pages that dot different seams.
         * The fallbacks are the assembled page's original values (393:3222).
         */
        left: calc(50% + var(--cm-dots-x, -147px));
        bottom: var(--cm-dots-y, -155px);
        width: 236px;
        height: 236px;
        z-index: 0;
        pointer-events: none;
        background: url('../img/dots-light.svg') no-repeat center / 236px 236px;
    }
}

/*
 * The LIVE dot grids — inline SVGs that parts.js builds inside every dotted
 * section, mirroring the painted fallbacks above (same 5x5 geometry, same
 * per-corner grade, same inset variables). Inline because the WAVE needs a
 * phase per dot, and only real elements can carry one; the script owns the
 * delays, this sheet owns everything else.
 *
 * Desktop only, like the painted fallback: below 1025px the grids are not
 * merely invisible, display:none also stops their animations from running.
 * The rule below is that display:none — it was described here but never
 * written, so on phones the two SVGs sat as static 236 × 236 blocks at the
 * top of every dotted section (found 2026-09-23 when the Program Details
 * card moved into Program Highlights and landed 700px down).
 */
@media (max-width: 1024px) {
    .pk-sec .pk-dots,
    .acad-cm .pk-dots {
        display: none;
    }
}

@media (min-width: 1025px) {
    .pk-sec .pk-dots,
    .acad-cm .pk-dots {
        position: absolute;
        width: 236px;
        height: 236px;
        z-index: 0;
        pointer-events: none;
        overflow: visible;
    }

    /* The corner pair mirrors the fallback's background-position maths. */
    .pk-sec .pk-dots--a {
        right: var(--pk-dots-a-x, 38px);
        top: var(--pk-dots-a-y, 42px);
    }

    .pk-sec .pk-dots--b {
        left: var(--pk-dots-b-x, 48px);
        bottom: var(--pk-dots-b-y, 30px);
    }

    .pk-sec--dots-tlbr .pk-dots--a {
        right: auto;
        left: var(--pk-dots-a-x, 38px);
    }

    .pk-sec--dots-tlbr .pk-dots--b {
        left: auto;
        right: var(--pk-dots-b-x, 48px);
    }

    /* The seam grid straddling a content-media row's bottom boundary. */
    .acad-cm .pk-dots--seam {
        left: calc(50% + var(--cm-dots-x, -147px));
        bottom: var(--cm-dots-y, -155px);
    }

    /*
     * The wave: a per-section cascade. Dotted sections fire in document
     * order a fixed 0.25s apart, grids and rows stagger inside them — the
     * schedule lives in parts.js as offsets in absolute SECONDS, so the
     * sweep looks identical whatever the page's height or length. The cycle
     * is declared here; parts.js sets each circle's negative animation-delay
     * (and the matching duration), which is the entire wave — same keyframes
     * everywhere, phase from section order.
     */
    .pk-sec .pk-dots circle,
    .acad-cm .pk-dots circle {
        transform-box: fill-box;
        transform-origin: center;
        animation: pk-dots-wave 4s ease-in-out infinite;
    }

    /*
     * Crest per variant (tuned in tools/dot-wave-lab): the corner grids'
     * small dots carry a 2x swell, but the seam grid's dots are drawn at
     * full size already and read best at 1.4x. The property is set on the
     * svg and inherits to the circles the keyframe animates.
     */
    .acad-cm .pk-dots--seam {
        --pk-dots-crest: 1.4;
    }

    @media (prefers-reduced-motion: reduce) {
        .pk-sec .pk-dots circle,
        .acad-cm .pk-dots circle {
            animation: none;
        }
    }
}

/*
 * A NARROW pulse, not a full-cycle swell — this is what makes the cascade
 * visible: rest (the drawn design) fills half the cycle, and the swell is
 * the 2s window at the START, so a dot's fire time in parts.js' schedule is
 * the moment it begins to grow. A full-cycle sine here reads as one
 * synchronized pulse instead: every dot is always mid-swell, so nothing
 * appears to travel.
 */
@keyframes pk-dots-wave {
    0%, 50%, 100% { transform: scale(1); }
    25%           { transform: scale(var(--pk-dots-crest, 2)); }
}

/*
 * If a scroll-LINKED dot animation ever comes back, it goes through
 * JavaScript, not this sheet: CSS scroll-driven animations
 * (animation-timeline: view()) were tried and only Chrome drove them —
 * Safari 26 parses the syntax without progressing the timeline here, and
 * Firefox has neither. (Both a position-locked parallax and a spring
 * rebound shipped briefly on that lesson before being cut: the bubbling
 * alone is the look.)
 */

/*
 * Admin kill switches — Tools → LF Custom Plugins → Designs → Animations.
 * animations.php server-renders one body class per disabled animation, so
 * there is no flash of motion before a script could act. The element stays
 * (dots drawn at rest size, in place); only its movement goes. The wave is
 * killed here; chalk is script-run, so parts.js checks its class itself.
 */
body.lfcp-anim-off-dot-wave .pk-dots circle {
    animation: none;
}

.pk-sec .pk-sec__inner {
    position: relative;
    z-index: 1;
    max-width: var(--pk-max, 1170px);
    margin-left: auto;
    margin-right: auto;
}

/*
 * Text for screen readers only — a live region, "(opens in a new tab)", a
 * control's fuller name. One rule for every section (review 2026-10-29:
 * four designs each had their own copy).
 */
.pk-sec .pk-sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

/* ----------------------------------------------------------------- header */

.pk-sec .pk-hd {
    display: flex;
    flex-direction: column;
}

.pk-sec .pk-hd__eyebrow,
.pk-sec .pk-hd__eyebrow-italic {
    margin: 0 0 10px;
    color: var(--pk-eyebrow-fg);
    line-height: var(--pk-tight);
    text-transform: uppercase;
}

.pk-sec .pk-hd__eyebrow {
    font-family: var(--pk-sans);
    font-weight: 800;
    font-size: var(--pk-eyebrow-size);
    letter-spacing: 0;
}

.pk-sec .pk-hd__eyebrow-italic {
    font-family: var(--pk-display);
    font-style: italic;
    font-weight: 900;
    font-size: var(--pk-eyebrow-alt-size);
    letter-spacing: var(--pk-track);
}

.pk-sec .pk-hd__heading {
    margin: 0 0 25px;
    font-family: var(--pk-display);
    font-weight: 900;
    font-size: var(--pk-h2-size);
    line-height: var(--pk-tight);
    text-transform: uppercase;
    color: var(--pk-heading-fg);
}

.pk-sec .pk-hd__subheading {
    margin: 0 0 20px;
    font-family: var(--pk-display);
    font-weight: 900;
    font-size: var(--pk-h3-size);
    line-height: var(--pk-tight);
    text-transform: uppercase;
    color: var(--pk-heading-fg);
}

.pk-sec .pk-hd__subheading-sm {
    margin: 0 0 15px;
    font-family: var(--pk-display);
    font-weight: 900;
    font-size: var(--pk-h4-size);
    line-height: var(--pk-tight);
    color: var(--pk-heading-fg);
}

/*
 * A run of blocks sets its own rhythm: the last one in the run must not add a
 * trailing gap, or the section's own spacing stops being the thing that controls
 * the distance to whatever follows.
 */
.pk-hd > *:last-child { margin-bottom: 0; }

.pk-sec .pk-hd__copy {
    font-family: var(--pk-sans);
    font-size: var(--pk-copy-lg-size);
    line-height: var(--pk-loose);
    color: var(--pk-muted-fg);
}

/*
 * Every descendant of a section, pushed back to inheriting.
 *
 * This is the blanket answer to the theme's `* { font-family: Poppins }`, and
 * a blanket is the right shape: the alternative is naming every element that
 * could appear, which includes whatever `wp_kses_post` lets an author write
 * and every wrapper a part happens to use — the link's inner <span> was the
 * one that made that obvious. `.pk-sec *` is (0,1,0) against the universal
 * selector's (0,0,0), and our own parts at (0,2,0) still win where they set a
 * family of their own.
 *
 * `code`/`pre`/`kbd`/`samp` are exempted, since inheriting a proportional
 * face is worse than the problem being fixed for those.
 */
.pk-sec * {
    font-family: inherit;
}

.pk-sec code,
.pk-sec pre,
.pk-sec kbd,
.pk-sec samp,
.acad-cm code,
.acad-cm pre,
.acad-cm kbd,
.acad-cm samp {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

.pk-sec .pk-hd__copy > *:first-child { margin-top: 0; }
.pk-sec .pk-hd__copy > *:last-child  { margin-bottom: 0; }

/*
 * Paragraph rhythm inside copy: the comps separate paragraphs by ~35px
 * (they are sibling text nodes in a 35px-gap flex column), where the theme's
 * default <p> margin gave 14. 1.25em of margin plus the line boxes' own
 * slack lands on the comps' visual gap.
 */
.pk-sec .pk-hd__copy p + p,
.acad-cm .acad-cm__body p + p {
    margin-top: 1.25em;
}

/* ------------------------------------------------------------------- link */

.pk-sec .pk-lnk,
.acad-cm .pk-lnk {
    font-family: var(--pk-sans);
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 8px;
    position: relative;
    color: var(--pk-link-fg);
    font-weight: 800;
    font-size: var(--pk-link-size);
    line-height: var(--pk-tight);
    letter-spacing: var(--pk-track);
    text-transform: uppercase;
    text-decoration: none;
    align-self: flex-start;
}

/*
 * The drawn underline is the actual brush stroke from the file (Vector 24,
 * 246x10), rasterised to a 3x PNG and applied as an alpha MASK so one asset
 * serves every colour — the paint comes from --pk-chalk. It replaced a plain
 * 2px border: at link size the wobble IS the point, and the home page draws
 * the same stroke, so a straight line read as a different site.
 */
.pk-sec .pk-lnk::after,
.acad-cm .pk-lnk::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    /* The comps draw the stroke fully BELOW the link box (377:2609: box 40
     * tall, stroke at y 45) — at -3px it crowded the text's descenders. */
    bottom: -8px;
    height: 8px;
    background: var(--pk-chalk, var(--pk-accent-orange));
    -webkit-mask: url('../img/chalk-underline.png') no-repeat center / 100% 100%;
    mask: url('../img/chalk-underline.png') no-repeat center / 100% 100%;
}

/*
 * The draw-in, and why it is structured back to front.
 *
 * The first version left the base stroke VISIBLE and had the script hide it
 * before animating. That is a paint-order bug by construction: the browser
 * paints before the footer script's DOMContentLoaded init runs, so the stroke
 * appeared, vanished, then drew itself — reported, accurately, as "drawn
 * first, then it removes itself and animates".
 *
 * So the hiding is now done by CSS from the very first paint, gated on
 * `@media (scripting: enabled)` — the stroke is only ever hidden in a browser
 * that will run the script. Three exits, all of them CSS:
 *
 *   - parts.js stamps `pk-chalk-js` on <html> the moment it executes; until
 *     that class exists a 2.5s-delayed failsafe animation draws every stroke
 *     anyway, so a blocked or 404ing script costs a delay, never the stroke.
 *   - the script's own IntersectionObserver adds `--chalk-draw` per link.
 *   - `pk-chalk-static` on <html> (reduced motion, no IntersectionObserver)
 *     restores the plain visible stroke.
 *
 * A browser too old for the scripting query never hides anything and the
 * script detects that and stays out of the way: static stroke, no flash.
 */
@media (scripting: enabled) {
    .pk-sec .pk-lnk::after,
    .acad-cm .pk-lnk::after {
        clip-path: inset(0 100% 0 0);
    }

    :root:not(.pk-chalk-js) .pk-sec .pk-lnk::after,
    :root:not(.pk-chalk-js) .acad-cm .pk-lnk::after {
        animation: pk-chalk-draw 700ms ease-out 2500ms both;
    }

    .pk-sec .pk-lnk--chalk-draw::after,
    .acad-cm .pk-lnk--chalk-draw::after {
        animation: pk-chalk-draw 700ms ease-out 80ms both;
    }

    :root.pk-chalk-static .pk-sec .pk-lnk::after,
    :root.pk-chalk-static .acad-cm .pk-lnk::after {
        clip-path: none;
        animation: none;
    }
}

@keyframes pk-chalk-draw {
    from { clip-path: inset(0 100% 0 0); }
    to   { clip-path: inset(0 0 0 0); }
}

@media (prefers-reduced-motion: reduce) {
    .pk-sec .pk-lnk::after,
    .acad-cm .pk-lnk::after {
        clip-path: none !important;
        animation: none !important;
    }
}

.pk-sec .pk-lnk:hover,
.pk-sec .pk-lnk:focus-visible,
.acad-cm .pk-lnk:hover,
.acad-cm .pk-lnk:focus-visible {
    color: var(--pk-link-fg);
    text-decoration: none;
}

.pk-sec .pk-lnk:hover .pk-lnk__chevron,
.acad-cm .pk-lnk:hover .pk-lnk__chevron {
    transform: translateX(3px);
}

.pk-sec .pk-lnk__chevron,
.acad-cm .pk-lnk__chevron {
    width: 20px;
    height: 20px;
    flex: 0 0 auto;
    transition: transform var(--pk-dur-fast) ease;
}

/* Reduced motion holds the chevron still, as the button and nav chevrons do. */
@media (prefers-reduced-motion: reduce) {
    .pk-sec .pk-lnk__chevron,
    .acad-cm .pk-lnk__chevron {
        transition: none;
    }

    .pk-sec .pk-lnk:hover .pk-lnk__chevron,
    .acad-cm .pk-lnk:hover .pk-lnk__chevron {
        transform: none;
    }
}

/* An unlinked label still reads as one; it just does not invite a click. */
.pk-sec .pk-lnk--inert,
.acad-cm .pk-lnk--inert {
    cursor: default;
    opacity: .7;
}

/* ------------------------------------------------------------- copy links */

/*
 * Inline links inside body copy, everywhere in the layer. Without this the
 * theme kit's global accent painted them orange — 482:1343 draws "Parker
 * Seminars" bold Secondary Blue, and that is the academics default. The role
 * token flips to off-white inside the dark and brand skins, where #254CA7
 * would sink into the band. The chalk CTA links (.pk-lnk) are a different
 * object and keep their own colour.
 */
.pk-sec .pk-hd__copy a,
.pk-cg .pk-cg__body a,
.pk-acc .pk-acc__panel-inner a,
.acad-cm .acad-cm__copy a,
.acad-cm .acad-cm__body a {
    color: var(--pk-copy-link-fg, #254CA7);
    font-weight: 700;
    text-decoration: none;
}

.pk-sec .pk-hd__copy a:hover,
.pk-cg .pk-cg__body a:hover,
.pk-acc .pk-acc__panel-inner a:hover,
.acad-cm .acad-cm__copy a:hover,
.acad-cm .acad-cm__body a:hover {
    text-decoration: underline;
}

/* ----------------------------------------------------------------- button */

.pk-sec .pk-btn,
.pk-ctas .pk-btn {
    font-family: var(--pk-sans);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 50px;
    padding: 8px 40px;
    border: 2px solid currentColor;
    border-radius: var(--pk-radius-pill);
    color: var(--pk-link-fg);
    font-weight: 900;
    font-size: var(--pk-button-size);
    line-height: var(--pk-tight);
    letter-spacing: var(--pk-track);
    text-transform: uppercase;
    text-decoration: none;
    align-self: flex-start;
    transition: background-color var(--pk-dur-fast) ease, color var(--pk-dur-fast) ease, filter var(--pk-dur-fast) ease;
}

/*
 * Two classes deep NOT only for the theme floor: the base rule above is
 * `.pk-sec .pk-btn` at (0,2,0), so a one-class `.pk-btn:hover` at (0,1,1)
 * lost the `color` fight and the hover was a solid off-white pill with
 * off-white text — reported on the split band's "Explore all graduate
 * programs" as unreadable on hover. The background applied (the base sets
 * none) while the colour silently did not, which is what made it look like a
 * translucency problem rather than a cascade one.
 */
.pk-sec .pk-btn:hover,
.pk-sec .pk-btn:focus-visible,
.pk-ctas .pk-btn:hover,
.pk-ctas .pk-btn:focus-visible {
    background: var(--pk-link-fg);
    color: var(--pk-rich-blue);
    text-decoration: none;
}

.pk-skin-light .pk-sec .pk-btn:hover,
.pk-sec.pk-skin-light .pk-btn:hover,
.pk-skin-light .pk-sec .pk-btn:focus-visible,
.pk-sec.pk-skin-light .pk-btn:focus-visible {
    color: var(--pk-off-white);
}

/*
 * The NEAREST skin wins. The split band is a light-skinned section (that is
 * its mobile card) holding a brand-skinned panel, and the light rule above
 * matched its button off the section root — off-white text on the off-white
 * hover fill, which is the unreadable hover that got reported. A button
 * inside a re-skinned wrapper takes that wrapper's contract: hover fill is
 * the wrapper's --pk-link-fg (off-white on brand/dark), so the text goes
 * Rich Blue. Same specificity as the light rule, later in the file, on
 * purpose — source order is the tiebreak.
 */
.pk-sec .pk-skin-brand .pk-btn:hover,
.pk-sec .pk-skin-dark .pk-btn:hover,
.pk-sec .pk-skin-brand .pk-btn:focus-visible,
.pk-sec .pk-skin-dark .pk-btn:focus-visible {
    color: var(--pk-rich-blue);
}

.pk-sec .pk-btn--inert,
.pk-ctas .pk-btn--inert {
    cursor: default;
    opacity: .7;
}

/*
 * The two button faces the hero frames draw side by side (1095:10363):
 * SOLID is the Accent Orange pill with off-white text ("Apply Now"), OUTLINE
 * is the base rule's 2px stroke in the skin's link colour ("Request
 * information"). The chevron is an inline SVG at 18px, boxicons'
 * chevron-right, 8px after the label.
 *
 * HOVER is the program nav's (user, 2026-09-22: "match the header nav look"):
 * the pill keeps its orange and brightens 8% over .15s, and the chevron
 * slides 3px right over .18s — not the jump to Light Orange it had first.
 * The translate is the whole transform here (the nav's chevron is a rotated
 * border corner and needs its rotate kept; this one is an SVG). Reduced
 * motion keeps the colour fade and drops the slide.
 */
.pk-sec .pk-btn--solid,
.pk-ctas .pk-btn--solid,
.pk-skin-dark .pk-sec .pk-btn--solid,
.pk-sec.pk-skin-dark .pk-btn--solid {
    background: var(--pk-accent-orange);
    border-color: var(--pk-accent-orange);
    color: var(--pk-off-white);
    gap: 8px;
}

.pk-sec .pk-btn--solid:hover,
.pk-sec .pk-btn--solid:focus-visible,
.pk-ctas .pk-btn--solid:hover,
.pk-ctas .pk-btn--solid:focus-visible,
.pk-sec.pk-skin-dark .pk-btn--solid:hover,
.pk-sec.pk-skin-dark .pk-btn--solid:focus-visible {
    background: var(--pk-accent-orange);
    border-color: var(--pk-accent-orange);
    color: var(--pk-off-white);
    filter: brightness(1.08);
}

.pk-sec .pk-btn__chevron,
.pk-ctas .pk-btn__chevron {
    display: block;
    width: 18px;
    height: 18px;
    flex: 0 0 18px;
    transition: transform var(--pk-dur-nudge) ease;
}

.pk-sec .pk-btn:hover .pk-btn__chevron,
.pk-sec .pk-btn:focus-visible .pk-btn__chevron,
.pk-ctas .pk-btn:hover .pk-btn__chevron,
.pk-ctas .pk-btn:focus-visible .pk-btn__chevron {
    transform: translateX(3px);
}

@media (prefers-reduced-motion: reduce) {
    .pk-sec .pk-btn__chevron,
    .pk-ctas .pk-btn__chevron {
        transition: none;
    }

    .pk-sec .pk-btn:hover .pk-btn__chevron,
    .pk-ctas .pk-btn:hover .pk-btn__chevron {
        transform: none;
    }
}

/*
 * The opener's pair of buttons (1095:10382): 45 apart, 25 under the copy,
 * wrapping when the column is narrow and closing to 20 on phones. The
 * wrapper is also what carries the button faces into a design whose root is
 * not `.pk-sec` — every button rule above names `.pk-ctas .pk-btn` too. On a
 * light ground the outlined pill's hover fills orange with off-white text.
 */
.pk-sec .pk-ctas,
.acad-cm .pk-ctas {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 20px 45px;
    margin-top: 25px;
}

.acad-cm .pk-ctas .pk-btn:hover,
.acad-cm .pk-ctas .pk-btn:focus-visible {
    color: var(--pk-off-white);
}

/*
 * Stacked (tablet and phone — the user wants tablet to BE the phone
 * layout, 2026-09-22): the pair stacks and each pill runs the full measure
 * (the mobile opener frames still draw the old chalk link, so "flex full
 * width" is the call until the designer redraws them). The base rule's
 * `align-self: flex-start` is what keeps a pill at its text width, so it
 * is undone here at the same depth, later in the file.
 */
@media (max-width: 1024px) {
    .pk-sec .pk-ctas,
    .acad-cm .pk-ctas {
        flex-direction: column;
        align-items: stretch;
        gap: 20px;
    }

    .pk-ctas .pk-btn {
        width: 100%;
        align-self: stretch;
    }
}

/* ------------------------------------------------------------ degree info */

/*
 * The degree-info tile (918:10755): fill #E6F2FE, 2px border at Border Blue
 * 15%, radius 8, padding 20, 8px between icon / label / value, 25px between
 * tiles. Label Barlow Bold 15 / 1.2, 5% tracking, uppercase, body at 55%;
 * value Barlow SemiBold 15 / 1.2, charcoal. Drawn by
 * LFCP_Design_Render::facts(); the caller places the list (grid columns, row
 * height) under its own `pk-facts--{modifier}`.
 *
 * Scoped to the LIST, not to `.pk-sec`: Content + Media's root is `.acad-cm`
 * (it predates the shell parts and never took the class), and the first pass
 * of this scoped everything under `.pk-sec` — the hero's tiles were styled,
 * the opener's were bare. The list rule names both roots; the tile rules
 * hang off `.pk-facts`, which is two deep wherever the list is drawn.
 */
.pk-sec .pk-facts,
.acad-cm .pk-facts {
    display: grid;
    gap: 25px;
    margin: 0;
    padding: 0;
}

.pk-facts .pk-fact {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-width: 0;
    margin: 0;
    padding: 20px;
    text-align: center;
    background: var(--pk-fact-bg, #E6F2FE);
    border: 2px solid var(--pk-fact-border, rgba(20, 99, 176, .15));
    border-radius: var(--pk-radius, 8px);
}

.pk-facts .pk-fact__icon {
    display: block;
    width: 24px;
    height: 24px;
    color: var(--pk-rich-blue, #0E1781);
}

.pk-facts .pk-fact__icon svg {
    display: block;
    width: 100%;
    height: 100%;
}

.pk-facts .pk-fact__label {
    margin: 0;
    font-family: var(--pk-sans);
    font-weight: 700;
    font-size: 15px;
    line-height: 1.2;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: rgba(11, 11, 11, .55);
}

.pk-facts .pk-fact__value {
    margin: 0;
    font-family: var(--pk-sans);
    font-weight: 600;
    font-size: 15px;
    line-height: 1.2;
    color: var(--pk-charcoal, #343434);
    overflow-wrap: anywhere;
}

/* ------------------------------------------------------------- two columns */

/*
 * The header-beside-body arrangement shared by §2, §3 and §5. Collapses to one
 * column at 1024px with the header first, which is what every mobile frame
 * shows — and comes free from the markup order being header-then-body, so the
 * query only has to unset the direction.
 */
.pk-sec .pk-split {
    display: flex;
    align-items: center;
    gap: var(--pk-gap-desktop, 50px);
}

.pk-sec .pk-split--header-right {
    flex-direction: row-reverse;
}

/*
 * Equal halves, and `flex-basis: 0` is what makes them equal.
 *
 * These were `flex: 1 1 auto`, which bases each column on its own content —
 * measured on the local site, §3's header took 795px and its accordion column
 * 395px purely because the header has more words. Two sections with identical
 * settings would size differently for no reason an author could see, and no
 * design in the file is proportioned by sentence length.
 *
 * Basis 0 is applied only in the row direction: `.pk-split--stacked` and the
 * ≤1024px media query turn this into a column, where the main axis is height
 * and a basis of 0 would collapse both children.
 */
.pk-sec .pk-split__header,
.pk-sec .pk-split__body {
    min-width: 0;
}

.pk-sec .pk-split:not(.pk-split--stacked) > .pk-split__header,
.pk-sec .pk-split:not(.pk-split--stacked) > .pk-split__body {
    flex: 1 1 0;
}

.pk-sec .pk-split--stacked {
    flex-direction: column;
    align-items: stretch;
}

/*
 * Text Position: Below. The blocks stay first in the DOM whatever this is set
 * to -- reading order should not depend on a layout field -- so painting them
 * after the body is `order`, applied to both children rather than only the one
 * being moved: a lone `order: 1` works until a third child appears, and both
 * these sections already have a link or button that would then be caught by
 * source order instead of by intent.
 */
.pk-split--text-below > .pk-split__header { order: 2; }
.pk-split--text-below > .pk-split__body   { order: 1; }

@media (max-width: 1024px) {
    .pk-sec {
        margin-top: var(--pk-mt-tablet, 50px);
        margin-bottom: var(--pk-mb-tablet, 50px);
        padding: var(--pk-pad-tablet, 100px 30px);
    }

    .pk-sec .pk-split,
    .pk-sec .pk-split--header-right {
        flex-direction: column;
        align-items: stretch;
        gap: var(--pk-gap-tablet, 50px);
    }

    /* Column direction: the main axis is height, so basis returns to auto. */
    .pk-sec .pk-split > .pk-split__header,
    .pk-sec .pk-split > .pk-split__body {
        flex: 0 1 auto;
    }
}

@media (max-width: 767px) {
    .pk-sec {
        margin-top: var(--pk-mt-mobile, 50px);
        margin-bottom: var(--pk-mb-mobile, 50px);
        padding: var(--pk-pad-mobile, 100px 30px);
    }

    .pk-sec .pk-split,
    .pk-sec .pk-split--header-right {
        gap: var(--pk-gap-mobile, 50px);
    }
}

/* ------------------------------------------------------- the section stack */

/* Sections rendered as one group. A FLEX COLUMN specifically: section spacing
   is the sum of two adjacent margins (50 + 50 between the usual pair, 0 + 0
   where a run of bands butts), and only flex siblings ADD margins — block
   siblings collapse them, which silently halves every gap. */

.pk-stack.pk-stack--sections {
    display: flex;
    flex-direction: column;
}

/* Becoming a flex item changes how a section is sized, and these two put it
   back. `max-width` is the load-bearing one: without it a section resolves to
   its own max-content width — the section HEADER is a flex row whose child
   carries the automatic `min-width: auto` — and a section then overflows its
   container instead of fitting it. On mobile that pushed the page from 380px
   to 886px wide, and the faculty carousel was merely where it showed, because
   its cards are `flex-basis: 85%` of whatever width it was handed.
   `width: 100%` rather than `max-width: 100%` on purpose: a section that sets
   its OWN cap (content-media's 1210px) must keep it, and a blanket max-width
   overrides that and widens the desktop layout. An explicit width makes the
   item exactly its container, and the section's own max-width still applies on
   top. `min-width`/`min-height: 0` restore the two flex-item defaults that
   otherwise differ from what the sections computed as block children.
   Verified 2026-09-18 against all three viewports. */

.pk-stack.pk-stack--sections > * {
    width: 100%;
    min-width: 0;
    min-height: 0;
}
