/* ═══ HELHEIMRS — page: تالار ارواح (Hall of Spirits) ═══ */
.pg-hall { padding-block: var(--s-6) 0; }

/* Keyboard focus never lands under the sticky header — nor, on the feed, under
   the filter bar that sticks below it (WCAG 2.4.11). */
:root[data-page="hall"]:has(.hall-bar:not([hidden])) { scroll-padding-top: calc(var(--hdr-h, 68px) + 72px); }
/* Decoration placed for a long feed (the lantern's hidden runes, laid out on
   #app) never holds the page open after a filter or a search has made it
   short: what runs past the page's end is clipped, not scrolled to. Nothing on
   the hall opens past its own end (its dialogs live on <body>). */
:root[data-page="hall"] #app { overflow-y: clip; }
@media (max-width: 900px) { :root[data-page="hall"] { scroll-padding-bottom: 96px; } }

/* Community text never widens the page. A Persian compound joined with ZWNJs
   is one long word to the line breaker; HX.ct gives it break points (.wb in
   base.css, which a one-line ellipsised name switches off by itself, so no
   rule here has to hide them), and this is the last resort for anything still
   longer than a line. */
.pg-hall :is(h1, h2, h3, p, li, blockquote, figcaption), .hcard :is(.card__title, .card__ititle, .card__excerpt, .card__author, .card__byname) { overflow-wrap: anywhere; }
/* A list item's text-align is the browser's match-parent, which an English
   list turns into a hard «left» that a Persian title inside it inherits: the
   items align by each line's own direction instead. */
.pg-hall :is(.mine__item, .vnext__list > li, .related > li) { text-align: start; }

/* ── page header ── */
.pg-hall .hall-head { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--s-4) var(--s-5); flex-wrap: wrap; margin-bottom: var(--s-5); }
.pg-hall .hall-head__text { flex: 1 1 520px; min-width: 0; }
.pg-hall .hall-head h1 { margin: 0 0 .15em; }
.pg-hall--hub .hall-head h1 { font-size: var(--fs-3xl); }
.pg-hall--hub { padding-top: var(--s-5); }
.pg-hall .hall-head p { color: var(--fg-muted); margin: 0; max-width: 60ch; }
.pg-hall .hall-head__actions { gap: var(--s-2); flex-wrap: wrap; }
.pg-hall .hall-head__join { display: inline-flex; align-items: center; min-height: 44px; color: var(--accent-text); font-weight: 600; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 5px; }
/* in Frost the link sits on the grey of the painted sky: the deepest jade keeps it above 4.5:1 there */
:root[data-theme="light"] .pg-hall .hall-head__join { color: var(--jade-deep); }
/* An ornament, not a word: two hairlines and one rune. Runes that spelled
   English words read as misspelt Latin capitals above a Persian title. */
.hall-eyebrow { display: flex; align-items: center; gap: 10px; margin-bottom: var(--s-2); color: var(--ornament); opacity: .6; }
.hall-eyebrow i { width: 40px; height: 1px; background: currentColor; }
.hall-eyebrow span { display: inline-flex; line-height: 0; }
@media (max-width: 699px) {
  /* the realm's name is still there, in the «why» line under the title */
  .pg-hall--hub .realm-alias { display: none; }
  .pg-hall--hub .hall-head { margin-bottom: var(--s-4); }
  .pg-hall--hub .hall-head__lead { font-size: var(--fs-sm); line-height: 1.85; }
  .pg-hall--hub .realm-plain { margin-top: var(--s-1); }
}

/* ── the filter bar: chips, search, sticky under the header ──
   The bar is a solid pane (frosted where the browser can), with a rule under
   it: nothing of the cards scrolling beneath shows between the chips. */
.pg-hall .hall-bar {
  position: sticky; top: var(--hdr-h, 68px); z-index: 5;
  display: flex; align-items: center; gap: var(--s-3);
  min-height: 56px; padding: var(--s-2) var(--s-3); margin: 0 calc(-1 * var(--s-3)) var(--s-5);
  background: var(--bg); background: color-mix(in srgb, var(--bg) 92%, transparent);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}
.pg-hall .hall-bar[hidden] { display: none; }
.pg-hall .hall-filters { position: relative; flex: 1 1 auto; min-width: 0; }
/* The snap lines and the focus scroll keep clear of the edge fades below (and
   of the 5px kept for the chips' glow, or the row rests 5px scrolled): a chip
   the row comes to rest on, or one reached by Tab, is whole and unfaded
   (hall.js brings a focused one in; a fade only shows where chips are hidden,
   so at either end the padding asks for nothing). */
.pg-hall .hall-filters__chips { display: flex; gap: var(--s-2); overflow-x: auto; scrollbar-width: none; scroll-snap-type: x proximity; scroll-padding-inline: calc(var(--f-out) + var(--f-in) + 5px); padding: 6px 5px; margin: -6px -5px; }
.pg-hall .hall-filters__chips::-webkit-scrollbar { display: none; }
/* Whenever the chips run past their room, at any width, the edge that hides
   some fades (hall.js sets which): a row that looks complete never has a
   category missing from it. A mouse gets a chevron in the faded end that
   brings the next chip into view; a finger swipes, and its fade is shorter. */
.pg-hall .hall-filters { --fade-to: left; --f-in: 28px; --f-out: 0px; }
/* (on the narrowest phones the rail is ~190px: two 28px fades left no room
   for «خلاصه‌ی جلسه ۸۰», 144px, to stand whole and unfaded once focused) */
@media (max-width: 380px) { .pg-hall .hall-filters { --f-in: 16px; } }
.pg-hall .hall-filters:dir(ltr) { --fade-to: right; }
.pg-hall .hall-filters:is(.is-over-start, .is-over-end) .hall-filters__chips {
  --s-a: 0px; --s-b: 0px; --e-a: 0px; --e-b: 0px;
  -webkit-mask-image: linear-gradient(to var(--fade-to), transparent var(--s-a), #000 var(--s-b), #000 calc(100% - var(--e-b)), transparent calc(100% - var(--e-a)));
  mask-image: linear-gradient(to var(--fade-to), transparent var(--s-a), #000 var(--s-b), #000 calc(100% - var(--e-b)), transparent calc(100% - var(--e-a)));
}
.pg-hall .hall-filters.is-over-start .hall-filters__chips { --s-a: var(--f-out); --s-b: calc(var(--f-out) + var(--f-in)); }
.pg-hall .hall-filters.is-over-end .hall-filters__chips { --e-a: var(--f-out); --e-b: calc(var(--f-out) + var(--f-in)); }
.pg-hall .hall-filters__step { display: none; }
@media (hover: hover) and (pointer: fine) {
  .pg-hall .hall-filters { --f-in: 32px; --f-out: 32px; }
  .pg-hall .hall-filters__step {
    position: absolute; inset-block: 0; z-index: 1; width: 32px; padding: 0;
    place-items: center; background: none; border: 0; color: var(--fg-muted); cursor: pointer;
    transition: color var(--t-fast) var(--ease-stone);
  }
  .pg-hall .hall-filters__step[data-step="-1"] { inset-inline-start: 0; }
  .pg-hall .hall-filters__step[data-step="1"] { inset-inline-end: 0; }
  .pg-hall .hall-filters.is-over-start .hall-filters__step[data-step="-1"], .pg-hall .hall-filters.is-over-end .hall-filters__step[data-step="1"] { display: grid; }
  .pg-hall .hall-filters__step:hover { color: var(--accent-text); }
  .pg-hall .hall-filters__step .ico { --n: 20; --ico: 20px; stroke-width: 1.8; }
}
/* the chips themselves are the shared component (rest, hover, on and focus are
   four different looks there); the hall only adds its counts */
.pg-hall .hall-chip { scroll-snap-align: start; flex: none; }
.pg-hall .hall-chip__n { font-weight: 400; color: var(--fg-muted); font-variant-numeric: tabular-nums; }
.pg-hall .hall-chip[aria-pressed="true"] .hall-chip__n { color: inherit; }
.pg-hall .hall-chip__n:empty { display: none; }
/* a filter with nothing in it (a search that found none of its kind) fades; it shows no lone zero */
.pg-hall .hall-chip.is-zero:not([aria-pressed="true"]) { color: var(--fg-faint); }
.pg-hall .hall-search { position: relative; flex: 0 1 260px; min-width: 0; margin: 0; }
.pg-hall .hall-search__input { width: 100%; min-height: 40px; padding-inline-start: 38px; }
.pg-hall .hall-search__ico { position: absolute; inset-inline-start: 10px; top: 50%; display: grid; width: 20px; height: 20px; margin-top: -10px; color: var(--fg-faint); pointer-events: none; }
.pg-hall .hall-search__ico .ico { --n: 20; --ico: 20px; stroke-width: 1.8; }
.pg-hall .hall-search__toggle { display: none; flex: none; }
.pg-hall .hall-search__toggle[aria-expanded="true"] { color: var(--accent-text); }
.pg-hall .hall-count { font-size: var(--fs-sm); white-space: nowrap; color: var(--fg-muted); }
.pg-hall .hall-count:empty { display: none; }
/* The order — newest, or most liked — is the shared two-way control, one chip
   high, beside the chips: it changes what comes first, not what is there. The
   pressed order's mark is lit, so the heart reads as the like heart on the cards. */
.pg-hall .hall-sort { flex: none; padding: 2px; gap: 2px; }
.pg-hall .hall-sort > button { display: inline-flex; align-items: center; justify-content: center; gap: 6px; min-height: 34px; white-space: nowrap; }
.pg-hall .hall-sort .ico { --n: 16; --ico: 16px; stroke-width: 2.25; }
.pg-hall .hall-sort > button[aria-pressed="true"] .ico { color: var(--accent-text); }
/* the facets clip an outside ring, so the focus ring is drawn inside */
.pg-hall .hall-sort > button:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; box-shadow: none; }
@media (pointer: coarse) { .pg-hall .hall-sort > button { min-height: 38px; } }
@media (max-width: 900px) {
  /* the count is still announced; the bar has no room to show it */
  .pg-hall .hall-count { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  /* nor for the two orders' names beside the chips and a search field that
     still holds its placeholder: the marks alone (a clock, the like heart),
     their names still there for the ear and in the tooltip */
  .pg-hall .hall-sort > button { min-width: 40px; padding: 0; }
  .pg-hall .hall-sort__t { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}
/* the search field never shrinks past its own placeholder; the chips scroll instead */
@media (min-width: 700px) { .pg-hall .hall-search { min-width: 13.5em; } }
@media (max-width: 699px) {
  .pg-hall .hall-bar { flex-wrap: wrap; gap: var(--s-2); }
  .pg-hall .hall-filters { flex: 1 1 0; }
  .pg-hall .hall-search__toggle { display: inline-grid; place-items: center; }
  .pg-hall .hall-search { display: none; flex: 1 0 100%; order: 3; }
  .pg-hall .hall-search.is-open { display: block; }
}
@media (pointer: coarse) { .pg-hall .hall-search__input { min-height: 44px; } }

/* ── featured: one lit opening, the words on the dark side, the picture on the other ──
   The picture stands in the half the words leave free and is drawn for that
   box (hall.js fitCover), so its subject is whole and never under the
   headline; it melts into the dark ground on the words' side. On a narrow
   screen it stands above the words instead. The ground and the art are always
   dark, so this keeps fixed light values in BOTH themes. */
.pg-hall .featured {
  position: relative; isolation: isolate; overflow: hidden;
  min-height: 300px; display: grid; align-items: end;
  margin-bottom: var(--s-5);
  background: linear-gradient(180deg, #0B0C0D 0%, #131518 62%, #191C1F 100%);
  border: 1px solid var(--line-glow);
  --facet: 18px; clip-path: var(--clip-facet);
  box-shadow: var(--glow-inset-soft);
  --fade-to: left;
}
.pg-hall .featured:dir(ltr) { --fade-to: right; }
.pg-hall .featured__media {
  position: absolute; inset-block: 0; inset-inline-end: 0; inset-inline-start: 44%; z-index: -2;
  -webkit-mask-image: linear-gradient(to var(--fade-to), transparent 0, #000 14%); mask-image: linear-gradient(to var(--fade-to), transparent 0, #000 14%);
}
.pg-hall .featured__media .hx-cover { width: 100%; height: 100%; object-fit: cover; }
/* a hairline of shade where the picture meets the words, and a floor under the foot */
.pg-hall .featured__scrim {
  position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background:
    linear-gradient(to var(--fade-to), rgba(8,9,10,.55) 0%, rgba(8,9,10,.35) 40%, transparent 52%),
    linear-gradient(to top, rgba(8,9,10,.45), transparent 35%);
}
.pg-hall .featured__body { position: relative; max-width: min(56ch, 46%); min-width: 0; padding: var(--s-5) var(--s-6); display: grid; gap: var(--s-3); }
.pg-hall .featured__meta { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; font-size: var(--fs-xs); color: #B9BEB8; }
.pg-hall .featured__meta .tag { color: #C8CEC7; border-color: rgba(237,239,234,.22); background: rgba(255,255,255,.04); }
.pg-hall .featured__meta .tag--accent { color: #7BE6C0; border-color: rgba(47,211,154,.5); }
/* Three lines before the clamp: an ordinary headline (the demo's 47
   characters, at a tablet's 28px) is never cut inside a word; only a title
   past about 70 characters ends in an ellipsis. */
.pg-hall .featured__body h2 { font-size: clamp(1.75rem, 2.6vw, 2.4rem); line-height: 1.35; margin: 0; color: var(--frost); display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; padding-block: 2px; }
.pg-hall .featured__body h2 a { color: var(--frost); text-shadow: 0 2px 18px rgba(0,0,0,.6); }
.pg-hall .featured__body h2 a:hover { color: #7BE6C0; text-decoration: none; }
.pg-hall .featured__body h2 a:focus-visible { outline: none; text-decoration: underline 2px #7BE6C0; text-underline-offset: 6px; }
.pg-hall .featured__body > p { color: #CFD4CD; margin: 0; max-width: 48ch; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
/* The foot is two units: who wrote it and how long it reads, then «بخوان».
   When the words' column is narrow (a tablet, where the picture keeps its
   half) the button goes to the next line as a whole; nothing in the foot is
   ever squeezed. The read time used to be the item that gave way, and at 820px
   it broke inside its words, «۱ / دقیقه / خواند / ن». A long name ends in an
   ellipsis instead; the read time and the button keep their own width. */
.pg-hall .featured__foot { display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap; margin-top: var(--s-1); }
.pg-hall .featured__by { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: var(--s-3); }
.pg-hall .featured__by > .avatar, .pg-hall .featured__foot > .btn { flex: none; }
.pg-hall .featured__who { display: grid; line-height: 1.7; min-width: 0; max-width: 18em; text-decoration: none; }
.pg-hall .featured__who > * { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pg-hall .featured__who b { color: var(--frost); }
.pg-hall .featured__who small { color: #AEB4AD; }
.pg-hall a.featured__who:hover b, .pg-hall a.featured__who:focus-visible b { color: #7BE6C0; }
.pg-hall .featured__read { flex: none; white-space: nowrap; color: #AEB4AD; font-size: var(--fs-sm); }
/* A tablet held upright (801–1099px): 46% of the card left the words a
   340px column, and the lead's ordinary headline was cut inside a word
   («…پشت می…»). The words take three fifths; the picture starts behind them
   and the scrim's fade moves with it, so the picture is still whole in the
   part the words leave free. */
@media (min-width: 801px) and (max-width: 1099px) {
  .pg-hall .featured__body { max-width: min(56ch, 60%); }
  .pg-hall .featured__media { inset-inline-start: 54%; }
  .pg-hall .featured__scrim {
    background:
      linear-gradient(to var(--fade-to), rgba(8,9,10,.55) 0%, rgba(8,9,10,.35) 52%, transparent 64%),
      linear-gradient(to top, rgba(8,9,10,.45), transparent 35%);
  }
}
@media (max-width: 800px) {
  /* the picture above, the words below on the dark ground: nothing over the subject */
  .pg-hall .featured { min-height: 0; align-items: stretch; grid-template-rows: auto auto; }
  .pg-hall .featured__media {
    position: relative; inset: auto; height: clamp(150px, 44vw, 250px);
    -webkit-mask-image: linear-gradient(to bottom, #000 84%, transparent); mask-image: linear-gradient(to bottom, #000 84%, transparent);
  }
  .pg-hall .featured__scrim { display: none; }
  .pg-hall .featured__body { max-width: none; padding: var(--s-3) var(--s-4) var(--s-5); gap: var(--s-2); }
  .pg-hall .featured__body > p { display: none; }
}

/* ── the feed: a row-ordered masonry on an 8px row grid (placed by hall.js) ──
   Until the script has measured the cards it is an ordinary grid, which is
   also what it stays if the script never runs. */
.pg-hall .feed { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s-5); align-items: start; }
.pg-hall .feed.is-packed { grid-auto-rows: 8px; row-gap: 0; }
.pg-hall .feed > .hcard { margin: 0; align-self: start; }
.pg-hall .feed__empty { grid-column: 1 / -1; }
/* a new filter or search dims what is there until the new cards arrive; the page keeps its height */
.pg-hall .feed > * { transition: opacity 120ms linear; }
.pg-hall .feed.is-loading > * { opacity: .4; pointer-events: none; }
@media (max-width: 1099px) { .pg-hall .feed { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 699px) { .pg-hall .feed { gap: var(--s-3); } }
@keyframes hall-arrive { from { opacity: 0; transform: translateY(10px); } }
.hcard.is-arriving { animation: hall-arrive 240ms var(--ease-out) var(--d, 0ms) both; }
.pg-hall .hall-more { display: flex; justify-content: center; margin-block: var(--s-6); }
.pg-hall .btn[aria-disabled="true"], .hall-actions .btn[aria-busy="true"], .pg-hall .btn[aria-busy="true"] { opacity: .65; cursor: progress; }
/* a button's mark is the 20px optical size of the set (its stroke 1.5px at 1×) */
.pg-hall .btn .ico, .hall-actions .btn .ico, .lightbox .btn .ico { --n: 20; --ico: 20px; stroke-width: 1.8; }

/* ═══ cards: three content types, three anatomies ═══
   On .hcard, not under the hall page: the profile and any other list of posts
   use the same markup, and must look the same. */
.hcard { position: relative; display: flex; flex-direction: column; min-width: 0; }
/* icons on the four optical sizes of the set (16/20/24/32), never sized by the text around them */
.hcard .ico { --n: 16; --ico: 16px; stroke-width: 2.25; flex: none; }

/* shared text atoms */
.hcard .card__meta, .pg-hall .card__meta { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; font-size: var(--fs-xs); color: var(--fg-muted); }
.hcard .card__meta time, .pg-hall .card__meta time { font-variant-numeric: tabular-nums; }
.hcard .card__title { font-size: var(--fs-lg); margin: 0; line-height: 1.45; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.hcard .card__title a { color: var(--fg-strong); }
.hcard .card__title a:hover { color: var(--accent-text); text-decoration: none; }
/* the title is clamped (and so clipped): its focus is an underline, and the card lights around it */
.hcard .card__title a:focus-visible { outline: none; box-shadow: none; text-decoration: underline 2px var(--accent); text-underline-offset: 5px; }
.hcard .card__excerpt { margin: 0; color: var(--fg-muted); font-size: var(--fs-sm); line-height: var(--lh-body); display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.hcard .card__foot { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; font-size: var(--fs-xs); color: var(--fg-muted); }
.hcard .card__author { color: var(--fg); font-weight: 600; min-width: 0; }
.hcard .card__sep, .pg-hall .card__sep { color: var(--ornament); font-style: normal; }
/* a compact count ("123.5 thousand") is one figure: it never breaks inside its word, and the name beside it is what gives way */
.hcard .card__likes { display: inline-flex; align-items: center; gap: 4px; flex: none; white-space: nowrap; color: var(--accent-text); font-variant-numeric: tabular-nums; }
.hcard .card__likes .ico { --n: 16; --ico: 16px; stroke-width: 2.25; }
.hcard .avatar--sm { flex: none; }

/* ── ARTICLE = a printed page: margin rule, text first ── */
.hcard.card--article .card__page {
  position: relative; overflow: hidden; flex: 1;
  padding: var(--s-5); padding-inline-start: var(--s-6);
  display: grid; align-content: start; gap: var(--s-3);
  background: var(--stone-grad); border: 1px solid var(--line);
  --facet: 14px; clip-path: var(--clip-facet);
  box-shadow: var(--shadow-stone);
  transition: border-color var(--t-ui) var(--ease-stone), box-shadow var(--t-ui) var(--ease-stone);
}
/* the ruled margin of a page, not a decorative accent bar: it sits inside the text block */
.hcard.card--article .card__page::after {
  content: ""; position: absolute; inset-block: var(--s-4); inset-inline-start: calc(var(--s-6) - 10px);
  width: 1px; background: linear-gradient(180deg, transparent, var(--line-strong) 12%, var(--line-strong) 88%, transparent);
}
.hcard.card--article:hover .card__page { border-color: var(--line-glow); }
.hcard.card--article:focus-within .card__page { border-color: var(--line-glow); box-shadow: var(--shadow-stone), var(--glow-inset); }
.hcard.card--article .card__title { font-size: var(--fs-xl); line-height: 1.4; }
/* the illustration is a plate set into the page, never a full-bleed banner */
.hcard .card__plate { display: block; aspect-ratio: 21 / 9; overflow: hidden; border: 1px solid var(--line-strong); background: var(--bg); }
.hcard .card__plate .hx-cover { width: 100%; height: 100%; }
/* a post with no cover carries a carved band with its kind's rune, not a fake picture */
.hcard .card__band {
  display: flex; align-items: center; gap: var(--s-3); height: 48px;
  margin: calc(-1 * var(--s-5)) calc(-1 * var(--s-5)) 0; margin-inline-start: calc(-1 * var(--s-6)); padding-inline: var(--s-5);
  background: linear-gradient(180deg, rgba(0,0,0,.34), rgba(0,0,0,.12)), repeating-linear-gradient(90deg, transparent 0 53px, rgba(0,0,0,.35) 53px 54px, rgba(255,255,255,.04) 54px 55px);
  border-bottom: 1px solid var(--line-strong);
  box-shadow: inset 0 -1px 0 rgba(255,255,255,.04);
}
:root[data-theme="light"] .hcard .card__band { background: linear-gradient(180deg, rgba(20,24,22,.08), rgba(20,24,22,.02)), repeating-linear-gradient(90deg, transparent 0 53px, rgba(20,24,22,.12) 53px 54px, rgba(255,255,255,.7) 54px 55px); box-shadow: inset 0 -1px 0 rgba(255,255,255,.7); }
/* the stave is drawn (hall.js RUNE) and cut into the band: a lit lower lip, a dark upper one */
.hcard .card__band > span { display: inline-flex; line-height: 0; color: var(--rune-lit); filter: drop-shadow(0 1px 0 rgba(255,255,255,.07)) drop-shadow(0 -1px 0 rgba(0,0,0,.8)); }
:root[data-theme="light"] .hcard .card__band > span { filter: drop-shadow(0 1px 0 rgba(255,255,255,.9)) drop-shadow(0 -1px 0 rgba(20,24,22,.25)); }
.hcard .card__band::after { content: ""; flex: 1; height: 1px; background: linear-gradient(to var(--band-to, left), var(--line-strong), transparent); }
.hcard .card__band:dir(ltr) { --band-to: right; }
/* the lead of a page: two columns wide, its plate a wide band */
.hcard.is-lead .card__title { font-size: clamp(1.5rem, 2.2vw, 1.875rem); line-height: 1.35; }
.hcard.is-lead .card__excerpt { font-size: var(--fs-md); -webkit-line-clamp: 3; }
.hcard.is-lead .card__page { gap: var(--s-4); }
/* a lead that had to narrow to one column keeps the size of the cards beside it */
.hcard.is-lead.is-narrowed .card__title { font-size: var(--fs-xl); }
.hcard.is-lead.is-narrowed .card__excerpt { font-size: var(--fs-sm); }

/* ── VIDEO = a lit screen on a recessed deck ── */
.hcard.card--video { background: var(--stone-grad); border: 1px solid var(--line); --facet: 14px; clip-path: var(--clip-facet); box-shadow: var(--shadow-stone); transition: border-color var(--t-ui) var(--ease-stone); }
.hcard.card--video:hover, .hcard.card--video:focus-within { border-color: var(--line-glow); }
/* above the deck (z-index), so its glow spills onto it */
.hcard .card__screen {
  position: relative; z-index: 1; display: block; aspect-ratio: 16 / 9; overflow: hidden;
  background: #000; margin: var(--s-2) var(--s-2) 0;
  box-shadow: 0 0 0 1px rgba(47,211,154,.28);
  transition: box-shadow 240ms var(--ease-stone);
}
.hcard .card__screen::after { content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none; box-shadow: inset 0 0 26px rgba(47,211,154,.1); transition: box-shadow 240ms var(--ease-stone); }
.hcard .card__reel { position: absolute; inset: 0; display: block; }
.hcard .card__reel .hx-cover { width: 100%; height: 100%; object-fit: cover; }
/* hover: the rim lights outward, and the poster runs through three framings like a storyboard */
.hcard.card--video:hover .card__screen, .hcard .card__screen:focus-visible { box-shadow: 0 0 0 1px rgba(47,211,154,.8), 0 0 22px 2px rgba(47,211,154,.35); }
.hcard.card--video:hover .card__screen::after { box-shadow: inset 0 0 28px rgba(47,211,154,.18); }
.hcard .card__deck { flex: 1; padding: var(--s-4) var(--s-5) var(--s-5); display: grid; align-content: start; gap: var(--s-2); background: var(--bg); margin: var(--s-2); box-shadow: inset 0 1px 0 rgba(0,0,0,.6); }
:root[data-theme="light"] .hcard .card__deck { box-shadow: inset 0 1px 0 rgba(20,24,22,.12); }
.hcard .card__play { position: absolute; inset: 0; z-index: 3; display: grid; place-items: center; opacity: 0; transition: opacity var(--t-ui) var(--ease-out); }
.hcard .card__play span { width: 58px; height: 58px; clip-path: var(--clip-hex); background: rgba(10,10,11,.72); display: grid; place-items: center; color: var(--emerald); }
.hcard .card__play .ico { --n: 24; --ico: 24px; stroke-width: 1.75; margin-inline-start: 2px; }
.hcard .card__dur { position: absolute; z-index: 3; bottom: var(--s-2); inset-inline-start: var(--s-2); padding: 2px 8px; font-size: var(--fs-2xs); font-variant-numeric: tabular-nums; background: rgba(10,10,11,.78); color: var(--frost); direction: ltr; unicode-bidi: isolate; }
.hcard .card__scrub { position: absolute; z-index: 3; inset-inline: 0; bottom: 0; height: 2px; background: rgba(255,255,255,.12); opacity: 0; transition: opacity var(--t-ui) var(--ease-out); }
.hcard .card__scrub i { display: block; height: 100%; width: 0; background: var(--emerald); box-shadow: 0 0 6px rgba(47,211,154,.8); }
.hcard.card--video:hover .card__play, .hcard.card--video:focus-within .card__play, .hcard.card--video:hover .card__scrub { opacity: 1; }
@keyframes hall-reel {
  0% { transform: none; }
  7%, 30% { transform: scale(1.18) translate(4%, 3%); }
  37%, 60% { transform: scale(1.24) translate(-5%, -2%); }
  67%, 92% { transform: scale(1.14) translate(1%, -5%); }
  100% { transform: none; }
}
@keyframes hall-scrub { from { width: 0; } to { width: 100%; } }
/* a quarter-second of intent before it plays: a pointer passing over does not set it off */
.hcard.card--video:hover .card__reel { animation: hall-reel 3.6s var(--ease-stone) 250ms infinite; }
.hcard.card--video:hover .card__scrub i { animation: hall-scrub 3.6s linear 250ms infinite; }
@media (hover: none) { .hcard .card__play { opacity: 1; } }

/* ── IMAGE = a carved window: the stone frames the whole picture ──
   The picture keeps its shape (portrait, square, wide); nothing is cut off its
   top. The portal's roof is a line drawn over it — fixed 32° shoulders, the same
   on every card — not a mask. One maker's mark, not four stray letters. */
.hcard.card--image .card__window {
  position: relative; display: block; padding: 10px; color: inherit; text-decoration: none;
  background: var(--stone-grad-2); box-shadow: var(--shadow-stone);
  --facet: 12px; clip-path: var(--clip-facet);
}
.hcard .card__pane { position: relative; display: block; aspect-ratio: var(--ar-fixed, var(--ar, .8)); overflow: hidden; background: var(--bg); box-shadow: 0 0 0 1px rgba(0,0,0,.45); }
.hcard .card__pane .hx-cover { width: 100%; height: 100%; object-fit: cover; transition: transform 1.4s var(--ease-out); }
.hcard .card__pane::after, .pg-hall .article__cover::after {
  content: ""; position: absolute; inset: 10px 10px auto; height: 24px; pointer-events: none;
  --arch: var(--emerald);
  background:
    linear-gradient(to bottom right, transparent calc(50% - .8px), var(--arch) calc(50% - .3px) calc(50% + .3px), transparent calc(50% + .8px)) left top / 38px 24px no-repeat,
    linear-gradient(to bottom left, transparent calc(50% - .8px), var(--arch) calc(50% - .3px) calc(50% + .3px), transparent calc(50% + .8px)) right top / 38px 24px no-repeat,
    linear-gradient(var(--arch), var(--arch)) center top / calc(100% - 76px) 1px no-repeat;
  opacity: .35; transition: opacity var(--t-ui) var(--ease-stone), filter var(--t-ui) var(--ease-stone);
}
.hcard.card--image .card__window:hover .card__pane::after, .hcard.card--image .card__window:focus-visible .card__pane::after { opacity: .7; filter: drop-shadow(0 0 6px rgba(47,211,154,.75)); }
.hcard.card--image .card__window:hover .hx-cover { transform: scale(1.04); }
.hcard.card--image .card__window:focus-visible { outline-offset: -3px; box-shadow: var(--glow-inset); }
/* "opens larger": a small carved stud in the picture's corner, quiet at rest,
   lit emerald with the portal's roof when the window is pointed at or focused.
   It sits on the picture, which is dark or not, so the stud carries its own
   dark ground (fixed values in both themes). The glyph is the set's 16. */
.hcard .card__mark {
  position: absolute; bottom: 16px; inset-inline-end: 16px; display: grid; place-items: center; width: 28px; height: 28px;
  color: #EDEFEA; background: rgba(8,9,10,.62); --facet: 6px; clip-path: var(--clip-facet);
  opacity: .55; pointer-events: none; transition: opacity var(--t-ui) var(--ease-stone), color var(--t-ui) var(--ease-stone);
}
.hcard.card--image .card__window:is(:hover, :focus-visible) .card__mark { opacity: 1; color: #7BE6C0; }
.hcard .card__lintel { flex: 1; display: grid; align-content: start; gap: 2px; padding: var(--s-3) var(--s-4); background: var(--bg-elev); border-top: 1px solid var(--line-glow); }
.hcard .card__ititle { margin: 0; font-family: var(--font-body); font-weight: 700; font-size: .9375rem; line-height: 1.5; color: var(--fg-strong); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.hcard .card__by { display: flex; align-items: center; gap: var(--s-2); min-width: 0; font-size: var(--fs-xs); color: var(--fg-muted); }
.hcard .card__byname { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* phone: pictures go two to a row as square thumbnails; writing and video take the full width */
@media (max-width: 699px) {
  .pg-hall .feed .card--image .card__pane { --ar-fixed: 1; }
  .pg-hall .feed .card--image .card__window { padding: 6px; --facet: 8px; }
  .pg-hall .feed .card--image .card__pane::after { inset: 6px 6px auto; height: 14px; background-size: 22px 14px, 22px 14px, calc(100% - 44px) 1px; }
  .pg-hall .feed .card--image .card__mark { display: none; }
  .pg-hall .feed .card--image .card__lintel { padding: var(--s-2) var(--s-3); }
  .pg-hall .feed .card--image .card__ititle { font-size: .8125rem; }
  .pg-hall .feed .hcard .card__excerpt { -webkit-line-clamp: 2; }
  .pg-hall .feed .card--article .card__page { padding: var(--s-4); padding-inline-start: var(--s-5); gap: var(--s-2); }
  .pg-hall .feed .card--article .card__page::after { inset-inline-start: calc(var(--s-5) - 9px); }
  .pg-hall .feed .card--article .card__band { margin: calc(-1 * var(--s-4)) calc(-1 * var(--s-4)) 0; margin-inline-start: calc(-1 * var(--s-5)); height: 40px; padding-inline: var(--s-4); }
  .pg-hall .feed .card--article .card__title { font-size: var(--fs-lg); }
  .pg-hall .feed .card__deck { padding: var(--s-3) var(--s-4) var(--s-4); }
}

/* ── like / save / share / report ── */
.hall-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); }
.hall-actions .btn[aria-pressed="true"] { color: var(--accent-text); border-color: var(--line-glow); box-shadow: var(--glow-inset); }
.hall-actions [data-like-count] { font-variant-numeric: tabular-nums; }
/* a figure is one piece wherever its line breaks (hall.js countHTML) */
.hall-actions__n { white-space: nowrap; }
/* Nothing in the row moves when it is pressed. Like and save are optimistic:
   the new state is painted on the press itself, and that is the feedback (a
   refusal puts it back, with a toast). The press still marks the button busy —
   for assistive tech, and so a second press waits for the first — but the
   busy ring is not laid out beside the mark: in flow it was 14px and a gap,
   and grew the lightbox's cells 18px for as long as the request was out
   (on a phone the picture shrank and shifted, then snapped back), and widened
   «پسند» 22px in an article's row, pushing its neighbours. Nor is the pressed
   state dimmed: the fresh state is the answer to the press, at full strength.
   Only a slow answer earns a sign: after 400ms a small ring turns in the
   button's corner, out of flow, until the server replies. */
.hall-actions .btn[aria-busy="true"] { opacity: 1; }
.hall-actions .btn[aria-busy="true"]::before {
  position: absolute; inset-block-start: 4px; inset-inline-end: 4px; width: 10px; height: 10px;
  animation: hall-wait 400ms, btn-busy .9s steps(6) infinite;
}
@keyframes hall-wait { from, to { visibility: hidden; } }
@media (prefers-reduced-motion: reduce) { .hall-actions .btn[aria-busy="true"]::before { animation: hall-wait 400ms; } }
:root[data-motion="off"] .hall-actions .btn[aria-busy="true"]::before { animation: hall-wait 400ms; }
/* An article's or a video's row is a line of words, so a like count and the
   save button's two words would change the width of what was pressed and push
   what follows. The heart's word and its count share one place (the count
   stands in the word's stead, as in the lightbox; the word stays for screen
   readers), and «ذخیره» and «ذخیره‌شده» are laid one over the other, the
   other kept hidden: each button is as wide as its longest state, always. */
.hall-actions:not(.hall-actions--bar) [data-act="like"] { display: inline-grid; grid-template-columns: auto auto; align-items: center; justify-content: center; column-gap: var(--s-2); }
.hall-actions:not(.hall-actions--bar) [data-act="like"] > span { grid-area: 1 / 2; justify-self: start; }
.hall-actions[data-counted]:not(.hall-actions--bar) [data-act="like"] .hall-actions__word { opacity: 0; }
.hall-actions__bm { display: inline-grid; }
.hall-actions__bm > span { grid-area: 1 / 1; }
.hall-actions [aria-pressed="true"] .hall-actions__bm > :first-child, .hall-actions :not([aria-pressed="true"]) > .hall-actions__bm > :last-child { visibility: hidden; }
/* reporting is there when it is needed, and never the loudest thing in the row */
:is(.hall-actions, .lightbox__flag) .hall-report { margin-inline-start: auto; width: 36px; min-height: 36px; padding: 0; justify-content: center; color: var(--fg-faint); background: none; border-color: transparent; box-shadow: none; }
:is(.hall-actions, .lightbox__flag) .hall-report > span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
:is(.hall-actions, .lightbox__flag) .hall-report .ico { --n: 20; --ico: 20px; stroke-width: 1.8; }
:is(.hall-actions, .lightbox__flag) .hall-report:hover, :is(.hall-actions, .lightbox__flag) .hall-report:focus-visible { color: var(--ember-soft); border-color: rgba(224,101,79,.4); }
@media (pointer: coarse) { :is(.hall-actions, .lightbox__flag) .hall-report { width: 44px; min-height: 44px; } }
/* The lightbox's actions are one bar of three equal cells, an icon over its
   word, so «پسند ۱۲۳٫۵ هزار · ذخیره · هم‌رسانی» never breaks two and one in a
   340px column; a like count stands in the word's place (the word stays for
   screen readers).
   Nothing in a cell is ever cut. An ellipsis there left «ه…» and «ذ…» at a
   large text size, and in a count it cut the unit («۱۲۳٫۵ …», a hundred and
   twenty-three) or, eaten from the left in RTL, the leading digit («…۲۳٫۵»).
   So a count wraps its unit under the figure (a figure itself has no break in
   it), and when the bar is too narrow for its longest word — «ذخیره‌شده» is
   3.45em at the cell's size, plus 14px of cell and 8px of gap: 10.35em + 58px
   for three — the words go to the ear and the marks stay, as on a phone on its
   side. The measure is the bar's own width in em, so it moves with the
   reader's text size; English words are shorter, and give way later.
   The three cells read as one row: the marks on one line, the figure and the
   words on the next. So a cell's content stands at its top, not its middle,
   and what one cell has more of hangs below that shared line — the unit of
   a count that wrapped («۱۲۳٫۵» over «هزار»), or a count under the heart
   beside two bare marks — while its neighbours, stretched to the same height,
   keep the room at their foot. Centred, the heart rose 13–36px above the
   other two whenever its cell held one line more.
   The inset is what centres a mark and one line in the 60px cell (a 1px
   border each side, the 20px mark, 4px gap, a 1.35em line), so the everyday
   bar is as balanced and as tall as before; a larger text size outgrows the
   60px and the inset falls to its 8px floor.
   Where the words go to the ear, the heart keeps its own — «پسند» is the
   shortest of the three, and fits wherever the marks do — until a count
   takes its place. So the heart's cell always holds its mark and one line
   under it, and the first like only writes «۱» where «پسند» was: no mark in
   the bar moves. (Three bare marks used to stand in the middle, and the
   first like lifted all three 11px to the top line, and unliking dropped
   them again.) */
.hall-actions--bar { container: hx-bar / inline-size; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); align-items: stretch; gap: var(--s-2); }
.hall-actions--bar .btn { flex-direction: column; justify-content: flex-start; gap: 4px; min-width: 0; min-height: 60px; padding: max(var(--s-2), (60px - 2px - 24px - 1.35em) / 2) 6px; font-size: var(--fs-xs); }
.hall-actions--bar .btn > span { max-width: 100%; white-space: normal; text-align: center; line-height: 1.35; }
.hall-actions--bar[data-counted] [data-act="like"] .hall-actions__word { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
@container hx-bar (max-width: calc(10.5em + 60px)) {
  .hall-actions--bar:not(:lang(en)) .btn > span:not([data-like-count], .hall-actions__word) { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}
@container hx-bar (max-width: calc(7em + 60px)) {
  .hall-actions--bar .btn > span:not([data-like-count], .hall-actions__word) { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}

/* ── lightbox: a picture set in a carved stone window ──
   The window is cut to the picture's own shape and as large as the screen
   allows, so the whole picture shows. The frame is slabs: a lintel, a sill and
   two jambs, each of three or four stones, with an emerald-lit channel at the
   lip where stone meets picture.
   The dialog round it is the screen's, not the picture's: as tall as the
   screen less the backdrop's margins, and as wide as the widest picture of the
   set needs (--lb-maxar, set once by hall.js when it opens). The window is set
   into it like a window into a wall — the largest of the picture's shape that
   fits the stage (container units), centred — so from picture to picture only
   the window changes shape, and it eases there (--lb-ar is a registered
   number, so it transitions). The actions and the way on stand at the dialog's
   foot and never move under the pointer. A toast is laid over the top of the
   stage and takes no room from the picture. Nothing scrolls inside the dialog;
   only the words may, once the reader has opened a long description. */
@property --lb-ar { syntax: '<number>'; inherits: true; initial-value: 1.333; }
.modal--lightbox {
  --lb-vh: 100vh; --lb-gap: var(--gutter, 24px); --lb-frame: 30px; --lb-pad: var(--s-5);
  --lb-H: calc(var(--lb-vh) - 2 * var(--lb-gap));
  display: grid; grid-template-rows: minmax(0, 1fr);
  width: min(100%, 1180px); height: min(var(--lb-H), var(--lb-need, var(--lb-H))); max-height: var(--lb-H);
  padding: var(--lb-pad); overflow: hidden;
}
/* the dialog's height is counted in dvh, so the picture is too: a phone's toolbar is not screen */
@supports (height: 100dvh) { .modal--lightbox { --lb-vh: 100dvh; } }
.modal--lightbox > .modal__body, .modal--lightbox .lightbox { display: grid; min-width: 0; min-height: 0; }
.modal--lightbox > .modal__close {
  z-index: 3; top: 4px; inset-inline-end: 4px; width: 44px; min-height: 44px; height: 44px; padding: 0;
  display: grid; place-items: center; clip-path: var(--clip-hex); border: 0;
  background: linear-gradient(160deg, #3A3D41, #1C1D1F); color: #EDEFEA; box-shadow: none;
  transition: color var(--t-fast) var(--ease-stone), background var(--t-fast) var(--ease-stone);
}
.modal--lightbox > .modal__close .ico { --n: 20; --ico: 20px; stroke-width: 1.8; }
.modal--lightbox > .modal__close:hover, .modal--lightbox > .modal__close:focus-visible { color: var(--emerald); background: linear-gradient(160deg, #24453A, #0C1F18); }
.modal--lightbox > .modal__close:focus-visible { outline: 2px solid var(--emerald); outline-offset: -4px; }
/* a message («link copied») lies over the top of the stage, clear of the close button */
.modal--lightbox > .modal__toasts { position: absolute; z-index: 4; top: var(--lb-pad); inset-inline: var(--lb-pad) 60px; margin: 0; pointer-events: none; }
.modal--lightbox > .modal__toasts > * { pointer-events: auto; }
/* the stage, then the caption; the stage keeps a third of the dialog however long an opened description is */
.lightbox__fig { margin: 0; min-width: 0; min-height: 0; display: grid; grid-template-rows: minmax(30%, 1fr) minmax(0, auto); gap: var(--s-4); }
.lightbox__stage { position: relative; min-width: 0; min-height: 0; display: grid; place-items: center; container-type: size; }
.lightbox__window {
  --joint: rgba(0,0,0,.55); --joint-hi: rgba(255,255,255,.07);
  position: relative; box-sizing: border-box;
  width: min(100%, (var(--lb-H) * .55) * var(--lb-ar));
  width: min(100cqw, (100cqh - 2 * var(--lb-frame)) * var(--lb-ar) + 2 * var(--lb-frame));
  padding: var(--lb-frame);
  background:
    linear-gradient(90deg, transparent 31%, var(--joint) 31% calc(31% + 1px), var(--joint-hi) calc(31% + 1px) calc(31% + 2px), transparent 0 66%, var(--joint) 66% calc(66% + 1px), var(--joint-hi) calc(66% + 1px) calc(66% + 2px), transparent 0) top / 100% var(--lb-frame) no-repeat,
    linear-gradient(90deg, transparent 22%, var(--joint) 22% calc(22% + 1px), var(--joint-hi) calc(22% + 1px) calc(22% + 2px), transparent 0 57%, var(--joint) 57% calc(57% + 1px), var(--joint-hi) calc(57% + 1px) calc(57% + 2px), transparent 0 84%, var(--joint) 84% calc(84% + 1px), var(--joint-hi) calc(84% + 1px) calc(84% + 2px), transparent 0) bottom / 100% var(--lb-frame) no-repeat,
    linear-gradient(180deg, transparent 38%, var(--joint) 38% calc(38% + 1px), var(--joint-hi) calc(38% + 1px) calc(38% + 2px), transparent 0 71%, var(--joint) 71% calc(71% + 1px), var(--joint-hi) calc(71% + 1px) calc(71% + 2px), transparent 0) left / var(--lb-frame) 100% no-repeat,
    linear-gradient(180deg, transparent 29%, var(--joint) 29% calc(29% + 1px), var(--joint-hi) calc(29% + 1px) calc(29% + 2px), transparent 0 63%, var(--joint) 63% calc(63% + 1px), var(--joint-hi) calc(63% + 1px) calc(63% + 2px), transparent 0) right / var(--lb-frame) 100% no-repeat,
    var(--stone-grad-2);
  clip-path: polygon(12px 0, calc(100% - 12px) 0, 100% 12px, 100% calc(100% - 12px), calc(100% - 12px) 100%, 12px 100%, 0 calc(100% - 12px), 0 12px);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.08), inset 0 -2px 0 rgba(0,0,0,.5), inset 0 0 0 1px rgba(0,0,0,.35);
  /* from one picture's shape to the next: eased, never a cut (instant under reduced motion, base.css) */
  transition: --lb-ar 240ms cubic-bezier(.3,.7,.4,1);
}
:root[data-theme="light"] .lightbox__window { --stone-grad-2: linear-gradient(160deg, #D5D8D1 0%, #C3C7BF 55%, #B2B6AE 100%); --joint: rgba(20,24,22,.3); --joint-hi: rgba(255,255,255,.55); box-shadow: inset 0 1px 0 rgba(255,255,255,.9), inset 0 -2px 0 rgba(20,24,22,.12), inset 0 0 0 1px rgba(20,24,22,.12); }
.lightbox__pane {
  position: relative; aspect-ratio: var(--lb-ar); overflow: hidden; background: #050607;
  box-shadow: 0 0 0 1px rgba(47,211,154,.6), 0 0 0 4px rgba(4,5,6,.9), 0 0 0 5px rgba(255,255,255,.07), 0 0 24px 4px rgba(47,211,154,.18);
}
/* one picture to a layer: during a step the leaving one and the arriving one overlap (hall.js) */
.lightbox__shot { position: absolute; inset: 0; }
.lightbox__shot > .hx-cover, .lightbox__img { display: block; width: 100%; height: 100%; object-fit: contain; }
.lightbox__shot.is-leaving { pointer-events: none; }
/* The window emptied by a step past the last picture loaded, while the next
   page comes (hall.js): the site's rune ring at 40px, its label for the ear;
   or the line that says the picture did not come, and the way to try again.
   The pane is dark in both themes, so this is set in the dark theme's light. */
.lightbox__wait { position: absolute; inset: 0; z-index: 1; display: grid; place-content: center; justify-items: center; gap: var(--s-3); padding: var(--s-4); text-align: center; color: #C9CDC6; }
.lightbox__wait .loading { padding: 0; animation: none; }
.lightbox__wait .loading > span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.lightbox__wait .rune-ring { margin: -28px; transform: scale(.42); }
:root .lightbox__pane .lightbox__wait .rune-ring span { color: color-mix(in srgb, #2FD39A calc(var(--lit) * 100%), #8F948E); text-shadow: 0 0 calc(var(--lit) * 10px) rgba(47,211,154,.6); }
.lightbox__wait .rune-ring::after { background: #2FD39A; }
.lightbox__wait.is-failed p { margin: 0; font-size: var(--fs-sm); line-height: 1.7; }
/* the caption: the words, then the controls at its foot */
.lightbox__cap { position: relative; min-width: 0; min-height: 0; display: flex; flex-direction: column; gap: var(--s-4); }
/* Under the picture the words keep the room the tallest caption so far has
   needed (--lb-room, hall.js), so a title's second line does not move the
   window. They are the one part that may scroll, and only once opened; the
   inset keeps a focus ring inside the scrolling box. */
.lightbox__words { position: relative; flex: 0 1 auto; min-height: var(--lb-room, 0px); overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; padding: 4px; margin: -4px; }
.lightbox__words.is-more-below { -webkit-mask-image: linear-gradient(#000 calc(100% - 32px), transparent); mask-image: linear-gradient(#000 calc(100% - 32px), transparent); }
/* the words that are leaving fade out over the ones arriving, clipped to the room the new ones take */
.lightbox__info.is-leaving { position: absolute; inset: 4px 4px auto; max-height: calc(100% - 8px); overflow: hidden; pointer-events: none; }
.lightbox__info { min-width: 0; }
.lightbox__title { font-size: 1.5rem; line-height: 1.4; margin: 0 0 var(--s-2); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere; }
.lightbox__by { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); font-size: var(--fs-sm); color: var(--fg-muted); }
/* the flag closes the maker's line, quiet, away from the actions */
.lightbox__flag { display: inline-flex; margin-inline-start: auto; margin-block: -6px; }
.lightbox__by .card__author { color: var(--fg); font-weight: 600; }
/* one row of tags (hall.js hides those that wrap behind a «+N»), one line of description */
.lightbox__tags { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: var(--s-2); min-width: 0; }
.lightbox__tags .tag { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lightbox__tagmore { cursor: pointer; font-variant-numeric: tabular-nums; color: var(--accent-text); border-color: var(--line-glow); background: none; }
.lightbox__tagmore:hover, .lightbox__tagmore:focus-visible { border-color: var(--accent); }
.lightbox__alt { font-size: var(--fs-xs); line-height: 1.8; color: var(--fg-muted); margin: var(--s-2) 0 0; max-width: 64ch; display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden; }
.lightbox__alt.is-open { display: block; -webkit-line-clamp: none; }
.lightbox__more { padding: 0; min-height: 32px; background: none; border: 0; color: var(--accent-text); font-size: var(--fs-xs); font-weight: 600; text-decoration: underline; text-underline-offset: 4px; cursor: pointer; }
@media (pointer: coarse) { .lightbox__more { min-height: 44px; } .lightbox__tagmore { min-height: 32px; } }
/* The actions, then the way on: one row from a tablet up, a row each on a
   phone — and a row each wherever the two no longer fit side by side, which a
   larger text size brings on at any width: the actions ask for the room their
   words need (the bar's measure above), and the way on goes under them
   instead of squeezing their cells to one letter each. */
.lightbox__controls { container: hx-lbctl / inline-size; flex: none; display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-3) var(--s-5); }
.lightbox__controls > .hall-actions { flex: 999 1 calc(10.5em + 60px); min-width: 0; }
/* «قبلی», the count, «بعدی»: the count takes what is between and is centred
   there; the buttons keep their own width and never pass the frame. On a line
   of its own the way on spans it. */
.lightbox__nav { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: var(--s-3); flex: 1 0 auto; }
.lightbox__count { color: var(--fg-muted); font-size: var(--fs-sm); font-variant-numeric: tabular-nums; min-width: 6ch; text-align: center; }
/* When the line cannot hold «قبلی ۱۲ از ۹۶+ بعدی» — two buttons' 148px of
   padding, mark and gap, and about 6.8em of words in Persian, 8.6em in
   English — the buttons become their arrows, 44px each, the words left to the
   ear (as on a phone on its side). In em, so it holds at every text size. A
   longer count («۱۲۳ از ۲۴۰+») may take a second line in the room between;
   it is never cut. */
@container hx-lbctl (max-width: calc(7em + 150px)) {
  .lightbox__nav:not(:lang(en)) .lightbox__way { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .lightbox__nav:not(:lang(en)) .btn { width: 44px; min-height: 44px; padding: 0; justify-content: center; }
}
@container hx-lbctl (max-width: calc(8.75em + 150px)) {
  .lightbox__nav:lang(en) .lightbox__way { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .lightbox__nav:lang(en) .btn { width: 44px; min-height: 44px; padding: 0; justify-content: center; }
}
/* Busy (the step past the last picture loaded, while the next page comes):
   the ring turns where the arrow was, so the button keeps its width and
   nothing beside it moves. */
.lightbox__nav [data-lb="next"][aria-busy="true"] .ico { display: none; }
.lightbox__nav [data-lb="next"][aria-busy="true"]::before { order: 1; margin-inline: 3px; }
@media (max-width: 600px) {
  .modal--lightbox { --lb-frame: 14px; --lb-pad: var(--s-3); padding-top: 56px; }
  .lightbox__title { font-size: 1.25rem; }
  .lightbox__controls { gap: var(--s-3); }
  .lightbox__controls > .hall-actions, .lightbox__nav { flex: 1 1 100%; }
}
/* A wide screen — or one on its side, where a caption under the picture would
   leave it a strip — sets the caption beside the picture, a column of its
   own: the words at its top, the actions and the way on at its foot, and the
   picture takes the full height.
   The column is at least 17.5rem, so it grows with the reader's text size
   (at 100 % that floor is the old 280px and nothing changes): at 150 % the
   words, the three actions with theirs and «قبلی ۱ از ۸ بعدی» still fit
   instead of turning to marks. It never takes more than 45 % of the screen
   from the picture. */
@media (min-width: 1100px), (min-width: 900px) and (orientation: landscape), (min-width: 560px) and (max-height: 500px) and (orientation: landscape) {
  .modal--lightbox {
    --lb-side: min(max(clamp(280px, 30vw, 340px), 17.5rem), 45vw);
    width: min(100%, 1480px, max(900px, (var(--lb-H) - 2 * var(--lb-pad) - 2 * var(--lb-frame)) * var(--lb-maxar, 1.333) + 2 * var(--lb-frame) + var(--lb-side) + 2 * var(--lb-pad) + var(--s-5)));
  }
  .modal--lightbox > .modal__toasts { inset-inline-end: calc(var(--lb-side) + var(--lb-pad) + var(--s-5)); }
  .lightbox__fig { grid-template-columns: minmax(0, 1fr) var(--lb-side); grid-template-rows: minmax(0, 1fr); column-gap: var(--s-5); }
  .lightbox__cap { padding-top: var(--s-6); }
  .lightbox__words { min-height: 0; }
  .lightbox__controls { margin-top: auto; flex-direction: column; flex-wrap: nowrap; align-items: stretch; gap: var(--s-4); }
  .lightbox__controls > .hall-actions, .lightbox__nav { flex: none; }
}
/* A phone on its side (740×360, 844×390, 915×412): the whole screen is the
   dialog, the frame is a thin stone, and the caption column is compact — a
   one-line title beside the close button's corner, a one-line maker, one row
   of tags, the description folded behind its button, the actions three
   44px tiles (their words left to the ear; a like count stays), and the way
   on two 44px arrows with the count between them. The picture keeps at least
   four fifths of the screen's height. */
@media (min-width: 560px) and (max-height: 500px) and (orientation: landscape) {
  .modal-backdrop:has(> .modal--lightbox) { padding: 0; }
  /* (the column grows with the text size here too, or at 200 % «۱۲۳٫۵» alone was wider than its cell) */
  .modal--lightbox { --lb-gap: 0px; --lb-frame: 10px; --lb-pad: var(--s-2); --lb-side: min(max(clamp(220px, 32vw, 300px), 13.75rem), 45vw); padding: var(--lb-pad); }
  .modal--lightbox > .modal__toasts { inset-inline-end: calc(var(--lb-side) + var(--lb-pad) + var(--s-3)); }
  .lightbox__fig { column-gap: var(--s-3); }
  .lightbox__cap { padding-top: 44px; gap: var(--s-2); }
  .lightbox__title { font-size: 1.125rem; -webkit-line-clamp: 1; margin-bottom: var(--s-1); }
  .lightbox__by { flex-wrap: nowrap; min-width: 0; }
  .lightbox__by .card__author { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .lightbox__tags { margin-top: var(--s-1); }
  .lightbox__alt:not(.is-open) { display: none; }
  .lightbox__controls { gap: var(--s-2); }
  .lightbox__controls .hall-actions--bar { gap: var(--s-1); }
  /* the mark over its count, as at every width, packed into 44px: a «123.5K» keeps the tile's whole width
     (the heart and its count — or, before the first like, its word — fill the 44px, so the bare marks
     beside them stand on the heart's line, and a first like moves none of them) */
  .lightbox__controls .hall-actions--bar .btn { gap: 2px; min-height: 44px; padding: 2px 4px; line-height: 1.25; }
  .lightbox__controls .hall-actions--bar .btn > span:not([data-like-count], .hall-actions__word), .lightbox__way { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .lightbox__nav .btn { width: 44px; min-height: 44px; padding: 0; justify-content: center; }
}

/* ── the reading view ──
   One unit — the text column and its notes beside it — centred on the page, with
   the header, the cover and the author set to the same edges. Everything
   vertical counts in lines of body text (19px × 1.95 ≈ 37px) and half-lines. */
.pg-hall .article {
  --text: calc(1.185rem * 34);   /* 34em of body text, ≈ 65 Persian characters a line */
  --notes: 15rem;
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, var(--text)) var(--s-6) var(--notes) minmax(0, 1fr);
  padding-block: var(--s-4) var(--s-6);
}
.pg-hall .article > * { grid-column: 2 / 5; min-width: 0; }
.pg-hall .article > .article__grid { grid-column: 2 / 3; }
.pg-hall .article > .article__related { grid-column: 1 / -1; }
@media (max-width: 1099px) {
  .pg-hall .article { grid-template-columns: minmax(0, 1fr) minmax(0, var(--text)) minmax(0, 1fr); }
  .pg-hall .article > *, .pg-hall .article > .article__grid { grid-column: 2; }
  .pg-hall .article > .article__related { grid-column: 1 / -1; }
}
.pg-hall .article__head { display: grid; gap: var(--s-3); margin-bottom: var(--s-5); }
.pg-hall .article__head h1 { margin: 0; font-size: clamp(2.125rem, 1.4rem + 2.8vw, 3.4rem); line-height: 1.3; }
.pg-hall .article__excerpt { font-size: var(--fs-lg); line-height: 1.8; color: var(--fg-muted); margin: 0; max-width: 58ch; }
.pg-hall .article__meta { display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap; color: var(--fg-muted); font-size: var(--fs-sm); line-height: 1.7; }
.pg-hall .article__meta b { color: var(--fg-strong); }
/* a line of facts (metaLine in hall.js), as on the profile (misc.css): each
   fact holds together and carries the lozenge before it; the row is pulled
   back by one lozenge's room (5px + 2 × 8px) and its holder clips that room,
   so the first fact of every line loses its lozenge with the line's start. A
   wrapped line neither ends nor starts on a separator. Only text lives in it,
   so the clip never cuts a focus ring (the by-line link stands outside). */
.pg-hall .meta-line { display: block; min-width: 0; overflow: hidden; }
.pg-hall .meta-line__in { display: flex; flex-wrap: wrap; align-items: center; margin-inline-start: -21px; }
.pg-hall .meta-part { min-width: 0; max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pg-hall .meta-part::before { content: ""; display: inline-block; width: 5px; height: 5px; margin-inline: 8px; vertical-align: middle; background: var(--ornament); transform: rotate(45deg); }
@media (forced-colors: active) { .pg-hall .meta-part::before { forced-color-adjust: none; background: CanvasText; } }
.pg-hall .article__by { color: inherit; text-decoration: none; display: inline-grid; line-height: 1.6; min-width: 0; }
.pg-hall a.article__by:hover, .pg-hall a.article__by:focus-visible { color: var(--accent-text); }
.pg-hall a.article__by:hover b { color: var(--accent-text); }
/* the cover spans the text and its notes; the portal's roof is a line over it, not a crop */
.pg-hall .article__cover { position: relative; margin: 0 0 calc(1.185rem * 1.95 * 1.5); aspect-ratio: 21 / 9; max-height: 56vh; overflow: hidden; background: var(--bg-elev); border: 1px solid var(--line-strong); }
.pg-hall .article__cover > .hx-cover { width: 100%; height: 100%; object-fit: cover; }
.pg-hall .article__cover::after { inset: 12px 12px auto; opacity: .55; }
.pg-hall .article__cover::before { content: ""; position: absolute; inset: auto 0 0; height: 40px; z-index: 1; background: linear-gradient(transparent, rgba(8,9,10,.5)); pointer-events: none; }
@media (max-width: 699px) {
  .pg-hall .article__cover { aspect-ratio: 16 / 9; margin-inline: calc(-1 * var(--gutter)); border-inline: 0; }
}
.pg-hall .article__grid { position: relative; }

/* reading typography, shared by the article and the editor, so a writer sees what readers get */
.pg-hall .reading { --rl: calc(1.185rem * 1.95); font-size: 1.185rem; line-height: 1.95; max-width: none; }
.pg-hall .article__body { max-width: var(--text); }
.pg-hall .reading p { margin: 0 0 var(--rl); max-width: none; }
.pg-hall .reading h2 { position: relative; font-size: 1.625rem; line-height: var(--rl); margin: calc(var(--rl) * 2) 0 calc(var(--rl) / 2); color: var(--fg-strong); }
.pg-hall .reading h3 { position: relative; font-size: 1.25rem; line-height: var(--rl); margin: var(--rl) 0 calc(var(--rl) / 2); color: var(--fg-strong); }
.pg-hall .reading > :first-child, .pg-hall .reading > .sidenote:first-child + * { margin-top: 0; }
/* a small lit hex in the margin marks a section; the heading's own edge stays clean */
.pg-hall .reading h2::before { content: ""; position: absolute; inset-inline-start: -26px; top: calc(var(--rl) / 2 - 5px); width: 10px; height: 10px; clip-path: var(--clip-hex); background: var(--accent); opacity: .85; }
.pg-hall .reading ul, .pg-hall .reading ol { margin: 0 0 var(--rl); padding-inline-start: 1.4em; }
.pg-hall .reading li { margin-bottom: calc(var(--rl) / 4); }
.pg-hall .reading hr { border: 0; height: 1px; margin: calc(var(--rl) * 1.5) auto; width: 40%; background: linear-gradient(90deg, transparent, var(--line-strong), transparent); }
/* the pull quote: display face, a lit rule, a line and a half of air either side */
.pg-hall .reading blockquote {
  clear: inline-end; margin: calc(var(--rl) * 1.5) 0; padding: 0; padding-inline-start: 24px;
  border-inline-start: 2px solid var(--accent); background: none;
  font-family: var(--font-display); font-weight: 700; font-size: 1.5rem; line-height: 1.6; color: var(--fg-strong);
}
.pg-hall .reading blockquote p { margin: 0; }
.pg-hall .reading blockquote p + p { margin-top: calc(var(--rl) / 2); }
@media (min-width: 1100px) { .pg-hall .article__body blockquote { margin-inline-end: -8rem; } }
@media (max-width: 699px) {
  .pg-hall .reading h2 { font-size: 1.375rem; padding-inline-start: 20px; }
  .pg-hall .reading h2::before { inset-inline-start: 0; }
  .pg-hall .reading blockquote { font-size: 1.25rem; padding-inline-start: 16px; }
}
.pg-hall .article__body .divider { margin-top: calc(var(--rl) * 1.5); }

/* the raised initial: one short word, exactly two lines deep, carved in emerald,
   with its rune set out in the margin — ᚨ, the rune of the spoken word, not a
   lone ᛟ (the one rune hate-symbol lists flag) — and never above a Persian
   letter, where it would read as a vowel mark */
.pg-hall .dropcap {
  float: inline-start; position: relative;
  font-family: var(--font-display); font-weight: 900; font-size: 3.3em; line-height: 1;
  /* the box ends on the second line's baseline: the letters stand on it, the underline lies under it */
  height: calc(var(--rl) * 2 - 24px); margin-block-start: .14em; margin-inline-end: .3em; margin-block-end: 0;
  color: var(--accent-text); text-shadow: 0 0 10px rgba(47,211,154,.28);
}
:root[data-theme="light"] .pg-hall .dropcap { color: var(--jade); text-shadow: none; }
.pg-hall .dropcap::before { content: ""; position: absolute; inset-inline-start: 0; bottom: 0; width: 60%; height: 1px; background: var(--emerald); opacity: .8; }
/* the initial's mark: ansuz, drawn on the stave grid of HX.art.rune (the font's
   runes come out at mixed heights), carried here as a mask so the pseudo-element
   can draw it in the accent colour */
.pg-hall .dropcap::after {
  content: ""; position: absolute; inset-inline-start: -24px; top: 50%; width: 10px; height: 15px; margin-top: -7.5px;
  background: var(--accent-text); opacity: .5;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='butt' stroke-linejoin='miter'%3E%3Cpath d='M5 22.75V1.25L11.5 7.75M5 7.5L11.5 14'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='butt' stroke-linejoin='miter'%3E%3Cpath d='M5 22.75V1.25L11.5 7.75M5 7.5L11.5 14'/%3E%3C/svg%3E") center / contain no-repeat;
}
@media (max-width: 599px) { .pg-hall .dropcap::after { display: none; } }

/* margin notes: beside their paragraph on a wide screen, set into the text on a narrow one */
.pg-hall .sidenote { font-size: .875rem; line-height: 1.8; color: var(--fg-muted); }
.pg-hall .sidenote b { display: block; color: var(--fg-strong); font-weight: 700; }
/* the definition keeps its own direction (an English one in a Persian article) */
.pg-hall .sidenote__def { display: block; text-align: start; }
.pg-hall .sidenote__n { float: inline-start; margin-inline-end: var(--s-2); color: var(--accent-text); font-weight: 700; font-variant-numeric: tabular-nums; }
.pg-hall .note-mark { margin-inline-start: 2px; color: var(--accent-text); font-size: .62em; font-weight: 700; line-height: 0; vertical-align: super; }
.pg-hall .reading h2 .note-mark, .pg-hall .reading h3 .note-mark { font-size: .55em; }
@media (min-width: 1100px) {
  .pg-hall .article__body .sidenote {
    float: inline-end; clear: inline-end; width: var(--notes);
    margin-inline-end: calc(-1 * (var(--notes) + var(--s-6))); margin-block: .5em var(--s-4);
    padding-inline-start: var(--s-3); border-inline-start: 1px solid var(--accent);
  }
}
@media (max-width: 1099px) {
  .pg-hall .article__body .sidenote { margin: 0 0 var(--rl); padding: var(--s-3) var(--s-4); background: var(--bg-elev); border-inline-start: 2px solid var(--accent); }
  /* notes that follow one another read as one box */
  .pg-hall .article__body .sidenote:has(+ .sidenote) { margin-bottom: 0; padding-bottom: var(--s-2); }
  .pg-hall .article__body .sidenote + .sidenote { padding-top: var(--s-2); }
}

/* ── reading progress: an emerald fissure spreading down the stone beside the text ──
   Drawn by hall.js for the size it is shown at; lit by stroke offset, so
   scrolling never lays anything out. */
.pg-hall .read-crack { position: absolute; inset-block: 0; inset-inline-start: -66px; width: 14px; pointer-events: none; }
.pg-hall .read-crack__rail { position: sticky; top: calc(var(--sticky-top) + var(--s-4)); height: calc(100vh - var(--sticky-top) - var(--s-4) - var(--s-6)); }
.pg-hall .read-crack svg { position: absolute; top: 0; left: 0; overflow: visible; }
.pg-hall .read-crack__bed path { fill: none; stroke: var(--line-strong); stroke-width: 1.5; stroke-linejoin: round; stroke-linecap: round; }
.pg-hall .read-crack__bed .read-crack__br { stroke-width: 1; }
.pg-hall .read-crack__lit { filter: drop-shadow(0 0 6px rgba(47,211,154,.6)); }
.pg-hall .read-crack__lit path { fill: none; stroke: var(--emerald); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
:root[data-theme="light"] .pg-hall .read-crack__lit path { stroke: #13946B; }
.pg-hall .read-crack__tip { position: absolute; top: -3px; left: -3px; width: 6px; height: 6px; clip-path: var(--clip-hex); background: var(--emerald-soft); opacity: 0; transition: opacity var(--t-fast) var(--ease-out); }
.pg-hall .read-crack.is-lit .read-crack__tip { opacity: 1; }
/* Where the margin cannot hold the rail — a narrow screen, or a large text
   size that fills the screen with the column — the crack runs along the top
   instead (hall.js sets .is-bar), never past the screen's edge. */
.pg-hall .read-crack.is-bar { position: fixed; inset-block: var(--hdr-h, 68px) auto; inset-inline: 0; width: auto; height: 4px; z-index: calc(var(--z-nav) - 1); }
.pg-hall .read-crack.is-bar .read-crack__rail { position: absolute; inset: 0; top: 0; height: 4px; }
.pg-hall .read-crack.is-bar .read-crack__tip { display: none; }

/* the author */
.pg-hall .author-box { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--s-5); align-items: center; margin-block: var(--s-7); padding: var(--s-5); background: var(--stone-grad); border: 1px solid var(--line); --facet: 14px; clip-path: var(--clip-facet); box-shadow: var(--shadow-stone); }
.pg-hall .author-box__kicker { display: block; font-size: var(--fs-xs); font-weight: 600; color: var(--fg-muted); }
.pg-hall .author-box h2 { margin: 2px 0 var(--s-2); font-size: 1.5rem; line-height: 1.4; color: var(--fg-strong); }
.pg-hall .author-box h2 a { color: var(--fg-strong); }
.pg-hall .author-box h2 a:hover { color: var(--accent-text); }
.pg-hall .author-box h2 small { font-family: var(--font-body); font-weight: 400; font-size: var(--fs-sm); color: var(--fg-muted); }
.pg-hall .author-box__links { gap: var(--s-2) var(--s-4); font-size: var(--fs-sm); }
.pg-hall .author-box__links a { display: inline-flex; align-items: center; min-height: 32px; color: var(--accent-text); }
@media (max-width: 600px) { .pg-hall .author-box { grid-template-columns: 1fr; justify-items: start; gap: var(--s-3); } }
.pg-hall .article__related .sec-head, .pg-hall .missing__more .sec-head { margin-bottom: var(--s-4); }
.pg-hall .related .hcard { margin: 0; }

/* ── video view: the screen and its story on the reading side, the rest beside it ── */
.pg-hall .video-layout { display: grid; grid-template-columns: minmax(0, 8fr) minmax(0, 4fr); gap: var(--s-6); align-items: start; margin-bottom: var(--s-7); }
.pg-hall .video-main, .pg-hall .video-side { min-width: 0; }
.pg-hall .video-side { display: grid; gap: var(--s-5); }
@media (max-width: 1099px) { .pg-hall .video-layout { grid-template-columns: minmax(0, 1fr); gap: var(--s-5); } }
.pg-hall .player { position: relative; aspect-ratio: 16 / 9; background: #000; overflow: hidden; border: 1px solid var(--line-strong); clip-path: var(--clip-facet); --facet: 14px; }
.pg-hall .player > .hx-cover { width: 100%; height: 100%; object-fit: cover; }
.pg-hall .player__btn { position: absolute; inset: 0; display: grid; place-items: center; background: none; border: 0; padding: 0; text-decoration: none; }
.pg-hall .player__btn span { width: 96px; height: 96px; clip-path: var(--clip-hex); background: var(--emerald-grad); color: var(--accent-fg); display: grid; place-items: center; box-shadow: var(--glow-strong); transition: transform var(--t-ui) var(--ease-stone); }
.pg-hall .player__btn .ico { --n: 32; --ico: 32px; stroke-width: 1.5; margin-inline-start: 4px; }
.pg-hall .player__btn:hover span { transform: scale(1.06); }
.pg-hall .player--embed { clip-path: none; }
.pg-hall .player--embed iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
/* nothing to play yet: the play mark is set in stone, not offered as a button,
   and a band across the whole screen says why (the player is always dark) */
.pg-hall .player--empty > .hx-cover { filter: saturate(.55) brightness(.62); }
.pg-hall .player__hex { position: absolute; inset: 0; display: grid; place-items: center; padding-bottom: 40px; }
.pg-hall .player__hex span { width: 96px; height: 96px; clip-path: var(--clip-hex); background: linear-gradient(160deg, #3A3D41, #18191B); color: rgba(237,239,234,.42); display: grid; place-items: center; }
.pg-hall .player__hex .ico { --n: 32; --ico: 32px; stroke-width: 1.5; margin-inline-start: 4px; }
.pg-hall .player__note { position: absolute; inset-inline: 0; bottom: 0; max-width: none; margin: 0; padding: var(--s-3) var(--s-5); background: rgba(0,0,0,.72); -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px); color: #C9CDC6; font-size: var(--fs-sm); line-height: 1.8; text-align: center; }
.pg-hall .video-head { margin-top: var(--s-5); display: grid; gap: var(--s-3); }
.pg-hall .video-head h1 { margin: 0; font-size: clamp(1.75rem, 1.2rem + 2vw, 2.6rem); line-height: 1.35; }
.pg-hall .video-head__out { margin: 0; }
/* the description sits in the post's own direction, as the title over it does,
   so its first line starts at the title's edge */
.pg-hall .video-desc { margin-top: var(--s-5); font-size: var(--fs-lg); line-height: 1.95; color: var(--fg); max-width: var(--text, 40rem); }
.pg-hall .video-side .author-box { margin: 0; padding: var(--s-4); gap: var(--s-3); grid-template-columns: auto minmax(0, 1fr); }
.pg-hall .video-side .author-box .avatar--lg { width: 56px; height: 56px; }
.pg-hall .video-side .author-box h2 { font-size: 1.125rem; }
.pg-hall .vnext__h { font-size: var(--fs-lg); margin: 0 0 var(--s-3); }
.pg-hall .vnext__list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-1); }
.pg-hall .vnext__item { display: grid; grid-template-columns: 136px minmax(0, 1fr); gap: var(--s-3); align-items: start; padding: 6px; color: inherit; text-decoration: none; border: 1px solid transparent; transition: background var(--t-fast) var(--ease-stone), border-color var(--t-fast) var(--ease-stone); }
.pg-hall .vnext__item:hover { background: rgba(255,255,255,.03); border-color: var(--line); text-decoration: none; }
.pg-hall .vnext__item:hover b { color: var(--accent-text); }
.pg-hall .vnext__thumb { position: relative; display: block; aspect-ratio: 16 / 9; overflow: hidden; background: #000; box-shadow: 0 0 0 1px rgba(47,211,154,.25); }
.pg-hall .vnext__thumb .hx-cover { width: 100%; height: 100%; object-fit: cover; }
.pg-hall .vnext__dur { position: absolute; bottom: 4px; inset-inline-start: 4px; padding: 0 6px; font-size: var(--fs-2xs); line-height: 1.6; background: rgba(10,10,11,.8); color: var(--frost); direction: ltr; unicode-bidi: isolate; font-variant-numeric: tabular-nums; }
.pg-hall .vnext__text { display: grid; gap: 2px; min-width: 0; }
.pg-hall .vnext__text b { font-size: .9375rem; line-height: 1.55; color: var(--fg-strong); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere; }
.pg-hall .vnext__text small { font-size: var(--fs-xs); color: var(--fg-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (min-width: 700px) and (max-width: 1099px) { .pg-hall .vnext__list { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* ── crumbs: a finger-sized target on every link; a long title ends in an ellipsis ── */
.pg-hall .crumbs { align-items: center; margin-bottom: var(--s-3); }
.pg-hall .crumbs li { align-items: center; min-width: 0; }
.pg-hall .crumbs a { display: inline-flex; align-items: center; min-height: 44px; padding-inline: 4px; }
.pg-hall .crumbs [aria-current="page"] { display: block; max-width: min(40ch, 64vw); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; overflow-wrap: normal; }

/* ── compose / upload ── */
.pg-hall .compose { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: var(--s-7); align-items: start; margin-bottom: var(--s-7); }
.pg-hall .compose__form { gap: var(--s-5); min-width: 0; }
.pg-hall .compose__preview { position: sticky; top: calc(var(--sticky-top) + var(--s-4)); display: grid; gap: var(--s-3); }
.pg-hall .compose__preview .hcard { margin: 0; }
.pg-hall .compose__actions { margin-top: var(--s-2); }
/* a form that cannot be sent yet is shown, but cannot be touched */
.pg-hall .compose.is-blocked { opacity: .5; }
@media (max-width: 960px) { .pg-hall .compose { grid-template-columns: minmax(0, 1fr); } .pg-hall .compose__preview { position: static; } }
.pg-hall .dropzone { display: grid; justify-items: center; text-align: center; gap: var(--s-1); padding: var(--s-7) var(--s-5); border: 1px dashed var(--line-strong); clip-path: var(--clip-facet); background: rgba(255,255,255,.015); cursor: pointer; transition: border-color var(--t-ui) var(--ease-stone), background var(--t-ui) var(--ease-stone), box-shadow var(--t-ui) var(--ease-stone); }
.pg-hall .dropzone .ico { --n: 32; --ico: 32px; stroke-width: 1.5; color: var(--accent-text); margin-bottom: var(--s-2); }
.pg-hall .dropzone b { color: var(--fg-strong); }
.pg-hall .dropzone span { font-size: var(--fs-sm); text-wrap: balance; }
.pg-hall .dropzone:hover { border-color: var(--line-glow); }
/* The zone is cut with a clip-path, which took the ring drawn outside it, and
   its focus was only its hover: a dashed hairline turning glow (at best 2.9:1,
   0.3% of its pixels). Focus is a ring inside the cut, as on every faceted
   control (base.css), and the frame turns whole and emerald, its chamfers
   drawn too, so the ring's clipped corners are closed. */
.pg-hall .dropzone:focus-visible {
  --bd: var(--accent); border: 1px solid var(--bd); background: var(--facet-edges), rgba(255,255,255,.015);
  outline-offset: -4px; box-shadow: var(--glow-inset); border-radius: 0;
}
.pg-hall .dropzone.is-over { border-color: var(--emerald); background: rgba(47,211,154,.06); box-shadow: var(--glow-inset), var(--glow); }
.pg-hall .thumbs { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: var(--s-3); margin-top: var(--s-3); }
.pg-hall .thumbs:empty { display: none; }
.pg-hall .thumb { position: relative; margin: 0; aspect-ratio: 4 / 3; clip-path: var(--clip-facet); --facet: 8px; overflow: hidden; background: var(--bg-elev); border: 1px solid var(--line); }
.pg-hall .thumb img { width: 100%; height: 100%; object-fit: cover; }
.pg-hall .thumb figcaption { position: absolute; inset-inline: 0; bottom: 0; display: grid; padding: 4px 8px; background: rgba(10,10,11,.7); color: var(--frost); font-size: var(--fs-2xs); line-height: 1.5; }
.pg-hall .thumb figcaption span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pg-hall .thumb__x { position: absolute; top: 4px; inset-inline-start: 4px; width: 32px; height: 32px; padding: 0; background: rgba(10,10,11,.75); border: 1px solid var(--line-strong); color: var(--frost); font-size: var(--fs-2xs); }
.pg-hall .thumb__x:hover { border-color: var(--ember-soft); color: var(--ember-soft); }
/* ready-made covers: native radios (one Tab stop, arrow keys choose) under picture labels */
.pg-hall .covers-field { border: 0; padding: 0; margin: 0; min-width: 0; }
.pg-hall .covers-field > legend { padding: 0; margin-bottom: var(--s-2); }
.pg-hall .covers { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: var(--s-2); }
.pg-hall .cover-opt { position: relative; display: block; aspect-ratio: 4 / 3; overflow: hidden; cursor: pointer; background: var(--bg); border: 1px solid var(--line); clip-path: var(--clip-facet); --facet: 8px; transition: border-color var(--t-ui) var(--ease-stone); }
.pg-hall .cover-opt__art { position: absolute; inset: 0; }
.pg-hall .cover-opt__name { position: absolute; inset-inline: 0; bottom: 0; z-index: 1; padding: 2px 6px; font-size: var(--fs-2xs); line-height: 1.6; color: #EDEFEA; background: rgba(10,10,11,.72); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pg-hall .cover-opt::after { content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none; transition: box-shadow var(--t-ui) var(--ease-stone); }
.pg-hall .cover-opt:hover { border-color: var(--line-glow); }
.pg-hall .cover-opt:has(input:checked) { border-color: var(--emerald); }
.pg-hall .cover-opt:has(input:checked)::after { box-shadow: inset 0 0 0 2px var(--emerald), inset 0 0 22px rgba(47,211,154,.35); }
.pg-hall .cover-opt:has(input:focus-visible)::after { box-shadow: inset 0 0 0 3px var(--accent), inset 0 0 0 5px rgba(0,0,0,.6); }
@media (max-width: 600px) {
  /* five across, two rows: no orphan; the name sits under its picture */
  .pg-hall .covers { gap: 6px; }
  .pg-hall .cover-opt { aspect-ratio: auto; display: grid; grid-template-rows: 44px auto; }
  .pg-hall .cover-opt__art { position: relative; }
  .pg-hall .cover-opt__name { position: static; padding: 2px; text-align: center; white-space: normal; line-height: 1.35; min-height: 2.7em; display: grid; place-items: center; }
}
.pg-hall .tagbox { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; padding: 6px 8px; cursor: text; }
.pg-hall .tagbox input { flex: 1; min-width: 140px; min-height: 30px; background: none; border: 0; outline: none; color: var(--fg-strong); padding: 0 4px; }
/* The field is the box, not the bare input inside it: focus lights the box's
   frame exactly as it lights the title's (components.css .input:focus-visible),
   and the input draws no second, inner rectangle of its own. */
.pg-hall .tagbox:focus-within { border-color: var(--accent); box-shadow: inset 0 2px 6px rgba(0,0,0,.55), 0 0 0 1px var(--accent), var(--glow-soft); border-radius: var(--r-1); }
:root[data-theme="light"] .pg-hall .tagbox:focus-within { box-shadow: inset 0 2px 4px rgba(24,36,34,.1), 0 0 0 1px var(--accent), 0 0 0 4px rgba(15,107,79,.14); }
.pg-hall .tagbox input:focus-visible { outline: none; box-shadow: none; }
@media (forced-colors: active) { .pg-hall .tagbox:focus-within { outline: 2px solid Highlight; outline-offset: 2px; } }
.pg-hall .tagbox input::placeholder { color: var(--fg-faint); }
/* An added tag is a token, not a toggle: the on-chip's fill and edge, but
   not its tick, which said «selected, press to unselect» beside the ✕ that
   is the only thing that removes it. */
.pg-hall .tagbox .chip { cursor: default; min-height: 28px; padding-inline-end: 4px; }
.pg-hall .tagbox .chip--token::before { content: none; display: none; }
.pg-hall .tagbox .tag-x { display: inline-grid; place-items: center; min-width: 24px; min-height: 24px; padding: 0; padding-inline-start: 2px; background: none; border: 0; color: inherit; font-size: var(--fs-2xs); line-height: 1; }
.pg-hall .tagbox .tag-x:hover { color: var(--ember-soft); }
/* the toolbar is the lintel of the editor: one frame, one edge */
.pg-hall .editor-frame { border: 1px solid var(--line-strong); background: var(--bg); box-shadow: inset 0 2px 6px rgba(0,0,0,.55); transition: border-color var(--t-ui) var(--ease-stone), box-shadow var(--t-ui) var(--ease-stone); }
:root[data-theme="light"] .pg-hall .editor-frame { box-shadow: inset 0 2px 5px rgba(0,0,0,.1); }
.pg-hall .editor-frame:focus-within { border-color: var(--accent); }
.pg-hall .editor-toolbar { position: sticky; top: var(--hdr-h, 68px); z-index: 2; display: flex; flex-wrap: wrap; align-items: center; gap: 2px; padding: 6px; background: var(--bg-elev); border-bottom: 1px solid var(--line-strong); }
.pg-hall .editor-toolbar .tool { min-width: 36px; min-height: 36px; padding: 0 8px; display: inline-grid; place-items: center; background: none; border: 1px solid transparent; color: var(--fg-muted); font-weight: 700; font-size: var(--fs-sm); line-height: 1; transition: color var(--t-fast) var(--ease-stone), border-color var(--t-fast) var(--ease-stone), background var(--t-fast) var(--ease-stone); }
.pg-hall .editor-toolbar .tool:hover { color: var(--fg-strong); border-color: var(--line); }
.pg-hall .editor-toolbar .tool[aria-pressed="true"] { color: var(--accent-text); border-color: var(--line-glow); background: rgba(47,211,154,.08); box-shadow: var(--glow-inset); }
.pg-hall .editor-toolbar .tool:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.pg-hall .editor-toolbar .tool b, .pg-hall .editor-toolbar .tool i { font-family: Georgia, 'Times New Roman', serif; font-size: 1.05rem; }
.pg-hall .editor-toolbar .tool .ico { --n: 16; --ico: 16px; stroke-width: 2.25; }
.pg-hall .tool-rule { display: block; width: 16px; height: 2px; background: currentColor; }
.pg-hall .tool-turn { font-size: 1.15rem; }
.pg-hall .editor-toolbar__sep { width: 1px; height: 22px; margin-inline: 4px; background: var(--line-strong); }
.pg-hall .editor-link { display: inline-flex; gap: 6px; align-items: center; margin-inline-start: auto; }
.pg-hall .editor-link .input { min-height: 36px; width: 220px; font-size: var(--fs-sm); }
/* the page is as wide as the frame; the text inside keeps the reading measure */
.pg-hall .editor { min-height: 320px; max-width: none; padding-block: var(--s-5); padding-inline: max(var(--s-6), calc((100% - 34em) / 2)); background: none; color: var(--fg); border: 0; outline: none; }
.pg-hall .editor:empty::before { content: attr(data-placeholder); color: var(--fg-faint); pointer-events: none; }
.pg-hall .editor a { color: var(--accent-text); text-decoration: underline; }
.pg-hall .editor b, .pg-hall .editor strong { color: var(--fg-strong); }
@media (max-width: 600px) { .pg-hall .editor { padding-inline: var(--s-5) var(--s-4); } }

/* ── my posts: one status each, what needs the writer first, twenty at a time ── */
.pg-hall .mine-tabs { display: flex; flex-wrap: wrap; gap: var(--s-2); margin: var(--s-4) 0; }
.pg-hall .mine-tab { min-height: 40px; padding-inline: var(--s-3); font-size: var(--fs-sm); }
.pg-hall .mine-tab__n { font-variant-numeric: tabular-nums; color: var(--fg-muted); }
.pg-hall .mine-tab[aria-pressed="true"] .mine-tab__n { color: inherit; }
.pg-hall .mine { list-style: none; padding: 0; margin: 0 0 var(--s-5); display: grid; gap: var(--s-2); }
.pg-hall .mine__item { display: grid; grid-template-columns: 96px minmax(0, 1fr) auto; gap: var(--s-4); align-items: center; min-height: 72px; padding: 6px; padding-inline-end: var(--s-3); background: var(--bg-elev); border: 1px solid var(--line); transition: border-color var(--t-fast) var(--ease-stone); }
.pg-hall .mine__item:hover { border-color: var(--line-strong); }
.pg-hall .mine__thumb { display: block; width: 96px; height: 60px; overflow: hidden; background: var(--bg); }
.pg-hall .mine__thumb .hx-cover { width: 100%; height: 100%; object-fit: cover; }
.pg-hall .mine__main { min-width: 0; }
.pg-hall .mine__title { margin: 0; font-family: var(--font-body); font-size: 1rem; font-weight: 700; line-height: 1.55; color: var(--fg-strong); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
/* A title in the other script is laid out in its own direction (its letter
   order, the side its ellipsis falls on), but it is a row's label: it starts
   at the row's edge, beside its status line and its picture, not at the far end. */
/* (-webkit-match-parent first: Chromium drops the unprefixed keyword) */
.pg-hall .mine__title[dir] { text-align: -webkit-match-parent; text-align: match-parent; }
.pg-hall .mine__title a { color: var(--fg-strong); }
.pg-hall .mine__title a:hover { color: var(--accent-text); text-decoration: none; }
.pg-hall .mine__meta { display: flex; flex-wrap: wrap; align-items: center; gap: 2px var(--s-3); font-size: var(--fs-xs); color: var(--fg-muted); }
.pg-hall .mine__meta time { font-variant-numeric: tabular-nums; }
.pg-hall .mine__status { display: inline-flex; align-items: center; gap: 6px; font-weight: 700; color: var(--fg); }
.pg-hall .mine__status::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: currentColor; flex: none; }
.pg-hall .mine__status--published { color: var(--accent-text); }
.pg-hall .mine__status--pending { color: var(--fg); }
.pg-hall .mine__status--pending::before { background: none; box-shadow: inset 0 0 0 1.5px var(--fg-muted); }
.pg-hall .mine__status--draft { color: var(--fg-muted); }
.pg-hall .mine__status--rejected, .pg-hall .mine__status--hidden { color: var(--danger); }
.pg-hall .mine__likes { display: inline-flex; align-items: center; gap: 4px; color: var(--accent-text); }
.pg-hall .mine__likes .ico { --n: 16; --ico: 16px; stroke-width: 2.25; }
.pg-hall .mine__note { margin: 4px 0 0; font-size: var(--fs-xs); line-height: 1.75; color: var(--fg-muted); }
.pg-hall .mine__note--warn { color: var(--fg); padding-inline-start: var(--s-2); border-inline-start: 2px solid var(--ember-soft); }
.pg-hall .mine__note a { color: var(--accent-text); }
.pg-hall .mine__actions { display: flex; gap: 2px; }
.pg-hall .mine__act { width: 36px; min-height: 36px; padding: 0; justify-content: center; }
.pg-hall .mine__act .ico { --n: 20; --ico: 20px; stroke-width: 1.8; }
.pg-hall .mine__act--del:hover, .pg-hall .mine__act--del:focus-visible { color: var(--danger); }
/* the one thing a waiting post can do: named in words, since no mark says
   "take it back out of the queue" */
.pg-hall .mine__actions { align-items: center; }
.pg-hall .mine__withdraw { min-height: 36px; padding-inline: var(--s-3); white-space: nowrap; }
.pg-hall .mine__none { padding: var(--s-5); text-align: center; }
@media (max-width: 600px) {
  .pg-hall .mine__item { grid-template-columns: 64px minmax(0, 1fr); gap: var(--s-3); align-items: start; }
  .pg-hall .mine__thumb { width: 64px; height: 40px; }
  .pg-hall .mine__actions { grid-column: 2; margin-top: -4px; }
}
@media (pointer: coarse) { .pg-hall .mine__act { width: 44px; min-height: 44px; } .pg-hall .mine__withdraw { min-height: 44px; } }

/* ── a post that is not there ── */
.pg-hall .missing { display: grid; justify-items: start; gap: var(--s-3); padding-block: var(--s-6) var(--s-7); max-width: 62ch; }
.pg-hall .missing h1 { margin: 0; }
.pg-hall .missing__lead { color: var(--fg-muted); margin: 0; }
.pg-hall .missing .row { gap: var(--s-2); margin-top: var(--s-2); }
.pg-hall .missing__more { margin-bottom: var(--s-7); }

/* ── what happens when you press the button, and why a post is not public ── */
.pg-hall .write-state { margin-bottom: var(--s-4); }
.pg-hall .write-state .btn { margin-top: var(--s-2); }

/* ── touch: nothing a finger must hit stays under 44px ── */
@media (hover: none), (pointer: coarse) {
  .pg-hall .thumb__x { width: 44px; height: 44px; }
  .pg-hall .tagbox .chip { min-height: 44px; }
  .pg-hall .tagbox .tag-x { min-width: 44px; min-height: 44px; }
  .pg-hall .editor-toolbar .tool { min-width: 44px; min-height: 44px; }
  .pg-hall .vnext__item { min-height: 44px; }
}

/* ── motion off: everything is simply where it ends up ── */
@media (prefers-reduced-motion: reduce) {
  .hcard.is-arriving, .hcard.card--video:hover .card__reel, .hcard.card--video:hover .card__scrub i { animation: none; }
  .hcard .card__pane .hx-cover, .pg-hall .feed > * { transition: none; }
}
:root[data-motion="off"] .hcard.is-arriving, :root[data-motion="off"] .hcard.card--video:hover .card__reel, :root[data-motion="off"] .hcard.card--video:hover .card__scrub i { animation: none; }
:root[data-motion="off"] .hcard .card__pane .hx-cover { transition: none; }
