/* ---------------------------------------------------------------------- *
 * Atoms — shadcn-flavoured token-driven primitives
 *
 * The base button surface is set on `theme.json` `styles.elements.button`,
 * which paints every <button>, .wp-block-button__link, etc. Variants
 * + sizes layer on top via BEM classes. Reach for them with:
 *
 *   <button class="aff-btn">…</button>                          (primary, default)
 *   <button class="aff-btn aff-btn--secondary">…</button>
 *   <button class="aff-btn aff-btn--ghost">…</button>
 *   <button class="aff-btn aff-btn--sm">…</button>              (compact)
 *   <button class="aff-btn aff-btn--md">…</button>              (medium)
 *   <button class="aff-btn aff-btn--lg">…</button>              (CTA)
 *   <a class="aff-btn aff-btn--secondary">…</a>                 (any tag)
 *
 * Pattern authors writing block markup can drop the `aff-btn` prefix on
 * `core/button` via the block's `className` attribute and the variant
 * styles still resolve.
 * ---------------------------------------------------------------------- */

/* `:where()` flattens specificity to 0 so the WP-core
 * `.wp-block-button__link` selector wins/ties without each rule below
 * having to repeat the doubled selector. Add new modifiers as plain
 * `.aff-btn--foo` and they apply to both anchor- and button-shaped
 * primitives. */
:where(.aff-btn, .wp-block-button__link.aff-btn) {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    border: 1px solid transparent;
    cursor: pointer;
    text-decoration: none;
    /* `<button>` inherits the UA stylesheet font (system / Arial) and a
     * tighter line-height than the document; `<a>` inherits the page
     * font. Force both to the document baseline so `aff-btn` renders
     * identically across element shapes. */
    font-family: inherit;
    font-size: inherit;
    line-height: 1.2;
    transition:
        background-color var(--aff-transition),
        color var(--aff-transition),
        border-color var(--aff-transition),
        transform var(--aff-transition);
}

/* theme.json `styles.elements.link` paints every <a> orange via a
 * `:where(:not(.wp-element-button))` selector with 0 specificity;
 * matched by these `:where()` rules below in source order. Use a
 * plain class selector here (specificity 0,1,0) so anchor-shaped
 * `.aff-btn` overrides the global link colour without `!important`. */
a.aff-btn,
a.aff-btn:hover,
a.aff-btn:focus-visible,
a.aff-btn:visited {
    text-decoration: none;
}

.aff-btn:disabled,
.aff-btn[aria-disabled="true"] {
    opacity: 0.55;
    cursor: not-allowed;
    pointer-events: none;
}

/* Default lives on theme.json `styles.elements.button` — accent (orange)
 * fill, white text, hover deepens to brand-orange-hover. */

/* Primary — brand-blue surface. Use for the highest-emphasis action on
 * a band where the orange accent reads as a CTA elsewhere (e.g. download
 * a report on the magazine single, where header "Bli medlem" already
 * owns the orange). */
.aff-btn--primary,
.wp-block-button__link.aff-btn--primary,
a.aff-btn--primary,
a.aff-btn--primary:visited {
    background-color: var(--aff-primary);
    color: var(--aff-primary-fg);
    border-color: var(--aff-primary);
}

.aff-btn--primary:hover,
.aff-btn--primary:focus-visible,
a.aff-btn--primary:hover,
a.aff-btn--primary:focus-visible {
    background-color: var(--aff-blue-deep);
    color: var(--aff-primary-fg);
    border-color: var(--aff-blue-deep);
}

/* Secondary — outlined, neutral surface. */
.aff-btn--secondary,
.wp-block-button__link.aff-btn--secondary,
a.aff-btn--secondary,
a.aff-btn--secondary:visited {
    background-color: var(--aff-card);
    color: var(--aff-fg);
    border-color: var(--aff-border);
}

.aff-btn--secondary:hover,
.aff-btn--secondary:focus-visible,
a.aff-btn--secondary:hover,
a.aff-btn--secondary:focus-visible {
    background-color: var(--aff-muted);
    color: var(--aff-fg);
    border-color: var(--aff-fg);
}

/* Ghost — transparent, only ink + underline reveal. */
.aff-btn--ghost,
.wp-block-button__link.aff-btn--ghost,
a.aff-btn--ghost,
a.aff-btn--ghost:visited {
    background-color: transparent;
    color: var(--aff-fg);
    border-color: transparent;
}

.aff-btn--ghost:hover,
.aff-btn--ghost:focus-visible,
a.aff-btn--ghost:hover,
a.aff-btn--ghost:focus-visible {
    background-color: var(--aff-muted);
    color: var(--aff-fg);
}

/* Sizes — override the theme.json padding without changing the colour
 * surface. Same rhythm as shadcn's sm/lg knobs. */
:where(.aff-btn--sm, .wp-block-button__link.aff-btn--sm) {
    padding: 0.4375rem 0.75rem;
    font-size: 0.8125rem;
}

:where(.aff-btn--md, .wp-block-button__link.aff-btn--md) {
    padding: 0.75rem 1.25rem;
    font-size: 0.9375rem;
}

:where(.aff-btn--lg, .wp-block-button__link.aff-btn--lg) {
    padding: 0.875rem 1.5rem;
    font-size: 1rem;
}

/* Icon-only — square. Padding wins over the size-modifier so the box
 * stays square at every size. Combined with `--sm` / `--lg` the inner
 * icon size is whatever the SVG sets; the surrounding padding flexes
 * to keep the button height matching the sibling text button. */
:where(.aff-btn--icon, .wp-block-button__link.aff-btn--icon) {
    aspect-ratio: 1;
    padding: 0;
    width: auto;
}

:where(.aff-btn--icon.aff-btn--sm, .wp-block-button__link.aff-btn--icon.aff-btn--sm) {
    height: 2.125rem;
}

:where(.aff-btn--icon.aff-btn--lg, .wp-block-button__link.aff-btn--icon.aff-btn--lg) {
    height: 3rem;
}

/* Default icon size when neither --sm nor --lg is applied — matches
 * the base button height (theme.json button padding + line-height). */
:where(
    .aff-btn--icon:not(.aff-btn--sm):not(.aff-btn--lg),
    .wp-block-button__link.aff-btn--icon:not(.aff-btn--sm):not(.aff-btn--lg)
) {
    height: 2.625rem;
}

/* Inline icon wrappers inside a button: <span aria-hidden> defaults
 * to display: inline, so an SVG inside it sits on the text baseline
 * and looks off-centre next to a flex sibling. Force inline-flex so
 * the wrapper picks up the parent's centred alignment. */
:where(
    .aff-btn > span[aria-hidden],
    .wp-block-button__link.aff-btn > span[aria-hidden]
) {
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* ---------------------------------------------------------------------- *
 * Form fields — input, textarea, select baseline. WP doesn't ship a
 * theme.json hook for form controls so the rules sit here. Scoped to
 * .aff-field to keep core block forms (search, comments) untouched
 * unless the pattern opts in.
 * ---------------------------------------------------------------------- */

.aff-field,
input[type="text"].aff-field,
input[type="email"].aff-field,
input[type="search"].aff-field,
input[type="url"].aff-field,
input[type="tel"].aff-field,
input[type="password"].aff-field,
input[type="number"].aff-field,
textarea.aff-field,
select.aff-field {
    width: 100%;
    background-color: var(--aff-card);
    color: var(--aff-fg);
    border: 1px solid var(--aff-border);
    border-radius: var(--aff-radius-md);
    padding: 0.625rem 0.875rem;
    font-family: var(--wp--preset--font-family--sans);
    font-size: 0.9375rem;
    line-height: 1.4;
    transition:
        border-color var(--aff-transition),
        box-shadow var(--aff-transition);
}

.aff-field:hover {
    border-color: var(--aff-fg);
}

.aff-field::placeholder {
    color: var(--aff-muted-fg);
}

.aff-field:disabled {
    opacity: 0.55;
    cursor: not-allowed;
}

textarea.aff-field {
    min-height: 6rem;
    resize: vertical;
}

select.aff-field {
    appearance: none;
    background-image: linear-gradient(45deg, transparent 50%, var(--aff-fg) 50%),
        linear-gradient(135deg, var(--aff-fg) 50%, transparent 50%);
    background-position:
        calc(100% - 1.25rem) calc(50% - 2px),
        calc(100% - 0.75rem) calc(50% - 2px);
    background-size: 0.5rem 0.5rem;
    background-repeat: no-repeat;
    padding-right: 2.5rem;
}

.aff-field-label {
    display: block;
    font-family: var(--wp--preset--font-family--sans);
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--aff-fg);
    margin-bottom: 0.375rem;
}

.aff-field-hint {
    display: block;
    font-size: 0.8125rem;
    color: var(--aff-muted-fg);
    margin-top: 0.375rem;
}

.aff-field-error {
    display: block;
    font-size: 0.8125rem;
    color: var(--aff-destructive);
    margin-top: 0.375rem;
}

/* ---------------------------------------------------------------------- *
 * Breadcrumb band — global, rendered by the aff/breadcrumb block
 *
 * Sits flush under the global header on every template that inserts
 * `\3c !-- wp:aff/breadcrumb /-->`. The block's render.php resolves the
 * crumb list per view; the styles here handle the band shell + the
 * link/separator typography.
 * ---------------------------------------------------------------------- */

.aff-breadcrumb-band {
    background: var(--aff-bg);
    border-bottom: 1px solid var(--aff-border);
    padding: 0.75rem clamp(1rem, 4vw, 3rem);
    /* WP applies `--wp--style--block-gap` between top-level blocks; null
     * it so the band sits flush under the header. */
    margin-block: 0;
}

.aff-breadcrumb {
    max-width: var(--wp--style--global--content-size);
    margin-inline: auto;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    font-family: var(--wp--preset--font-family--sans);
    font-size: 0.8125rem;
    color: var(--aff-muted-fg);
}

.aff-breadcrumb a {
    color: var(--aff-muted-fg);
    text-decoration: none;
    transition: color var(--aff-transition);
}

.aff-breadcrumb a:hover {
    color: var(--aff-primary);
}

.aff-breadcrumb [aria-current="page"] {
    color: var(--aff-fg);
    font-weight: 500;
}

.aff-breadcrumb__sep {
    color: var(--aff-border);
}

/* ---------------------------------------------------------------------- *
 * Badge / pill — compact status chip
 * ---------------------------------------------------------------------- */

.aff-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.125rem 0.625rem;
    border-radius: var(--aff-radius-pill);
    font-family: var(--wp--preset--font-family--sans);
    font-size: 0.75rem;
    font-weight: 600;
    line-height: 1.4;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    background-color: var(--aff-muted);
    color: var(--aff-fg);
    border: 1px solid transparent;
    white-space: nowrap;
}

.aff-badge--primary {
    background-color: var(--aff-primary);
    color: var(--aff-primary-fg);
}

.aff-badge--accent {
    background-color: var(--aff-accent);
    color: var(--aff-accent-fg);
}

.aff-badge--success {
    background-color: var(--wp--preset--color--secondary);
    color: var(--wp--preset--color--secondary-foreground);
}

.aff-badge--muted {
    background-color: var(--aff-muted);
    color: var(--aff-muted-fg);
}

.aff-badge--warning {
    background-color: rgb(230 126 34 / 0.15);
    color: var(--aff-accent);
}

.aff-badge--destructive {
    background-color: rgb(180 84 73 / 0.15);
    color: var(--aff-destructive);
}

.aff-badge--outline {
    background-color: transparent;
    color: var(--aff-fg);
    border-color: var(--aff-border);
}

.aff-badge--outline-primary {
    background-color: transparent;
    color: var(--aff-primary);
    border-color: var(--aff-primary);
}

.aff-badge--soft-primary {
    background-color: rgb(41 61 130 / 0.1);
    color: var(--aff-primary);
    border-color: transparent;
}

/* ---------------------------------------------------------------------- *
 * Focus ring — single contract for every interactive element
 *
 * Only `:focus-visible` so mouse clicks don't paint a ring; keyboard +
 * screen-reader navigation still does. Buttons get a 2px outer ring;
 * fields get a 3px primary-tinted glow that doubles as the field's
 * own focus indicator. The `outline-offset` keeps the ring outside
 * rounded corners.
 * ---------------------------------------------------------------------- */

a:focus-visible,
button:focus-visible,
summary:focus-visible,
[role="button"]:focus-visible,
[tabindex]:focus-visible,
.wp-block-button__link:focus-visible {
    outline: 2px solid var(--aff-ring);
    outline-offset: 2px;
    border-radius: var(--aff-radius-sm);
}

input:focus-visible,
textarea:focus-visible,
select:focus-visible {
    outline: none;
    border-color: var(--aff-ring);
    box-shadow: 0 0 0 3px rgb(41 61 130 / 0.18);
}

/* ---------------------------------------------------------------------- *
 * 404
 *
 * Centred column. Display "404" is the loudest type on the page —
 * Source Serif 4 at the top end of the variable axis. Quick-link cards
 * reuse `.aff-btn--secondary` (outlined neutral surface) so the design
 * system carries through.
 * ---------------------------------------------------------------------- */

.aff-404 {
    padding-block: 6rem 7rem;
    background: linear-gradient(to bottom, var(--aff-card), var(--aff-bg));
}

.aff-404__inner {
    max-width: 720px;
    margin-inline: auto;
    text-align: center;
    align-items: center;
    gap: 1.5rem;
}

.aff-404__display {
    font-family: var(--wp--preset--font-family--serif);
    font-weight: 700;
    font-size: clamp(7rem, 22vw, 16rem);
    line-height: 0.95;
    letter-spacing: -0.04em;
    margin: 0;
    color: var(--aff-fg);
}

.aff-404__title {
    font-family: var(--wp--preset--font-family--serif);
    font-weight: 700;
    font-size: clamp(1.75rem, 2.5vw + 1rem, 2.5rem);
    line-height: 1.15;
    margin: 0.5rem 0 0;
    color: var(--aff-fg);
}

.aff-404__lead {
    max-width: 36rem;
    margin: 0 auto;
    color: var(--aff-muted-fg);
    font-size: 1rem;
    line-height: 1.6;
}

/* WP search block — re-skin to match the design-system field width
 * and the button-inside layout. Scoped to `.aff-404` so the header
 * search keeps its original chrome. */
.aff-404 .wp-block-search {
    width: 100%;
    max-width: 36rem;
    margin: 1rem auto 0;
}

.aff-404 .wp-block-search .wp-block-search__inside-wrapper {
    background: var(--aff-card);
    border: 1px solid var(--aff-border);
    border-radius: var(--aff-radius-md);
    padding: 0.25rem;
    transition: border-color var(--aff-transition), box-shadow var(--aff-transition);
}

.aff-404 .wp-block-search .wp-block-search__inside-wrapper:focus-within {
    border-color: var(--aff-ring);
    box-shadow: 0 0 0 3px rgb(41 61 130 / 0.18);
}

.aff-404 .wp-block-search .wp-block-search__input {
    border: 0;
    background: transparent;
    padding: 0.625rem 0.875rem;
    font-family: var(--wp--preset--font-family--sans);
    font-size: 0.9375rem;
    color: var(--aff-fg);
}

.aff-404 .wp-block-search .wp-block-search__input:focus {
    outline: none;
    box-shadow: none;
}

.aff-404 .wp-block-search .wp-block-search__button {
    background: var(--aff-primary);
    color: var(--aff-primary-fg);
    border: 0;
    border-radius: var(--aff-radius-sm);
    padding: 0 0.875rem;
    margin: 0;
    cursor: pointer;
    transition: background-color var(--aff-transition);
}

.aff-404 .wp-block-search .wp-block-search__button:hover {
    background: var(--aff-blue-deep);
}

.aff-404__kicker {
    margin: 2rem 0 0;
    font-family: var(--wp--preset--font-family--sans);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--aff-muted-fg);
}

.aff-404 .aff-404__quicklinks,
/* Site Editor wraps InnerBlocks children in
 * .block-editor-inner-blocks > .block-editor-block-list__layout; mirror
 * the grid onto the inner layout div so the canvas matches the
 * frontend list layout. */
.aff-404 .aff-404__quicklinks .block-editor-block-list__layout {
    list-style: none;
    padding: 0;
    margin: 0.5rem auto 0;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    column-gap: 1.25rem;
    row-gap: 1.25rem;
    width: 100%;
    max-width: 42rem;
}

/* The inner-blocks wrapper itself shouldn't add box behaviour. */
.aff-404 .aff-404__quicklinks > .block-editor-inner-blocks {
    display: contents;
}

.aff-404 .aff-404__quicklinks li,
.aff-404 .aff-404__quicklinks .block-editor-block-list__layout > * {
    margin: 0;
    padding: 0;
    list-style: none;
}

/* Override the inline button compactness — quick-links want card
 * proportions inside the 404 layout. */
.aff-404__quicklink {
    width: 100%;
    padding: 1rem 1.25rem;
    justify-content: center;
    gap: 0.625rem;
    font-weight: 500;
}

.aff-404__quicklink-icon {
    display: inline-flex;
    color: var(--aff-fg);
}

.aff-404__divider {
    width: 100%;
    max-width: 36rem;
    margin: 2.5rem auto 1rem;
    border: 0;
    border-top: 1px solid var(--aff-border);
}

.aff-404__contact-lead {
    margin: 0;
    color: var(--aff-muted-fg);
    font-size: 0.9375rem;
}

.aff-404__contact {
    margin: 0.25rem 0 0;
    font-size: 1rem;
}

.aff-404__contact-link {
    color: var(--aff-accent);
    text-decoration: none;
    font-weight: 600;
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    transition: color var(--aff-transition);
}

.aff-404__contact-link:hover {
    color: var(--aff-orange-hover);
}

/* ---------------------------------------------------------------------- *
 * Event single
 *
 * Bands top → bottom:
 *   1. Breadcrumb (own row, kissing the global header, border-bottom)
 *   2. Hero — gradient white→bg, holds badge + title + white fact cards
 *      (datum / plats) + arrangör card
 *   3. Body — solid white surface, prose left + sidebar right
 *   4. Related — bg surface, "Fler evenemang från <branch>"
 * ---------------------------------------------------------------------- */


/* ----- hero band ----- */
.aff-event-single__hero {
    padding-block: 2.5rem 3rem;
    background: var(--aff-bg);
}


.aff-event-single__status {
    margin-bottom: 1.25rem;
}

.aff-event-single__title {
    font-family: var(--wp--preset--font-family--serif);
    font-size: clamp(2rem, 3vw + 1.25rem, 3.25rem);
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: -0.02em;
    color: var(--aff-fg);
    margin: 0 0 1.75rem 0;
}

/* White fact-cards row — datum / plats. */
.aff-event-single__facts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 1rem;
    margin: 0;
}

.aff-event-single__fact {
    background: var(--aff-card);
    border: 1px solid var(--aff-border);
    border-radius: var(--aff-radius-card);
    padding: 1rem 1.25rem;
    display: flex;
    align-items: flex-start;
    gap: 0.875rem;
}

.aff-event-single__fact-icon {
    display: inline-flex;
    color: var(--aff-primary);
    margin-top: 0.125rem;
}

.aff-event-single__fact-body {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    min-width: 0;
}

.aff-event-single__fact-label {
    font-family: var(--wp--preset--font-family--sans);
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--aff-muted-fg);
}

.aff-event-single__fact-value {
    font-family: var(--wp--preset--font-family--sans);
    font-size: 1rem;
    font-weight: 500;
    color: var(--aff-fg);
}

/* ----- body band (solid white) ----- */
.aff-event-single__body {
    padding-block: 3rem 4rem;
}

.aff-event-single__body-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 2.5rem;
}

@media (min-width: 900px) {
    .aff-event-single__body-grid {
        grid-template-columns: minmax(0, 2fr) minmax(280px, 1fr);
        gap: 3rem;
    }
}

.aff-event-single__prose {
    font-size: 1.0625rem;
    line-height: 1.7;
    color: var(--aff-fg);
}

.aff-event-single__prose > * + * {
    margin-top: 1.25rem;
}

.aff-event-single__prose h2,
.aff-event-single__prose h3 {
    margin-top: 2rem;
    margin-bottom: 0.75rem;
}

.aff-event-single__sidebar {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.aff-event-single__card {
    background: var(--aff-card);
    border: 1px solid var(--aff-border);
    border-radius: var(--aff-radius-card);
    padding: 1.25rem 1.5rem;
}

.aff-event-single__card-title {
    font-family: var(--wp--preset--font-family--sans);
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--aff-muted-fg);
    margin: 0 0 0.75rem 0;
}

.aff-event-single__card-line {
    margin: 0 0 0.5rem 0;
    font-size: 0.9375rem;
    color: var(--aff-fg);
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.aff-event-single__card-line a {
    color: var(--aff-fg);
    text-decoration: none;
    border-bottom: 1px solid transparent;
    transition: border-color var(--aff-transition), color var(--aff-transition);
}

.aff-event-single__card-line a:hover {
    color: var(--aff-primary);
    border-color: currentColor;
}

.aff-event-single__card-line--strong {
    font-weight: 600;
}

.aff-event-single__card-icon {
    display: inline-flex;
    color: var(--aff-muted-fg);
}

.aff-event-single__card-hint {
    margin: 0.75rem 0 0 0;
    font-size: 0.8125rem;
    color: var(--aff-muted-fg);
    line-height: 1.5;
}

/* Share-actions block (aff/share-actions) ships its own row layout in
 * src/blocks/share-actions/style.css. The card here is a plain wrapper. */

/* ----- related band ----- */
.aff-event-single__related {
    padding-block: 3.5rem 4.5rem;
    background: var(--aff-bg);
}

.aff-event-single__related-title {
    font-family: var(--wp--preset--font-family--serif);
    font-size: clamp(1.5rem, 1.5vw + 1rem, 2rem);
    font-weight: 700;
    color: var(--aff-fg);
    margin: 0 0 1.75rem 0;
}

.aff-event-single__related-grid {
    list-style: none;
    padding: 0;
    margin: 0;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 1.5rem;
}

/* ----- event card (also used by related grid + future archives) ----- */
.aff-event-card {
    background: var(--aff-card);
    border: 1px solid var(--aff-border);
    border-radius: var(--aff-radius-card);
    overflow: hidden;
    transition: transform var(--aff-transition), box-shadow var(--aff-transition);
}

.aff-event-card:hover {
    transform: translateY(-2px);
    box-shadow: var(--aff-shadow-hover);
}

.aff-event-card__link {
    display: flex;
    flex-direction: column;
    height: 100%;
    color: inherit;
    text-decoration: none;
}

.aff-event-card__body {
    padding: 1.25rem 1.5rem 1.5rem 1.5rem;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    flex: 1;
}

.aff-event-card__date {
    font-family: var(--wp--preset--font-family--sans);
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--wp--preset--color--secondary);
}

.aff-event-card__title {
    font-family: var(--wp--preset--font-family--serif);
    font-size: 1.125rem;
    font-weight: 700;
    line-height: 1.25;
    color: var(--aff-fg);
    margin: 0;
}

.aff-event-card__more {
    margin-top: auto;
    padding-top: 0.5rem;
    font-family: var(--wp--preset--font-family--sans);
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--aff-accent);
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
}

/* ---------------------------------------------------------------------- *
 * Project single
 *
 * Hero is shared aff/hero (split + useFeaturedImage). Body band sits on
 * a white card surface with a 2-col layout: prose + sticky sidebar
 * (membership widget by default, editable in the Site Editor).
 * ---------------------------------------------------------------------- */

.aff-project-single {
    margin-block: 0;
}

.aff-project-single__cols {
    gap: 3rem;
}

@media (min-width: 900px) {
    .aff-project-single__cols {
        gap: 4rem;
    }
}

.aff-project-single__main {
    min-width: 0;
}

.aff-project-single__aside {
    min-width: 0;
}

@media (min-width: 900px) {
    .aff-project-single__aside {
        position: sticky;
        top: 6rem;
        align-self: flex-start;
    }
}

.aff-project-single__prose {
    font-size: 1.0625rem;
    line-height: 1.7;
    color: var(--aff-fg);
}

.aff-project-single__prose > * + * {
    margin-top: 1.25rem;
}

.aff-project-single__prose h2,
.aff-project-single__prose h3 {
    font-family: var(--wp--preset--font-family--serif);
    line-height: 1.25;
    margin-top: 2.25rem;
}

.aff-project-single__prose h2 {
    font-size: 1.5rem;
}

.aff-project-single__prose h3 {
    font-size: 1.25rem;
}

.aff-project-single__prose a {
    color: var(--aff-accent);
    text-underline-offset: 3px;
}

.aff-project-single__prose blockquote {
    margin: 1.5rem 0;
    padding: 0.5rem 1.25rem;
    border-inline-start: 3px solid var(--aff-primary);
    color: var(--aff-muted-fg);
    font-style: italic;
}

/* Embeds (YouTube, Vimeo, etc.) and raw iframes/videos must respect the
 * column width and keep a 16:9 aspect ratio. core/embed already provides
 * the figure + wp-block-embed__wrapper hooks; cover both. */
.aff-project-single__prose img,
.aff-project-single__prose video,
.aff-project-single__prose iframe,
.aff-project-single__prose embed,
.aff-project-single__prose object {
    max-width: 100%;
    height: auto;
}

.aff-project-single__prose .wp-block-embed,
.aff-project-single__prose figure {
    max-width: 100%;
    margin-inline: 0;
}

.aff-project-single__prose .wp-block-embed__wrapper {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 9;
}

.aff-project-single__prose .wp-block-embed__wrapper iframe,
.aff-project-single__prose .wp-block-embed__wrapper video {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
}

/* Legacy WordPress auto-embed (wraps the iframe in <span class="embed-youtube">).
 * The iframe carries inline width/height attributes so we force aspect-ratio
 * sizing on the wrapper and stretch the iframe inside it. */
.aff-project-single__prose .embed-youtube,
.aff-project-single__prose .embed-vimeo {
    display: block;
    position: relative;
    width: 100%;
    max-width: 100%;
    aspect-ratio: 16 / 9;
}

.aff-project-single__prose .embed-youtube iframe,
.aff-project-single__prose .embed-vimeo iframe {
    position: absolute;
    inset: 0;
    width: 100% !important;
    height: 100% !important;
}

/* ---------------------------------------------------------------------- *
 * Project body block — variant-specific overrides
 *
 * .aff-project-body wraps all three status variants (active, external,
 * archived). Active re-uses the columns layout above. External and
 * Archived add to it.
 * ---------------------------------------------------------------------- */

/* Outer wrapper — resets block margin so the card band sits flush */
.aff-project-body {
    margin-block: 0;
}

/* Sections emitted by render.php — match the card surface of the original
 * wp:group. `has-global-padding` + `has-card-background-color` come from
 * WordPress core class helpers; duplicate the padding here as a fallback. */
.aff-project-body .aff-project-single {
    padding-block: clamp(2rem, 5vw, 4rem);
    padding-inline: clamp(1rem, 4vw, 3rem);
    background-color: var(--aff-card);
    margin-block: 0;
}

/* ---------------------------------------------------------------------- *
 * External variant — CTA band sits below the prose inside the main
 * column. Membership widget stays in the aside (same shape as Active).
 * ---------------------------------------------------------------------- */

.aff-project-body__cta-band {
    margin-block-start: 2rem;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 1rem;
    padding-block-start: 1.5rem;
    border-block-start: 1px solid var(--aff-border);
}

@media (min-width: 640px) {
    .aff-project-body__cta-band {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
    }
}

.aff-project-body__microcopy {
    margin: 0;
    font-size: 0.9375rem;
    color: var(--aff-muted-fg);
}

.aff-project-body__cta-link {
    flex-shrink: 0;
}

/* ---------------------------------------------------------------------- *
 * Archived variant — muted badge above the prose. Hero eyebrow text
 * still flips to "Arkiverat projekt" via aff/project-eyebrow but uses
 * the default eyebrow styling.
 * ---------------------------------------------------------------------- */

.aff-project-body__archived-badge {
    display: inline-flex;
    margin-block-end: 1.25rem;
}

/* Inline editor-only notice surfaced when an external project has no
 * external URL. Frontend does not load wp-admin styles, so re-create
 * a minimal admin-notice look here. Only visible to users with the
 * edit_aff_projects cap (the render branch gates on that). */
.aff-project-body > .notice {
    margin: 1rem;
    padding: 0.75rem 1rem;
    background-color: #fff8e5;
    border-inline-start: 4px solid #dba617;
    color: #1d2327;
    border-radius: 3px;
}

.aff-project-body > .notice p {
    margin: 0;
}

/* ---------------------------------------------------------------------- *
 * Magazine single (Vårt Försvar)
 *
 * Bands top → bottom:
 *   1. Breadcrumb band (global, owned by aff/breadcrumb)
 *   2. Hero — two-column: prose (chips + title + buttons) | cover image
 *   3. Year picker — heading + hint left, year buttons right
 *
 * Magazine CPT has no editor support (Magazine.php), so the hero leans
 * on post-title + meta blocks; there is no post-content prose.
 * ---------------------------------------------------------------------- */

.aff-magazine-single__hero {
    padding-block: 3rem 4rem;
    background: var(--aff-bg);
}

.aff-magazine-single__hero-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 2.5rem;
    align-items: start;
}

@media (min-width: 900px) {
    .aff-magazine-single__hero-grid {
        /* 50/50 split. Cover stays portrait via aspect-ratio on .aff-magazine-single__cover. */
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
        gap: 4rem;
    }
}

/* Prose column ------------------------------------------------------- */

.aff-magazine-single__prose {
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
}

.aff-magazine-single__chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 0;
}

.aff-magazine-single__title {
    font-family: var(--wp--preset--font-family--serif);
    font-size: clamp(2.25rem, 3vw + 1.5rem, 3.5rem);
    font-weight: 700;
    line-height: 1.05;
    letter-spacing: -0.02em;
    color: var(--aff-fg);
    margin: 0;
}

.aff-magazine-single__lede {
    font-size: 1rem;
    line-height: 1.6;
    color: var(--aff-muted-fg);
    margin: 0;
}

.aff-magazine-single__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    align-items: center;
    margin-top: 0.5rem;
}

/* Bli medlem CTA card under the action buttons. Icon left, copy + link
 * stacked right. Border + soft surface so it reads as a side-note rather
 * than a primary CTA (the primary CTA is the PDF download above). */
.aff-magazine-single__cta {
    display: flex;
    flex-wrap: nowrap;
    align-items: flex-start;
    gap: 1rem;
    padding: 1.25rem 1.5rem;
    border: 1px solid var(--aff-border);
    border-radius: var(--aff-radius-card);
    background: var(--aff-card);
    margin-top: 1rem;
    max-width: 480px;
}

.aff-magazine-single__cta-icon {
    color: var(--aff-secondary);
    flex-shrink: 0;
    margin-top: 0.125rem;
}

.aff-magazine-single__cta-body {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
}

.aff-magazine-single__cta-title {
    font-family: var(--wp--preset--font-family--sans);
    font-size: 1rem;
    font-weight: 700;
    color: var(--aff-fg);
    margin: 0;
}

.aff-magazine-single__cta-text {
    font-size: 0.9375rem;
    line-height: 1.5;
    color: var(--aff-muted-fg);
    margin: 0;
}

/* Cover column ------------------------------------------------------- */

.aff-magazine-single__cover {
    margin: 0;
    border-radius: var(--aff-radius-card);
    overflow: hidden;
    box-shadow: var(--aff-shadow-card);
    background: var(--aff-muted);
    /* Magazine covers are portrait — render at 3:4 ratio. Capped width
     * + height keeps the cover from dominating the band even when the
     * prose column is short. */
    aspect-ratio: 3 / 4;
    width: 100%;
    max-width: 420px;
    max-height: 560px;
    justify-self: center;
}

.aff-magazine-single__cover img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
    display: block;
}

/* Year picker band -------------------------------------------------- */

.aff-magazine-single__years {
    padding-block: 2rem 3rem;
    border-top: 1px solid var(--aff-border);
}

.aff-magazine-single__years-inner {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    align-items: flex-start;
}

.aff-magazine-single__years-head {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.aff-magazine-single__years-title {
    font-family: var(--wp--preset--font-family--sans);
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--aff-muted-fg);
    margin: 0;
}

.aff-magazine-single__years-hint {
    font-size: 0.875rem;
    color: var(--aff-muted-fg);
    margin: 0;
}

.aff-magazine-single__years-list {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.aff-magazine-single__year-btn.is-current {
    background-color: var(--aff-primary);
    color: var(--aff-primary-fg);
    border-color: var(--aff-primary);
}

.aff-magazine-single__year-btn.is-current:hover,
.aff-magazine-single__year-btn.is-current:focus-visible {
    background-color: var(--aff-blue-deep);
    color: var(--aff-primary-fg);
    border-color: var(--aff-blue-deep);
}

/* ---------------------------------------------------------------------- *
 * Hero block — two layout variants and four media kinds.
 *
 * `split`      — text + media columns (matches home design).
 * `background` — full-bleed media behind the copy with a dark overlay.
 *
 * Carousel + video classes live below the variant rules.
 * ---------------------------------------------------------------------- */

.aff-hero {
    --aff-hero-overlay: 40%;
    position: relative;
    overflow: hidden;
}

/* Orange dot accents on inner heading words. Two markup paths produce the
 * same look:
 *  - Pattern source: <span class="aff-hero__word">Word</span> — a
 *    `::after` injects the dot, content stays minimal so a content-only
 *    save round-trip can't strip the punctuation.
 *  - Saved post content: Word<span class="aff-hero__dot">.</span> — the
 *    dot is a real character spawned at first save; colour the span. */
/* Hero h1 — slightly smaller than theme.json's site-wide h1 ramp.
 * theme.json caps at 5.625rem (90px); the hero ramp tops out at
 * 4.5rem (72px) so the hero reads as a hero rather than a marquee. */
.aff-hero h1 {
    font-size: clamp(2.5rem, 4.5vw + 1.25rem, 4.5rem);
}

.aff-hero h1 .aff-hero__word::after {
    content: ".";
    color: var(--aff-accent);
}

.aff-hero h1 .aff-hero__dot {
    color: var(--aff-accent);
}

/* ---------- Split variant ---------- */

.aff-hero--split {
    padding-block: 6rem 8rem;
    padding-inline: var(--wp--style--root--padding-right, 1.5rem);
    background: linear-gradient(to bottom, var(--aff-card), var(--aff-bg));
}

/* Inner shell holds the grid so the editor's block wrapper (which adds
 * its own ::after pseudo for the appender) can't claim a grid track and
 * shrink the layout. Same shape on frontend (`__shell`) and editor
 * (`__editor-shell`) — see edit.tsx. */
.aff-hero--split .aff-hero__shell,
.aff-hero--split .aff-hero__editor-shell {
    display: grid;
    gap: 3rem;
    align-items: center;
}

@media (min-width: 900px) {
    .aff-hero--split .aff-hero__shell,
    .aff-hero--split .aff-hero__editor-shell {
        grid-template-columns: 1fr 1fr;
        gap: 4rem;
    }

    /* When no media is configured the split variant collapses to a single
     * column so the copy doesn't sit alongside an empty grid track. */
    .aff-hero--split .aff-hero__shell--no-media {
        grid-template-columns: minmax(0, 720px);
    }
}

/* Tighten vertical padding when no media — the band otherwise reserves
 * space for a tall image column that no longer exists. */
.aff-hero--split:has(.aff-hero__shell--no-media) {
    padding-block: 4rem 5rem;
}

/* Mobile: 6rem top is too loud on a phone screen, especially under the
 * sticky header. Drop the top to 3rem (48px) so the hero starts under
 * the chrome rather than burying it. */
@media (max-width: 720px) {
    .aff-hero--split {
        padding-block: 3rem 4rem;
    }

    .aff-hero--split:has(.aff-hero__shell--no-media) {
        padding-block: 3rem 3rem;
    }
}

.aff-hero--split .aff-hero__copy,
.aff-hero--split .aff-hero__media-col {
    min-width: 0;
}

.aff-hero--split .aff-hero__media {
    border-radius: var(--aff-radius-lg);
    overflow: hidden;
    aspect-ratio: 4 / 3;
    background: var(--aff-muted);
    position: relative;
}

/* Byline sits directly under the media frame, left-aligned to the image.
 * Wrapper lets us swap per-slide bylines on carousels without disturbing
 * surrounding layout. */
.aff-hero--split .aff-hero__bylines {
    margin-top: 0.5rem;
}

.aff-hero--split .aff-hero__bylines .aff-byline {
    margin-top: 0;
}

.aff-hero--split .aff-hero__media > * {
    width: 100%;
    height: 100%;
}

.aff-hero--split .aff-hero__image {
    display: block;
    object-fit: cover;
}

/* ---------- Background variant ---------- */

.aff-hero--background {
    min-height: clamp(420px, 60vh, 720px);
    display: grid;
    align-items: end;
    padding: clamp(3rem, 8vw, 6rem) var(--wp--style--root--padding-right, 1.5rem);
}

.aff-hero--background .aff-hero__bg {
    position: absolute;
    inset: 0;
    z-index: 0;
    overflow: hidden;
}

.aff-hero--background .aff-hero__bg > * {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.aff-hero--background .aff-hero__scrim {
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, rgba(0, 0, 0, calc(var(--aff-hero-overlay) * 0.4 / 100)) 0%, rgba(0, 0, 0, calc(var(--aff-hero-overlay) / 100)) 100%);
    pointer-events: none;
}

.aff-hero--background .aff-hero__copy {
    position: relative;
    z-index: 1;
    max-width: 720px;
}

/* ---------- Carousel ---------- */

.aff-hero__slides {
    list-style: none;
    margin: 0;
    padding: 0;
    position: absolute;
    inset: 0;
}

.aff-hero__slide {
    position: absolute;
    inset: 0;
    opacity: 0;
    transition: opacity 600ms ease;
    pointer-events: none;
}

.aff-hero__slide[data-aff-active="1"] {
    opacity: 1;
}

.aff-hero__slide-img,
.aff-hero__slide img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Slide transition. Each slide sits offset and slides in from the right.
 * Active slide settles at translateX(0). */
.aff-hero--carousel-slide .aff-hero__slide {
    opacity: 1;
    transform: translateX(100%);
    transition: transform 600ms ease;
}

.aff-hero--carousel-slide .aff-hero__slide[data-aff-active="1"] {
    transform: translateX(0);
}

@media (prefers-reduced-motion: reduce) {
    .aff-hero__slide,
    .aff-hero--carousel-slide .aff-hero__slide {
        transition: none;
    }
}

/* ---------- Video ---------- */

.aff-hero__video {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.aff-hero__embed {
    position: relative;
    width: 100%;
    height: 100%;
}

.aff-hero__embed iframe {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: 0;
}

/* Background variant uses the embed at full bleed instead of the 16:9
 * letterbox the split variant gives it. */
.aff-hero--split .aff-hero__embed {
    aspect-ratio: 16 / 9;
    height: auto;
}

/* ---------- Editor canvas — keep parity with the frontend ---------- */

/* Background variant in the editor still needs a single-column shell so
 * the copy stacks above the media preview. Split variant inherits the
 * grid rules above. */
.aff-hero--background .aff-hero__editor-shell {
    display: block;
}

.aff-hero__editor-media {
    border-radius: var(--aff-radius-lg);
    overflow: hidden;
    aspect-ratio: 4 / 3;
    background: var(--aff-muted);
}

.aff-hero__editor-media img,
.aff-hero__editor-media video {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.aff-hero__editor-embed-placeholder {
    padding: 1rem;
    color: var(--aff-muted-fg);
    font-size: 0.875rem;
}

/* ---------------------------------------------------------------------- *
 * Header
 *
 * Layout strategy:
 *   - Desktop ≥1024px: 3-column bar [logo (left), nav (center), actions (right)].
 *     The nav block sits second in DOM but is reordered to the center via
 *     flex `order`. Outer .aff-header__actions cluster carries search +
 *     lang switcher + Bli medlem button.
 *   - Mobile <1024px: 3-column bar [burger (left), logo (center), spacer (right)].
 *     The outer .aff-header__actions cluster hides; an in-overlay duplicate
 *     (.aff-header__nav-actions, inside the nav block) carries the same
 *     three controls inside the burger overlay so they ride along.
 *
 * The duplicate (vs CSS-only move) is intentional: CSS can't reparent
 * blocks across containers, and JS reparenting is fragile around the
 * core nav block's interactive hydration. Two static instances + a
 * single visibility toggle per breakpoint keeps the logic in CSS.
 * ---------------------------------------------------------------------- */

.aff-header {
    padding-block: 0.75rem;
    background-color: var(--aff-bg);
    border-bottom: 1px solid var(--aff-border);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
}

/* Tighten the global edge padding on the header only — body sections
 * keep the wider gutter for breathing room, but the header packs
 * logo + nav + actions in a single row so it needs every horizontal
 * pixel back. Override scoped via `.aff-header.has-global-padding`
 * (specificity 0,2,0) beats core `.has-global-padding` (0,1,0). */
.aff-header.has-global-padding {
    padding-inline: 0.75rem;
}

@media (min-width: 768px) {
    .aff-header.has-global-padding {
        padding-inline: 1.5rem;
    }
}

@media (min-width: 1100px) {
    .aff-header.has-global-padding {
        padding-inline: 2rem;
    }
}

/* Bar: three-column layout. flex with `order` keeps DOM order
 * [nav, logo, actions] while rendering logo first on desktop. */
.aff-header__bar {
    align-items: center;
}

.aff-header__logo {
    order: 1;
}

.aff-header__nav {
    order: 2;
}

.aff-header__actions {
    order: 3;
}

@media (max-width: 1023.98px) {
    /* Mobile column order: logo left, burger (nav block) right. Parent
     * uses `justify-content: space-between` so the two children push to
     * opposite edges automatically — no margin trick needed. The outer
     * actions cluster hides; its content lives inside the burger overlay
     * via .aff-header__nav-actions. */
    .aff-header__logo {
        order: 0;
    }

    .aff-header__nav {
        order: 1;
    }

    /* `body` prefix bumps specificity to (0,1,1) so we beat core's
     * `body .is-layout-flex { display: flex; }` which would otherwise
     * win on equal-specificity source order. */
    body .aff-header__actions {
        display: none;
    }
}

/* Desktop nav: inline row of links. */
.aff-header__nav .wp-block-navigation__container {
    gap: 2rem;
    align-items: center;
}

/* Tighter gap at small-laptop widths (1024–1199px) to keep the nav on a
 * single row above the burger breakpoint. Above 1200 the comfortable
 * 2rem gap kicks back in. */
@media (max-width: 1199.98px) and (min-width: 1024px) {
    .aff-header__nav .wp-block-navigation__container {
        gap: 1.25rem;
    }
}

.aff-header__nav .wp-block-navigation-item {
    font-size: 0.875rem;
    font-weight: 500;
}

/* Reset link styling inside the nav, but skip the foreningshuset-link
 * block — it has its own button/link variants and shouldn't lose the
 * vertical padding when the in-overlay duplicate renders inside .aff-header__nav. */
.aff-header__nav .wp-block-navigation-item__content,
.aff-header__nav a:not(.aff-foreningshuset-link) {
    color: var(--aff-fg);
    text-decoration: none;
    padding-block: 0;
    transition: color var(--aff-transition);
}

.aff-header__nav .wp-block-navigation-item__content:hover,
.aff-header__nav a:not(.aff-foreningshuset-link):hover {
    color: var(--aff-primary);
}

.aff-header__nav .current-menu-item > a.wp-block-navigation-item__content,
.aff-header__nav .current-menu-parent > a.wp-block-navigation-item__content,
.aff-header__nav .current-menu-ancestor > a.wp-block-navigation-item__content,
.aff-header__nav a[aria-current="page"].wp-block-navigation-item__content {
    color: var(--wp--preset--color--primary);
    border-bottom: 2px solid var(--wp--preset--color--primary);
    padding-bottom: 0.25rem;
}

/* In-overlay duplicate cluster — hidden by default everywhere. The
 * burger overlay rules below flip it to flex inside the open overlay.
 *
 * `!important` is required because WP injects a per-block
 * `wp-container-…-is-layout-flex { display: flex }` rule whose
 * specificity matches and source-order wins. That core rule fires in
 * both the frontend and the Site Editor canvas — without `!important`
 * the cluster shows up next to the desktop actions in the editor and
 * (depending on cache state) on the frontend too. */
body .aff-header__nav-actions {
    display: none !important;
}

/* Desktop-only outer actions cluster. Mobile hides this via the
 * <1024 media query above; we scope `display: flex` to min-width so
 * source-order doesn't override the hide. */
@media (min-width: 1024px) {
    .aff-header__actions {
        display: flex;
        align-items: center;
        gap: 1.25rem;
    }
}

/* Icon-only search. Button stays in flow; input floats absolutely so it
 * never pushes other actions. WP toggles `searchfield-hidden` on click. */
.aff-header__actions .wp-block-search {
    position: relative;
    margin: 0;
}

.aff-header__actions .wp-block-search__inside-wrapper {
    border: 0;
    background: transparent;
    padding: 0;
    box-shadow: none;
}

.aff-header__actions .wp-block-search__button {
    position: relative;
    z-index: 10;
    margin: 0;
    border: 0;
    background: transparent;
    padding: 0;
    color: var(--aff-fg);
    transition: color var(--aff-transition);
}

.aff-header__actions .wp-block-search__button:hover {
    color: var(--aff-primary);
}

.aff-header__actions .wp-block-search__button svg {
    width: 1.25rem;
    height: 1.25rem;
    fill: currentColor;
}

.aff-header__actions .wp-block-search .wp-block-search__input {
    position: absolute;
    top: 50%;
    right: calc(100% + 0.5rem);
    left: auto;
    transform: translateY(-50%);
    margin: 0;
    width: 18rem;
    min-width: 18rem;
    border: 1px solid var(--aff-border);
    border-radius: var(--aff-radius-md);
    background: var(--aff-card);
    padding: 0.5rem 0.875rem;
    font-size: 0.875rem;
    color: var(--aff-fg);
    box-shadow: var(--aff-shadow-card);
    transition: opacity var(--aff-transition-fast), transform var(--aff-transition-fast);
    opacity: 1;
    pointer-events: auto;
    z-index: 60;
}

.aff-header__actions .wp-block-search.wp-block-search__searchfield-hidden .wp-block-search__input {
    opacity: 0;
    pointer-events: none;
    transform: translateY(-50%) translateX(0.5rem);
}

.aff-header__actions .wp-block-search .wp-block-search__input:focus {
    outline: none;
    box-shadow: var(--aff-focus-ring);
}

/* 1px separator between search and lang switcher. */
.aff-header__actions .wp-block-search + .aff-language-switcher {
    position: relative;
    padding-left: 1.25rem;
}

.aff-header__actions .wp-block-search + .aff-language-switcher::before {
    content: "";
    position: absolute;
    left: 0;
    top: 50%;
    transform: translateY(-50%);
    width: 1px;
    height: 1rem;
    background-color: var(--aff-border);
}

.aff-header__actions .aff-language-switcher__trigger {
    padding-inline: 0;
    color: var(--aff-fg);
}

.aff-header__actions .aff-language-switcher__trigger:hover {
    color: var(--aff-primary);
}

.aff-header__actions .aff-language-switcher__current {
    font-weight: 500;
    letter-spacing: normal;
}

/* ---------------------------------------------------------------------- *
 * Burger overlay (<1024px)
 *
 * WP core nav switches inline→overlay at 600px by default; we raise that
 * to the standard small-laptop floor (Tailwind `lg` / Bootstrap `lg`).
 * The overlay machinery (toggle button, modal container, close button)
 * is already emitted by core; we override visibility per breakpoint and
 * restyle the modal contents.
 * ---------------------------------------------------------------------- */
@media (max-width: 1023.98px) {
    /* Show the burger toggle, hide the inline container. */
    .aff-header__nav .wp-block-navigation__responsive-container-open {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 2.5rem;
        height: 2.5rem;
        margin: 0;
        padding: 0;
        background: transparent;
        border: 0;
        border-radius: var(--aff-radius-sm);
        color: var(--aff-fg);
        cursor: pointer;
        transition: background-color var(--aff-transition-fast);
    }

    .aff-header__nav .wp-block-navigation__responsive-container-open:hover,
    .aff-header__nav .wp-block-navigation__responsive-container-open:focus-visible {
        background-color: var(--aff-muted);
    }

    .aff-header__nav .wp-block-navigation__responsive-container-open svg {
        width: 1.5rem;
        height: 1.5rem;
        fill: currentColor;
    }

    .aff-header__nav .wp-block-navigation__responsive-container:not(.is-menu-open) {
        display: none;
    }

    /* Slide-in overlay from the right. */
    .aff-header__nav .wp-block-navigation__responsive-container.is-menu-open {
        position: fixed;
        inset: 0;
        z-index: 100000;
        padding: 0;
        background: var(--aff-bg);
        display: block;
        animation: aff-header-overlay-in 200ms ease-out;
    }

    .aff-header__nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-close {
        max-width: 100%;
        padding: 1.5rem;
    }

    .aff-header__nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-dialog {
        margin-top: 0;
    }

    /* Close (X) button — top-right corner of overlay. */
    .aff-header__nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-close {
        position: absolute;
        top: 1rem;
        right: 1rem;
        width: 2.5rem;
        height: 2.5rem;
        display: flex;
        align-items: center;
        justify-content: center;
        background: transparent;
        border: 0;
        border-radius: var(--aff-radius-sm);
        color: var(--aff-fg);
        cursor: pointer;
        transition: background-color var(--aff-transition-fast);
    }

    .aff-header__nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-close:hover,
    .aff-header__nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-close:focus-visible {
        background-color: var(--aff-muted);
    }

    .aff-header__nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-close svg {
        width: 1.5rem;
        height: 1.5rem;
        fill: currentColor;
    }

    /* Force the overlay dialog + content + list to fill the modal so
     * items left-align instead of shrink-to-content centering. WP core
     * gives the dialog content-width margins; we override to flush left. */
    .aff-header__nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-dialog,
    .aff-header__nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content {
        width: 100%;
        max-width: 100%;
        margin: 0;
    }

    /* Stacked list inside the overlay. */
    .aff-header__nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container {
        flex-direction: column;
        align-items: stretch;
        gap: 0;
        width: 100%;
        font-size: 1.125rem;
        padding: 3.5rem 0 1rem;
    }

    .aff-header__nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item {
        font-size: 1.125rem;
        font-weight: 600;
        justify-content: flex-start;
        border-bottom: 1px solid var(--aff-border);
    }

    .aff-header__nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content {
        padding: 0.875rem 0;
        display: block;
        flex: 1 1 auto;
        width: 100%;
        text-align: left;
    }

    /* Submenu items inline-expand: parent stays a link, the chevron next
     * to it is the toggle. WP core forces flex-direction:column on the
     * submenu li — we need row + wrap so [link | chevron] sit on one row
     * and the submenu container wraps to a new line below. */
    .aff-header__nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-submenu {
        flex-direction: row;
        flex-wrap: wrap;
        align-items: center;
    }

    /* Submenu parent link: shrink-to-share so chevron sits next to it on
     * the same row. Override the unconditional width:100% from
     * `.wp-block-navigation-item__content` above. */
    .aff-header__nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-submenu > .wp-block-navigation-item__content {
        flex: 1 1 auto;
        min-width: 0;
        width: auto;
    }

    /* Force the chevron toggle visible inside the overlay — core sets
     * it to display:none below the desktop breakpoint by default.
     * Fixed-width box (no padding) so the flex sibling content can
     * compute against a known footprint without wrapping. */
    .aff-header__nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-icon {
        display: flex;
        align-items: center;
        justify-content: center;
        flex: 0 0 2.5rem;
        width: 2.5rem;
        height: 2.5rem;
        margin: 0;
        padding: 0;
        background: transparent;
        border: 0;
        border-radius: var(--aff-radius-sm);
        color: var(--aff-fg);
        cursor: pointer;
        transition: background-color var(--aff-transition-fast);
    }

    .aff-header__nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-icon:hover,
    .aff-header__nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-icon:focus-visible {
        background-color: var(--aff-muted);
    }

    .aff-header__nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-icon svg {
        width: 0.875rem;
        height: 0.875rem;
        transition: transform 150ms ease;
    }

    .aff-header__nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-submenu.is-menu-open > .wp-block-navigation__submenu-icon svg {
        transform: rotate(180deg);
    }

    /* Submenu collapsed by default. Core toggles `.is-menu-open` on the
     * parent submenu li via interactive script when the chevron is clicked. */
    .aff-header__nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container {
        display: none;
        position: static;
        background: transparent;
        box-shadow: none;
        border: 0;
        min-width: 0;
        flex-basis: 100%;
        padding: 0 0 0.5rem 1rem;
    }

    .aff-header__nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-submenu.is-menu-open > .wp-block-navigation__submenu-container,
    .aff-header__nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-submenu:hover > .wp-block-navigation__submenu-container,
    .aff-header__nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-submenu:focus-within > .wp-block-navigation__submenu-container {
        display: block;
    }

    .aff-header__nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container .wp-block-navigation-item {
        font-size: 1rem;
        font-weight: 500;
        border-bottom: 0;
    }

    .aff-header__nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container .wp-block-navigation-item__content {
        padding: 0.5rem 0;
    }

    /* In-overlay action cluster — visible only inside the open overlay.
     * Single row: search (flex-grow 1) + lang switcher + Bli medlem
     * button. Wraps when the viewport gets too narrow for all three. */
    .aff-header__nav .wp-block-navigation__responsive-container.is-menu-open .aff-header__nav-actions {
        display: flex !important;
        flex-direction: row;
        flex-wrap: wrap;
        align-items: center;
        gap: 0.75rem;
        margin-top: 1.5rem;
    }

    .aff-header__nav .wp-block-navigation__responsive-container.is-menu-open .aff-header__nav-actions .wp-block-search {
        flex: 1 1 12rem;
        min-width: 0;
    }

    .aff-header__nav .wp-block-navigation__responsive-container.is-menu-open .aff-header__nav-actions .wp-block-search {
        margin: 0;
    }

    .aff-header__nav .wp-block-navigation__responsive-container.is-menu-open .aff-header__nav-actions .wp-block-search__inside-wrapper {
        display: flex;
        align-items: stretch;
        border: 1px solid var(--aff-border);
        border-radius: var(--aff-radius-md);
        background: var(--aff-card);
        padding: 0;
        box-shadow: none;
    }

    .aff-header__nav .wp-block-navigation__responsive-container.is-menu-open .aff-header__nav-actions .wp-block-search__input {
        position: static;
        width: 100%;
        min-width: 0;
        margin: 0;
        border: 0;
        background: transparent;
        box-shadow: none;
        padding: 0.625rem 0.875rem;
        font-size: 1rem;
        opacity: 1;
        pointer-events: auto;
        transform: none;
    }

    .aff-header__nav .wp-block-navigation__responsive-container.is-menu-open .aff-header__nav-actions .wp-block-search__button {
        display: flex;
        align-items: center;
        justify-content: center;
        margin: 0;
        padding: 0.5rem 0.875rem;
        background: transparent;
        border: 0;
        color: var(--aff-fg);
    }

    .aff-header__nav .wp-block-navigation__responsive-container.is-menu-open .aff-header__nav-actions .wp-block-search__button svg {
        width: 1.125rem;
        height: 1.125rem;
        fill: currentColor;
    }

    .aff-header__nav .wp-block-navigation__responsive-container.is-menu-open .aff-header__nav-actions .aff-language-switcher,
    .aff-header__nav .wp-block-navigation__responsive-container.is-menu-open .aff-header__nav-actions .aff-foreningshuset-link {
        flex: 0 0 auto;
    }

    /* Lock body scroll while overlay is open. */
    .aff-header__nav .wp-block-navigation__responsive-container.has-modal-open {
        overflow: auto;
    }
}

@keyframes aff-header-overlay-in {
    from {
        transform: translateX(2rem);
        opacity: 0;
    }
    to {
        transform: translateX(0);
        opacity: 1;
    }
}

@media (min-width: 1024px) {
    .aff-header__nav .wp-block-navigation__responsive-container-open {
        display: none;
    }
}

/* ---------------------------------------------------------------------- *
 * Project grid (home)
 * ---------------------------------------------------------------------- */

.aff-project-grid {
    gap: 2rem;
}

.aff-project-grid__head {
    margin-bottom: 3rem;
    align-items: flex-end;
}

.aff-project-grid__all a {
    text-decoration: none;
    font-weight: 500;
    color: var(--aff-accent);
    transition: color var(--aff-transition);
}

.aff-project-grid__all a:hover {
    color: var(--aff-orange-hover);
}

.aff-project-card {
    background: var(--aff-card);
    border: 1px solid var(--aff-border);
    border-radius: var(--aff-radius-card);
    box-shadow: var(--aff-shadow-card);
    overflow: hidden;
    transition: box-shadow var(--aff-transition);
    padding: 0;
    height: 100%;
    display: flex;
    flex-direction: column;
}

.aff-project-card:hover {
    box-shadow: var(--aff-shadow-hover);
}

.aff-project-card__media {
    margin: 0;
}

/* Collapse empty featured-image wrapper when post has no thumbnail —
 * core renders an empty `<a>` placeholder otherwise, leaving a blank
 * box at the top of the card. `:has(img)` keeps the slot when there
 * IS an image. */
.aff-project-card__media:not(:has(img)) {
    display: none;
}

/* When no media, body needs its own top padding (otherwise it sits
 * flush to the card top). */
.aff-project-card:not(:has(.aff-project-card__media img)) .aff-project-card__body {
    padding-top: 2rem;
}

.aff-project-card__media img {
    width: 100%;
    height: 12rem;
    object-fit: cover;
    display: block;
    transition: transform 500ms ease;
}

.aff-project-card:hover .aff-project-card__media img {
    transform: scale(1.05);
}

.aff-project-card__body {
    padding: 0 2rem 2rem 2rem;
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    gap: 1rem;
}

.aff-project-card__title {
    font-size: 1.5rem;
    line-height: 1.25;
    font-weight: 700;
    margin: 0;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.aff-project-card__title a {
    color: var(--aff-fg);
    text-decoration: none;
    transition: color var(--aff-transition);
}

.aff-project-card__title a:hover {
    color: var(--aff-primary);
}

.aff-project-card__excerpt {
    margin: 0;
    flex: 1 1 auto;
    color: var(--aff-fg);
}

.aff-project-card__excerpt p {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
    margin: 0;
}

/* Editor only: post-excerpt paints a placeholder more-link inline. We
 * render the more-link via a sibling `wp:read-more` block, so suppress
 * the inline one. Frontend never renders it (moreText is empty). */
.aff-project-card__excerpt .wp-block-post-excerpt__more-link {
    display: none;
}

.aff-project-card__more {
    margin-top: auto;
    color: var(--aff-accent);
    text-decoration: none;
    font-weight: 500;
    align-self: flex-start;
    transition: color var(--aff-transition);
}

.aff-project-card__more:hover {
    color: var(--aff-orange-hover);
}


/* ---------------------------------------------------------------------- *
 * Footer
 * ---------------------------------------------------------------------- */

.aff-footer {
    padding-block: 5rem 2rem;
    border-top: 4px solid var(--aff-accent);
}

/* Core's `:where(.wp-site-blocks) > *` rule injects ~24px margin-block-start
 * on every top-level block — including the footer template-part wrapper.
 * Kill it on the footer wrapper specifically. */
.wp-site-blocks > footer.wp-block-template-part {
    margin-block-start: 0;
}

/* Footer-owned heading. Decoupled from raw <h3>/<h4> tags so any future
 * heading inside the footer pattern picks up the dark-on-light styling
 * intentionally, not by accident. */
.aff-footer__heading {
    color: var(--aff-card);
    margin: 0 0 1.5rem 0;
    font-family: var(--wp--preset--font-family--serif);
    font-size: 1.25rem;
    font-weight: 700;
    line-height: 1.15;
}

.aff-footer a {
    color: var(--aff-footer-text);
    text-decoration: none;
    transition: color var(--aff-transition);
}

.aff-footer a:hover {
    color: var(--aff-footer-text-strong);
}

.aff-footer__links {
    list-style: none;
    padding-left: 0;
    margin: 0;
}

.aff-footer__links li {
    margin-bottom: 0.75rem;
}

.aff-footer__logo {
    background: var(--aff-card);
    border-radius: var(--aff-radius-sm);
    padding: 0.375rem 0.5rem;
    width: 6.5rem;
    margin: 0 0 1.5rem 0;
}

.aff-footer__logo img {
    width: 100%;
    height: auto;
    display: block;
}

.aff-footer__intro {
    color: var(--aff-footer-text);
    margin: 0 0 1.5rem 0;
    line-height: 1.6;
}

/* On-dark variants of the social-icons / subscribe-form blocks. The
 * footer pattern adds these modifier classes so the dark-surface styles
 * stay opt-in instead of leaking via descendant selectors. The class
 * may land on the <ul> itself (frontend, via get_block_wrapper_attributes)
 * or on a wrapping <div> (Site Editor block-renderer wrapper). Match
 * both so the icons stay horizontal in either context. */
.aff-social-icons.aff-social-icons--on-dark,
.aff-social-icons--on-dark .aff-social-icons,
.aff-social-icons--on-dark > ul {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.aff-social-icons--on-dark .aff-social-icons__item a {
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 50%;
    background: var(--aff-footer-icon-bg);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--aff-footer-text-faint);
    transition: background var(--aff-transition), color var(--aff-transition);
}

.aff-social-icons--on-dark .aff-social-icons__item a:hover {
    background: var(--aff-accent);
    color: var(--aff-footer-text-strong);
}

.aff-social-icons--on-dark .aff-social-icons__item svg {
    width: 1.125rem;
    height: 1.125rem;
    display: block;
}

.aff-subscribe-form--on-dark {
    margin-top: 0.5rem;
}

.aff-subscribe-form--on-dark .aff-field,
.aff-subscribe-form--on-dark input[type="email"],
.aff-subscribe-form--on-dark input[type="text"] {
    width: 100%;
    min-width: 0;
    max-width: 100%;
    background: var(--aff-footer-input-bg);
    border: 1px solid var(--aff-footer-input-border);
    border-radius: var(--aff-radius-md);
    color: var(--aff-footer-text-strong);
    padding: 0.75rem 1rem;
    font-size: 0.9375rem;
}

.aff-subscribe-form--on-dark .aff-field:hover {
    border-color: var(--aff-accent);
}

.aff-subscribe-form--on-dark input::placeholder {
    color: var(--aff-footer-text-muted);
}

.aff-subscribe-form--on-dark input:focus {
    outline: none;
    border-color: var(--aff-accent);
}

.aff-subscribe-form--on-dark button {
    width: 100%;
    background: var(--aff-accent);
    color: var(--aff-footer-text-strong);
    border: 0;
    border-radius: var(--aff-radius-md);
    padding: 0.75rem 1rem;
    font-weight: 600;
    cursor: pointer;
    transition: background var(--aff-transition);
    margin-top: 0.75rem;
}

.aff-subscribe-form--on-dark button:hover {
    background: var(--aff-orange-hover);
}

/* Footer subscribe drops the chatty intro/legal — mockup has neither. */
.aff-subscribe-form--on-dark .aff-subscribe-form__intro,
.aff-subscribe-form--on-dark .aff-subscribe-form__legal {
    display: none;
}

/* Labels stay in the DOM and announce to screen readers but are
 * visually hidden — the field is unmistakable from the placeholder
 * and the surrounding "Följ oss" + intro copy. `display: none` would
 * also hide the label from assistive tech (Lighthouse a11y rule
 * "Form elements do not have associated labels"). */
.aff-subscribe-form--on-dark label,
.aff-subscribe-form--on-dark .aff-field-label {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.aff-subscribe-form--on-dark .aff-subscribe-form__notice,
.aff-subscribe-form--on-dark .aff-subscribe-form__placeholder {
    font-size: 0.75rem;
    color: var(--aff-footer-text-muted);
    line-height: 1.5;
    margin-top: 0.75rem;
}

.aff-footer__divider {
    border: 0;
    border-top: 1px solid var(--aff-footer-divider);
    background: transparent;
    margin: 3rem 0 2rem 0;
}

.aff-footer__legal {
    align-items: center;
    gap: 1.5rem;
}

.aff-footer__legal p {
    margin: 0;
    color: var(--aff-footer-text-muted);
}

.aff-footer__legal-links {
    display: inline-flex;
    gap: 1.5rem;
}

/* ---------------------------------------------------------------------- *
 * Föreningshuset CTA
 * ---------------------------------------------------------------------- */

.aff-foreningshuset-link {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    text-decoration: none;
}

.aff-foreningshuset-link--button {
    border-radius: var(--aff-radius-md);
    background: var(--aff-accent);
    color: var(--aff-accent-fg);
    padding: 0.625rem 1.25rem;
    font-size: 0.875rem;
    font-weight: 500;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
    transition: background var(--aff-transition);
}

.aff-foreningshuset-link--button:hover {
    background: var(--aff-orange-hover);
}

.aff-foreningshuset-link--button:focus-visible {
    outline: none;
    box-shadow: var(--aff-focus-ring);
}

.aff-foreningshuset-link--link {
    color: var(--aff-accent);
    text-decoration: none;
    font-weight: 600;
    gap: 0.375rem;
    transition: color var(--aff-transition), gap var(--aff-transition);
}

.aff-foreningshuset-link--link .aff-foreningshuset-link__label {
    text-decoration: none;
}

.aff-foreningshuset-link--link:hover,
.aff-foreningshuset-link--link:focus-visible {
    color: var(--aff-orange-hover);
    gap: 0.5rem;
}

.aff-foreningshuset-link--link:hover .aff-foreningshuset-link__label,
.aff-foreningshuset-link--link:focus-visible .aff-foreningshuset-link__label {
    text-decoration: underline;
    text-underline-offset: 0.2em;
}

.aff-foreningshuset-link__arrow {
    display: inline-flex;
    align-items: center;
    line-height: 1;
}


/* ---------------------------------------------------------------------- *
 * Event list — home "Kommande Evenemang" section.
 *
 * Two-column at >= 782px (core columns breakpoint): left rail with
 * eyebrow / heading / "Se hela kalendern", right column with event
 * cards. Layout itself comes from the wp:columns block in
 * patterns/event-list.php; rules here only style the inner content.
 * ---------------------------------------------------------------------- */

.aff-event-list__intro {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.aff-event-list__heading {
    font-family: var(--wp--preset--font-family--serif);
    font-size: clamp(2rem, 3.2vw, 2.75rem);
    line-height: 1.1;
    margin: 0;
    color: var(--aff-fg);
}

.aff-event-list__all {
    margin: 0.5rem 0 0;
    font-weight: 500;
}

.aff-event-list__all a {
    color: var(--aff-accent);
    text-decoration: none;
    transition: color var(--aff-transition);
}

.aff-event-list__all a:hover,
.aff-event-list__all a:focus-visible {
    color: var(--aff-orange-hover);
}

.aff-event-list__items {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
}

.aff-event-list__item {
    display: grid;
    grid-template-columns: 4.5rem 1fr auto;
    column-gap: 2rem;
    row-gap: 0.5rem;
    align-items: start;
    padding-block: 1.75rem;
    border-block-start: 1px solid var(--aff-border);
}

.aff-event-list__item:first-child {
    border-block-start: 0;
    padding-block-start: 0;
}

.aff-event-list__date {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    line-height: 1;
}

.aff-event-list__date-month {
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.1em;
    color: var(--aff-muted-fg);
    margin-block-end: 0.5rem;
}

.aff-event-list__date-day {
    font-family: var(--wp--preset--font-family--serif);
    font-size: 2.75rem;
    font-weight: 700;
    color: var(--aff-primary);
}

.aff-event-list__body {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    min-width: 0;
}

.aff-event-list__meta {
    margin: 0;
    font-size: 0.875rem;
    color: var(--aff-muted-fg);
    display: flex;
    align-items: center;
    gap: 1rem;
}

.aff-event-list__location {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
}

.aff-event-list__location svg {
    flex-shrink: 0;
}

.aff-event-list__title {
    font-family: var(--wp--preset--font-family--serif);
    font-size: 1.375rem;
    line-height: 1.25;
    margin: 0;
    font-weight: 700;
}

.aff-event-list__title a {
    color: var(--aff-fg);
    text-decoration: none;
    transition: color var(--aff-transition);
}

.aff-event-list__title a:hover,
.aff-event-list__title a:focus-visible {
    color: var(--aff-primary);
}

.aff-event-list__excerpt {
    margin: 0;
    color: var(--aff-muted-fg);
    line-height: 1.5;
}

.aff-event-list__cta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    border: 1px solid var(--aff-border);
    border-radius: var(--aff-radius-pill);
    color: var(--aff-fg);
    text-decoration: none;
    transition: background-color var(--aff-transition), color var(--aff-transition), border-color var(--aff-transition);
    align-self: center;
}

.aff-event-list__cta:hover,
.aff-event-list__cta:focus-visible {
    background-color: var(--aff-primary);
    border-color: var(--aff-primary);
    color: var(--aff-primary-fg);
}

.aff-event-list__empty {
    margin: 0;
    color: var(--aff-muted-fg);
}

@media (max-width: 600px) {
    .aff-event-list__item {
        grid-template-columns: 3.5rem 1fr;
        column-gap: 1.25rem;
    }

    .aff-event-list__cta {
        grid-column: 2;
        justify-self: flex-start;
        margin-block-start: 0.5rem;
    }

    .aff-event-list__date-day {
        font-size: 2.25rem;
    }
}

/* ---------------------------------------------------------------------- *
 * Event archive — /kalendarium/. Reuses `.aff-event-list__items` cards
 * via the aff/event-cards block; this file owns the surrounding band
 * headings + spacing for the upcoming / past pair.
 * ---------------------------------------------------------------------- */

.aff-event-archive {
    margin-block: 0;
}

.aff-event-archive__heading {
    font-family: var(--wp--preset--font-family--serif);
    font-size: clamp(1.5rem, 1rem + 1.25vw, 2rem);
    line-height: 1.2;
    margin: 0 0 1.75rem;
    color: var(--aff-fg);
}
/* ---------------------------------------------------------------------- *
 * Branch grid — home "Länsavdelningar" section.
 *
 * Centred intro, four-column card grid (drops to two-up under 900px,
 * single column under 600px). Footer CTA centres a pill button linking
 * to the branch archive.
 * ---------------------------------------------------------------------- */

.aff-branch-grid {
    text-align: center;
}

/* Extra breathing room below the branch section before the footer/next
 * surface kicks in. .aff-section's 6rem block padding only buys the same
 * top and bottom; the home design wants a deeper tail here. */
.aff-branch-grid-section {
    padding-block-end: 9rem;
}

.aff-branch-grid-section .aff-eyebrow.has-text-align-center {
    /* Recentre the eyebrow's leading dot when the paragraph is
     * centre-aligned. The base atom anchors the dot at the left of the
     * text run, which reads off when the surrounding column is centred. */
    text-align: center;
}

.aff-branch-grid__heading {
    font-family: var(--wp--preset--font-family--serif);
    font-size: clamp(2rem, 3.2vw, 2.5rem);
    font-weight: 700;
    line-height: 1.1;
    margin-block: 0 1rem;
    color: var(--aff-fg);
}

.aff-branch-grid__lede {
    max-width: 640px;
    margin: 0 auto 3rem;
    color: var(--aff-muted-fg);
    line-height: 1.6;
}

.aff-branch-grid__items {
    list-style: none;
    margin: 0 0 2.5rem;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 1.25rem;
}

.aff-branch-grid__card {
    background: var(--aff-muted);
    border-radius: var(--aff-radius-card);
    padding: 1.75rem 1.5rem;
    text-align: left;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    min-height: 8rem;
    transition: box-shadow var(--aff-transition);
}

.aff-branch-grid__card:hover,
.aff-branch-grid__card:focus-within {
    box-shadow: var(--aff-shadow-hover);
}

.aff-branch-grid__card-title {
    font-family: var(--wp--preset--font-family--serif);
    font-size: 1.25rem;
    font-weight: 700;
    margin: 0;
    line-height: 1.2;
    color: var(--aff-fg);
}

.aff-branch-grid__card-meta {
    margin: 0;
    color: var(--aff-muted-fg);
    font-size: 0.875rem;
}

.aff-branch-grid__cta {
    margin: 0;
}

.aff-branch-grid__cta-link {
    display: inline-block;
    padding: 0.75rem 1.5rem;
    border: 1px solid var(--aff-border);
    border-radius: var(--aff-radius-md);
    color: var(--aff-fg);
    background: var(--aff-card);
    font-weight: 600;
    text-decoration: none;
    transition: background-color var(--aff-transition), border-color var(--aff-transition), color var(--aff-transition);
}

.aff-branch-grid__cta-link:hover,
.aff-branch-grid__cta-link:focus-visible {
    background: var(--aff-primary);
    border-color: var(--aff-primary);
    color: var(--aff-primary-fg);
}

.aff-branch-grid__empty {
    margin: 0;
    color: var(--aff-muted-fg);
}

@media (max-width: 900px) {
    .aff-branch-grid__items {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (max-width: 600px) {
    .aff-branch-grid__items {
        grid-template-columns: 1fr;
    }
}

/* ---------------------------------------------------------------------- *
 * Branch archive — Länsavdelningar full archive page
 *
 * Hero band lives in the template (aff/hero with no media). This file
 * styles the body: search input, count + view toggle, branch cards.
 * ---------------------------------------------------------------------- */

.aff-branch-archive {
    /* Stack search → head → grid; consistent vertical rhythm. */
    display: flex;
    flex-direction: column;
    gap: 2rem;
}

/* ----- search ----- */

.aff-branch-archive__search {
    display: flex;
    justify-content: center;
    /* Pull the search up so it visually overlaps the hero edge — matches
     * the design where the input sits between the hero copy and the
     * white card grid. */
    margin-block-start: -3.5rem;
}

.aff-branch-archive__search-label {
    position: relative;
    display: block;
    width: 100%;
    max-width: 480px;
}

.aff-branch-archive__search-icon {
    position: absolute;
    left: 1rem;
    top: 50%;
    transform: translateY(-50%);
    color: var(--aff-muted-fg);
    pointer-events: none;
    display: inline-flex;
}

/* Higher specificity than `input[type="search"].aff-field` so the
 * archive search overrides the atom's default padding to make room
 * for the leading icon. */
input[type="search"].aff-branch-archive__search-input {
    padding-inline-start: 2.75rem;
    padding-block: 0.875rem;
    border-radius: var(--aff-radius-lg);
    box-shadow: var(--aff-shadow-card);
    background: var(--aff-card);
}

/* ----- head row (count + view toggle) ----- */

.aff-branch-archive__head {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: center;
    gap: 1rem;
}

.aff-branch-archive__count {
    font-family: var(--wp--preset--font-family--sans);
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--aff-fg);
    margin: 0;
}

.aff-branch-archive__view {
    display: inline-flex;
    border: 1px solid var(--aff-border);
    border-radius: var(--aff-radius-md);
    background: var(--aff-card);
    overflow: hidden;
}

.aff-branch-archive__view-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.5rem 0.875rem;
    background: transparent;
    border: 0;
    color: var(--aff-muted-fg);
    font-family: inherit;
    font-size: 0.8125rem;
    font-weight: 600;
    cursor: pointer;
    transition: background var(--aff-transition), color var(--aff-transition);
}

.aff-branch-archive__view-btn + .aff-branch-archive__view-btn {
    border-inline-start: 1px solid var(--aff-border);
}

.aff-branch-archive__view-btn:hover {
    color: var(--aff-fg);
}

.aff-branch-archive__view-btn.is-active {
    background: var(--aff-primary);
    color: var(--aff-primary-fg);
}

/* ----- card grid ----- */

.aff-branch-archive__items {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 1.25rem;
}

@media (max-width: 1200px) {
    .aff-branch-archive__items {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

@media (max-width: 900px) {
    .aff-branch-archive__items {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (max-width: 600px) {
    .aff-branch-archive__items {
        grid-template-columns: 1fr;
    }
}

/* ---------------------------------------------------------------------- *
 * List view — drops the card surface entirely. Rows separated by hairlines,
 * single column, denser line-height, action link right-aligned.
 * ---------------------------------------------------------------------- */

.aff-branch-archive__items[data-aff-view="list"] {
    grid-template-columns: 1fr;
    gap: 0;
    border-block: 1px solid var(--aff-border);
}

.aff-branch-archive__items[data-aff-view="list"] .aff-branch-archive__card {
    background: transparent;
    border: 0;
    border-radius: 0;
    padding: 1rem 1.25rem;
    min-height: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0.5rem;
    border-block-end: 1px solid var(--aff-border);
}

.aff-branch-archive__items[data-aff-view="list"] .aff-branch-archive__card:last-child {
    border-block-end: 0;
}

.aff-branch-archive__items[data-aff-view="list"] .aff-branch-archive__card:hover,
.aff-branch-archive__items[data-aff-view="list"] .aff-branch-archive__card:focus-within {
    box-shadow: none;
    background: transparent;
}

/* ----- card ----- */

.aff-branch-archive__card {
    background: var(--aff-muted);
    border: 1px solid transparent;
    border-radius: var(--aff-radius-card);
    padding: 1.25rem 1.5rem 1.5rem;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    min-height: 8rem;
    transition: box-shadow var(--aff-transition), border-color var(--aff-transition);
}

/* `display: flex` above wins over the UA `[hidden] { display: none }`
 * rule, so explicitly hide cards the live filter has marked hidden. */
.aff-branch-archive__card[hidden] {
    display: none;
}

.aff-branch-archive__card:hover,
.aff-branch-archive__card:focus-within {
    box-shadow: var(--aff-shadow-hover);
    border-color: var(--aff-border);
}

/* ----- card details (collapsible) ----- */

.aff-branch-archive__card-details {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    flex: 1;
}

.aff-branch-archive__card-summary {
    list-style: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 0.625rem;
    padding: 0;
}

.aff-branch-archive__card-summary::-webkit-details-marker {
    display: none;
}

.aff-branch-archive__card-summary-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--aff-muted-fg);
    transition: transform var(--aff-transition);
    flex-shrink: 0;
}

/* Open state rotates the chevron 180° regardless of view mode. CSS only
 * — `[open]` flips driven by JS-set state in grid view and by the user
 * click in list view. */
.aff-branch-archive__card-details[open] .aff-branch-archive__card-summary-icon {
    transform: rotate(180deg);
}

.aff-branch-archive__card-title {
    font-family: var(--wp--preset--font-family--serif);
    font-size: 1.25rem;
    font-weight: 700;
    margin: 0;
    line-height: 1.2;
    color: var(--aff-fg);
}

/* Two title + two meta nodes shipped per card — one each for the grid
 * surface (visible at the top of the card) and one each for the list
 * surface (rendered inside the collapsible details). View-mode CSS
 * hides the unused pair. */
.aff-branch-archive__items[data-aff-view="grid"] .aff-branch-archive__card-title--list,
.aff-branch-archive__items[data-aff-view="grid"] .aff-branch-archive__card-meta--list {
    display: none;
}

.aff-branch-archive__items[data-aff-view="list"] .aff-branch-archive__card-title--grid,
.aff-branch-archive__items[data-aff-view="list"] .aff-branch-archive__card-meta--grid {
    display: none;
}

/* Summary labels — only render the "Visa/Dölj kontaktinfo" pair in grid
 * mode (next to the bottom chevron). List mode shows the title in the
 * summary instead. CSS-only swap between closed + open labels. */
.aff-branch-archive__card-summary-label {
    display: none;
}

.aff-branch-archive__items[data-aff-view="grid"] .aff-branch-archive__card-summary-label--closed {
    display: inline;
}

.aff-branch-archive__items[data-aff-view="grid"] .aff-branch-archive__card-details[open] .aff-branch-archive__card-summary-label--closed {
    display: none;
}

.aff-branch-archive__items[data-aff-view="grid"] .aff-branch-archive__card-details[open] .aff-branch-archive__card-summary-label--open {
    display: inline;
}

/* Grid view ----------
 * Title + meta sit at the top of the card. The details element drops
 * into the flex flow as `display: contents` so its summary + body
 * become direct flex children of the card. Order pushes the summary
 * (chevron only) to the bottom. Body holds the contacts list which
 * the chevron toggles. */
.aff-branch-archive__items[data-aff-view="grid"] .aff-branch-archive__card-details {
    display: contents;
}

.aff-branch-archive__items[data-aff-view="grid"] .aff-branch-archive__card-summary {
    /* Sits directly under the meta line. Body expands BELOW it (flex
     * order=99) so the toggle stays put when contacts open. */
    order: 50;
    padding-block-start: 0.5rem;
    align-self: flex-start;
    color: var(--aff-muted-fg);
    background: transparent;
    border: 0;
    font-size: 0.8125rem;
    font-weight: 600;
    transition: color var(--aff-transition);
}

/* No contacts → no body to expand; hide the chevron in grid mode so the
 * card doesn't show a no-op affordance. List mode keeps the chevron
 * because it still reveals the meta line. */
.aff-branch-archive__items[data-aff-view="grid"] .aff-branch-archive__card-details[data-has-contacts="false"] .aff-branch-archive__card-summary {
    display: none;
}

.aff-branch-archive__items[data-aff-view="grid"] .aff-branch-archive__card-summary:hover,
.aff-branch-archive__items[data-aff-view="grid"] .aff-branch-archive__card-summary:focus-visible {
    color: var(--aff-fg);
}

.aff-branch-archive__items[data-aff-view="grid"] .aff-branch-archive__card-body {
    order: 99;
}

.aff-branch-archive__card-body {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.aff-branch-archive__card-meta {
    margin: 0;
    color: var(--aff-muted-fg);
    font-size: 0.875rem;
}

/* ----- contacts list ----- */

.aff-branch-archive__card-contacts-list {
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
}

.aff-branch-archive__card-contact-title {
    margin: 0.625rem 0 0.125rem;
    font-size: 0.75rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--aff-muted-fg);
}

.aff-branch-archive__card-contact-title:first-child {
    margin-top: 0;
}

.aff-branch-archive__card-contact-line {
    margin: 0;
    font-size: 0.875rem;
    line-height: 1.4;
    color: var(--aff-fg);
}

.aff-branch-archive__card-contact-line a {
    color: var(--aff-fg);
    text-decoration: none;
    transition: color var(--aff-transition);
}

.aff-branch-archive__card-contact-line a:hover,
.aff-branch-archive__card-contact-line a:focus-visible {
    color: var(--aff-primary);
    text-decoration: underline;
}

/* ----- empty + no-match ----- */

.aff-branch-archive__empty,
.aff-branch-archive__no-matches {
    margin: 0;
    color: var(--aff-muted-fg);
    text-align: center;
    padding-block: 2rem;
}

/* ---------------------------------------------------------------------- *
 * Magazine grid — home "Vårt Magasin" section.
 *
 * Light cream panel matching the home design. Eyebrow + heading + "Se
 * alla utgåvor →" sit on the same row at wide viewports. Three cover
 * cards below with issue label, title, and "Läs vidare" link.
 * ---------------------------------------------------------------------- */

.aff-magazine-grid__head {
    margin-block-end: 3rem;
}

.aff-magazine-grid__heading {
    font-family: var(--wp--preset--font-family--serif);
    font-size: clamp(2rem, 3.2vw, 2.75rem);
    font-weight: 700;
    line-height: 1.1;
    margin: 0;
    color: var(--aff-fg);
}

.aff-magazine-grid__all {
    margin: 0;
    font-weight: 500;
}

.aff-magazine-grid__all a {
    color: var(--aff-accent);
    text-decoration: none;
    transition: color var(--aff-transition);
}

.aff-magazine-grid__all a:hover,
.aff-magazine-grid__all a:focus-visible {
    color: var(--aff-orange-hover);
}

.aff-magazine-grid {
    display: block;
}

.aff-magazine-grid__items {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 2rem;
}

.aff-magazine-grid__card {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.aff-magazine-grid__cover {
    display: block;
    /* Magazine covers are portrait (Vårt Försvar trim is roughly 3:4).
     * The aspect-ratio holds card height even when the cover image
     * fails to load, so the row stays aligned. */
    aspect-ratio: 3 / 4;
    overflow: hidden;
    border-radius: var(--aff-radius-card);
    background: var(--aff-secondary);
    transition: transform var(--aff-transition);
}

.aff-magazine-grid__cover:hover,
.aff-magazine-grid__cover:focus-visible {
    transform: translateY(-2px);
}

.aff-magazine-grid__cover-img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.aff-magazine-grid__cover-fallback {
    display: block;
    width: 100%;
    height: 100%;
    background: var(--aff-secondary);
}

.aff-magazine-grid__label {
    margin: 0.5rem 0 0;
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--aff-muted-fg);
}

.aff-magazine-grid__title {
    font-family: var(--wp--preset--font-family--serif);
    font-size: 1.375rem;
    font-weight: 700;
    line-height: 1.25;
    margin: 0;
}

.aff-magazine-grid__title a {
    color: var(--aff-fg);
    text-decoration: none;
    transition: color var(--aff-transition);
}

.aff-magazine-grid__title a:hover,
.aff-magazine-grid__title a:focus-visible {
    color: var(--aff-primary);
}

.aff-magazine-grid__more {
    /* Push the link down so cards align even when titles wrap to two
     * lines on one card and one on another. */
    margin-block-start: auto;
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    color: var(--aff-accent);
    font-weight: 600;
    text-decoration: none;
    transition: color var(--aff-transition), gap var(--aff-transition);
}

.aff-magazine-grid__more:hover,
.aff-magazine-grid__more:focus-visible {
    color: var(--aff-orange-hover);
    gap: 0.5rem;
}

.aff-magazine-grid__empty {
    margin: 0;
    color: var(--aff-muted-fg);
}

@media (max-width: 1200px) {
    .aff-magazine-grid__items {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

@media (max-width: 900px) {
    .aff-magazine-grid__items {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .aff-magazine-grid__head {
        flex-direction: column;
        align-items: flex-start;
        gap: 1rem;
    }
}

@media (max-width: 600px) {
    .aff-magazine-grid__items {
        grid-template-columns: 1fr;
    }
}

/* ---------------------------------------------------------------------- *
 * Membership CTA — green panel with centered headline, two CTAs, three
 * stats split by a hairline divider. Branch count is queried server-side
 * (see patterns/membership-cta.php).
 * ---------------------------------------------------------------------- */

.aff-membership {
    text-align: center;
    /* Subtle vertical brand-green gradient — matches the mockup's slight
     * tonal shift without a second background colour. */
    background: linear-gradient(180deg, var(--aff-secondary, #5C7A5C) 0%, color-mix(in srgb, var(--aff-secondary, #5C7A5C) 90%, #000 10%) 100%);
}

.aff-membership__heading {
    font-family: var(--wp--preset--font-family--serif);
    font-size: clamp(2rem, 4vw, 2.75rem);
    font-weight: 700;
    line-height: 1.1;
    margin: 0 0 1rem;
    color: #fff;
}

.aff-membership__lede {
    font-size: 1rem;
    line-height: 1.6;
    max-width: 560px;
    margin: 0 auto 2rem;
    color: rgba(255, 255, 255, 0.85);
}

.aff-membership__buttons {
    margin-block: 0 3rem;
    gap: 1rem;
}

.aff-membership__cta-primary .wp-block-button__link {
    /* Solid orange already comes from has-accent-background-color. Padding
     * mirrors site-wide button atom; defined locally so the pattern reads
     * straight without depending on a shared `.is-style-fill` token. */
    padding-inline: 1.5rem;
    padding-block: 0.75rem;
    font-weight: 600;
    border-radius: var(--aff-radius-md);
}

.aff-membership__cta-primary .wp-block-button__link:hover,
.aff-membership__cta-primary .wp-block-button__link:focus-visible {
    background-color: var(--aff-orange-hover) !important;
}

.aff-membership__cta-secondary .wp-block-button__link {
    background: transparent;
    color: #fff;
    border: 1px solid rgba(255, 255, 255, 0.5);
    padding-inline: 1.5rem;
    padding-block: 0.75rem;
    font-weight: 600;
    border-radius: var(--aff-radius-md);
    transition: background-color var(--aff-transition), border-color var(--aff-transition);
}

.aff-membership__cta-secondary .wp-block-button__link:hover,
.aff-membership__cta-secondary .wp-block-button__link:focus-visible {
    background: rgba(255, 255, 255, 0.1);
    border-color: #fff;
}

.aff-membership__divider {
    border: 0;
    border-block-start: 1px solid rgba(255, 255, 255, 0.25);
    max-width: 880px;
    margin: 0 auto 2.5rem;
}

.aff-membership__stats {
    list-style: none;
    margin: 0 auto;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 2rem;
    max-width: 720px;
}

.aff-membership__stat {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
}

.aff-membership__stat-value {
    font-family: var(--wp--preset--font-family--serif);
    font-size: clamp(1.75rem, 3vw, 2.25rem);
    font-weight: 700;
    color: #fff;
    line-height: 1;
}

.aff-membership__stat-label {
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.7);
}

@media (max-width: 600px) {
    .aff-membership__stats {
        grid-template-columns: 1fr;
        gap: 1.5rem;
    }
}

/* ---------------------------------------------------------------------- *
 * Membership widget — sidebar CTA next to long-form page content.
 *
 * Lives inside an aff/page-with-sidebar pattern (or any 2-col layout).
 * Sticks to the top while scrolling on desktop, drops below content on
 * narrow viewports. Brand-green panel mirrors the home Bli medlem
 * section.
 * ---------------------------------------------------------------------- */

.aff-membership-widget {
    background: var(--aff-secondary);
    color: var(--aff-secondary-fg);
    border-radius: var(--aff-radius-card);
    padding: 1.75rem;
    box-shadow: var(--aff-shadow-card);
    /* Sticky vertical offset gives the header a little air; matches the
     * 24px block-gap WP injects between top-level blocks. */
    position: sticky;
    top: 1.5rem;
    /* Constrain max-width so the widget doesn't sprawl on wide layouts
     * even when the parent column is wider. */
    max-width: 320px;
    margin-inline-start: auto;
}

.aff-membership-widget h2,
.aff-membership-widget h3 {
    color: #fff;
    font-family: var(--wp--preset--font-family--serif);
    font-size: 1.5rem;
    line-height: 1.2;
}

.aff-membership-widget p {
    color: rgba(255, 255, 255, 0.9);
    line-height: 1.5;
}

.aff-membership-widget ul,
.aff-membership-widget ol {
    padding-inline-start: 1.25rem;
    color: rgba(255, 255, 255, 0.9);
}

.aff-membership-widget li {
    margin-block: 0.25rem;
}

/* WP's layout CSS applies block-gap via margin-block-start on direct
 * children of `.is-layout-flow`. The inner blocks wrap in a flow layout
 * automatically; override the gap via the local --wp--style--block-gap
 * set on the wrapper (see render.php / edit.tsx). */
.aff-membership-widget > * {
    margin-block-start: var(--wp--style--block-gap, 1.5rem);
}

.aff-membership-widget > :first-child {
    margin-block-start: 0;
}

.aff-membership-widget__buttons {
    /* Stack buttons vertically inside the narrow column. Override the
     * core/buttons default flex-row so each button takes a full row. */
    flex-direction: column;
    align-items: stretch;
    gap: 0.5rem;
}

.aff-membership-widget__buttons .wp-block-button {
    width: 100%;
}

.aff-membership-widget__buttons .wp-block-button__link {
    display: block;
    width: 100%;
    text-align: center;
    font-weight: 600;
    border-radius: var(--aff-radius-md);
}

.aff-membership-widget__cta-secondary .wp-block-button__link {
    background: transparent;
    color: #fff;
    border: 1px solid rgba(255, 255, 255, 0.5);
    transition: background-color var(--aff-transition), border-color var(--aff-transition);
}

.aff-membership-widget__cta-secondary .wp-block-button__link:hover,
.aff-membership-widget__cta-secondary .wp-block-button__link:focus-visible {
    background: rgba(255, 255, 255, 0.1);
    border-color: #fff;
}

@media (max-width: 900px) {
    .aff-membership-widget {
        position: static;
        max-width: none;
        margin-inline-start: 0;
    }
}

/* ---------------------------------------------------------------------- *
 * aff/page-with-sidebar — 2-col layout that hosts the widget. core/columns
 * already gives us the layout; rules here just polish the behaviour at
 * the breakpoint join. The aside column carries `aff-membership-widget`
 * so its sticky behaviour anchors against the column, not the page root.
 * ---------------------------------------------------------------------- */

.aff-page-with-sidebar__aside {
    /* The widget itself is position:sticky; the column it lives in
     * needs align-self stretch so the sticky bounds make sense. */
    align-self: stretch;
}

@media (max-width: 900px) {
    /* Core columns already stacks at this width via its own breakpoint
     * but the aside needs the same horizontal margin reset the widget
     * gets, otherwise it inherits the asymmetric desktop offset. */
    .aff-page-with-sidebar__aside {
        align-self: auto;
    }
}

/* ---------------------------------------------------------------------- *
 * Contact form honeypot — invisible to humans, fillable by dumb bots.
 * ---------------------------------------------------------------------- */

.aff-contact-form__honeypot {
    position: absolute;
    left: -9999px;
    top: auto;
    width: 1px;
    height: 1px;
    overflow: hidden;
}


/* ---------------------------------------------------------------------- *
 * Language switcher (compact dropdown — SV ⌄ / EN ⌄)
 * Translation runs through Google but its widget UI is hidden; cookie +
 * reload drive the swap.
 * ---------------------------------------------------------------------- */

.aff-language-switcher {
    position: relative;
    display: inline-flex;
    align-items: center;
}

.aff-language-switcher__trigger {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.25rem 0.5rem;
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--aff-fg);
    background: transparent;
    border: 0;
    cursor: pointer;
    border-radius: var(--aff-radius-sm);
    transition: color var(--aff-transition);
}

.aff-language-switcher__trigger:hover {
    color: var(--aff-primary);
}

.aff-language-switcher__trigger:focus-visible {
    outline: none;
    box-shadow: var(--aff-focus-ring);
}

.aff-language-switcher__trigger[aria-busy="true"] {
    opacity: 0.6;
    cursor: progress;
}

.aff-language-switcher__current {
    font-weight: 600;
    letter-spacing: 0.025em;
}

.aff-language-switcher__caret {
    width: 0.75rem;
    height: 0.75rem;
    transition: transform var(--aff-transition);
}

.aff-language-switcher__trigger[aria-expanded="true"] .aff-language-switcher__caret {
    transform: rotate(180deg);
}

.aff-language-switcher__menu {
    position: absolute;
    right: 0;
    top: 100%;
    margin-top: 0.25rem;
    z-index: 50;
    min-width: 10rem;
    border-radius: var(--aff-radius-md);
    border: 1px solid var(--aff-border);
    background: var(--aff-card);
    box-shadow: var(--aff-shadow-card);
    list-style: none;
    padding: 0.25rem;
}

.aff-language-switcher__option {
    display: flex;
    width: 100%;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.75rem;
    font-size: 0.875rem;
    color: var(--aff-fg);
    background: transparent;
    border: 0;
    cursor: pointer;
    border-radius: var(--aff-radius-sm);
    text-align: left;
    transition: background var(--aff-transition);
}

.aff-language-switcher__option:hover,
.aff-language-switcher__option:focus-visible {
    outline: none;
    background: var(--aff-muted);
}

.aff-language-switcher__option[aria-checked="true"] {
    font-weight: 600;
    color: var(--aff-primary);
}

.aff-language-switcher__code {
    font-weight: 600;
    letter-spacing: 0.025em;
    width: 1.5rem;
}

.aff-language-switcher__widget {
    /* Google Translate mounts here; never visible to the user. */
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

.aff-language-switcher__error {
    position: absolute;
    right: 0;
    top: 100%;
    margin-top: 0.25rem;
    font-size: 0.75rem;
    color: var(--aff-destructive);
    white-space: nowrap;
}

/* Floating bottom-center toast — anchored to the viewport rather than
 * the switcher trigger so it's visible regardless of where the trigger
 * sits in the header (desktop right, mobile burger overlay). Clamped to
 * `min(...)` width so it never exceeds the viewport on narrow phones.
 *
 * The `[hidden]` opt-out is explicit because our class-level
 * `display: flex` overrides the UA `[hidden] { display: none }`
 * declaration (class selector beats attribute selector specificity).
 */
.aff-language-switcher__disclaimer {
    position: fixed;
    left: 50%;
    bottom: 1.5rem;
    transform: translateX(-50%);
    z-index: 9000;
    width: min(28rem, calc(100vw - 2rem));
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.875rem 1rem;
    border-radius: var(--aff-radius-md);
    border: 1px solid var(--aff-border);
    background: var(--aff-card);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
    font-size: 0.875rem;
    color: var(--aff-fg);
}

.aff-language-switcher__disclaimer[hidden] {
    display: none;
}

.aff-language-switcher__disclaimer-text {
    margin: 0;
    flex: 1 1 auto;
    font-style: italic;
    font-size: 0.8125rem;
    line-height: 1.4;
    color: var(--aff-muted-fg);
}

.aff-language-switcher__disclaimer-dismiss {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.25rem 0.75rem;
    border-radius: var(--aff-radius-sm);
    background: var(--aff-primary);
    color: var(--aff-primary-fg);
    font-size: 0.75rem;
    font-weight: 600;
    border: 0;
    cursor: pointer;
    transition: background var(--aff-transition);
}

.aff-language-switcher__disclaimer-dismiss:hover {
    background: var(--aff-blue-deep);
}

.aff-language-switcher__disclaimer-dismiss:focus-visible {
    outline: none;
    box-shadow: var(--aff-focus-ring);
}


/* ---------------------------------------------------------------------- *
 * Search hero — tighter than the default 6rem aff-section. The hero is
 * just an eyebrow + h1, no rationale for the full archive band.
 * ---------------------------------------------------------------------- */

/* Hero keeps the global 6rem aff-section rhythm on desktop — tighten
 * on narrow viewports so the h1 doesn't push the result list below the
 * fold on phones. */
@media (max-width: 720px) {
    .aff-section.aff-search-hero {
        padding-block: 2.5rem;
    }
}

.aff-search-hero h1 {
    font-family: var(--wp--preset--font-family--serif);
    font-size: clamp(1.5rem, 1.25rem + 1.5vw, 2.5rem);
    font-weight: 700;
    line-height: 1.15;
    margin: 0;
    color: var(--aff-fg);
}

.aff-section.aff-search-section {
    padding-block: 1.5rem 4rem;
}

.aff-search-section .aff-search-results {
    padding-block: 0;
}

/* ---------------------------------------------------------------------- *
 * Search results
 *
 * Hosts the surface beneath the search hero: form, type-filter chips,
 * result cards, pagination, "Hittade du inte..." CTA. Reuses tokens
 * + the .aff-btn primitive — no bespoke colour values.
 * ---------------------------------------------------------------------- */

.aff-search-results {
    max-width: var(--wp--style--global--content-size);
    margin-inline: auto;
    padding-block: 2rem 4rem;
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
}

/* Search form — full-width pill input with inline submit, mirrors the
 * 404 / branch-archive search affordance. */
.aff-search-results__form {
    margin: 0;
}

.aff-search-results__field {
    position: relative;
    display: flex;
    align-items: center;
    width: 100%;
    max-width: 36rem;
}

.aff-search-results__field .aff-field {
    width: 100%;
    padding-inline-end: 3rem;
}

.aff-search-results__submit {
    position: absolute;
    inset-inline-end: 0.25rem;
    inset-block: 0.25rem;
    aspect-ratio: 1 / 1;
    height: auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--aff-primary);
    color: var(--aff-primary-fg);
    border: 0;
    border-radius: var(--aff-radius-sm);
    cursor: pointer;
    transition: background-color var(--aff-transition);
}

.aff-search-results__submit:hover,
.aff-search-results__submit:focus-visible {
    background: var(--aff-blue-deep);
}

.aff-search-results__submit:focus-visible {
    outline: none;
    box-shadow: var(--aff-focus-ring);
}

/* Filter chips — horizontal scroll on narrow viewports, wrap on wide.
 * Active chip flips to the primary surface. */
.aff-search-results__chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.aff-search-results__chip {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.4rem 0.85rem;
    border: 1px solid var(--aff-border);
    border-radius: var(--aff-radius-pill);
    background: var(--aff-card);
    color: var(--aff-fg);
    font-size: 0.875rem;
    font-weight: 500;
    text-decoration: none;
    transition:
        background-color var(--aff-transition),
        border-color var(--aff-transition),
        color var(--aff-transition);
}

.aff-search-results__chip:hover {
    border-color: var(--aff-primary);
    color: var(--aff-primary);
}

.aff-search-results__chip.is-active {
    background: var(--aff-primary);
    border-color: var(--aff-primary);
    color: var(--aff-primary-fg);
}

.aff-search-results__chip-count {
    color: inherit;
    opacity: 0.7;
    font-weight: 400;
}

.aff-search-results__chip.is-active .aff-search-results__chip-count {
    opacity: 0.85;
}

/* Result list — flat ul; cards sit on their own surface. */
.aff-search-results__items {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.aff-search-results__item {
    margin: 0;
}

.aff-search-results__card {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1rem;
    padding: 1.25rem;
    background: var(--aff-card);
    border: 1px solid var(--aff-border);
    border-radius: var(--aff-radius-card);
    box-shadow: var(--aff-shadow-card);
    transition: box-shadow var(--aff-transition), transform var(--aff-transition);
}

.aff-search-results__card:hover {
    box-shadow: var(--aff-shadow-hover);
}

/* Card has a thumb? Use a 2-column layout with thumb on the right. */
.aff-search-results__card:has(.aff-search-results__thumb-link) {
    grid-template-columns: 1fr auto;
}

.aff-search-results__body {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    min-width: 0;
}

.aff-search-results__badges {
    margin: 0;
}

.aff-search-results__badge {
    display: inline-flex;
    align-items: center;
    padding: 0.15rem 0.5rem;
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    border-radius: var(--aff-radius-sm);
    background: rgba(41, 61, 130, 0.08);
    color: var(--aff-primary);
}

.aff-search-results__badge--aff-event {
    background: rgba(34, 137, 92, 0.12);
    color: #1a7d4b;
}

.aff-search-results__badge--aff-branch {
    background: rgba(41, 61, 130, 0.1);
    color: var(--aff-primary);
}

.aff-search-results__badge--aff-magazine {
    background: rgba(230, 126, 34, 0.12);
    color: var(--aff-accent);
}

.aff-search-results__title {
    margin: 0;
    font-family: var(--wp--preset--font-family--serif);
    font-size: clamp(1.1rem, 0.9rem + 0.6vw, 1.35rem);
    font-weight: 700;
    line-height: 1.25;
    color: var(--aff-fg);
}

.aff-search-results__title a {
    color: inherit;
    text-decoration: none;
}

.aff-search-results__title a:hover {
    color: var(--aff-primary);
    text-decoration: underline;
    text-underline-offset: 3px;
}

.aff-search-results__excerpt {
    margin: 0;
    color: var(--aff-muted-fg);
    font-size: 0.95rem;
    line-height: 1.55;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.aff-search-results__meta {
    margin: 0.25rem 0 0;
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
    color: var(--aff-muted-fg);
    font-size: 0.8rem;
}

.aff-search-results__meta-item {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
}

.aff-search-results__thumb-link {
    display: block;
    border-radius: var(--aff-radius-md);
    overflow: hidden;
    align-self: start;
    line-height: 0;
}

.aff-search-results__thumb {
    width: 96px;
    height: 96px;
    object-fit: cover;
    display: block;
}

@media (min-width: 720px) {
    .aff-search-results__thumb {
        width: 120px;
        height: 96px;
    }
}

.aff-search-results__empty {
    margin: 2rem 0;
    padding: 2rem;
    background: var(--aff-card);
    border: 1px dashed var(--aff-border);
    border-radius: var(--aff-radius-card);
    text-align: center;
    color: var(--aff-muted-fg);
}

/* Pagination — sober numbered links, current sits on the primary surface. */
.aff-search-results__pagination {
    margin-top: 0.5rem;
}

.aff-search-results__pagination-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    justify-content: center;
}

.aff-search-results__pagination-item .page-numbers {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 2.25rem;
    height: 2.25rem;
    padding: 0 0.5rem;
    border: 1px solid var(--aff-border);
    border-radius: var(--aff-radius-sm);
    background: var(--aff-card);
    color: var(--aff-fg);
    text-decoration: none;
    font-size: 0.9rem;
    transition: background-color var(--aff-transition), color var(--aff-transition);
}

.aff-search-results__pagination-item .page-numbers:hover {
    background: var(--aff-muted);
}

.aff-search-results__pagination-item .page-numbers.current {
    background: var(--aff-primary);
    color: var(--aff-primary-fg);
    border-color: var(--aff-primary);
}

.aff-search-results__pagination-item .page-numbers.dots {
    border-color: transparent;
    background: transparent;
}

/* "Hittade du inte..." CTA — sits on the muted band, single primary button. */
.aff-search-results__cta {
    margin-top: 2rem;
    padding: 2.5rem 1.5rem;
    background: var(--aff-bg);
    border-top: 1px solid var(--aff-border);
    text-align: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.75rem;
}

.aff-search-results__cta-title {
    margin: 0;
    font-family: var(--wp--preset--font-family--serif);
    font-size: clamp(1.25rem, 1rem + 1vw, 1.75rem);
    font-weight: 700;
    color: var(--aff-fg);
}

.aff-search-results__cta-lead {
    margin: 0;
    max-width: 36rem;
    color: var(--aff-muted-fg);
    line-height: 1.55;
}

.aff-search-results__cta-actions {
    margin: 0.5rem 0 0;
}

/* ---------------------------------------------------------------------- *
 * News archive
 *
 * Reuses .aff-project-card surface + .aff-project-grid columns from
 * _project-grid.css. Adds a post-date overline and the pagination shell
 * that core/query-pagination emits.
 * ---------------------------------------------------------------------- */

.aff-news-archive .aff-project-card__date {
    margin: 0;
    color: var(--aff-muted-fg);
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.aff-news-archive__empty {
    padding: 2rem;
    text-align: center;
    color: var(--aff-muted-fg);
    background: var(--aff-card);
    border: 1px dashed var(--aff-border);
    border-radius: var(--aff-radius-card);
}

/* core/query-pagination renders as .wp-block-query-pagination with three
 * inner links (previous / numbers / next). Mirror the search-results
 * pagination affordance so the two archives feel consistent. */
.aff-news-archive .wp-block-query-pagination {
    margin-top: 2.5rem;
    gap: 0.25rem;
}

.aff-news-archive .wp-block-query-pagination .page-numbers,
.aff-news-archive .wp-block-query-pagination-previous,
.aff-news-archive .wp-block-query-pagination-next {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 2.25rem;
    height: 2.25rem;
    padding: 0 0.75rem;
    border: 1px solid var(--aff-border);
    border-radius: var(--aff-radius-sm);
    background: var(--aff-card);
    color: var(--aff-fg);
    text-decoration: none;
    font-size: 0.9rem;
    transition: background-color var(--aff-transition), color var(--aff-transition);
}

.aff-news-archive .wp-block-query-pagination .page-numbers:hover,
.aff-news-archive .wp-block-query-pagination-previous:hover,
.aff-news-archive .wp-block-query-pagination-next:hover {
    background: var(--aff-muted);
}

.aff-news-archive .wp-block-query-pagination .page-numbers.current {
    background: var(--aff-primary);
    color: var(--aff-primary-fg);
    border-color: var(--aff-primary);
}

.aff-news-archive .wp-block-query-pagination .page-numbers.dots {
    border-color: transparent;
    background: transparent;
}

/* ---------------------------------------------------------------------- *
 * News single
 *
 * Hero is shared aff/hero (split + useFeaturedImage). Body band sits on
 * a white card surface with a 2-col layout: prose + sticky sidebar
 * (membership widget by default, editable in the Site Editor).
 * ---------------------------------------------------------------------- */

.aff-news-single {
    margin-block: 0;
}

.aff-news-single__cols {
    gap: 3rem;
}

@media (min-width: 900px) {
    .aff-news-single__cols {
        gap: 4rem;
    }
}

.aff-news-single__main {
    min-width: 0;
}

.aff-news-single__aside {
    min-width: 0;
}

@media (min-width: 900px) {
    .aff-news-single__aside {
        position: sticky;
        top: 6rem;
        align-self: flex-start;
    }
}

.aff-news-single__prose {
    font-size: 1.0625rem;
    line-height: 1.7;
    color: var(--aff-fg);
}

.aff-news-single__prose > * + * {
    margin-top: 1.25rem;
}

.aff-news-single__prose h2,
.aff-news-single__prose h3 {
    font-family: var(--wp--preset--font-family--serif);
    line-height: 1.25;
    margin-top: 2.25rem;
}

.aff-news-single__prose h2 {
    font-size: 1.5rem;
}

.aff-news-single__prose h3 {
    font-size: 1.25rem;
}

.aff-news-single__prose a {
    color: var(--aff-accent);
    text-underline-offset: 3px;
}

.aff-news-single__prose blockquote {
    margin: 1.5rem 0;
    padding: 0.5rem 1.25rem;
    border-inline-start: 3px solid var(--aff-primary);
    color: var(--aff-muted-fg);
    font-style: italic;
}

/* ---------------------------------------------------------------------- *
 * Magazine archive
 *
 * Two stacked full-width sections beneath the hero, per ADR-019:
 *
 *   1. .aff-magazine-archive (bg=card)  — "Senaste numren". Two columns:
 *        main (66%): year-grouped active issues
 *        aside (33%): aff/membership-widget, sticky on wide viewports
 *
 *   2. .aff-magazine-arkiv (bg=muted) — year-grouped årgångar äldre än
 *        2 år, full-width on a contrasting surface. Cards capped at
 *        ~240px so the deep back-catalogue reads denser than Senaste.
 *
 * Both grids render via aff/magazine-cards with groupByYear:true — one
 * <section> per årgång, year heading divider per section.
 * ---------------------------------------------------------------------- */

.aff-magazine-archive {
    margin-block: 0;
}

.aff-magazine-archive__cols {
    gap: 3rem;
}

@media (min-width: 900px) {
    .aff-magazine-archive__cols {
        gap: 4rem;
    }
}

.aff-magazine-archive__main {
    min-width: 0;
}

.aff-magazine-archive__aside {
    min-width: 0;
}

@media (min-width: 900px) {
    .aff-magazine-archive__aside {
        position: sticky;
        top: 6rem;
        align-self: flex-start;
    }
}

.aff-magazine-archive__heading,
.aff-magazine-archive__rest-heading {
    margin: 0 0 1.5rem;
    font-family: var(--wp--preset--font-family--serif);
    font-size: clamp(1.25rem, 1rem + 0.5vw, 1.5rem);
    line-height: 1.2;
}

/* Year-grouped grid shared between Senaste (card surface) and Arkiv
 * (muted surface). Each year is its own row (`<section>` with year
 * heading + 4-card ul), shrinking on narrow viewports. */
.aff-magazine-archive__rest .aff-magazine-grid__year + .aff-magazine-grid__year,
.aff-magazine-arkiv__grid .aff-magazine-grid__year + .aff-magazine-grid__year {
    margin-top: 2.5rem;
}

.aff-magazine-archive__rest .aff-magazine-grid__year-heading,
.aff-magazine-arkiv__grid .aff-magazine-grid__year-heading {
    font-family: var(--wp--preset--font-family--serif);
    font-size: 1.125rem;
    font-weight: 700;
    margin: 0 0 1rem;
    padding-bottom: 0.5rem;
    border-bottom: 1px solid var(--aff-border);
    color: var(--aff-fg);
    letter-spacing: 0.02em;
}

.aff-magazine-archive__rest .aff-magazine-grid__items {
    grid-template-columns: repeat(4, minmax(0, 1fr));
}

@media (max-width: 1100px) {
    .aff-magazine-archive__rest .aff-magazine-grid__items {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

@media (max-width: 700px) {
    .aff-magazine-archive__rest .aff-magazine-grid__items {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* Arkiv — plain second section on muted bg. */
.aff-magazine-arkiv {
    margin-block: 0;
}

.aff-magazine-arkiv__heading {
    margin: 0 0 0.5rem;
    font-family: var(--wp--preset--font-family--serif);
    font-size: clamp(1.5rem, 1.2rem + 0.8vw, 2rem);
    line-height: 1.2;
    color: var(--aff-fg);
}

.aff-magazine-arkiv__lead {
    margin: 0 0 2rem;
    color: var(--aff-muted-fg);
    font-size: 0.9375rem;
}

/* Arkiv grid — denser than Senaste. Track floor at 140px so columns
 * shrink before reflowing; `1fr` upper bound lets tracks grow to share
 * leftover space, then the per-card max-width caps each card at 240px
 * so wide rows don't stretch covers oversized. */
.aff-magazine-arkiv__grid .aff-magazine-grid__items {
    grid-template-columns: repeat(auto-fill, minmax(min(140px, 100%), 1fr));
    justify-content: start;
}

.aff-magazine-arkiv__grid .aff-magazine-grid__card {
    max-width: 240px;
    width: 100%;
}

.aff-magazine-arkiv__grid .aff-magazine-grid__title {
    font-size: 1.25rem;
}

/* ---------------------------------------------------------------------- *
 * Alert — severity-aware notice block
 *
 * Layout: thick left accent rail, circular icon chip, body column.
 * Severity drives the accent colour + chip colour + role. Body lives
 * in inner blocks so editors compose freely.
 * ---------------------------------------------------------------------- */

.aff-alert {
    /* Per-severity tint slots — overridden by modifier classes below. */
    --aff-alert-accent: var(--aff-primary);
    --aff-alert-surface: rgba(41, 61, 130, 0.04);

    position: relative;
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 0.875rem;
    padding: 1rem 1.25rem 1rem 1.5rem;
    margin-block: 1.5rem;
    background: var(--aff-alert-surface);
    border-radius: var(--aff-radius-card);
    border: 1px solid color-mix(in srgb, var(--aff-alert-accent) 18%, transparent);
    border-left: 4px solid var(--aff-alert-accent);
    color: var(--aff-fg);
}

.aff-alert--info {
    --aff-alert-accent: var(--aff-primary);
    --aff-alert-surface: rgba(41, 61, 130, 0.04);
}

.aff-alert--success {
    --aff-alert-accent: #1a7d4b;
    --aff-alert-surface: rgba(26, 125, 75, 0.06);
}

.aff-alert--warning {
    --aff-alert-accent: #b87012;
    --aff-alert-surface: rgba(184, 112, 18, 0.07);
}

.aff-alert--danger {
    --aff-alert-accent: var(--aff-destructive);
    --aff-alert-surface: rgba(220, 38, 38, 0.06);
}

.aff-alert__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    flex: 0 0 1.75rem;
    border-radius: 999px;
    background: var(--aff-alert-accent);
    color: #ffffff;
    margin-top: 0.1rem;
}

.aff-alert__icon svg {
    width: 0.9rem;
    height: 0.9rem;
}

.aff-alert__body {
    min-width: 0;
}

.aff-alert__body > * {
    margin: 0;
}

.aff-alert__body > * + * {
    margin-top: 0.4rem;
}

.aff-alert__title {
    font-family: var(--wp--preset--font-family--serif);
    font-weight: 700;
    font-size: 1rem;
    color: var(--aff-fg);
}

.aff-alert__body p {
    line-height: 1.55;
    color: var(--aff-muted-fg);
}

/* Editor-canvas parity — the canvas renders edit.tsx's JSX (no PHP icon
 * mapping), so paint the chip from CSS using the severity modifier. The
 * frontend gets the SVG via render.php; this rule only kicks in when the
 * span has no children (editor mode). */
.editor-styles-wrapper .aff-alert__icon:empty::before {
    content: "i";
    font-family: var(--wp--preset--font-family--serif);
    font-weight: 700;
    font-size: 0.85rem;
}

/* ---------------------------------------------------------------------- *
 * Form-status alert — page-top banner variant
 *
 * Lives at the top of every page via the `aff/form-status-alert` block in
 * the header part. Reads as a slim banner rather than a card: no rounded
 * corners, no block margin, smaller chip + type, title + body on one row
 * (wraps to two on narrow viewports).
 * ---------------------------------------------------------------------- */
.aff-form-status-alert .aff-alert {
    margin-block: 0;
    border-radius: 0;
    padding: 0.625rem 1rem 0.625rem 1.125rem;
    gap: 0.625rem;
}

.aff-form-status-alert .aff-alert__icon {
    width: 1.375rem;
    height: 1.375rem;
    flex: 0 0 1.375rem;
    margin-top: 0;
}

.aff-form-status-alert .aff-alert__icon svg {
    width: 0.75rem;
    height: 0.75rem;
}

.aff-form-status-alert .aff-alert__body {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.375rem 0.625rem;
}

/* Override the default `* + * { margin-top }` rule on the body so the
 * inline layout stays on one row instead of stacking. */
.aff-form-status-alert .aff-alert__body > * + * {
    margin-top: 0;
}

.aff-form-status-alert .aff-alert__title {
    font-size: 0.9375rem;
}

.aff-form-status-alert .aff-alert__body p {
    font-size: 0.9375rem;
    line-height: 1.45;
}

/* ---------------------------------------------------------------------- *
 * Image byline — photo credit rendered below the WP caption.
 *
 * Two markup shapes (see ADR-020 + BylineRenderer.php):
 *
 *   figcaption.aff-byline          — sole byline when no WP caption present
 *   span.aff-byline                — byline appended after WP's figcaption
 *
 * Hero split variant renders the byline as:
 *   p.aff-byline                   — inside .aff-hero__bylines, under media
 * ---------------------------------------------------------------------- */

.aff-byline {
    display: block;
    font-size: 0.875rem;
    font-style: italic;
    color: var(--aff-muted-fg);
    margin-top: 0.25rem;
    line-height: 1.4;
    text-align: left;
}

/* Generic `display: block` above overrides the native `hidden` attribute.
 * Re-assert it so per-slide bylines stay hidden when view.ts toggles them. */
.aff-byline[hidden] {
    display: none;
}

/*
 * AFF theme CSS. Plain CSS, loaded on both frontend and editor via
 * add_editor_style() so Site Editor / post editor render matches the
 * frontend.
 *
 * Tokens live in `theme.json`. The `--wp--preset--*` variables are
 * emitted by core; we mirror the most-referenced ones onto shorter
 * names below to keep the rest of this file readable.
 *
 * Per-section rules are split into `src/styles/_<section>.css` and
 * inlined here via `@import`. CSS spec requires @import rules to come
 * before any other rule, so the imports sit at the top, with tokens,
 * fonts, base, and Google Translate suppressions following.
 *
 * Webpack's css-loader resolves `@import` paths and inlines content;
 * `url()` references inside an imported file are resolved relative to
 * the importing file (this one). Keep `url()` references either in
 * this file (e.g. @font-face below) or use paths relative to /src/.
 */

/* Self-hosted webfonts. URLs resolve from build/app.css to ../assets/fonts/.
 * No third-party CDN — keeps visitor IP off Google.
 *
 * Variable fonts (`wght 400..700`, plus `opsz` axis on Source Serif 4) —
 * static-bold woff2 files render as `SourceSerif4-Bold` (thicker, no
 * optical-size adjustment); the variable woff2 reports
 * `SourceSerif4Roman-Regular_wght...opsz...` and renders the design's
 * intended display weight. Two subset files per family: `latin` covers
 * basic Latin, `latin-ext` covers extended (åäö included via Latin-1
 * Supplement which the latin file already carries). */
@font-face {
    font-family: "Inter";
    src: url(fonts/inter-v20-latin.404ca8da.woff2) format("woff2");
    font-weight: 400 700;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: "Inter";
    src: url(fonts/inter-v20-latin-ext.9c8c91dc.woff2) format("woff2");
    font-weight: 400 700;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
    font-family: "Source Serif 4";
    src: url(fonts/source-serif-4-v14-latin.94ae19c9.woff2) format("woff2");
    font-weight: 400 700;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: "Source Serif 4";
    src: url(fonts/source-serif-4-v14-latin-ext.cef29ad3.woff2) format("woff2");
    font-weight: 400 700;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
    --aff-bg:            var(--wp--preset--color--background);
    --aff-fg:            var(--wp--preset--color--foreground);
    --aff-card:          var(--wp--preset--color--card);
    --aff-primary:       var(--wp--preset--color--primary);
    --aff-primary-fg:    var(--wp--preset--color--primary-foreground);
    --aff-secondary:     var(--wp--preset--color--secondary);
    --aff-secondary-fg:  var(--wp--preset--color--secondary-foreground);
    --aff-accent:        var(--wp--preset--color--accent);
    --aff-accent-fg:     var(--wp--preset--color--accent-foreground);
    --aff-muted:         var(--wp--preset--color--muted);
    --aff-muted-fg:      var(--wp--preset--color--muted-foreground);
    --aff-border:        var(--wp--preset--color--border);
    --aff-destructive:   var(--wp--preset--color--destructive);
    --aff-ring:          var(--wp--preset--color--primary);
    --aff-orange-hover:  var(--wp--preset--color--brand-orange-hover);
    --aff-blue-deep:     var(--wp--preset--color--brand-blue-deep);

    /* Non-token locals — no theme.json equivalent. Keep these inline
     * until enough designs share a value to justify promoting them. */
    --aff-radius-sm: 4px;
    --aff-radius-md: 6px;
    --aff-radius-card: 8px;
    --aff-radius-lg: 10px;
    --aff-radius-pill: 999px;

    --aff-shadow-card: 0 2px 8px rgba(41, 61, 130, 0.08);
    --aff-shadow-hover: 0 6px 16px rgba(41, 61, 130, 0.12);

    --aff-transition: 200ms ease;
    --aff-transition-fast: 180ms ease;
    --aff-focus-ring: 0 0 0 2px var(--aff-ring);
}

/* Footer-only tokens. Scoped to .aff-footer so they don't pollute the
 * global namespace (and don't apply when a future surface uses
 * --aff-* without expecting inverse colours). */
.aff-footer {
    --aff-footer-text: rgba(255, 255, 255, 0.7);
    --aff-footer-text-strong: #ffffff;
    --aff-footer-text-muted: rgba(255, 255, 255, 0.5);
    --aff-footer-text-faint: rgba(255, 255, 255, 0.85);
    --aff-footer-input-bg: rgba(255, 255, 255, 0.05);
    --aff-footer-input-border: rgba(255, 255, 255, 0.12);
    --aff-footer-icon-bg: rgba(255, 255, 255, 0.08);
    --aff-footer-divider: rgba(255, 255, 255, 0.1);
}

/* Universal border-box. Modern reset — Paul Irish "* { box-sizing }"
 * pattern. `inherit` on `*::before/::after` lets a component locally
 * opt out by setting box-sizing on its root. Anchored to `html` so
 * the rule itself isn't subject to inheritance. */
html {
    box-sizing: border-box;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

*,
*::before,
*::after {
    box-sizing: inherit;
}

/* Defensive: alignfull math is occasionally off by a hair on the editor
 * canvas; never let horizontal scroll appear. Use `overflow-clip` rather
 * than `overflow-x: hidden` so the wrapper doesn't become a scroll
 * container — the latter establishes a containing block for `position:
 * sticky` and silently breaks sticky widgets (membership CTA, future
 * sticky header). */
.wp-site-blocks {
    overflow-x: clip;
}

/* Drop default block-margin so the header sits flush against main. */
body > main,
.wp-site-blocks > main {
    margin-block-start: 0;
}

/* ---------------------------------------------------------------------- *
 * Section — single source of vertical rhythm. Patterns add `aff-section`
 * to their outer alignfull group; padding-block lives here, not in
 * per-pattern markup.
 * ---------------------------------------------------------------------- */

.aff-section {
    padding-block: 6rem;
}

/* Header + footer inner content sit on a flex layout, which WP's constrained
 * layout doesn't auto-cap. Match the global content width so they align with
 * other section content at wide viewports. */
.aff-header > .wp-block-group,
.aff-footer > .wp-block-columns,
.aff-footer > .wp-block-separator,
.aff-footer > .aff-footer__legal {
    max-width: var(--wp--style--global--content-size);
    margin-inline: auto;
    width: 100%;
}

/* ---------------------------------------------------------------------- *
 * Eyebrow / "section-label" — small kicker above section heading
 * ---------------------------------------------------------------------- */

.aff-eyebrow {
    display: block;
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--aff-primary);
    margin: 0 0 0.5rem 0;
}

.aff-eyebrow::before {
    content: "";
    display: inline-block;
    width: 0.375rem;
    height: 0.375rem;
    border-radius: 50%;
    background-color: var(--aff-primary);
    margin-right: 0.5rem;
    vertical-align: middle;
}


/* Hide Google Translate's injected chrome (top banner iframe, tooltip,
 * balloon). Catches every skiptranslate iframe variant Google ships. */
iframe.skiptranslate,
.goog-te-banner-frame,
.goog-te-balloon-frame,
.goog-tooltip,
.goog-tooltip:hover,
#goog-gt-tt {
    display: none !important;
    visibility: hidden !important;
}

/* Google Translate sets `body { top: 40px; position: relative }` to
 * make room for its banner. Counteract it — but only on the frontend
 * where the `.translated-ltr` / `.translated-rtl` body class lands.
 * Unconditional `body { … !important }` would also fight Gutenberg's
 * editor canvas styles (the file is loaded into the canvas iframe via
 * add_editor_style). */
body.translated-ltr,
body.translated-rtl {
    top: 0 !important;
    position: static !important;
}

.goog-text-highlight {
    background: none !important;
    box-shadow: none !important;
}


