/* Component-owned styles (shipped only when this component is used) */
@layer components {

/*
 * SPDX-FileCopyrightText: 2026 The freelance-persona_theme Project Contributors
 *
 * SPDX-License-Identifier: MIT
 */

/* Pre-migration origin: _cards.scss (converted in phase 3.1) */

/* ====================================================
   === SHARED CARD BASE ===
   ==================================================== */

/* ====================================================
   === CARD SYSTEM CONSTITUTION ===
   1. ONE proportional system for all card types: the
      desktop rendering at 1920×1080 (16:9) is the master
      mask; every other viewport renders a scaled version
      of the same design.
   2. Shared primitives live here (container setup,
      image aspects, structure). Per-type files hold only
      overrides/additions and propagate through the
      consumable chain.
   3. NO card deforms: every card type carries a fixed
      aspect-ratio derived from its master measurements.
      A new shape = an explicit fixed-ratio override or a
      new card type. heise news rows are list items, not
      cards, and are exempt.
   Master measurements @1920×1080:
   - feature card   402.7×338.8  → 403/339
   - post card      410.7×426    → 403/418
   - blog big card  410.7×543.8  → 403/534
   - mini card      410.7×114.9  → 403/113
   ==================================================== */

/* Every card wrapper is an inline-size container: card
   internals are sized in cqi (% of card width) so the
   whole design scales like an image at any viewport. */
.feature-group-wrapper,
.category-card-wrapper,
.mini-category-card-wrapper,
.post-card-cell,
.preview-card-wrapper {
    container-type: inline-size;
}

.card-wrapper {
    height: 100%;
    text-decoration: none;
    
    &:hover, &:focus {
        text-decoration: none;
    }
}

.card-base {
    background: var(--card-background, #ffffff);
    border-radius: 0.75rem;
    /* Border moved to ::after for strict overlay */
    border: none;
    position: relative;
    overflow: hidden;
    transition:
        transform 0.3s ease-out,
        box-shadow 0.3s ease-out;
    display: flex;
    flex-direction: column;
    height: 100%;
    text-decoration: none;
    color: inherit;
    
    &:hover, &:focus {
        text-decoration: none;
    }
    
    /* will-change provides the promotion hint without statically
       pre-promoting every card on page load (translateZ(0) was doing that) */
    will-change: transform, box-shadow;
    backface-visibility: hidden;
}

/* Overlay Border to cover sub-pixel content bleed */
.card-base::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    border: 1px solid var(--card-border, #f0f0f0);
    pointer-events: none;
    z-index: 10;
}

/* Hover Effect triggers on wrapper, affects card */
.card-wrapper:hover .card-base {
    transform: translateY(-0.3125rem);
    /* -5px */
    box-shadow: 0 0.625rem 1.25rem rgba(0, 0, 0, 0.1);
    /* 0 10px 20px */
}

/* Touch Device Optimization: Disable Lift */
@media (hover: none) {
    .card-wrapper:hover .card-base {
        transform: none;
        box-shadow: none;
        /* Optional: or keep default shadow */
    }
}

/* Dark Mode Hover Highlight */
@media (prefers-color-scheme: dark) {
    :root:not(:has(.theme-state-light:checked)) .card-wrapper:hover .card-base {
        box-shadow: none;
        background-color: color-mix(in srgb, var(--card-background), var(--heading-color) 4%);
    }
}
@media (prefers-color-scheme: light) {
    :root:has(.theme-state-dark:checked) .card-wrapper:hover .card-base {
        box-shadow: none;
        background-color: color-mix(in srgb, var(--card-background), var(--heading-color) 4%);
    }
}

.card-content {
    padding: calc(1.5rem * var(--scale-factor, 1));
    display: flex;
    flex-direction: column;
    flex-grow: 1;
}
}
/* Styles live in styles/_cards.css (imported above) */.preview-card-wrapper[data-astro-cid-pwd3q4gj] {
  container-type: inline-size;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.mock-page-content[data-astro-cid-pwd3q4gj] {
  width: 100%;
  height: 100%;
  padding: 2.5cqw;
  background-color: var(--surface-color, #fff);
  color: var(--default-color);
  overflow: hidden;
  position: relative;
}

.mock-fade[data-astro-cid-pwd3q4gj] {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 25%;
  background: linear-gradient(to bottom, transparent, var(--surface-color, #fff));
  z-index: 2;
  pointer-events: none;
}

.mock-page-content[data-astro-cid-pwd3q4gj] .post-header[data-astro-cid-pwd3q4gj] {
  width: 62.5cqw;
  margin-inline: auto;
}

.mock-page-content[data-astro-cid-pwd3q4gj] .post-title[data-astro-cid-pwd3q4gj] {
  font-size: 3.13cqw;
  line-height: 1.2;
  margin-bottom: .63cqw;
  color: var(--heading-color);
}

.post-tags[data-astro-cid-pwd3q4gj] {
  margin-bottom: 0;
}

.mock-page-content[data-astro-cid-pwd3q4gj] .tag[data-astro-cid-pwd3q4gj].badge {
  font-size: .94cqw;
  padding: .31cqw .63cqw;
  border-radius: .23cqw;
  margin-inline-end: .63cqw;
  margin-block-end: .31cqw;
}

.mock-page-content[data-astro-cid-pwd3q4gj] .mock-hr[data-astro-cid-pwd3q4gj] {
  margin: .63cqw 0;
  opacity: .2;
  border-top: .16cqw solid;
}

.mock-page-content[data-astro-cid-pwd3q4gj] .mock-hr-wide[data-astro-cid-pwd3q4gj] {
  margin: .94cqw 0;
}

.mock-page-content[data-astro-cid-pwd3q4gj] .meta-top[data-astro-cid-pwd3q4gj] {
  display: flex;
  align-items: center;
  margin-bottom: 1.25cqw;
  font-size: 1.09cqw;
  color: var(--text-muted);
}

.mock-page-content[data-astro-cid-pwd3q4gj] .mock-sep[data-astro-cid-pwd3q4gj] {
  margin-inline: .31cqw;
}

.mock-page-content[data-astro-cid-pwd3q4gj] .post-content[data-astro-cid-pwd3q4gj] {
  font-size: 1.25cqw;
  line-height: 1.6;
  white-space: pre-line;
}
/* Component-owned styles (shipped only when this component is used) */
@layer components {

/*
 * SPDX-FileCopyrightText: 2026 The freelance-persona_theme Project Contributors
 *
 * SPDX-License-Identifier: MIT
 */

/* Pre-migration origin: _filtered-posts.scss (converted in phase 3.1) */

/* ====================================================
   === COMPONENT: FILTERED POSTS SECTION ===
   ==================================================== */

/* === TUNABLE DIALS ===
   --fp-meta-gap: the vertical distance between the row content
   (text + thumb) and the meta line (tags + date). Adjust here.
   --fp-meta-date-gap: horizontal breathing room between the tag
   rail's cutoff (or last badge, fully scrolled) and the date.
   Adjust here.
   --fp-news-*-size: MOBILE news-UI typography (<768px news rows —
   home news + inner list on phones): headline, excerpt, tag badge,
   date. Adjust here.
   --fp-news-desktop-*-size: DESKTOP news-UI typography (rows
   variant at ≥768px — the inner category list pages): same four
   roles, independently tunable. The desktop cards layout is NOT
   touched by either set (it scales via cqi). Adjust here.
   --fp-news-title-lines / --fp-news-title-lines-desktop: how many
   lines the post-card headline wraps to before the ellipsis
   (mobile news rows / rows + cards). Adjust here. */
.filtered-posts {
    --fp-meta-gap: 0.5rem;
    --fp-meta-date-gap: 1rem;
    --fp-news-title-lines: 2;
    --fp-news-title-lines-desktop: 2;
    /* mobile (<768px) */
    --fp-news-title-size: 1rem;
    --fp-news-desc-size: 0.75rem;
    --fp-news-tag-size: 0.75rem;
    --fp-news-date-size: 0.7rem;
    /* desktop (≥768px, rows variant) */
    --fp-news-desktop-title-size: 1.5rem;
    --fp-news-desktop-desc-size: 1rem;
    --fp-news-desktop-tag-size: 0.75rem;
    --fp-news-desktop-date-size: 0.8rem;
}

/* 16:9 Image Container */
.post-image-container {
    width: 100%;
    aspect-ratio: 16/9;
    overflow: hidden;
    background-color: var(--card-background, #ffffff);
    position: relative;

    /* Attribution: desktop = fixed 0.6rem (pre-proportional value —
       NO container here: inline-size containment inside the desktop
       rows' auto-hugging grid column collapses the thumb). */
    --attribution-font-size: 0.6rem;

    /* Import attribution styles FIRST */

    /* Override for 2-line layout on cards */
    .img-attribution {
        bottom: 0.25rem;
        right: 0.5rem;
        flex-direction: column;
        align-items: flex-end;
        gap: 0;

        /* Mobile specific adjustments */
        @media (max-width: 767px) {
            right: 0.4rem;
            bottom: 0.2rem;
            --attribution-font-size: max(var(--attribution-ratio-mobile), var(--attribution-min-size));
        }
    }
}

.post-image {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* Mock previews must never inflate the 16:9 image window — their
   min-content height would beat the aspect-ratio and push the meta
   line down (text-only posts). Absolute fill + the window's
   overflow clip. */
.post-image-container .preview-card-wrapper {
    position: absolute;
    inset: 0;
    height: 100%;
}

/* Post Details Container */
.post-details {
    /* No padding here, use Card's padding via .card-content */
    display: flex;
    flex-direction: column;
    flex-grow: 1;
    height: 100%;
    min-width: 0;
}

/* ====================================================
   === PROPORTIONAL POST CARD (constitution) ===
   One card type for home + inner category pages. Fixed
   master shape 403×418 (measured @1920×1080, card 410.7px):
   radius 12→2.92, title 20→4.87 (mb 8→1.95), desc 16→3.90
   @ lh 1.5, date 12→2.92, tag badge 12→2.92 (r 3→0.73,
   pads 4/8→0.97/1.95). Image window = 16:9 (master).
   The meta row (all tags left, date right) sits at the
   card BOTTOM at every viewport (heise mockup).
   ==================================================== */
.filtered-posts .card-base {
    aspect-ratio: 403 / 418;
    border-radius: 2.92cqi;
}

.filtered-posts .card-content {
    padding: 5.84cqi;
}

.post-details .post-content {
    flex-grow: 1;
}

.post-details .post-content .post-card-title {
    font-weight: 500;
    font-size: 4.87cqi;
    line-height: 1.2;
    margin-bottom: 1.95cqi;
    display: -webkit-box;
    -webkit-line-clamp: var(--fp-news-title-lines-desktop);
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.post-details .post-content .post-card-desc {
    margin-left: 0;
    font-size: 3.9cqi;
    line-height: 1.5;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Meta line: tags bottom-left, date bottom-right */
.post-meta-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    /* Breathing room between the tag rail's cutoff (or its last
       badge, fully scrolled) and the date — dial at the top. */
    gap: var(--fp-meta-date-gap, 0.5rem);
}

/* Tags: single row, horizontally scrollable, scrollbar hidden —
   the mid-badge cutoff at the date's edge is the scroll affordance.
   min-width: 0 + flex: 1 lets the row shrink instead of deforming
   the date. */
.post-meta-row .meta {
    flex: 1;
    min-width: 0;
    overflow-x: auto;
    overflow-y: hidden;
    white-space: nowrap;
    scrollbar-width: none; /* Firefox + all modern engines */
}

.post-meta-row .meta::-webkit-scrollbar {
    display: none; /* older Chromium/Safari fallback */
}

/* The date can never deform: fixed at the right edge, single line. */
.post-meta-row .date {
    flex-shrink: 0;
    white-space: nowrap;
}

.post-meta-row .date {
    position: static;
    font-size: 2.92cqi;
    font-weight: 500;
    line-height: 1.5;
    color: var(--text-muted);
}

.post-details .meta .tag.badge {
    font-size: 2.92cqi;
    border-radius: 0.73cqi;
    padding: 0.97cqi 1.95cqi;
}

/* Transition base state for text elements */
.post-details .post-content p,
.post-details .date {
    transition: color 0.3s ease-out;
    /* transition-delay: 0s; Remove delay to match standard */
    will-change: color;
}

/* Hover Text Color Changes */
/* We rely on global selector because Card wrapper handles hover */
/* Using specificity to target within the card wrapper context */
.card-wrapper:hover .post-details .post-content p,
.card-wrapper:hover .post-details .date {
    color: var(--accent-color);
}

/* OVERRIDE: Prevent text-only preview cards from lighting up on hover */
/* .card-wrapper:hover .mock-page-content, */
/* .card-wrapper:hover .mock-page-content * { */
/*     color: var(--text-muted) !important; */
/* } */

/* TAG STYLES (Refactored from inline) */

/* ====================================================
   === MOBILE DENSITY (phones only, <768px) ===
   heise.de-style teaser rows: card chrome off, 1px hairline
   separators in the card-border color, text left + small
   16:9 thumb right (~40% width). Typography follows the
   inner Design-System list guide (24px title, 16px excerpt).
   Posts without a thumbnail keep the mock-preview as thumb.
   ==================================================== */
@media (max-width: 767px) {
    /* heise rows are list items, NOT cards: exempt from the
       constitution's fixed ratio and proportional internals. */
    .filtered-posts .card-base {
        aspect-ratio: auto;
        border-radius: 0;
        display: grid;
        /* Same two-column stacks as the rows variant: text over tag
           rail (left), thumb over date (right). No column-gap — the
           text block carries its own right padding, so the rail's
           cutoff sits EXACTLY inline with the thumb's left edge. */
        grid-template-areas:
            "text img"
            "meta date";
        grid-template-columns: 1fr 40%;
        column-gap: 0;
        row-gap: var(--fp-meta-gap, 0.5rem);
        background: transparent;
        box-shadow: none;
    }

    /* Unwrap the Card's content box so .post-details and
       .post-meta-row become direct grid children (the meta row
       unwraps further, see below) — text and rail own the left
       column, thumb and date the right. */
    .filtered-posts .card-content {
        display: contents;
    }

    .filtered-posts .card-base::after {
        border: none;
    }

    .filtered-posts .card-wrapper .card-base:hover {
        transform: none;
        box-shadow: none;
        background: transparent;
    }

    /* Hairline centered in the vertical gap between rows — the
       border-top variant hugged the post below it. */
    .filtered-posts .grid > div {
        position: relative;
    }

    .filtered-posts .grid > div:not(:first-child)::before {
        content: "";
        position: absolute;
        top: calc(var(--fp-hairline-gap, 2.25rem) / -2);
        left: 0;
        right: 0;
        height: 1px;
        background: var(--card-border);
    }

    /* Small landscape thumb on the right, subtle outline like the list */
    .filtered-posts .post-image-container {
        grid-area: img;
        align-self: center;
        width: 100%;
        aspect-ratio: 16 / 9;
        height: auto;
        border-radius: 0.375rem;
        overflow: hidden;
        border: 1px solid var(--card-border);
        /* Mobile only: the thumb becomes the query container so the
           attribution scales with the image (floor = Permaculture
           reference). Desktop rows/cards stay fixed-rem — containment
           in the desktop rows' auto column collapses the thumb. */
        container-type: inline-size;
        --attribution-font-size: max(var(--attribution-ratio-mobile), var(--attribution-min-size));
    }

    .filtered-posts .post-details {
        grid-area: text;
        /* Right padding instead of the grid's column-gap: the rail
           (row 2) has no gap of its own and clips at the column
           boundary = the thumb's left edge. */
        padding: 0.5rem 0.75rem 0 0;
        min-width: 0;
    }

    /* Unwrap so the rail (meta) and the date land in the two
       columns independently — see the grid areas above. */
    .filtered-posts .post-meta-row {
        display: contents;
    }

    .filtered-posts .post-meta-row .meta {
        grid-area: meta;
        align-self: end;
        padding-bottom: 0.25rem;
    }

    .filtered-posts .post-meta-row .date {
        grid-area: date;
        align-self: end;
        justify-self: end; /* flush with the thumb's right edge */
        padding-bottom: 0.25rem;
    }

    .post-details .meta .tag.badge {
        font-size: var(--fp-news-tag-size, 0.75rem);
        border-radius: 0.25rem;
        padding: 0.1rem 0.4rem;
    }

    /* Design-System-list guide: big single-line headline (long
       titles shrink to fit via the title-fit script; without JS
       the base 2-line clamp applies instead), 16px excerpt. */
    .post-details .post-content .post-card-title {
        font-size: var(--fp-news-title-size, 1.5rem);
        line-height: 1.2;
        margin-bottom: 0.5rem;
        -webkit-line-clamp: var(--fp-news-title-lines);
    }

    .post-details .post-content .post-card-desc {
        font-size: var(--fp-news-desc-size, 1rem);
        line-height: 1.6;
        -webkit-line-clamp: 3;
    }

    /* Date: modest, right end of the meta line (big stacked dates
       were the layout killer in the guide list). */
    .post-meta-row .date {
        font-size: var(--fp-news-date-size, 0.8rem);
        line-height: 1.2;
    }
}

/* Fit-to-one-line titles: dropped — a plain 2-line wrap won
   (no JS to maintain). The base clamp handles it. */

/* ====================================================
   === ROWS VARIANT (layout="rows") — news rows at ALL widths ===
   Same consumable as the mobile news UI; the inner blogs list
   pages opt in so mobile + desktop render the identical rows.
   (The <768 media block below applies the same rules to every
   .filtered-posts — for .rows they're redundant but identical,
   so both blocks can coexist without conflicts.)
   ==================================================== */
.filtered-posts.rows {
    /* The hairline sits centered in the vertical gap between cells:
       default gutter = cell mt 1.5rem + mb 1.5rem = 3rem. */
    --fp-hairline-gap: 3rem;
}

@media (max-width: 767px) {
    .filtered-posts.rows {
        --fp-hairline-gap: 2.25rem;
    }
}

.filtered-posts.rows .card-base {
    aspect-ratio: auto;
    border-radius: 0;
    display: grid;
    /* Two columns, two stacks: left = text over tag rail, right =
       thumb over date. The rail's cutoff therefore sits inline with
       the thumb's left edge. */
    grid-template-areas:
        "text img"
        "meta date";
    grid-template-columns: 1fr 40%;
    column-gap: 0;
    row-gap: var(--fp-meta-gap, 0.5rem);
    background: transparent;
    box-shadow: none;
}

/* Desktop rows: the thumb is capped (13.5rem, flush right) — hug
   the second column to it so the rail's cutoff lines up with the
   thumb's LEFT edge, not the wide 40% column boundary. */
@media (min-width: 768px) {
    .filtered-posts.rows .card-base {
        grid-template-columns: 1fr auto;
    }

    /* Mock-preview rows (text-only posts) contribute min-content to the
       auto column and would collapse — floor them at the same cap the
       real thumbs use, so every row's thumb is 13.5rem on desktop. */
    .filtered-posts.rows .post-image-container {
        min-width: 13.5rem;
    }
}

.filtered-posts.rows .card-base::after {
    border: none;
}

.filtered-posts.rows .card-wrapper .card-base:hover {
    transform: none;
    box-shadow: none;
    background: transparent;
}

.filtered-posts.rows .grid > div {
    position: relative;
}

.filtered-posts.rows .grid > div:not(:first-child)::before {
    content: "";
    position: absolute;
    top: calc(var(--fp-hairline-gap, 2.25rem) / -2);
    left: 0;
    right: 0;
    height: 1px;
    background: var(--card-border);
}

.filtered-posts.rows .post-image-container {
    grid-area: img;
    align-self: center;
    justify-self: end;
    width: 100%;
    /* Cap the thumb so desktop rows stay flat heise-style; flush
       right = the hairline and the date end at its corner. */
    max-width: 13.5rem;
    aspect-ratio: 16 / 9;
    height: auto;
    border-radius: 0.375rem;
    overflow: hidden;
    border: 1px solid var(--card-border);
}

.filtered-posts.rows .post-details {
    grid-area: text;
    /* Right padding instead of the grid's column-gap (see the
       mobile block): the rail clips at the thumb's left edge. */
    padding: 0.5rem 0.75rem 0 0;
    min-width: 0;
}

.filtered-posts.rows .card-content {
    display: contents;
}

.filtered-posts.rows .post-meta-row {
    /* Unwrap so the rail (meta) and the date land in the two
       columns independently — see the grid areas above. */
    display: contents;
}

.filtered-posts.rows .post-meta-row .meta {
    grid-area: meta;
    align-self: end;
    padding-bottom: 0.25rem;
}

.filtered-posts.rows .post-meta-row .date {
    grid-area: date;
    align-self: end;
    justify-self: end; /* flush with the thumb's right edge */
    padding-bottom: 0.25rem;
}

/* Desktop rows typography — the mobile set above (in the <768px
   block) covers phones on ALL .filtered-posts, so these four rules
   only need the ≥768px range and read the desktop dials. */
@media (min-width: 768px) {
    .filtered-posts.rows .post-details .meta .tag.badge {
        font-size: var(--fp-news-desktop-tag-size, 0.75rem);
        border-radius: 0.25rem;
        padding: 0.1rem 0.4rem;
    }

    .filtered-posts.rows .post-details .post-content .post-card-title {
        font-size: var(--fp-news-desktop-title-size, 1.5rem);
        line-height: 1.2;
        margin-bottom: 0.5rem;
        -webkit-line-clamp: var(--fp-news-title-lines-desktop);
    }

    .filtered-posts.rows .post-details .post-content .post-card-desc {
        font-size: var(--fp-news-desktop-desc-size, 1rem);
        line-height: 1.6;
        -webkit-line-clamp: 3;
    }

    .filtered-posts.rows .post-meta-row .date {
        font-size: var(--fp-news-desktop-date-size, 0.8rem);
        line-height: 1.2;
    }
}
}@layer components {
  .post-image-container {
    position: relative;
    overflow: hidden;
  }
}
/* Card-facing post primitives (.post-header/.post-title/.meta-top) render here too,
     so this partial ships wherever those cards appear. */
@layer components {

/*
 * SPDX-FileCopyrightText: 2026 The freelance-persona_theme Project Contributors
 *
 * SPDX-License-Identifier: MIT
 */

/*--------------------------------------------------------------
# Blog Post Section
--------------------------------------------------------------*/
.blog-post {
  padding-bottom: 1.875rem; /* 30px */
  margin: 0; /* Spacing handled by .section padding-top */
}

.blog-post .article {
  padding: 1.875rem; /* 30px */
  box-shadow: 0 0.25rem 1rem color-mix(in srgb, var(--default-color), transparent 90%); /* 0 4px 16px */
}

.blog-post .post-img {
  /* margin: -1.875rem -1.875rem 1.25rem -1.875rem; // -30px -30px 20px -30px */
  margin: 0 0 1.25rem 0;
  overflow: hidden;
  border-radius: 0.25rem;
  aspect-ratio: 16/9;
  position: relative; /* For attribution overlay positioning */

  /* Attribution scales with the image; the wrapper is the query
     container (inline-size) so the rail/overlay can use cqi.
     1.3cqi ≈ the pre-proportional 0.65rem at desktop article width —
     the 2.34cqi card ratio overscaled on full-width post images. */
  container-type: inline-size;
  --attribution-font-size: max(1.3cqi, var(--attribution-min-size));

  img {
    width: 100%;
    height: 100%;
    object-fit: cover;

    /* Mute brightness in dark mode to avoid glare */
    @media (prefers-color-scheme: dark) {
      :root:not(:has(.theme-state-light:checked)) & {
        filter: brightness(0.85) contrast(1.1);
        transition: filter 0.3s ease;
      }
    }

    @media (prefers-color-scheme: light) {
      :root:has(.theme-state-dark:checked) & {
        filter: brightness(0.85) contrast(1.1);
        transition: filter 0.3s ease;
      }
    }
  }
}

/* Hover to restore full brightness for hero image */
@media (prefers-color-scheme: dark) {
  :root:not(:has(.theme-state-light:checked)) .blog-post .post-img img:hover {
    filter: brightness(1) contrast(1);
  }
}

@media (prefers-color-scheme: light) {
  :root:has(.theme-state-dark:checked) .blog-post .post-img img:hover {
    filter: brightness(1) contrast(1);
  }
}

.blog-post .title {
  color: var(--heading-color);
  font-size: 1.75rem; /* 28px */
  font-weight: 700;
  padding: 0;
  margin: 1.875rem 0; /* 30px 0 */
}

.blog-post .post-content {
  margin-top: 1.25rem; /* 20px */
  display: flow-root;
}

.blog-post .post-content p {
  text-align: justify;
}

.blog-post .post-content img {
  max-width: 100%;
  height: auto;
  display: block;
  border-radius: 0.25rem; /* 4px */
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--default-color), transparent 85%);
  margin-left: auto;
  margin-right: auto;
  margin-bottom: 1.25rem; /* 20px */
  margin-top: 0.625rem; /* 10px */
}

.blog-post .post-content svg {
  max-width: 100%;
  height: auto;
  display: block;
  margin-left: auto;
  margin-right: auto;
  margin-bottom: 1.25rem; /* 20px */
  margin-top: 0.625rem; /* 10px */
}

.blog-post .post-content.science-layout {
  text-align: justify;

  p {
    margin-bottom: 1.25rem;
    line-height: 1.6;
  }

  @media (min-width: 768px) {
    column-count: 2;
    column-gap: 2.5rem;
    column-rule: 1px solid color-mix(in srgb, var(--default-color), transparent 90%);

    h3, blockquote, table, iframe, pre, .expressive-code {
      column-span: all;
    }

    svg, img {
      &[style*="margin: 1.5rem auto"], &[style*="margin:1.5rem auto"] {
        column-span: all;
        max-width: 60%;
        margin: 2.5rem auto;
      }
    }
  }
}

.blog-post .post-content h3 {
  font-size: 1.375rem; /* 22px */
  margin-top: 1.875rem; /* 30px */
  font-weight: bold;
}

.blog-post .post-content table {
  /* Tables can't shrink below min-content — block + scroll keeps wide
     tables INSIDE the article instead of overflowing the page (which
     made mobile browsers zoom out and shrink everything). */
  display: block;
  width: 100%;
  max-width: 100%;
  overflow-x: auto;
  border-collapse: collapse;
  margin: 1.25rem 0; /* 20px 0 */
  background-color: var(--surface-color);
  text-align: left;
}

.blog-post .post-content th {
  border-bottom: 2px solid color-mix(in srgb, var(--default-color), transparent 80%);
  background-color: color-mix(in srgb, var(--default-color), transparent 95%);
  color: var(--heading-color);
  padding: 0.75rem; /* 12px */
}

.blog-post .post-content td {
  border-bottom: 1px solid color-mix(in srgb, var(--default-color), transparent 90%);
  padding: 0.75rem; /* 12px */
}

.blog-post .post-content tr:nth-child(even) td {
  background-color: color-mix(in srgb, var(--default-color), transparent 97%);
}

.blog-post .post-content tr:hover td {
  background-color: color-mix(in srgb, var(--default-color), transparent 95%);
}

/* ====================================================
   === MOBILE TABLE TREATMENTS (phones only, ≤767px) ===
   Markdown tables can't shrink below min-content; the base
   block+scroll above keeps them inside the article but hides
   columns with zero affordance. The treatment is selected via
   visuals.tables.mobile_style (body[data-tables-mobile]):
   - cards (default): each row becomes a self-describing card —
     remarkTableDataLabels copies the column headers into
     data-label attributes
   - scroll: the grid stays, first column pinned, right-edge
     fade as the scroll affordance (the tag-rail peek idiom)
   - native: no extra rules (base block+scroll only)
   ==================================================== */
@media (max-width: 767px) {
  /* --- "cards": labeled row cards, no horizontal scroll --- */
  body[data-tables-mobile="cards"] .blog-post .post-content table {
    display: block;
    border-collapse: separate;
    background-color: transparent;
  }

  body[data-tables-mobile="cards"] .blog-post .post-content thead {
    display: none; /* column names live on each cell as data-label */
  }

  body[data-tables-mobile="cards"] .blog-post .post-content tbody {
    display: block;
  }

  body[data-tables-mobile="cards"] .blog-post .post-content tbody tr {
    display: block;
    background-color: var(--surface-color);
    border: 1px solid var(--card-border);
    border-radius: 0.375rem;
    padding: 0.75rem 1rem;
    margin-bottom: 0.75rem;
  }

  body[data-tables-mobile="cards"] .blog-post .post-content tbody tr:last-child {
    margin-bottom: 0;
  }

  body[data-tables-mobile="cards"] .blog-post .post-content tbody td {
    display: block;
    padding: 0.25rem 0;
    border-bottom: none;
    background-color: transparent;
  }

  body[data-tables-mobile="cards"] .blog-post .post-content tbody tr:last-child td:last-child {
    border-bottom: none;
  }

  /* Column label as an overline above each cell's content. */
  body[data-tables-mobile="cards"] .blog-post .post-content tbody td::before {
    content: attr(data-label);
    display: block;
    font-family: var(--font-mono, monospace);
    font-size: 0.6875rem; /* 11px */
    font-weight: 500;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: color-mix(in srgb, var(--default-color), transparent 45%);
    margin-bottom: 0.125rem;
  }

  /* --- Per-column accents: visual anchors so grouped columns
     (e.g. two colony columns in a schedule table) are pattern-
     scannable. Each column gets a hue for its label and a soft
     left bar on its blocks; the first column stays the neutral
     card header. Override any column via the custom properties,
     e.g. --table-col-3-color: #d97706. --- */
  body[data-tables-mobile="cards"] .blog-post .post-content tbody td:nth-child(2) {
    --table-col-color: var(--table-col-2-color, #0284c7); /* sky-600 */
  }

  body[data-tables-mobile="cards"] .blog-post .post-content tbody td:nth-child(3) {
    --table-col-color: var(--table-col-3-color, #d97706); /* amber-600 */
  }

  body[data-tables-mobile="cards"] .blog-post .post-content tbody td:nth-child(4) {
    --table-col-color: var(--table-col-4-color, #16a34a); /* green-600 */
  }

  body[data-tables-mobile="cards"] .blog-post .post-content tbody td:nth-child(5) {
    --table-col-color: var(--table-col-5-color, #dc2626); /* red-600 */
  }

  body[data-tables-mobile="cards"] .blog-post .post-content tbody td:nth-child(6) {
    --table-col-color: var(--table-col-6-color, #7c3aed); /* violet-600 */
  }

  body[data-tables-mobile="cards"] .blog-post .post-content tbody td:nth-child(7) {
    --table-col-color: var(--table-col-7-color, #0284c7);
  }

  body[data-tables-mobile="cards"] .blog-post .post-content tbody td:nth-child(8) {
    --table-col-color: var(--table-col-8-color, #d97706);
  }

  body[data-tables-mobile="cards"] .blog-post .post-content tbody td:nth-child(n + 2) {
    border-left: 0.1875rem solid color-mix(in srgb, var(--table-col-color, var(--accent-color)), transparent 60%);
    padding-left: 0.5rem;
  }

  body[data-tables-mobile="cards"] .blog-post .post-content tbody td:nth-child(n + 2)::before {
    color: var(--table-col-color, color-mix(in srgb, var(--default-color), transparent 45%));
  }

  /* First column = the row identifier ("Day 0 — The Split"):
     emphasize it as the card header. */
  body[data-tables-mobile="cards"] .blog-post .post-content tbody td:first-child {
    padding-bottom: 0.5rem;
    margin-bottom: 0.25rem;
    border-bottom: 1px solid color-mix(in srgb, var(--default-color), transparent 90%);
    color: var(--heading-color);
    font-weight: 700;
  }

  body[data-tables-mobile="cards"] .blog-post .post-content tbody td:first-child strong {
    color: var(--accent-color);
  }

  /* --- "scroll": compact data-grid for structured content
     (statistics, price lists — content that reads like a sheet).
     Dense typography, pinned first column, thin column separators,
     right-edge fade as the swipe affordance (the tag-rail peek
     idiom). Note: a sticky TOP header row is impossible inside an
     overflow-x scroll container (the spec forces overflow-y to auto,
     so there is no page-scroll to stick against) — the header row
     scrolls away vertically by design. */
  body[data-tables-mobile="scroll"] .blog-post .post-content table {
    font-size: 0.8125rem; /* 13px — sheet-density body */
    -webkit-mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 1.5rem), transparent);
    mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 1.5rem), transparent);
  }

  body[data-tables-mobile="scroll"] .blog-post .post-content th {
    padding: 0.5rem 0.625rem; /* 8px 10px */
    background-color: var(--surface-color); /* solid: sticky head */
    border-bottom: 2px solid color-mix(in srgb, var(--default-color), transparent 75%);
    font-weight: 700;
    white-space: nowrap;
  }

  body[data-tables-mobile="scroll"] .blog-post .post-content td {
    padding: 0.5rem 0.625rem;
    border-bottom: 1px solid color-mix(in srgb, var(--default-color), transparent 90%);
  }

  /* Thin column separators give the grid its spreadsheet feel. */
  body[data-tables-mobile="scroll"] .blog-post .post-content th:not(:first-child),
  body[data-tables-mobile="scroll"] .blog-post .post-content td:not(:first-child) {
    border-left: 1px solid color-mix(in srgb, var(--default-color), transparent 88%);
  }

  /* Pinned first column: row identifiers stay readable while the
     remaining columns scroll. box-shadow instead of border — with
     border-collapse the td borders live on the table and would not
     travel with a sticky cell. */
  body[data-tables-mobile="scroll"] .blog-post .post-content th:first-child,
  body[data-tables-mobile="scroll"] .blog-post .post-content td:first-child {
    position: sticky;
    left: 0;
    background-color: var(--surface-color);
    font-weight: 600;
    z-index: 1;
    box-shadow: inset -1px 0 0 color-mix(in srgb, var(--default-color), transparent 88%);
  }

  /* Zebra rows must stay behind the pinned column: use the opaque
     composite so the sticky cell doesn't turn see-through. */
  body[data-tables-mobile="scroll"] .blog-post .post-content tr:nth-child(even) td:first-child {
    background-color: color-mix(in srgb, var(--default-color) 3%, var(--surface-color));
  }

  body[data-tables-mobile="scroll"] .blog-post .post-content thead th:first-child {
    z-index: 2; /* corner cell above pinned tds */
  }
}

/* Quote — paragraph-friendly: the accent bar (blockquote:after)
   is the signature; text sits left and reads like prose. For the
   big centered "pop" look use the :::pullquote directive instead. */
.blog-post .post-content blockquote {
  overflow: hidden;
  background-color: color-mix(in srgb, var(--default-color), transparent 95%);
  padding: 1rem 1.25rem;
  position: relative;
  text-align: left;
  margin: 1.25rem 0; /* 20px 0 */
}

.blog-post .post-content blockquote p {
  color: var(--default-color);
  line-height: 1.6;
  margin-bottom: 0;
  font-style: italic;
  font-weight: 400;
  font-size: 1.0625rem; /* 17px */
  text-align: left;
}

/* Opt-in pop quote (:::pullquote) — one-liners meant to stand out. */
.blog-post .post-content blockquote.pullquote {
  text-align: center;
  padding: 1.875rem; /* 30px */
}

.blog-post .post-content blockquote.pullquote p {
  font-size: 1.375rem; /* 22px */
  font-weight: 500;
  text-align: center;
}

.blog-post .post-content blockquote:after {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 0.1875rem; /* 3px */
  background-color: var(--accent-color);
  margin-top: 1.25rem; /* 20px */
  margin-bottom: 1.25rem; /* 20px */
}

/* ====================================================
   === ADMONITIONS (markdown container directives) ===
   :::warning[Title] … ::: / :::tip / :::info / :::note /
   :::important / :::caution — semantic hues are fixed on
   purpose (universal callout semantics); transparency keeps
   them dark-mode safe. See docs/features/admonitions.md.
   ==================================================== */
.blog-post .post-content .admonition {
  --admonition-color: var(--accent-color);
  margin: 1.25rem 0; /* 20px 0 */
  padding: 1rem 1.25rem;
  border-left: 0.1875rem solid var(--admonition-color);
  background-color: color-mix(in srgb, var(--admonition-color), transparent 92%);
  border-radius: 0.375rem;
  overflow: hidden;
}

.blog-post .post-content .admonition p {
  margin-bottom: 0.5rem;
  line-height: 1.6;
  text-align: left;
}

.blog-post .post-content .admonition p:last-child {
  margin-bottom: 0;
}

.blog-post .post-content .admonition-title {
  margin: 0 0 0.5rem !important;
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--admonition-color);
}

/* The bracket line (:::info[Subtitle]) — follows the theme's subtitle
   idiom (mono, size/weight like .section-title em) but takes the
   admonition's semantic hue instead of the accent, matching the type
   title above it. */
.blog-post .post-content .admonition .admonition-subtitle {
  margin: 0 0 0.75rem;
  font-family: var(--font-mono, monospace);
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--admonition-color);
}

.blog-post .post-content .admonition.admonition-warning {
  --admonition-color: #d97706; /* amber-600: readable on both themes */
}

.blog-post .post-content .admonition.admonition-caution {
  --admonition-color: #dc2626; /* red-600 */
}

.blog-post .post-content .admonition.admonition-tip {
  --admonition-color: #16a34a; /* green-600 */
}

.blog-post .post-content .admonition.admonition-info {
  --admonition-color: #0284c7; /* sky-600 */
}

.blog-post .post-content .admonition.admonition-note {
  --admonition-color: var(--default-color);
}

/* meta top styles */

.meta-top-divider {
  height: 1px;
  background-color: color-mix(in srgb, var(--default-color), transparent 85%);
  margin: 0.625rem 0; /* 10px 0 */
  padding: 0;
}

.blog-post .meta-top {
  margin-top: 0.625rem; /* 10px */
  color: color-mix(in srgb, var(--default-color), transparent 40%);
  margin-bottom: 0.625rem; /* 10px */
}

.blog-post .meta-top ul {
  display: flex;
  flex-wrap: wrap;
  list-style: none;
  align-items: center;
  padding: 0;
  margin: 0;
}

.blog-post .meta-top #info li+li {
  padding-left: 1.25rem; /* 20px */
}

.blog-post .meta-top #action li+li {
  padding-left: 0.625rem; /* 10px */
}

.blog-post .meta-top #info li [data-icon] {
  font-size: 1rem; /* 16px */
  margin-right: 0.5rem; /* 8px */
  line-height: 0;
  color: color-mix(in srgb, var(--default-color), transparent 40%);
}

.blog-post .meta-top time,
.blog-post .meta-top span {
  color: color-mix(in srgb, var(--default-color), transparent 40%);
  font-size: 0.875rem; /* 14px */
  display: inline-block;
  line-height: 1;
}

.blog-post .meta-bottom {
  padding-top: 0.625rem; /* 10px */
  border-top: 1px solid color-mix(in srgb, var(--default-color), transparent 90%);
}

.blog-post .meta-bottom [data-icon] {
  color: color-mix(in srgb, var(--default-color), transparent 40%);
  display: inline;
}

.blog-post .meta-bottom a {
  color: color-mix(in srgb, var(--default-color), transparent 40%);
  transition: 0.3s;
}

.blog-post .meta-bottom a:hover {
  color: var(--accent-color);
}

.blog-post .meta-bottom .cats {
  list-style: none;
  display: inline;
  padding: 0 1.25rem 0 0; /* 0 20px 0 0 */
  font-size: 0.875rem; /* 14px */
}

.blog-post .meta-bottom .cats li {
  display: inline-block;
}

.blog-post .meta-bottom .tags {
  list-style: none;
  display: inline;
  padding: 0;
  font-size: 0.875rem; /* 14px */
}

.blog-post .meta-bottom .tags li {
  display: inline-block;
}

.blog-post .meta-bottom .tags li+li::before {
  padding-right: 0.375rem; /* 6px */
  color: var(--default-color);
  content: ",";
}

.blog-post .meta-bottom .share {
  font-size: 1rem; /* 16px */
}

.blog-post .meta-bottom .share [data-icon] {
  padding-left: 0.3125rem; /* 5px */
}


.blog-post .post-top-content img,
.blog-post .post-content img {
  border-radius: 0.25rem; /* 4px */

  /* Mute brightness in dark mode to avoid glare */
  @media (prefers-color-scheme: dark) {
    :root:not(:has(.theme-state-light:checked)) & {
      filter: brightness(0.85) contrast(1.1);
      transition: filter 0.3s ease;
    }
  }

  @media (prefers-color-scheme: light) {
    :root:has(.theme-state-dark:checked) & {
      filter: brightness(0.85) contrast(1.1);
      transition: filter 0.3s ease;
    }
  }
}

/* Hover to restore full brightness */
@media (prefers-color-scheme: dark) {
  :root:not(:has(.theme-state-light:checked)) .blog-post img:hover {
    filter: brightness(1) contrast(1);
  }
}

@media (prefers-color-scheme: light) {
  :root:has(.theme-state-dark:checked) .blog-post img:hover {
    filter: brightness(1) contrast(1);
  }
}

.blog-post .post-tags {
  margin-top: 0.5em;
  position: relative;
  transition: max-height 0.35s ease-out;
}

/* ============================================================
   Clamped post tags — native reveal/collapse (checkbox pattern,
   theme-consistent with the radio theme switcher; works without JS).
   1 row on mobile, 2 on desktop; the label renders server-side only
   when the tag count can overflow (BlogPostTemplate).
   ============================================================ */
.blog-post {
  --post-tags-clamp: 1.75rem;      /* mobile: 1 badge row */
  --post-tags-clamp-desktop: 3.5rem; /* desktop: 2 rows */
}

@media (min-width: 768px) {
  .blog-post {
    --post-tags-clamp: var(--post-tags-clamp-desktop);
  }
}

.blog-post .tags-toggle-cb {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

/* Collapsed: 1 row (mobile) / 2 rows (desktop) fully crisp, plus a
   small PEEK strip where the next row's badge tops fade out (real
   hidden tags, not a fake hint) — via mask, so there is no overlay
   gradient (a gradient read as a dirty shadow in the dark theme).
   The toggle label sits centered below. */
.blog-post .tags-toggle-cb:not(:checked) ~ .post-tags {
  max-height: calc(var(--post-tags-clamp) + var(--post-tags-peek, 0.625rem));
  overflow: hidden;
  mask-image: linear-gradient(
    to bottom,
    #000 calc(100% - var(--post-tags-peek, 0.625rem)),
    transparent
  );
}

/* Expanded */
.blog-post .tags-toggle-cb:checked ~ .post-tags {
  max-height: 40rem;
}

/* Toggle label — subtitle idiom (mono + accent) */
.blog-post .tags-toggle {
  /* Full row + centered: sits under the tag block, aligned with it */
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  gap: 0.5rem;
  margin-top: 0.375rem;
  font-family: var(--font-mono, monospace);
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--accent-color);
  cursor: pointer;
  user-select: none;
}

.blog-post .tags-toggle .tags-chevron {
  display: inline-block;
  transition: transform 0.35s ease-out;
}

.blog-post .tags-toggle-cb:checked ~ .tags-toggle .tags-chevron {
  transform: rotate(180deg);
}

.blog-post .tags-toggle .when-open {
  display: none;
}

.blog-post .tags-toggle-cb:checked ~ .tags-toggle .when-closed {
  display: none;
}

.blog-post .tags-toggle-cb:checked ~ .tags-toggle .when-open {
  display: inline;
}

/* The label renders per tag count: 4–10 = mobile only (desktop fits
   two rows), ≥11 = always. ≤3: no label at all. */
.blog-post .tags-toggle--mobile-only {
  display: none;
}

@media (max-width: 767px) {
  .blog-post .tags-toggle--mobile-only {
    display: inline-flex;
  }
}

/* Keyboard: focus ring on the label when the hidden checkbox focuses */
.blog-post .tags-toggle-cb:focus-visible ~ .tags-toggle {
  outline: 2px solid var(--accent-color);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  .blog-post .post-tags,
  .blog-post .tags-toggle .tags-chevron {
    transition: none;
  }
}



.blog-post .post-content {
  margin-top: 2em;
}

#blog-post {
  position: relative;
  z-index: 10;
}

/* Post header layout */
.post-header {
  margin-bottom: 2em;
  position: relative;
  z-index: 5;
}

.header-content {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: 0.5em;
}

.post-title {
  margin: 0;
  flex: 1;
}

.MathJax {
  overflow-x: auto;
  overflow-y: hidden;
  max-width: 100%;
}

.post-content .mjx-chtml {
  margin: 1em 0;
}

.post-content .mjx-chtml.MJXc-display {
  margin: 1.5em 0;
  padding: 0;
}

/* Ensure equation numbers are visible */
.post-content .mjx-chtml .mjx-right {
  margin-right: 0 !important;
  float: right !important;
  text-align: right !important;
}

/* LaTeX equation overflow handling with centered content */
.post-content .MathJax_Display,
.post-content .mjx-chtml.MJXc-display {
  overflow-x: auto;
  overflow-y: hidden;
  margin: 1em 0;
  padding: 0.5em 0;
  width: 100% !important;
  /* Force width to ensure scrollbar works */
  max-width: 100%;
  display: flex !important;
  /* Use flexbox for centering */
  justify-content: center !important;
}

/* Center the math content while allowing it to be wider than container */
.post-content .mjx-chtml .mjx-math {
  min-width: min-content !important;
  /* Allow content to determine width */
  display: inline-block !important;
  text-align: center !important;
  margin: 0 auto !important;
}

/* Style the scrollbar for better appearance */
.post-content .mjx-chtml.MJXc-display::-webkit-scrollbar,
.post-content .MathJax_Display::-webkit-scrollbar {
  height: 0.5rem; /* 8px */
}

.post-content .mjx-chtml.MJXc-display::-webkit-scrollbar-track,
.post-content .MathJax_Display::-webkit-scrollbar-track {
  background: var(--scrollbar-track);
  border-radius: 4px;
}

.post-content .mjx-chtml.MJXc-display::-webkit-scrollbar-thumb,
.post-content .MathJax_Display::-webkit-scrollbar-thumb {
  background: var(--scrollbar-thumb);
  border-radius: 4px;
}

.post-content .mjx-chtml.MJXc-display::-webkit-scrollbar-thumb:hover,
.post-content .MathJax_Display::-webkit-scrollbar-thumb:hover {
  background: var(--scrollbar-thumb-hover);
}

/* Ensure equation container doesn't overflow */
.post-content .MathJax_SVG_Display,
.post-content .MathJax {
  max-width: 100%;
}

/* Ensure container for equations has proper overflow */
.post-content .mjx-container {
  overflow-x: auto;
  overflow-y: hidden;
  max-width: 100%;
}

/* Figure-wrapper alignment: paragraphs inside .text-center/.text-end
   wrappers (used by post content for figure grouping) follow the
   wrapper's alignment instead of the post-wide justified text. */
.text-center p, .text-end p, .text-start p {
  text-align: inherit !important;
}
}