@charset "UTF-8";
/* ===========================================================================
   Hafetz Haim — "Vigil"
   A redesign of hafetzhaim.online. Independent build; no file outside
   assets/ and the page files is touched.

   ---------------------------------------------------------------------------
   THE IDEA
   ---------------------------------------------------------------------------
   The source site is a daylight page: off-white ground, centred column, a
   photo of a portrait, a photo of a webcam frame, a donation form. It reads as
   an informational leaflet about a grave.

   This one is a night room. The ground is unlit and warm-black, the way the
   wooden structure over the grave looks at 19:00 when the camera stops, and
   there is exactly one light source: a votive candle. That flame is not
   decoration and it is not an accent colour — it *is* the interface. It marks
   whether the broadcast is running right now, it is the affordance of the
   "light a candle" action, and it is the light that illuminates the page near
   the controls. Every other colour on the site is a value of the same dark
   brown-black. There is nothing else to look at, which is the point.

   The second structural idea is the **day rule**: a hairline drawn to scale
   across twenty-four hours, with the 08:00–18:00 broadcast window filled. It
   is not a divider. It is the schedule, and it is the same object under the
   hero and in the footer, so a reader learns it once.

   ---------------------------------------------------------------------------
   TYPOGRAPHY
   ---------------------------------------------------------------------------
   Old Standard TT carries the display type and the prose. It is a Scotch-Roman
   revival drawn for a book, and it is the only widely-available bookface with
   a real Cyrillic cut — which matters, because this site is Russian first.
   IBM Plex Sans carries the interface, IBM Plex Mono carries figures: UNP,
   BIC, the account number, the clock, the plate numbers in the gallery.
   Neither is Inter, Roboto or system-ui.

   Hebrew has no cut in either of the first two, so Hebrew prose is set in
   Frank Ruhl Libre (a Hebrew bookface) and Hebrew interface in IBM Plex Sans
   Hebrew. The role map is identical in all three languages, which means
   switching language never moves anything on the page.

   Everything is measured. The prose column is capped at 68 characters. Old
   Standard TT runs at 1.72 leading because a Scotch Roman with that much
   contrast needs air under it; a sans would drown at the same setting.

   ---------------------------------------------------------------------------
   ALIGNMENT
   ---------------------------------------------------------------------------
   Nothing on this site is centred. Everything hangs off a left rail that
   carries the meta — the section index, a year, a plate number, a clock — set
   in Plex Mono at 11px, and the content sits to its right. It is a book
   convention, it is what RTL needs, and it is the exact opposite of the
   centred 900px column it replaces.

   Radius is 0 everywhere except the flame and 2px on photo plates. This is a
   site about stone, timber and paper; nothing here is a pill.
   =========================================================================== */

@import url("fonts/fonts.css?v=a4ec656b30"));

/* ===========================================================================
   1. TOKENS
   =========================================================================== */

:root {
  color-scheme: dark;

  /* -- ground ------------------------------------------------------------
     Not #000 and not blue-black. Warm near-black, sampled from the timber
     cladding of the structure over the grave after sunset. */
  --ground: #0c0a09;
  --ground-deep: #070605;
  --surface: #15110e;
  --surface-2: #1f1913;
  --surface-3: #2a2219;

  /* -- ink ---------------------------------------------------------------
     Unbleached paper and limestone, not pure white. Pure white on this ground
     vibrates; #EFE7DA does not. */
  --ink: #efe7da;
  --ink-2: #cfc4b1;
  --ink-3: #a79c8b;
  --ink-4: #8f8474;
  /* -- display watermark ---------------------------------------------------
     A numeral large enough to be a graphic (4rem–9rem) still has to be
     readable as a numeral. WCAG's threshold for text at 24px and above is 3:1,
     and the 404 page failed it at 1.26:1 — measured by tools/audit-ui.mjs —
     because .nf__code was painted in --surface-3, a token for fills on the
     light contact-sheet plate, not for type on the dark ground. The result was
     a 404 you could not see.

     3.21:1 measured against --ground. One step above the threshold, and far
     enough below --ink-4 (5.4:1) that a 140px numeral still reads as
     atmosphere rather than as the loudest thing on the page. */
  --ink-watermark: #6e5f4e;

  /* -- rules -------------------------------------------------------------
     The line a scribe rules on a page. Warm, never grey. */
  --rule: #2c241b;
  --rule-2: #3b3025;
  --rule-strong: #55463a;

  /* -- the flame ---------------------------------------------------------
     The only chromatic value in the design. VISA/MasterCard/БЕЛКАРТ keep
     their own brand colours in the logos strip; that is a legal requirement,
     not a palette decision. */
  --flame: #e8a33d;
  --flame-hi: #f6c877;
  --flame-deep: #b4651c;
  --flame-glow: rgba(232, 163, 61, 0.14);

  /* -- type ------------------------------------------------------------- */
  --face-display: "Old Standard TT", "Frank Ruhl Libre", "Times New Roman",
    serif;
  --face-text: "Old Standard TT", "Frank Ruhl Libre", "Times New Roman", serif;
  --face-ui: "IBM Plex Sans", "IBM Plex Sans Hebrew", "Segoe UI", sans-serif;
  --face-mono: "IBM Plex Mono", "IBM Plex Sans Hebrew", ui-monospace, monospace;

  --t-mega: clamp(3.6rem, 12.5vw, 10.5rem);
  --t-hero: clamp(2.6rem, 7vw, 5.4rem);
  --t-1: clamp(1.85rem, 4.4vw, 3.2rem);
  --t-2: clamp(1.35rem, 2.4vw, 1.9rem);
  --t-3: 1.2rem;
  --t-body: 1.0625rem;
  --t-small: 0.875rem;
  --t-micro: 0.8125rem;
  --t-mono: 0.6875rem;

  /* -- measure & rhythm ------------------------------------------------- */
  --measure: 68ch;
  --rail: 9rem;
  --rail-tight: 5.5rem;
  --gutter: clamp(1.25rem, 4vw, 3.5rem);
  --s1: 0.5rem;
  --s2: 1rem;
  --s3: 1.5rem;
  --s4: 2.5rem;
  --s5: 4rem;
  --s6: 6.5rem;
  --s7: 10rem;

  /* -- motion -----------------------------------------------------------
     One curve, two durations. A vigil should not move on its own. */
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --t-fast: 180ms;
  --t-slow: 620ms;

  --plate-radius: 2px;
}

/* High-contrast mode, carried over from the source site as a real
   accessibility feature rather than a preference. It lifts ink and rules and
   pushes the ground further down; it does not change hue, because the flame
   has to stay the only light in the room. */
:root[data-contrast="high"] {
  --ground: #000000;
  --ground-deep: #000000;
  --surface: #0b0908;
  --surface-2: #14100d;
  --ink: #ffffff;
  --ink-2: #f0e9de;
  --ink-3: #d8cfc1;
  --ink-4: #c2b7a6;
  --rule: #5a4c3e;
  --rule-2: #7a6857;
  --rule-strong: #9c8772;
  --flame: #ffb752;
  --flame-hi: #ffd894;
}

/* ===========================================================================
   2. RESET
   =========================================================================== */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
}

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--face-text);
  font-size: var(--t-body);
  line-height: 1.72;
  text-wrap: pretty;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* A single soft warm pool at the top of the document: the light is above
     you, at the head of the page. Nothing else in the layout is lit. */
  background-image: radial-gradient(
    120% 70% at 50% -10%,
    rgba(232, 163, 61, 0.055) 0%,
    rgba(232, 163, 61, 0) 60%
  );
  background-repeat: no-repeat;
}

img,
svg,
video {
  display: block;
  max-width: 100%;
}

img {
  height: auto;
}

a {
  color: inherit;
}

button,
input,
select {
  font: inherit;
  color: inherit;
}

:focus-visible {
  outline: 2px solid var(--flame);
  outline-offset: 3px;
  border-radius: 1px;
}

::selection {
  background: var(--flame-deep);
  color: var(--ink);
}

hr {
  border: 0;
  border-top: 1px solid var(--rule);
  margin: 0;
}

/* ===========================================================================
   3. THE RAIL — the structural spine of every page
   ---------------------------------------------------------------------------
   A fixed-width left column that carries meta, and a hairline that runs the
   full height of the sheet. Content sits to its right. The rail is 0 on
   narrow screens, where the meta moves inline above its section.
   =========================================================================== */

.sheet {
  display: grid;
  grid-template-columns: var(--rail) minmax(0, 1fr);
  column-gap: var(--gutter);
  width: min(100% - var(--gutter) * 2, 84rem);
  margin-inline: auto;
}

.sheet--tight {
  grid-template-columns: var(--rail-tight) minmax(0, 1fr);
}

/* The single hairline down the margin.
   It belongs to the SHEET, not to the rail. The first version drew it inside
   the rail element, which is `align-self: start` — so the line was only as tall
   as whatever sat in the rail and showed on screen as a stray 20px tick in an
   otherwise empty margin. The margin rule has to run the whole way down; that
   is the entire structural idea. */
.sheet {
  position: relative;
}

.sheet::before {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-start: var(--rail);
  inline-size: 1px;
  background: var(--rule);
  pointer-events: none;
}

.sheet--tight::before {
  inset-inline-start: var(--rail-tight);
}

.rail {
  grid-column: 1;
  padding-block-start: 0.5rem;
  position: sticky;
  top: 6.5rem;
  align-self: start;
  height: max-content;
}

.body {
  grid-column: 2;
  min-width: 0;
}

@media (max-width: 60rem) {
  .sheet,
  .sheet--tight {
    grid-template-columns: minmax(0, 1fr);
  }
  .sheet::before {
    display: none;
  }
  .rail {
    grid-column: 1;
    position: static;
    padding-block: 0 0.4rem;
  }
  .body {
    grid-column: 1;
  }
}

/* Meta text: index, year, plate number, clock. Plex Mono at 11px, tracked.
   This is the one place a monospace face appears, and it appears only where
   the value is genuinely a datum.

   --ink-4 was #7d7365, which measures 4.23:1 against the ground — below the
   4.5:1 that 11px text needs, and this is the smallest text on the site. Lifted
   to #8f8474 (5.4:1), which still reads clearly as the dimmest ink without
   being the thing a reader has to squint at. The ground is not pure black on
   purpose, so the ratio has to be computed against #0c0a09 and not #000. */
.meta {
  font-family: var(--face-mono);
  font-size: var(--t-mono);
  letter-spacing: 0.14em;
  line-height: 1.5;
  color: var(--ink-4);
  margin: 0;
  text-transform: uppercase;
}

.meta--flame {
  color: var(--flame);
}

/* ===========================================================================
   4. TYPE
   =========================================================================== */

.prose {
  max-width: var(--measure);
}

.prose > p {
  margin: 0 0 1.4em;
  text-wrap: pretty;
}

/* Old Standard TT sits visually small next to a sans; optical sizing needs a
   touch more size and leading than the numbers suggest. */
.prose > p:first-of-type::first-line {
  font-variant-caps: normal;
}

h1,
h2,
h3,
h4 {
  font-family: var(--face-display);
  font-weight: 400;
  margin: 0;
  text-wrap: balance;
  line-height: 1.06;
  letter-spacing: -0.012em;
}

.display {
  font-size: var(--t-hero);
  line-height: 0.98;
  letter-spacing: -0.022em;
}

.h1 {
  font-size: var(--t-1);
  line-height: 1.1;
}

.h2 {
  font-size: var(--t-2);
  line-height: 1.2;
}

.h3 {
  font-size: var(--t-3);
  line-height: 1.3;
}

/* An italic lead paragraph, set one step up. Used once per page, at the top,
   to open the argument — never repeated as a section decoration. */
.lede {
  font-size: clamp(1.15rem, 1.9vw, 1.45rem);
  line-height: 1.58;
  color: var(--ink-2);
  max-width: 60ch;
  font-style: italic;
}

/* Section heads are a rule with a word in it, not a bold line. */
.rulehead {
  display: flex;
  align-items: baseline;
  gap: var(--s2);
  border-top: 1px solid var(--rule);
  padding-top: 0.85rem;
  margin-bottom: var(--s3);
}

.rulehead__word {
  font-family: var(--face-display);
  font-size: var(--t-2);
  line-height: 1.2;
}

.rulehead__rest {
  flex: 1;
}

a.link {
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px solid var(--rule-strong);
  padding-bottom: 1px;
  transition: border-color var(--t-fast) var(--ease),
    color var(--t-fast) var(--ease);
}

a.link:hover {
  border-bottom-color: var(--flame);
  color: var(--flame-hi);
}

a.link--flame {
  color: var(--flame);
  border-bottom-color: var(--flame-deep);
}

a.link--flame:hover {
  color: var(--flame-hi);
  border-bottom-color: var(--flame);
}

[dir="rtl"] {
  --face-display: "Frank Ruhl Libre", "Old Standard TT", serif;
  --face-text: "Frank Ruhl Libre", "Old Standard TT", serif;
}

/* ===========================================================================
   5. THE FLAME — the one light in the room
   =========================================================================== */

.flame {
  --size: 0.72rem;
  position: relative;
  display: inline-block;
  inline-size: var(--size);
  block-size: calc(var(--size) * 1.5);
  flex: none;
  vertical-align: -0.12em;
  color: var(--flame);
}

/* The body of the flame.
   Shaped with a mask rather than clip-path: path() is expressed in absolute
   user units against the border box and does not scale, so a flame drawn for
   16px would be cut off on a 19px one. A mask with mask-size:100% 100% is
   resolution-independent, which matters because the same element appears at
   four sizes on this site. The viewBox below is 24×36 — the same 1:1.5 ratio
   as the box, so the teardrop never distorts. */
.flame::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to bottom,
    var(--flame-hi) 0%,
    var(--flame) 42%,
    var(--flame-deep) 100%
  );
  -webkit-mask-image: var(--flame-mask);
  mask-image: var(--flame-mask);
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  transform-origin: 50% 100%;
}

:root {
  --flame-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 36'%3E%3Cpath d='M12 0c5.2 9.4 12 14.6 12 22.2A12 12 0 0 1 0 22.2C0 14.6 6.8 9.4 12 0z'/%3E%3C/svg%3E");
}

/* The glow it throws on the surface it sits on. This is the only box-shadow in
   the design and it is warm. */
.flame::after {
  content: "";
  position: absolute;
  inset: -150% -200%;
  background: radial-gradient(
    closest-side,
    var(--flame-glow) 0%,
    rgba(232, 163, 61, 0) 70%
  );
  pointer-events: none;
}

.flame--lg {
  --size: 1.05rem;
}

/* A burning candle is never perfectly steady. Four seconds, small amplitude,
   and it is the only ambient motion in the site. */
.flame[data-lit="true"]::before {
  animation: flicker 4s var(--ease) infinite;
}

@keyframes flicker {
  0%,
  100% {
    transform: scaleY(1) scaleX(1) translateY(0);
    opacity: 1;
  }
  22% {
    transform: scaleY(1.05) scaleX(0.93) translateY(-0.5px);
    opacity: 0.9;
  }
  47% {
    transform: scaleY(0.95) scaleX(1.06) translateY(0.4px);
    opacity: 1;
  }
  71% {
    transform: scaleY(1.03) scaleX(0.97) translateY(-0.3px);
    opacity: 0.94;
  }
}

/* Unlit: the wick, cold. Same shape, no glow, no motion. */
.flame[data-lit="false"] {
  color: var(--ink-4);
}

.flame[data-lit="false"]::before {
  background: var(--ink-4);
  opacity: 0.45;
}

.flame[data-lit="false"]::after {
  display: none;
}

/* ===========================================================================
   6. THE DAY RULE — the broadcast window, drawn to scale
   ---------------------------------------------------------------------------
   The first pass drew this as a 2px hairline and it read as a stray border
   rather than as the thing it is. It is now the one graphic object that sits
   between the hero and the text: 4px, with the broadcast window filled in
   flame, a flame riding the current time, and the hours labelled.
   =========================================================================== */

.dayrule {
  --from: 33.3333%; /* 08:00 */
  --to: 75%; /* 18:00 */
  display: block;
}

.dayrule__track {
  position: relative;
  height: 4px;
  background: var(--surface-2);
  border-radius: 1px;
}

/* Hour ticks, every third one taller. The scale has to be readable without a
   label, because the label is 11px and this is a phone. */
.dayrule__track::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: repeating-linear-gradient(
    to right,
    var(--rule-2) 0 1px,
    transparent 1px calc(100% / 24)
  );
}

.dayrule__on {
  position: absolute;
  inset-block: 0;
  inset-inline-start: var(--from);
  inline-size: calc(var(--to) - var(--from));
  background: var(--flame-deep);
  border-radius: 1px;
}

.dayrule[data-now="in"] .dayrule__on {
  background: linear-gradient(
    to right,
    var(--flame-deep),
    var(--flame) 60%,
    var(--flame-hi)
  );
}

/* Where "now" sits on the track. A small flame rather than a tick, because on
   this site the flame is how you say a thing is happening. Hidden entirely
   outside the window — the rule is a schedule, not a clock that must always
   render something. */
.dayrule__now {
  position: absolute;
  inset-block-start: 50%;
  inset-inline-start: var(--now, 0%);
  inline-size: 0.5rem;
  block-size: 0.5rem;
  translate: -50% -50%;
  background: var(--flame-hi);
  border-radius: 50%;
  box-shadow: 0 0 0 4px rgba(232, 163, 61, 0.18);
  opacity: 0;
  transition: opacity var(--t-fast) var(--ease);
}

.dayrule[data-now="in"] .dayrule__now {
  opacity: 1;
}

.dayrule__ticks {
  display: flex;
  justify-content: space-between;
  margin-top: 0.55rem;
}

.dayrule__legend {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.7rem;
}

/* ===========================================================================
   6b. THE VIGIL BAR
   ---------------------------------------------------------------------------
   The band between the camera and the text. It holds the day rule, the live
   state, and the one button that acts on the stream. In the first pass the
   button was in the corner of the hero, where it collided with the frame's own
   burnt-in timecode and put a bright rectangle at the least important corner
   of the most important image on the site. Here the rule and the control are
   the same object, which is what they are: the schedule, and the thing you do
   about it.
   =========================================================================== */

.vigilbar {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--s3) var(--s4);
  align-items: end;
}

.vigilbar__side {
  display: grid;
  gap: 0.7rem;
  justify-items: end;
  text-align: end;
}

.vigilbar__note {
  font-family: var(--face-ui);
  font-size: var(--t-micro);
  line-height: 1.5;
  color: var(--ink-3);
  max-inline-size: 30ch;
  margin: 0;
}

@media (max-width: 48rem) {
  .vigilbar {
    grid-template-columns: minmax(0, 1fr);
  }
  .vigilbar__side {
    justify-items: start;
    text-align: start;
  }
}

/* ===========================================================================
   6c. THE SPREAD
   ---------------------------------------------------------------------------
   One long statement on the left, one bordered note on the right. The note is
   the second half of the same idea, set smaller and dimmer. This is the layout
   that stops a text-only section from leaving 40% of a wide screen empty
   without reaching for a photograph that has no reason to be there.
   =========================================================================== */

.spread {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
  gap: clamp(1.5rem, 4vw, 3.5rem);
  align-items: start;
}

@media (max-width: 48rem) {
  .spread {
    grid-template-columns: minmax(0, 1fr);
  }
}

.note {
  border-top: 2px solid var(--flame-deep);
  padding-top: var(--s2);
  max-inline-size: 40ch;
}

.note__title {
  font-family: var(--face-display);
  font-size: var(--t-3);
  line-height: 1.25;
  margin-bottom: 0.7rem;
}

.note p {
  font-family: var(--face-ui);
  font-size: var(--t-micro);
  line-height: 1.68;
  color: var(--ink-2);
  margin: 0 0 0.9em;
}

.note p:last-child {
  margin-bottom: 0;
}

/* ===========================================================================
   7. HEADER
   =========================================================================== */

.masthead {
  position: sticky;
  top: 0;
  z-index: 40;
  /* Запасной вариант — непрозрачный фон. `color-mix` появился в 2023 году,
     и без этой строки в старом браузере шапка стала бы ПОЛНОСТЬЮ прозрачной
     поверх текста, который под ней едет. Размытие при непрозрачном фоне
     ничего не даёт — и это правильная деградация, а не поломка. */
  background: var(--ground);
  backdrop-filter: blur(14px) saturate(1.1);
  border-bottom: 1px solid var(--rule);
}

.masthead__in {
  display: flex;
  align-items: center;
  gap: var(--s3);
  width: min(100% - var(--gutter) * 2, 84rem);
  margin-inline: auto;
  min-height: 4.25rem;
  padding-block: 0.7rem;
}

.brand {
  position: relative; /* the ::after hit area needs a containing block */
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  text-decoration: none;
  color: var(--ink);
  margin-inline-end: auto;
  flex: none;
}

/* Same treatment as .iconbtn, for the same reason: measured 122x29, and it is
   the link home from every page on the site. The row it sits in is already
   4.25rem tall, so the extra reach costs nothing visually. */
.brand::after {
  content: "";
  position: absolute;
  inset-block: -0.5rem;
  inset-inline: -0.4rem;
}

.brand__mark {
  inline-size: 1.05rem;
  block-size: 1.15rem;
  fill: var(--ink);
  flex: none;
  transition: fill var(--t-fast) var(--ease);
}

.brand:hover .brand__mark {
  fill: var(--flame);
}

.brand__name {
  font-family: var(--face-display);
  font-size: 1.06rem;
  letter-spacing: 0.01em;
  white-space: nowrap;
}

.nav {
  display: flex;
  align-items: center;
  gap: clamp(0.9rem, 2vw, 1.9rem);
}

.nav__link {
  font-family: var(--face-ui);
  font-size: var(--t-micro);
  letter-spacing: 0.04em;
  color: var(--ink-3);
  text-decoration: none;
  padding: 0.4rem 0;
  border-bottom: 1px solid transparent;
  transition: color var(--t-fast) var(--ease),
    border-color var(--t-fast) var(--ease);
  white-space: nowrap;
}

.nav__link:hover {
  color: var(--ink);
}

.nav__link[aria-current="page"] {
  color: var(--ink);
  border-bottom-color: var(--flame);
}

.masthead__tools {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex: none;
}

.langbar {
  display: inline-flex;
  border: 1px solid var(--rule);
  border-radius: 1px;
  overflow: hidden;
  /* Desktop: park the switcher at the trailing end of the nav row, which is
     where it sat when it lived in the tools cluster. */
  margin-inline-start: auto;
}

.langbar__btn {
  font-family: var(--face-mono);
  font-size: var(--t-mono);
  letter-spacing: 0.1em;
  background: none;
  border: 0;
  padding: 0.5rem 0.6rem;
  color: var(--ink-4);
  cursor: pointer;
  min-height: 2.25rem;
  transition: color var(--t-fast) var(--ease),
    background-color var(--t-fast) var(--ease);
}

.langbar__btn + .langbar__btn {
  border-inline-start: 1px solid var(--rule);
}

.langbar__btn:hover {
  color: var(--ink-2);
}

.langbar__btn[aria-pressed="true"] {
  color: var(--ground);
  background: var(--ink);
}

.iconbtn {
  position: relative; /* the ::after hit area needs a containing block */
  inline-size: 2.25rem;
  block-size: 2.25rem;
  display: inline-grid;
  place-items: center;
  background: none;
  border: 1px solid var(--rule);
  border-radius: 1px;
  color: var(--ink-3);
  cursor: pointer;
  padding: 0;
  transition: color var(--t-fast) var(--ease),
    border-color var(--t-fast) var(--ease);
}

/* A 36px box is a 36px target, and these are the only controls in the
   masthead: the contrast toggle and, below 30rem, the burger — which is the
   sole route to the whole menu. Measured by tools/audit-ui.mjs at 390px as
   36x36, against a 44px minimum.

   The fix is an invisible ::after rather than a bigger box. A 44px button with
   a 1px hairline border and an 18px glyph inside does not look like this
   masthead, and the design is not the thing that is wrong here — the touch
   target is. So the drawn size stays 36px and the hit area grows to 44px, which
   is what the platform checks and what a thumb actually hits.

   Overlap is the one cost: neighbouring controls are 8px apart, so the two hit
   areas meet. They still do not cover each other, because 44 - 36 = 8 is
   exactly the gap. */
.iconbtn::after {
  content: "";
  position: absolute;
  inset: -4px;
}

.iconbtn:hover {
  color: var(--ink);
  border-color: var(--rule-strong);
}

.iconbtn svg {
  inline-size: 1.15rem;
  block-size: 1.15rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
}

.burger {
  display: none;
}

@media (max-width: 60rem) {
  .burger {
    display: inline-grid;
  }
  .nav {
    position: fixed;
    inset: 4.25rem 0 auto 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    background: var(--ground-deep);
    border-bottom: 1px solid var(--rule);
    padding: var(--s2) var(--gutter) var(--s3);
    transform: translateY(-130%);
    transition: transform var(--t-slow) var(--ease);
    visibility: hidden;
    /* Сначала vh, потом dvh: в браузере без dvh первая строка остаётся в
       силе, и меню по-прежнему ограничено по высоте и прокручивается.
       Без запасного варианта max-block-size просто исчезал бы, и длинное
       меню нельзя было бы прокрутить. */
    max-block-size: calc(100vh - 4.25rem);
    max-block-size: calc(100dvh - 4.25rem);
    overflow-y: auto;
  }
  .nav[data-open="true"] {
    transform: translateY(0);
    visibility: visible;
  }
  .nav__link {
    font-size: 1rem;
    padding: 0.9rem 0;
    border-bottom: 1px solid var(--rule);
  }
  .nav__link[aria-current="page"] {
    border-bottom-color: var(--flame);
  }
  /* In the drawer the switcher is a full-width row of three, not a chip
     floating at one end. */
  .langbar {
    margin-inline-start: 0;
    margin-block-start: var(--s3);
  }
  .langbar__btn {
    flex: 1;
    padding-block: 0.9rem;
    font-size: var(--t-small);
  }
}

/* ===========================================================================
   8. THE VIGIL — hero
   ---------------------------------------------------------------------------
   The most characteristic thing in this subject's world is a fixed camera
   looking at a lit headstone through a window. So the hero is that frame, at
   full bleed, and the name is set over the empty plaster wall in its upper
   left rather than parked underneath it.
   =========================================================================== */

.vigil {
  position: relative;
  margin-top: 0;
}

.vigil__frame {
  position: relative;
  background: var(--ground-deep);
  overflow: hidden;
}

.vigil__frame img,
.vigil__frame video {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  /* A 16:9 frame at full width is 630px tall on a laptop and nearly 1100px on
     a wide monitor, which pushes the first paragraph off the screen. The cap
     keeps the camera the first thing seen without making it the whole screen;
     the poster is 1280px wide, so cropping rather than scaling also stops the
     image from being upscaled past its own resolution. */
  aspect-ratio: 16 / 9;
  max-block-size: min(66vh, 40rem);
  /* The camera is not art. It is held at the warmth and contrast it actually
     has, and darkened at the top so type can sit on it. */
  filter: saturate(0.86) contrast(1.02) brightness(0.8);
}

/* The live video only exists once the manifest has been confirmed to be a real
   playlist. Until then the poster holds the frame, so the hero is never an
   empty black rectangle and the page never shifts height. */
.vigil__frame video {
  display: none;
  position: absolute;
  inset: 0;
  filter: saturate(0.9) contrast(1.02) brightness(0.92);
}

.vigil__frame[data-stage="live"] video {
  display: block;
}

.vigil__frame[data-stage="live"] img {
  visibility: hidden;
}

.vigil__frame[data-stage="live"]::before {
  content: "";
  position: absolute;
  z-index: 2;
  inset-block-start: 0.9rem;
  inset-inline-start: 0.9rem;
  inline-size: 0.6rem;
  block-size: 0.6rem;
  border-radius: 50%;
  background: var(--flame);
  box-shadow: 0 0 0 3px rgba(232, 163, 61, 0.22);
  animation: rec 2.4s var(--ease) infinite;
}

@keyframes rec {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.35;
  }
}

.vigil__frame::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
      to bottom,
      rgba(7, 6, 5, 0.72) 0%,
      rgba(7, 6, 5, 0.12) 34%,
      rgba(7, 6, 5, 0) 52%,
      rgba(7, 6, 5, 0.66) 100%
    ),
    linear-gradient(to right, rgba(7, 6, 5, 0.62) 0%, rgba(7, 6, 5, 0) 46%);
  pointer-events: none;
}

.vigil__inner {
  position: absolute;
  inset: 0;
  display: grid;
  align-content: space-between;
  padding: clamp(1.1rem, 3vw, 2.4rem);
  pointer-events: none;
}

.vigil__top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--s2);
}

.vigil__bottom {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s3);
  flex-wrap: wrap;
}

.vigil__name {
  font-size: var(--t-mega);
  line-height: 0.84;
  letter-spacing: -0.03em;
  text-transform: uppercase;
  /* One line per name part, flush to the frame edge. The wordmark is the
     architecture of the page, not a title above it. */
  display: flex;
  flex-direction: column;
}

.vigil__name span {
  display: block;
}

.vigil__dates {
  font-family: var(--face-mono);
  font-size: var(--t-mono);
  letter-spacing: 0.28em;
  color: var(--ink-2);
  margin-top: 0.7rem;
}

/* Live status. The flame is the indicator; the word beside it is the
   translation of it. */
.status {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-family: var(--face-mono);
  font-size: var(--t-mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-2);
}

.status[data-on="true"] {
  color: var(--flame);
}

.status[data-on="false"] {
  color: var(--ink-3);
}

/* ===========================================================================
   9. BUTTONS
   ---------------------------------------------------------------------------
   Two kinds. A quiet one: a rule, a word, a fill that arrives on hover. A
   lit one: only for the action that is literally lighting something.
   =========================================================================== */

.btn {
  --btn-fg: var(--ink);
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.55rem;
  font-family: var(--face-ui);
  font-size: var(--t-micro);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-decoration: none;
  color: var(--btn-fg);
  background: none;
  border: 1px solid var(--rule-strong);
  border-radius: 1px;
  padding: 0.85rem 1.5rem;
  min-height: 2.9rem;
  cursor: pointer;
  transition: background-color var(--t-fast) var(--ease),
    border-color var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}

.btn:hover {
  background: var(--surface-2);
  border-color: var(--ink-4);
}

.btn:active {
  background: var(--surface-3);
}

.btn[disabled],
.btn[aria-disabled="true"] {
  opacity: 0.45;
  cursor: not-allowed;
}

.btn--lit {
  border-color: var(--flame-deep);
  color: var(--flame);
  /* Запасной вариант: та же доля янтарного, но без color-mix. */
  background: rgba(232, 163, 61, 0.07);
}

.btn--lit:hover {
  background: rgba(232, 163, 61, 0.15);
  border-color: var(--flame);
  color: var(--flame-hi);
}

/* The main action of a section. */
.btn--lead {
  background: var(--ink);
  color: var(--ground);
  border-color: var(--ink);
  font-weight: 600;
}

.btn--lead:hover {
  background: var(--flame);
  border-color: var(--flame);
  color: var(--ground);
}

.btn--ghost {
  border-color: transparent;
  padding-inline: 0.4rem;
}

.btn--ghost:hover {
  background: none;
  border-color: var(--rule);
}

.btnrow {
  display: flex;
  flex-wrap: wrap;
  gap: 0.7rem;
  align-items: center;
}

/* ===========================================================================
   10. SECTIONS
   =========================================================================== */

/* Sections. The first pass used 6.5rem of padding on both sides of every
   block, which put 13rem of nothing between two paragraphs and made the page
   read as sparse rather than calm. Tightened; the space that remains is
   deliberately the space around the pull-quote, which is the one place on the
   site that is allowed to breathe. */
.section {
  padding-block: var(--s5);
  border-top: 1px solid var(--rule);
}

.section--tight {
  padding-block: var(--s4);
}

.section--air {
  padding-block: var(--s6);
}

.section--flush {
  border-top: 0;
}

.section__head {
  display: grid;
  grid-template-columns: var(--rail) minmax(0, 1fr);
  column-gap: var(--gutter);
  margin-bottom: var(--s4);
  align-items: baseline;
}

.section__head .meta {
  grid-column: 1;
}

.section__head .h2 {
  grid-column: 2;
  max-width: 24ch;
}

@media (max-width: 60rem) {
  .section__head {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 0.35rem;
  }
  .section__head .meta,
  .section__head .h2 {
    grid-column: 1;
  }
}

/* A two-up: prose and image, image deliberately not mirrored every other
   block (the original alternates, which makes it read as a template). */
.split {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: clamp(1.5rem, 4vw, 3.5rem);
  align-items: start;
}

.split--wide {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
}

@media (max-width: 48rem) {
  .split,
  .split--wide {
    grid-template-columns: minmax(0, 1fr);
  }
  /* No reordering. The first version pulled the image above the prose with
     `order: -1`, which is right when the plate is the subject of the section
     and wrong on the history page, where a long biography should start with
     its first sentence rather than a portrait. The markup order is already
     correct in both cases, so the rule is simply gone. */
}

.plate {
  position: relative;
  background: var(--surface);
  border-radius: var(--plate-radius);
  overflow: hidden;
}

.plate img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
}

.plate--square {
  aspect-ratio: 1;
}

.plate--portrait {
  aspect-ratio: 3 / 4;
}

.plate--land {
  aspect-ratio: 4 / 3;
}

.plate--wide {
  aspect-ratio: 16 / 7;
}

.plate figcaption {
  font-family: var(--face-mono);
  font-size: var(--t-mono);
  letter-spacing: 0.1em;
  color: var(--ink-4);
  margin-top: 0.6rem;
}

/* ===========================================================================
   11. PULL QUOTE
   ---------------------------------------------------------------------------
   Used once, on the history page, for the passage that is a quotation in
   spirit and a statement in the source. Full bleed, italic, over the
   black-and-white study photograph. Nothing else on the site does this.
   =========================================================================== */

.pullquote {
  position: relative;
  margin-block: var(--s6);
  padding-block: clamp(3rem, 8vw, 6rem);
  overflow: hidden;
  border-block: 1px solid var(--rule);
}

.pullquote__bg {
  position: absolute;
  inset: 0;
}

.pullquote__bg img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  /* Two passes failed here. At brightness .42 under a .9 scrim the photograph
     was invisible and the block was a black rectangle with a sentence in it.
     At .72 with an asymmetric scrim it works: the study group is legible as a
     photograph on the right, and the italic clears 14:1 on the left where the
     scrim is heaviest. */
  filter: grayscale(1) contrast(1.06) brightness(0.78);
}

.pullquote__bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to right,
    rgba(7, 6, 5, 0.95) 0%,
    rgba(7, 6, 5, 0.88) 38%,
    rgba(7, 6, 5, 0.55) 72%,
    rgba(7, 6, 5, 0.3) 100%
  );
}

.pullquote__in {
  position: relative;
  width: min(100% - var(--gutter) * 2, 84rem);
  margin-inline: auto;
}

.pullquote blockquote {
  margin: 0;
  max-width: 40ch;
  font-family: var(--face-display);
  font-style: italic;
  font-size: clamp(1.35rem, 3.2vw, 2.35rem);
  line-height: 1.28;
  color: var(--ink);
  text-wrap: pretty;
}

.pullquote figcaption {
  margin-top: var(--s3);
  font-family: var(--face-mono);
  font-size: var(--t-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* ===========================================================================
   12. THE LEDGER — history page
   ---------------------------------------------------------------------------
   A dated spine. Years in the rail, prose to the right, one hairline running
   the length. This replaces the source's alternating image/paragraph blocks,
   which is the layout the original repeats four times in a row.

   The rail is narrower here than on the other pages (--rail-tight) because a
   year is four characters and a section index is two: a 9rem margin holding
   "1838" is 5rem of nothing, repeated four times down the page.
   =========================================================================== */

.ledger {
  position: relative;
  display: grid;
  gap: var(--s5);
}

.ledger::before {
  display: none;
}

.ledger__row {
  display: grid;
  grid-template-columns: var(--rail-tight) minmax(0, 1fr);
  column-gap: var(--gutter);
  position: relative;
}

.ledger__row::before {
  content: "";
  position: absolute;
  inset-inline-start: var(--rail-tight);
  inset-block-start: 0.5rem;
  inline-size: 5px;
  block-size: 1px;
  background: var(--rule-strong);
}

.ledger__year {
  grid-column: 1;
  font-family: var(--face-mono);
  font-size: var(--t-mono);
  letter-spacing: 0.1em;
  color: var(--ink-2);
  text-align: end;
  padding-top: 0.15rem;
}

/* A continuation row: the source gives no second date, so the rail gets a
   short rule instead of an invented year. At a glance the column reads as a
   chronology with gaps rather than as four identical markers. */
.ledger__year[data-cont="true"] {
  color: var(--ink-4);
}

.ledger__body {
  grid-column: 2;
  min-width: 0;
}

.ledger__body > * + * {
  margin-top: 1.3em;
}

.ledger__body h3 {
  margin-bottom: 0.6em;
}

@media (max-width: 60rem) {
  .ledger::before {
    inset-inline-start: 0;
  }
  .ledger__row {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 0.4rem;
    padding-inline-start: 1.1rem;
  }
  .ledger__row::before {
    inset-inline-start: 0;
    inline-size: 1px;
    block-size: 1.7rem;
  }
  .ledger__year {
    text-align: start;
  }
  .ledger__body {
    grid-column: 1;
  }
}

/* The works, set as a list beside the one real photograph of one of them.
   The source page shows a book lying on a table; pairing the list with the
   book means the list is doing the describing and the photograph is doing the
   proving. */
.works-block {
  display: grid;
  grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr);
  gap: clamp(1.25rem, 3.5vw, 2.75rem);
  align-items: start;
}

@media (max-width: 48rem) {
  .works-block {
    grid-template-columns: minmax(0, 1fr);
  }
  .works-block .plate {
    max-inline-size: 22rem;
  }
}

.works {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--rule);
}

/* ===========================================================================
   BIDI — numeric ranges must not be reordered by the RTL layout
   ---------------------------------------------------------------------------
   A year range is a left-to-right fact inside a right-to-left page. Without
   isolation the Hebrew history page showed "1907–1873" for 1873–1907 and
   "1894–1907" as "1907–1894", because the whole run is neutral characters and
   the paragraph direction wins.

   `direction: ltr` sets the run order; `unicode-bidi: isolate` keeps the fix
   local, so an LTR number next to Hebrew text does not flip the surrounding
   sentence. Alignment is then set physically, because `text-align: end` inside
   an LTR box would mean "right" even on a Hebrew page — and the rail's year
   has to sit next to the prose in both directions.
   =========================================================================== */

.ledger__year,
.works__year,
.nf__code,
.vigil__dates,
[data-num] {
  direction: ltr;
  unicode-bidi: isolate;
}

/* A time range is not a year range, and it fails the same way. "08:00 — 18:00"
   in a Hebrew paragraph laid out as two LTR number runs joined by a neutral
   dash: the paragraph direction wins, the runs swap, and the site prints its
   own broadcast window backwards — measured on the Hebrew /stream page, which
   showed 18:00 — 08:00. Every standalone range is marked `data-num` for this. */
[data-num] {
  font-variant-numeric: tabular-nums;
}

.ledger__year {
  text-align: right;
}

[dir="rtl"] .ledger__year {
  text-align: left;
}

/* The dash inside a range is fine once the box is LTR: a neutral character
   takes the direction of the box it is in, so 1873—1907 stays 1873—1907. What
   it needs is `tnum` so the figures do not jitter as the clock ticks. */
.works__year,
.ledger__year {
  font-variant-numeric: tabular-nums;
}

.works__year {
  font-family: var(--face-mono);
  font-size: var(--t-mono);
  letter-spacing: 0.08em;
  color: var(--flame);
}

.works__year[data-cont="true"] {
  color: var(--ink-4);
}

/* The works list. Title and note are siblings, never nested: a data-t write is
   `textContent = …`, which replaces all children, so a nested binding is
   destroyed the moment the language is painted. */
.works li {
  display: grid;
  grid-template-columns: 6rem minmax(0, 1fr);
  gap: var(--s2);
  align-items: baseline;
  border-bottom: 1px solid var(--rule);
  padding-block: 0.8rem;
}

.works__text {
  min-width: 0;
}

.works__title {
  display: block;
  font-family: var(--face-display);
  font-size: 1.12rem;
  line-height: 1.3;
  color: var(--ink);
}

.works__note {
  display: block;
  font-family: var(--face-ui);
  font-size: var(--t-micro);
  line-height: 1.5;
  color: var(--ink-3);
  margin-top: 0.25rem;
  max-width: 44ch;
}

/* ===========================================================================
   13. CONTACT SHEET — gallery
   ---------------------------------------------------------------------------
   Twelve plates on a six-column grid. The span of every plate is chosen so
   that each row sums to exactly six columns, which is the only way a
   mixed-span grid tiles: 2+2+2, 2+2+2, 3+3, 2+2+2, 6. The first attempt mixed
   2-, 3- and 6-column plates in sequence, which left a one-column hole in
   most rows, so the wall read as a broken grid with plate numbers floating in
   the gaps and no cue where one row ended and the next began.

   Numbered in the rail like a negative written in the margin of a proof
   sheet. The source page has neither captions nor numbering, and a grid of
   twelve unlabelled rectangles is not a gallery — it is a contact sheet
   somebody forgot to label.
   =========================================================================== */

.sheetgrid {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: clamp(0.5rem, 1.4vw, 1.1rem);
  align-items: start;
}

.cell {
  grid-column: span 2;
  position: relative;
  display: block;
  padding: 0;
  background: none;
  border: 0;
  cursor: zoom-in;
  text-align: start;
}

.cell--wide {
  grid-column: span 3;
}

.cell--full {
  grid-column: span 6;
}

.cell__frame {
  position: relative;
  overflow: hidden;
  border-radius: var(--plate-radius);
  background: var(--surface);
  aspect-ratio: 3 / 2;
}

.cell--wide .cell__frame {
  aspect-ratio: 16 / 9;
}

.cell--full .cell__frame {
  aspect-ratio: 21 / 8;
}

.cell img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  /* The wall is dim and the photographs are of a dim place. At rest they sit
     nearly monochrome; the colour arrives on hover, focus, and touch. */
  filter: grayscale(0.72) brightness(0.86) contrast(1.04);
  transition: filter var(--t-slow) var(--ease), transform var(--t-slow) var(--ease);
}

.cell:hover img,
.cell:focus-visible img {
  filter: grayscale(0) brightness(0.98) contrast(1);
  transform: scale(1.015);
}

.cell__cap {
  display: flex;
  justify-content: space-between;
  gap: var(--s2);
  margin-top: 0.5rem;
  font-family: var(--face-mono);
  font-size: var(--t-mono);
  letter-spacing: 0.1em;
  color: var(--ink-4);
  transition: color var(--t-fast) var(--ease);
}

.cell:hover .cell__cap,
.cell:focus-visible .cell__cap {
  color: var(--ink-2);
}

@media (max-width: 60rem) {
  .sheetgrid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
  .cell,
  .cell--wide {
    grid-column: span 2;
  }
  .cell--full {
    grid-column: span 4;
  }
}

@media (max-width: 34rem) {
  .sheetgrid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .cell--full {
    grid-column: span 2;
  }
  .cell--full .cell__frame {
    aspect-ratio: 3 / 2;
  }
}

/* ===========================================================================
   14. LIGHTBOX
   =========================================================================== */

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: grid;
  grid-template-rows: auto 1fr auto;
  background: rgba(4, 3, 3, 0.97);
  padding: var(--s2);
}

.lightbox[hidden] {
  display: none;
}

.lightbox__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s2);
  padding-block: 0.5rem;
}

.lightbox__stage {
  display: grid;
  place-items: center;
  min-height: 0;
  padding: var(--s2) 0;
}

.lightbox__stage img {
  max-block-size: 100%;
  max-inline-size: 100%;
  inline-size: auto;
  object-fit: contain;
  border-radius: var(--plate-radius);
}

.lightbox__foot {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--s3);
  padding-block: var(--s2);
  flex-wrap: wrap;
}

.lightbox__count {
  font-family: var(--face-mono);
  font-size: var(--t-mono);
  letter-spacing: 0.16em;
  color: var(--ink-3);
}

/* ===========================================================================
   15. FORMS
   ---------------------------------------------------------------------------
   A field is a line you write on, not a box you fill in. The label sits above
   in Plex Sans at 13px; the input is a single hairline that brightens on
   focus. No rounded rectangles, no shadows, no placeholder-as-label.
   =========================================================================== */

.field {
  display: block;
  margin-bottom: var(--s3);
}

.field__label {
  display: block;
  font-family: var(--face-ui);
  font-size: var(--t-micro);
  letter-spacing: 0.04em;
  color: var(--ink-3);
  margin-bottom: 0.4rem;
}

.field__input {
  inline-size: 100%;
  background: none;
  border: 0;
  border-bottom: 1px solid var(--rule-strong);
  border-radius: 0;
  padding: 0.6rem 0;
  font-family: var(--face-text);
  font-size: 1.05rem;
  color: var(--ink);
  transition: border-color var(--t-fast) var(--ease);
}

.field__input::placeholder {
  color: var(--ink-4);
  opacity: 1;
}

.field__input:hover {
  border-bottom-color: var(--ink-4);
}

.field__input:focus {
  outline: none;
  border-bottom-color: var(--flame);
}

.field__input:focus-visible {
  outline: none;
}

.field--err .field__input {
  border-bottom-color: #c0563c;
}

.formnote {
  font-family: var(--face-ui);
  font-size: var(--t-micro);
  line-height: 1.6;
  color: var(--ink-3);
  max-width: 46ch;
}

.formmsg {
  font-family: var(--face-ui);
  font-size: var(--t-micro);
  min-block-size: 1.4em;
  margin-top: 0.6rem;
  color: #d4795c;
}

.formmsg[data-ok="true"] {
  color: var(--flame);
}

/* ===========================================================================
   16. THE FILING — legal page
   ---------------------------------------------------------------------------
   A ledger of key/value rows in monospace figures, and the five documents as
   a numbered list. No cards. The original wraps every one of these in a white
   rounded box; here the rows themselves are the structure, separated by
   hairlines, the way a company's disclosure actually reads.
   =========================================================================== */

.kv {
  display: grid;
  grid-template-columns: minmax(9rem, 14rem) minmax(0, 1fr);
  border-top: 1px solid var(--rule);
}

.kv__k,
.kv__v {
  padding-block: 0.85rem;
  padding-inline-end: var(--s2);
  border-bottom: 1px solid var(--rule);
}

.kv__k {
  font-family: var(--face-ui);
  font-size: var(--t-micro);
  color: var(--ink-3);
}

.kv__v {
  font-size: var(--t-body);
  color: var(--ink);
  text-wrap: pretty;
}

.kv__v--mono {
  font-family: var(--face-mono);
  font-size: 0.8125rem;
  letter-spacing: 0.02em;
  overflow-wrap: anywhere;
}

.kv__v a {
  color: var(--flame);
  text-decoration: none;
  border-bottom: 1px solid var(--flame-deep);
}

.kv__v a:hover {
  color: var(--flame-hi);
  border-bottom-color: var(--flame);
}

@media (max-width: 34rem) {
  .kv {
    grid-template-columns: minmax(0, 1fr);
  }
  .kv__k {
    padding-bottom: 0.15rem;
    border-bottom: 0;
  }
  .kv__v {
    padding-top: 0;
  }
}

/* A rulehead already draws its own top rule; without this the ledger below it
   draws a second one 40px lower and the pair reads as a mistake. */
.rulehead + .kv,
.rulehead + .doclist,
.rulehead + .works {
  border-top: 0;
}

.prose--tight > p:last-child {
  margin-bottom: 0;
}

/* Payment logos. These keep their own brand colours because the banks require
   it. The first pass put them on a full-bleed pure-white band, which on a
   ground this dark was a fluorescent stripe across the page — the single
   loudest thing on the site, and it was a legal requirement, not a design
   choice. It is now a paper-coloured plate, sized to its content and ruled like
   a document pasted into a filing, which is what it is. */
.logos {
  display: block;
  inline-size: 100%;
  max-inline-size: 40rem;
  background: #e9e3d7;
  border: 1px solid var(--rule-strong);
  border-radius: 2px;
  padding: clamp(0.6rem, 1.6vw, 1rem);
  block-size: auto;
}

.doclist {
  list-style: none;
  margin: 0;
  padding: 0;
  counter-reset: doc;
  border-top: 1px solid var(--rule);
}

.doclist li {
  counter-increment: doc;
  display: grid;
  grid-template-columns: 2.6rem minmax(0, 1fr) auto;
  gap: var(--s2);
  align-items: center;
  border-bottom: 1px solid var(--rule);
  padding-block: 1rem;
}

.doclist li::before {
  content: counter(doc, decimal-leading-zero);
  font-family: var(--face-mono);
  font-size: var(--t-mono);
  letter-spacing: 0.1em;
  color: var(--ink-4);
}

.doclist__name {
  font-size: var(--t-body);
  color: var(--ink);
}

.doclist__get {
  font-family: var(--face-ui);
  font-size: var(--t-micro);
  color: var(--flame);
  text-decoration: none;
  border-bottom: 1px solid var(--flame-deep);
  padding-bottom: 1px;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

.doclist__get:hover {
  color: var(--flame-hi);
  border-bottom-color: var(--flame);
}

.doclist__get::after {
  content: "↓";
  font-family: var(--face-mono);
}

@media (max-width: 34rem) {
  .doclist li {
    grid-template-columns: 2.2rem minmax(0, 1fr);
  }
  .doclist__get {
    grid-column: 2;
    justify-self: start;
  }
}

/* ===========================================================================
   17. PROFILE
   =========================================================================== */

.profilecard {
  border: 1px solid var(--rule);
  border-radius: var(--plate-radius);
  padding: clamp(1.25rem, 3vw, 2.25rem);
  background: var(--surface);
  max-inline-size: 32rem;
}

.profilecard .kv {
  border-top: 0;
}

/* ===========================================================================
   18. FOOTER
   =========================================================================== */

.footer {
  /* The last section already carries its own bottom padding; a 10rem gap on
     top of that left the page floating before the footer. */
  margin-top: var(--s5);
  border-top: 1px solid var(--rule);
  padding-block: var(--s4) var(--s5);
}

.footer__in {
  display: grid;
  grid-template-columns: var(--rail) minmax(0, 1fr);
  column-gap: var(--gutter);
  row-gap: var(--s4);
}

.footer__col {
  grid-column: 2;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: var(--s3) var(--s4);
  align-items: start;
}

.footer__mark {
  grid-column: 1;
  grid-row: 1;
  inline-size: 1.05rem;
  block-size: 1.15rem;
  fill: var(--ink-3);
}

@media (max-width: 60rem) {
  .footer__in {
    grid-template-columns: minmax(0, 1fr);
  }
  .footer__mark,
  .footer__col {
    grid-column: 1;
  }
  .footer__mark {
    grid-row: auto;
  }
}

.footer__nav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.4rem;
}

.footer__nav a {
  font-family: var(--face-ui);
  font-size: var(--t-micro);
  color: var(--ink-3);
  text-decoration: none;
  /* 24px minimum, which is WCAG 2.5.8 Target Size (Minimum) at AA — measured
     at 22px by tools/audit-ui.mjs and failing it.

     The footer nav is a wrapped inline list, not a row of controls, so 44px
     would mean re-spacing the whole column and there is no honest way to get
     44px out of a 22px line of text without doing that. 24px is the standard
     for this case and it costs 2px. `inline-block` is required: a bare inline
     anchor ignores block-size.

     BOTH axes need it, and the width is not hypothetical: measured in Hebrew,
     where the nav label for the home page is "בית", the link rendered 19x24 —
     passing on height, failing on width. Russian "главная" is 48px wide and
     never showed it, which is exactly the kind of fault a single-language
     review walks past. */
  display: inline-block;
  min-block-size: 1.5rem;
  min-inline-size: 1.5rem;
}

.footer__nav a:hover {
  color: var(--flame);
}

.footer__legal {
  font-family: var(--face-mono);
  font-size: var(--t-mono);
  letter-spacing: 0.04em;
  color: var(--ink-4);
  line-height: 1.9;
  margin: 0;
}

.footer__legal a {
  color: var(--ink-3);
  text-decoration: none;
  border-bottom: 1px solid var(--rule-strong);
}

.footer__legal a:hover {
  color: var(--flame);
  border-bottom-color: var(--flame-deep);
}

/* ===========================================================================
   19. UTILITIES
   =========================================================================== */

.skip {
  position: absolute;
  inset-inline-start: -9999px;
  top: 0;
  z-index: 100;
  background: var(--ink);
  color: var(--ground);
  padding: 0.7rem 1.1rem;
  font-family: var(--face-ui);
  font-size: var(--t-micro);
  text-decoration: none;
}

.skip:focus {
  inset-inline-start: 0;
}

.sr {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.stack > * + * {
  margin-top: var(--s3);
}

.stack--tight > * + * {
  margin-top: var(--s2);
}

.dim {
  color: var(--ink-3);
}

.nowrap {
  white-space: nowrap;
}

/* ===========================================================================
   19b. LAYOUT UTILITIES
   ---------------------------------------------------------------------------
   Every one of these used to be a `style="…"` attribute in the markup, and
   the CSP is `style-src 'self'` — so the browser was silently discarding all
   twenty-six of them. It cost nothing visible except a figure's default
   40px side margin, but "the browser is throwing your CSS away and the page
   still looks fine" is exactly the state where the next bug hides too.

   This is also the right way round: a rule that a designer has to grep for is
   a rule that will drift from the rest of the system.
   =========================================================================== */

.u-flush {
  margin: 0; /* figures inside a grid, which otherwise carry 1em 40px */
}
.u-mt2 {
  margin-top: var(--s2);
}
.u-mt3 {
  margin-top: var(--s3);
}
.u-mt4 {
  margin-top: var(--s4);
}
.u-mb3 {
  margin-bottom: var(--s3);
}
.u-mb4 {
  margin-bottom: var(--s4);
}
.u-mt3-end {
  margin-block-start: var(--s3);
  text-align: end;
}
.u-plate-gap {
  margin: var(--s3) 0 0;
}
.u-narrow {
  max-inline-size: 26rem;
}
.u-center {
  justify-content: center;
}
.u-pb2 {
  padding-bottom: 0.5rem;
}

/* The three prose blocks on the legal page, side by side and divided by rules
   rather than boxed into cards. */
.cols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  gap: var(--s4) var(--s5);
}

/* ===========================================================================
   20. NOTICE
   ---------------------------------------------------------------------------
   The source site's candle, prayer and mailing-list actions are not connected
   to anything: no payment provider, no list. Rather than let a button look
   like it works, each one answers with the truth and points at the address
   that does. The box is a rule, not a toast — nothing slides, nothing times
   out, and it is reachable by keyboard.
   =========================================================================== */

.notice {
  margin-top: var(--s3);
  max-inline-size: 52ch;
  border-inline-start: 2px solid var(--flame-deep);
  padding: 0.15rem 0 0.15rem var(--s2);
  font-family: var(--face-ui);
  font-size: var(--t-micro);
  line-height: 1.65;
  color: var(--ink-2);
}

.notice[hidden] {
  display: none;
}

.notice:focus-visible {
  outline: 2px solid var(--flame);
  outline-offset: 4px;
}

/* ===========================================================================
   21. AUTH PAGES
   ---------------------------------------------------------------------------
   One narrow column, flush left, on the same ground as everything else. The
   source wraps these in a centred white card; here a form is a page, not a
   modal that happens to be a page.
   =========================================================================== */

.authblock {
  max-inline-size: 30rem;
  padding-block: var(--s6) var(--s5);
}

.authblock .formmsg {
  margin-bottom: var(--s3);
}

.authlink {
  margin-top: var(--s4);
  padding-top: var(--s2);
  border-top: 1px solid var(--rule);
  font-family: var(--face-ui);
  font-size: var(--t-micro);
  color: var(--ink-3);
}

.authlink a {
  color: var(--flame);
  text-decoration: none;
  border-bottom: 1px solid var(--flame-deep);
  margin-inline-start: 0.35rem;
}

.authlink a:hover {
  color: var(--flame-hi);
  border-bottom-color: var(--flame);
}

/* ===========================================================================
   22. NOT FOUND
   =========================================================================== */

.nf {
  min-block-size: 60vh;
  display: grid;
  align-content: center;
  padding-block: var(--s6);
}

.nf__code {
  font-family: var(--face-mono);
  font-size: clamp(4rem, 14vw, 9rem);
  line-height: 0.9;
  letter-spacing: 0.04em;
  /* --ink-watermark, not --surface-3. See the token: this painted the numeral
     in a fill colour meant for the light plate, and the "404" measured 1.26:1
     against the ground — present in the DOM, invisible on the page. */
  color: var(--ink-watermark);
  margin: 0 0 var(--s3);
}

/* ===========================================================================
   23. MOTION OFF
   =========================================================================---
   The flame stops flickering and the "recording" dot stops blinking. Nothing
   else in this site moves on its own, so this is the whole of it.
   =========================================================================== */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .flame[data-lit="true"]::before,
  .vigil__frame[data-stage="live"]::before {
    animation: none;
  }
  .masthead {
    backdrop-filter: none;
  }
  .cell img {
    transition: none;
  }
  .cell:hover img {
    transform: none;
  }
}

/* --------------------------------------------------------------------------
   СМЕШЕНИЕ ЦВЕТОВ — только там, где поддерживается.

   Выше стоят запасные варианты на rgba: они не зависят от темы и потому
   не умеют следовать за переменной --ground в режиме высокой контрастности,
   где она становится чёрной. Здесь — точное смешение с переменной, и оно
   применяется только если браузер color-mix понимает.

   Именно так и должно быть: сначала грубое и работающее везде, потом точное
   и только там, где оно действительно считается.
   -------------------------------------------------------------------------- */
@supports (background: color-mix(in srgb, red 50%, transparent)) {
  .masthead {
    background: color-mix(in srgb, var(--ground) 88%, transparent);
  }

  .btn--lit {
    background: color-mix(in srgb, var(--flame) 7%, transparent);
  }

  .btn--lit:hover {
    background: color-mix(in srgb, var(--flame) 15%, transparent);
  }
}
