/* ==========================================================================
   lpen-course-grid.css
   LPEN Design System applied to the LearnDash course grid.

   Scope:  /2021-courses/ ONLY — page 2007. A pilot, per the owner
           2026-08-26. Seven other pages carry the same grid and are
           deliberately untouched until this one is signed off:
             /2022-courses/  /2023-courses/  /2024-courses/  /2025-courses/
             /regular-courses/2026-regular-courses/
             /immigration-consultants-lawyers-paralegals/
             /my-lpen-courses/

   Rules of engagement
   -------------------
   - CSS only. Nothing in LearnDash, Design Upgrade, the child theme's
     style.css or any Elementor template is modified. This file is deployed
     to the child theme via POST lpen/v1/asset.
   - lpen-assets/ is enqueued SITE-WIDE, so every selector below is anchored
     on `body.page-id-2007`. deploy.py fails the build on any selector that
     is not — an id anchor is a fact you can grep, where a prefix scoper is a
     transformation you have to trust (CLAUDE.md 18k).
   - `!important` appears only where something else used it first, and each
     occurrence names what it is outbidding. Two sources use it here: the
     child theme's own style.css section 4 (which paints this grid with ~40
     !important declarations) and Design Upgrade for LearnDash.
   - Tokens are LPEN-Design-System.md sections 3 to 7. Do not substitute a
     hex without re-running the contrast check in section 3.4.


   WHO ACTUALLY OWNS THIS GRID — read this before editing
   ------------------------------------------------------
   Four stylesheets paint these cards, and the obvious one is not the one in
   charge. Measured on the live page 2026-08-26:

     1  LearnDash legacy-v1 skin      bootstrap row/cols, ribbon, .btn
     2  Design Upgrade ld3.css        THE CARD. Overrides most of the skin.
     3  child theme style.css §4      ~40 !important: #446996 buttons,
                                      20px/600 #1D1D1F titles, 1em caption
     4  this file

   The single most useful fact: **the card is the COLUMN, not the article.**
   Design Upgrade puts the background, border, radius and `overflow: hidden`
   on `.ld_course_grid` and then flattens `article.thumbnail.course` with
   `border: 0 !important; background: transparent; display: flex !important`.
   Styling the article as the card, which is what it looks like it should be,
   gets you a 1px border that never renders and a second set of corners 4px
   inside the real ones.

   It also already does several things this file would otherwise have to:
   `.ld-course-list-items.row { margin: 0 }`, the article as a flex column
   with `min-height: 100%`, `.caption { flex: 1; display: flex }`, and
   `.ld_course_grid_button { margin-top: auto !important }`.

   And it exposes a `--ldx-*` custom-property API for the parts that are just
   colour and shape, so section 2 remaps those rather than overriding its
   selectors — no specificity war, and it survives a plugin update. Same
   approach as learndash/lpen-learndash.css (CLAUDE.md 18j).


   What this replaces, measured on the live page 2026-08-26
   --------------------------------------------------------
   Three fixed bootstrap columns, a green corner ribbon with a shadow tail
   and a folded-corner pseudo-element, 20px/600 titles in #1D1D1F,
   undifferentiated grey body copy, and a #446996 button with a 7px radius
   that inverts to white on hover. None of those values is in the design
   system.

   Built 2026-08-26.
   ========================================================================== */


/* ==========================================================================
   1. Gate and tokens
   Declared on the page gate, NOT on :root — these names must not leak into
   the other design-system assets, several of which define their own.
   ========================================================================== */

body.page-id-2007 {
	/* navy — brand */
	--lpen-navy-800: #022E48;

	/* action — interactive */
	--lpen-action:       #0F5C96;
	--lpen-action-hover: #0B4465;

	/* neutral */
	--lpen-ink:           #111820;
	--lpen-muted:         #4A5666;
	--lpen-subtle:        #6B7684;
	--lpen-border-strong: #78848F;
	--lpen-border:        #CFD6DD;
	--lpen-surface-2:     #EEF2F5;
	--lpen-white:         #FFFFFF;

	/* feedback — "Enrolled" is a status, so it takes the success pair.
	   Gold is reserved for accreditation and urgency and is never used
	   here (design system 3.1). */
	--lpen-success:    #125E26;
	--lpen-success-bg: #E6F4E9;

	/* focus — purple, a hue used for nothing else in the system */
	--lpen-focus:      #6A3FD4;
	--lpen-focus-halo: #F3F7F9;
	--lpen-focus-ring: 0 0 0 2px var(--lpen-focus), 0 0 0 4px var(--lpen-focus-halo);

	/* type */
	--lpen-font-sans: "Source Sans 3", "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Arial, sans-serif;

	/* space */
	--lpen-space-4:  4px;
	--lpen-space-8:  8px;
	--lpen-space-12: 12px;
	--lpen-space-16: 16px;
	--lpen-space-24: 24px;

	/* radius */
	--lpen-radius-sm: 2px;
	--lpen-radius-md: 4px;
	--lpen-radius-lg: 8px;

	/* elevation — navy-tinted, never neutral black */
	--lpen-elevation-1: 0 1px 3px rgba(1, 32, 50, .08), 0 1px 2px rgba(1, 32, 50, .06);

	/* motion */
	--lpen-duration-fast: 120ms;
	--lpen-ease:          cubic-bezier(.2, 0, .2, 1);

	/* the price badge overhangs the thumbnail by this much. The two numbers
	   are load-bearing arithmetic — see section 6. */
	--lpen-cg-badge-h:   28px;
	--lpen-cg-badge-gap: 12px;
}


/* ==========================================================================
   2. Design Upgrade's own token API
   These are declared on its :root at (0,1,0); the page gate is (0,1,1), so
   this wins with no !important and no selector duplication, and a Design
   Upgrade update cannot silently undo it.

   Everything here is colour and shape only. Anything structural has to be
   done in the sections below, because there is no token for it.
   ========================================================================== */

body.page-id-2007 {
	/* the card: a 1px decorative border and radius-lg, per design system
	   4 and 8.6, against the plugin default 2px #ddd at 6px */
	--ldx-grid-item-border-radius: var(--lpen-radius-lg);
	--ldx-grid-item-border-width:  1px;
	--ldx-grid-item-border-color:  var(--lpen-border);

	/* the price ribbon becomes a navy badge. Green is a feedback colour in
	   this system and a price is not feedback. */
	--ldx-grid-ribbon-bg-color:            var(--lpen-navy-800);
	--ldx-grid-ribbon-text-color:          var(--lpen-white);
	--ldx-grid-ribbon-free-bg-color:       var(--lpen-navy-800);
	--ldx-grid-ribbon-free-text-color:     var(--lpen-white);
	--ldx-grid-ribbon-custom-bg-color:     var(--lpen-navy-800);
	--ldx-grid-ribbon-custom-text-color:   var(--lpen-white);

	/* "Enrolled" is a status, not a price: the success pair on a light
	   surface, so it reads as a different class of information */
	--ldx-grid-ribbon-enrolled-bg-color:   var(--lpen-success-bg);
	--ldx-grid-ribbon-enrolled-text-color: var(--lpen-success);
}


/* ==========================================================================
   3. The grid
   Bootstrap's flex row and fixed `col-md-4` become one auto-fill grid, per
   design system section 7: catalogue grids use
   `repeat(auto-fill, minmax(280px, 1fr))` rather than a fixed column count,
   so they degrade gracefully regardless of container width. At the live
   1132px container that is four columns; it is one below 600px, with no
   media query.
   ========================================================================== */

body.page-id-2007 .ld-course-list-content .ld-course-list-items.row {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
	gap: var(--lpen-space-24);
	margin: 0;
}

/* (0,4,1). Design Upgrade's per-column margin rules are (0,4,0) — a
   percentage gutter per nth-child, which a grid does not need and which
   would fight `gap`. This has to outbid them. */
body.page-id-2007 .ld-course-list-content .ld-course-list-items .ld_course_grid {
	/* `col-sm-8 col-md-4` sets flex-basis and max-width; both are
	   meaningless in a grid and max-width would still clamp the track */
	width: auto;
	max-width: none;
	min-width: 0;
	padding: 0;
	margin: 0;
	display: flex;
}


/* ==========================================================================
   4. The card
   This is the COLUMN — see the note at the top of the file. Design system
   8.6: white surface, 1px border, radius-lg, elevation-1 on hover only
   because the whole card is a link (section 9).
   ========================================================================== */

body.page-id-2007 .ld-course-list-content .ld-course-list-items .ld_course_grid {
	font-family: var(--lpen-font-sans);
	/* the plugin ships `transition: all .15s ease`, which would animate
	   layout properties too */
	transition:
		border-color var(--lpen-duration-fast) var(--lpen-ease),
		box-shadow   var(--lpen-duration-fast) var(--lpen-ease);
}

body.page-id-2007 .ld-course-list-content .ld-course-list-items .ld_course_grid:hover {
	border-color: var(--lpen-border-strong);
	box-shadow: var(--lpen-elevation-1);
}


/* ==========================================================================
   5. The article — flex column and source order
   Design Upgrade already makes this a flex column with `min-height: 100%`
   and strips its border and background. All that is left is the source
   order: LearnDash writes the ribbon FIRST, before the thumbnail, which is
   what forces it to be absolutely positioned. Reordering here lets it become
   a badge that sits in flow (section 6) instead.

   Anything unrecognised lands at order 2 — after the media, before the
   badge — rather than jumping above the thumbnail.
   ========================================================================== */

body.page-id-2007 .ld-course-list-items .ld_course_grid .thumbnail.course {
	/* the stretched link in section 9 must resolve against the card, so
	   nothing between it and the card may be positioned */
	position: static;
	width: 100%;
}

body.page-id-2007 .ld-course-list-items .ld_course_grid .thumbnail.course > * {
	order: 2;
}

body.page-id-2007 .ld-course-list-items .ld_course_grid .thumbnail.course > a,
body.page-id-2007 .ld-course-list-items .ld_course_grid .thumbnail.course > .ld_course_grid_video_embed {
	order: 1;
}

body.page-id-2007 .ld-course-list-items .ld_course_grid .thumbnail.course > .ribbon {
	order: 3;
}

body.page-id-2007 .ld-course-list-items .ld_course_grid .thumbnail.course > .caption {
	order: 4;
}


/* ==========================================================================
   6. Thumbnail and price badge
   ========================================================================== */

/* The media link is aria-hidden with tabindex="-1" in LearnDash's own
   markup, so it is not a second tab stop. Left as it is. */
body.page-id-2007 .ld-course-list-items .ld_course_grid .thumbnail.course > a {
	display: block;
	position: static;
	aspect-ratio: 16 / 9;
	overflow: hidden;
	background-color: var(--lpen-surface-2);
	line-height: 0;
}

body.page-id-2007 .ld-course-list-items .ld_course_grid .thumbnail.course > a > img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	margin: 0;
	box-shadow: none;
	border-radius: 0;
}

/* The ribbon becomes a badge. It stays in flow as a flex item and is pulled
   back up over the bottom of the thumbnail by a negative top margin; the
   bottom margin gives that space back, so the caption still starts exactly
   where the image ends:
       -(badge-h + gap) + badge-h + gap = 0
   Both numbers are tokens in section 1 and must stay in step with the
   badge's own line-height and padding, which is what makes badge-h 28px.

   Bottom RIGHT, not left: the cover art on this catalogue has the course
   title burned into the left third of the image (CLAUDE.md 18j, 18p), so a
   badge on the left sits on top of drawn lettering.

   Colours come from the tokens in section 2, not from here. */
body.page-id-2007 .ld-course-list-items .ld_course_grid .thumbnail.course .ribbon {
	position: relative;
	z-index: 2;
	align-self: flex-end;
	left: auto;
	right: auto;
	top: auto;
	margin: calc(-1 * (var(--lpen-cg-badge-h) + var(--lpen-cg-badge-gap)))
	        var(--lpen-cg-badge-gap)
	        var(--lpen-cg-badge-gap)
	        var(--lpen-cg-badge-gap);
	padding: var(--lpen-space-4) var(--lpen-space-8);
	font-size: 14px;
	line-height: 20px;
	font-weight: 700;
	border-radius: var(--lpen-radius-sm);
	box-shadow: none;
	text-shadow: none;
}

/* the folded-corner tail, which only made sense on a ribbon */
body.page-id-2007 .ld-course-list-items .ld_course_grid .thumbnail.course .ribbon:before {
	content: none;
}

/* a light surface needs its own edge to hold the shape */
body.page-id-2007 .ld-course-list-items .ld_course_grid .thumbnail.course .ribbon.enrolled {
	box-shadow: inset 0 0 0 1px var(--lpen-success);
}


/* ==========================================================================
   7. Caption — the reading order
   `display: contents` on .entry-content promotes its three paragraphs to
   flex items of .caption, which is the only way to lift the date-and-hours
   line ABOVE the title without touching the markup. That gives the same
   meta line / title / detail hierarchy as the native cards already shipped
   on /hrcpd/ and /ontario-paralegal-cpd-courses/.

   The three paragraphs are LearnDash's course grid short description, and
   on this page all 25 cards carry exactly three, in this order:
     1  session date and length     2  description     3  instructors
   A card with a different shape degrades to plain stacked paragraphs.
   ========================================================================== */

body.page-id-2007 .ld-course-list-items .ld_course_grid .thumbnail.course .caption {
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
	gap: var(--lpen-space-12);
	/* Design Upgrade sets this relative. It has to be static or the
	   stretched link in section 9 covers the caption only and the whole
	   thumbnail stays dead to the click. Nothing inside is positioned. */
	position: static;
	/* !important outbids the child theme's `padding: 1em 1em 1em !important` */
	padding: var(--lpen-space-24) !important;
	color: var(--lpen-ink);
}

body.page-id-2007 .ld-course-list-items .ld_course_grid .thumbnail.course .caption .entry-content {
	display: contents;
}

/* !important outbids the legacy-v1 skin's `margin: 15px 0 0 !important` */
body.page-id-2007 .ld-course-list-items .ld_course_grid .thumbnail.course .caption p {
	margin: 0 !important;
	width: auto !important;
}

/* 1 — session date and length.
   The negative bottom margin pulls the title up against it: the meta line
   labels the title, so the two are one group, and the 12px gap belongs
   between groups. !important because the skin's margins are !important. */
body.page-id-2007 .ld-course-list-items .ld_course_grid .thumbnail.course .caption .entry-content p:nth-of-type(1) {
	order: 1;
	margin-bottom: -6px !important;
	font-size: 12px;
	line-height: 1.3;
	font-weight: 700;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: var(--lpen-muted);
}

/* 2 — the course title.
   Deliberately NOT clamped to two lines, against design system 9.5. Course
   titles here run to four lines at this card width and the title is the
   product for a regulated buyer; hiding half of it to tidy the grid is the
   wrong trade. Nothing needs the clamp for alignment — grid stretch
   equalises the row and the button is pinned to the bottom. */
body.page-id-2007 .ld-course-list-items .ld_course_grid .thumbnail.course .caption .entry-title {
	order: 2;
	/* !important outbids Design Upgrade's `margin-bottom: 15px !important` */
	margin: 0 !important;
	font-size: 18px !important;              /* child theme: 20px !important */
	line-height: 1.35 !important;
	font-weight: 700 !important;             /* child theme: 600 !important */
	color: var(--lpen-navy-800) !important;  /* child theme: #1D1D1F !important */
	letter-spacing: -.005em;
	transition: color var(--lpen-duration-fast) var(--lpen-ease);
}

body.page-id-2007 .ld-course-list-items .ld_course_grid:hover .thumbnail.course .caption .entry-title {
	color: var(--lpen-action) !important;
}

/* 3 — description */
body.page-id-2007 .ld-course-list-items .ld_course_grid .thumbnail.course .caption .entry-content p:nth-of-type(2) {
	order: 3;
	font-size: 15px;
	line-height: 1.55;
	color: var(--lpen-muted);
}

/* 4 — instructors. Tertiary, so `subtle`, which the design system floors at
   14px — do not take this smaller. */
body.page-id-2007 .ld-course-list-items .ld_course_grid .thumbnail.course .caption .entry-content p:nth-of-type(3) {
	order: 4;
	font-size: 14px;
	line-height: 1.4;
	color: var(--lpen-subtle);
}


/* ==========================================================================
   8. Button
   Design system 8.1 primary: `action` fill, white label, radius-md, 44px
   minimum, weight 600. The child theme paints this button #446996 and
   inverts it to white on hover through ~10 !important declarations, so
   every property it names has to be outbid property by property.
   ========================================================================== */

body.page-id-2007 .ld-course-list-items .ld_course_grid .thumbnail.course .caption .ld_course_grid_button {
	order: 5;
	/* auto top margin pins the button to the bottom of the card, so every
	   button in a row lines up whatever the copy above it does. Design
	   Upgrade already does this; the !important is for the legacy-v1 skin's
	   `margin: 5px 0 !important`. */
	margin: auto 0 0 !important;
	padding-top: var(--lpen-space-8);
	width: 100%;
}

body.page-id-2007 .ld-course-list-items .ld_course_grid .thumbnail.course .caption .ld_course_grid_button a.btn {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	min-height: 44px;
	padding: var(--lpen-space-8) var(--lpen-space-24);
	background: var(--lpen-action) !important;
	color: var(--lpen-white) !important;
	border: 0 !important;
	border-radius: var(--lpen-radius-md) !important;
	font-family: var(--lpen-font-sans);
	font-size: 16px !important;
	font-weight: 600 !important;
	line-height: 1.25;
	white-space: normal;
	text-align: center;
	text-decoration: none !important;
	box-shadow: none;
	transition: background-color var(--lpen-duration-fast) var(--lpen-ease);
}

/* The whole card is the hover target, so the button follows the card rather
   than only its own 44px. */
body.page-id-2007 .ld-course-list-items .ld_course_grid:hover .thumbnail.course .caption .ld_course_grid_button a.btn,
body.page-id-2007 .ld-course-list-items .ld_course_grid .thumbnail.course .caption .ld_course_grid_button a.btn:hover {
	background: var(--lpen-action-hover) !important;
	color: var(--lpen-white) !important;
	border: 0 !important;
}


/* ==========================================================================
   9. One card, one link
   Design system 8.6 and 9.5: if the whole card is clickable it is ONE link
   with ONE accessible name containing the course title.

   That is already almost true here — LearnDash gives the thumbnail link
   `aria-hidden` and `tabindex="-1"`, and the button carries
   `aria-label="More Info / Buy: <course title>"`. Stretching the button's
   anchor over the card makes the visual affordance match the tab order
   instead of contradicting it.

   The overlay resolves against `.ld_course_grid`, which the bootstrap column
   rule already makes `position: relative`. That only works because sections
   5 and 7 set the article and the caption back to `position: static` —
   otherwise the overlay stops at the caption and the thumbnail, a third of
   the card, stays dead to the click. Verified by hit-testing a 5x5 grid of
   points per card, not by reading the CSS.

   The cost, stated: text inside the card can no longer be selected. That is
   the accepted trade for a card-as-link (CLAUDE.md 18k).
   ========================================================================== */

body.page-id-2007 .ld-course-list-items .ld_course_grid .thumbnail.course .caption .ld_course_grid_button a.btn:after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 3;
}

/* Fallback ring, and the safe default: this is what renders where :has() is
   unsupported. The enhancement below moves it to the card. */
body.page-id-2007 .ld-course-list-items .ld_course_grid .thumbnail.course .caption .ld_course_grid_button a.btn:focus-visible {
	outline: none;
	box-shadow: var(--lpen-focus-ring);
}

@supports selector(:has(*)) {
	body.page-id-2007 .ld-course-list-items .ld_course_grid .thumbnail.course .caption .ld_course_grid_button a.btn:focus-visible {
		box-shadow: none;
	}

	/* The ring belongs on the thing that is actually clickable.
	   Do NOT add `overflow: visible` here to "let the ring out". An
	   element's own box-shadow is never clipped by its own overflow — only
	   its descendants are — so the ring already renders in full, and
	   un-clipping the card on focus makes the thumbnail's rounded corners
	   snap square for as long as it is focused. Tried, seen, reverted. */
	body.page-id-2007 .ld-course-list-items .ld_course_grid:has(.ld_course_grid_button a.btn:focus-visible) {
		border-color: var(--lpen-action);
		box-shadow: var(--lpen-focus-ring);
	}
}


/* ==========================================================================
   10. Narrow screens
   The auto-fill grid already collapses to one column below ~600px, so this
   only relaxes the card padding.
   ========================================================================== */

@media (max-width: 599px) {
	body.page-id-2007 .ld-course-list-content .ld-course-list-items.row {
		gap: var(--lpen-space-16);
	}

	body.page-id-2007 .ld-course-list-items .ld_course_grid .thumbnail.course .caption {
		padding: var(--lpen-space-16) !important;
	}
}


/* ==========================================================================
   11. Reduced motion
   Kill the motion, not the transform — CLAUDE.md 18c records a reduced-motion
   block that cancelled a transform doing layout work and parked the skip link
   on screen. Nothing here transforms; only durations collapse.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
	body.page-id-2007 .ld-course-list-content .ld-course-list-items .ld_course_grid,
	body.page-id-2007 .ld-course-list-items .ld_course_grid .thumbnail.course .caption .entry-title,
	body.page-id-2007 .ld-course-list-items .ld_course_grid .thumbnail.course .caption .ld_course_grid_button a.btn {
		transition-duration: 1ms;
	}
}
