/**
 * design-system.css - LandboUngdom reusable components
 *
 * Handle: egovt-child-ds. Depends on egovt-child-tokens.
 *
 *   tokens.css
 *   design-system.css   <- we are here
 *   restyle.css
 *
 * ==========================================================================
 * THE HOUSE RULE, AND IT IS THE ONLY ONE THAT MATTERS
 * ==========================================================================
 *
 *   A COMPONENT IN THIS FILE NEVER SETS A FILL.
 *
 * No `background-color`. No `color` with a value of its own. A component sets
 * radius, padding, aspect ratio, layout and type role - the things that are the
 * same whatever colour the box is - and lets colour arrive from two places:
 *
 *   1. Elementor's own background / text-colour controls on that element, which
 *      the client sets per instance in the editor, and which always win because
 *      Elementor prints them later and more specifically than this file.
 *   2. Inheritance. `color: inherit` and `currentColor` mean a card's title,
 *      body copy, chip and rule all follow whatever the client set once on the
 *      card, with no second control to keep in sync.
 *
 * WHY. The same card component appears in the Figma file with a dark green body
 * and pale green text on the homepage (node 1:45), and with a pink body and
 * dark red text on the Frivillige page (node 1:112) - identical geometry, every
 * fill different, and the whole page behind it blue instead of cream. If this
 * file hardcoded green, that second page would need a second component, then a
 * third, and the client could not recolour anything without a developer.
 *
 * So: if you are about to write a hex, or a var(--lu-*) colour, in this file -
 * stop. It belongs in the Elementor Kit or on the element in the editor.
 *
 * TWO NARROW EXCEPTIONS, BOTH DELIBERATE
 *
 * 1. Structural colour. The 1px rule between list items is `currentColor` at
 *    30%, and the date chip inverts the card. Both follow whatever the client
 *    picked. That is inheritance, not a fill.
 *
 * 2. FILL PAIRINGS - `lu-fill-*` in section 10.
 *
 *    Some widgets have no Elementor control for the surface we need to colour.
 *    `ova_blog` is the case in point: it exposes controls for the title, the
 *    read-more link and the date chip, but NOT for `.evgovt-content`, the card
 *    body itself. Checked in ova-framework/ova-elementor/widgets/ova_blog.php -
 *    there is no selector for it at any control.
 *
 *    So for those, the fill is chosen with a class instead of a colour picker:
 *    `lu-fill-primary`, `lu-fill-pink`, `lu-fill-red`, and so on. Each is a
 *    PAIRING taken from the design - a background, the foreground that belongs
 *    on it, and the accent used for headings inside it - and each value is
 *    still `var(--lu-*)`, which is still an alias of the Kit. Change "Primaer"
 *    in Site Settings and every lu-fill-primary card follows.
 *
 *    This is a better answer than a free colour picker here, not a worse one.
 *    The Figma file does not use arbitrary fills either: it uses a handful of
 *    approved combinations, and pale green text belongs on dark green, dark red
 *    on pink. A picker would let someone put pink on pink. A pairing cannot.
 *
 *    Where the widget DOES have a control - a section background, a button
 *    colour, a heading colour - use the control, not a variant class.
 *
 * ==========================================================================
 * HOW A COMPONENT IS APPLIED
 * ==========================================================================
 *
 * Type the class into Elementor's Advanced -> CSS Classes field on the section,
 * column or widget. Nothing here is applied automatically, which is deliberate:
 * an opt-in class cannot break a page nobody has looked at yet, and there are
 * 279 Elementor documents on this site.
 *
 * Where a component dresses a third-party widget (`ova_blog`, `ova_events_cat`)
 * the class goes on the widget and the rules reach its internals by its own
 * stable class names. A PHP template override only where the plugin's markup
 * cannot carry the design at all, and then a template of this theme's own rather
 * than a copy of the plugin's - HANDOFF section 9 issue 4 records what stale
 * copies do. The listing, hub and people templates are the three; the people
 * one hands back to the plugin's own file wherever `lu-people` is not set.
 *
 * ==========================================================================
 * SPECIFICITY BUDGET
 * ==========================================================================
 *
 * Elementor's cascade, verified against the rendered page:
 *
 *   .elementor-widget-x .y                    (0,2,0)  per-widget sheets, in <head>
 *   THIS FILE                                          aim for (0,2,0)-(0,3,0)
 *   .elementor-NNNN .elementor-element-xxxxx  (0,3,0)  per-element, inline in <body>
 *
 * Sitting in that gap is the point. We beat the plugin defaults; the client's
 * own edits in the editor beat us. A `!important` here would break that and is
 * not allowed - if a rule will not land, the fix is clearing the stale value on
 * the widget in Elementor, not forcing it from here.
 */


/* ==========================================================================
   1. Type roles
   ==========================================================================
   For text inside widget markup that the Kit's h1-h4 rules cannot reach, or
   reach with the wrong value. Family and weight come from the Kit's typography
   globals via the tokens; only size, line-height and tracking are set here.
   ========================================================================== */

.lu-h1, .lu-h2, .lu-h3, .lu-h4 {
	font-family: var(--lu-font-display);
	font-weight: 500;
}

.lu-h1 { font-size: var(--lu-type-h1-size); line-height: var(--lu-type-h1-lh); letter-spacing: var(--lu-type-h1-ls); }
.lu-h2 { font-size: var(--lu-type-h2-size); line-height: var(--lu-type-h2-lh); letter-spacing: var(--lu-type-h2-ls); }
.lu-h3 { font-size: var(--lu-type-h3-size); line-height: var(--lu-type-h3-lh); letter-spacing: var(--lu-type-h3-ls); }
.lu-h4 { font-size: var(--lu-type-h4-size); line-height: var(--lu-type-h4-lh); letter-spacing: var(--lu-type-h4-ls); }

/* "Broedtekst" and "Mellemrubrik" - the same size, distinguished by weight. */
.lu-body   { font-family: var(--lu-font-body); font-size: var(--lu-type-body-size); line-height: var(--lu-type-body-lh); font-weight: 400; }
.lu-subhed { font-family: var(--lu-font-body); font-size: var(--lu-type-body-size); line-height: var(--lu-type-body-lh); font-weight: 700; }


/* ==========================================================================
   2. lu-section-heading
   ==========================================================================
   The centred H2 that opens a band of content - "Seneste nyheder og
   begivenheder" (node 1:37), "Er du frivillig?" (node 1:123). Orange on the
   homepage, dark red on the Frivillige page, so no colour here.

   Applied to: ova_heading, or a plain heading widget.
   ========================================================================== */

/**
 * The `ova_heading` widget renders `<div class="ova-heading"><h3 class="title">`,
 * NOT an .elementor-heading-title - and as an h3, which the Kit sizes at 36px.
 * The design's section heading is H2, so the size has to be stated here.
 */
.lu-section-heading .ova-heading .title,
.lu-section-heading .elementor-heading-title,
.lu-section-heading > .elementor-widget-container > h2 {
	font-family: var(--lu-font-display);
	font-size: var(--lu-type-h2-size);
	font-weight: 500;
	line-height: var(--lu-type-h2-lh);
	letter-spacing: var(--lu-type-h2-ls);
	text-align: center;
}

.lu-section-heading,
.lu-section-heading .ova-heading {
	text-align: center;
}

/**
 * lu-section-intro - the paragraph under that heading.
 *
 * Three things, and they are one decision: a centred lead needs a MEASURE, or
 * it runs the full 1320px container and stops being a paragraph. 660px is the
 * frame (node 1:124) and about 55 characters at the H4 size, which is where a
 * display face stops being comfortable to read across.
 *
 * The mobile frame (1:275) drops both the cap and the centring - at 362px a
 * measure is whatever the screen is, and six centred lines read as a poem. So
 * this is not "centred text that also has a max-width"; it is one role that
 * behaves differently at the two widths.
 *
 * Type comes from lu-lead, which this is always used with. Nothing here sets a
 * size.
 */
.lu-section-intro {
	max-width: 660px;
	margin-inline: auto;
	text-align: center;
}

@media (max-width: 767px) {
	.lu-section-intro {
		max-width: none;
		text-align: left;
	}
}


/* ==========================================================================
   3. lu-card
   ==========================================================================
   Media on top, coloured body beneath. The single most reused shape in the
   design: news teasers, the toolbox tiles, the events panel.

       +---------------------+  <- 24px radius, top corners only
       |       media         |     aspect-ratio 427/263, object-fit cover
       +---------------------+
       | [chip]              |  <- optional date chip
       | Title           H4  |
       |                     |
       | Laes mere ->    16  |
       +---------------------+  <- square. Never rounded.

   Applied to: the ova_blog / ova_events_cat widget, or a column holding an
   image + text stack.
   ========================================================================== */

.lu-card {
	--lu-card-radius: var(--lu-radius-card);

	/**
	 * THE FOUR THINGS THE TWO CARD SIZES DIFFER BY, and nothing else.
	 *
	 * There are two cards in the design, not one. The news teaser (node 1:47) has
	 * a 427/263 photograph and an H4 title; the toolbox tile on /for-frivillige/
	 * (node 1:112) has a 427/321 photograph and an H3 one, and starts its body
	 * with a padding rather than with a chip straddling the media edge.
	 *
	 * Everything else about them is identical - the radius, the square bottom, the
	 * side padding, the read-more sitting one card-padding above the baseline - so
	 * the variant is four custom properties rather than a second component. These
	 * are the defaults, which are the news card; lu-card-lg below is the tile.
	 */
	--lu-card-title-size: var(--lu-type-h4-size);
	--lu-card-title-lh:   var(--lu-type-h4-lh);
	--lu-card-title-ls:   var(--lu-type-h4-ls);

	/**
	 * The read-more's weight, and the two cards really do differ here - this is
	 * measured, not tidied. On the news card (node 1:49) "Laes mere ->" is
	 * GT_Era_Text:Regular, the Broedtekst role, the same as the copy above it.
	 * On the toolbox tile (node 1:116) it is GT_Era_Text:Bold - Mellemrubrik.
	 * DESIGN.md's type table files links under Broedtekst, so the default stays
	 * there and the tile is the stated exception.
	 */
	--lu-card-link-weight: 400;

	/* The whole gap from the title down to the read-more - see the title rule. */
	--lu-card-title-gap: 32px;

	/**
	 * Zero, and load-bearing at zero: it is what lets the date chip straddle the
	 * media's bottom edge. On a card with a chip the top inset is the chip's own,
	 * not the body's. A card WITHOUT a chip has to put it back.
	 */
	--lu-card-pad-top: 0px;
}

/**
 * lu-card-lg - the toolbox tile.
 *
 * Measured off frame 1:105, card 1:112: 427 x 551 with the media 58.33% of it,
 * so 427/321 rather than the news card's 427/263, and the title at H3 where the
 * news card is at H4. Both Figma frames agree, desktop and mobile - the tile
 * does not step down, the same way no card title does.
 *
 * The 20px title gap is the frame too: the title's line box ends around y379
 * and the copy under it starts at y401. The news card's 32 would read as a hole
 * under a title half again as large.
 */
.lu-card-lg {
	--lu-card-ratio:      427 / 321;
	--lu-card-title-size: var(--lu-type-h3-size);
	--lu-card-title-lh:   var(--lu-type-h3-lh);
	--lu-card-title-ls:   var(--lu-type-h3-ls);
	--lu-card-title-gap:  20px;
	--lu-card-pad-top:    var(--lu-card-pad);
	--lu-card-link-weight: 700;        /* Mellemrubrik - node 1:116 */
}

/* A card over two tracks (lu-span-2) is twice as wide, so at the card's own
 * ratio its photo was as tall as a screen. From the tablet up it is 2:1 - the
 * photo stays a band, and the row takes the height of what sits beside it.
 * Om LandboUngdom's "Mød hovedbestyrelsen". On a phone the row stacks and the
 * card is one track wide again, so the ratio goes back. */
@media (min-width: 768px) {
	.lu-card.lu-span-2 {
		--lu-card-ratio: 2 / 1;
	}
}

/* Media -------------------------------------------------------------------
 * The radius goes on BOTH the wrapper and the img. The wrapper alone is not
 * enough because ova_blog's image is lazy-loaded and swaps its own src, and the
 * img alone is not enough because a broken or missing image leaves a square
 * placeholder box behind it.
 */
/**
 * THE RATIO GOES ON THE BOX, NOT ON THE IMAGE.
 *
 * It used to be on the `img`, where it never once applied: WP Smush's lazy-load
 * CSS carries
 *   .lazyload, .lazyloading { aspect-ratio: var(--smush-image-aspect-ratio) !important }
 * and every card image is a `.lazyload`. So the media box has been taking the
 * FILE's proportions - 560/373 on the generated size, 284px tall where the
 * design wants 263 - and the card's whole vertical layout was built on top of
 * that. Nothing in this file could have out-ranked it; moving the ratio one
 * level up to the wrapper, which is not a `.lazyload`, means nothing has to.
 *
 * With the wrapper's height definite, the img's `height: 100%` wins over its own
 * aspect-ratio (a box with both dimensions resolved ignores it), so Smush's
 * !important becomes moot rather than contested.
 */
.lu-card .post-media,
.lu-card .lu-card__media {
	display: block;
	overflow: hidden;
	aspect-ratio: var(--lu-card-ratio);
	border-radius: var(--lu-card-radius);
}

/* A linked image: Elementor wraps it in an inline-block <a> sized to the
 * picture, so the img's 100% height stopped at the picture's own height and
 * left a band of the card's fill under it. The link fills the media box. */
.lu-card .lu-card__media a {
	display: block;
	height: 100%;
}

.lu-card .post-media img,
.lu-card .lu-card__media img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	border-radius: var(--lu-card-radius);
}

/* Body --------------------------------------------------------------------
 * `color: inherit` is doing real work: it means the client sets the text colour
 * once, on the card, and the title, the copy and the read-more link all follow.
 * The background is not set at all - Elementor's own control owns it.
 */
/**
 * `padding-block-start: 0` is load bearing - it is what lets the date chip
 * straddle the media's bottom edge (below). The card's top inset is the chip's
 * own, not the body's.
 *
 * The bottom is --lu-card-pad less one descender, and that is the whole trick
 * behind the row's last line: the events panel's final RULE sits --lu-card-pad
 * above its card's bottom edge, and this card has to put a BASELINE there. A
 * rule is a line and type is a box, so the two differ by the drop from the line
 * box to the baseline - 5px for the body role, whose 20px line is exactly the
 * face's 15/5 ascent and descent with no half-leading. tools/verify.js asserts
 * the two land together, so this cannot drift silently if the face changes.
 */
.lu-card .evgovt-content,
.lu-card .lu-card__body {
	padding: var(--lu-card-pad-top) var(--lu-card-pad) calc(var(--lu-card-pad) - 5px);
	color: inherit;
}

/* Date chip ---------------------------------------------------------------
 * A pale block behind the date, CENTRED ON THE MEDIA'S BOTTOM EDGE - half over
 * the photograph, half over the coloured body. On node 1:48 it is 32 tall at
 * y 247 with the body starting at 263: sixteen above the line and sixteen
 * below. That straddle is the shape; a chip sitting wholly inside the body is a
 * different card.
 *
 * Kept in normal flow rather than absolutely positioned, so a card with no
 * image still lays out. The lift is half its own height, written from the type
 * rather than as a literal 16 so the chip cannot come off the line if the body
 * role is ever re-sized.
 */
.lu-card .post-meta-date,
.lu-card .lu-card__chip {
	display: inline-block;
	/**
	 * ...and `inline-block` is not enough on its own here.
	 *
	 * The body is a flex column (section 17, so the read-more can be pinned to
	 * the bottom), and a flex item is BLOCKIFIED - `display: inline-block`
	 * computes to `block`, and the chip stretched its pale ground across the
	 * whole card. The title and the read-more want that full width; the chip
	 * wants to be the size of the date inside it, so it opts out of the stretch
	 * on its own rather than the container turning it off for everyone.
	 */
	align-self: flex-start;
	margin-block-start: calc((var(--lu-type-body-lh) + 12px) / -2);
	margin-block-end: var(--lu-card-pad);   /* chip 279 to title 303 on the frame */
	padding: 6px 14px;
	font-family: var(--lu-font-body);
	font-size: var(--lu-type-body-size);
	line-height: var(--lu-type-body-lh);
}

/* Title -------------------------------------------------------------------
 * ova_blog renders this as an <h2>. That is defensible markup, but the Kit
 * styles every h2 at 48px, which is a section heading, not a card title. This
 * is the case the --lu-type-* tokens exist for. Matched at (0,2,0) so the
 * client can still set a per-widget size in Elementor and win.
 */
/* theme.css owns this at (0,4,2):
 *   .blog-grid article.post-wrap .post-title h2.post-title { font-size:30px }
 * so the selector has to reach the same shape. It still loses to Elementor's
 * per-element rules, which is what keeps the widget's own controls working. */
/**
 * The third shape is an Elementor HEADING WIDGET carrying the class, where the
 * class lands on the widget wrapper and the type has to be set one level in -
 * on `.elementor-heading-title`, against the Kit's own `h2`/`h3` rule. Same
 * reasoning, and the same pair of selectors, as lu-section-heading in section 2.
 */
body .lu-card article.post-wrap .post-title h2.post-title,
.lu-card .lu-card__title,
.lu-card .lu-card__title .elementor-heading-title {
	/* The whole gap down to the read-more, in one place. It used to be 12 here
	 * plus theme.css's 20 on the footer, and that 20 disappeared the moment the
	 * footer's margin became `auto` - an auto margin replaces the edge it is on,
	 * it does not add to it. A minimum gap has to live on the element ABOVE. */
	margin: 0 0 var(--lu-card-title-gap);
	font-family: var(--lu-font-display);
	font-size: var(--lu-card-title-size);
	font-weight: 500;
	line-height: var(--lu-card-title-lh);
	letter-spacing: var(--lu-card-title-ls);
	color: inherit;

	/**
	 * DANISH COMPOUND NOUNS DO NOT FIT A NARROW CARD, and there is no space in
	 * them for the browser to break at.
	 *
	 * "Landsorganisation" is one word ~366px wide at the H3 size. The design
	 * draws it in a 427px card and it fits; between 768 and about 1200 the same
	 * three-track row gives each card 227-337px, and the word ran out of the
	 * card and off the page - 2px of horizontal overflow at 360, and up to 139px
	 * past the card's edge at 768. Invisible at both design widths, which is
	 * exactly the failure DESIGN.md's "check between the breakpoints" is about.
	 *
	 * Both properties, because they do different jobs: `hyphens` breaks the word
	 * properly, at a syllable and with a hyphen, wherever the browser has Danish
	 * patterns (the document is lang="da-DK"); `overflow-wrap` is the floor that
	 * guarantees it breaks SOMEWHERE when it does not. Neither does anything to
	 * a title that fits, so the news cards are untouched.
	 */
	overflow-wrap: break-word;
	hyphens: auto;
}

/* The wrapper itself keeps no margin of its own - the heading inside carries
 * the gap, and Elementor's widget wrapper would otherwise add to it. */
.lu-card .lu-card__title {
	margin-block: 0;
}

/**
 * A LINKED CARD TITLE OR READ-MORE MUST INHERIT ITS TYPE, NOT RE-STATE IT.
 *
 * The Kit publishes its "text" typography role onto every anchor on the site:
 *
 *   .elementor-kit-4 a { font-family: var(--e-global-typography-text-font-family);
 *                        font-size: …; font-weight: …; line-height: … }
 *
 * at (0,1,1). That is reasonable for body copy, and wrong inside a heading: a
 * card title wrapped in a link came out GT Era Text Regular at the heading's
 * size, because the `h3` said Display Medium and the `a` inside it then said
 * Broedtekst. The same rule flattened the bold read-more back to 400 - the
 * `<p>` was 700 and the anchor holding the words was not.
 *
 * Both bugs are invisible until a card's title or read-more is actually a link,
 * which is why they surfaced on the toolbox tiles and not on the news cards.
 *
 * Elementor half-fixes this itself for heading widgets -
 * `.elementor-widget-heading .elementor-heading-title[class*="elementor-size-"] > a`
 * inherits font-size and line-height, but not family or weight. This finishes
 * the same thought, and states every inherited property rather than using the
 * `font` shorthand, which would also reset font-style and font-variant.
 */
body .lu-card article.post-wrap .post-title a,
.lu-card .lu-card__title a,
.lu-card .lu-card__link a {
	font-family: inherit;
	font-size: inherit;
	font-weight: inherit;
	line-height: inherit;
	letter-spacing: inherit;
	color: inherit;
}

/* Read more ---------------------------------------------------------------
 * The design draws the arrow as a text character. The widget renders a feather
 * SVG. Styling the SVG is better than replacing it with a pseudo-element: it
 * keeps the link's accessible name intact and survives the plugin swapping its
 * icon set.
 */
/* theme.css:
 *   .blog-grid article.post-wrap .post-footer .egovt-post-readmore a
 *   { color: #42516d }  (0,4,2) - a slate blue in no palette. */
body .lu-card article.post-wrap .post-footer .egovt-post-readmore a,
.lu-card .lu-card__link {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	font-family: var(--lu-font-body);
	font-size: var(--lu-type-body-size);
	font-weight: var(--lu-card-link-weight);
	line-height: var(--lu-type-body-lh);
	color: inherit;
}

.lu-card .egovt-post-readmore a svg,
.lu-card .egovt-post-readmore a [data-feather],
.lu-card .lu-card__link svg {
	width: 1em;
	height: 1em;
	stroke: currentColor;
}


/* --- Cards built from Elementor widgets ---------------------------------
 * The BEM aliases above were written for hand-authored markup, where the class
 * is ON the element it describes. A third shape needs them: a card assembled in
 * the Elementor editor out of an image, an inner section and three text
 * widgets, which is how the toolbox tiles on /for-frivillige/ are built so the
 * client can edit each one.
 *
 * There, every class lands on a WIDGET WRAPPER with Elementor's own
 * `.elementor-widget-container` inside it, so each rule has to reach one level
 * further in. Nothing here is new design - it is the same component, addressed
 * through one more div.
 */

/**
 * The media box's height has to be handed to the image.
 *
 * `aspect-ratio` and `overflow: hidden` go on the widget wrapper - that is the
 * box, and it is deliberately not the `<img>` (see the Smush note above). But
 * Elementor puts `.elementor-widget-container` between the two, and its height
 * is `auto`, so the img's `height: 100%` resolved against nothing and fell back
 * to the file's own proportions - the exact failure the ratio was moved up a
 * level to avoid, reintroduced by the wrapper. One line closes the chain.
 */
.lu-card .lu-card__media > .elementor-widget-container {
	height: 100%;
}

/* The body is an inner section, so the fill and the padding land on the section
 * and its container must not re-cap or re-pad what is already inside a card. */
.lu-card .lu-card__body > .elementor-container {
	max-width: none;
	padding-inline: 0;
}

.lu-card .lu-card__text p {
	font-family: var(--lu-font-body);
	font-size: var(--lu-type-body-size);
	line-height: var(--lu-type-body-lh);
	margin-block: 0;
}

/**
 * THE CARD'S INTERNAL MARGINS ARE OWNED HERE, NOT IN ELEMENTOR.
 *
 * They were first written as explicit zeros on every widget in the editor, by
 * analogy with the padding - and that was the wrong analogy. Padding has to be
 * zeroed in Elementor because clearing the control falls back to its own 10px
 * default. Margin has no such default worth beating, and a per-element
 * `_margin` prints at (0,3,0) from inside <body>, so it silently out-ranked the
 * gap below and the read-more sat flush against the copy at every width where
 * there was no slack for the auto margin to give it - which is every card on
 * mobile. DESIGN.md step 2, exactly: clear, don't overwrite.
 *
 * Elementor's own default is `.elementor-widget:not(:last-child)
 * { margin-bottom: 20px }` at (0,1,0), which these clear on specificity. The
 * media needs it stated too: the coloured body is a section rather than a
 * widget, so the image above it is `:not(:last-child)` and took the 20px.
 */
.lu-card .lu-card__media {
	margin-block: 0;
}

/**
 * ...and the one gap that is not zero: the MINIMUM above the read-more.
 *
 * The read-more is pinned with `margin-block-start: auto`, and an auto margin
 * is only whatever is left over - nothing at all in the tallest card of a row,
 * and nothing ever on mobile, where each card is its own row and sized to its
 * own content. At 1440 every card had slack and the frame's ~44px gap appeared
 * on its own, which is exactly why this was invisible at the design widths.
 *
 * One blank line is the design's smallest vertical unit, so that is the floor;
 * the auto margin still adds the rest wherever there is any.
 */
.lu-card .lu-card__text {
	margin-block: 0 var(--lu-type-body-lh);
}


/**
 * "Laes mere ->" is a text widget rather than a button: the design draws it as
 * a bold line of copy with the arrow as a character, not as an lu-btn.
 *
 * `color: inherit` on the anchor is the load-bearing half - the Kit binds
 * link colour to Sekundaer, which would put a yellow-green link on both the
 * pink and the dark red card. Inheriting instead means the read-more is always
 * the pairing's foreground, and can never be picked wrong.
 */
.lu-card .lu-card__link p {
	font-family: var(--lu-font-body);
	font-size: var(--lu-type-body-size);
	font-weight: 700;
	line-height: var(--lu-type-body-lh);
	margin-block: 0;
}

.lu-card .lu-card__link a,
.lu-card .lu-card__title a {
	text-decoration: none;
}

/* On hover Sekundær, not underlined, like the news card's "Læs mere" and every
 * other link (DESIGN.md "Colour"). Hand-built cards had no hover at all. The
 * Lyseblå pages keep their own opacity hover (restyle.css, lu-page-frivillige). */
body:not(.lu-page-frivillige) .lu-card .lu-card__link a:hover,
body:not(.lu-page-frivillige) .lu-card .lu-card__title a:hover {
	color: var(--lu-secondary);
	text-decoration: none;
}


/* ==========================================================================
   4. lu-list
   ==========================================================================
   A titled list of dated items, ruled between rows - "Kommende aktiviteter"
   (node 1:52). Sits inside an lu-card, so it inherits the card's colour.

   Applied to: the ova_events_cat widget.
   ========================================================================== */

.lu-list .title-event,
.lu-list .lu-list__title {
	margin: 0 0 32px;
	font-family: var(--lu-font-display);
	font-size: var(--lu-type-h3-size);
	font-weight: 500;
	line-height: var(--lu-type-h3-lh);
}

/* event.css sets `.ovaev-event-element .item:not(:last-child)` (0,3,0) to a flat
 * #e5e5e5 and gives the last item no rule at all. The design rules every item,
 * in the card's own colour. */
body .lu-list .ovaev-event-element .item,
.lu-list .lu-list__item {
	/* --lu-list-rule-gap, not a literal 16: the news card beside this one reads
	 * the same token to put "Læs mere →" on the same line as the last item's
	 * text. See section 3. */
	padding-block: 0 var(--lu-list-rule-gap);
	margin-block-end: var(--lu-list-rule-gap);
	border-bottom: var(--lu-rule);
}

/* The last rule in the Figma frame is drawn, so no :last-child exception. */

/**
 * The title sits at the top of the card and the items at the bottom.
 *
 * The card is as tall as the two news cards beside it, and its own content is
 * shorter than that - so something has to take the slack. Left alone it all
 * falls below the last item, which reads as the list having stopped early.
 *
 * `margin-block-start: auto` on the FIRST item moves the whole group down as a
 * block, rather than `justify-content: space-between`, which would also push
 * the three items apart from each other and lose their 16px rhythm. Same
 * technique as the footer's "Følg med på" column.
 *
 * The last item's trailing margin goes with it: below the last rule the card's
 * own padding is the only space that should be there.
 */
.lu-list .ovaev-event-element,
.lu-list .lu-list__body {
	display: flex;
	flex-direction: column;
}

.lu-list .ovaev-event-element .item:first-of-type,
.lu-list .lu-list__item:first-of-type {
	margin-block-start: auto;
}

body .lu-list .ovaev-event-element .item:last-child,
.lu-list .lu-list__item:last-child {
	margin-block-end: 0;
}

.lu-list .item .title,
.lu-list .lu-list__item-title {
	margin: 0 0 4px;
	font-family: var(--lu-font-display);
	font-size: var(--lu-type-h4-size);
	font-weight: 500;
	line-height: var(--lu-type-h4-lh);
	color: inherit;
}

.lu-list .item .title a,
.lu-list .lu-list__item-title a {
	color: inherit;
}

.lu-list .time-event,
.lu-list .time-event .time,
.lu-list .lu-list__item-meta {
	font-family: var(--lu-font-body);
	font-size: var(--lu-type-body-size);
	line-height: var(--lu-type-body-lh);
	color: inherit;
}


/* ==========================================================================
   5. lu-band
   ==========================================================================
   A full-width block of colour, inset to the container, carrying the diagonal
   brand radius - the stats strip (node 1:67).

   Applied to: a top-level section.

   The radius is the detail worth protecting. It is top-right and bottom-left
   only. See the note in tokens.css.
   ========================================================================== */

.lu-band {
	border-radius: var(--lu-radius-band);
	padding-block: var(--lu-band-pad-y);
	overflow: hidden;   /* clips a background image to the diagonal corners */
}

/**
 * A band is a filled box, so its contents need to sit inside it rather than
 * running to the edge - especially at the two rounded corners, and especially on
 * mobile where the band is only as wide as the page gutter allows.
 */
.lu-band > .elementor-container {
	max-width: var(--lu-container);
	padding-inline: var(--lu-band-pad-x);
}

/* The stats sit further apart than a card row - they are short labels, and at
 * a card's 20px they read as one block rather than four figures. */
.lu-band.lu-row > .elementor-container {
	gap: var(--lu-band-gap);
}


/* ==========================================================================
   6. lu-stat
   ==========================================================================
   One big figure over a short label, centred (node 1:68). Four across on
   desktop, stacked on mobile - the stacking is Elementor's column behaviour,
   not ours.

   Applied to: a counter widget. The site's counters also carry the theme's
   own `ova_egovt_counter` class; this does not depend on it, because that
   class is on 12 pages, 8 of them demo leftovers.
   ========================================================================== */

.lu-stat {
	text-align: center;
	color: inherit;
}

/* Two competitors, and the theme's is the stronger one:
 *   widget-counter.min.css  .elementor-counter .elementor-counter-number-wrapper  69px   (0,2,0)
 *   style-elementor.css     .ova_egovt_counter.elementor-widget-counter ...       50px   (0,3,0)
 * Hence `body` + the widget class, for (0,3,1). */
body .lu-stat.elementor-widget-counter .elementor-counter-number-wrapper,
.lu-stat .lu-stat__figure {
	font-family: var(--lu-font-display);
	font-size: var(--lu-type-h1-size);
	font-weight: 500;
	line-height: var(--lu-type-h1-lh);
	letter-spacing: var(--lu-type-h1-ls);
	color: inherit;
}

/**
 * Elementor's own counter CSS puts an 11px bottom margin under the figure, and
 * it was never cleared - so the 17px below was landing on top of it and the gap
 * has always rendered at 28. Zeroed here so ONE number controls the space.
 */
body .lu-stat.elementor-widget-counter .elementor-counter-number-wrapper {
	margin-block-end: 0;
}

body .lu-stat.elementor-widget-counter .elementor-counter-title,
.lu-stat .lu-stat__label {
	/* Half of the 28px that was rendering. The desktop frame draws 17 (figure
	 * ends 181, label starts 198) and the mobile frame ~14 between the two text
	 * boxes, so this sits at the tighter end of what the design shows. */
	margin-block-start: 14px;
	font-family: var(--lu-font-display);
	font-size: var(--lu-type-h4-size);
	font-weight: 500;
	line-height: var(--lu-type-h4-lh);
	color: inherit;
}


/* ==========================================================================
   7. lu-btn
   ==========================================================================
   The pill button (node 1:41/1:42). Geometry only - Elementor's button widget
   already gives the client background, text and hover colour controls, and
   those are better than anything this file could offer.

   Applied to: a button widget.
   ========================================================================== */

.lu-btn .elementor-button,
a.lu-btn {
	display: inline-block;
	padding: var(--lu-btn-pad);
	border-radius: var(--lu-radius-btn);
	font-family: var(--lu-font-display);
	font-size: var(--lu-type-h4-size);
	font-weight: 500;
	line-height: var(--lu-type-h4-lh);
	text-align: center;
}

/**
 * lu-btn--sm - the same pill, one step down, for a call to action inside a
 * section ("Ny kampagnefilm", "Find din lokalforening"), so it does not compete
 * with the hero's "Bliv medlem". The label takes the Menu step (18/20), the
 * padding --lu-btn-pad-sm: 48px tall against the hero's 61.
 *
 * Applied to: a button widget, with lu-btn.
 */
.lu-btn--sm .elementor-button,
a.lu-btn--sm {
	padding: var(--lu-btn-pad-sm);
	font-size: var(--lu-type-menu-size);
	line-height: var(--lu-type-menu-lh);
}


/* ==========================================================================
   8. lu-prose
   ==========================================================================
   Article body copy, from the text-hierarchy sheet (node 1:126): a deck, then
   Mellemrubrik and Broedtekst in a measured column. DESIGN.md "Articles".

   Applied to: the body of a news post (single.php), or a text-editor widget on
   an article page such as Vedtægter.

   Every rule here has to work on content nobody styled for it: 236 posts
   written over years in the Elementor editor, some pasted from Word. So the
   component describes ROLES - a paragraph, a subhead, a list, a link - and
   reaches them wherever they turn up, rather than expecting particular markup.
   ========================================================================== */

.lu-prose {
	max-width: 780px;   /* 779px measured on node 1:127 */
	font-family: var(--lu-font-body);
	font-size: var(--lu-type-body-size);
	line-height: var(--lu-type-body-lh);
	color: inherit;
}

/**
 * One blank line between paragraphs - Broedtekst's own line, 20px - not
 * theme.css's `p { margin-bottom: 2rem }`.
 *
 * Bottom margins rather than `* + *`, because the paragraphs are not siblings:
 * each Elementor text widget wraps its own in two divs, so a sibling selector
 * only ever reaches the paragraphs inside one widget. The last one in a widget
 * gives its margin back and the widget's own spacing takes over.
 */
.lu-prose p,
.lu-prose ul,
.lu-prose ol {
	margin-block: 0 var(--lu-type-body-lh);
}

.lu-prose :is(p, ul, ol):last-child {
	margin-block-end: 0;
}

.lu-prose ul,
.lu-prose ol {
	padding-inline-start: 1.4em;
}

.lu-prose li {
	margin-block: 0 4px;
}

.lu-prose li:last-child {
	margin-block-end: 0;
}

.lu-prose strong,
.lu-prose b {
	font-weight: 700;
}

/**
 * SUBHEADS ARE MELLEMRUBRIK, WHATEVER THEY WERE WRITTEN AS.
 *
 * Posts carry three kinds: real H2s and H3s (50 posts), heading widgets, and a
 * short paragraph that is only bold text (57 posts - marked `lu-subhead` by
 * inc/article.php). Figma 1:126 draws one subhead, 16/20 bold, so all three
 * become it. An H2 in a post used to render at the Kit's 48px.
 *
 * `html body` because two rules sit above the obvious selector: the Kit's
 * `.elementor-kit-4 h2` (0,1,1) and restyle.css's mobile step-down
 * `body[class*="elementor-kit-"] h2` (0,1,2), which loads later. (0,1,3) clears
 * both and still loses to a heading widget's own per-element typography.
 *
 * No space above - the paragraph before already leaves its blank line - and
 * none below: a subhead sits directly on the text it introduces.
 */
html body .lu-prose :is(h2, h3, h4, h5, h6),
html body .lu-prose .elementor-heading-title,
html body .lu-prose p.lu-subhead {
	margin-block: 0;
	font-family: var(--lu-font-body);
	font-size: var(--lu-type-body-size);
	font-weight: 700;
	line-height: var(--lu-type-body-lh);
	letter-spacing: 0;
	text-transform: none;
	color: inherit;
}

/**
 * Inside an lu-textblock the paragraphs lose their blank line - the textblock's
 * `p { margin-block: 0 }` and `p + p` spacing win over the rule above - so a
 * subhead after a paragraph sat directly on it (Vækstlaget, and nine partner
 * and insurance pages with h2-h5 in their text). Give the blank line back above
 * the subhead; the text under it still sits directly on it.
 */
html body .lu-textblock .lu-prose :is(p, ul, ol) + :is(h2, h3, h4, h5, h6) {
	margin-block-start: var(--lu-type-body-lh);
}

/**
 * THE DECK: the first paragraph when it is entirely bold (decision D4, marked
 * by inc/article.php). The display face at H4 size - 20/24 on phones, via the
 * deck tokens - with the article's first blank line and a wider one below.
 *
 * The bold inside it becomes the deck's own weight: the paragraph's <strong>
 * is what made it a deck, not something to render on top of one.
 */
html body .lu-prose p.lu-deck {
	margin-block: 0 var(--lu-post-deck-gap);
	font-family: var(--lu-font-display);
	font-size: var(--lu-type-deck-size);
	font-weight: 500;
	line-height: var(--lu-type-deck-lh);
}

.lu-prose p.lu-deck :is(strong, b) {
	font-weight: inherit;
}

/**
 * LINKS: PRIMAER AND UNDERLINED (decision D5).
 *
 * The body text is Primaer too, so the underline is what marks a link. The
 * Kit's link colour is Sekundaer, 1.89 : 1 on the page ground; Primaer is
 * 8.19 : 1. Scoped to articles - the site-wide link colour stays a Kit decision
 * for the client (HANDOFF.md section 7).
 *
 * The typography is inherited for the same reason as a card's linked title
 * (section 3): `.elementor-kit-4 a` restates Broedtekst on every anchor, which
 * would unbold a link inside a subhead.
 */
html body .lu-prose a:not(.elementor-button) {
	font-family: inherit;
	font-size: inherit;
	font-weight: inherit;
	line-height: inherit;
	color: inherit;
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 0.18em;
}

/* On hover Sekundær. The underline STAYS - D1, wave 3: hover preserves the
 * rest state's underline rather than removing it. */
html body .lu-prose a:not(.elementor-button):hover {
	color: var(--lu-secondary);
}

/**
 * FORMATTING PASTED FROM WORD AND GOOGLE DOCS (decision D6).
 *
 * About 32 posts carry inline styles copied in with their text - measured
 * across all posts: `font-family: Montserrat` 226 times, `font-size: 15px`
 * 195, `color: #111111` 195, plus line-heights, letter-spacings and paragraph
 * margins in the hundreds. An inline style beats every stylesheet, so without
 * this those posts keep a different face, size and colour from the rest.
 *
 * `!important` is the only thing that out-ranks an inline style, and it is
 * scoped to the article body and to the properties pasting brings - never
 * weight or style, which carry meaning. Stripping the styles from the posts
 * instead was the rejected alternative: it edits client content, on local and
 * then on production, and has to be redone whenever someone pastes again.
 */
.lu-prose [style] {
	font-family: inherit !important;
	font-size: inherit !important;
	line-height: inherit !important;
	letter-spacing: inherit !important;
	color: inherit !important;
	/* Pasted layout too: one post carries `width: 750px` on a wrapper around an
	 * image carousel, which pushed a phone 383px sideways. A max-width needs no
	 * !important - the inline style sets the width, not a maximum. */
	max-width: 100%;
}

.lu-prose p[style] {
	margin-block: 0 var(--lu-type-body-lh) !important;
	text-indent: 0 !important;
}

.lu-prose li[style] {
	margin-block: 0 4px !important;
	text-indent: 0 !important;
}

/* A deck that was pasted keeps its deck size: the rule above would otherwise
 * hand it the body's 16px. */
html body .lu-prose p.lu-deck[style] {
	margin-block: 0 var(--lu-post-deck-gap) !important;
	font-family: var(--lu-font-display) !important;
	font-size: var(--lu-type-deck-size) !important;
	line-height: var(--lu-type-deck-lh) !important;
}


/* ==========================================================================
   9. Layout helpers
   ========================================================================== */

/**
 * lu-row - an equal-width grid that collapses to one column on mobile.
 *
 * The homepage news row is three 427px cards in a 1320px container. Elementor's
 * own 65/35 column split cannot express that, because _inline_size renders as
 * an inline width:% on the column and would have to be retyped per breakpoint.
 * Applied to a section, this takes the columns over.
 */
/**
 * The row gap is NOT always the column gap.
 *
 * Every row on the front page is one row deep, so the two were the same number
 * and `gap` took one value. The toolbox grid is the first to wrap - six cards
 * over two rows - and the frame puts 52px between them against 20px between the
 * columns (row 1 ends at y1157, row 2 starts at y1209). Mobile goes back to 20,
 * because there the cards are a single column and the gap is the only rhythm
 * there is.
 *
 * Written as a fallback so nothing that does not set it changes: unset,
 * --lu-row-gap resolves to --lu-col-gap and this is the rule it always was.
 */
.lu-row > .elementor-container {
	display: grid;
	grid-template-columns: repeat(var(--lu-row-cols, 3), minmax(0, 1fr));
	gap: var(--lu-row-gap, var(--lu-col-gap)) var(--lu-col-gap);
	max-width: var(--lu-container);
}

.lu-row > .elementor-container > .elementor-column {
	width: 100%;
	max-width: 100%;
}

.lu-row-2 { --lu-row-cols: 2; }
.lu-row-4 { --lu-row-cols: 4; }

/**
 * lu-row-wrap - a row deep enough to wrap onto a second line of cards.
 *
 * Six cards in three tracks is still one `lu-row`; the grid makes the second
 * line itself. What it cannot guess is that the design spaces the two LINES
 * further apart than the columns - 52px against 20px on node 1:105 - so that
 * the row reads as two rows rather than as one block of six.
 *
 * Mobile puts it back: there the cards are a single column, the "rows" are the
 * cards themselves, and 20px is the gap between cards everywhere else in the
 * design.
 */
.lu-row-wrap { --lu-row-gap: 52px; }

@media (max-width: 767px) {
	.lu-row-wrap { --lu-row-gap: var(--lu-col-gap); }
}

@media (max-width: 767px) {
	.lu-row > .elementor-container {
		grid-template-columns: minmax(0, 1fr);
	}
}

/**
 * lu-row-flip - a two-column row whose first column is drawn on the right.
 *
 * Vækstlaget opens with its video on the left and the text on the right, but a
 * phone should read the text and the dates before a square video fills the
 * screen. So the text stays the first column - in the editor, for a screen
 * reader and when the row stacks - and only the drawing order changes, from
 * the tablet up.
 */
@media (min-width: 768px) {
	.lu-row-flip > .elementor-container > .elementor-column:first-child {
		order: 2;
	}
}

/**
 * lu-row-media-first - lu-row-flip's mirror: a two-column row whose second
 * column comes first on a phone.
 *
 * The front page's "Find din lokalforening" reads text left, map right from
 * the tablet up, but on a phone the map should come first, as the picture that
 * the text under it explains. The text stays the first column - in the editor
 * and for a screen reader - and only the stacked drawing order changes.
 *
 * lu-row-aside-first is the same rule under a name that does not say "media":
 * the front page's "Seneste nyheder og begivenheder" row (209efbb) shows its
 * "Kommende aktiviteter" card before the two news cards on a phone (2026-10-05).
 */
@media (max-width: 767px) {
	.lu-row-media-first > .elementor-container > .elementor-column:last-child,
	.lu-row-aside-first > .elementor-container > .elementor-column:last-child {
		order: -1;
	}
}


/* ==========================================================================
   10. lu-fill-* - the approved colour pairings
   ==========================================================================
   Read the "TWO NARROW EXCEPTIONS" note at the top of this file before adding
   one. In short: these exist for surfaces no Elementor control can reach, every
   value is still a Kit alias, and each variant is a pairing lifted from the
   design rather than a free choice.

   Each variant sets three custom properties and nothing else:

     --lu-fill-bg      the surface
     --lu-fill-fg      the foreground that belongs on it
     --lu-fill-accent  headings and highlights inside it

   Applied to: an element that also carries lu-card, lu-band, lu-list or lu-people.
   ========================================================================== */

.lu-fill-primary { --lu-fill-bg: var(--lu-primary);        --lu-fill-fg: var(--lu-surface-green); --lu-fill-accent: var(--lu-secondary); }
.lu-fill-pink    { --lu-fill-bg: var(--lu-rule-pink);      --lu-fill-fg: var(--lu-deep-red);      --lu-fill-accent: var(--lu-deep-red); }
.lu-fill-red     { --lu-fill-bg: var(--lu-deep-red);       --lu-fill-fg: var(--lu-rule-pink);     --lu-fill-accent: var(--lu-rule-pink); }
.lu-fill-blue    { --lu-fill-bg: var(--lu-stat-blue);      --lu-fill-fg: var(--lu-surface-sand);  --lu-fill-accent: var(--lu-surface-sand); }
.lu-fill-green   { --lu-fill-bg: var(--lu-surface-green);  --lu-fill-fg: var(--lu-primary);       --lu-fill-accent: var(--lu-primary); }
.lu-fill-sand    { --lu-fill-bg: var(--lu-surface-sand);   --lu-fill-fg: var(--lu-primary);       --lu-fill-accent: var(--lu-primary); }
.lu-fill-banner  { --lu-fill-bg: var(--lu-banner-surface); --lu-fill-fg: var(--lu-primary);       --lu-fill-accent: var(--lu-stat-blue); }
.lu-fill-lyseblaa{ --lu-fill-bg: var(--lu-surface-blue);   --lu-fill-fg: var(--lu-deep-red);      --lu-fill-accent: var(--lu-deep-red); }

/**
 * A band paints itself. A card paints only its body, because its media sits
 * above and must stay flush to the card's top edge.
 */
.lu-band[class*="lu-fill-"] {
	background-color: var(--lu-fill-bg);
	color: var(--lu-fill-fg);
}

/* `.wrap-article` is in the selector to reach (0,4,1), which clears
 * style-elementor.css `.ova-blog .post-wrap .wrap-article .evgovt-content`
 * at (0,4,0) - the rule that was painting every card body white. */
body .lu-card[class*="lu-fill-"] .wrap-article .evgovt-content,
.lu-card[class*="lu-fill-"] .lu-card__body,
.lu-card.lu-list[class*="lu-fill-"] .ovaev-event-element {
	background-color: var(--lu-fill-bg);
	color: var(--lu-fill-fg);
}

/* The person card paints its body, as a card does; a person with no photograph
 * keeps the media box, a step towards the foreground so it still reads as one. */
.lu-people[class*="lu-fill-"] .lu-person__body {
	background-color: var(--lu-fill-bg);
	color: var(--lu-fill-fg);
}

.lu-people[class*="lu-fill-"] .lu-person__media--empty {
	background-color: color-mix(in srgb, var(--lu-fill-fg) 12%, var(--lu-fill-bg));
	color: var(--lu-fill-fg);
}

/**
 * The events panel has no media, so the whole panel is the body - and it is the
 * one card that rounds its top corners itself.
 */
.lu-card.lu-list[class*="lu-fill-"] .ovaev-event-element {
	padding: var(--lu-card-pad);
	border-radius: var(--lu-radius-card);
}

/* Headings inside a filled surface take the pairing's accent. */
.lu-list[class*="lu-fill-"] .title-event,
.lu-list[class*="lu-fill-"] .lu-list__title {
	color: var(--lu-fill-accent);
}

/**
 * The date chip is the card inverted - pale block, dark text - which is exactly
 * what the design draws, and it means the chip can never be picked wrong.
 */
.lu-card[class*="lu-fill-"] .post-meta-date,
.lu-card[class*="lu-fill-"] .lu-card__chip {
	background-color: var(--lu-fill-fg);
	color: var(--lu-fill-bg);
}

/**
 * The date sits inside three nested spans, and the Ovatheme Customizer paints
 * the middle one white:
 *   .blog-grid article.post-wrap .post-meta-date .post-meta-content-date
 *   { color: #fff }   (0,4,1)
 *
 * `color: inherit` on the inner span is NOT enough - it would faithfully
 * inherit that white. The value has to be stated, at a specificity that clears
 * the Customizer on the intermediate element too, hence `article.post-wrap`.
 */
body .lu-card[class*="lu-fill-"] article.post-wrap .post-meta-date,
body .lu-card[class*="lu-fill-"] article.post-wrap .post-meta-date *,
.lu-card[class*="lu-fill-"] .lu-card__chip * {
	color: var(--lu-fill-bg);
}


/* ==========================================================================
   11. lu-hero
   ==========================================================================
   Full-bleed photograph with a lead paragraph and a call to action.

   The two breakpoints are genuinely different layouts, not one layout resized:

     desktop   90% of the window less the header, text ON the photo, bottom
               left, in white - so the next section always shows
     mobile    268px of photo, then the text BELOW it on the page background,
               in accent

   Elementor has no responsive control for text colour, so that switch is here.
   The value is still a Kit alias - change "Markering" in Site Settings and the
   mobile hero follows.

   Applied to: a section with a background image.
   ========================================================================== */

.lu-hero {
	/**
	 * A SHARE OF THE WINDOW, WITH THE HEADER COUNTED IN.
	 *
	 * The hero does not start at the top of the screen - the two header bars sit
	 * above it - so a hero sized against the window alone always overshoots by
	 * their height. That is what made it "too high": at 961px on a 982px laptop
	 * the fold landed inside the photograph, so nothing below the hero was ever
	 * visible and the page gave no sign that it continued.
	 *
	 * Subtracting --lu-chrome-h makes the number mean what it looks like:
	 * header + hero together take --lu-hero-fill per cent of the window, and the
	 * rest of that window is the next section showing.
	 *
	 * `max(…, 320px)` is the floor, for a short window rather than a small one -
	 * a laptop with the window half-height, or a phone in landscape. The copy
	 * and the button need about 250px between them; below that the hero stops
	 * shrinking and the page scrolls instead of overlapping.
	 *
	 * TWO DECLARATIONS, and the second is not a typo. `svh` is the window at its
	 * SMALLEST - toolbars showing - which is what keeps the next section visible
	 * on a tablet whose browser chrome comes and goes. Browsers that do not know
	 * `svh` (before Safari 15.4 / Chrome 108) drop that line and keep the `vh`
	 * one, which is the same number on any desktop.
	 */
	min-height: max(320px, calc(var(--lu-hero-fill)  * 1vh - var(--lu-chrome-h)));
	min-height: max(320px, calc(var(--lu-hero-fill) * 1svh - var(--lu-chrome-h)));
	display: flex;
	align-items: flex-end;
	position: relative;   /* the wash below is positioned against this */
}

/**
 * The same wash the video cover carries (section 21), for the same reason: the
 * hero copy is white type laid straight over a photograph, and a photograph
 * with a bright sky in it is not a background until something backs it off.
 * --lu-media-tint is the primary green at 18%, so it tints with the palette
 * rather than greying the picture, and one token keeps the two media
 * treatments in step.
 *
 * A pseudo-element rather than Elementor's own Background Overlay control: the
 * overlay control is per-element and would have to be retyped, at the right
 * opacity, on every hero anyone builds. This travels with the class.
 *
 * `position: absolute` keeps it out of the flex flow - it is not a flex item.
 */
.lu-hero::before {
	content: "";
	position: absolute;
	inset: 0;
	/* The SOFT strength, not the video still's. Nothing has to stay legible
	 * against this photograph - the hero copy lands on a dark corner of its own
	 * - so the wash is only seating the picture into the page, and at the full
	 * 18% it was doing more than that. See tokens.css. */
	background-color: var(--lu-media-tint-soft);
	pointer-events: none;
}

/* A flex item shrinks to its content by default, which left the hero copy
 * floating in the middle of the photo instead of at the container's left edge.
 * Width and gutter come from section 13b.
 *
 * The stacking context is the wash's companion: an absolutely positioned
 * pseudo-element paints above its parent's in-flow children, so without this
 * the tint would sit over the copy and the button rather than under them. Same
 * trap the video's play button hit - see section 21. */
.lu-hero > .elementor-container {
	flex: 1 1 auto;
	width: 100%;
	padding-block-end: 52px;   /* button baseline 971.6 of 1024 on the frame */
	position: relative;
	z-index: 1;
}

.lu-hero .elementor-widget-text-editor { max-width: 640px; }   /* 630px measured */

.lu-hero .elementor-widget:not(:last-child) { margin-block-end: 31px; }

/**
 * ...and 31px is all it should be.
 *
 * theme.css:34 sets `p { margin-bottom: 2rem }`, and a paragraph's bottom
 * margin collapses straight out through .elementor-widget-container and the
 * widget itself. So the measured 31px above was landing UNDER a 32px margin
 * nobody wrote, and the gap between the lead and the button was 63px.
 *
 * Zeroed here rather than in the theme-wide defaults because 2rem is load
 * bearing for body copy elsewhere on the site; HANDOFF section 9 records the
 * general case. Paragraphs inside the block keep a separation of their own, at
 * the design's 20px (DESIGN.md, "Space") rather than the theme's 32.
 */
.lu-hero .elementor-widget-text-editor p { margin-block: 0; }
.lu-hero .elementor-widget-text-editor p + p { margin-block-start: var(--lu-type-body-lh); }

@media (max-width: 767px) {
	/**
	 * The photo becomes a banner and the copy drops beneath it.
	 *
	 * The image itself is NOT handled here. Elementor owns background-image,
	 * -size and -position on this section and emits them at (0,4,0) through the
	 * element hash, so taking them from CSS would mean either !important or
	 * hard-coding a hash that changes whenever the section is rebuilt. Its
	 * controls are responsive, so the section carries
	 * `background_size_mobile: initial` at 100% width, top aligned - and the
	 * photo being 1500x1000 means that renders exactly 268px tall at 402 wide,
	 * which is the Figma frame's hero height to the pixel.
	 *
	 * All that leaves here is layout.
	 */
	.lu-hero {
		display: block;
		min-height: 0;
		/**
		 * The copy has to clear the photo, and the photo's height is not fixed -
		 * it is painted 100% of a 100vw-wide section, so it scales with the
		 * viewport. A literal 294px only lined up at exactly 402px wide and
		 * left a gap or an overlap at every other width, which is what made
		 * this break while resizing.
		 */
		padding-block-start: calc(100vw / var(--lu-hero-ratio) + 26px);
	}

	/**
	 * The wash stops where the picture does.
	 *
	 * Mobile drops the copy BELOW the photo, onto the page background, so an
	 * inset:0 tint would wash the text block too - and there is nothing
	 * overlaid down there for it to back off. The photo's painted height is the
	 * same expression the padding above is built from, which is what keeps the
	 * two edges together at every width rather than at one.
	 */
	.lu-hero::before {
		bottom: auto;
		height: calc(100vw / var(--lu-hero-ratio));
	}

	.lu-hero > .elementor-container {
		padding-block-end: 0;
	}

	.lu-hero .elementor-widget-text-editor { max-width: none; }

	/**
	 * The documented exception from the top of this file: on desktop this copy
	 * is white over the photo, on mobile it is accent on the page background,
	 * and Elementor has no responsive control for text colour.
	 *
	 * Elementor's own rule is `.elementor-2984 .elementor-element-1a5e003
	 * { color: #FFFFFF }` at (0,3,0) and prints inside <body>, later than this
	 * file - so this needs (0,3,1), which is what the leading `body` buys.
	 * The value is still a Kit alias: change "Markering" and this follows.
	 */
	body .lu-hero .lu-hero__text.elementor-widget-text-editor,
	body .lu-hero .lu-hero__text.elementor-widget-text-editor p {
		color: var(--lu-accent);
	}
}


/* ==========================================================================
   11b. lu-page-head
   ==========================================================================
   The head of a subpage: where you are. Replaced eight Slider Revolution
   modules that were each a page title on a photograph, placed by hand at a
   different x on every page (DESIGN.md, "lu-page-head").

     lu-page-head lu-bleed   full-bleed photograph with the title bottom-left
                             ON it, at every width. The front page hero is
                             the only head that drops its copy below the
                             photograph on a phone, and it stays the exception.
     lu-page-head            no photograph: the same title on the page ground,
                             in the same place.

   Applied to: a section, holding one column (lu-page-head__inner, padding
   zeroed in the editor) with ONE heading widget set to H1
   (lu-page-head__title), and nothing else. The photograph is the section's own
   background image or background video control, and the title's colour is the
   heading's own colour control, bound to the Kit's Hvid. Nothing here chooses
   either.
   ========================================================================== */

.lu-page-head {
	position: relative;   /* the wash below is positioned against this */
	margin-block-end: var(--lu-section-gap);
}

/**
 * Header + head = --lu-page-head-fill per cent of the window. Section 11 has
 * the reasoning for subtracting the chrome and for the doubled declaration.
 */
.lu-page-head.lu-bleed {
	min-height: max(320px, calc(var(--lu-page-head-fill)  * 1vh - var(--lu-chrome-h)));
	min-height: max(320px, calc(var(--lu-page-head-fill) * 1svh - var(--lu-chrome-h)));
	display: flex;
	align-items: flex-end;
	/* A full-bleed section escapes .wrap_site, so it puts the page's line back
	 * itself - both halves, as section 13b explains for the hero. */
	--lu-container-max: calc(var(--lu-container) + 2 * var(--lu-pad));
}

/**
 * Wash and scrim in ONE pseudo-element: the brand tint as its colour, the
 * black scrim as its image. One layer rather than ::before plus ::after, so
 * nothing else that decorates a section with ::after can collide with it.
 */
.lu-page-head.lu-bleed::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
	background-color: var(--lu-media-tint);
	background-image: var(--lu-media-scrim);
	pointer-events: none;
}

/* Elementor's background video goes under the wash; the copy goes over it. */
.lu-page-head > .elementor-background-video-container {
	z-index: 0;
}

.lu-page-head.lu-bleed > .elementor-container {
	flex: 1 1 auto;
	width: 100%;
	padding-inline: var(--lu-pad);
	padding-block: var(--lu-page-head-inset);
	position: relative;
	z-index: 2;
}

/**
 * The title is the Kit's own H1 - 81/81, and 48/52 on mobile via restyle.css
 * section 2 - so no size is set here. Only the Danish-compound floor from
 * DESIGN.md "Type": a long compound has no space for the browser to break at.
 *
 * There is deliberately no rule for anything BESIDE the title. The head holds
 * the H1 and nothing else; a sentence that wants to sit with it opens the page's
 * content as an H2 instead. A second widget dropped into the head gets no
 * styling from here, and tools/checks/page-head.js fails on it.
 */
.lu-page-head__title .elementor-heading-title {
	hyphens: auto;
	overflow-wrap: break-word;
}

/**
 * Without a photograph. It sits inside .wrap_site, so the line is already
 * right; it only needs the page's opening rhythm above the title.
 */
.lu-page-head:not(.lu-bleed) {
	padding-block-start: var(--lu-page-head-top);
	/* An article page (Vedtægter) goes from its title straight into the text, so
	 * the gap below is the article's - the same 56 / 32 a news post has under its
	 * title - not a section break. */
	margin-block-end: var(--lu-post-deck-gap);
}

@media (max-width: 767px) {
	/**
	 * A proportion of the width rather than of the window, with the title still
	 * on the photograph. `min-height`, so a long title grows the band instead of
	 * running out of it - "Netværk for unge nyuddannede faglærte landmænd" is
	 * the one that does.
	 */
	.lu-page-head.lu-bleed {
		min-height: calc(100vw / var(--lu-page-head-ratio));
	}
}


/* ==========================================================================
   12. Type utilities
   ==========================================================================
   For text-editor widgets, where the Kit's h1-h4 rules cannot reach because the
   markup is <p>. Both are used by the "Ny kampagnefilm" block and the hero.
   ========================================================================== */

/* Lead paragraph: H4 size, display face. */
.lu-lead,
.lu-lead p {
	font-family: var(--lu-font-display);
	font-size: var(--lu-type-h4-size);
	font-weight: 500;
	line-height: var(--lu-type-h4-lh);
}

/* The Ovatheme Customizer sets a 24px line-height on p, so body-size display
 * copy has to state its own or it inherits the wrong leading. */
.lu-display,
.lu-display p {
	font-size: var(--lu-type-body-size);
	line-height: var(--lu-type-body-lh);
}

/* Body copy set in the display face, at body size. */
.lu-display,
.lu-display p {
	font-family: var(--lu-font-display);
	font-weight: 500;
}


/* ==========================================================================
   13. lu-section
   ==========================================================================
   Vertical rhythm between top-level sections, replacing the spacer widgets the
   site currently uses. `spacer` appears 128 times across 39 pages; every one of
   them is a hand-tuned number that a token scale would fight.
   ========================================================================== */

.lu-section {
	margin-block: var(--lu-section-gap);
}

/**
 * ...except at the bottom of the page, where the rhythm is already there.
 *
 * The Annoncer strip is the first thing in the FOOTER document, so it renders
 * under every page, and it opens with --lu-section-gap of its own
 * (lu-annoncer-head, section 20). A last section that also closes with one puts
 * 180px between the last card and the "Annoncer" label where the frame draws
 * about 110.
 *
 * The two margins cannot collapse into each other - they are in different
 * documents, with the page wrapper's edge between them - so one of them has to
 * stand down, and it is this one: the strip's margin belongs to the strip, and
 * is the same on every page whether the last section is an lu-section or not.
 */
.lu-section:last-child {
	margin-block-end: 0;
}

.lu-section > .elementor-container {
	max-width: var(--lu-container);
}

/**
 * ...and rhythm INSIDE the section once it stacks.
 *
 * Below the breakpoint a two-column section is no longer two columns - it is
 * two blocks, one above the other, and Elementor gives them nothing between.
 * The video and "Ny kampagnefilm" were touching.
 *
 * --lu-section-gap rather than a new number: on mobile a stacked row reads as
 * part of the page's vertical sequence, not as a row, so it takes the page's
 * vertical rhythm. The mobile frame agrees - the video (node 1:157) ends at
 * y 831 and the copy under it (1:158) starts at 881.
 *
 * `:not(.lu-row)` because a row brings its own gap: lu-row is a grid and spaces
 * its tracks with --lu-col-gap, and the stats band with --lu-band-gap. Those
 * are the row's rhythm and this must not land on top of them.
 */
@media (max-width: 767px) {
	.lu-section:not(.lu-row) > .elementor-container > .elementor-column:not(:last-child) {
		margin-block-end: var(--lu-section-gap);
	}
}


/* ==========================================================================
   13b. Minimum gutter
   ==========================================================================
   See the --lu-pad note in tokens.css. A centred max-width alone leaves no
   gutter at all once the viewport reaches the container width, so text ran into
   the edge everywhere between about 1024 and 1340. Padding the container and
   widening its cap by the same amount keeps the gutter at exactly 60px at the
   design width and never lets it fall below --lu-pad.
   ========================================================================== */

/**
 * Sections inside the page wrapper need nothing here - .wrap_site already pads
 * them, and adding more would inset them from everything around them.
 *
 * This is for sections that escape that wrapper: the full-bleed hero, and the
 * header and footer documents, which render outside .wrap_site entirely. They
 * raise --lu-container-max rather than setting max-width directly, because the
 * theme's `max-width: 1270px !important` reads that variable (restyle.css 2b).
 *
 * BOTH HALVES ARE REQUIRED. Padding a container that is still capped at
 * --lu-container does not move it onto the page's line - it insets it by
 * --lu-pad, which is exactly why the logo, the nav and the utility links each
 * sat 24px inside the line every other element on the page shares.
 */
.lu-hero,
.elementor-5460 > .elementor-section,
.elementor-3677 > .elementor-section {
	--lu-container-max: calc(var(--lu-container) + 2 * var(--lu-pad));
}

.lu-hero > .elementor-container,
.elementor-5460 > .elementor-section > .elementor-container,
.elementor-3677 > .elementor-section > .elementor-container {
	padding-inline: var(--lu-pad);
}


/* ==========================================================================
   14. Grid modifiers
   ==========================================================================
   Companions to lu-row in section 9.
   ========================================================================== */

/**
 * A column that occupies two grid tracks.
 *
 * The homepage news row is one Elementor column holding an ova_blog with two
 * posts, beside a second column holding the events panel. Spanning the first
 * column across two of three tracks, and gridding ova_blog's own wrapper to two
 * columns inside it, makes all three cards exactly equal - which a 65/35 split
 * cannot do, because the inter-column gap lands in the wrong place.
 */
.lu-row > .elementor-container > .elementor-column.lu-span-2 {
	grid-column: span 2;
}

/* Three of four tracks: the text beside a picture a quarter wide
 * (LU's organisering's diagrams, wave 1). */
.lu-row > .elementor-container > .elementor-column.lu-span-3 {
	grid-column: span 3;
}

/**
 * lu-row-middle - the columns' contents centred on the row's height, for text
 * beside a picture it should sit against the middle of (LU's organisering).
 * Rows are top-aligned everywhere else: headings share a top line.
 */
.lu-row-middle > .elementor-container {
	align-items: center;
}

.lu-card-grid .ova-wrap-grid {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: var(--lu-col-gap);
}

@media (max-width: 767px) {
	.lu-row > .elementor-container > .elementor-column.lu-span-2,
	.lu-row > .elementor-container > .elementor-column.lu-span-3 { grid-column: auto; }
	.lu-card-grid .ova-wrap-grid { grid-template-columns: minmax(0, 1fr); }
}


/* ==========================================================================
   15. lu-bleed
   ==========================================================================
   Break a section out of the page's content column to the full viewport width.

   Every page section on this site lives inside `div.wrap_site`, which the
   Ovatheme Customizer caps with an !important rule built from the
   `global_boxed_container_width` theme mod. Elementor's own "Stretch Section"
   would need its JS to measure and inline a width; this needs neither.

   `margin-inline: calc(50% - 50vw)` widens the element to exactly 100vw
   whatever the ancestor's cap. 100vw includes the scrollbar, so `body` carries
   `overflow-x: clip` in restyle.css - `clip`, not `hidden`, because `hidden`
   would create a scroll container and break `position: sticky` in the header.
   ========================================================================== */

.lu-bleed {
	margin-inline: calc(50% - 50vw);
	max-width: 100vw;
}


/* ==========================================================================
   16. ova_blog's gutter system
   ==========================================================================
   The widget lays its cards out with the old negative-margin idiom: a -15px
   inline margin on `.ova-wrap-grid` and 15px of padding plus `width: 50%` on
   each `article.post-wrap`. Left in place under `lu-card-grid` the percentage
   width applies to the grid TRACK rather than the row, so every card came out
   at half its track - 102px instead of 427px.

   Neutralised rather than fought: with the plugin's gutter off, `gap` is the
   only thing setting the space between cards, which is the point of a grid.
   ========================================================================== */

.lu-card-grid .ova-wrap-grid {
	margin-inline: 0;
}

.lu-card-grid article.post-wrap {
	width: 100%;
	max-width: none;
	float: none;
	padding-inline: 0;
	margin-block-end: 0;
}


/* ==========================================================================
   17. Cards fill their cell
   ==========================================================================
   Three cards sit in one row: two blog posts inside a single Elementor column
   (ova_blog draws its own grid) and an events panel in the next column. The
   grid stretches the COLUMNS to equal height, but neither widget filled the
   column it was given, so the cards ended up 457, 457 and 433 tall.

   Height has to be handed down the whole chain - Elementor's widget wrapper,
   the widget, the plugin's own wrappers - or it stops at the first link.
   ========================================================================== */

.lu-row > .elementor-container > .elementor-column > .elementor-widget-wrap {
	height: 100%;
}

.lu-card,
.lu-card > .elementor-widget-container,
.lu-card .ova-blog,
.lu-card .ova-wrap-grid,
.lu-card article.post-wrap,
.lu-card article.post-wrap .wrap-article,
.lu-card .ovaev-event-element {
	height: 100%;
}

.lu-card { width: 100%; }

/**
 * THE IMAGE TAKES THE SLACK, NOT THE BODY.
 *
 * Cards in a row are all as tall as the tallest, and something has to absorb
 * the difference. It used to be the body, and that got worse the narrower the
 * cards became: the media is a ratio, so it loses height as the card narrows,
 * while the row stays as tall as the events panel beside it. Measured across
 * the range, the body went 168 -> 290 between 1440 and 900 while its contents
 * stayed the same - the copy drifting further and further up a growing green
 * box, with dead space beneath it.
 *
 * Inverted here. The body is sized to its contents at every width, and the
 * media grows instead: `flex: 1 0 auto` lets it take the spare height and
 * `flex-shrink: 0` stops it ever going below --lu-card-ratio, which stays its
 * floor. The image is already `object-fit: cover`, so the extra height crops
 * rather than distorts.
 *
 * This is also what makes the read-more's alignment real rather than lucky. It
 * sits at the body's bottom padding, and the body now ends where its content
 * ends - so the baseline lands on the events panel's last rule at every width,
 * not only at 1440 where the two happened to agree.
 */
.lu-card article.post-wrap .wrap-article {
	display: flex;
	flex-direction: column;
}

/**
 * No shadow. theme.css gives `.blog-grid article.post-wrap .wrap-article` a
 * 40px shadow in the eGovt demo navy, on a SQUARE box - so around each card's
 * rounded top corners the shadow lit up the square the curve cuts away, and
 * every news card had pale patches at its corners. Cards carry no shadow
 * (DESIGN.md: only the nav and the page-head scrim cast one), so it goes rather
 * than being rounded to match. (0,3,2) clears theme.css's (0,2,2).
 */
.lu-card article.post-wrap .wrap-article {
	box-shadow: none;
}

.lu-card article.post-wrap .post-media {
	flex: 1 0 auto;
}

/**
 * ...and one shared media edge across the row.
 *
 * Sizing each card's body to its own contents (section 17) is right within a
 * card, but two cards side by side then start their coloured bodies at
 * different heights whenever one title wraps a line further than its
 * neighbour's - the media edge steps across the row.
 *
 * Subgrid fixes it without giving the height back to the body. The wrapper
 * declares two rows, the media's and the body's, and both cards adopt them
 * instead of laying themselves out: `grid-template-rows: subgrid` twice over,
 * because ova_blog puts a `.wrap-article` between the grid item and the two
 * parts, and a subgrid only passes its tracks down one level at a time.
 *
 * The body row is `auto` - the taller of the two bodies, so the shorter card
 * carries one line of space under its read-more rather than the row's whole
 * difference. The media row is `1fr` and takes everything else, which is the
 * same bargain as section 17, now struck once for the row instead of per card.
 *
 * Above 767px only: below it the cards are one per row, there is nothing to
 * align them with, and the flex layout in section 17 is the simpler answer.
 */
@media (min-width: 768px) {
	/* `1fr` can only hand the media the spare height if the grid HAS a definite
	 * height to spare. ova_blog wraps its grid in two plain blocks, and a block
	 * does not inherit its parent's height, so the chain is spelled out. */
	.lu-card-grid > .elementor-widget-container,
	.lu-card-grid .ova-blog,
	.lu-card-grid .ova-wrap-grid {
		height: 100%;
	}

	.lu-card-grid .ova-wrap-grid {
		grid-template-rows: 1fr auto;
		/* The gap between the CARDS is horizontal here. Now that the wrapper has
		 * two rows they are the two halves of a card, and a row gap would open a
		 * 20px strip between every photograph and the body under it. Below the
		 * breakpoint the rows are the cards again and the gap comes back. */
		row-gap: 0;
	}

	/**
	 * And with a shared body row, the shorter card's body is taller than its
	 * contents again - by one line, not by the row's whole difference. That
	 * line goes ABOVE the read-more, so all three cards still end together.
	 *
	 * theme.css's `.blog-grid article.post-wrap .post-footer { margin-top: 20px }`
	 * is (0,3,1) and would tie with this on specificity; the leading `body`
	 * settles it at (0,3,2) rather than leaving it to source order.
	 */
	body .lu-card-grid article.post-wrap .post-footer {
		margin-block-start: auto;
	}

	/**
	 * The media has to be told to fill its track.
	 *
	 * `align-self: stretch` is the default and does nothing here: stretching
	 * applies only to an item whose size in that axis is `auto`, and
	 * `aspect-ratio` makes the media's height anything but. So it sat at the
	 * ratio inside a taller row, and the row's spare height showed up as a gap
	 * under the card rather than as a taller picture.
	 *
	 * The ratio still earns its keep - it is what the track's own minimum is
	 * measured from, so it remains the floor, exactly as in section 17. This
	 * only lets the box grow past it.
	 */
	/**
	 * `min-height`, NOT `height`.
	 *
	 * Both make the box fill a taller row, but they get there in opposite
	 * orders, and only one of them survives an aspect ratio. With `height: 100%`
	 * the height is definite before layout, so an `auto` width is computed FROM
	 * the ratio rather than from the track - the media came out 425px wide
	 * inside a 304px card, clipped rather than resized. With `min-height` the
	 * width stretches to the track first, the ratio gives the height from it,
	 * and the minimum then raises it to fill the row.
	 *
	 * The width has to be stated rather than left to stretch, and that is the
	 * other half of the same trap: a grid item WITH AN ASPECT RATIO does not
	 * stretch. `align-self`/`justify-self: normal` behave as `start` for it, so
	 * the box sized itself to its content - and its content is an image WP Smush
	 * has pinned to a fixed pixel width, captured at whatever size it first
	 * measured. Hence 425px of media in a 304px card. With the width definite
	 * the ratio gives the height from it, `overflow: hidden` crops the oversized
	 * image as it always did, and the minimum then fills the row.
	 *
	 * It also keeps the ratio doing its other job: it is still what the track's
	 * own minimum is measured from, so --lu-card-ratio remains the floor.
	 */
	.lu-card-grid article.post-wrap .post-media {
		inline-size: 100%;
		min-block-size: 100%;
	}

	.lu-card-grid article.post-wrap,
	.lu-card-grid article.post-wrap .wrap-article {
		display: grid;
		grid-template-rows: subgrid;
		grid-row: span 2;
		/**
		 * Only the ROWS are inherited; the single column is this grid's own, and
		 * an `auto` column sizes to its content. That matters because WP Smush's
		 * lazy-load CSS pins a PIXEL width on the image
		 * (`width: var(--smush-image-width) !important`) captured at whatever
		 * size it first measured - so the column sized itself to a stale 425px
		 * image and the card stopped tracking its track, clipped rather than
		 * resized. `minmax(0, 1fr)` caps it at the card, and `overflow: hidden`
		 * on the media goes back to quietly cropping the oversized image, which
		 * is what it did under the old block layout.
		 */
		grid-template-columns: minmax(0, 1fr);
		/**
		 * A grid item's automatic minimum size is its CONTENT, in both axes, and
		 * both bite here. Without `min-width: 0` the card refuses to go below
		 * the intrinsic width of the photograph inside it and overflows its
		 * track - which is why the cards stayed 427 wide at a 1000px viewport,
		 * clipped rather than resized. Without `min-height: 0` a long title can
		 * push the body past the row it was given.
		 */
		min-inline-size: 0;
		min-block-size: 0;
	}
}


/**
 * The body takes the slack, and lays its own contents out as a column so the
 * read-more can be pinned to the bottom of it.
 *
 * The padding is restated here for a reason: section 3 sets --lu-card-pad on
 * `.lu-card .evgovt-content` at (0,2,0), and style-elementor.css's
 * `.ova-blog .post-wrap .wrap-article .evgovt-content` at (0,4,0) was quietly
 * winning - so every news card has been rendering the plugin's asymmetric
 * `0 15px 33px 25px` rather than an even 24. This selector is (0,4,1).
 */
.lu-card article.post-wrap .evgovt-content {
	flex: 0 0 auto;
	display: flex;
	flex-direction: column;
	/* The same padding section 3 states, restated at (0,4,1). It has to be:
	 * style-elementor.css's `.ova-blog .post-wrap .wrap-article .evgovt-content`
	 * is (0,4,0) and beats section 3's (0,2,0), which is why every news card
	 * rendered the plugin's asymmetric `0 15px 33px 25px` for so long. Keep the
	 * two in step - section 3 is the one that documents the reasoning. */
	padding: 0 var(--lu-card-pad) calc(var(--lu-card-pad) - 5px);
}

/**
 * "Læs mere →" goes to the bottom of the card, on the same line as the last
 * line of the events panel beside it.
 *
 * Two separate things have to be true for that, and only the first is obvious:
 *
 *   1. The link has to be pinned rather than left to fall where the title's
 *      length puts it. `margin-block-start: auto` does that - without it a card
 *      with a one-line title floats its link halfway up the body, and the three
 *      cards in the row stop agreeing with each other.
 *
 *   2. It has to clear the same distance from the card's bottom edge as the
 *      events panel's last line does. That panel ends with a RULED item, so its
 *      text stops --lu-list-rule-gap plus the rule above the padding edge. The
 *      news card draws no rule, but it has to leave the same room, or the two
 *      final lines miss each other by exactly the height of a rule and its gap.
 *
 * tools/verify.js asserts the two land on one line, so neither half can drift.
 */
/**
 * No auto margin here, and that is deliberate.
 *
 * One used to be, and it never applied - theme.css's
 * `.blog-grid article.post-wrap .post-footer { margin-top: 20px }` is (0,3,1)
 * and beat it, which is worth knowing because the read-more still looked
 * correctly pinned: the body had no spare height to distribute at 1440. It does
 * at every narrower width, and there the link floated while empty green piled up
 * under it.
 *
 * The body being content-sized (section 17) settles it properly. There is no
 * slack left inside the body for an auto margin to collect, so the read-more is
 * last in the flow and the body's own bottom padding is what places it. The
 * theme's 20px above it is the gap the design wants anyway (27 on the frame).
 */
.lu-card-grid .post-footer,
.lu-card .lu-card__footer {
	margin-block-end: 0;
}


/* --- ...except when the card is built from Elementor widgets -------------
 * THE BODY TAKES THE SLACK HERE, WHICH IS THE OPPOSITE OF THE RULE ABOVE, AND
 * IT IS THE SAME ARGUMENT REACHING A DIFFERENT ANSWER.
 *
 * Above, a news card shares its row with the events panel - a different
 * component, of a fixed height, often much taller. Letting the body absorb that
 * difference left the copy stranded at the top of a growing green box, so the
 * media grew instead and the subgrid kept the media edge level across the row.
 *
 * The toolbox row is six of the SAME card. Their bodies differ by at most one
 * line of copy, and their media boxes are all the same width, so a fixed ratio
 * already leaves the media edge dead level across the row with nothing needed
 * to enforce it. That frees the body to take the slack - and the frame says it
 * should: "Laes mere ->" sits at the same 92.52% of all six cards on node
 * 1:105, with the gap above it varying card by card. A pinned read-more IS the
 * design, not a side effect.
 *
 * So: no flex-grow on the media, the body flexes, and the read-more takes an
 * auto margin inside it. No subgrid, because nothing here needs one.
 */
.lu-card > .elementor-widget-wrap {
	flex-direction: column;
	flex-wrap: nowrap;
}

.lu-card > .elementor-widget-wrap > .lu-card__body {
	flex: 1 1 auto;
}

/* Elementor's inner section nests four elements between the body and its
 * widgets, and a definite height stops at the first one that does not pass it
 * on - the same chain the note at the top of section 17 spells out. */
.lu-card .lu-card__body > .elementor-container,
.lu-card .lu-card__body > .elementor-container > .elementor-column,
.lu-card .lu-card__body > .elementor-container > .elementor-column > .elementor-widget-wrap {
	height: 100%;
}

/**
 * `.elementor-widget-wrap` is already a flex container in Elementor's own
 * stylesheet - a wrapping ROW, with `align-content: flex-start`. Turning it
 * into a column is three declarations rather than one: the direction, the wrap
 * (a wrapping column would break into a second track rather than growing), and
 * align-content, which pins every track to the top and would leave the auto
 * margin below with nothing to push against.
 */
.lu-card .lu-card__body > .elementor-container > .elementor-column > .elementor-widget-wrap {
	display: flex;
	flex-direction: column;
	flex-wrap: nowrap;
	align-content: stretch;
}

.lu-card .lu-card__link {
	margin-block-start: auto;
}


/* ==========================================================================
   18. Card details the plugins get wrong
   ========================================================================== */

/**
 * The date chip is two nested boxes - `.post-meta-date` wrapping
 * `.post-meta-content-date` - and the Ovatheme Customizer paints the inner one
 * with `primary_color`. With section 10 painting the outer one, the chip
 * rendered as a pale block with a lime block inside it.
 *
 * The outer box keeps the fill and the padding; the inner one is stripped back
 * to nothing so there is a single chip.
 */
body .lu-card[class*="lu-fill-"] article.post-wrap .post-meta-date .post-meta-content-date {
	/* theme.css:… gives this inner span `line-height: 30px`, which made the chip
	 * 42px tall where the frame draws 32 - and a chip 10px too tall pushes the
	 * whole card body down with it. One line of body copy, like the date it
	 * holds. */
	line-height: var(--lu-type-body-lh);
	background: none;
	padding: 0;
}

/**
 * event.css paints the item date `#62718d` - a slate blue in no palette, and
 * the one colour on these cards that was still ignoring the fill pairing.
 */
/* event.css puts a 60px bottom margin on the panel itself, which stopped it
 * ever reaching the bottom of its column - so it could not match the blog
 * cards' height however far `height: 100%` was handed down. */
body .lu-card .ovaev-event-element {
	margin-block-end: 0;
}

body .lu-list .ovaev-event-element .item .time-event,
body .lu-list .ovaev-event-element .item .time-event .time,
body .lu-list .ovaev-event-element .item .time-event .time span {
	color: inherit;
}


/* ==========================================================================
   19. lu-textblock
   ==========================================================================
   A heading, a lead and body copy set as one block - the "Ny kampagnefilm"
   column, and the shape the Figma text-hierarchy sheet describes.

   The theme gives h2 a 40px bottom margin and p a 24px one, and Elementor adds
   20px between widgets, so the three parts drifted 60px apart where the design
   has a single blank line. Rhythm is stated once here instead.

   Applied to: the column holding the widgets.
   ========================================================================== */

.lu-textblock .elementor-widget {
	margin-block: 0;
}

.lu-textblock .elementor-widget + .elementor-widget {
	margin-block-start: var(--lu-type-h4-lh);   /* 27px - one blank line */
}

.lu-textblock .elementor-heading-title,
.lu-textblock h1, .lu-textblock h2, .lu-textblock h3, .lu-textblock h4 {
	margin-block: 0;
}

.lu-textblock p {
	margin-block: 0;
}

.lu-textblock p + p {
	margin-block-start: var(--lu-type-body-lh);
}

/**
 * A widget Elementor hides at this width is still the previous sibling, so the
 * blank line above the next one stays and the block starts 27px low. When the
 * hidden widget opens the block, the next one takes its place at the top.
 * Elementor's own breakpoints (frontend.css): mobile to 767, tablet to 1024.
 * For pressen's "Kontaktpersoner for pressen", shown only once the row stacks.
 */
@media (min-width: 1025px) {
	.lu-textblock .elementor-widget.elementor-hidden-desktop:first-child + .elementor-widget { margin-block-start: 0; }
}

@media (min-width: 768px) and (max-width: 1024px) {
	.lu-textblock .elementor-widget.elementor-hidden-tablet:first-child + .elementor-widget { margin-block-start: 0; }
}

@media (max-width: 767px) {
	.lu-textblock .elementor-widget.elementor-hidden-mobile:first-child + .elementor-widget { margin-block-start: 0; }
}

/**
 * lu-to-end - this widget, and every one after it, sit at the bottom of the
 * column. For a text column beside something taller: its heading level with the
 * neighbour's top, its last line level with the neighbour's bottom, and the
 * slack between the two groups (DESIGN.md "Layout" - an auto margin, never
 * space-between). For pressen's downloads under its text, beside the contacts.
 *
 * The padding keeps the one blank line when there is no slack - a stacked
 * column on a phone, where the auto margin resolves to nothing.
 */
.lu-textblock > .elementor-widget-wrap:has(> .lu-to-end) {
	flex-direction: column;
	flex-wrap: nowrap;
	align-content: normal;
}

.lu-textblock > .elementor-widget-wrap > .elementor-widget.lu-to-end {
	margin-block-start: auto;
	padding-block-start: var(--lu-type-h4-lh);
}


/* ==========================================================================
   20. lu-annoncer-head
   ==========================================================================
   The "Annoncer" label belongs to the adverts underneath it, so it does not get
   the 90px section rhythm - that pushed it 100px clear of the row it labels.
   ========================================================================== */

.lu-annoncer-head {
	margin-block: var(--lu-section-gap) 0;
}

.lu-annoncer-head + .elementor-section,
.lu-annoncer-row {
	margin-block-start: 20px;
}


/* ==========================================================================
   21. lu-video
   ==========================================================================
   A video embed shown as a still with a play button over it.

   THE COVER IMAGE IS NOT SET HERE. Elementor's video widget already has an
   "Image Overlay" control, so the client picks the still in the editor -
   Content -> Image Overlay - and can change it whenever they like. Without one
   the widget falls back to YouTube's own auto-generated poster, which on this
   video is a frame with a burnt-in subtitle.

   All this adds is the button: Elementor draws a bare glyph, the design draws a
   small rounded box around it. The box takes its colour from the fill pairing
   (section 10) so it can be recoloured with a class; the GLYPH keeps Elementor's
   own "Play Icon Color" control, so that stays editable too.

   Applied to: a video widget, alongside a lu-fill-* class.
   ========================================================================== */

.lu-video .elementor-custom-embed-image-overlay {
	position: relative;
}

.lu-video .elementor-custom-embed-image-overlay img {
	object-fit: cover;
}

/**
 * While Smush lazy-loads the cover, its placeholder rule gives the image the
 * FILE's ratio (1500 x 1000 is 3:2), not the video's 16:9, so the tile shrank
 * 36px the moment the still arrived and the page jumped. Keep the video's own
 * ratio throughout. !important because Smush's own rule is (lu-video--portrait
 * has its own version).
 */
.lu-video .elementor-custom-embed-image-overlay img:is(.lazyload, .lazyloading) {
	aspect-ratio: var(--video-aspect-ratio) !important;
}

/**
 * A subtle wash over the still. It sits between the image and the play button -
 * `pointer-events: none` so it never intercepts the click that opens the
 * lightbox - and takes its colour from the palette, so it tints rather than
 * simply greys.
 */
.lu-video .elementor-custom-embed-image-overlay::after {
	content: "";
	position: absolute;
	inset: 0;
	background-color: var(--lu-media-tint);
	pointer-events: none;
}

.lu-video .elementor-custom-embed-play {
	/* 68x47 with a 6px radius, measured off the frame (node I1:39;33:4). */
	width: 68px;
	height: 47px;
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 6px;
	background-color: var(--lu-fill-bg, var(--lu-stat-blue));
	transition: transform .2s ease;
	/* The play button is a CHILD of the image overlay, so the tint's ::after -
	 * later in the box order - paints over it and dulls it. One notch lifts it
	 * clear without creating a stacking context anything else has to reason
	 * about. */
	z-index: 1;
}

/**
 * Elementor centres this button with
 *   transform: translate(calc(-50% * var(--direction-multiplier)), -50%)
 * so ANY transform written here has to carry that translate too. Setting a bare
 * `scale()` replaces it outright and the button jumps 34px right and 23px down
 * on hover - it looked like the button was sliding rather than growing.
 *
 * --direction-multiplier is Elementor's RTL flag; it is passed through rather
 * than assumed so the button stays centred in both directions.
 */
.lu-video .elementor-custom-embed-play,
.lu-video:hover .elementor-custom-embed-play {
	--lu-play-center: translate(calc(-50% * var(--direction-multiplier, 1)), -50%);
}

/**
 * Elementor's glyph is a play triangle inside a ring; the design draws a plain
 * triangle. Rather than swapping the icon - which the widget gives no control
 * for - the glyph's own ::before is dropped and the triangle is drawn with
 * borders on the <i> itself.
 *
 * Doing it on the <i> rather than the box keeps BOTH Elementor controls live:
 *   Play Icon Color -> `color` on the <i>  -> currentColor fills the triangle
 *   Play Icon Size  -> `font-size` on it   -> the em border-widths scale with it
 */
.lu-video .elementor-custom-embed-play i {
	text-shadow: none;   /* the widget's stale -65/23/34 shadow, cleared at source too */
	width: 0;
	height: 0;
	border-style: solid;
	border-width: 0.45em 0 0.45em 0.75em;
	border-color: transparent transparent transparent currentColor;
}

.lu-video .elementor-custom-embed-play i::before {
	content: none;
}

/**
 * ...and the SIZE has a default here, because the control is usually empty.
 *
 * Only the front page's video ever had Play Icon Size set (20px). The 26 that
 * waves 3, 4 and 6 built never did, so they fell through to Elementor's own
 * `font-size: 100px` and the triangle came out 75x90 inside the 68x47 box.
 * One extra class, (0,3,1), clears Elementor's default; the control's
 * per-element rule, (0,4,1) and up, still beats this when someone sets it.
 */
.lu-video.elementor-widget-video .elementor-custom-embed-play i {
	font-size: 20px;
}

/**
 * Optical centring. A right-pointing triangle has its visual mass to the left
 * of its bounding box, so a geometrically centred one reads as sitting too far
 * left. Nudging it right by a couple of pixels fixes that - the standard
 * correction for a play glyph.
 *
 * Done with a transform rather than a margin: the box is a centred flex
 * container, so a 2px margin would only move it 1px.
 */
.lu-video .elementor-custom-embed-play i {
	transform: translateX(2px);
}

.lu-video:hover .elementor-custom-embed-play {
	transform: var(--lu-play-center) scale(1.08);
}

/* Reduced motion drops the growth, NOT the transform - `transform: none` here
 * would un-centre the button. */
@media (prefers-reduced-motion: reduce) {
	.lu-video .elementor-custom-embed-play { transition: none; }
	.lu-video:hover .elementor-custom-embed-play { transform: var(--lu-play-center); }
}


/* ==========================================================================
   22. lu-card-grid-3, lu-card-grid-2
   ==========================================================================
   Three news cards in a row, always one height: "Seneste nyheder" at the end of
   every news post (DESIGN.md "Articles", decision D1).

   A VARIANT, not a change to lu-card-grid. The front page's two news cards
   share their row with the events panel and take their height from it
   (sections 17 and 18); nothing here reaches them.

   Applied to: an ova_blog widget, together with lu-card, lu-card-grid and a
   fill pairing. The Elementor template "Seneste nyheder" carries it.

   lu-card-grid-2 is the same card two across - the news archive, where the
   cards share the page with the sidebar (index.php; DESIGN.md "Listings").
   Every rule below names both; only the track count and the space between
   rows of cards differ, at the end of the section.
   ========================================================================== */

/* Three tracks from the tablet breakpoint up. Below it lu-card-grid's own
 * single column applies, and this rule must not follow it down there. */
@media (min-width: 768px) {
	:is(.lu-card-grid-2, .lu-card-grid-3) .ova-wrap-grid {
		grid-template-columns: repeat(3, minmax(0, 1fr));
		/* Rows sized by their content. lu-card-grid's `1fr auto` exists to let the
		 * front page's media absorb a taller neighbour; with three equal cards and
		 * no neighbour, `1fr` only let the photographs grow to 416px. */
		grid-template-rows: auto auto;
	}

	:is(.lu-card-grid-2, .lu-card-grid-3) article.post-wrap .post-media {
		min-block-size: 0;
	}
}

/**
 * A card grid that stands on its own sizes to its content.
 *
 * Section 17 hands `height: 100%` down the whole widget so the front page's
 * cards can fill a row cell. Here the widget sits under its own heading in a
 * plain column, so 100% of the column is the heading AND the cards - and the
 * grid overflowed the section by exactly the heading's height, running over
 * the footer's "Annoncer" label.
 */
:is(.lu-card-grid-2, .lu-card-grid-3),
:is(.lu-card-grid-2, .lu-card-grid-3) > .elementor-widget-container,
:is(.lu-card-grid-2, .lu-card-grid-3) .ova-blog,
:is(.lu-card-grid-2, .lu-card-grid-3) .ova-wrap-grid {
	height: auto;
}

/**
 * ONE HEIGHT AT EVERY WIDTH - including stacked on a phone, where there is no
 * row to even the cards out.
 *
 * Everything in a card is a fixed height except the title: the media is a
 * ratio, the chip and the read-more are one line each. So the title gets room
 * for three lines whatever it holds, and a longer one stops at three. That
 * puts every card's read-more on the same line, in a row or down a column.
 *
 * Same selector shape as the title rule in section 3, later in the file.
 */
body :is(.lu-card-grid-2, .lu-card-grid-3) article.post-wrap .post-title h2.post-title {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 3;
	line-clamp: 3;
	overflow: hidden;
	min-block-size: calc(3 * var(--lu-card-title-lh));
}

/**
 * A news card's photo meets its body - on a news post too.
 *
 * theme.css styles the POST'S OWN photo with
 *   .single-post article.post-wrap .post-media { margin-bottom: 52px }   (0,2,1)
 * and ova_blog's cards reuse exactly that markup, so every card in "Seneste
 * nyheder" opened a 52px strip of page ground between its photograph and its
 * coloured body, and the date chip no longer straddled the edge. The front page
 * never showed it because it is not a `single-post` page. Stated for every
 * lu-card news card, one notch above the theme's rule, so any future card on a
 * post is covered.
 */
body .lu-card article.post-wrap .post-media {
	margin-block-end: 0;
}


/* The two-across variant. Beside the sidebar each card is 490px at 1440; below
 * about 1100 two would be under 300, so the column holds one until the phone
 * layout takes over. */
@media (min-width: 768px) {
	.lu-card-grid-2 .ova-wrap-grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	/**
	 * Space between ROWS of cards - which a row gap cannot give. The wrapper's
	 * rows are the halves of a card (a photograph row and a body row, shared
	 * through subgrid), so a row gap would open between every photograph and
	 * its own body. A subgrid's margin goes into its edge track instead, below
	 * the body, which is the one place the space belongs.
	 */
	.lu-card-grid-2 article.post-wrap {
		margin-block-end: var(--lu-col-gap);
	}
}

@media (min-width: 768px) and (max-width: 1099px) {
	.lu-card-grid-2 .ova-wrap-grid {
		grid-template-columns: minmax(0, 1fr);
	}
}

/* A post without a photograph keeps its media box, filled, so its row keeps
 * one height (18 of the 236 posts). */
.lu-card .lu-card__media--empty {
	background-color: var(--lu-surface-green);
}


/* ==========================================================================
   23. lu-labels
   ==========================================================================
   Categories as small labels - the date chip's shape: Lysegroen fade behind
   Primaer, square, inverting on hover, filled when it is the page you are on.
   The same look the post sidebar gives its category widget (restyle.css
   section 7), as a component for markup this theme prints itself.

     lu-labels        Broedtekst on a 32px label: an event page's categories
     lu-labels--sm    one step down, for a calendar row: 14/28, 12/24 on phones

   Applied to: a <ul> of links (inc/listing.php, lu_event_labels()).
   ========================================================================== */

.lu-labels {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin: 0;
	padding: 0;
	list-style: none;
}

.lu-labels > li {
	margin: 0;
	padding: 0;
}

/* (0,1,2): the Kit re-states Broedtekst on every <a> at (0,1,1). */
body .lu-labels a {
	display: block;
	padding: 6px 12px;
	background-color: var(--lu-surface-green);
	font-family: var(--lu-font-body);
	font-size: var(--lu-type-body-size);
	font-weight: 400;
	line-height: var(--lu-type-body-lh);
	color: var(--lu-primary);
	text-decoration: none;
}

body .lu-labels a:hover,
body .lu-labels a.is-current {
	background-color: var(--lu-primary);
	color: var(--lu-surface-green);
}

.lu-labels--sm {
	gap: 6px;
}

body .lu-labels--sm a {
	padding: 0 var(--lu-label-sm-pad);
	font-size: var(--lu-label-sm-size);
	line-height: var(--lu-label-sm-lh);
}


/* ==========================================================================
   24. lu-event-row, lu-month
   ==========================================================================
   One event in a list, and the month heading above a group of them - the
   calendar, and "Flere arrangementer" under an event.

       +-----+ Fredag 18. september          (Broedtekst bold)
       | (O) | Kreaaften                     (H3; H4 on phones)       >
       +-----+ Kl. 18.00-22.00 - venue       (fact, 20/24; Broedtekst on phones)
               [Region Aarhus] [Social]      (lu-labels--sm)
       ------------------------------------------------------------------ rule

   The logo is round, 24px clear of the rule above and below: it sets the
   row's least height, and its top is level with the date. The whole row is the
   title's link (a stretched ::after); the labels sit above it and stay links
   of their own. Grown out of lu-list - title over meta, a rule under each.

   Applied to: an <li> in a <ul class="lu-event-list"> (inc/listing.php).
   ========================================================================== */

.lu-event-list {
	margin: 0;
	padding: 0;
	list-style: none;
}

.lu-event-row {
	position: relative;
	display: grid;
	grid-template-columns: var(--lu-event-logo) minmax(0, 1fr) auto;
	column-gap: var(--lu-event-row-gap);
	align-items: start;
	margin: 0;
	padding-block: var(--lu-event-row-pad);
	border-bottom: var(--lu-rule);
	color: var(--lu-primary);
}

.lu-event-row__logo {
	display: block;
	inline-size: var(--lu-event-logo);
	aspect-ratio: 1;
	border-radius: 50%;
	overflow: hidden;
	background-color: var(--lu-white);
}

.lu-event-row__logo img {
	display: block;
	inline-size: 100%;
	block-size: 100%;
	object-fit: cover;
}

.lu-event-row__logo--empty {
	background-color: var(--lu-surface-green);
}

.lu-event-row__text {
	display: grid;
	gap: 8px;
	justify-items: start;
	min-inline-size: 0;
}

.lu-event-row__date {
	margin: 0;
	font-family: var(--lu-font-body);
	font-size: var(--lu-type-body-size);
	font-weight: 700;
	line-height: var(--lu-type-body-lh);
}

/* (0,2,1): the Kit sets h3 at (0,1,1), and a heading's size has to beat it. */
body[class*="elementor-kit-"] .lu-event-row__title {
	margin: 0;
	font-family: var(--lu-font-display);
	font-size: var(--lu-type-h3-size);
	font-weight: 500;
	line-height: var(--lu-type-h3-lh);
	letter-spacing: var(--lu-type-h3-ls);
	color: inherit;
	/* "Hovedbestyrelsesmoede" is one word (DESIGN.md "Type"). */
	overflow-wrap: break-word;
	hyphens: auto;
}

body .lu-event-row__title a {
	font: inherit;
	letter-spacing: inherit;
	color: inherit;
	text-decoration: none;
}

.lu-event-row__title a::after {
	content: "";
	position: absolute;
	inset: 0;
}

/* Hovering anywhere on the row IS hovering this link, so the title takes the
 * link hover - Sekundær, no underline (DESIGN.md "Colour") - from the row.
 * (0,3,2). */
body .lu-event-row:hover .lu-event-row__title a {
	color: var(--lu-secondary);
	text-decoration: none;
}

.lu-event-row__meta {
	margin: 0;
	font-family: var(--lu-font-display);
	font-size: var(--lu-type-fact-size);
	font-weight: 500;
	line-height: var(--lu-type-fact-lh);
}

.lu-event-row .lu-labels {
	position: relative;
	z-index: 1;
	margin-block-start: 8px;
}

/* The menu's chevron, turned to point right - drawn, not a glyph. */
.lu-event-row__chevron {
	align-self: center;
	inline-size: 24px;
	block-size: 24px;
	background-color: currentColor;
	-webkit-mask: var(--lu-icon-chevron) center / contain no-repeat;
	mask: var(--lu-icon-chevron) center / contain no-repeat;
	transform: rotate(-90deg);
	transition: translate 0.2s ease;
}

.lu-event-row:hover .lu-event-row__chevron {
	translate: 4px 0;
}

@media (prefers-reduced-motion: reduce) {
	.lu-event-row__chevron { transition: none; }
}

/* The month heading: H4, with the rule the first row hangs from. */
body[class*="elementor-kit-"] .lu-month {
	margin: 0;
	padding-block-end: 16px;
	border-bottom: var(--lu-rule);
	font-family: var(--lu-font-display);
	font-size: var(--lu-type-h4-size);
	font-weight: 500;
	line-height: var(--lu-type-h4-lh);
	letter-spacing: var(--lu-type-h4-ls);
	color: var(--lu-primary);
}

@media (max-width: 767px) {
	.lu-event-row__text {
		gap: 4px;
	}

	body[class*="elementor-kit-"] .lu-event-row__title {
		font-size: var(--lu-type-h4-size);
		line-height: var(--lu-type-h4-lh);
		letter-spacing: var(--lu-type-h4-ls);
	}

	.lu-event-row__meta {
		font-family: var(--lu-font-body);
		font-size: var(--lu-type-body-size);
		font-weight: 400;
		line-height: var(--lu-type-body-lh);
	}
}


/* ==========================================================================
   25. lu-facts
   ==========================================================================
   Dato / Tid / Sted (and Arrangoer, when there is one) between two Primaer
   rules: the label in Broedtekst, exactly as the text below it, and the fact
   under it in the display face at 20/24. As many equal columns as there are
   facts - a fact left empty is not printed - stacked on a phone.

   Applied to: a <dl> of <div><dt/><dd/></div> (ovaev-templates/single-event.php).
   ========================================================================== */

.lu-facts {
	display: grid;
	grid-auto-flow: column;
	grid-auto-columns: minmax(0, 1fr);
	column-gap: 40px;
	margin: 0;
	border-top: 1px solid var(--lu-primary);
	border-bottom: 1px solid var(--lu-primary);
	color: var(--lu-primary);
}

.lu-facts > div {
	display: grid;
	gap: 4px;
	align-content: start;
	min-inline-size: 0;
	padding-block: 16px;
}

.lu-facts dt {
	margin: 0;
	font-family: var(--lu-font-body);
	font-size: var(--lu-type-body-size);
	font-weight: 400;
	line-height: var(--lu-type-body-lh);
}

.lu-facts dd {
	margin: 0;
	font-family: var(--lu-font-display);
	font-size: var(--lu-type-fact-size);
	font-weight: 500;
	line-height: var(--lu-type-fact-lh);
	overflow-wrap: anywhere;
}

body .lu-facts dd a {
	font: inherit;
	color: inherit;
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 0.18em;
}

/* Underlined at rest, and it stays underlined on hover (D1, wave 3). */
body .lu-facts dd a:hover {
	color: var(--lu-secondary);
}

/**
 * Four facts are two across on a tablet. Kontakt os's "info@landboungdom.dk" is
 * one word at 20px, about 220px, and a quarter of a 720px row is 150: the item
 * ran 44px past the page at 768. `anywhere` above is only the floor.
 */
@media (min-width: 768px) and (max-width: 1024px) {
	.lu-facts:has(> div:nth-child(4)) {
		grid-auto-flow: row;
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (max-width: 767px) {
	.lu-facts {
		grid-auto-flow: row;
		grid-template-columns: minmax(0, 1fr);
	}

	.lu-facts > div + div {
		border-top: var(--lu-rule);
	}
}

/**
 * lu-facts--panel - the facts on a fill, one fact per row.
 *
 * For facts that sit in a text column rather than across the page (Vækstlaget's
 * weekends, price and sign-up, beside the video). The row's Primær rules give
 * way to a fill pairing and the link tile's diagonal corners; each fact is a
 * row with its label in the first third and the fact in the other two, with a
 * rule between rows.
 *
 * It switches on its own width, not the window's, because it lives in columns:
 * below about 400px each label sits over its fact. The widget holding it is the
 * container, so the text-editor needs nothing but the markup.
 *
 * Applied to: <dl class="lu-facts lu-facts--panel lu-fill-green"> in a text-editor.
 */
.elementor-widget:has(> .elementor-widget-container > .lu-facts--panel),
.elementor-widget-container:has(> .lu-facts--panel) {
	container-type: inline-size;
}

.lu-facts.lu-facts--panel {
	grid-auto-flow: row;
	grid-template-columns: minmax(0, 1fr);
	padding: 8px 32px;
	border: 0;
	border-radius: var(--lu-radius-band);
	background-color: var(--lu-fill-bg, var(--lu-surface-green));
	color: var(--lu-fill-fg, var(--lu-primary));
}

.lu-facts.lu-facts--panel > div {
	grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
	align-items: baseline;
	gap: 4px 20px;
}

.lu-facts.lu-facts--panel > div + div {
	border-top: var(--lu-rule);
}

@container (max-width: 399px) {
	.lu-facts.lu-facts--panel {
		padding-inline: 20px;
	}

	.lu-facts.lu-facts--panel > div {
		grid-template-columns: minmax(0, 1fr);
	}
}


/* ==========================================================================
   26. lu-pagination
   ==========================================================================
   "Forrige 1 2 ... 24 Naeste": 40px boxes ruled in Primaer, the current page
   filled. Replaces the theme's and the plugin's lime squares.

   Applied to: <nav class="lu-pagination"><ul> of paginate_links() output
   (inc/listing.php, lu_pagination()).
   ========================================================================== */

.lu-pagination {
	margin-block-start: var(--lu-post-deck-gap);
}

.lu-pagination ul {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin: 0;
	padding: 0;
	list-style: none;
}

.lu-pagination li {
	margin: 0;
}

body .lu-pagination .page-numbers {
	box-sizing: border-box;
	display: grid;
	place-items: center;
	min-inline-size: var(--lu-pager-size);
	block-size: var(--lu-pager-size);
	padding-inline: 12px;
	border: 1px solid var(--lu-primary);
	font-family: var(--lu-font-body);
	font-size: var(--lu-type-body-size);
	font-weight: 400;
	line-height: var(--lu-type-body-lh);
	color: var(--lu-primary);
	text-decoration: none;
}

body .lu-pagination a.page-numbers:hover,
body .lu-pagination .page-numbers.current {
	background-color: var(--lu-primary);
	color: var(--lu-surface-green);
}

body .lu-pagination .page-numbers.dots {
	min-inline-size: 0;
	padding-inline: 4px;
	border-color: transparent;
}


/* ==========================================================================
   27. lu-filter
   ==========================================================================
   The calendar's filter: Fra, Til, Kategori and Find in one row on the page's
   lines - fields 48px, ruled in Primaer like the sidebar's search, and Find
   filled. On a phone the fields fold behind "Filtrer kalenderen" (decision
   D3): a checkbox and its label, so it works without a script.

   Applied to: ovaev-templates/search_form.php.
   ========================================================================== */

.lu-filter {
	margin: 0 0 var(--lu-post-deck-gap);
	color: var(--lu-primary);
}

.lu-filter__switch,
.lu-filter__toggle {
	display: none;
}

.lu-filter__fields {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr)) auto;
	gap: 20px;
	align-items: end;
}

.lu-filter__field {
	position: relative;
	display: grid;
	gap: 8px;
}

body .lu-filter label {
	margin: 0;
	font-family: var(--lu-font-body);
	font-size: var(--lu-type-body-size);
	font-weight: 700;
	line-height: var(--lu-type-body-lh);
	color: inherit;
}

body .lu-filter input[type="text"],
body .lu-filter select {
	box-sizing: border-box;
	inline-size: 100%;
	block-size: var(--lu-field-h);
	margin: 0;
	padding: 0 14px;
	border: 1px solid var(--lu-primary);
	border-radius: 0;
	background: transparent;
	font-family: var(--lu-font-body);
	font-size: var(--lu-type-body-size);
	font-weight: 400;
	line-height: var(--lu-type-body-lh);
	color: inherit;
	-webkit-appearance: none;
	appearance: none;
}

body .lu-filter input[type="text"]::placeholder {
	color: color-mix(in srgb, var(--lu-primary) 60%, transparent);
}

body .lu-filter select {
	padding-inline-end: 40px;
}

/**
 * ova-events hands the category <select> to Select2, which hides it (1px,
 * clipped) and draws a box of its own after it. So the visible field is
 * Select2's `.select2-selection`, and it takes the field's geometry here; the
 * hidden select is taken out of the flow, or the grid gap is counted twice and
 * the label sits 8px lower than its neighbours'.
 */
.lu-filter__field .select2-hidden-accessible {
	position: absolute !important;
}

.lu-filter .select2-container {
	inline-size: 100% !important;
}

body .lu-filter .select2-container .select2-selection--single {
	box-sizing: border-box;
	block-size: var(--lu-field-h);
	border: 1px solid var(--lu-primary);
	border-radius: 0;
	background: transparent;
}

body .lu-filter .select2-container .select2-selection__rendered {
	padding: 0 40px 0 14px;
	font-family: var(--lu-font-body);
	font-size: var(--lu-type-body-size);
	line-height: calc(var(--lu-field-h) - 2px);
	color: var(--lu-primary);
}

.lu-filter .select2-selection__arrow {
	display: none;
}

/* The select's arrow, drawn over it - the same chevron as the menu. */
.lu-filter__field--select::after {
	content: "";
	position: absolute;
	inset-inline-end: 14px;
	inset-block-end: 16px;
	inline-size: 16px;
	block-size: 16px;
	background-color: currentColor;
	-webkit-mask: var(--lu-icon-chevron) center / contain no-repeat;
	mask: var(--lu-icon-chevron) center / contain no-repeat;
	pointer-events: none;
}

body .lu-filter button {
	block-size: var(--lu-field-h);
	margin: 0;
	padding: 0 40px;
	border: 0;
	border-radius: 0;
	background-color: var(--lu-primary);
	font-family: var(--lu-font-body);
	font-size: var(--lu-type-body-size);
	font-weight: 700;
	line-height: var(--lu-type-body-lh);
	color: var(--lu-surface-green);
	cursor: pointer;
}

body .lu-filter button:hover {
	background-color: var(--lu-secondary);
	color: var(--lu-primary);
}

@media (max-width: 767px) {
	/* Visually hidden, not display: none - it has to stay reachable from the
	 * keyboard, and the label's focus ring stands in for it. */
	.lu-filter__switch {
		display: block;
		position: absolute;
		inline-size: 1px;
		block-size: 1px;
		opacity: 0;
		pointer-events: none;
	}

	body .lu-filter .lu-filter__toggle {
		display: flex;
		align-items: center;
		justify-content: space-between;
		block-size: var(--lu-field-h);
		padding: 0 14px;
		border: 1px solid var(--lu-primary);
		cursor: pointer;
	}

	.lu-filter__toggle::after {
		content: "";
		inline-size: 16px;
		block-size: 16px;
		background-color: currentColor;
		-webkit-mask: var(--lu-icon-chevron) center / contain no-repeat;
		mask: var(--lu-icon-chevron) center / contain no-repeat;
	}

	.lu-filter__switch:checked + .lu-filter__toggle::after {
		transform: rotate(180deg);
	}

	.lu-filter__switch:focus-visible + .lu-filter__toggle {
		outline: 2px solid var(--lu-primary);
		outline-offset: 2px;
	}

	.lu-filter__fields {
		display: none;
		grid-template-columns: minmax(0, 1fr);
		gap: 16px;
		margin-block-start: 16px;
	}

	.lu-filter__switch:checked ~ .lu-filter__fields {
		display: grid;
	}

	body .lu-filter button {
		inline-size: 100%;
	}
}



/* ==========================================================================
   28. Hub-page modifiers: lu-card-nochip, lu-span-all, lu-section-lead
   ==========================================================================
   Three small companions for the hub pages (DESIGN.md "Hubs").

     lu-card-nochip   a hand-built lu-card with no date chip, so its body puts
                      the top padding back (section 3's --lu-card-pad-top note)
     lu-span-all      a column across every track of an lu-row - the section
                      heading over a row of cards, in the same section, so
                      the heading and its cards stay one block
     lu-section-lead  a section whose heading leads content in the same column
                      (the events): 40px under the heading, as "Seneste nyheder"
   ========================================================================== */

.lu-card-nochip {
	--lu-card-pad-top: var(--lu-card-pad);
}

.lu-row > .elementor-container > .elementor-column.lu-span-all {
	grid-column: 1 / -1;
}

/* With the row's own gap below it (20px, 52 in a wrapping row, 0 in a contact
 * list), the heading ends 40px over the cards. */
.lu-span-all .lu-section-heading {
	margin-block-end: calc(40px - var(--lu-row-gap, var(--lu-col-gap)));
}

.lu-section-lead .lu-section-heading {
	margin-block-end: 40px;
}


/* ==========================================================================
   29. lu-link-tile
   ==========================================================================
   The toolbox card without its photo (decision D4): a pink or dark red box with
   the brand's diagonal corners, an H3 title, a line of text and "Læs mere →".
   "Værktøjskassen for pløjning", "Landspløjeudvalg", "Jeg er medlem".

   Applied to: a hand-built card column - lu-card lu-card-lg lu-link-tile and a
   fill pairing - holding only the lu-card__body section (no lu-card__media).
   ========================================================================== */

.lu-link-tile .lu-card__body {
	border-radius: var(--lu-radius-band);
}

/**
 * Four across (LU's organisering) a tile is ~315px, and an H3 hyphenated
 * "Hoved-bestyrelsen". Below ~400px of its own width the title is H4; the
 * hubs' tiles are two across and keep their H3. A container query, because the
 * same tile sits in rows of two and of four at one window width.
 */
.lu-link-tile {
	container-type: inline-size;
}

@container (max-width: 399px) {
	.lu-link-tile .lu-card__body {
		--lu-card-title-size: var(--lu-type-h4-size);
		--lu-card-title-lh:   var(--lu-type-h4-lh);
		--lu-card-title-ls:   var(--lu-type-h4-ls);
		--lu-card-title-gap:  16px;
	}
}


/* ==========================================================================
   30. lu-link-list
   ==========================================================================
   Many links, read rather than looked at (decision D5): H4 titles between
   rules, two columns, the calendar row's chevron - and, when the link is a file
   or a Google document, what kind, read from the address itself so nobody has
   to type it.

   Applied to: an Elementor Icon List widget (each item a text and a link), or
   the ova_archive_sev widget on Udvalg og netværk (still drawn from the
   committee posts).
   ========================================================================== */

.lu-link-list .elementor-icon-list-items,
body .lu-link-list .ova_archive_sev .content .wp-content {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	column-gap: 40px;
	margin: 0;
	padding: 0;
	list-style: none;
}

.lu-link-list .elementor-icon-list-item,
.lu-link-list .ova_archive_sev .items {
	margin: 0;
	padding: 0;
	border-bottom: var(--lu-rule);
}

.lu-link-list .elementor-icon-list-item:nth-child(-n + 2),
.lu-link-list .ova_archive_sev .items:nth-child(-n + 2) {
	border-top: var(--lu-rule);
}

.lu-link-list .elementor-icon-list-icon,
.lu-link-list .ova_archive_sev .icon,
.lu-link-list .ova_archive_sev .icon-hide,
.lu-link-list .ova_archive_sev .content-sub {
	display: none;
}

/**
 * The plugin draws each committee as a box a third wide (0,4,0 on the column
 * count), 188px tall, whose title rises 67px and whose excerpt slides in on
 * hover. A list row has none of it: the box, the gutters and the motion cleared.
 * Its link wraps the whole item, so the link is the row.
 */
body .lu-link-list .ova_archive_sev,
body .lu-link-list .ova_archive_sev .content {
	width: auto;
	margin: 0;
	padding: 0;
}

body .lu-link-list .ova_archive_sev .content .items {
	width: auto;
	margin: 0;
	padding: 0;
}

body .lu-link-list .ova_archive_sev .items .wp-items,
body .lu-link-list .ova_archive_sev .items .wp-items:hover {
	flex: 1 1 auto;
	min-height: 0;
	padding: 0;
	border: 0;
	box-shadow: none;
	overflow: visible;
	transition: none;
}

body[class*="elementor-kit-"] .lu-link-list .ova_archive_sev .items .title,
body[class*="elementor-kit-"] .lu-link-list .ova_archive_sev .items .wp-items:hover .title {
	top: 0;
	margin: 0;
	font-family: var(--lu-font-display);
	font-size: var(--lu-type-h4-size);
	font-weight: 500;
	line-height: var(--lu-type-h4-lh);
	color: inherit;
	transition: none;
}

body .lu-link-list .elementor-icon-list-item > a,
body .lu-link-list .ova_archive_sev .items > a {
	display: flex;
	align-items: center;
	gap: 12px;
	inline-size: 100%;
	padding-block: 20px;
	font-family: var(--lu-font-display);
	font-size: var(--lu-type-h4-size);
	font-weight: 500;
	line-height: var(--lu-type-h4-lh);
	color: inherit;
	text-decoration: none;
}

body .lu-link-list .elementor-icon-list-text {
	flex: 1 1 auto;
	padding: 0;
	font: inherit;
	color: inherit;
}


/* The chevron - last - and the kind of link before it. */
.lu-link-list .elementor-icon-list-item > a::after,
.lu-link-list .ova_archive_sev .items > a::after {
	content: "";
	order: 3;
	flex: 0 0 auto;
	inline-size: 20px;
	block-size: 20px;
	background-color: currentColor;
	-webkit-mask: var(--lu-icon-chevron) center / contain no-repeat;
	mask: var(--lu-icon-chevron) center / contain no-repeat;
	transform: rotate(-90deg);
	transition: translate 0.2s ease;
}

.lu-link-list .elementor-icon-list-item > a:hover::after,
.lu-link-list .ova_archive_sev .items > a:hover::after {
	translate: 4px 0;
}

body .lu-link-list .elementor-icon-list-item > a:hover,
body .lu-link-list .ova_archive_sev .items > a:hover {
	color: var(--lu-secondary);
}

:is(.lu-link-list .elementor-icon-list-item > a, .lu-toolbox .ova_box_resource ul.content li a)::before {
	order: 2;
	flex: 0 0 auto;
	font-family: var(--lu-font-body);
	font-size: var(--lu-type-body-size);
	font-weight: 400;
	line-height: var(--lu-type-body-lh);
}

:is(.lu-link-list .elementor-icon-list-item > a, .lu-toolbox .ova_box_resource ul.content li a)[href$=".pdf" i]::before { content: "PDF"; }
:is(.lu-link-list .elementor-icon-list-item > a, .lu-toolbox .ova_box_resource ul.content li a):is([href$=".xlsx" i], [href$=".xls" i])::before { content: "Excel"; }
:is(.lu-link-list .elementor-icon-list-item > a, .lu-toolbox .ova_box_resource ul.content li a):is([href$=".docx" i], [href$=".doc" i])::before { content: "Word"; }
:is(.lu-link-list .elementor-icon-list-item > a, .lu-toolbox .ova_box_resource ul.content li a):is([href*="drive.google.com"], [href*="docs.google.com"])::before { content: "Google Drev"; }
:is(.lu-link-list .elementor-icon-list-item > a, .lu-toolbox .ova_box_resource ul.content li a)[href$=".ai" i]::before { content: "AI"; }
:is(.lu-link-list .elementor-icon-list-item > a, .lu-toolbox .ova_box_resource ul.content li a):is([href$=".jpg" i], [href$=".jpeg" i])::before { content: "JPEG"; }
:is(.lu-link-list .elementor-icon-list-item > a, .lu-toolbox .ova_box_resource ul.content li a)[href$=".png" i]::before { content: "PNG"; }
:is(.lu-link-list .elementor-icon-list-item > a, .lu-toolbox .ova_box_resource ul.content li a)[href$=".zip" i]::before { content: "ZIP"; }

/**
 * lu-link-list--sm - a few files under a heading, rather than a page of links:
 * one column, and the title at Broedtekst, the size of the file kind beside it,
 * on 12px rows. For pressen's downloads (people proposal).
 */
.lu-link-list.lu-link-list--sm .elementor-icon-list-items {
	grid-template-columns: minmax(0, 1fr);
}

.lu-link-list.lu-link-list--sm .elementor-icon-list-item:nth-child(2) {
	border-top: 0;
}

body .lu-link-list.lu-link-list--sm .elementor-icon-list-item > a {
	padding-block: 12px;
	font-family: var(--lu-font-body);
	font-size: var(--lu-type-body-size);
	font-weight: 400;
	line-height: var(--lu-type-body-lh);
}

@media (prefers-reduced-motion: reduce) {
	.lu-link-list .elementor-icon-list-item > a::after,
	.lu-link-list .ova_archive_sev .items > a::after { transition: none; }
}

@media (max-width: 767px) {
	.lu-link-list .elementor-icon-list-items,
	body .lu-link-list .ova_archive_sev .content .wp-content {
		grid-template-columns: minmax(0, 1fr);
	}

	.lu-link-list .elementor-icon-list-item:nth-child(2),
	.lu-link-list .ova_archive_sev .items:nth-child(2) {
		border-top: 0;
	}
}


/* ==========================================================================
   31. lu-toggle
   ==========================================================================
   Elementor's Toggle, restyled: each question in Mellemrubrik between rules,
   the menu's chevron at the end turning when it is open, the answer in
   Broedtekst. Pløjning's "LU pløjning / Skolepløjning / Veteranpløjning".

   Applied to: a Toggle widget.
   ========================================================================== */

.lu-toggle .elementor-toggle {
	border-top: var(--lu-rule);
}

.lu-toggle .elementor-toggle-item {
	border-bottom: var(--lu-rule);
}

body .lu-toggle .elementor-toggle .elementor-tab-title {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	margin: 0;
	padding: 16px 0;
	border: 0;
	font-family: var(--lu-font-body);
	font-size: var(--lu-type-body-size);
	font-weight: 700;
	line-height: var(--lu-type-body-lh);
	color: inherit;
}

/* Elementor's caret, floated left. At (0,2,0) this lost to a rule setting it to
 * block, and a third flex item pushed the question to the middle of the row. */
body .lu-toggle .elementor-tab-title .elementor-toggle-icon {
	display: none;
}

body .lu-toggle .elementor-toggle-title {
	flex: 1 1 auto;
}

.lu-toggle .elementor-tab-title::after {
	content: "";
	flex: 0 0 auto;
	inline-size: 20px;
	block-size: 20px;
	background-color: currentColor;
	-webkit-mask: var(--lu-icon-chevron) center / contain no-repeat;
	mask: var(--lu-icon-chevron) center / contain no-repeat;
	transition: transform 0.2s ease;
}

.lu-toggle .elementor-tab-title.elementor-active::after {
	transform: rotate(180deg);
}

body .lu-toggle .elementor-toggle-title {
	font: inherit;
	color: inherit;
	text-decoration: none;
}

body .lu-toggle .elementor-toggle .elementor-tab-content {
	margin: 0;
	padding: 0 0 16px;
	border: 0;
	font-family: var(--lu-font-body);
	font-size: var(--lu-type-body-size);
	line-height: var(--lu-type-body-lh);
	color: inherit;
}

.lu-toggle .elementor-tab-content p {
	margin: 0 0 var(--lu-type-body-lh);
}

.lu-toggle .elementor-tab-content p:last-child {
	margin-bottom: 0;
}

body .lu-toggle .elementor-tab-content a {
	font: inherit;
	color: inherit;
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 0.18em;
}

/* Underlined at rest, and it stays underlined on hover (D1, wave 3). */
body .lu-toggle .elementor-tab-content a:hover {
	color: var(--lu-secondary);
}

@media (prefers-reduced-motion: reduce) {
	.lu-toggle .elementor-tab-title::after { transition: none; }
}


/* ==========================================================================
   32. lu-events, lu-band-cta
   ==========================================================================
     lu-events    the [lu_events] shortcode (inc/hubs.php): the calendar's rows
                  hanging from a rule, and "Se hele kalenderen →" under them
     lu-band-cta  a band with its text on the left and a button on the right,
                  centred and stacked on a phone - the "Bliv medlem" template
   ========================================================================== */

.lu-events .lu-event-list {
	border-top: var(--lu-rule);
}

.lu-events__all,
.lu-events__empty {
	margin: 40px 0 0;
	text-align: center;
	font-family: var(--lu-font-body);
	font-size: var(--lu-type-body-size);
	line-height: var(--lu-type-body-lh);
}

body .lu-events__all a {
	font: inherit;
	color: var(--lu-primary);
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 0.18em;
}

/* Underlined at rest, and it stays underlined on hover (D1, wave 3). */
body .lu-events__all a:hover {
	color: var(--lu-secondary);
}

.lu-band-cta {
	padding-block: var(--lu-post-deck-gap);
}

/**
 * Centred at every width, the button under the text (story-pages proposal,
 * 17 September 2026). It was text left and button right on desktop, which fell
 * apart once the text ran to three paragraphs beside a lone button.
 */
.lu-band-cta > .elementor-container {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	justify-items: center;
	row-gap: 40px;
	text-align: center;
}

body .lu-band-cta > .elementor-container > .elementor-column {
	width: 100%;
	max-width: none;
}

body .lu-band-cta .elementor-widget-wrap {
	justify-content: center;
}

.lu-band-cta .elementor-heading-title {
	text-align: center;
}

.lu-band-cta .elementor-widget-text-editor {
	max-width: 880px;
	margin-inline: auto;
}

/* The text at the lead size on desktop and tablet; Brødtekst on a phone. */
@media (min-width: 768px) {
	.lu-band-cta .elementor-widget-text-editor,
	.lu-band-cta .elementor-widget-text-editor p {
		font-family: var(--lu-font-display);
		font-size: var(--lu-type-h4-size);
		font-weight: 500;
		line-height: var(--lu-type-h4-lh);
	}

	.lu-band-cta .elementor-widget-text-editor p + p {
		margin-block-start: var(--lu-type-h4-lh);
	}
}

@media (max-width: 767px) {
	.lu-band-cta > .elementor-container {
		row-gap: 24px;
	}
}


/* ==========================================================================
   33. lu-people, lu-person
   ==========================================================================
   The people pages (DESIGN.md "People"): the news card holding a person. A 4:5
   portrait with the card's rounded top corners, and under it the name at the
   fact size, the job title and the contact lines at 14/18 - the email as a
   link, then "Tlf." and "Mobil" with the number in pairs.

       +-----------+  <- 24px radius, top corners only
       |  portrait |     4:5, focused a third of the way down
       +-----------+
       | Name   20 |
       | Job    14 |
       |-----------|  <- rule
       | e-mail    |
       | Tlf. 33.. |
       +-----------+

   COLUMNS COME FROM THE WIDGET'S WIDTH, NOT THE WINDOW'S. The same card sits
   four across the whole column on Medarbejdere and two across half a row on For
   pressen - where the two are exactly as wide as the four - and at 1000px that
   half row is 466px, a phone's worth. A media query would give the half row two
   160px cards there; a container query gives it the phone's card, on its side:
   the photo on the left, the details beside it.

   Applied to: an ova_team widget, with `lu-people` and a fill pairing
   (`lu-fill-green`). The markup is the theme's -
   ovateam-templates/elementor/ova_team.php - and only where the class is.
   ========================================================================== */

.lu-people > .elementor-widget-container {
	container-type: inline-size;
}

.lu-people__grid {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: var(--lu-col-gap);
	margin: 0;
	padding: 0;
	list-style: none;
}

/* The toolbox grid's 52 between the lines of a wrapped row (lu-row-wrap). */
@container (min-width: 600px) {
	.lu-people__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: 52px; }
}

@container (min-width: 940px) {
	.lu-people__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@container (min-width: 1280px) {
	.lu-people__grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

.lu-person {
	display: grid;
	grid-template-rows: auto 1fr;
	min-inline-size: 0;
	margin: 0;
	padding: 0;
}

.lu-person__media {
	overflow: hidden;
	aspect-ratio: var(--lu-person-ratio);
	border-radius: var(--lu-radius-card);
}

/* Board photos are 4:3 and centred, staff 4:5: a crop a third of the way down
 * keeps both faces in the frame. The ratio is on the box - section 3. */
.lu-person__media img {
	display: block;
	inline-size: 100%;
	block-size: 100%;
	object-fit: cover;
	object-position: 50% 30%;
	border-radius: inherit;
}

.lu-person__body {
	display: grid;
	align-content: start;
	gap: 4px;
	padding: var(--lu-card-pad);
}

/* (0,2,1): the Kit sets every h3 at (0,1,1). */
body .lu-people .lu-person__name {
	margin: 0;
	font-family: var(--lu-font-display);
	font-size: var(--lu-type-fact-size);
	font-weight: 500;
	line-height: var(--lu-type-fact-lh);
	letter-spacing: 0;
	color: inherit;
	hyphens: auto;
	overflow-wrap: break-word;
}

/* "Seniorkommunikationskonsulent" is wider than a card on its side at 360
 * (DESIGN.md "Type" - Danish compounds do not wrap). */
body .lu-people .lu-person__job {
	hyphens: auto;
	overflow-wrap: break-word;
}

/**
 * No photo: the portrait box keeps its size, a step towards the foreground
 * (section 10), with the person's initials in the display face - so a row with
 * one missing photo still reads as a row of people rather than a gap. Hidden
 * from screen readers; the name is right under it.
 */
.lu-person__media--empty {
	display: grid;
	place-items: center;
}

.lu-person__initials {
	font-family: var(--lu-font-display);
	font-size: var(--lu-type-h1-size);
	font-weight: 500;
	line-height: 1;
	letter-spacing: -0.01em;
}

body .lu-people .lu-person__job,
.lu-person__contact {
	margin: 0;
	font-family: var(--lu-font-body);
	font-size: var(--lu-person-detail-size);
	font-weight: 400;
	line-height: var(--lu-person-detail-lh);
	color: inherit;
}

.lu-person__contact {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	column-gap: 12px;
	row-gap: 2px;
	margin-block-start: 12px;
	padding-block-start: 12px;
	border-top: var(--lu-rule);
}

.lu-person__contact > div {
	display: contents;
}

.lu-person__contact dt {
	margin: 0;
	font-weight: 700;
}

.lu-person__contact dd {
	margin: 0;
	min-inline-size: 0;
	font-variant-numeric: tabular-nums;
}

/* The address has no space to break at; it wraps anywhere rather than past the card. */
.lu-person__mail dd {
	grid-column: 1 / -1;
	overflow-wrap: anywhere;
}

/* (0,2,1): the Kit re-states Broedtekst on every <a> at (0,1,1). */
body .lu-people .lu-person__contact a {
	font: inherit;
	color: inherit;
	text-decoration: none;
}

body .lu-people .lu-person__mail a {
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 0.18em;
}

/* Sekundaer, never underlined (DESIGN.md "Colour"). */
body .lu-people .lu-person__contact a:hover {
	color: var(--lu-secondary);
	text-decoration: none;
}

/* On its side, in anything narrower than two cards. */
@container (max-width: 599px) {
	.lu-person {
		grid-template-rows: none;
		grid-template-columns: var(--lu-person-side-media) minmax(0, 1fr);
	}

	.lu-person__initials {
		font-size: var(--lu-type-h3-size);
	}

	.lu-person__media {
		aspect-ratio: auto;
		min-block-size: var(--lu-person-side-min);
		border-radius: var(--lu-radius-card-side);
	}

	/* The details centred on the photo's height, not hung from its top
	 * (wave 1 proposal, user comment). */
	.lu-person__body {
		gap: 2px;
		padding: 14px 16px;
		align-content: center;
	}

	body .lu-people .lu-person__name {
		font-size: var(--lu-person-side-name);
		line-height: var(--lu-person-side-name-lh);
	}
}


/* ==========================================================================
   34. lu-theme
   ==========================================================================
   A story told in themes (Om LandboUngdom): each theme is a row with its
   heading in the first third and its text in the other two, one rule colour
   above, between and below. The rows sit 56 / 32 under the lead that opens
   the page, and 32 / 24 of padding each side of their rule.

   Applied to: a section with `lu-row lu-theme`, its first column holding an
   H4 heading, its second `lu-span-2` holding a text-editor with `lu-prose`.
   ========================================================================== */

.lu-theme {
	padding-block: 32px;
	border-bottom: var(--lu-rule);
	color: var(--lu-primary);
}

.lu-theme:not(.lu-theme + .lu-theme) {
	margin-block-start: var(--lu-post-deck-gap);
	border-top: var(--lu-rule);
}

/* A theme row can lead with a photo instead of a heading (Ud i verden): the
 * first third at 3:2 with the band's corners, the heading then over the text. */
/* !important: Smush's lazy-load placeholder (.lazyload) forces its own width
 * and aspect ratio until the photo loads. */
.lu-theme .lu-theme__media img {
	display: block;
	width: 100% !important;
	height: auto !important;
	aspect-ratio: 3 / 2 !important;
	object-fit: cover;
	border-radius: var(--lu-radius-band);
}

.lu-theme .lu-theme__media,
.lu-theme .lu-theme__media > .elementor-widget-container {
	width: 100%;
}

/* Danish compounds ("Ungdomsorganisation") are wider than a phone's column at
 * H3 (DESIGN.md "Type"). */
.lu-theme .elementor-heading-title {
	hyphens: auto;
	overflow-wrap: break-word;
}

/* A linked heading in a row (the organisation's name): the Kit publishes
 * Brødtekst onto every <a>, so the link has to inherit the heading's face. */
body .lu-theme .elementor-heading-title a {
	font: inherit;
	color: inherit;
	text-decoration: none;
}

body .lu-theme .elementor-heading-title a:hover {
	color: var(--lu-secondary);
	text-decoration: none;
}

@media (max-width: 767px) {
	.lu-theme {
		--lu-row-gap: 12px;
		padding-block: 24px;
	}
}


/* ==========================================================================
   35. lu-quote
   ==========================================================================
   A member speaking, one at a time: Elementor's Testimonial Carousel with the
   portrait (4:5, the band's diagonal corners) beside the quote in the display
   face, the name and role under it, and under those two arrow boxes and a
   count. The client adds a member in the widget as before.

   Set in the widget: Pagination "Fraction", Autoplay off. Everything else is
   here. `lu-quote--long` sets the quote at 24/27 for quotes of 200+ characters.

   The portrait moves above the quote when the widget itself is narrower than
   700px, not the window - a quote in half a row gets the phone's layout.

   Applied to: a testimonial-carousel widget, inside `lu-band lu-fill-*`.
   ========================================================================== */

.lu-quote {
	--lu-quote-media: 315px;
	--lu-quote-gap: 60px;
	--lu-quote-arrow: 48px;
	container-type: inline-size;
}

/* The widget narrows the swiper for its side arrows (calc(95% - 40px), side
 * margins), pads the slide 20px and the pagination row 40px; none of that is
 * wanted once the arrows sit under the quote. */
body .lu-quote .elementor-main-swiper.swiper,
body .lu-gallery .elementor-main-swiper.swiper {
	position: relative;
	width: 100%;
	margin: 0;
}

body .lu-quote .elementor-main-swiper.swiper {
	padding-block-end: 0;
}

body .lu-quote.elementor-element .swiper .swiper-slide {
	padding: 0;
}

body .lu-quote .elementor-testimonial {
	display: grid;
	grid-template-columns: var(--lu-quote-media) minmax(0, 1fr);
	grid-template-areas:
		"media text"
		"media cite"
		"media nav";
	grid-template-rows: 1fr auto var(--lu-quote-arrow);
	column-gap: var(--lu-quote-gap);
	row-gap: var(--lu-type-h4-lh);
	align-items: end;
	text-align: start;
}

.lu-quote .elementor-testimonial__content {
	grid-area: text;
	margin: 0;
}

body .lu-quote .elementor-testimonial__text {
	font-family: var(--lu-font-display);
	font-size: var(--lu-type-h3-size);
	font-style: normal;
	font-weight: 500;
	line-height: var(--lu-type-h3-lh);
	color: inherit;
}

body .lu-quote.lu-quote--long .elementor-testimonial__text {
	font-size: var(--lu-type-h4-size);
	line-height: var(--lu-type-h4-lh);
}

.lu-quote .elementor-testimonial__footer {
	display: contents;
}

body .lu-quote .elementor-testimonial__image {
	grid-area: media;
	align-self: stretch;
	inline-size: 100%;
	aspect-ratio: 4 / 5;
	margin: 0;
	overflow: hidden;
	border-radius: var(--lu-radius-band);
}

body .lu-quote .elementor-testimonial__image img {
	inline-size: 100%;
	block-size: 100%;
	max-inline-size: none;
	object-fit: cover;
	object-position: 50% 30%;
	border-radius: 0;
}

body .lu-quote .elementor-testimonial .elementor-testimonial__cite {
	grid-area: cite;
	display: grid;
	align-items: start;
	margin: 0;
	text-align: start;
	font-family: var(--lu-font-body);
	font-size: var(--lu-type-body-size);
	line-height: var(--lu-type-body-lh);
}

body .lu-quote .elementor-testimonial__name {
	font-weight: 700;
	font-size: inherit;
	color: inherit;
}

body .lu-quote .elementor-testimonial__title {
	font-size: inherit;
	font-weight: 400;
	color: inherit;
}

/* The arrows and count sit in the slide's empty "nav" row, under the cite.
 * `.swiper` is in the selectors and the offsets are physical (top/left) to
 * beat e-swiper.css's `.elementor-element.elementor-pagination-position-outside
 * .swiper .elementor-swiper-button` (0,4,0), which centres the arrows vertically with top + transform. */
body .lu-quote.elementor-element .swiper .elementor-swiper-button,
body .lu-gallery.elementor-element .swiper .elementor-swiper-button {
	position: absolute;
	top: auto;
	bottom: 0;
	transform: none;
	display: grid;
	place-items: center;
	width: var(--lu-quote-arrow, 48px);
	height: var(--lu-quote-arrow, 48px);
	margin: 0;
	border-radius: var(--lu-radius-btn);
	background-color: var(--lu-fill-fg, var(--lu-primary));
	color: var(--lu-fill-bg, var(--lu-surface-green));
	font-size: 20px;
	z-index: 2;
}

body .lu-quote.elementor-element .swiper .elementor-swiper-button:hover,
body .lu-gallery.elementor-element .swiper .elementor-swiper-button:hover {
	background-color: var(--lu-secondary);
}

body .lu-quote.elementor-element .swiper .elementor-swiper-button i,
body .lu-gallery.elementor-element .swiper .elementor-swiper-button i {
	color: inherit;
}

body .lu-quote.elementor-element .swiper .elementor-swiper-button-prev {
	left: calc(var(--lu-quote-media) + var(--lu-quote-gap));
	right: auto;
}

body .lu-quote.elementor-element .swiper .elementor-swiper-button-next {
	left: calc(var(--lu-quote-media) + var(--lu-quote-gap) + var(--lu-quote-arrow) + 12px);
	right: auto;
}

body .lu-quote.elementor-element .swiper .swiper-pagination-fraction,
body .lu-gallery.elementor-element .swiper .swiper-pagination-fraction {
	position: absolute;
	top: auto;
	bottom: 0;
	width: auto;
	height: var(--lu-quote-arrow, 48px);
	display: flex;
	align-items: center;
	font-family: var(--lu-font-body);
	font-size: var(--lu-type-body-size);
	line-height: var(--lu-type-body-lh);
	font-variant-numeric: tabular-nums;
	color: inherit;
}

body .lu-quote.elementor-element .swiper .swiper-pagination-fraction {
	left: calc(var(--lu-quote-media) + var(--lu-quote-gap) + 2 * var(--lu-quote-arrow) + 24px);
	right: auto;
}

@container (max-width: 699px) {
	body .lu-quote .elementor-testimonial {
		grid-template-columns: minmax(0, 1fr);
		grid-template-areas: "media" "text" "cite" "nav";
		grid-template-rows: auto auto auto var(--lu-quote-arrow);
		row-gap: 20px;
	}

	body .lu-quote .elementor-testimonial__image {
		inline-size: 160px;
		border-radius: 0 24px 0 24px;
	}

	body .lu-quote .elementor-testimonial__text {
		font-size: var(--lu-type-h4-size);
		line-height: var(--lu-type-h4-lh);
	}

	body .lu-quote.elementor-element .swiper .elementor-swiper-button-prev { left: 0; }
	body .lu-quote.elementor-element .swiper .elementor-swiper-button-next { left: calc(var(--lu-quote-arrow) + 12px); }
	body .lu-quote.elementor-element .swiper .swiper-pagination-fraction { left: calc(2 * var(--lu-quote-arrow) + 24px); }
}

@media (prefers-reduced-motion: reduce) {
	.lu-quote .swiper-wrapper,
	.lu-gallery .swiper-wrapper {
		transition-duration: 0ms !important;
	}
}


/* ==========================================================================
   36. lu-gallery
   ==========================================================================
   A few photographs from an event: Elementor's Media Carousel, three across
   (two on a tablet, one on a phone - the widget's Slides Per View), 4:3 with
   the band's diagonal corners, and the arrows and count under its right edge.
   A click still opens the photo in the lightbox.

   Set in the widget: Slides Per View 3 / 2 / 1, Space Between 20, Pagination
   "Fraction", Autoplay off.

   Applied to: a media-carousel widget.
   ========================================================================== */

/* media-carousel.css fixes `.elementor-skin-carousel .elementor-main-swiper` at
 * 230px; the photos' 4:3 sets the height instead. */
body .lu-gallery .elementor-main-swiper.swiper {
	height: auto;
	padding-block-end: 68px;   /* the 48px arrow row and 20px above it */
}

/* The widget fixes the slide at its Height control (200px); the photo's 4:3 sets it instead. */
body .lu-gallery.elementor-element .swiper .swiper-slide {
	height: auto;
}

/* !important twice over: the widget's Height control writes a fixed px value,
 * and Smush's lazy-load placeholder (.lazyload) forces 100px at 1:1 until the
 * photo loads, which made the row jump. */
body .lu-gallery .elementor-carousel-image {
	inline-size: 100% !important;
	block-size: auto !important;
	aspect-ratio: 4 / 3 !important;
	border-radius: var(--lu-radius-band);
	background-size: cover;
	background-position: center;
}

body .lu-gallery.elementor-element .swiper .elementor-swiper-button {
	background-color: var(--lu-primary);
	color: var(--lu-surface-green);
}

body .lu-gallery.elementor-element .swiper .elementor-swiper-button-next { left: auto; right: 0; }
body .lu-gallery.elementor-element .swiper .elementor-swiper-button-prev { left: auto; right: 60px; }
body .lu-gallery.elementor-element .swiper .swiper-pagination-fraction { left: auto; right: 120px; color: var(--lu-primary); }

@media (max-width: 767px) {
	body .lu-gallery .elementor-carousel-image {
		border-radius: 0 24px 0 24px;
	}
}


/* ==========================================================================
   37. lu-panel
   ==========================================================================
   A column on a fill pairing, with the band's diagonal corners and 48px of
   room inside (24 on a phone): Netværk's programme downloads, Årsmøde's two
   nominations. Headings and text take the fill's foreground; a button keeps
   its own Elementor colours, set to the same pairing. In a row it is as tall
   as its neighbours, and with `lu-textblock` + `lu-to-end` its button sits on
   the bottom edge, level across the row.

   Applied to: a column, with `lu-fill-*` (and usually `lu-textblock`).
   ========================================================================== */

body .lu-panel > .elementor-widget-wrap.elementor-element-populated {
	padding: 48px;
	border-radius: var(--lu-radius-band);
	background-color: var(--lu-fill-bg);
	color: var(--lu-fill-fg);
}

body .lu-panel .elementor-heading-title,
body .lu-panel .elementor-widget-text-editor {
	color: inherit;
}

/* lu-textblock sets p to margin 0; in a panel a list is a paragraph too, one
 * blank line from what is above and below it. */
.lu-panel .elementor-widget-text-editor :is(p, ul, ol) + :is(p, ul, ol) {
	margin-block-start: var(--lu-type-body-lh);
}

.lu-panel .elementor-widget-text-editor :is(ul, ol) {
	margin-block-end: 0;
	padding-inline-start: 20px;
}

@media (max-width: 767px) {
	body .lu-panel > .elementor-widget-wrap.elementor-element-populated {
		padding: 24px;
		border-radius: 0 24px 0 24px;
	}
}

/* Links in a panel's text: the fill's foreground, underlined; Sekundær on
 * hover, keeping the underline (D1, wave 3). */
body .lu-panel .elementor-widget-text-editor a {
	color: inherit;
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 0.18em;
}

body .lu-panel .elementor-widget-text-editor a:hover {
	color: var(--lu-secondary);
}

.lu-panel small {
	font-size: 14px;
	line-height: 18px;
}

/* lu-panel--compact: 32px inside, for a row of four small panels (Lokalforeninger's
 * regions), where 48px would leave an email address 130px at 1000. */
body .lu-panel.lu-panel--compact > .elementor-widget-wrap.elementor-element-populated {
	padding: 32px;
}

.lu-panel--compact .elementor-widget-text-editor {
	overflow-wrap: anywhere;
}

.lu-panel--compact .elementor-widget + .elementor-widget {
	margin-block-start: 12px !important;
}

@media (max-width: 767px) {
	body .lu-panel.lu-panel--compact > .elementor-widget-wrap.elementor-element-populated {
		padding: 24px;
	}
}


/* ==========================================================================
   38. lu-news
   ==========================================================================
   The latest posts as the front page's "Kommende aktiviteter" list: the title
   in the fill's accent, each post's title and date between rules, the items at
   the bottom of the card, and "Se alle nyheder →" to the archive.

   Printed by [lu_news count="4"] (inc/story.php) in a column with
   `lu-panel lu-panel--card lu-fill-primary`: the card's top corners and its
   padding instead of the panel's.
   ========================================================================== */

body .lu-panel.lu-panel--card > .elementor-widget-wrap.elementor-element-populated {
	/* The bottom matches lu-card__body's, so "Se alle nyheder →" sits on the
	 * line of the card beside it's "Læs mere →". */
	padding: 32px var(--lu-card-pad) calc(var(--lu-card-pad) - 5px);
	border-radius: var(--lu-radius-card);
	align-content: stretch;
}

.lu-panel--card .elementor-widget-shortcode,
.lu-panel--card .elementor-widget-shortcode > .elementor-widget-container,
.lu-panel--card .elementor-shortcode {
	block-size: 100%;
}

.lu-news {
	display: flex;
	flex-direction: column;
	block-size: 100%;
}

.lu-news .lu-list__body {
	flex: 1;
}

.lu-news .lu-list__title {
	color: var(--lu-fill-accent, var(--lu-secondary));
}

/* The Kit publishes Brødtekst onto every <a>: a linked title has to inherit. */
body .lu-news .lu-list__item-title a {
	font: inherit;
}

body .lu-news .lu-list__item-title a,
body .lu-news__all a {
	color: inherit;
	text-decoration: none;
}

body .lu-news .lu-list__item-title a:hover,
body .lu-news__all a:hover {
	color: var(--lu-secondary);
	text-decoration: none;
}

.lu-news .lu-list__item-meta {
	margin: 0;
}

.lu-news__all {
	margin: var(--lu-card-pad) 0 0;
	font-family: var(--lu-font-body);
	font-size: var(--lu-type-body-size);
	line-height: var(--lu-type-body-lh);
}


/* ==========================================================================
   39. lu-logo, lu-logos
   ==========================================================================
   The partners' banners on Samarbejdspartnere. Each is the partner's own
   artwork, so it gets no site shapes: a plain white 40:21 tile (the banners'
   1200 x 630) with square corners and no shadow, the banner shown whole
   (contain), and a Sekundær edge on hover. Four across; two on a phone.

   Applied to: an image widget (lu-logo), each in its own column of one
   `lu-section lu-row lu-row-4 lu-logos` section.
   ========================================================================== */

/* Two classes: Smush's lazy rule (also !important) and Elementor's image rule
   load later with one class each, and would leave an unloaded logo 1px wide. */
.lu-logos .lu-logo img {
	display: block;
	width: 100% !important;
	height: auto !important;
	aspect-ratio: 40 / 21 !important;   /* !important: Smush's lazy placeholder */
	object-fit: contain;
	background-color: #fff;
	border-radius: 0;
}

.lu-logos .lu-logo a {
	display: block;
}

.lu-logo a:hover img,
.lu-logo a:focus-visible img {
	outline: 3px solid var(--lu-secondary);
	outline-offset: -3px;
}

@media (max-width: 767px) {
	.lu-logos > .elementor-container {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 12px;
	}
}


/* ==========================================================================
   40. lu-video--portrait
   ==========================================================================
   A row of videos of mixed shapes (Lokale aktiviteter: a vertical Short, a
   square Short, a widescreen video). The tiles are all 4:5 with the band's
   corners mirrored (top-left and bottom-right); each plays in a lightbox at its own shape, which is the widget's
   Aspect Ratio setting (9:16, 1:1, 16:9). So the grid never shows black bars.

   Applied to: a video widget with lu-video, Image Overlay and Lightbox on.
   ========================================================================== */

body .lu-video--portrait .elementor-wrapper {
	aspect-ratio: 4 / 5 !important;
	height: auto !important;
	--video-aspect-ratio: 0.8;
	position: relative;   /* the containing block of the absolute cover, or overflow does not clip it */
	overflow: hidden;
	border-radius: 36px 0 36px 0;
}

body .lu-video--portrait .elementor-custom-embed-image-overlay {
	position: absolute;
	inset: 0;
	height: 100% !important;
	background-size: cover !important;
	background-position: center !important;
}

/* !important: Smush's lazy placeholder sizes the cover until it loads, which
 * left a grey band under it. */
body .lu-video--portrait .elementor-custom-embed-image-overlay img {
	width: 100% !important;
	height: 100% !important;
	aspect-ratio: auto !important;
	object-fit: cover;
}

@media (max-width: 767px) {
	body .lu-video--portrait .elementor-wrapper {
		border-radius: 24px 0 24px 0;
	}
}

/* In the lightbox Elementor sizes a vertical video by its height and a 9:16
 * aspect ratio, but a width: 100% on iframes elsewhere stretched it to the full
 * dialog. The width follows the ratio instead. */
.elementor-lightbox .elementor-video-portrait iframe {
	width: auto !important;
	margin-inline: auto;
	display: block;
}

/* On a phone the screen's width is the limit, so the height follows it. */
@media (max-width: 767px) {
	.elementor-lightbox .elementor-video-portrait iframe {
		width: 100% !important;
		height: auto !important;
	}
}


/* ==========================================================================
   41. lu-photo, lu-photo--whole, lu-photo--mirror
   ==========================================================================
   A photograph that stands on its own in half a row (Martskursus, LU-kurset):
   4:3, cropped, the band's diagonal corners. The story pages only had these
   shapes inside carousels, theme rows and videos.

   --whole shows the whole picture at its own ratio instead of cropping it: a
   diagram, not a photograph (LU's organisering). --mirror turns the corners
   to top-left and bottom-right, the portrait videos' pair, for a picture on
   the left of its text.

   Applied to: an image widget. Link it to its file with the lightbox on when
   the picture needs reading (the diagrams).
   ========================================================================== */

/* !important: Smush's lazy-load placeholder (.lazyload) forces its own width
 * and aspect ratio until the file loads - the same fight as lu-theme__media. */
.lu-photo img {
	display: block;
	width: 100% !important;
	height: auto !important;
	aspect-ratio: 4 / 3 !important;
	object-fit: cover;
	border-radius: var(--lu-radius-band);
}

/* The <a> of a linked image is an inline-block the picture's own size; as a
 * block it takes the column, and with it the image does (DESIGN.md Gotchas:
 * a Smush image in a linked widget collapses to 1px otherwise). */
.lu-photo,
.lu-photo > .elementor-widget-container,
.lu-photo .elementor-widget-container > a {
	display: block;
	width: 100%;
}

/**
 * A photo alone in its column, beside a text column (the course pages): the
 * PHOTO absorbs the row's spare height, not the text (DESIGN.md Layout). 4:3 is
 * its floor; where the text is taller - 768-1100, where half a row is narrow -
 * the photo crops taller so the facts panel still ends on its bottom edge.
 * Stacked on a phone the column has no height to fill, and the floor is all
 * there is. Elementor's widget wrap is a wrapping flex row pinned to the top
 * (align-content: flex-start); stretched, its one line fills the column.
 */
.lu-row > .elementor-container > .elementor-column > .elementor-widget-wrap:has(> .lu-photo:not(.lu-photo--whole):only-child) {
	align-content: stretch;
}

.lu-row .lu-photo:not(.lu-photo--whole):only-child > .elementor-widget-container {
	position: relative;
	height: 100%;
	min-height: 0;
	aspect-ratio: 4 / 3;
}

.lu-row .lu-photo:not(.lu-photo--whole):only-child img {
	position: absolute;
	inset: 0;
	height: 100% !important;
	aspect-ratio: auto !important;
}

.lu-photo.lu-photo--whole img {
	aspect-ratio: auto !important;
	object-fit: contain;
}

.lu-photo.lu-photo--mirror img {
	border-radius: var(--lu-radius-band-mirror);
}


/* ==========================================================================
   42. lu-card--cover
   ==========================================================================
   A magazine issue (LUBladet): the card with its A4 cover, whole, where the
   photograph would be; the issue as its title, a summary, "Læs bladet →" on
   the bottom line. Three across, one height, like every card in a row.

   On a phone the row is one column and three covers would fill three
   screens, so the card lies on its side as the person card does: the cover
   120px wide on the left with the card's two left corners, the issue and the
   link beside it, centred on the cover's height, and the summary left out.
   A media query, not a container query: the card only ever sits in a row of
   three, and at 768-1024 its 230px is an upright card, not a narrow one.

   Applied to: a hand-built card column - lu-card lu-card--cover lu-card-nochip
   and a fill pairing - holding an image widget `lu-card__media` and the
   `lu-card__body` section (title, `lu-card__text`, `lu-card__link`).
   ========================================================================== */

.lu-card--cover {
	--lu-card-ratio: 210 / 297;
}

@media (max-width: 767px) {
	.lu-card.lu-card--cover > .elementor-widget-wrap {
		display: grid;
		grid-template-columns: 120px minmax(0, 1fr);
	}

	.lu-card.lu-card--cover .lu-card__media,
	.lu-card.lu-card--cover .lu-card__media img {
		border-radius: var(--lu-radius-card-side);
	}

	.lu-card.lu-card--cover .lu-card__body > .elementor-container > .elementor-column > .elementor-widget-wrap {
		justify-content: center;
	}

	.lu-card.lu-card--cover .lu-card__text {
		display: none;
	}

	.lu-card.lu-card--cover .lu-card__link {
		margin-block-start: 0;
	}
}


/* ==========================================================================
   43. lu-heading-sm
   ==========================================================================
   An H2 that steps to H4 (24/27) on a phone instead of the usual 36/40.5: the
   committee pages' tagline and their people heading, which on a phone sit right
   under the page title (wave 2 proposal, user comments). Desktop and tablet keep
   the H2.

   Applied to: a heading widget (H2), with or without lu-section-heading.
   ========================================================================== */

@media (max-width: 767px) {
	body .lu-heading-sm .elementor-heading-title {
		font-size: var(--lu-type-h4-size);
		line-height: var(--lu-type-h4-lh);
		letter-spacing: var(--lu-type-h4-ls);
	}
}


/* ==========================================================================
   44. lu-contacts, lu-contact
   ==========================================================================
   People without photographs, as contact rows (Landstraktortrækudvalg,
   Landspløjeudvalg): the person card without its photo. The name at the fact
   size, the role and contact lines at 14/18, one rule colour above and below,
   four across, rows one height - and the rules of neighbouring rows meet, so
   there is no gap between them. The client edits a person as a column.

   Applied to: a section `lu-row lu-row-4 lu-contacts`, one column per person
   with `lu-contact`, holding a heading (the name) and a text widget (the role,
   then the email and number).
   ========================================================================== */

.lu-contacts {
	--lu-row-gap: 0px;
}

.lu-contacts > .elementor-container {
	color: var(--lu-primary);
}

/* The first row's top rule, whether or not a heading (lu-span-all) leads the
 * row; the rows below meet on their bottom rules. */
.lu-contacts > .elementor-container > .lu-contact:nth-child(-n + 4):not(.lu-span-all ~ .lu-contact),
.lu-contacts > .elementor-container > .lu-span-all ~ .lu-contact:nth-child(-n + 5) {
	border-top: var(--lu-rule);
}

@media (max-width: 767px) {
	.lu-contacts > .elementor-container > .lu-contact:nth-child(n):not(:first-child, .lu-span-all + .lu-contact) {
		border-top: 0;
	}
}

/* Elementor's own spacing between widgets; the column's gap is the spacing. */
body .lu-contact .elementor-widget:not(:last-child) {
	margin-block-end: 0;
}

body .lu-contact > .elementor-widget-wrap.elementor-element-populated {
	display: flex;
	flex-direction: column;
	align-content: flex-start;
	gap: 4px;
	height: 100%;
	padding: 16px 0;
	border-bottom: var(--lu-rule);
}

body .lu-contact .elementor-heading-title {
	margin: 0;
	font-family: var(--lu-font-display);
	font-size: var(--lu-type-fact-size);
	font-weight: 500;
	line-height: var(--lu-type-fact-lh);
	color: inherit;
	hyphens: auto;
	overflow-wrap: break-word;
}

body .lu-contact .elementor-widget-text-editor,
body .lu-contact .elementor-widget-text-editor p {
	margin: 0;
	font-family: var(--lu-font-body);
	font-size: var(--lu-person-detail-size);
	line-height: var(--lu-person-detail-lh);
	color: inherit;
}

body .lu-contact .elementor-widget-text-editor p + p {
	margin-block-start: 8px;
}

/* The address has no space to break at (DESIGN.md "Type"). */
body .lu-contact .elementor-widget-text-editor a {
	font: inherit;
	color: inherit;
	overflow-wrap: anywhere;
}

body .lu-contact .elementor-widget-text-editor a[href^="mailto:"] {
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 0.18em;
}

body .lu-contact .elementor-widget-text-editor a[href^="tel:"] {
	text-decoration: none;
}

/* Sekundær on hover, underline preserved (D1, wave 3). The tel: rule above
 * still applies, so a phone number stays un-underlined in both states. */
body .lu-contact .elementor-widget-text-editor a:hover {
	color: var(--lu-secondary);
}


/* ==========================================================================
   45. lu-card--person
   ==========================================================================
   The person card built by hand, for people who are not Team posts (Aktivitets-
   og kursusudvalg's members, typed on the page): the hand-built lu-card with a
   4:5 portrait cropped a third of the way down, the name at the fact size and
   the role at 14/18 - the look of lu-person, edited on the page.

   Applied to: a hand-built card column - lu-card lu-card--person lu-card-nochip
   and a fill (lu-fill-green) - with an image `lu-card__media` and an inner
   section `lu-card__body` holding the name (`lu-card__title`) and the role
   (`lu-card__text`). In an `lu-row lu-row-4 lu-row-wrap`.
   ========================================================================== */

.lu-card--person {
	--lu-card-ratio: 4 / 5;
	--lu-card-title-size: var(--lu-type-fact-size);
	--lu-card-title-lh:   var(--lu-type-fact-lh);
	--lu-card-title-ls:   0;
	--lu-card-title-gap:  4px;
}

.lu-card.lu-card--person .lu-card__media img {
	object-position: 50% 30%;
}

.lu-card.lu-card--person .lu-card__text,
.lu-card.lu-card--person .lu-card__text p {
	margin: 0;
	font-size: var(--lu-person-detail-size);
	line-height: var(--lu-person-detail-lh);
}


/* ==========================================================================
   46. lu-panel--links
   ==========================================================================
   A panel of links beside a text column (Landspløjeudvalg's "Find mere"): its
   heading's first line sits near the H2's beside it, so the top inset is 28px
   rather than the panel's 48 (user comment on the wave 2 proposal). The links
   sit on the bottom edge with lu-to-end.

   Applied to: with `lu-panel lu-fill-* lu-textblock` on a column.
   ========================================================================== */

@media (min-width: 768px) {
	body .lu-panel.lu-panel--links > .elementor-widget-wrap.elementor-element-populated {
		padding-block-start: 28px;
	}
}


/* ==========================================================================
   47. lu-results, lu-result
   ==========================================================================
   A stævne and the result it links to, as a ruled list - "Samlede resultater",
   "Stævner og resultater" and DM i pløjning's year groups (wave 3, D2/D3/D4).

   This is lu-list's idiom, not a new one: dated rows with a rule between them.
   It differs in two ways, both because the row is a LINK ROW rather than a text
   item - the destination sits at the end of the row, and a row can carry more
   than one (Region Aalborg has standardplov and vendeplov).

   Applied to: `lu-results` on a section, whose single column holds one INNER
   section per row carrying `lu-result` - two columns, the name and the links.
   Built from ordinary sections so an editor can add a row in Elementor without
   touching a template.

   What it replaces: one full section per row, two 50% columns, the name right-
   aligned and the link left-aligned so the pair met at the page's centre line.
   Thirty-seven of them on 14945 alone, no two the same height.
   ========================================================================== */

body .lu-results > .elementor-container {
	display: block;
	border-top: var(--lu-rule);
}

/**
 * One rule colour down the whole list: --lu-rule is the full Primær rule the
 * other ruled components use. Mixing it with a 30% rule inside one component is
 * what DESIGN.md "Rules" forbids.
 */
body .lu-result {
	padding-block: 16px;
	border-bottom: var(--lu-rule);
}

/**
 * The row. `auto` on the second track, so the links take what they need and the
 * name takes the rest - a name from "Thy LU 12/9-25" to "Traktortræk Landsdel
 * Syd (Ribe, Vejle, Sønderjylland og Fyn) 3/7-26" wraps inside its own track
 * instead of pushing the row wider.
 *
 * `align-items: baseline` rather than center: the name can be two lines and the
 * link one, and the two should start on the same line.
 */
body .lu-result > .elementor-container {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
	align-items: baseline;
	column-gap: 24px;
}

body .lu-result > .elementor-container > .elementor-column {
	width: auto;
}

/* The text widgets inside carry theme.css's `p { margin: 2rem 0 }` otherwise. */
body .lu-result__name p,
body .lu-result__links p {
	margin: 0;
	font-family: var(--lu-font-body);
	font-size: var(--lu-type-body-size);
	font-weight: 400;
	line-height: var(--lu-type-body-lh);
	color: var(--lu-primary);
}

/* The date is part of the name, but it is the part a reader scans down the
 * column, so it never breaks across lines. */
body .lu-result__name .lu-result__date {
	white-space: nowrap;
	font-variant-numeric: tabular-nums;
}

/**
 * The destinations. Flex rather than a second grid track: a row has one link or
 * two, and a third wraps under them rather than squeezing the name.
 */
body .lu-result__links p {
	display: flex;
	flex-wrap: wrap;
	justify-content: flex-end;
	gap: 4px 20px;
}

body .lu-result__links a {
	font: inherit;
	color: var(--lu-primary);
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 0.18em;
	white-space: nowrap;
}

/* Sekundær on hover, underline preserved (D1). */
body .lu-result__links a:hover {
	color: var(--lu-secondary);
}

/**
 * A stævne whose result has not arrived.
 *
 * Ten rows across the two results pages carry a bold "Resultat" with no link
 * behind it - the label was typed when the row was made and the PDF never came.
 * Set as muted text, so it cannot be read as a link that is merely broken.
 */
body .lu-result__links .lu-result__pending {
	opacity: 0.5;
}

/**
 * On a phone the row becomes one column (D3).
 *
 * The two 50% Elementor columns this replaces never stacked, so a name had
 * 170px to wrap into and ran to three or four lines beside a one-word link -
 * most of why the traktortræk page was 8,200px tall at 402. Here the name gets
 * the full measure and its links sit under it.
 */
@media (max-width: 767px) {
	body .lu-result {
		padding-block: 14px;
	}

	body .lu-result > .elementor-container {
		grid-template-columns: 1fr;
		row-gap: 6px;
	}

	body .lu-result__links p {
		justify-content: flex-start;
	}
}


/* ==========================================================================
   48. lu-guide-row, lu-guide
   ==========================================================================
   A step of a guide - a heading and the list under it - three across, sitting
   on one rule: Generalforsamling's Før / Under / Efter, Logoer's three logo
   groups, værktøjer til regionen's three tools (wave 4, D4).

   Applied to: `lu-guide-row` on a section, `lu-guide` on each of its columns,
   each column holding a heading and a text widget.

   Why it exists at all. These three pages already had three columns; what they
   did not have was a COMPONENT, and that is what was breaking them. A heading
   in a bare Elementor column inherits none of the type rules the design system
   applies per component - including `hyphens: auto` - so "generalforsamlingen"
   (19 characters) in a 427px track did not wrap, it overflowed and printed
   across the column beside it. Three of those in a row read as one word.

   DESIGN.md "Type" says this outright: any display-size role that can land in
   a box narrower than the frame draws needs `hyphens: auto` and
   `overflow-wrap: break-word` as the floor. The component is how a heading
   gets them.
   ========================================================================== */

body .lu-guide-row > .elementor-container {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: var(--lu-col-gap);
	align-items: start;
	border-top: var(--lu-rule);
	padding-block-start: 32px;
}

body .lu-guide-row > .elementor-container > .elementor-column {
	width: auto;
}

body .lu-guide > .elementor-widget-wrap {
	align-content: start;
	gap: 16px;
}

/**
 * The heading. H4 rather than the H3 these pages use today: three across, a
 * track is ~427px, and at H3 a Danish compound hyphenates on every line. H4 is
 * the card title's size, which is what a column of this width is.
 */
body .lu-guide .elementor-heading-title {
	font-family: var(--lu-font-display);
	font-size: var(--lu-type-h4-size);
	font-weight: 500;
	line-height: var(--lu-type-h4-lh);
	color: var(--lu-primary);
	hyphens: auto;
	overflow-wrap: break-word;
}

/**
 * The list. `list-style-position: outside` with the padding on the list, so a
 * wrapped line aligns under the first word rather than under the number -
 * these are instructions, and a reader scans the left edge of the text.
 */
body .lu-guide .elementor-widget-text-editor ol,
body .lu-guide .elementor-widget-text-editor ul {
	margin: 0;
	padding-inline-start: 20px;
	display: grid;
	gap: 8px;
}

body .lu-guide .elementor-widget-text-editor li {
	font-family: var(--lu-font-body);
	font-size: var(--lu-type-body-size);
	line-height: var(--lu-type-body-lh);
	color: var(--lu-primary);
}

body .lu-guide .elementor-widget-text-editor li::marker {
	color: var(--lu-primary);
}

/* theme.css's `p { margin: 2rem 0 }` again - see HANDOFF section 9 #18. */
body .lu-guide .elementor-widget-text-editor p {
	margin: 0 0 16px;
}

body .lu-guide .elementor-widget-text-editor p:last-child {
	margin-bottom: 0;
}

/* One column on a phone, where three tracks of 114px would hyphenate every
 * line of every heading. */
@media (max-width: 767px) {
	body .lu-guide-row > .elementor-container {
		grid-template-columns: 1fr;
		row-gap: 32px;
		padding-block-start: 24px;
	}
}


/* ==========================================================================
   49. lu-logo-grid, lu-logo-card
   ==========================================================================
   One version of a logo: the picture, its name, and the formats it comes in.
   Four of them on a region or lokalforening page (shape × colour), two on the
   hovedorganisation's own pages, where the page IS the colour (wave 5, D3–D6).

   Applied to: `lu-logo-grid` with `lu-section lu-row lu-row-2` on the section,
   `lu-logo-card` on each column, and `--dark` on the columns holding a white
   logo. The column holds an image, a heading and a text widget of links.

   Why the picture is here at all. The page hands over four versions of a logo
   and, before this wave, showed none of them - you downloaded files to find
   out which one you wanted. The `png` the card already links to IS the
   preview, so this adds no asset and invents nothing.
   ========================================================================== */

body .lu-logo-grid {
	--lu-row-gap: 20px;
}

/* All four are the same object, so the 2x2 reads as one block rather than two
 * rows of slightly different depth. */
body .lu-logo-grid > .elementor-container {
	grid-auto-rows: 1fr;
}

body .lu-logo-card > .elementor-widget-wrap {
	align-content: start;
	border: 1px solid var(--lu-rule-colour, rgba(18, 84, 66, .28));
	padding: 0;
}

/**
 * The picture sits in a fixed 3:2 tile so the four cards line up whatever the
 * logo's own proportions - a square mark and a wide lockup are both in here.
 * `contain`, never `cover`: a cropped logo is a broken logo.
 */
body .lu-logo-card__pic {
	width: 100%;
	background: #fff;
}

body .lu-logo-card__pic .elementor-widget-container {
	aspect-ratio: 3 / 2;
	display: grid;
	place-items: center;
	padding: 28px;
	/**
	 * `aspect-ratio` is only a suggestion once the content is taller than the
	 * box it implies, and a square mark IS taller than a 3:2 tile at this
	 * width - the Kvadratisk tiles came out 49px deeper than the Vandret ones.
	 * overflow + a zero minimum hold the ratio and let the image shrink into
	 * it instead of pushing it open.
	 */
	overflow: hidden;
	min-height: 0;
}

/* !important: Smush's lazy-load placeholder forces its own width and ratio
 * until the file loads - the same fight as lu-photo and lu-theme__media. */
body .lu-logo-card__pic img {
	min-height: 0;
	width: auto !important;
	height: auto !important;
	max-width: 72% !important;
	max-height: 100% !important;
	object-fit: contain;
}

/**
 * The white logo gets Primær behind it.
 *
 * Not a flourish: on the page's cream a white logo is invisible, which is the
 * whole reason the two colours cannot share one tile. It also shows the reader
 * what the white version is for.
 */
body .lu-logo-card--dark .lu-logo-card__pic {
	background: var(--lu-primary);
}

body .lu-logo-card__title {
	padding: 24px 24px 0;
}

body .lu-logo-card__title .elementor-heading-title {
	font-family: var(--lu-font-display);
	font-size: var(--lu-type-h4-size);
	font-weight: 500;
	line-height: var(--lu-type-h4-lh);
	color: var(--lu-primary);
	hyphens: auto;
	overflow-wrap: break-word;
}

/**
 * The formats, on one line (D6).
 *
 * The Digital/Print split went with the labels: it made an uneven row read as
 * an omission. The hvid variants have no jpg, and four blocks across the 61
 * pages are irregular in other ways - on one line that is simply a shorter
 * line rather than a gap in a list.
 */
body .lu-logo-card__formats {
	padding: 16px 24px 24px;
}

body .lu-logo-card__formats p {
	margin: 0;
	display: flex;
	flex-wrap: wrap;
	gap: 6px 16px;
	font-family: var(--lu-font-body);
	font-size: var(--lu-type-body-size);
	line-height: var(--lu-type-body-lh);
}

body .lu-logo-card__formats a {
	color: var(--lu-primary);
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 0.18em;
}

/* Sekundær on hover, underline preserved (D1, wave 3). */
body .lu-logo-card__formats a:hover {
	color: var(--lu-secondary);
}

/* The formats sit on the card's bottom edge, so four cards of different
 * title lengths still line their links up. */
body .lu-logo-card > .elementor-widget-wrap > .lu-logo-card__formats {
	margin-block-start: auto;
}
