/*
  Portal default theme — hand-written, framework-free CSS.

  This stylesheet is the whole look of the default public surface. It is
  plain CSS on purpose: no Tailwind, no build step. Edit it directly and
  reload — the file is served as-is from
  /themes/<slug>/assets/theme.css. Themes that want a utility framework
  (Tailwind, etc.) may bring their own; the portal does not require one.

  Structure:
    1. Design tokens (:root custom properties) — change these first.
    2. Reset + base elements.
    3. Layout: page frame, header, footer, navigation.
    4. Components: cards, buttons, badges, tables, forms, avatars,
       reactions, gallery, lightbox, command palette.
    5. Rich-text output (.post-body) + Edica blocks.
*/

/* ------------------------------------------------------------------ *
 * 1. Design tokens
 * ------------------------------------------------------------------ */
:root {
  /* type */
  --font-sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
  --leading: 1.6;

  /* neutral surfaces + text */
  --bg: #fafaf9;
  --surface: #ffffff;
  --surface-2: #f5f5f4;
  --text: #1c1917;
  --text-muted: #57534e;
  --text-subtle: #78716c;
  --border: #e7e5e4;
  --border-strong: #d6d3d1;

  /* accent (brand) */
  --accent: #ea580c;
  --accent-hover: #c2410c;
  --accent-soft: #fff7ed;
  --accent-soft-text: #9a3412;
  --accent-ring: #fdba74;

  /* status */
  --danger: #b91c1c;
  --danger-border: #ef4444;
  --danger-soft: #fef2f2;
  --warn-text: #b45309;
  --warn-soft: #fffbeb;
  --warn-border: rgba(180, 83, 9, 0.25);
  --online: #10b981;

  /* code */
  --code-bg: #1c1917;
  --code-text: #f5f5f4;

  /* shape */
  --radius-sm: 0.375rem;
  --radius: 0.5rem;
  --radius-lg: 0.75rem;
  --radius-xl: 1rem;
  --radius-full: 9999px;

  /* elevation */
  --shadow-sm: 0 1px 2px rgb(0 0 0 / 0.05);
  --shadow: 0 1px 3px rgb(0 0 0 / 0.08), 0 1px 2px rgb(0 0 0 / 0.05);
  --shadow-lg: 0 10px 25px -5px rgb(0 0 0 / 0.15), 0 8px 10px -6px rgb(0 0 0 / 0.10);

  /* rhythm + widths */
  --gap: 1.5rem;
  --pad-x: 1.5rem;
  --maxw: 80rem;
  --maxw-wide: 64rem;
  --maxw-read: 48rem;
  --header-h: 4rem;
}

/* ------------------------------------------------------------------ *
 * 2. Reset + base
 * ------------------------------------------------------------------ */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  /* Reserve the scrollbar gutter so switching between short and tall
     pages never shifts the centered layout sideways. */
  overflow-y: scroll;
}

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  font-family: var(--font-sans);
  font-size: 1rem;
  line-height: var(--leading);
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4, h5, h6, p, figure { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }
img, svg, video { display: block; max-width: 100%; }
img { height: auto; }
a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent-hover); }
button { font: inherit; color: inherit; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
[x-cloak] { display: none !important; }

/* inline icon sizing — SVGs carry stroke="currentColor" so they tint
   with the surrounding text. */
.icon { width: 1.25rem; height: 1.25rem; flex: none; display: inline-block; }
.icon-sm { width: 1rem; height: 1rem; }
.icon-lg { width: 1.5rem; height: 1.5rem; }

/* ------------------------------------------------------------------ *
 * 3. Layout
 * ------------------------------------------------------------------ */
.container {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--pad-x);
}
.container--wide { max-width: var(--maxw-wide); }
.container--read { max-width: var(--maxw-read); }
.container--full { max-width: none; }

.site-main { flex: 1 0 auto; }
.site-main > .container { padding-block: 2rem; }

/* vertical rhythm helper — replaces per-element margins for a stacked
   column of blocks. */
.stack { display: flex; flex-direction: column; gap: var(--gap); }
.stack--xs { gap: 0.5rem; }
.stack--sm { gap: 1rem; }
.stack--lg { gap: 2rem; }

/* headings */
.page-title { font-size: 1.875rem; font-weight: 700; letter-spacing: -0.02em; color: var(--text); line-height: 1.25; }
.page-title--sm { font-size: 1.5rem; }
/* a blog post's own title has to outrank the headings in its body,
   which reach 1.75rem; size alone carries that, so it scales with the
   viewport rather than wrapping a long title into a wall on a phone. */
.page-title--lg { font-size: clamp(2rem, 1.4rem + 2.5vw, 2.75rem); line-height: 1.15; letter-spacing: -0.025em; }
.page-subtitle { margin-top: 0.5rem; color: var(--text-muted); }
.section-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.breadcrumb { font-size: 0.875rem; color: var(--text-subtle); }
.breadcrumb a { color: inherit; }
.breadcrumb a:hover { text-decoration: underline; }
.muted { color: var(--text-muted); }
.meta { font-size: 0.875rem; color: var(--text-subtle); display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.meta__name { font-weight: 500; color: var(--text-muted); }
.eyebrow { font-size: 0.75rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-subtle); }

/* --- header --- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 40;
  background: rgb(255 255 255 / 0.8);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--border);
}
.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  min-height: var(--header-h);
  padding-block: 0.5rem;
}
.site-header__left { display: flex; align-items: center; gap: 1.5rem; min-width: 0; }

.brand { display: flex; flex-direction: column; line-height: 1.1; color: var(--text); min-width: 0; }
.brand:hover { color: var(--accent); }
.brand__logo { height: 2rem; width: auto; }
.brand__name { font-weight: 600; letter-spacing: -0.01em; }
.brand__tagline { font-size: 0.75rem; color: var(--text-subtle); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.nav { display: flex; align-items: center; gap: 0.25rem; flex-wrap: wrap; }
.nav__link {
  display: inline-flex; align-items: center; gap: 0.25rem;
  padding: 0.375rem 0.75rem; border-radius: var(--radius-sm);
  font-size: 0.875rem; color: var(--text-muted); cursor: pointer;
}
.nav__link:hover { background: var(--surface-2); color: var(--text); }

.header-actions { display: flex; align-items: center; gap: 0.75rem; }

/* Language switcher — one short code per language, the current one
   marked. Codes rather than full names: the header is already busy,
   and a reader looking for their own language recognises "de" as
   quickly as "Deutsch". The full name is on the title attribute. */
.lang-switch { display: inline-flex; align-items: center; gap: 0.125rem; }
.lang-switch__item {
  padding: 0.25rem 0.4rem; border-radius: var(--radius-sm);
  font-size: 0.75rem; font-weight: 500; text-transform: uppercase;
  letter-spacing: 0.03em; color: var(--text-muted); text-decoration: none;
}
.lang-switch__item:hover { background: var(--surface-2); color: var(--text); }
.lang-switch__item--current { background: var(--surface-2); color: var(--text); }

.iconbtn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.25rem; height: 2.25rem; border-radius: var(--radius-full);
  color: var(--text-muted); background: none; border: 0; cursor: pointer;
}
.iconbtn:hover { background: var(--surface-2); color: var(--text); }
.iconbtn--bell { position: relative; }

.badge-count {
  position: absolute; top: -0.125rem; right: -0.125rem;
  min-width: 1rem; height: 1rem; padding: 0 0.25rem;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--radius-full); background: var(--accent);
  color: #fff; font-size: 10px; font-weight: 600; line-height: 1;
}

.ws-dot {
  display: inline-block; width: 0.5rem; height: 0.5rem;
  border-radius: var(--radius-full); background: var(--border-strong);
  vertical-align: middle; transition: background-color 0.2s;
}
[data-ws-status="online"].ws-dot { background: var(--online); }

/* --- dropdown (<details>) shared by nav + user menu --- */
.dropdown { position: relative; }
.dropdown > summary { list-style: none; cursor: pointer; }
.dropdown > summary::-webkit-details-marker { display: none; }
.chevron { transition: transform 0.15s; }
.dropdown[open] .chevron { transform: rotate(180deg); }

.menu {
  position: absolute; right: 0; margin-top: 0.5rem; min-width: 11rem;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-lg);
  padding-block: 0.25rem; z-index: 50;
}
.menu-item {
  display: flex; align-items: center; gap: 0.75rem; width: 100%;
  padding: 0.5rem 1rem; font-size: 0.875rem; color: var(--text-muted);
  background: none; border: 0; cursor: pointer; text-align: left;
}
.menu-item:hover { background: var(--surface-2); color: var(--text); }

/* user menu trigger + avatar open-state tint */
.user-menu__trigger {
  display: flex; align-items: center; gap: 0.5rem;
  padding: 0.25rem 0.5rem; border-radius: var(--radius-full);
}
.user-menu__trigger:hover { background: var(--surface-2); }
.user-menu__name { font-size: 0.875rem; font-weight: 500; color: var(--text-muted); }
.dropdown[open] .avatar--interactive { background: var(--accent-soft); color: var(--accent); }
.signin-link { display: inline-flex; align-items: center; gap: 0.5rem; font-size: 0.875rem; font-weight: 500; color: var(--text-muted); }
.signin-link:hover { color: var(--accent); }

/* --- footer --- */
.site-footer { margin-top: 4rem; border-top: 1px solid var(--border); background: var(--surface); }
.site-footer__inner { padding-block: 2.5rem; }
.footer-cols { display: grid; grid-template-columns: repeat(2, 1fr); gap: 2rem; }
.footer-col__title { font-size: 0.875rem; font-weight: 600; color: var(--text); margin-bottom: 0.75rem; }
.footer-links { display: flex; flex-direction: column; gap: 0.5rem; font-size: 0.875rem; }
.footer-links a { color: var(--text-muted); }
.footer-links a:hover { color: var(--accent); }
.footer-bottom {
  display: flex; flex-direction: column; gap: 0.25rem;
  margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid var(--border);
  font-size: 0.75rem; color: var(--text-subtle);
}
.footer-bottom--bare { margin-top: 0; padding-top: 0; border-top: 0; }
.footer-bottom a:hover { text-decoration: underline; }
@media (min-width: 640px) {
  .footer-cols { grid-template-columns: repeat(3, 1fr); }
  .footer-bottom { flex-direction: row; align-items: center; justify-content: space-between; }
}
@media (min-width: 768px) { .footer-cols { grid-template-columns: repeat(4, 1fr); } }

/* ------------------------------------------------------------------ *
 * 4. Components
 * ------------------------------------------------------------------ */

/* cards + tiles */
.card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-lg); padding: 1.5rem; box-shadow: var(--shadow-sm);
}
.card--flush { padding: 0; overflow: hidden; }
.card--error { border-color: var(--danger-border); }

.tile {
  display: block; background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-lg); padding: 1.5rem; color: inherit;
  box-shadow: var(--shadow-sm);
  transition: border-color 0.15s, box-shadow 0.15s;
}
.tile:hover { border-color: var(--accent-ring); box-shadow: var(--shadow); }
.tile__title { font-weight: 600; color: var(--text); }
.tile:hover .tile__title { color: var(--accent); }
.tile__desc { margin-top: 0.5rem; font-size: 0.875rem; color: var(--text-muted); }

.card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr)); gap: var(--gap); }

.empty {
  border: 1px dashed var(--border-strong); border-radius: var(--radius-lg);
  background: var(--surface); padding: 2.5rem; text-align: center; color: var(--text-muted);
}

/* buttons */
.btn {
  display: inline-flex; align-items: center; gap: 0.5rem;
  padding: 0.5rem 1rem; border-radius: var(--radius);
  font-size: 0.875rem; font-weight: 600; white-space: nowrap; cursor: pointer;
  border: 1px solid transparent; background: var(--accent); color: #fff;
  box-shadow: var(--shadow-sm); transition: background-color 0.15s, color 0.15s, border-color 0.15s;
}
.btn:hover { background: var(--accent-hover); color: #fff; }
.btn--ghost { background: transparent; color: var(--text-muted); border-color: var(--border-strong); box-shadow: none; }
.btn--ghost:hover { background: var(--surface-2); color: var(--text); }
.btn--link { background: none; border: 0; box-shadow: none; padding: 0; font-weight: 500; color: var(--accent); }
.btn--link:hover { background: none; color: var(--accent-hover); }

/* badges + tags */
.badge {
  display: inline-flex; align-items: center; border-radius: var(--radius-full);
  padding: 0.125rem 0.5rem; font-size: 0.75rem; font-weight: 500; line-height: 1.4;
}
.tag { background: var(--surface-2); color: var(--text-muted); }
.badge--warn { background: var(--warn-soft); color: var(--warn-text); box-shadow: inset 0 0 0 1px var(--warn-border); }
.badge--accent { background: var(--accent-soft); color: var(--accent-soft-text); }
.tags { display: flex; flex-wrap: wrap; gap: 0.375rem; }

/* segmented view toggle */
.seg { display: inline-flex; align-items: center; border-radius: var(--radius-full); padding: 0.25rem 0.625rem; font-size: 0.75rem; font-weight: 500; background: var(--surface-2); color: var(--text-muted); }
.seg:hover { background: var(--border); }
.seg--on { background: var(--accent-soft); color: var(--accent-soft-text); font-weight: 600; }

/* tables */
.table-wrap { overflow-x: auto; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); }
.table { width: 100%; border-collapse: collapse; font-size: 0.875rem; }
.table thead { background: var(--surface-2); }
.table th { text-align: left; padding: 0.5rem 1rem; font-size: 0.75rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-subtle); }
.table td { padding: 0.75rem 1rem; border-top: 1px solid var(--border); color: var(--text-muted); vertical-align: top; }
.table tbody tr:hover { background: var(--surface-2); }
.table a { color: var(--text); }
.table a:hover { color: var(--accent); }
.row--dim { opacity: 0.6; }

/* forms */
.label { display: block; font-size: 0.875rem; font-weight: 500; color: var(--text-muted); margin-bottom: 0.25rem; }
.input, .textarea {
  display: block; width: 100%; padding: 0.5rem 0.75rem; font: inherit; font-size: 0.875rem;
  color: var(--text); background: var(--surface); border: 1px solid var(--border-strong);
  border-radius: var(--radius);
}
.input:focus, .textarea:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.input--error { border-color: var(--danger-border); }
.field-error { margin-top: 0.25rem; font-size: 0.75rem; color: var(--danger); }
.field-help { margin-top: 0.25rem; font-size: 0.75rem; color: var(--text-subtle); }
.form-error { border-radius: var(--radius); background: var(--danger-soft); padding: 0.5rem 0.75rem; font-size: 0.875rem; color: var(--danger); }

/* Thread properties dialog — the author's (or a moderator's) settings for
   their own thread, opened from the thread header. Native <dialog>, so
   the browser handles the backdrop, focus and Escape; this is only the
   look. */
.modal { max-width: 32rem; width: calc(100% - 2rem); border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); color: var(--text); padding: 1.25rem; }
.modal::backdrop { background: rgba(0, 0, 0, 0.45); }
.modal__title { margin: 0; font-size: 1.05rem; font-weight: 600; }
.modal__actions { display: flex; justify-content: flex-end; gap: 0.5rem; }
.checkline { display: flex; align-items: center; gap: 0.5rem; font-size: 0.9375rem; }
.btn--sm { padding: 0.25rem 0.6rem; font-size: 0.8125rem; }
.thread-flags { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }

/* avatars */
.avatar {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.25rem; height: 2.25rem; border-radius: var(--radius-full);
  background: var(--surface-2); color: var(--text-subtle); overflow: hidden; flex: none;
}
img.avatar { object-fit: cover; }
.avatar--sm { width: 1.5rem; height: 1.5rem; }
.avatar--md { width: 1.75rem; height: 1.75rem; }
.avatar--lg { width: 2.5rem; height: 2.5rem; }
.avatar .icon { width: 1.25rem; height: 1.25rem; }

/* posts (thread / comments) */
.post--dim { opacity: 0.6; }
.post__head { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; margin-bottom: 0.75rem; font-size: 0.875rem; color: var(--text-subtle); }
.post__author { display: flex; align-items: center; gap: 0.5rem; }

/* live arrivals — the sticky "n new …" pill and the flash on the items
   it reveals. The pill sits below the header so it stays reachable while
   reading; [hidden] wins over the flex display until a frame arrives. */
.live-banner {
  position: sticky; top: calc(var(--header-h) + 0.5rem); z-index: 20;
  align-self: center; display: inline-flex; align-items: center; gap: 0.375rem;
  border-radius: var(--radius-full); border: 1px solid var(--accent-ring);
  background: var(--accent-soft); color: var(--accent-soft-text);
  padding: 0.375rem 0.875rem; font-size: 0.875rem; font-weight: 500;
  cursor: pointer; box-shadow: var(--shadow);
}
.live-banner:hover { background: var(--accent); border-color: var(--accent); color: #fff; }
.live-banner[hidden] { display: none; }

.live-new { animation: live-flash 2s ease-out; }
tr.live-new { animation: live-flash-row 2s ease-out; }
@keyframes live-flash {
  0%   { box-shadow: 0 0 0 2px var(--accent); }
  100% { box-shadow: 0 0 0 2px transparent; }
}
@keyframes live-flash-row {
  0%   { background: var(--accent-soft); }
  100% { background: transparent; }
}
@media (prefers-reduced-motion: reduce) {
  .live-new, tr.live-new { animation: none; box-shadow: 0 0 0 2px var(--accent-ring); }
}

/* thread + reply composer */
.composer { display: flex; gap: 1rem; padding-block: 1.25rem; border-block: 1px solid var(--border); }
/* --flush drops the rules and padding for a composer already inside a card */
.composer--flush { padding-block: 0; border-block: 0; }
.composer__body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.75rem; }
.composer__line { display: flex; align-items: center; gap: 0.5rem; }
/* the title (or byline) row carries the submit button, so the primary
   action stays next to the first field instead of below the fold */
.composer__head { display: flex; align-items: flex-end; gap: 0.75rem; }
.composer__head--baseline { align-items: center; }
.composer__grow { flex: 1; min-width: 0; }
.composer__head .btn { flex: none; }
.composer__field { min-width: 0; }
@media (max-width: 40rem) {
  .composer__head { flex-wrap: wrap; }
  .composer__head .btn { width: 100%; }
}

/* reactions */
.reactions { margin-top: 1rem; display: flex; flex-wrap: wrap; gap: 0.375rem; }
/* The post foot carries the reaction bar and the quote control on one
   row; .reactions brings its own top margin, which would push the two
   out of line inside a flex row. */
.post__foot { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; flex-wrap: wrap; margin-top: 1rem; }
.post__foot .reactions { margin-top: 0; }
.post__quote { flex: none; }
.post__foot--end { justify-content: flex-end; }
.reaction {
  display: inline-flex; align-items: center; gap: 0.25rem;
  border-radius: var(--radius-full); border: 1px solid var(--border);
  background: var(--surface); color: var(--text-muted);
  padding: 0.25rem 0.625rem; font-size: 0.875rem; cursor: pointer; transition: background-color 0.15s;
}
.reaction:hover { background: var(--surface-2); }
.reaction--on { border-color: var(--accent-ring); background: var(--accent-soft); color: var(--accent-soft-text); }
.reaction__count { font-size: 0.75rem; font-weight: 500; font-variant-numeric: tabular-nums; }

/* blog post cards */
.post-card__img { width: 100%; height: 12rem; object-fit: cover; }
.post-card__body { padding: 1.5rem; }
.post-card__title { font-size: 1.25rem; font-weight: 600; letter-spacing: -0.01em; }
.post-card__title a { color: var(--text); }
.post-card__title a:hover { color: var(--accent); }

/* older / newer links under a blog post. Two fixed columns so a lone
   "Newer" keeps to the right instead of sliding into the older slot;
   on a phone the two stack. */
.post-nav { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; padding-top: 1.5rem; border-top: 1px solid var(--border); }
.post-nav__link {
  display: flex; flex-direction: column; gap: 0.25rem; padding: 1rem 1.25rem;
  border: 1px solid var(--border); border-radius: var(--radius-lg);
  background: var(--surface); color: var(--text); transition: border-color 0.15s;
}
.post-nav__link:hover { border-color: var(--accent-ring); }
.post-nav__link--older { grid-column: 1; }
.post-nav__link--newer { grid-column: 2; text-align: right; }
.post-nav__label { font-size: 0.875rem; color: var(--text-subtle); }
.post-nav__title { font-weight: 600; }
@media (max-width: 640px) {
  .post-nav { grid-template-columns: 1fr; }
  .post-nav__link--older, .post-nav__link--newer { grid-column: auto; }
}

/* the post toolbar (blog_post.liquid). On a wide screen the aside spans
   the article's full height in the gutter to its right, and the bar
   inside it sticks under the header, so it stays beside the text while
   the reader scrolls and stops where the article does. On a narrow one
   there is no gutter, so it becomes a pill in the corner. */
.post-layout { position: relative; }
.post-tools { position: fixed; right: 1rem; bottom: 1rem; z-index: 30; }
.post-tools__bar {
  display: flex; gap: 0.25rem; padding: 0.25rem;
  border: 1px solid var(--border); border-radius: var(--radius-full);
  background: var(--surface); box-shadow: var(--shadow-lg);
}
.post-tools__btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.5rem; height: 2.5rem; border: 0; border-radius: var(--radius-full);
  background: transparent; color: var(--text-muted); cursor: pointer;
  transition: background-color 0.15s, color 0.15s;
}
.post-tools__btn:hover { background: var(--surface-2); color: var(--text); }
.post-tools__btn--on { background: var(--warn-soft); color: var(--warn-text); }
.post-tools__btn--on:hover { background: var(--warn-soft); color: var(--warn-text); }
@media (min-width: 64rem) {
  .post-tools {
    position: absolute; top: 0; bottom: 0; right: auto;
    left: calc(50% + var(--maxw-read) / 2 + 1.5rem);
  }
  .post-tools__bar { position: sticky; top: calc(var(--header-h) + 1.5rem); flex-direction: column; }
}

/* gallery (collection grid) */
.gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr)); gap: 1rem; }
.gallery__item {
  display: block; overflow: hidden; border: 1px solid var(--border);
  border-radius: var(--radius-lg); background: var(--surface); color: inherit;
  box-shadow: var(--shadow-sm); padding: 0; text-align: left; cursor: pointer;
}
.gallery__thumb { aspect-ratio: 1 / 1; background: var(--surface-2); display: flex; align-items: center; justify-content: center; color: var(--text-subtle); }
.gallery__thumb img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.2s; }
.gallery__item:hover .gallery__thumb img { transform: scale(1.05); }
.gallery__cap { padding: 0.75rem; }
.gallery__name { font-size: 0.875rem; font-weight: 500; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.gallery__meta { margin-top: 0.125rem; font-size: 0.75rem; color: var(--text-subtle); }

/* lightbox */
.lightbox { position: fixed; inset: 0; z-index: 50; display: flex; align-items: center; justify-content: center; background: rgb(0 0 0 / 0.8); padding: 1rem; }
.lightbox__frame { position: relative; max-width: 72rem; max-height: 100%; }
.lightbox__img { max-height: 85vh; max-width: 100%; border-radius: var(--radius); box-shadow: var(--shadow-lg); object-fit: contain; background: #000; }
.lightbox__close {
  position: absolute; top: -0.75rem; right: -0.75rem;
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.25rem; height: 2.25rem; border-radius: var(--radius-full);
  background: var(--surface); color: var(--text-muted); border: 0; cursor: pointer; box-shadow: var(--shadow-lg);
}
.lightbox__close:hover { color: var(--text); }
.lightbox__cap { margin-top: 0.75rem; text-align: center; font-size: 0.875rem; color: #e7e5e4; }

/* command palette */
.cmdk { position: fixed; inset: 0; z-index: 60; display: flex; align-items: flex-start; justify-content: center; padding-top: 6rem; padding-inline: 1rem; background: rgb(0 0 0 / 0.3); }
.cmdk__panel { width: 100%; max-width: 32rem; overflow: hidden; border-radius: var(--radius-lg); background: var(--surface); border: 1px solid var(--border); box-shadow: var(--shadow-lg); }
.cmdk__search { display: flex; align-items: center; gap: 0.5rem; padding-inline: 1rem; border-bottom: 1px solid var(--border); }
.cmdk__search .icon { color: var(--text-subtle); }
.cmdk__input { width: 100%; padding-block: 0.75rem; border: 0; outline: none; background: none; font-size: 0.875rem; color: var(--text); }
.cmdk__input::placeholder { color: var(--text-subtle); }
.cmdk__list { max-height: 20rem; overflow-y: auto; padding-block: 0.25rem; }
.cmdk__item { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; padding: 0.625rem 1rem; font-size: 0.875rem; color: inherit; }
.cmdk__item:hover, .cmdk__item.is-active { background: var(--surface-2); }
.cmdk__title { display: block; font-weight: 500; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cmdk__sub { display: block; font-size: 0.75rem; color: var(--text-subtle); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cmdk__kind { flex: none; border-radius: var(--radius-sm); background: var(--surface-2); padding: 0.125rem 0.375rem; font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-subtle); }
.cmdk__empty { padding: 2rem 1rem; text-align: center; font-size: 0.875rem; color: var(--text-subtle); }

/* error page */
.error-page { max-width: var(--maxw-read); margin-inline: auto; padding-block: 4rem; text-align: center; }
.error-badge { display: inline-flex; align-items: center; justify-content: center; width: 3rem; height: 3rem; border-radius: var(--radius-full); background: var(--surface-2); color: var(--text-muted); margin-inline: auto; }

/* --- page canvas (styled pages) --- */
.page { max-width: var(--maxw-read); margin-inline: auto; }
.page--wide { max-width: var(--maxw-wide); }
.page--full { max-width: none; }
.page-canvas { background-size: cover; background-position: center; background-repeat: no-repeat; padding: 2rem 1.5rem; }
.page-canvas--pad-none { padding: 0; }
.page-canvas--pad-spacious { padding: 4rem 3rem; }
.page-canvas--full { min-height: 100vh; }

/* ------------------------------------------------------------------ *
 * 5. Rich-text output (.post-body) + Edica blocks
 *
 * The stored article/comment HTML is semantic (plain <p>, <h2>, <ul>,
 * <pre>, <blockquote>, <table>) plus a fixed set of edica-* classes.
 * These rules give that markup its reading typography. Kept token-based
 * so restyling the theme restyles article bodies too.
 * ------------------------------------------------------------------ */
.post-body { color: var(--text); }

/* A styled canvas carries its own text colour (inline, computed from the
   background it was given), so the article inside it has to inherit
   rather than reassert the theme's --text. Without this a white canvas
   on a dark theme renders light text on white. */
.page-canvas .post-body { color: inherit; }
.post-body > :first-child { margin-top: 0; }
.post-body > :last-child { margin-bottom: 0; }
.post-body p { margin-block: 1em; }
.post-body h1 { font-size: 1.75rem; font-weight: 700; line-height: 1.25; margin-block: 0.8em 0.4em; }
.post-body h2 { font-size: 1.5rem; font-weight: 700; line-height: 1.25; margin-block: 0.7em 0.35em; }
.post-body h3 { font-size: 1.25rem; font-weight: 600; line-height: 1.25; margin-block: 0.6em 0.3em; }
.post-body h4 { font-size: 1.1rem; font-weight: 600; line-height: 1.25; margin-block: 0.6em 0.3em; }
.post-body ul, .post-body ol { margin-block: 1em; padding-left: 1.5em; }
.post-body ul { list-style: disc; }
.post-body ol { list-style: decimal; }
.post-body li { margin-block: 0.25em; }
.post-body li > p { margin-block: 0.25em; }
.post-body blockquote { border-left: 3px solid var(--border-strong); padding-left: 1em; color: var(--text-muted); margin-block: 1em; }
/* A quote-reply reads as one unit: the attribution line naming whoever
   is quoted, then their words, then — one level deeper — whatever they
   were themselves quoting. The attribution sits directly on top and
   outside the rules; it is Portal's label, not part of what was said.
   The quoted lines carry their rules as background gradients rather
   than borders, so depth 2 can show both of them without needing a
   wrapper the flat block model has no way to give it.
   The blockquote rule below still covers a quote somebody wrote by
   hand, and older replies stored before depth roles existed. */
.post-body .edica-quote-attribution { font-size: 0.8125rem; color: var(--text-subtle); margin: 0 0 0.15rem; }
.post-body .edica-quote-attribution + blockquote { margin: 0 0 1em; font-style: italic; }
.post-body .edica-quote-1,
.post-body .edica-quote-2,
.post-body .edica-quote-attribution-1,
.post-body .edica-quote-attribution-2 {
  margin: 0;
  color: var(--text-muted);
  font-style: italic;
  background-repeat: no-repeat;
  background-image: linear-gradient(var(--border-strong), var(--border-strong));
  background-size: 3px 100%;
  background-position: 0 0;
}
/* rem, not em: the attribution lines are smaller, and an em indent
   would scale with their own font-size and fall out of line with the
   quoted words at the same level. */
.post-body .edica-quote-1,
.post-body .edica-quote-attribution-1 { padding-left: 1rem; }
.post-body .edica-quote-2,
.post-body .edica-quote-attribution-2 {
  padding-left: 2rem;
  background-image: linear-gradient(var(--border-strong), var(--border-strong)), linear-gradient(var(--border-strong), var(--border-strong));
  background-size: 3px 100%, 3px 100%;
  background-position: 0 0, 1rem 0;
}
/* an attribution stays a label wherever it sits, so a nested one reads
   at the same size as the one on top rather than as quoted words. */
.post-body .edica-quote-attribution-1,
.post-body .edica-quote-attribution-2 { font-size: 0.8125rem; }
/* the run of quoted lines is flush, so the rules read as unbroken; the
   member's own words below get their spacing back. */
.post-body .edica-quote-1 + :not([class^="edica-quote-"]),
.post-body .edica-quote-2 + :not([class^="edica-quote-"]) { margin-top: 1em; }
.post-body code { background: var(--surface-2); padding: 0.1em 0.35em; border-radius: 0.25rem; font-family: var(--font-mono); font-size: 0.9em; }
.post-body pre { background: var(--code-bg); color: var(--code-text); padding: 1em; border-radius: var(--radius); overflow-x: auto; margin-block: 1em; }
.post-body pre code { background: transparent; padding: 0; color: inherit; font-size: inherit; }
.post-body a { color: var(--accent); text-decoration: underline; }
.post-body a:hover { color: var(--accent-hover); }
.post-body hr { border: 0; border-top: 1px solid var(--border); margin-block: 1.5em; }
.post-body img { max-width: 100%; height: auto; border-radius: var(--radius); }
.post-body table { width: 100%; border-collapse: collapse; margin-block: 1em; font-size: 0.95em; }
.post-body th, .post-body td { border: 1px solid var(--border); padding: 0.5em 0.75em; text-align: left; }
.post-body th { background: var(--surface-2); font-weight: 600; }

/* File-download chip: any link to /files/<nid>/raw that is not an image. */
.post-body a[href^="/files/"][href$="/raw"]:not(:has(img)) {
  display: inline-flex; align-items: center; gap: 0.4em;
  padding: 0.2em 0.55em; border-radius: var(--radius-sm); font-weight: 600;
  color: #0284c7; background: #f0f9ff; text-decoration: none;
  transition: background-color 0.15s, color 0.15s;
}
.post-body a[href^="/files/"][href$="/raw"]:not(:has(img)):hover { color: #0369a1; background: #e0f2fe; }
.post-body a[href^="/files/"][href$="/raw"]:not(:has(img))::before {
  content: ''; display: inline-block; width: 1em; height: 1em; background-color: currentColor;
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2 -2v-2'/><path d='M7 11l5 5l5 -5'/><path d='M12 4l0 12'/></svg>") center / contain no-repeat;
  mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2 -2v-2'/><path d='M7 11l5 5l5 -5'/><path d='M12 4l0 12'/></svg>") center / contain no-repeat;
}

/* Edica image + attachment + columns blocks. */
.post-body figure.image { margin-block: 1em; }
.post-body figure.image img { max-width: 100%; height: auto; border-radius: var(--radius); display: block; }
.post-body figure.image figcaption { margin-top: 0.35em; font-size: 0.85em; color: var(--text-subtle); }
.edica-image { margin: 1rem 0; }
.edica-image--align-center { text-align: center; }
.edica-image--align-right { text-align: right; }
.edica-image--align-center img { margin-inline: auto; }
.edica-image--align-right img { margin-inline-start: auto; margin-inline-end: 0; }
.edica-image--align-wide img { width: 100%; height: auto; }
/* Size, corners and frame as the author set them in the editor. Sizes
   are a share of the column, the editor's own percentages; a labelled
   image sizes its media box instead, and the picture fills that. */
.edica-image--size-sm img, .edica-image--size-sm .edica-image__media { width: 30%; }
.edica-image--size-md img, .edica-image--size-md .edica-image__media { width: 50%; }
.edica-image--size-lg img, .edica-image--size-lg .edica-image__media { width: 75%; }
.edica-image--size-full img, .edica-image--size-full .edica-image__media { width: 100%; }
.edica-image[class*="--size-"] .edica-image__media img { width: 100%; }
/* In a column the column owns the width: a share of the column would
   multiply with the split, so sm/md/lg draw at natural size there, as
   the editor shows them. */
.edica-columns__col :is(.edica-image--size-sm, .edica-image--size-md, .edica-image--size-lg) :is(img, .edica-image__media, .edica-image__media img) { width: auto; }
.edica-image--round-none img { border-radius: 0; }
.edica-image--round-lg img { border-radius: var(--radius-xl); }
.edica-image--frame-border img { border: 1px solid var(--border); }
.edica-image--frame-shadow img { box-shadow: var(--shadow); }
/* AI disclosure: a chip on the picture's bottom edge that always reads
   "AI" — a label that needs a hover discloses nothing — and unfolds in
   place to "AI-generated" / "AI-edited" on hovering the picture, on
   keyboard focus, or on a tap (the chip takes focus). The detail is
   clipped, never hidden, so a screen reader hears the whole phrase.
   The chip and the picture share a box the picture's size, so the chip
   sits against its edges. */
.edica-image__media { position: relative; display: inline-block; max-width: 100%; vertical-align: top; }
.edica-image__media img { display: block; }
.edica-image--align-wide .edica-image__media { width: 100%; }
/* The bar spans the picture's width and is the container the chip is
   sized against: full size from a ~320px picture up, shrinking with a
   smaller one so it never covers the picture it labels. Padding and
   corners are in em so the chip keeps its shape at every size. */
.edica-image__ai-bar {
  position: absolute; left: 0; right: 0; bottom: 0;
  container-type: inline-size; pointer-events: none;
}
.edica-image__ai {
  position: absolute; bottom: 0;
  left: 0.5rem; left: clamp(0.25rem, 2.5cqi, 0.5rem);
  padding: 0.18em 0.57em; border-radius: 0.36em 0.36em 0 0;
  background: rgb(0 0 0 / 0.85); color: #fff;
  font-size: 0.7rem; font-size: clamp(0.5rem, 3.5cqi, 0.7rem);
  font-weight: 600; line-height: 1.4; letter-spacing: 0.02em; white-space: nowrap;
  pointer-events: auto; cursor: default;
}
.edica-image__ai:focus { outline: none; }
.edica-image__ai:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.edica-image__ai-more {
  display: inline-block; vertical-align: bottom; overflow: hidden;
  max-width: 0; transition: max-width 0.2s ease;
}
.edica-image__media:hover .edica-image__ai-more,
.edica-image__ai:focus .edica-image__ai-more { max-width: 6em; }
@media (prefers-reduced-motion: reduce) { .edica-image__ai-more { transition: none; } }
/* clear of a very rounded corner, as the editor places it. */
.edica-image--round-lg .edica-image__ai { left: clamp(0.25rem, 5cqi, var(--radius-xl)); }
/* Paragraph roles. A post's opening paragraph may carry one of these —
   the editor allows one or the other, never both — and they answer two
   different questions, so they should not look alike.

   The abstract is the standfirst that opens the piece: the same voice as
   the body, set larger, no frame. The TL;DR is the reader who wants the
   answer and not the article: set apart, tinted, deliberately compact. */
.post-body .edica-abstract {
  font-size: 1.15em;
  line-height: 1.5;
  color: var(--text-muted);
}

.post-body .edica-tldr {
  margin-block: 1.25em;
  padding: 0.75rem 1rem;
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-sm);
  background: var(--accent-soft);
  color: var(--accent-soft-text);
  font-size: 0.95em;
}

/* A row's looks are named steps the editor stores; the pixels are the
   theme's. Every gap measurement derives from --edica-columns-gap, so the
   divider stays on the seam at every step. Columns stretch to the tallest
   unless the author lined them up otherwise, as in the editor. */
.edica-columns { --edica-columns-gap: 1.5rem; display: flex; gap: var(--edica-columns-gap); }
.edica-columns--gap-none { --edica-columns-gap: 0rem; }
.edica-columns--gap-sm { --edica-columns-gap: 0.75rem; }
.edica-columns--gap-lg { --edica-columns-gap: 3rem; }
.edica-columns--valign-top { align-items: flex-start; }
.edica-columns--valign-center { align-items: center; }
.edica-columns--valign-bottom { align-items: flex-end; }
.edica-columns__col { flex: 1 1 0; min-width: 0; }
.edica-columns__col--w-20 { flex: 20 1 0; }
.edica-columns__col--w-25 { flex: 25 1 0; }
.edica-columns__col--w-30 { flex: 30 1 0; }
.edica-columns__col--w-33 { flex: 33 1 0; }
.edica-columns__col--w-40 { flex: 40 1 0; }
.edica-columns__col--w-50 { flex: 50 1 0; }
.edica-columns__col--w-60 { flex: 60 1 0; }
.edica-columns__col--w-67 { flex: 67 1 0; }
.edica-columns__col--w-70 { flex: 70 1 0; }
.edica-columns__col--w-75 { flex: 75 1 0; }
.edica-columns__col--w-80 { flex: 80 1 0; }
.edica-columns--divider .edica-columns__col + .edica-columns__col { position: relative; }
.edica-columns--divider .edica-columns__col + .edica-columns__col::before {
  content: ""; position: absolute; top: 0; bottom: 0;
  left: calc(var(--edica-columns-gap) / -2); width: 1px; background: var(--border);
}
/* On a phone the row stacks, and the rule turns to lie between the rows. */
@media (max-width: 640px) {
  .edica-columns { flex-direction: column; }
  .edica-columns--divider .edica-columns__col + .edica-columns__col::before {
    top: calc(var(--edica-columns-gap) / -2); bottom: auto; left: 0; right: 0; width: auto; height: 1px;
  }
}

/* Landing-page blocks: the hero banner and the call-to-action button.
   The renderer emits classes and nothing else — no inline style ever
   reaches a page — so how these look is decided here, in the theme. */
.post-body .edica-hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  margin-block: 1.5em;
  padding: clamp(1.5rem, 5vw, 3.5rem);
  border-radius: var(--radius-lg);
  background: var(--surface-2);
}
.post-body .edica-hero__body { position: relative; max-width: var(--maxw-read); }
.post-body .edica-hero--align-center { text-align: center; }
.post-body .edica-hero--align-center .edica-hero__body { margin-inline: auto; }
.post-body .edica-hero__heading {
  margin: 0;
  font-size: clamp(1.75rem, 4vw, 2.75rem);
  line-height: 1.15;
  letter-spacing: -0.02em;
}
.post-body .edica-hero__subheading {
  margin: 0.75rem 0 0;
  font-size: 1.15em;
  line-height: 1.5;
  color: var(--text-muted);
}
.post-body .edica-hero__actions { margin-top: 1.5rem; }

/* A banner image is a real <img> the theme positions, never a background
   in a style attribute the sanitiser would have to trust. It fills the
   block behind the text, and the scrim over it is what keeps the words
   readable on any photograph — which is also why the text turns light
   here instead of following the theme's own --text. */
.post-body .edica-hero__image {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
}
.post-body .edica-hero:has(.edica-hero__image)::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(180deg, rgb(0 0 0 / 0.30), rgb(0 0 0 / 0.65));
}
.post-body .edica-hero:has(.edica-hero__image) { color: #fff; }
.post-body .edica-hero:has(.edica-hero__image) .edica-hero__subheading { color: rgb(255 255 255 / 0.85); }
.post-body .edica-hero:has(.edica-hero__image) .edica-hero__heading,
.post-body .edica-hero:has(.edica-hero__image) .edica-hero__subheading { text-shadow: 0 1px 3px rgb(0 0 0 / 0.55); }
/* with a banner behind it the block is a banner, not a paragraph with a
   picture: give it height of its own and centre what little text there is. */
.post-body .edica-hero:has(.edica-hero__image) {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 20rem;
}

/* One button shape for the hero's call to action and for the standalone
   one, because that is what they both are. */
.post-body .edica-cta { margin-block: 1.5em; }
.post-body .edica-hero__button,
.post-body .edica-cta__link {
  display: inline-block;
  padding: 0.7rem 1.4rem;
  border-radius: var(--radius);
  background: var(--accent);
  color: #fff;
  font-weight: 600;
  text-decoration: none;
  box-shadow: var(--shadow-sm);
  transition: background-color 0.15s, color 0.15s;
}
.post-body .edica-hero__button:hover,
.post-body .edica-cta__link:hover { background: var(--accent-hover); color: #fff; }
.post-body .edica-cta--secondary .edica-cta__link {
  background: transparent;
  color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent-ring);
}
.post-body .edica-cta--secondary .edica-cta__link:hover {
  background: var(--accent-soft);
  color: var(--accent-soft-text);
}
@media (max-width: 640px) {
  .post-body .edica-hero__button,
  .post-body .edica-cta__link { display: block; text-align: center; }
}

/* Card grid: a row of cards, the third landing-page block. Everything
   about it that could have been a number in the document is a class
   instead, so the theme decides the look and no author string reaches
   CSS. The count collapses to one column on a narrow screen. */
.post-body .edica-cardgrid {
  display: grid;
  gap: 1.25rem;
  margin-block: 1.5em;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
.post-body .edica-cardgrid--cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.post-body .edica-cardgrid--cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 720px) {
  .post-body .edica-cardgrid,
  .post-body .edica-cardgrid--cols-2,
  .post-body .edica-cardgrid--cols-4 { grid-template-columns: minmax(0, 1fr); }
}
/* --surface rather than --surface-2: a card has to read as raised off
   the page on a dark theme too, and --border-strong is what keeps its
   edge visible where the two greys are close. */
.post-body .edica-cardgrid__card {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
}
.post-body .edica-cardgrid__image {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}
.post-body .edica-cardgrid__body { flex: 1 1 auto; padding: 1.1rem 1.25rem 1.25rem; }
.post-body .edica-cardgrid__title { margin: 0; font-size: 1.15em; line-height: 1.3; }
.post-body .edica-cardgrid__text {
  margin: 0.45rem 0 0;
  color: var(--text-muted);
  font-size: 0.95em;
  line-height: 1.5;
}
/* A card with a destination is the link — the whole card reacts, and the
   title takes the accent so it still reads as something to click. */
.post-body a.edica-cardgrid__card--link {
  color: inherit;
  text-decoration: none;
  transition: border-color 0.15s, box-shadow 0.15s, transform 0.15s;
}
.post-body a.edica-cardgrid__card--link:hover {
  border-color: var(--accent);
  box-shadow: var(--shadow);
  transform: translateY(-2px);
}
.post-body a.edica-cardgrid__card--link:hover .edica-cardgrid__title { color: var(--accent); }
@media (prefers-reduced-motion: reduce) {
  .post-body a.edica-cardgrid__card--link { transition: none; }
  .post-body a.edica-cardgrid__card--link:hover { transform: none; }
}

/* Latest posts: a board's newest threads, listed at request time rather
   than baked into the page's saved HTML. It is a list of links, so it is
   styled as one — the theme decides everything, as with the other three
   landing-page blocks. */
.post-body .edica-latestposts { margin-block: 1.5em; }
.post-body .edica-latestposts__list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 0.75rem;
}
.post-body .edica-latestposts__item {
  padding: 0.85rem 1rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
  background: var(--surface);
}
.post-body .edica-latestposts__link {
  display: block;
  font-weight: 600;
  text-decoration: none;
  color: inherit;
}
.post-body .edica-latestposts__link:hover { color: var(--accent); }
.post-body .edica-latestposts__date {
  display: block;
  margin-top: 0.15rem;
  color: var(--text-muted);
  font-size: 0.85em;
}
.post-body .edica-latestposts__excerpt {
  margin: 0.4rem 0 0;
  color: var(--text-muted);
  font-size: 0.95em;
  line-height: 1.5;
}

/* Edica live editor host (reply / new-thread / page editor forms). */
.edica-host { min-height: 12rem; padding: 0; border-radius: var(--radius-sm); border: 1px solid var(--border-strong); background: var(--surface); }
.edica-host:focus-within { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
[data-page-edit] .edica-host { padding: 0; border: 0; background: transparent; }
[data-page-edit] .edica-host:focus-within { border: 0; box-shadow: none; }

/* Event pages (templates/page.event.liquid).
   Written entirely in the theme's own tokens, so the same rules read
   correctly on a light or a dark scheme without a second copy. */
.event-poster { display: block; width: 100%; height: auto; border-radius: var(--radius); margin-bottom: var(--gap); }
.event-meta { display: grid; grid-template-columns: auto 1fr; gap: 0.5rem 0.75rem; align-items: start;
  margin: 0 0 var(--gap); padding: 1rem; border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface-2); }
.event-meta__label { display: flex; align-items: center; gap: 0.5rem; color: var(--text-muted); font-size: 0.875rem; }
.event-meta__icon { width: 1.125rem; height: 1.125rem; flex: none; color: var(--accent); }
.event-meta__term { font-weight: 600; }
.event-meta__value { margin: 0; color: var(--text); font-size: 0.875rem; }
.event-meta__value a { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }
.event-meta__value a:hover { color: var(--accent-hover); }
@media (max-width: 30rem) {
  .event-meta { grid-template-columns: 1fr; gap: 0.25rem; }
  .event-meta__value { margin-bottom: 0.5rem; }
}
