/* Posts: cards, the reading view, post bodies, and tags. */
@layer components {
  /* Presets that size the card title differently set this, so the body
     heading scale below follows the title they actually show. */
  .post-card {
    --card-title-size: var(--text-section-title);

    padding: var(--space-6) 0 calc(var(--space-6) + var(--space-1));
    border-top: var(--border-thin) solid var(--color-border);
  }

  .post-card__header {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin-bottom: var(--space-4);
  }

  .post-card__userpic {
    flex: 0 0 4rem;
    width: 4rem;
    height: 4rem;
    overflow: hidden;
    border-radius: 50%;
    line-height: 0;
  }

  .post-card__meta {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--space-1);
    min-width: 0;
    color: var(--color-text-muted);
    font-family: var(--font-interface);
    font-size: var(--text-xs);
  }

  body:not(.error-layout) .post-card__author {
    display: inline-flex;
    align-items: center;
    max-width: 100%;
    min-height: 1.5rem;
    color: var(--color-accent);
    font-weight: 800;
    letter-spacing: var(--journal-meta-letter-spacing);
    overflow-wrap: anywhere;
    text-decoration: none;
    text-transform: var(--journal-meta-transform);
    white-space: normal;
  }

  .post-card__timestamp {
    color: var(--color-text-muted);
  }

  /* The timestamp is a permalink, styled as the plain text it has always
     looked like so the byline keeps its weight; it reveals itself on hover
     and keeps the focus ring for keyboard users. */
  .post-card__timestamp a {
    color: inherit;
    text-decoration: none;
  }

  .post-card__timestamp a:hover {
    text-decoration: underline;
  }

  /* Byline connectors are presentational and hidden from assistive tech.
     The default shows "author · time"; a preset that leads with the time
     swaps the separator for the translated connector. */
  .byline-separator {
    color: var(--color-text-muted);
    font-size: smaller;
  }

  .byline-connector {
    display: none;
  }

  .post-card__body {
    max-width: var(--width-reading);
  }

  /* A listed post title stays one step below the page title it sits under. */
  .post-card__title {
    max-width: 18ch;
    margin: 0 0 var(--space-3);
    font-size: var(--card-title-size);
    font-weight: 700;
    letter-spacing: -0.045em;
    line-height: var(--leading-tight);
  }

  body:not(.error-layout) .post-card__title a {
    color: var(--journal-post-title-color);
    text-decoration: none;
  }

  body:not(.error-layout) .post-card__title a:hover {
    color: var(--journal-post-title-hover);
  }

  /* Matches .post-reading__title--untitled: a placeholder title is real
     navigation, but should not carry a titled post's visual weight.
     Both classes are named so this outranks the `.post-card__title a`
     rule above instead of merely tying with it and depending on source
     order — the specificity trap logged as backlog K3(b). */
  body:not(.error-layout) .post-card__title.post-card__title--untitled a {
    color: var(--color-text-muted);
  }

  .post-card__excerpt {
    margin: 0;
    color: var(--color-text);
    font-family: var(--font-reading);
    font-size: var(--text-lg);
    line-height: 1.55;
  }

  .post-featured-image {
    margin-block: var(--journal-featured-image-margin);
    margin-inline: 0;
  }

  .post-featured-image__image {
    display: block;
    width: 100%;
    aspect-ratio: 8 / 5;
    object-fit: cover;
  }

  .post-featured-image__caption {
    margin-top: var(--space-2);
    color: var(--journal-featured-caption-color);
    font-family: var(--font-interface);
    font-size: var(--text-xs);
    line-height: 1.45;
  }

  .post-body > .post-featured-image:first-child {
    margin-top: 0;
  }

  .post-card__cw {
    margin: 0 0 var(--space-3);
    padding: var(--space-2) var(--space-3);
    border-left: 3px solid var(--color-accent);
    background: var(--color-surface);
    color: var(--color-text);
    font-size: var(--text-sm);
  }

  .post-card__reveal,
  .post-card__reveal-no-js a {
    display: inline-flex;
    align-items: center;
    min-height: 2rem;
    margin-bottom: var(--space-3);
    padding: var(--space-1) var(--space-2);
    border: var(--border-thin) solid var(--color-border-strong);
    border-radius: var(--radius-small);
    background: transparent;
    color: var(--color-text);
    font-size: var(--text-xs);
    font-weight: 700;
    text-decoration: none;
    cursor: pointer;
  }

  .post-card__footer {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    margin-top: var(--space-4);
    color: var(--color-text-muted);
    font-size: var(--text-xs);
  }

  .post-card__tags {
    display: inline-flex;
    flex-wrap: wrap;
    gap: var(--space-2);
  }

  .post-card__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2) var(--space-4);
  }

  .post-card__comment-actions {
    display: inline-flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    align-items: center;
    gap: var(--space-2) var(--space-4);
    margin-left: auto;
  }

  body:not(.error-layout) .post-card__tag,
  body:not(.error-layout) .post-card__comments {
    display: inline-flex;
    align-items: center;
    min-height: 1.5rem;
    color: var(--color-text-muted);
  }

  body:not(.error-layout) .post-card__tag {
    min-width: 0;
    overflow-wrap: anywhere;
  }

  body:not(.error-layout) .post-card__read-more {
    display: inline-flex;
    align-items: center;
    min-height: 1.5rem;
    color: var(--color-accent);
    font-weight: 800;
  }

  /* Thread preview + new comment (post–Track A follow-up Slice 3). The
     counter slot stays in the footer at zero so a first comment can fill it;
     the expanded panel always follows the footer. */
  .post-card__count-slot:empty {
    display: none;
  }

  body:not(.error-layout) .post-card__leave-comment {
    display: inline-flex;
    align-items: center;
    min-height: 1.5rem;
    color: var(--color-text);
    font-weight: 700;
  }

  .post-card__conversation {
    display: grid;
    gap: var(--space-3);
    min-width: 0;
    margin-top: var(--space-4);
    padding: var(--space-4) 0 0;
    border-top: var(--border-thin) solid var(--color-border);
  }

  .post-card__conversation[hidden] {
    display: none;
  }

  .post-card__conversation-frame {
    display: block;
    min-width: 0;
  }

  .post-card__conversation-frame[hidden] {
    display: none;
  }

  .post-card__conversation-status,
  .post-card__conversation-error p {
    margin: 0;
    color: var(--color-text-muted);
    font-size: var(--text-sm);
  }

  .post-card__conversation-error {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2) var(--space-3);
  }

  .post-card__conversation-error[hidden] {
    display: none;
  }

  .post-card__conversation-retry,
  .post-card__conversation-hide {
    justify-self: start;
    min-height: 2rem;
    padding: var(--space-1) var(--space-2);
    border: var(--border-thin) solid var(--color-border-strong);
    border-radius: var(--radius-small);
    background: transparent;
    color: var(--color-text);
    font-size: var(--text-xs);
    font-weight: 700;
    cursor: pointer;
  }

  .post-card-conversation {
    display: grid;
    gap: var(--space-3);
    min-width: 0;
  }

  .post-card-conversation__title {
    margin: 0;
    font-size: var(--text-base);
    letter-spacing: -0.01em;
  }

  .post-card-conversation__list {
    min-width: 0;
  }

  .post-card-conversation .comment {
    padding-block: var(--space-3);
  }

  .post-card-conversation__full {
    margin: 0;
    font-size: var(--text-sm);
    font-weight: 700;
  }

  .post-card-conversation .comments-section__composer {
    margin-top: 0;
    padding-top: 0;
    border-top: 0;
  }

  .post-card-conversation .comment-form,
  .post-card-conversation .comments-section__closed {
    margin-top: 0;
  }

  .post-body--blurred {
    filter: blur(12px);
    pointer-events: none;
    user-select: none;
    transition: filter 0.2s ease;
  }

  .post-reading__header {
    margin-bottom: var(--space-6);
  }

  .post-reading__author {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin: var(--space-4) 0 0;
  }

  .post-reading__userpic,
  .post-reading__userpic .userpic-image,
  .post-reading__userpic .userpic-placeholder {
    width: 4rem;
    height: 4rem;
  }

  .post-reading__userpic {
    flex: 0 0 4rem;
    overflow: hidden;
    border-radius: 50%;
    line-height: 0;
  }

  .post-reading__byline {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--space-1);
    min-width: 0;
    margin: 0;
    color: var(--color-text-muted);
    font-size: var(--text-xs);
  }

  body:not(.error-layout) .post-reading__author-link {
    color: var(--color-accent);
    font-weight: 800;
    letter-spacing: var(--journal-meta-letter-spacing);
    overflow-wrap: anywhere;
    text-decoration: none;
    text-transform: var(--journal-meta-transform);
  }

  .post-reading__timestamp,
  .post-edited-indicator {
    color: var(--color-text-muted);
  }

  .post-reading__title {
    max-width: 18ch;
    margin: 0;
    font-size: var(--text-page-title);
    font-weight: 700;
    letter-spacing: -0.06em;
    line-height: 0.94;
  }

  .post-reading__title--untitled {
    color: var(--color-text-muted);
  }

  .post-reading__status {
    margin: var(--space-4) 0 0;
  }

  .post-reading__metadata {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-4);
    margin: var(--space-4) 0 0;
    color: var(--color-text-muted);
  }

  .post-pin-indicator {
    margin: 0;
  }

  .post-reading__content-warning,
  .post-status {
    margin: var(--space-5) 0 0;
    padding: var(--space-3) var(--space-4);
    border-left: 3px solid var(--color-accent);
    background: var(--color-surface);
    font-size: var(--text-sm);
  }

  .post-status p {
    margin: 0;
  }

  .post-status p + p {
    margin-top: var(--space-2);
  }

  .post-reading__body {
    font-family: var(--font-reading);
    font-size: clamp(1.0625rem, 2vw, 1.1875rem);
    line-height: var(--leading-copy);
  }

  .post-body > :first-child {
    margin-top: 0;
  }

  .post-body > :last-child {
    margin-bottom: 0;
  }

  .post-body p,
  .post-body ul,
  .post-body ol,
  .post-body blockquote,
  .post-body pre,
  .post-body table,
  .post-body figure {
    margin-block: 1.35em;
  }

  .post-body h2,
  .post-body h3,
  .post-body h4 {
    margin: 1.8em 0 0.55em;
    letter-spacing: -0.025em;
    line-height: 1.15;
  }

  .post-body h2 {
    font-size: clamp(1.75rem, 4vw, 2.25rem);
  }

  .post-body h3 {
    font-size: clamp(1.35rem, 3vw, 1.7rem);
  }

  /* Card bodies demote their headings below the card title
     (specs/post-cut.md §6.2), so a title at h2 carries body h3–h6 and one
     at h3 carries h4–h6. Each level takes a fixed share of the distance
     from the body text (1em of the excerpt) up to the card title, so the
     levels spread apart as far as the title allows and never reach it or
     drop below the text. Where the title is barely larger than the text
     (Journal below wide screens), the levels sit close together and their
     shared bold weight sets them apart from the text.
     Presets may change the shares. The post page keeps the scale above. */
  .post-card__excerpt :is(h3, h4, h5, h6) {
    font-size: calc(1em + (var(--card-title-size) - 1em) * var(--card-heading-share));
  }

  .post-card__excerpt h3 {
    --card-heading-share: var(--card-h3-share, 0.45);
  }

  .post-card__excerpt h4 {
    --card-heading-share: var(--card-h4-share, 0.28);
  }

  .post-card__excerpt h5 {
    --card-heading-share: var(--card-h5-share, 0.13);
  }

  .post-card__excerpt h6 {
    --card-heading-share: var(--card-h6-share, 0);
  }

  /* The browser gives h5 and h6 their own margins and no line height; in a
     card they take those of the headings above. */
  .post-card__excerpt :is(h5, h6) {
    margin: 1.8em 0 0.55em;
    line-height: 1.15;
  }

  .post-body ul,
  .post-body ol {
    padding-inline-start: 1.4em;
  }

  .post-body li + li {
    margin-top: 0.4em;
  }

  .post-body blockquote {
    margin-inline: 0;
    padding: var(--space-1) 0 var(--space-1) var(--space-5);
    border-left: 2px solid var(--color-border-strong);
    color: var(--color-text-muted);
    font-style: italic;
  }

  .post-body pre {
    max-width: 100%;
    overflow-x: auto;
  }

  /* K17 — the table itself cannot be the scroll container: it sizes to its
     content, so `overflow-x` on it leaves the page scrolling sideways
     instead. The bounded region is the wrapper `sanitize_post_body` adds,
     which is why this is not a `.post-body` rule: the same scroller wraps
     tables in comment bodies, which are not `.post-body`. */
  .post-table-scroll {
    position: relative;
    max-width: 100%;
    margin-block: 1.35em;
    overflow-x: auto;
    border: var(--border-thin) solid var(--color-border-strong);
    background: var(--color-surface);
    -webkit-overflow-scrolling: touch;
  }

  .post-table-scroll > table {
    margin-block: 0;
  }

  /* No-JS fallback: at narrow widths the hint shows on the heuristic that a
     body table is likely to overflow. The controller replaces the guess
     with a measurement and takes the hint back over. */
  .post-table-scroll__hint {
    display: none;
    margin: 0;
    padding: var(--space-2) var(--space-3);
    border-bottom: var(--border-thin) solid var(--color-border);
    color: var(--color-text-muted);
    font-size: var(--text-xs);
    font-style: italic;
  }

  @media (max-width: 50rem) {
    .post-table-scroll__hint {
      display: block;
    }
  }

  .post-table-scroll.post-table-scroll--js .post-table-scroll__hint {
    display: none;
  }

  .post-table-scroll.post-table-scroll--overflowing .post-table-scroll__hint {
    display: block;
  }

  .post-table-scroll::before,
  .post-table-scroll::after {
    content: "";
    position: absolute;
    z-index: 2;
    top: 0;
    bottom: 0;
    width: 1.5rem;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.12s ease;
  }

  .post-table-scroll::before {
    left: 0;
    background: linear-gradient(
      to right,
      color-mix(in srgb, var(--color-surface) 95%, transparent),
      transparent
    );
  }

  .post-table-scroll::after {
    right: 0;
    background: linear-gradient(
      to left,
      color-mix(in srgb, var(--color-surface) 95%, transparent),
      transparent
    );
  }

  .post-table-scroll.post-table-scroll--overflowing:not(
    .post-table-scroll--at-start
  )::before,
  .post-table-scroll.post-table-scroll--overflowing:not(
    .post-table-scroll--at-end
  )::after {
    opacity: 1;
  }

  .post-body pre {
    padding: var(--space-4);
    border: var(--border-thin) solid var(--color-border);
    background: var(--color-surface);
    font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
    font-size: var(--text-sm);
    line-height: 1.55;
    white-space: pre;
  }

  .post-body :not(pre) > code {
    padding: 0.08em 0.25em;
    background: var(--color-surface);
    font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
    font-size: 0.9em;
  }

  .post-body img {
    display: block;
    margin-inline: auto;
  }

  .post-body hr {
    width: 25%;
    margin: var(--space-7) auto;
    border: 0;
    border-top: var(--border-thin) solid var(--color-border-strong);
  }

  .post-body__reveal,
  .post-body__reveal-no-js a {
    display: inline-flex;
    align-items: center;
    min-height: 2.5rem;
    margin-bottom: var(--space-4);
    padding: var(--space-2) var(--space-4);
    border: var(--border-thin) solid var(--color-border-strong);
    border-radius: var(--radius-small);
    background: var(--color-surface);
    color: var(--color-text);
    font-family: var(--font-interface);
    font-size: var(--text-sm);
    font-weight: 700;
    cursor: pointer;
  }

  .post-body__reveal[hidden] {
    display: none;
  }

  .post-reading__footer {
    display: grid;
    gap: var(--space-4);
    margin-top: var(--space-7);
    padding-top: var(--space-4);
    border-top: var(--border-thin) solid var(--color-border);
    font-size: var(--text-sm);
  }

  .post-tags {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--space-2);
    min-width: 0;
    color: var(--color-text-muted);
  }

  .post-tags__list {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-3);
    min-width: 0;
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .post-tags__item,
  .post-tags__item a {
    min-width: 0;
    overflow-wrap: anywhere;
  }

  .post-reading__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
  }

  .post-reading__actions form,
  .post-reading__secondary-action,
  .post-quote-unavailable {
    margin: 0;
  }

  @media (max-width: 430px) {
    .post-card {
      padding-block: var(--space-5);
    }

    .post-card__header {
      align-items: flex-start;
    }

    .post-card__title {
      max-width: 20ch;
    }

    .post-card__excerpt {
      font-size: 1.0625rem;
    }

    .post-reading__body {
      font-size: 1.0625rem;
    }
  }
}
