/* Emma portal. Reference lock: Symbolic paper layers + Waka Waka page artifact
   + Anthropic editorial metadata. One publication, not a SaaS card stack. */

/* The two faces `--sans` and `--mono` name, served from this origin.

   They were named when the palette was written and never delivered -- no `@font-face`, no font
   link -- so every visitor read the site in whatever their machine happened to have: Arial Narrow
   and Consolas on Windows, Courier New on macOS. Released by the owner 2026-09-07,
   `PORTAL_VISUAL_LANGUAGE.md` Amendment 10.

   Self-hosted rather than linked from Google, for two reasons that both matter here. Legal: a
   third-party font request hands Google every visitor's IP on every page view, before any consent,
   and `privacy.html` names only Yandex services as recipients -- the policy would have stopped
   describing the code. Practical: fonts.googleapis.com is unreliable from Russian networks, and a
   font that does not arrive leaves exactly the fallback this change exists to remove.

   The `unicode-range` split is Google's own and is load-bearing: a reader of the Russian site
   downloads the cyrillic file and never fetches latin-ext. Onest is variable, so 400-800 is one
   file per subset rather than five. Twelve files, 176 KB, none of it fetched unless a page
   actually paints a glyph from that range. */

@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-mono-400-cyrillic-ext.woff2') format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-mono-400-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-mono-400-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-mono-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-mono-500-cyrillic-ext.woff2') format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-mono-500-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-mono-500-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-mono-500-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Onest';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url('/assets/fonts/onest-400-800-cyrillic-ext.woff2') format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
@font-face {
  font-family: 'Onest';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url('/assets/fonts/onest-400-800-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Onest';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url('/assets/fonts/onest-400-800-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Onest';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url('/assets/fonts/onest-400-800-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  --canvas: #202020;
  --paper: #fdfcf5;
  --paper-bright: #fffef9;
  --paper-muted: #f0eee6;
  --ink: #171716;
  --muted: #686761;
  --line: #d5d0b8;
  --red: #f42c2b;
  /* The two strengths of the one mark. `--mark` is "you are pointing at this", `--mark-here`
     is "you are on this". Declared as flat rgba first because a custom property holding an
     unsupported `color-mix` is invalid at use time, not at declaration time -- the usual
     two-declaration fallback silently produces no colour at all. */
  --mark: rgba(244, 44, 43, .3);
  --mark-here: rgba(244, 44, 43, .8);
  /* How far every mark hangs below the baseline. One value, because the owner asked for the
     gap to be the same everywhere and then to grow -- two edits that would each have to be
     made in as many places as there are marks if this were written out per rule. */
  --mark-gap: .5em;
  /* Одно небольшое скругление на все углы всех элементов входа и плашки про куки — по указанию
     владельца 29.08.2026: «зачем по-разному скруглил, оставь одно небольшое скругление по всем
     краям, это касается и плашки с куками». В одном окне было три разных радиуса: карточка,
     поле и кнопка. Рваный угол §3.3 остаётся приёмом страницы и этих поверхностей не касается. */
  --radius: .6rem;
  --violet: #6938ef;
  --serif: "Iowan Old Style", "Palatino Linotype", "Book Antiqua", Georgia, "Times New Roman", serif;
  --sans: Onest, "Arial Narrow", "Roboto Condensed", "Segoe UI", system-ui, sans-serif;
  --mono: "IBM Plex Mono", Consolas, "Courier New", monospace;
  /* Briefly widened to 84/74 on 2026-08-28 to fit three cards, and put back the same day: the
     owner wants every page at the landing's width. The library fits two materials per row
     instead, which at this width is the larger card anyway. */
  --sheet-width: 70rem;
  --content-width: 62rem;
  --gutter: clamp(1.4rem, 4.2vw, 3.6rem);
}

@supports (color: color-mix(in srgb, red 30%, transparent)) {
  :root {
    --mark: color-mix(in srgb, var(--red) 30%, transparent);
    --mark-here: color-mix(in srgb, var(--red) 80%, transparent);
  }
}

* { box-sizing: border-box; }

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

body {
  min-width: 320px;
  margin: 0;
  padding: clamp(.75rem, 2vw, 1.75rem);
  overflow-x: hidden;
  background: var(--canvas);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.55;
}

a { color: inherit; }
img { display: block; max-width: 100%; }

.paper-shell {
  position: relative;
  width: min(100%, var(--sheet-width));
  margin-inline: auto;
  /* Keep the sheet's rounded clipping without becoming the sticky header's scroll container. */
  overflow: clip;
  border-radius: 2.4rem;
  background: var(--paper);
  box-shadow: 0 18px 60px rgba(0, 0, 0, .28);
}

.paper-shell::after {
  position: absolute;
  inset: 0;
  z-index: 20;
  pointer-events: none;
  border: 1px solid rgba(255, 255, 255, .18);
  border-radius: inherit;
  content: "";
}

main { background: var(--paper); }

.wrap {
  width: min(100%, var(--content-width));
  margin-inline: auto;
}

section {
  position: relative;
  padding: clamp(3rem, 7vw, 5.4rem) var(--gutter);
}

section + section { border-top: 1px solid var(--line); }
.band { background: transparent; }
p { margin: 0 0 1rem; }

h1,
h2,
h3 {
  margin: 0;
  font-family: var(--serif);
  font-weight: 400;
  text-wrap: balance;
}

h2 {
  max-width: 18ch;
  margin-bottom: 2.2rem;
  font-size: clamp(2.1rem, 4.8vw, 4rem);
  letter-spacing: -.045em;
  line-height: .98;
}

h3 { font-size: 1.18rem; line-height: 1.15; }

/* Masthead */

.bar {
  position: sticky;
  top: 0;
  z-index: 10;
  padding: 1.25rem var(--gutter) 1.1rem;
  border-bottom: 1px solid var(--line);
  background: rgba(253, 252, 245, .96);
}

.bar-inner {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  width: min(100%, var(--content-width));
  margin-inline: auto;
  gap: 1.25rem;
}

/* Wordmark and face travel together in the bar's left cell, so the photo sits beside the name
   rather than in the grid's centre column, which belongs to the edition line. */
.mark-group {
  display: inline-flex;
  align-items: center;
  gap: .6rem;
  justify-self: start;
}

/* The ring is `--red`, the page's one accent, used here as punctuation exactly as it is on the
   story card's bar and the blockquote rule -- not as a new decorative colour.
   `object-fit: cover` keeps a portrait from stretching inside the circle. */
.mark-face {
  width: 2.1rem;
  height: 2.1rem;
  border: 2px solid var(--red);
  border-radius: 50%;
  object-fit: cover;
}

.mark {
  font-size: 1.12rem;
  font-weight: 800;
  letter-spacing: .2em;
  line-height: 1;
  text-decoration: none;
}

.edition {
  color: var(--muted);
  font-family: var(--mono);
  font-size: .64rem;
  letter-spacing: .07em;
  text-transform: uppercase;
}

.nav { display: flex; align-items: baseline; justify-self: end; gap: clamp(.9rem, 2.2vw, 1.7rem); }

/* The typewriter face, same as the edition line beside it and the library's subsection strip.
   The bar is a row of labels; the sans belongs to running text. */
.nav a {
  display: inline-block;
  font-family: var(--mono);
  font-size: .66rem;
  letter-spacing: .07em;
  text-transform: uppercase;
  text-decoration: none;
  transition: transform .2s ease;
}

/* One mark for the whole site, not one per surface.
   -----------------------------------------------------------------------------------------
   Owner, 2026-08-29: «лишнее подчёркивание убери, и так полутоном надо не только в библиотеке
   а вообще как правило» -- pointing at the masthead, where hovering drew a plain ink underline
   while the library's subsection strip a few pixels below drew the half-tone red one. Two
   different answers to the same question on the same screen.

   So the red half-tone rule is now the site's only hover/focus mark on a label link, and the
   ink underline is gone. It is drawn with `text-decoration` everywhere -- on the tab's `b`
   rather than on the tab itself, so the count in `i` beside it stays unmarked -- because a
   decoration costs no layout, follows a link that wraps onto a second line, and hangs from the
   baseline, which is the only way two marks on different elements can sit at the same depth.

   Links inside article prose (`.read-body a`) are deliberately not in this list: an underline
   there is how a reader tells a link from a word, not a marker of where the pointer is. */
.nav a:hover,
.nav a:focus-visible,
.story-card a:hover,
.story-card a:focus-visible,
.lib-back:hover,
.lib-back:focus-visible,
/* `nav`, not the whole row: the subsection strip is a `ul` inside the same `.crumbs` div, so
   `.crumbs a` also matches `.lib-tab` and painted a second line across the tab -- one that
   broke in the middle, because a decoration on the link covers the label and the count but
   leaves the flex gap between them unpainted. Owner, 2026-08-29: «вот под словом практики две
   черты и верхняя прерывается ещё». The breadcrumb links are the ones inside the nav. */
.crumbs nav a:hover,
.crumbs nav a:focus-visible,
.lib-all a:hover,
.lib-all a:focus-visible,
.lib-intro .section-label a:hover,
.lib-intro .section-label a:focus-visible,
.lib-pages a:hover,
.lib-pages a:focus-visible,
.lib-tab:hover b,
.lib-tab:focus-visible b {
  text-decoration: underline;
  text-decoration-color: var(--mark);
  text-decoration-thickness: 2px;
  text-underline-offset: var(--mark-gap);
}

/* Being somewhere is a heavier statement than pointing at it, so the two differ in weight and
   not only in dilution -- owner, 2026-08-29: «толщину линии нижней ... возможно надо сделать
   чуть толще, при наведении всё равно две полоски». Two red lines are on screen whenever a
   pointer rests anywhere, and matching their weight is what made them read as a pair instead
   of as a hint next to a state.

   The gap under the text is one value everywhere («отступы наверно одинаковые»), which is why
   the tab marker moved off `border-bottom` and onto the same `text-decoration` as the rest: a
   border hangs below the descender and an underline hangs below the baseline, so the two could
   not be brought level while they were drawn by different mechanisms. Setting the decoration on
   `b` rather than on the link keeps it off the count in `i`, which is what the border was there
   to prevent (Amendment 4), and a decoration costs no layout, so nothing shifts on hover. */
.lib-tab[aria-current] b,
.nav .nav-active {
  text-decoration: underline;
  text-decoration-color: var(--mark-here);
  text-decoration-thickness: 3px;
  text-underline-offset: var(--mark-gap);
}
.nav a:hover,
.nav a:focus-visible { transform: scale(1.035); }


/* Плашка про куки.
   -----------------------------------------------------------------------------------------
   Новая поверхность, собранная из того же словаря, что окно входа (§5 разрешает новые
   поверхности, оформленные по §2-§3): бумага, тёплая тень, рваный угол, кнопки как у формы.
   Красный здесь не появляется вовсе -- §3.4 запрещает акцент заливкой, а «Принять» это именно
   заливка, поэтому она чернильная, как и остальные главные кнопки на сайте.

   Плашка не перекрывает страницу и не блокирует чтение: она лежит внизу, поверх содержимого,
   и её можно игнорировать сколько угодно. Модальное окно с затемнением на её месте было бы
   требованием выбора, а выбор здесь не обязателен -- пока согласия нет, счётчик не грузится. */
.cookie {
  position: fixed;
  z-index: 40;
  left: 50%;
  bottom: clamp(.8rem, 2.5vw, 1.6rem);
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: .9rem 1.6rem;
  width: min(94vw, var(--content-width));
  padding: .95rem 1.3rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--paper-bright);
  box-shadow: 0 14px 38px rgba(111, 104, 72, .3);
}
.cookie[hidden] { display: none; }

.cookie-text {
  margin: 0;
  max-width: 46rem;
  color: var(--muted);
  font-size: .84rem;
  line-height: 1.45;
}
.cookie-text a { color: var(--ink); }

.cookie-buttons { display: flex; gap: .55rem; flex-wrap: wrap; }

.cookie-no,
.cookie-yes {
  min-height: 2.4rem;
  padding: .45rem 1.1rem;
  border-radius: var(--radius);
  font: inherit;
  font-size: .84rem;
  cursor: pointer;
}
.cookie-no {
  border: 1px solid var(--line);
  background: transparent;
  color: var(--ink);
}
.cookie-no:hover,
.cookie-no:focus-visible { border-color: var(--ink); }
.cookie-yes {
  border: 1px solid var(--ink);
  background: var(--ink);
  color: var(--paper-bright);
}
.cookie-yes:hover,
.cookie-yes:focus-visible { background: var(--canvas); }

@media (max-width: 620px) {
  .cookie { flex-direction: column; align-items: stretch; }
  .cookie-buttons { justify-content: flex-end; }
}

/* Editorial hero: the brain sits on the page, never inside a card.
   Owner, 2026-09-12: more air on desktop and mobile, including beside the dividing rules.
   The smaller type and image leave room inside the existing sheet. */

.hero { min-height: 0; padding: 0; overflow: hidden; }

.hero-stage {
  position: relative;
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  grid-template-rows: auto 1fr auto;
  gap: 0 1rem;
  min-height: 34rem;
  padding: 3rem var(--gutter);
}

.hero-folio {
  grid-column: 1 / 4;
  grid-row: 1;
  margin: 0;
  color: var(--muted);
  font-family: var(--mono);
  font-size: .68rem;
  letter-spacing: .08em;
}

/* The red rule follows its label in normal flow, so changing the spacing cannot put it
   across the headline. */
.hero-folio::after {
  display: block;
  width: 3.8rem;
  height: 2px;
  margin-top: 1.1rem;
  background: var(--red);
  content: "";
}

.hero-copy {
  position: relative;
  z-index: 4;
  grid-column: 1 / 7;
  grid-row: 2;
  align-self: center;
  padding-block: 1.75rem .5rem;
}

.hero-title {
  max-width: 10ch;
  font-size: clamp(3.25rem, 6vw, 5.4rem);
  letter-spacing: -.07em;
  line-height: .94;
}

.hero-title span { display: block; }
/* Keep the reading measure: narrowing this copy would spend the extra space on more lines. */
.hero-text { max-width: 28rem; margin: 1.5rem 0 0; color: var(--muted); font-size: 1rem; }
.hero-action { margin-top: 1.5rem; }

/* Строка под кнопкой: снятие риска и ближайшее свободное окно. Второе приходит из календаря
   и появляется, только если пришло. */
.hero-fine { margin: .7rem 0 0; color: var(--muted); font-family: var(--mono); font-size: .64rem; }
/* `display` у этого элемента не переопределяется намеренно: пока он `hidden`, браузер держит его
   скрытым сам, и точка-разделитель не рисуется. Стоило один раз написать здесь `display: inline`,
   и на странице повисла одинокая точка при недоступном календаре. */
.hero-fine .next-slot::before { content: " · "; }
.next-slot { margin: .8rem 0 0; color: var(--muted); font-family: var(--mono); font-size: .68rem; }

.cta {
  display: inline-flex;
  align-items: center;
  gap: 1.8rem;
  min-height: 2.85rem;
  margin-top: .75rem;
  padding: .7rem 1.15rem;
  border: 1px solid var(--ink);
  border-radius: 1rem;
  background: var(--ink);
  color: var(--paper);
  font-size: .82rem;
  line-height: 1;
  text-decoration: none;
  transition: background .2s ease, color .2s ease, transform .2s ease;
}

.cta:hover,
.cta:focus-visible { background: transparent; color: var(--ink); transform: translateY(-2px); }
.cta-hero { margin: 0; }
.cta-hero span { font-size: 1.35rem; }

.brain-scene {
  position: relative;
  z-index: 1;
  grid-column: 6 / 13;
  grid-row: 1 / 4;
  align-self: stretch;
  /* Original image size (owner, 2026-09-13). `object-fit: contain` is width-limited here:
     restoring height alone leaves the brain small. Keep the original horizontal span,
     with the new vertical breathing room supplied by the hero stage. */
  min-height: 31rem;
  margin: 0 -2.5rem 0 -1.8rem;
  overflow: visible;
  pointer-events: none;
}

.brain-art,
#brain-canvas-back,
#brain-canvas-front { position: absolute; inset: 0; width: 100%; height: 100%; }

.brain-art {
  z-index: 1;
  object-fit: contain;
  object-position: center;
  filter: saturate(1.04) contrast(1.03);
  animation: brain-breathe 12s ease-in-out infinite;
}

#brain-canvas-back,
#brain-canvas-front { mix-blend-mode: normal; }
#brain-canvas-back { z-index: 0; opacity: .38; }
#brain-canvas-front { z-index: 2; opacity: .72; }


.brain-caption {
  position: absolute;
  right: 2.5rem;
  bottom: 0;
  z-index: 3;
  display: flex;
  flex-direction: column;
  margin: 0;
  padding-left: 2.8rem;
  color: var(--muted);
  font-family: var(--mono);
  font-size: .6rem;
  line-height: 1.45;
  text-transform: uppercase;
}

.brain-caption::before {
  position: absolute;
  left: 0;
  top: .45rem;
  width: 2.1rem;
  border-top: 1px solid var(--ink);
  content: "";
}

@keyframes brain-breathe {
  50% { transform: scale(1.025) rotate(.55deg); filter: saturate(1.12) contrast(1.04) hue-rotate(5deg); }
}

/* Unequal paper fragments form the article library. */

.library { padding-top: 4rem; }

.library-head {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: 1rem;
  align-items: end;
}

.section-label,
.story-meta {
  margin: 0;
  color: var(--muted);
  font-family: var(--mono);
  font-size: .68rem;
  letter-spacing: .07em;
  text-transform: uppercase;
}

.section-label { grid-column: 1 / 4; align-self: start; padding-top: .35rem; }
.library-head h2 { grid-column: 4 / 10; margin: 0; }
.library-head > p:last-child { grid-column: 10 / 13; margin: 0; color: var(--muted); font-size: .78rem; line-height: 1.45; }

.library-grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  grid-template-rows: minmax(10rem, auto) minmax(9rem, auto);
  gap: .8rem 1rem;
  margin-top: 2.7rem;
}

.story-card {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  min-height: 10rem;
  padding: 1.25rem;
  background: var(--paper-bright);
}

.story-card h3 {
  max-width: 19ch;
  margin: 1.6rem 0 1.2rem;
  font-size: clamp(1.35rem, 2.7vw, 2.4rem);
  letter-spacing: -.035em;
}

.story-card a { align-self: flex-start; font-size: .74rem; text-decoration: none; }
.story-card a span { margin-left: .5rem; }

.story-card-wide {
  grid-column: 1 / 8;
  grid-row: 1 / 3;
  min-height: 21rem;
  padding: 1.6rem;
  border-radius: 1.7rem .55rem 1.7rem .55rem;
  box-shadow: 0 5px 16px rgba(111, 104, 72, .13);
  transform: rotate(-.35deg);
}

.story-card-wide::after { position: absolute; right: 1.35rem; top: 0; width: 2.2rem; height: .38rem; background: var(--red); content: ""; }
.story-card-wide h3 { max-width: 16ch; font-size: clamp(2rem, 4.1vw, 3.65rem); line-height: .96; }

.story-card:nth-child(2) {
  grid-column: 8 / 13;
  grid-row: 1;
  border-top: 1px solid var(--ink);
  border-bottom: 1px solid var(--line);
  background: transparent;
}

.story-card:nth-child(2) h3 { margin-block: 1.1rem; }

.story-card-accent {
  grid-column: 8 / 13;
  grid-row: 2;
  border-radius: .45rem 1.4rem 1.4rem .45rem;
  background: var(--paper-muted);
  box-shadow: 0 3px 10px rgba(111, 104, 72, .1);
}

.story-card-accent::before { position: absolute; left: 0; top: 1rem; bottom: 1rem; width: .3rem; border-radius: 0 1rem 1rem 0; background: var(--red); content: ""; }

/* Recognition */

/* Колонки равные. Асимметрия 1.2 / .8 работала, пока цитат было три и две; с пятью и пятью узкая
   правая вытягивалась почти вдвое по высоте, и блок читался как перекошенный. */
.two { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(1.5rem, 5vw, 4.5rem); }
.quotes { padding-top: 1rem; border-top: 1px solid var(--ink); }

.quotes:nth-child(2) {
  align-self: start;
  padding: 1.25rem;
  border: 0;
  border-radius: .5rem 1.4rem .5rem 1.4rem;
  background: var(--paper-bright);
  box-shadow: 0 3px 12px rgba(111, 104, 72, .1);
  transform: rotate(.45deg);
}

.quotes h3 { margin-bottom: 1.3rem; }

blockquote {
  margin: 0 0 1.15rem;
  padding-left: 1rem;
  border-left: 1px solid var(--line);
  font-family: var(--serif);
  font-size: 1.03rem;
  line-height: 1.4;
}

.src { max-width: 38rem; margin: 2rem 0 0; color: var(--muted); font-size: .72rem; }

/* Method */

#kak .wrap { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: 1rem; }
#kak h2 { grid-column: 1 / 7; }
/* Правая колонка — один поток, а не три ячейки. Иначе первый абзац делит строку сетки с высоким
   заголовком, строка тянется под заголовок, и под абзацем открывается дыра. */
#kak .wrap > .kak-text { grid-column: 8 / 13; grid-row: 1 / span 2; padding-top: 1.1rem; color: #343430; }
#kak .kak-text p { margin: 0 0 1rem; }
#kak .kak-text p:last-child { margin-bottom: 0; }

#kak .wrap > .hit {
  grid-column: 1 / 7;
  grid-row: 2 / span 2;
  align-self: start;
  margin: 1.2rem 0 0;
  padding: 1.4rem 1.6rem 1.6rem;
  border-radius: 1.4rem .35rem 1.4rem .35rem;
  background: var(--paper-bright);
  box-shadow: 0 4px 14px rgba(111, 104, 72, .11);
  color: var(--ink);
  font-family: var(--serif);
  font-size: clamp(1.55rem, 3vw, 2.35rem);
  line-height: 1.12;
  transform: rotate(-.3deg);
}

.caps { display: inline-block; margin-top: .65rem; color: var(--red); font-family: var(--mono); font-size: .7rem; letter-spacing: .08em; text-transform: uppercase; }

/* Steps */

.steps { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); list-style: none; margin: 0; padding: 0; }
.steps li { min-height: 15rem; padding: 1rem 1.15rem 0; border-top: 1px solid var(--ink); border-left: 1px solid var(--line); }
.steps li:first-child { border-left: 0; padding-left: 0; }
.steps li:last-child { padding-right: 0; }
.n { display: block; margin-bottom: 2.6rem; color: var(--muted); font-family: var(--mono); font-size: .67rem; }
.steps h3 { margin-bottom: .65rem; }
.steps p { margin: 0; color: #44433f; font-size: .82rem; line-height: 1.5; }

/* Form */

#zapis .wrap { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(2rem, 4vw, 4rem); align-items: start; }
#zapis .booking-intro { grid-column: 1; }
#zapis h2 { margin-bottom: .8rem; }
#zapis .sub { margin: 0; color: var(--muted); font-size: .82rem; }
/* Колонка с полем опущена: вровень с заголовком она читалась как часть заголовка, а не как
   отдельное действие. Отступ съезжает вместе с одноколоночной раскладкой и там просто держит
   воздух между текстом и полем. */
#zapis .booking-action { grid-column: 2; min-width: 0; padding-top: 1.5rem; }

.form {
  grid-column: 2;
  grid-row: 1 / span 2;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
  margin: 0;
  padding: 1.65rem;
  border-radius: 1.6rem .45rem 1.6rem .45rem;
  background: var(--paper-bright);
  box-shadow: 0 5px 16px rgba(111, 104, 72, .13);
  transform: rotate(.25deg);
}

.form .step { display: contents; }
.form .step[hidden] { display: none; }
.form label { display: flex; flex-direction: column; gap: .42rem; }
.form label:nth-child(3),
.form .check,
.form .form-note { grid-column: 1 / -1; }
.form label > span { color: #45443f; font-size: .75rem; }

.form input[type="text"],
.form input[type="email"],
.form input[type="tel"],
.form select { width: 100%; min-height: 2.7rem; padding: .65rem .75rem; border: 1px solid var(--line); border-radius: .4rem; background: var(--paper); color: var(--ink); font: inherit; font-size: .86rem; }

/* The honeypot field: present in the DOM (so a script filling every input catches it) but
   invisible and unreachable to a real visitor -- `display:none` is deliberately avoided since
   some scripted fillers skip hidden inputs, which would defeat the point. */
.hp { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
     clip: rect(0,0,0,0); white-space: nowrap; border: 0; }

.slot-list { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: .5rem; }
.slot-list button {
  padding: .55rem .9rem; border: 1px solid var(--line); border-radius: .8rem;
  background: var(--paper); color: var(--ink); cursor: pointer; font: inherit; font-size: .78rem;
}
.slot-list button:hover,
.slot-list button:focus-visible { border-color: var(--ink); }

.check { flex-direction: row !important; align-items: flex-start; gap: .65rem !important; }
.check input { margin-top: .25rem; }
.check span { color: var(--muted) !important; font-size: .7rem !important; }

.form button {
  justify-self: start;
  min-height: 2.75rem;
  padding: .7rem 1.15rem;
  border: 1px solid var(--ink);
  border-radius: 1rem;
  background: var(--ink);
  color: var(--paper);
  cursor: pointer;
  font: inherit;
  font-size: .8rem;
}

.form input:focus-visible,
.form select:focus-visible,
.form button:focus-visible,
.cta:focus-visible { outline: 2px solid var(--violet); outline-offset: 3px; }
.form-note { margin: 0; color: var(--muted); font-size: .68rem; }

/* Author, questions and close */

.profile .wrap { display: grid; grid-template-columns: 1fr 1fr; column-gap: clamp(2rem, 7vw, 6rem); row-gap: 1.5rem; }
.profile h2 { grid-column: 1; grid-row: 1; }
/* Колонка с дипломами и колонка с текстом разведены по строкам явно. Пока полоса стояла
   обычным элементом сетки, она попадала в одну строку с первым абзацем и растягивала её на
   свою высоту — между первым и вторым абзацем зияло 260 px пустоты (владелец, снимок 09.09).
   Заголовок держит строку 1 один, диплом и текст стоят оба в строке 2 и потому начинаются с
   одной линии: иначе правая колонка визуально уезжала вверх (владелец, второй снимок 09.09). */
.profile .creds-wrap { grid-column: 1; grid-row: 2; align-self: start; }
.profile-text { grid-column: 2; grid-row: 2; }
.profile-text p { max-width: 34rem; }

.faq { display: grid; grid-template-columns: 1fr 1fr; gap: 2.1rem 3rem; }
.faq > div { padding-top: 1rem; border-top: 1px solid var(--line); }
.faq h3 { margin-bottom: .7rem; }
.faq p { margin: 0; color: #46453f; font-size: .82rem; }

/* Дипломы: полоса с листанием в левой колонке «Кто проводит» (решение владельца 09.09 — раньше
   они стояли отдельной секцией сеткой, и он попросил перенести их сюда и дать листать).

   Новая поверхность по §5 PORTAL_VISUAL_LANGUAGE: рамка, цвет подписи и шрифты — существующие
   токены, ничего нового в язык не вводится. Скрипта нет и не нужно: прокрутка нативная, палец
   на телефоне и трекпад на десктопе листают сами, а без JS полоса остаётся рабочей.

   `flex-basis: 84%` намеренно меньше сотни: край следующего диплома выглядывает и служит
   единственным намёком на то, что здесь листается — полосы прокрутки на macOS не видно.

   `height: auto` стоит явно, хотя и наследуется: 08.09 всем четырём картинкам была прописана
   одна коробка 640x470 при разных настоящих размерах, и владелец увидел искажение до 5 %.
   Настоящие размеры теперь в разметке, а эта строка не даёт им разъехаться снова. */
.creds {
  display: flex;
  gap: .8rem;
  padding-bottom: .7rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  overscroll-behavior-x: contain;
}
.creds figure { flex: 0 0 84%; margin: 0; scroll-snap-align: start; }
.creds img { height: auto; border: 1px solid var(--line); }
.creds figcaption { margin-top: .55rem; color: #46453f; font-size: .76rem; }
.creds figcaption span { display: block; margin-top: .15rem; color: var(--muted); font-size: .68rem; }
/* Ниже — вид, который включает скрипт, добавив классу `is-slider`. Без него полоса остаётся
   обычной прокруткой с видимым ползунком и выглядывающим краем следующего диплома: это
   единственная подсказка, что здесь есть что листать. Точек в разметке нет намеренно — иначе
   без скрипта на странице стояли бы кнопки, которые ничего не делают. */
.creds.is-slider { padding-bottom: 0; scrollbar-width: none; }
.creds.is-slider::-webkit-scrollbar { display: none; }
.creds.is-slider figure { flex-basis: 100%; }
.creds-dots { display: flex; gap: .45rem; margin-top: .9rem; }
.creds-dots button {
  width: .5rem;
  height: .5rem;
  padding: 0;
  border: 1px solid var(--muted);
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
}
.creds-dots button[aria-current="true"] { border-color: var(--red); background: var(--red); }
.creds-dots button:focus-visible { outline: 2px solid var(--red); outline-offset: 2px; }

/* Отзывы: одна стена сообщений. Владелец, 09.09: «надо так, чтобы как телеграм сообщения были,
   имена можно сделать как пишут пересланное сообщение, но там всё зачёркнуто», затем «я бы первый
   тоже сделал коллаж» и «зачёркивания я бы сделал настоящие и красным цветом, как у нас».

   Донор смотрели вместе: mymind.com/reviews (Refero) — стена коротких карточек в колонки разной
   высоты, половина подписей «Anonymous». Она и доказывает, что анонимная стена читается как
   доказательство, а не как отговорка.

   Новая поверхность по §5 PORTAL_VISUAL_LANGUAGE: форма новая, материал старый. Все цвета —
   объявленные токены, включая `--violet` (до сих пор жил только в обводке фокуса у `.cta`) на
   шапке пересылки: в мессенджере эта строка цветная, серой она читалась бы просто как подпись.

   Пузыри только входящие — слева, срезанный угол снизу, без галочек прочтения. Это не стилизация,
   а следствие: люди писали Эмме, значит сообщение входящее, а у входящего галочек не бывает.
   Времени нет по той же причине: у карточек с Taplink настоящей даты не существует, а
   правдоподобное «14:32» было бы подделкой свидетельства. Появятся даты — появится и `time`. */
.wall {
  padding: clamp(.9rem, 2.5vw, 1.4rem);
  border-radius: 1.1rem;
  background: var(--paper-muted);
}

/* Колонки, а не сетка: у отзывов разная длина, и `columns` укладывает их без дыр под короткими. */
.collage { margin: 0; padding: 0; columns: 3; column-gap: .8rem; list-style: none; }

.msg {
  position: relative;
  margin-bottom: .8rem;
  padding: .65rem .85rem .7rem;
  border: 1px solid var(--line);
  border-radius: 1rem 1rem 1rem .2rem;
  background: var(--paper-bright);
  break-inside: avoid;
  transition: transform .18s ease, box-shadow .18s ease;
}
/* `:not(.msg-from)` не для красоты: `.msg p` весит больше, чем `.msg-from`, и без исключения
   шапка пересылки получила бы размер текста сообщения и потеряла отступ под собой. */
.msg p:not(.msg-from) { margin: 0; font-size: .8rem; line-height: 1.5; }
.msg-from {
  display: flex;
  align-items: center;
  gap: .4rem;
  margin: 0 0 .35rem;
  padding-left: .5rem;
  border-left: 2px solid var(--violet);
  color: var(--violet);
  font-family: var(--mono);
  font-size: .6rem;
}

/* Имя зачёркнуто от руки, нашим красным. Владелец вела к этому в пять заходов 09.09: «красным
   цветом, как у нас» → «чтобы больше похоже, как будто зачеркали» → «побольше зачёркивания» →
   «крест, но не две линии, а больше» → «ошибка в том, что ты пытаешься в одном месте все линии
   пересечь» → «посмотри примеры в интернете» → «можно побольше».

   Каждая правка снимала одну мою ошибку, и последние две — главные. Первая: мои штрихи шли через
   всю ширину и потому сходились в одной точке посередине; рука так не черкает, штрихи короче и
   ложатся внахлёст, пересекаясь в разных местах. Вторая нашлась в Rough.js (roughjs.com) и его
   надстройке Rough Notation, где есть готовый приём «crossed-off»: рукописность даёт не форма
   линии, а то, что каждый штрих проводится ДВАЖДЫ — два прохода с чуть разными концами и
   смещёнными контрольными точками, плюс лёгкая выгнутость. Один гладкий безье всегда читается
   как вычерченный, сколько их ни рисуй. Библиотека не подключена: приём повторён генератором, на
   странице лежит готовый результат.

   Двенадцать штрихов по два прохода. Случайность была засеяна фиксированным числом, поэтому
   росчерк один и тот же всегда, а не новый при каждой сборке. Чем больше штрихов, тем тоньше
   каждый: иначе середина заливается в пятно и росчерк снова становится плашкой.

   Форма приходит из `mask-image`, цвет даёт `background` из токена `--mark-here`. Так красный
   остаётся одним значением в одном месте; зашей я цвет внутрь SVG, он бы жил второй копией и
   разошёлся с палитрой при первой же правке. Данные лежат прямо в строке — ни одного лишнего
   запроса, ни одного файла.

   Контрастных требований тут нет: это не текст, а украшение, и к дефекту §6 про красный на бумаге
   оно ничего не добавляет.

   Имени под росчерком нет — и это отдельное решение владельца, а не следствие. На вопрос «а мы
   можем там поставить имена» она уточнила: «везде пусть будет росчерк, я просто хотел имена под
   росчерком». Имя под маркой не спрятано: оно лежало бы в исходнике страницы, копировалось вместе
   с текстом и читалось экранным диктором вслух, то есть было бы закрыто только от зрячих. Плюс у
   восемнадцати отзывов из личного чата имени и нет — перенабирая скриншоты, владелец имена не
   переносила. Три ширины стоят для правдоподобия и намеренно не совпадают с длиной настоящих имён. */
.redact {
  display: inline-block;
  height: 1.05rem;
  vertical-align: -.28em;
  background: var(--mark-here);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 24' preserveAspectRatio='none'%3E%3Cpath d='M5.7,7.3 C23.9,13.2 36.8,11.7 46.8,22.3' fill='none' stroke='%23000' stroke-width='1.90' stroke-linecap='round' stroke-opacity='1.00'/%3E%3Cpath d='M6.8,-0.3 C27.2,12.5 40.9,13.8 43.2,24.6' fill='none' stroke='%23000' stroke-width='1.90' stroke-linecap='round' stroke-opacity='0.78'/%3E%3Cpath d='M11.1,17.9 C33.9,8.7 44.3,7.6 62.2,4.5' fill='none' stroke='%23000' stroke-width='1.75' stroke-linecap='round' stroke-opacity='0.90'/%3E%3Cpath d='M3.7,24.5 C34.5,6.0 50.6,8.6 55.6,6.8' fill='none' stroke='%23000' stroke-width='1.75' stroke-linecap='round' stroke-opacity='0.68'/%3E%3Cpath d='M13.7,4.4 C40.8,6.7 57.7,11.2 73.6,18.4' fill='none' stroke='%23000' stroke-width='1.60' stroke-linecap='round' stroke-opacity='0.80'/%3E%3Cpath d='M16.8,6.6 C47.0,6.4 63.1,9.3 72.2,17.3' fill='none' stroke='%23000' stroke-width='1.60' stroke-linecap='round' stroke-opacity='0.58'/%3E%3Cpath d='M20.8,22.2 C41.6,12.3 55.1,7.4 67.6,7.3' fill='none' stroke='%23000' stroke-width='1.90' stroke-linecap='round' stroke-opacity='0.70'/%3E%3Cpath d='M18.1,24.3 C40.5,10.8 58.5,0.4 63.1,5.2' fill='none' stroke='%23000' stroke-width='1.90' stroke-linecap='round' stroke-opacity='0.48'/%3E%3Cpath d='M25.8,2.4 C54.6,11.7 67.7,11.9 78.4,19.0' fill='none' stroke='%23000' stroke-width='1.75' stroke-linecap='round' stroke-opacity='1.00'/%3E%3Cpath d='M24.9,1.5 C53.3,5.1 71.5,13.4 80.9,16.1' fill='none' stroke='%23000' stroke-width='1.75' stroke-linecap='round' stroke-opacity='0.78'/%3E%3Cpath d='M29.9,17.5 C58.9,10.1 71.7,7.1 87.0,2.8' fill='none' stroke='%23000' stroke-width='1.60' stroke-linecap='round' stroke-opacity='0.90'/%3E%3Cpath d='M31.5,20.5 C56.2,5.5 69.6,6.2 88.5,7.0' fill='none' stroke='%23000' stroke-width='1.60' stroke-linecap='round' stroke-opacity='0.68'/%3E%3Cpath d='M43.5,5.2 C65.7,11.6 79.1,12.5 82.8,19.6' fill='none' stroke='%23000' stroke-width='1.90' stroke-linecap='round' stroke-opacity='0.80'/%3E%3Cpath d='M42.1,4.9 C69.1,6.6 77.4,15.1 87.0,25.5' fill='none' stroke='%23000' stroke-width='1.90' stroke-linecap='round' stroke-opacity='0.58'/%3E%3Cpath d='M41.1,18.1 C65.9,8.8 84.7,5.5 93.6,4.5' fill='none' stroke='%23000' stroke-width='1.75' stroke-linecap='round' stroke-opacity='0.70'/%3E%3Cpath d='M40.4,24.6 C73.3,5.1 86.5,6.4 97.1,1.5' fill='none' stroke='%23000' stroke-width='1.75' stroke-linecap='round' stroke-opacity='0.48'/%3E%3Cpath d='M42.3,2.4 C76.8,5.7 92.1,15.8 104.1,18.1' fill='none' stroke='%23000' stroke-width='1.60' stroke-linecap='round' stroke-opacity='1.00'/%3E%3Cpath d='M48.7,2.3 C75.4,5.5 93.4,12.8 98.8,19.1' fill='none' stroke='%23000' stroke-width='1.60' stroke-linecap='round' stroke-opacity='0.78'/%3E%3Cpath d='M63.6,18.6 C83.7,10.0 92.8,2.9 101.8,1.0' fill='none' stroke='%23000' stroke-width='1.90' stroke-linecap='round' stroke-opacity='0.90'/%3E%3Cpath d='M56.7,20.8 C79.0,12.8 94.6,7.8 104.0,0.6' fill='none' stroke='%23000' stroke-width='1.90' stroke-linecap='round' stroke-opacity='0.68'/%3E%3Cpath d='M59.0,3.5 C85.1,11.7 100.0,17.1 113.7,21.6' fill='none' stroke='%23000' stroke-width='1.75' stroke-linecap='round' stroke-opacity='0.80'/%3E%3Cpath d='M59.1,6.4 C90.7,8.9 100.7,16.2 109.0,18.9' fill='none' stroke='%23000' stroke-width='1.75' stroke-linecap='round' stroke-opacity='0.58'/%3E%3Cpath d='M57.4,17.3 C84.7,7.4 106.4,1.6 119.6,3.8' fill='none' stroke='%23000' stroke-width='1.60' stroke-linecap='round' stroke-opacity='0.70'/%3E%3Cpath d='M61.3,16.5 C87.6,8.6 105.3,9.3 114.8,9.2' fill='none' stroke='%23000' stroke-width='1.60' stroke-linecap='round' stroke-opacity='0.48'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 24' preserveAspectRatio='none'%3E%3Cpath d='M5.7,7.3 C23.9,13.2 36.8,11.7 46.8,22.3' fill='none' stroke='%23000' stroke-width='1.90' stroke-linecap='round' stroke-opacity='1.00'/%3E%3Cpath d='M6.8,-0.3 C27.2,12.5 40.9,13.8 43.2,24.6' fill='none' stroke='%23000' stroke-width='1.90' stroke-linecap='round' stroke-opacity='0.78'/%3E%3Cpath d='M11.1,17.9 C33.9,8.7 44.3,7.6 62.2,4.5' fill='none' stroke='%23000' stroke-width='1.75' stroke-linecap='round' stroke-opacity='0.90'/%3E%3Cpath d='M3.7,24.5 C34.5,6.0 50.6,8.6 55.6,6.8' fill='none' stroke='%23000' stroke-width='1.75' stroke-linecap='round' stroke-opacity='0.68'/%3E%3Cpath d='M13.7,4.4 C40.8,6.7 57.7,11.2 73.6,18.4' fill='none' stroke='%23000' stroke-width='1.60' stroke-linecap='round' stroke-opacity='0.80'/%3E%3Cpath d='M16.8,6.6 C47.0,6.4 63.1,9.3 72.2,17.3' fill='none' stroke='%23000' stroke-width='1.60' stroke-linecap='round' stroke-opacity='0.58'/%3E%3Cpath d='M20.8,22.2 C41.6,12.3 55.1,7.4 67.6,7.3' fill='none' stroke='%23000' stroke-width='1.90' stroke-linecap='round' stroke-opacity='0.70'/%3E%3Cpath d='M18.1,24.3 C40.5,10.8 58.5,0.4 63.1,5.2' fill='none' stroke='%23000' stroke-width='1.90' stroke-linecap='round' stroke-opacity='0.48'/%3E%3Cpath d='M25.8,2.4 C54.6,11.7 67.7,11.9 78.4,19.0' fill='none' stroke='%23000' stroke-width='1.75' stroke-linecap='round' stroke-opacity='1.00'/%3E%3Cpath d='M24.9,1.5 C53.3,5.1 71.5,13.4 80.9,16.1' fill='none' stroke='%23000' stroke-width='1.75' stroke-linecap='round' stroke-opacity='0.78'/%3E%3Cpath d='M29.9,17.5 C58.9,10.1 71.7,7.1 87.0,2.8' fill='none' stroke='%23000' stroke-width='1.60' stroke-linecap='round' stroke-opacity='0.90'/%3E%3Cpath d='M31.5,20.5 C56.2,5.5 69.6,6.2 88.5,7.0' fill='none' stroke='%23000' stroke-width='1.60' stroke-linecap='round' stroke-opacity='0.68'/%3E%3Cpath d='M43.5,5.2 C65.7,11.6 79.1,12.5 82.8,19.6' fill='none' stroke='%23000' stroke-width='1.90' stroke-linecap='round' stroke-opacity='0.80'/%3E%3Cpath d='M42.1,4.9 C69.1,6.6 77.4,15.1 87.0,25.5' fill='none' stroke='%23000' stroke-width='1.90' stroke-linecap='round' stroke-opacity='0.58'/%3E%3Cpath d='M41.1,18.1 C65.9,8.8 84.7,5.5 93.6,4.5' fill='none' stroke='%23000' stroke-width='1.75' stroke-linecap='round' stroke-opacity='0.70'/%3E%3Cpath d='M40.4,24.6 C73.3,5.1 86.5,6.4 97.1,1.5' fill='none' stroke='%23000' stroke-width='1.75' stroke-linecap='round' stroke-opacity='0.48'/%3E%3Cpath d='M42.3,2.4 C76.8,5.7 92.1,15.8 104.1,18.1' fill='none' stroke='%23000' stroke-width='1.60' stroke-linecap='round' stroke-opacity='1.00'/%3E%3Cpath d='M48.7,2.3 C75.4,5.5 93.4,12.8 98.8,19.1' fill='none' stroke='%23000' stroke-width='1.60' stroke-linecap='round' stroke-opacity='0.78'/%3E%3Cpath d='M63.6,18.6 C83.7,10.0 92.8,2.9 101.8,1.0' fill='none' stroke='%23000' stroke-width='1.90' stroke-linecap='round' stroke-opacity='0.90'/%3E%3Cpath d='M56.7,20.8 C79.0,12.8 94.6,7.8 104.0,0.6' fill='none' stroke='%23000' stroke-width='1.90' stroke-linecap='round' stroke-opacity='0.68'/%3E%3Cpath d='M59.0,3.5 C85.1,11.7 100.0,17.1 113.7,21.6' fill='none' stroke='%23000' stroke-width='1.75' stroke-linecap='round' stroke-opacity='0.80'/%3E%3Cpath d='M59.1,6.4 C90.7,8.9 100.7,16.2 109.0,18.9' fill='none' stroke='%23000' stroke-width='1.75' stroke-linecap='round' stroke-opacity='0.58'/%3E%3Cpath d='M57.4,17.3 C84.7,7.4 106.4,1.6 119.6,3.8' fill='none' stroke='%23000' stroke-width='1.60' stroke-linecap='round' stroke-opacity='0.70'/%3E%3Cpath d='M61.3,16.5 C87.6,8.6 105.3,9.3 114.8,9.2' fill='none' stroke='%23000' stroke-width='1.60' stroke-linecap='round' stroke-opacity='0.48'/%3E%3C/svg%3E");
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
}
.redact-s { width: 3.1rem; }
.redact-m { width: 4.2rem; }
.redact-l { width: 5.4rem; }

/* Кнопка «ещё» стоит внутри стены, между её частями, поэтому стена читается как одна.
   `<details>` вместо кнопки на скрипте: раскрытие нативное, работает без JS, открывается с
   клавиатуры и находится поиском по странице. Кнопка нарочно тихая — рамка и моноширинные
   прописные, как у входа в шапке. Чёрная `.cta` на этой странице значит «записаться», и второй
   такой же кнопкой мы бы отняли у неё вес. */
.more { margin-top: .3rem; }
.more summary {
  display: inline-flex;
  align-items: center;
  padding: .5rem .9rem;
  border: 1px solid var(--line);
  border-radius: 1rem;
  background: var(--paper-bright);
  color: var(--ink);
  font-family: var(--mono);
  font-size: .66rem;
  font-weight: 500;
  letter-spacing: .07em;
  text-transform: uppercase;
  list-style: none;
  cursor: pointer;
  transition: border-color .2s ease;
}
.more summary::-webkit-details-marker { display: none; }
.more summary:hover { border-color: var(--ink); }
.more summary:focus-visible { outline: 2px solid var(--violet); outline-offset: 3px; }
.more[open] summary { margin-bottom: 1.1rem; }
.more-close { display: none; }
.more[open] .more-open { display: none; }
.more[open] .more-close { display: inline; }

/* Подрастает только там, где есть настоящий курсор. На тачскрине :hover прилипает после касания,
   и карточка осталась бы увеличенной без причины. `focus-within` держит то же для клавиатуры. */
@media (hover: hover) and (pointer: fine) {
  .msg:hover,
  .msg:focus-within {
    z-index: 2;
    transform: scale(1.05);
    box-shadow: 0 12px 28px rgba(23, 23, 22, .16);
  }
}

.last .wrap { position: relative; padding: 1.5rem 1.7rem; border-radius: .5rem 1.7rem 1.7rem .5rem; background: var(--paper-muted); }
.last .wrap::before { position: absolute; left: 0; top: 1rem; bottom: 1rem; width: .35rem; background: var(--red); content: ""; }
.last h2 { margin-bottom: .5rem; }
.last p { color: var(--muted); }

.foot { padding: 1.4rem var(--gutter) 1.6rem; border-top: 1px solid var(--line); background: var(--paper); }
.foot-inner { display: flex; justify-content: space-between; gap: 1.5rem; width: min(100%, var(--content-width)); margin-inline: auto; color: var(--muted); font-family: var(--mono); font-size: .62rem; text-transform: uppercase; }
.foot-channel,
.foot-channel:hover,
.foot-channel:focus-visible { color: inherit; text-decoration: none; }
.foot-channel:focus-visible { outline: 2px solid var(--red); outline-offset: 3px; }

/* Smaller display type on short screens keeps the booking action above the first-visit
   cookie notice, with breathing room still reserved at both dividing rules. */
@media (max-height: 900px) {
  .hero-stage { min-height: 0; padding-block: 2rem 2.5rem; }
  .hero-title { font-size: clamp(3rem, 4.6vw, 4.1rem); }
  .brain-scene { min-height: 21rem; }
}

@media (max-width: 800px) {
  body { padding: 0; background: var(--paper); }
  .paper-shell { width: 100%; border-radius: 0; box-shadow: none; }
  .paper-shell::after { display: none; }
  .bar-inner { grid-template-columns: auto 1fr; }
  .edition { display: none; }
  .nav { gap: .85rem; }
  .nav a,
  .nav-login { font-size: .6rem; letter-spacing: .05em; }

  .hero-stage { display: block; min-height: auto; padding-block: 2rem 2.5rem; }
  .hero-copy { max-width: 30rem; padding-block: 1.75rem 0; }
  .hero-title { max-width: none; font-size: clamp(3rem, 12vw, 4.5rem); }
  .brain-scene { width: auto; min-height: 24rem; margin: 2rem -1rem 0; }
  .brain-caption { right: 1rem; }

  .library-head { display: block; }
  .section-label { display: block; margin-bottom: 1.4rem; }
  .library-head h2 { margin-bottom: 1.1rem; }
  .library-head > p:last-child { max-width: 25rem; }
  .library-grid { grid-template-columns: 1fr; grid-template-rows: auto; }
  .story-card-wide,
  .story-card:nth-child(2),
  .story-card-accent { grid-column: 1; grid-row: auto; min-height: 12rem; transform: none; }
  .story-card-wide { min-height: 18rem; }

  .two,
  .profile .wrap,
  #zapis .wrap { grid-template-columns: 1fr; }
  #kak .wrap { display: block; }
  #kak .wrap > .hit { margin-block: 2rem 0; }

  .steps { grid-template-columns: 1fr 1fr; gap: 2rem 0; }
  .steps li { min-height: 13rem; }
  .steps li:nth-child(3) { border-left: 0; padding-left: 0; }

  #zapis .booking-intro,
  #zapis .booking-action { grid-column: 1; }
  .form { grid-column: 1; grid-row: auto; transform: none; }
  .profile h2,
  .profile .creds-wrap,
  .profile-text { grid-column: 1; grid-row: auto; }

  /* Мелкий шрифт коллажа держался на том, что курсор может увеличить карточку. Здесь курсора
     нет, поэтому текст возвращается к обычному размеру, а колонок становится меньше. */
  .collage { columns: 2; }
  .collage .msg p:not(.msg-from) { font-size: .82rem; }
}

@media (max-width: 520px) {
  .nav a:not(:first-child) { display: none; }
  section { padding-block: 3.2rem; }
  .hero-title { font-size: clamp(2.65rem, 13.5vw, 3.5rem); }
  .brain-scene { min-height: 19rem; }
  .two { gap: 2.4rem; }

  .steps { grid-template-columns: 1fr; gap: 1.7rem; }
  .steps li,
  .steps li:nth-child(3) { min-height: auto; padding: 1rem 0 0; border-left: 0; }
  .n { margin-bottom: 1rem; }

  .form { display: flex; flex-direction: column; padding: 1.25rem; }
  .faq { grid-template-columns: 1fr; gap: 1.5rem; }
  .collage { columns: 1; }
  .foot-inner { flex-direction: column; }
}

/* Short phones need the smaller heading too; the width rules above must not push the
   booking button behind the cookie notice. */
@media (max-width: 520px) and (max-height: 700px) {
  .hero-title { font-size: clamp(2.5rem, 12.5vw, 3rem); }
  .hero-text { margin-top: 1.25rem; }
  .hero-action { margin-top: 1.25rem; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { scroll-behavior: auto !important; animation: none !important; transition: none !important; }
}

/* --- Правовые страницы -------------------------------------------------------------------
   `privacy.html` жила инлайновыми стилями, без шапки, подвала и общей ширины — это числилось
   дефектом в §6 документа о заморозке. Здесь она получает то же обрамление, что и остальной
   сайт, а не собственный вид.

   Единственное, что отличается от статьи, — мера строки. Библиотеке владелец задал полную
   ширину (Поправка 3), но юридический текст читают не подряд, а выборочно: ищут пункт, читают
   абзац, возвращаются. Для такого чтения короткая строка выигрывает, поэтому колонка здесь
   уже, а нумерация пунктов вынесена в сам текст, чтобы на них можно было ссылаться. */
.legal { padding: clamp(2.2rem, 5vw, 3.6rem) var(--gutter) clamp(3rem, 7vw, 5rem); }
.legal .wrap { max-width: 44rem; }
.legal-edition {
  margin: 0 0 .5rem;
  font-family: var(--mono);
  font-size: .62rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted);
}
.legal h1 { margin: 0 0 1.1rem; }
.legal-lead {
  margin: 0 0 2.4rem;
  padding-bottom: 1.6rem;
  border-bottom: 1px solid var(--line);
  color: var(--muted);
}
/* `max-width: 18ch` reset here -- the shared `h2` rule sizes it for the landing's hero-scale
   headings (`clamp(2.1rem, 4.8vw, 4rem)`), where 18ch is a deliberate line break. At this
   heading's own 1.05rem it computed to ~151px, which is not a shorter line but a wrapped-up
   title: "8. Хранение" broke from "и удаление", "9. Права" from "Пользователя". Pre-existing --
   invisible until the section titles got long enough to hit it -- and a correctness fix (§5),
   not a restyle: nothing about the visual language changes, a mis-inherited width does. */
.legal h2 {
  max-width: none;
  margin: 2.4rem 0 .8rem;
  font-size: 1.05rem;
  letter-spacing: 0;
}
.legal p { margin: 0 0 .8rem; }
.legal ul { margin: 0 0 1.1rem; padding-left: 1.15rem; }
.legal li { margin-bottom: .45rem; }
/* Названия свойств cookie — английские термины внутри русского текста. Моноширинный набор
   помечает их как термины, а не как выделение голосом. */
.legal-term { font-family: var(--mono); font-size: .86em; }
.legal-back { margin-top: 2.6rem; padding-top: 1.4rem; border-top: 1px solid var(--line); }

/* --- Вход в кабинет ----------------------------------------------------------------------
   Новая поверхность (§5 документа о заморозке): её не существовало, поэтому она собрана из
   уже принятых величин — та же бумага, та же асимметричная скруглённая карточка, что у формы
   записи, та же тень, тот же моноширинный шрифт для служебных подписей. Ничего нового в
   палитру не вводится.

   Разметка — <dialog>: браузер сам держит фокус внутри, сам возвращает его на кнопку при
   закрытии и сам закрывает по Escape. */
.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}

/* The one action in the masthead, set as the fourth label rather than as a widget.
   §3.5 of PORTAL_VISUAL_LANGUAGE.md fixes navigation as mono, uppercase, letter-spaced; a
   button that inherits the page's sans breaks that rule, which is what shipped first and what
   the owner saw. The red hairline is §3.4's punctuation — the same gesture the library's
   subsection strip uses to say "this is the live one" — so the site has one such mark, not two.
   No border box and no radius: the bar carries neither. */
.nav-login {
  display: inline-block;
  padding: 0;
  border: 0;
  background: transparent;
  /* The line is red; the letters are not. That is the library's gesture exactly, and it also
     keeps this label off the wrong side of a defect §6 already records: red on paper measures
     ~3.9:1 at this size, below the 4.5:1 small uppercase text needs. Colouring the letters here
     would add a second instance of an unfixed contrast problem on a session's own judgement. */
  color: var(--ink);
  font-family: var(--mono);
  font-size: .66rem;
  font-weight: 500;
  letter-spacing: .07em;
  text-transform: uppercase;
  line-height: inherit;
  cursor: pointer;
  visibility: hidden;
  transition: transform .2s ease;
}
.nav-login[data-session-ready="true"] { visibility: visible; }
.nav-login:hover,
.nav-login:focus-visible {
  text-decoration: underline;
  text-decoration-color: var(--mark);
  text-decoration-thickness: 2px;
  text-underline-offset: var(--mark-gap);
  transform: scale(1.035);
}

.login { border: 0; padding: 0; background: transparent; }
/* Плотнее, чем было. При 55% сквозь подложку просвечивала иллюстрация страницы, и тёмные
   пятна за углами карточки владелец прочитал как тень от самой карточки — то есть как дефект.
   Подложка должна убирать страницу, а не показывать её приглушённо. */
.login::backdrop { background: rgba(24, 24, 22, .78); }

.login-card {
  display: flex;
  flex-direction: column;
  gap: .9rem;
  width: min(92vw, 25rem);
  padding: 1.6rem;
  border-radius: var(--radius);
  background: var(--paper-bright);
  box-shadow: 0 12px 34px rgba(32, 32, 32, .28);
}
.login-head { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; }
.login-head h2 { margin: 0; font-size: 1.35rem; }
.login-x {
  border: 0; background: transparent; color: var(--muted);
  font-size: 1.4rem; line-height: 1; cursor: pointer; padding: .1rem .3rem;
}
.login-x:hover, .login-x:focus-visible { color: var(--ink); }

.login-sub { margin: 0 0 .8rem; color: var(--muted); font-size: .82rem; }
.login-field { display: block; }
.login-field input {
  width: 100%; min-height: 2.7rem; padding: .65rem .75rem;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--paper); color: var(--ink); font: inherit; font-size: .86rem;
}
.login-field input:focus-visible { border-color: var(--ink); outline: none; }
/* Шесть цифр читаются как шесть цифр, а не как слово: моноширинный шрифт, разрядка и центр.
   Так на образце владельца, и так же легче свериться с письмом, не теряя место. */
.login-field input[name="code"],
.signin-field input[name="code"] {
  font-family: var(--mono);
  font-size: 1.05rem;
  letter-spacing: .5em;
  text-indent: .5em;
  text-align: center;
}
/* Согласие — строкой под кнопкой, а не галочкой над ней: так на образце владельца, и так же
   в строке записи на главной, чтобы два входа выглядели одинаково.
   `auth.js` требовал отмеченной галочки только если она есть на странице, поэтому код не
   менялся. Юридическая сторона от этого не улучшилась: подтверждение согласия по-прежнему
   нигде не сохраняется — см. `consent_record` в списке долгов BUILD_STATUS. */
.login-terms {
  margin: .7rem 0 0;
  color: var(--muted);
  font-size: .72rem;
  line-height: 1.45;
  text-align: center;
}
.login-terms a { color: var(--muted); }
/* В строке записи текст идёт по левому краю, как и всё вокруг; по центру он выровнен только в
   окне, где кнопка занимает всю ширину и центр есть у чего держаться. */
.signin .login-terms { text-align: left; }

/* Кнопка во всю ширину карточки, как на образце, который прислал владелец. Раньше шаг формы
   не был контейнером-колонкой, поэтому подпись про согласие (строчный `label`) и кнопка
   (строчно-блочная по умолчанию) вставали в одну строку: текст обтекал кнопку, а сама она
   съезжала от центра. Ширина в 100% и колонка на шаге лечат обе половины этого. */
/* Кабинет больше не живёт в dialog: после кода браузер идёт на `/cabinet`. Поэтому шаги
   входа не должны резервировать высоту будущей встречи; скрытый шаг исключается из layout. */
.login-steps > [data-step] { display: flex; flex-direction: column; }
.login-card [data-step][hidden],
.login-steps > [data-step][hidden] { display: none; }
.login-go {
  width: 100%;
  min-height: 2.8rem; padding: .6rem 1rem;
  border: 1px solid var(--ink); border-radius: var(--radius);
  background: var(--ink); color: var(--paper-bright);
  font: inherit; font-size: .88rem; cursor: pointer;
}
.login-go:disabled { opacity: .55; cursor: default; }
.login-go:hover:not(:disabled),
.login-go:focus-visible { background: var(--canvas); }

.login-status {
  margin: 0; min-height: 1.1rem;
  font-family: var(--mono); font-size: .66rem; color: var(--muted);
}

/* Строка записи: почта и кнопка в одну линию. Заменила многошаговую форму 29.08.2026 по
   решению владельца — «надо убирать либо её сразу заменить на строчку email плюс политика и
   кнопка». Разметка та же, что у окна входа, и обслуживается тем же кодом: одно поведение в
   двух местах, а не две реализации. */
.signin { display: flex; flex-direction: column; gap: .55rem; max-width: 34rem; }
.signin-row { display: flex; gap: .55rem; align-items: stretch; flex-wrap: wrap; }
.signin-field { flex: 1 1 14rem; display: block; }
.signin-field input {
  width: 100%; min-height: 2.8rem; padding: .65rem .75rem;
  border: 1px solid var(--line); border-radius: .4rem;
  background: var(--paper-bright); color: var(--ink); font: inherit; font-size: .88rem;
}
.signin-field input:focus-visible { border-color: var(--ink); outline: none; }
.signin-go {
  flex: 0 0 auto; min-height: 2.8rem; padding: .6rem 1.15rem;
  border: 1px solid var(--ink); border-radius: var(--radius);
  background: var(--ink); color: var(--paper-bright);
  font: inherit; font-size: .88rem; cursor: pointer;
}
.signin-go:disabled { opacity: .55; cursor: default; }
.signin-go:hover:not(:disabled),
.signin-go:focus-visible { background: var(--canvas); }
.signin-consent { margin-top: .2rem; }

/* The booking section is already a two-column composition; its one decision must not become a
   second horizontal grid inside the action column. Field, action and consent read vertically. */
.booking-action .signin-row { flex-direction: column; }
.booking-action .signin-field { flex-basis: auto; }
.booking-action .signin-row .signin-go { width: 100%; }

/* Подсказка под полем кода. Взята с образца (smyslokod) и оставлена дословно по смыслу: «письмо
   идёт до минуты, посмотрите в спаме» — это две самые частые причины, по которым человек решает,
   что вход сломан, и уходит. */
.login-hint { margin: .7rem 0 0; color: var(--muted); font-size: .72rem; line-height: 1.45; }
.login-go, .signin-go { margin-top: .9rem; }
.signin-row .signin-go { margin-top: 0; }

/* Кабинет: выбор времени и состоявшаяся запись.
   -----------------------------------------------------------------------------------------
   Новая поверхность, собранная по §2–§3, а не по образцам. Из разобранных в Refero экранов
   записи (Fresha, TidyCal, Calendly, Acuity, Doctronic) взята структура: одна узкая колонка,
   один день на экране со стрелками, сетка времён в три колонки, одна кнопка во всю ширину.
   Взято именно это, потому что на четыре встречи в день сетка месяца была бы почти пустой —
   то есть обещала бы изобилие, которого нет. Цвета, шрифты и скругление наши; синего акцента,
   сиреневых кружков и «пилюль» из образцов здесь нет. */
.cab { display: flex; flex-direction: column; gap: .8rem; margin-top: .9rem; }
.cab[hidden], .cab-booked[hidden], .cab-diagnostic[hidden] { display: none; }
/* ADR-085: «откуда вы узнали» — вопрос рядом с выбором времени. Новая поверхность, собранная из
   уже существующих устройств (§5 PORTAL_VISUAL_LANGUAGE): подпись — та же, что у поля профиля,
   строка ввода — та же `.login-field input`. В язык не вводится ничего нового. */
.cab-source { margin: .9rem 0 1rem; }
.cab-source > span {
  display: block;
  margin-bottom: .35rem;
  font-family: var(--mono);
  font-size: .66rem;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--muted);
}
.cab-source[hidden] { display: none; }

.cab-day {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .6rem;
  padding: .45rem .2rem;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
.cab-day-label {
  font-family: var(--mono);
  font-size: .68rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink);
}
.cab-arrow {
  border: 0; background: transparent; color: var(--ink);
  font-size: 1.1rem; line-height: 1; padding: .1rem .5rem; cursor: pointer;
}
.cab-arrow:hover, .cab-arrow:focus-visible { color: var(--red); }

.cab-times { display: grid; grid-template-columns: repeat(3, 1fr); gap: .4rem; }
.cab-time {
  min-height: 2.3rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--paper);
  color: var(--ink);
  font-family: var(--mono);
  font-size: .78rem;
  letter-spacing: .04em;
  cursor: pointer;
}
.cab-time:hover, .cab-time:focus-visible { border-color: var(--ink); }
/* Выбранное окно залито чернилами, как главная кнопка. Красным заливать нельзя: §3.4 держит
   акцент знаком препинания, а не поверхностью. */
.cab-time[aria-pressed="true"] {
  background: var(--ink); border-color: var(--ink); color: var(--paper-bright);
}

.cab-note {
  margin: 0;
  font-family: var(--mono);
  font-size: .64rem;
  letter-spacing: .05em;
  color: var(--muted);
}

.cab-profile { margin: 0 0 1rem; }
.cab-profile-form {
  display: flex;
  flex-direction: column;
  gap: .55rem;
  max-width: 24rem;
  margin-top: .7rem;
}
.cab-profile-form[hidden] { display: none; }
.cab-profile-form .login-field > span {
  display: block;
  margin-bottom: .35rem;
  font-family: var(--mono);
  font-size: .66rem;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--muted);
}
.cab-profile-form input {
  width: 100%;
  min-height: 2.8rem;
  padding: .65rem .75rem;
  border: 1px solid var(--line);
  border-radius: .4rem;
  background: var(--paper-bright);
  color: var(--ink);
  font: inherit;
  font-size: .88rem;
}
.cab-profile-form .login-go { margin-top: .1rem; }

.cab-cta-copy {
  max-width: 31rem;
  margin: 0 0 .9rem;
  color: var(--ink);
  font-size: .92rem;
  line-height: 1.45;
}
.cab-cta-detail {
  margin: .7rem 0 0;
  color: var(--muted);
  font-size: .72rem;
  line-height: 1.45;
}

.cab-booked { display: flex; flex-direction: column; gap: .7rem; margin-top: .9rem; }
.cab-when { font-family: var(--serif); font-size: 1.25rem; line-height: 1.15; color: var(--ink); }
.cab-link { font-size: .82rem; color: var(--ink); word-break: break-all; }

/* Карточка каналов. Подключение телеграма живёт здесь, а не отдельным предложением после
   записи: так оно достраивает то, что человек только что настроил, вместо того чтобы
   навязываться следом за действием. Приём из разбора Doctronic, оформление наше. */
.cab-channels {
  padding: .85rem 1rem;
  border-radius: var(--radius);
  background: var(--paper-muted);
}
.cab-channels-head {
  font-family: var(--mono);
  font-size: .62rem;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--muted);
  padding-bottom: .5rem;
}
.cab-channel {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: .8rem;
  font-size: .82rem;
  color: var(--ink);
  padding: .2rem 0;
}
.cab-channel-status { display: inline-flex; align-items: center; gap: .42rem; }
.cab-channel-status::before {
  content: ''; width: .48rem; height: .48rem; flex: 0 0 .48rem; border-radius: 50%;
  background: var(--red); box-shadow: 0 0 0 2px var(--paper-muted);
}
.cab-channel-status.is-connected::before { background: #4b8b62; }
.cab-channel-note { margin: .4rem 0 0; color: var(--muted); font-size: .8rem; line-height: 1.45; }
.cab-diagnostic { margin-top: 1.4rem; padding-top: 1.35rem; border-top: 1px solid var(--line); }
.cab-diagnostic [data-el="diagnostic-copy"] { white-space: pre-line; line-height: 1.5; }
.cab-diagnostic .login-field { display: grid; gap: .45rem; margin: 0; }
.cab-diagnostic textarea { box-sizing: border-box; display: block; width: 100%; min-height: 8rem; padding: .85rem; border: 1px solid var(--line); border-radius: .5rem; background: var(--paper); color: var(--ink); font: inherit; line-height: 1.45; resize: vertical; }
.cab-diagnostic textarea:focus { outline: 2px solid color-mix(in srgb, var(--red) 55%, transparent); outline-offset: 2px; }
.cab-progress { margin: 1rem 0 .75rem; }
.cab-progress > span { display: block; margin-bottom: .45rem; font-family: var(--mono); font-size: .68rem; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.cab-progress > b { display: block; height: 4px; overflow: hidden; background: var(--paper-muted); }
.cab-progress i { display: block; height: 100%; background: var(--red); transition: width .2s ease; }
.cab-question-title { margin: 1rem 0 .35rem; color: var(--muted); font-family: var(--mono); font-size: .66rem; letter-spacing: .08em; text-transform: uppercase; }
.cab-question { margin: 0 0 1rem; font-family: var(--serif); font-size: 1.35rem; line-height: 1.18; }
.cab-answers { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .6rem; }
.cab-answer { min-height: 3.7rem; padding: .7rem .85rem; border: 1px solid var(--line); border-radius: .5rem; background: var(--paper); color: var(--ink); text-align: left; font: inherit; cursor: pointer; }
.cab-answer:hover, .cab-answer:focus-visible { border-color: var(--red); background: #fff8f5; }
.cab-diagnostic-actions { display: flex; align-items: center; gap: .8rem; margin-top: .9rem; }
@media (max-width: 520px) { .cab-answers { grid-template-columns: 1fr; } .cab-question { font-size: 1.2rem; } }
.cab-connect {
  display: block; box-sizing: border-box; margin-top: .85rem;
  background: var(--paper-bright); color: var(--ink); text-align: center; text-decoration: none;
}
.cab-connect[hidden] { display: none; }
.cab-connect.login-go:hover:not(:disabled), .cab-connect.login-go:focus-visible {
  background: var(--paper); color: var(--ink);
}
.cab-reschedule { margin-top: .35rem; }

.cab-out {
  border: 0; background: transparent; padding: 0;
  color: var(--muted); font: inherit; font-size: .72rem; cursor: pointer;
  text-decoration: underline; text-decoration-color: var(--mark);
  text-decoration-thickness: 2px; text-underline-offset: var(--mark-gap);
}
.cab-out:hover, .cab-out:focus-visible { text-decoration-color: var(--red); }

/* `/cabinet` extends the frozen paper sheet rather than starting a dashboard language. */
.cabinet-page { padding-top: 3.8rem; padding-bottom: 5rem; max-width: var(--content-width); }
.cabinet-page-head { max-width: 42rem; margin: 0 auto 1.4rem; }
.cabinet-page-head h1 { margin: .35rem 0 .7rem; }
.cabinet-page-head > p:last-child { color: var(--muted); }
.cabinet-card { max-width: 42rem; margin-inline: auto; padding: 1.3rem; background: var(--paper-bright); border-radius: var(--radius);
  box-shadow: 0 12px 34px rgba(111, 104, 72, .20); }
.cab-booked-title { margin: 0; font-family: var(--mono); font-size: .7rem; letter-spacing: .08em;
  text-transform: uppercase; color: var(--muted); }
.cabinet-login { max-width: 42rem; margin-inline: auto; color: var(--muted); }
.cab-reading { margin-top: 2.6rem; }
@media (max-width: 520px) { .cabinet-page { padding-top: 2.4rem; } }

@media (max-width: 420px) {
  .cab-times { grid-template-columns: repeat(2, 1fr); }
}
