/* «Очаг» — стили компонентов поверх tokens.css (слой components). В приложении подключается после
   tokens.css; разметка и правила — в docs/design/components.md, здесь только внешний вид.
   Цвет раздела приходит через --hue (корешок, точка, метка), цвета людей — через --me / --you.
   Цели касания: кнопки и чипы расширяют область нажатия невидимым ::after до 44 px.
   Наведение — только в @media (hover: hover): на iPhone :hover залипает после касания, и кнопка
   остаётся залитой, будто нажата. */

@layer components {
  /* ======== Оболочка: тулбар сверху на компьютере, снизу на телефоне ======== */
  .page { max-inline-size: var(--page); margin-inline: auto;
    padding: var(--sp-5) var(--gutter) calc(var(--sp-7) + var(--bar-h) + var(--safe-b)); }
  .page-core { max-inline-size: calc(var(--page) - 2 * var(--gutter)); margin-inline: auto; }
  @media (min-width: 1000px) { .page--wide { max-inline-size: 1200px; } }
  .topbar { position: sticky; top: 0; z-index: var(--z-bar); background: var(--paper); border-block-end: 1px solid var(--line); }
  /* Тестовый экземпляр ветки (ADR 0014): полоса над шапкой, чтобы не спутать с настоящим «Очагом» */
  .test-strip { margin: 0; padding: var(--sp-1) var(--gutter); background: var(--note); color: var(--ink);
    font-size: var(--fs-meta); line-height: var(--lh-meta); font-weight: 600; text-align: center; overflow-wrap: anywhere; }
  /* Шапка во всю ширину: логотип, строка разделов и правая группа («+ Записать», значки, имя)
     в один ряд; между «Очаг» и строкой — не меньше 32 px (зазор 16 + отступ логотипа 16) */
  .topbar-in { padding: 0 var(--gutter); min-height: var(--bar-h);
    display: flex; align-items: center; gap: var(--sp-4); }
  .logo { font-weight: 800; font-size: 21px; letter-spacing: -0.03em; text-decoration: none; flex: none; margin-inline-end: var(--sp-4); }
  @media (hover: hover) { .logo:hover { color: var(--ink); } }
  .nav { display: flex; gap: 2px; min-width: 0; overflow-x: auto; scrollbar-width: none; }
  /* От 1100 px шапка зеркалит колонку страницы: строка начинается там, где текст страницы, —
     «Сегодня» стоит на одной вертикали с заголовком под ним (6 px — поле ссылки, выравнивается текст) */
  @media (min-width: 1100px) {
    .topbar-in { display: grid; padding: 0;
      grid-template-columns: minmax(max-content, 1fr) minmax(0, var(--page)) minmax(0, 1fr); }
    .logo { margin-inline: var(--gutter) 0; grid-column: 1; grid-row: 1; }
    .nav { grid-column: 2; grid-row: 1; }
    .nav { margin-inline-start: calc(var(--gutter) - 6px); justify-self: start; max-inline-size: 100%; }
    /* правая группа шире боковой колонки — она растянута на вторую и третью и прижата к краю окна */
    .topbar-end { grid-column: 2 / 4; grid-row: 1; margin: 0; justify-self: end; padding-inline-end: var(--gutter); }
  }
  .nav a, .nav button { text-decoration: none; padding: 8px 6px; border-radius: 8px; font-size: 15px; font-weight: 500; color: var(--ink-2); white-space: nowrap; }
  @media (hover: hover) { .nav a:hover, .nav button:hover { color: var(--ink); background: var(--hover); } }
  .nav a[aria-current="page"], .nav button[aria-current] { color: var(--ink); background: none; box-shadow: inset 0 -2px 0 var(--ink); border-radius: 0; }
  /* «Ещё ▾» — кнопка того же вида, что ссылки строки; список — `.more-sheet` под ней */
  .nav button { font-family: inherit; background: none; border: 0; cursor: pointer; display: inline-flex; align-items: center; gap: 2px; }
  .nav-more { anchor-name: --nav-more; }
  .nav button .ic { width: 16px; height: 16px; }
  .topbar-end { margin-inline-start: auto; display: flex; align-items: center; gap: var(--sp-3); flex: none; }

  .tabbar { position: fixed; inset: auto 0 0 0; z-index: var(--z-bar); display: none;
    background: var(--paper); border-block-start: 1px solid var(--line); padding-block-end: var(--safe-b); }
  .tabbar-in { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); min-height: var(--bar-h); }
  .tabbar a, .tabbar button { display: grid; justify-items: center; align-content: center; gap: 3px; text-decoration: none;
    font: inherit; font-size: 11.5px; font-weight: 600; color: var(--ink-2); padding: 6px 2px 5px; white-space: nowrap;
    background: none; border: 0; cursor: pointer; -webkit-tap-highlight-color: transparent; }
  .tabbar .ic { width: 24px; height: 24px; }
  .tabbar a[aria-current="page"], .tabbar button.on { color: var(--accent); }
  /* «Ещё»: разделы, не вошедшие в пять вкладок, — меню поднимается справа над своей кнопкой */
  .more-sheet { inset: auto var(--sp-2) calc(var(--bar-h) + var(--safe-b) + var(--sp-2)) auto; margin: 0;
    width: 15rem; max-inline-size: calc(100% - 2 * var(--sp-2)); height: auto; overflow: visible;
    border: 1px solid var(--line-strong); border-radius: var(--r-sheet); padding: 0 var(--sp-1);
    background: var(--paper); color: var(--ink); box-shadow: var(--shadow-lift); }
  .more-sheet::backdrop { background: transparent; }
  .more-sheet a { display: flex; align-items: center; gap: var(--sp-3); min-height: 48px; padding-inline: var(--sp-3);
    text-decoration: none; color: var(--ink); font-weight: 600; white-space: nowrap; }
  .more-sheet a + a { border-block-start: 1px solid var(--line); }
  .more-sheet a .ic { width: 22px; height: 22px; color: var(--ink-2); }
  .more-sheet a[aria-current="page"], .more-sheet a[aria-current="page"] .ic { color: var(--accent); }
  .more-sheet:popover-open { transform-origin: bottom right;
    transition: opacity var(--t-slow) var(--ease), transform var(--t-slow) var(--ease); }
  @starting-style { .more-sheet:popover-open { opacity: 0; transform: translateY(8px) scale(0.98); } }
  @media (max-width: 699px) {
    .tabbar { display: block; }
    .topbar .nav { display: none; }
  }
  @media (min-width: 700px) {
    .page { padding-block-end: var(--sp-8); }
    /* Компьютер: тот же список раскрывается под «Ещё ▾» в шапке; разделы строки и значки шапки
       из него скрыты, а без поддержки якорной привязки он встаёт под шапкой у правого края */
    .more-sheet { inset: calc(var(--bar-h) + var(--sp-1)) var(--gutter) auto auto; }
    @supports (anchor-name: --nav-more) {
      .more-sheet { position-anchor: --nav-more; inset: auto; top: calc(anchor(bottom) + var(--sp-1)); left: anchor(left);
        position-try-fallbacks: flip-inline; }
    }
    .more-sheet:popover-open { transform-origin: top left; }
    @starting-style { .more-sheet:popover-open { transform: translateY(-8px) scale(0.98); } }
    .more-sheet .in-line, .more-sheet .phone-only { display: none; }
    .more-sheet a + a { border-block-start: 0; }
    .more-sheet a:not(.in-line, .phone-only) ~ a:not(.in-line, .phone-only) { border-block-start: 1px solid var(--line); }
  }

  /* ======== «Записать» (спека 027): плавающая «+» на телефоне, «+ Записать» в шапке ======== */
  /* Залитая терракотовая «+» на экране одна — плавающая; в шапке «+ Записать» контурная, как
     тихие «+» у строк разделов (.btn-icon.outline), — рядом с «+ Событие» и формами страниц */
  .btn.capture-open { flex: none; color: var(--accent); box-shadow: inset 0 0 0 1.5px var(--line-strong); padding-inline: 10px 14px; }
  @media (hover: hover) { .btn.capture-open:hover { color: var(--accent); background: var(--accent-soft); } }
  .fab { display: none; place-items: center;
    width: 56px; height: 56px; padding: 0; border: 0; border-radius: 50%; cursor: pointer;
    background: var(--accent); color: var(--on-accent); box-shadow: var(--shadow-lift);
    -webkit-tap-highlight-color: transparent; transition: background-color var(--t-fast); }
  .fab .ic { width: 26px; height: 26px; stroke-width: 2; }
  .fab:active { background: color-mix(in oklab, var(--accent) 76%, var(--ink)); }
  @media (max-width: 699px) {
    .topbar .capture-open { display: none; }
    /* Над нижней панелью справа, при прокрутке не прячется; тень — та же, что у тоста */
    .fab { position: fixed; z-index: var(--z-bar); inset-inline-end: var(--gutter);
      inset-block-end: calc(var(--bar-h) + var(--safe-b) + var(--sp-3)); display: grid; }
    /* Последняя строка списка прокручивается из-под кнопки; тост укорачивается справа */
    body:has(> .fab) .page { padding-block-end: calc(var(--sp-7) + var(--bar-h) + var(--safe-b) + 56px + var(--sp-3)); }
    body:has(> .fab) .toast { inset-inline-end: calc(var(--gutter) + 56px + var(--sp-3)); }
  }
  @media (hover: hover) { .fab:hover { background: color-mix(in oklab, var(--accent) 86%, var(--ink)); } }

  /* Панель «Записать» — popover у верхнего края: над клавиатурой iPhone поле остаётся видно.
     Страница под ней затемнена, как под диалогом: иначе край панели режет строку раздела и
     выглядит сломанной вёрсткой */
  .capture { inset: calc(env(safe-area-inset-top, 0px) + var(--sp-2)) 0 auto; margin: 0 auto;
    width: min(36rem, calc(100% - 2 * var(--sp-2))); height: auto; overflow: visible;
    border: 1px solid var(--line-strong); border-radius: var(--r-sheet); padding: var(--sp-3);
    background: var(--paper); color: var(--ink); box-shadow: var(--shadow-lift); }
  .capture::backdrop { background: var(--scrim); }
  .capture:popover-open { transition: opacity var(--t-slow) var(--ease), transform var(--t-slow) var(--ease); }
  @starting-style { .capture:popover-open { opacity: 0; transform: translateY(-8px); } }
  @media (min-width: 700px) { .capture { inset-block-start: calc(var(--bar-h) + var(--sp-2)); } }
  /* «Записать» рядом с полем — текстовая основная кнопка панели (залитая «+» на экране всё равно одна) */
  .capture .capture-send { flex: none; padding-inline: var(--sp-4); }
  .capture .quick-hint { min-height: 1lh; margin-block: 6px 0; padding-inline: 18px; }
  .capture .quick-hint.invalid-hint { color: var(--danger); font-weight: 500; }
  .capture-where { margin-block-start: var(--sp-1); }
  .capture-where > summary { list-style: none; justify-content: flex-start; width: fit-content; -webkit-tap-highlight-color: transparent; }
  .capture-where > summary::-webkit-details-marker { display: none; }
  .capture-where > summary b { font-weight: 700; color: var(--ink); }
  .capture-where > summary .ic { width: 16px; height: 16px; transition: transform var(--t-base) var(--ease); }
  .capture-where[open] > summary .ic { transform: rotate(180deg); }
  /* «Куда ▾»: семь мест чипами-переключателями; выбор несёт акцент, а не оттенок раздела */
  .capture-places { padding: var(--sp-2) var(--sp-1) var(--sp-1); }
  .capture-places .chip { min-height: var(--tap); padding-inline: 14px; font-size: var(--fs-small); }

  /* ======== Иконки (Lucide, инлайн-SVG из спрайта) ======== */
  .ic { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; flex: none; }
  .ic.inline { vertical-align: -0.22em; }

  /* ======== Текстовые роли ======== */
  .display { font-size: var(--fs-display); line-height: 1.12; font-weight: 800; letter-spacing: var(--ls-tight); }
  .title { font-size: var(--fs-title); line-height: 1.2; font-weight: 800; letter-spacing: -0.02em; }
  .h-card { font-size: var(--fs-card); line-height: 1.25; font-weight: 700; letter-spacing: -0.015em; }
  .h-block { font-size: var(--fs-block); line-height: 1.3; font-weight: 700; letter-spacing: -0.01em; }
  .h-group { font-size: var(--fs-group); line-height: 1.4; font-weight: 600; color: var(--ink-2); }
  .meta { font-size: var(--fs-meta); line-height: var(--lh-meta); font-weight: 500; color: var(--ink-2); }
  .quiet { color: var(--ink-2); }
  .stamp { font-size: var(--fs-stamp); line-height: 1; font-weight: 700; letter-spacing: var(--ls-stamp);
    text-transform: uppercase; color: var(--ink-2); font-variant-numeric: tabular-nums; white-space: nowrap; }

  /* ======== Точки людей, точка раздела, выбор цвета ======== */
  .dot { display: inline-block; width: var(--dot); height: var(--dot); border-radius: 50%; background: var(--c, var(--ink-3)); flex: none; }
  .dot.me { --c: var(--me); }
  .dot.you { --c: var(--you); }
  .dots { display: inline-flex; align-items: center; gap: 3px; vertical-align: middle; }
  .sdot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: var(--hue, var(--ink-3)); flex: none; }
  .swatches { display: flex; flex-wrap: wrap; gap: var(--sp-3); }
  .swatch.person-1 { --c: var(--person-1); }
  .swatch.person-2 { --c: var(--person-2); }
  .swatch.person-3 { --c: var(--person-3); }
  .swatch.person-4 { --c: var(--person-4); }
  .swatch.person-5 { --c: var(--person-5); }
  .swatch.person-6 { --c: var(--person-6); }
  .swatch > input { position: absolute; inset: -6px; width: auto; height: auto; margin: 0; opacity: 0; cursor: pointer; }
  .swatch:has(input:checked) { box-shadow: 0 0 0 3px var(--paper), 0 0 0 5px var(--c); }
  .swatch:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 7px; }
  .swatch { width: 32px; height: 32px; border-radius: 50%; background: var(--c); position: relative;
    box-shadow: 0 0 0 3px var(--paper), 0 0 0 4px transparent; transition: box-shadow var(--t-base) var(--ease); }
  .swatch::after { content: ""; position: absolute; inset: -6px; }
  @media (hover: hover) { .swatch:hover { box-shadow: 0 0 0 3px var(--paper), 0 0 0 5px var(--line-strong); } }
  .swatch[aria-checked="true"] { box-shadow: 0 0 0 3px var(--paper), 0 0 0 5px var(--c); }

  /* ======== «Карандашная» галочка ======== */
  .check-line { display: flex; align-items: center; gap: var(--sp-2); min-height: var(--tap); }
  .check-line input { inline-size: 20px; block-size: 20px; margin: 0; accent-color: var(--accent); }
  .check { position: relative; display: inline-grid; place-items: center; width: var(--tap); height: var(--tap); flex: none; cursor: pointer; }
  .check input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
  .check-mark { width: var(--check); height: var(--check); border-radius: 50%; display: grid; place-items: center;
    box-shadow: inset 0 0 0 1.5px var(--ink-3); transition: box-shadow var(--t-base) var(--ease); }
  .check-mark svg { width: 16px; height: 16px; fill: none; stroke: var(--accent); stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round;
    stroke-dasharray: 18; stroke-dashoffset: 18; transition: stroke-dashoffset var(--t-slow) var(--ease); }
  @media (hover: hover) { .check:hover .check-mark { box-shadow: inset 0 0 0 1.5px var(--ink-2); } }
  .check input:checked + .check-mark { box-shadow: inset 0 0 0 1.5px var(--accent); }
  .check input:checked + .check-mark svg { stroke-dashoffset: 0; }
  .check input:focus-visible + .check-mark { outline: 2px solid var(--accent); outline-offset: 3px; }
  .check input:disabled + .check-mark { opacity: 0.45; }
  .check.small { width: 32px; height: 32px; }
  .check.small .check-mark { width: 20px; height: 20px; }

  /* ======== Строка карточки ======== */
  .list { list-style: none; margin: 0; padding: 0; }
  .row { position: relative; display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; column-gap: var(--sp-2);
    min-height: var(--tap); padding: 5px var(--sp-1) 5px calc(var(--spine) + 3px); border-block-end: 1px solid var(--line);
    transition: background-color var(--t-fast); }
  .row::before { content: ""; position: absolute; inset-block: 7px; inset-inline-start: 0; width: var(--spine); border-radius: 2px; background: var(--hue, transparent); }
  .list.plain .row::before, .row.plain::before { display: none; }
  .list.plain .row { padding-inline-start: var(--sp-1); }
  .row.nolead { grid-template-columns: minmax(0, 1fr) auto; padding-inline-start: calc(var(--spine) + var(--sp-3)); }
  @media (hover: hover) { .row:hover { background: var(--hover); } }
  .row-lead { padding-inline: var(--sp-2) 0; color: var(--ink-2); font-weight: 600; font-variant-numeric: tabular-nums; }
  .row-main { min-width: 0; padding-block: 3px; }
  .row-title { display: inline; font-weight: 600; color: var(--ink); text-decoration: none;
    background: linear-gradient(var(--ink-2), var(--ink-2)) no-repeat 0 56% / 0 1.5px;
    -webkit-box-decoration-break: clone; box-decoration-break: clone;
    transition: background-size var(--t-slow) var(--ease), color var(--t-slow); }
  @media (hover: hover) { a.row-title:hover { color: var(--accent); } }
  .row-meta { font-size: var(--fs-meta); line-height: var(--lh-meta); font-weight: 500; color: var(--ink-2); margin-top: 1px;
    display: flex; flex-wrap: wrap; align-items: center; gap: 2px var(--sp-2); }
  /* Разделитель «·» принадлежит следующему элементу: при переносе уходит вместе с ним, а не висит в конце строки */
  .row-meta > * + *::before, .slip .meta > * + *::before { content: "·"; margin-inline-end: var(--sp-2); color: var(--ink-3); }
  .row-end { display: inline-flex; align-items: center; gap: var(--sp-2); padding-inline-end: var(--sp-2); }
  .row:has(> .check input:checked) .row-title, .row.done .row-title { background-size: 100% 1.5px; color: var(--ink-2); }
  .row:has(> .check input:checked)::before, .row.done::before { opacity: 0.45; }
  .shop .row { min-height: var(--row-shop); }

  /* Группы списка покупок и «Куплено» */
  .group { margin-block-start: var(--sp-4); }
  .group-h { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-3);
    padding: 0 var(--sp-2) var(--sp-1) calc(var(--spine) + 3px); border-block-end: 1px solid var(--line); }
  .bought { margin-block-start: var(--sp-5); }
  .bought > summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: var(--sp-2);
    min-height: var(--tap); padding: var(--sp-2) var(--sp-2) var(--sp-2) calc(var(--spine) + 3px); font-size: var(--fs-group); font-weight: 600; color: var(--ink-2); }
  .bought > summary::-webkit-details-marker { display: none; }
  .bought > summary .ic { width: 16px; height: 16px; transition: transform var(--t-base) var(--ease); }
  .bought[open] > summary .ic { transform: rotate(180deg); }

  /* ======== Листок ======== */
  .slip { display: block; min-width: 0; background: var(--paper-2); border-radius: var(--r-slip); padding: var(--sp-3) var(--sp-4);
    color: inherit; text-decoration: none; transition: background-color var(--t-fast), box-shadow var(--t-base); }
  @media (hover: hover) { a.slip:hover, .slip.hoverable:hover { background: var(--control); } }
  .slip.lifted { box-shadow: var(--shadow-lift); }
  .slip-title { display: flex; align-items: baseline; gap: var(--sp-2); font-weight: 600; }
  .slip-title .sdot { align-self: center; }
  .slip .meta { margin-top: 2px; display: flex; flex-wrap: wrap; align-items: center; gap: 2px var(--sp-2); }
  .shelf { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: var(--sp-2); }
  .shelf-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-2); }
  .count-slip { display: grid; gap: 2px; padding: var(--sp-3); }
  .count-slip .k { display: flex; align-items: center; gap: 6px; font-size: var(--fs-meta); font-weight: 600; color: var(--ink-2); min-width: 0; }
  .count-slip .k span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .count-slip .v { font-size: 24px; font-weight: 800; letter-spacing: -0.02em; line-height: 1.1; font-variant-numeric: tabular-nums; }
  .count-slip .v small { font-size: var(--fs-meta); font-weight: 500; letter-spacing: 0; color: var(--ink-2); margin-inline-start: 4px; }

  /* Доска (R2): колонки «вырезаны» в бумаге, листки на них — бумага */
  .board { display: flex; gap: var(--sp-3); overflow-x: auto; padding-block-end: var(--sp-2); scroll-snap-type: x proximity; scrollbar-width: thin; }
  .board-col { flex: 0 0 min(78vw, 272px); scroll-snap-align: start; background: var(--control); border-radius: var(--r-sheet);
    padding: var(--sp-3); display: grid; gap: var(--sp-2); align-content: start; }
  .board-col > .h-group { display: flex; justify-content: space-between; padding: 2px var(--sp-1) 4px; }
  .board .slip { background: var(--paper); }

  /* ======== Открытая карточка — лист ======== */
  .sheet { max-inline-size: var(--col); }
  /* Крошка остаётся мелкой строкой; невидимая зона расширяет цель касания. */
  .crumb::after { content: ""; position: absolute; inset: -12px -8px; }
  .crumb { position: relative; display: inline-flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-meta); font-weight: 600; color: var(--hue, var(--ink-2)); text-decoration: none; }
  /* «‹» перед точкой раздела: крошка — единственная дорога назад в приложении на экране «Домой»,
     без стрелки она не читается как «назад» (PD-093). Цвет — чернила 2, как у мелкой меты */
  .crumb::before { content: "‹"; flex: none; color: var(--ink-2); font-size: 1.6em; font-weight: 500;
    line-height: 1; margin-inline-end: calc(-1 * var(--sp-1)); transform: translateY(-0.04em); }
  .sheet-title { margin-block-start: var(--sp-2); }
  .props { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-1) var(--sp-3); margin-block-start: var(--sp-2);
    font-size: var(--fs-meta); font-weight: 500; color: var(--ink-2); }
  .pill { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
  .pill .ic { width: 15px; height: 15px; }
  .pill b { font-weight: 600; color: var(--ink); }
  .sheet-body { margin-block-start: var(--sp-5); padding-block-start: var(--sp-5); border-block-start: 1px solid var(--line); }
  .sheet-section { margin-block-start: var(--sp-6); }
  .sheet-section > .h-group { padding-block-end: var(--sp-2); border-block-end: 1px solid var(--line); display: flex; justify-content: space-between; align-items: baseline; }

  /* Проза Markdown */
  .prose { font-size: var(--fs-body); line-height: var(--lh-prose); max-inline-size: var(--col); }
  .prose > :first-child { margin-block-start: 0; }
  .prose p, .prose ul, .prose ol, .prose blockquote, .prose table { margin: 0 0 1em; }
  .prose h2 { font-size: 1.1em; margin: 1.6em 0 0.5em; }
  .prose h3 { font-size: 1em; margin: 1.4em 0 0.4em; }
  .prose ul, .prose ol { padding-inline-start: 1.3em; }
  .prose li + li { margin-block-start: 0.3em; }
  .prose a { text-decoration-color: var(--line-strong); }
  .prose a.wiki { text-decoration-style: dotted; text-decoration-color: var(--ink-3); }
  .prose blockquote { padding-inline-start: 1em; border-inline-start: 3px solid var(--line-strong); color: var(--ink-2); }
  .prose code { font: 0.9em ui-monospace, SFMono-Regular, Menlo, monospace; background: var(--control); padding: 0.1em 0.35em; border-radius: 4px; }
  .prose img { display: block; border-radius: var(--r-slip); }
  .prose del { color: var(--ink-2); }
  .prose table { border-collapse: collapse; width: 100%; font-size: 0.95em; font-variant-numeric: tabular-nums; }
  .prose th, .prose td { text-align: start; padding: 0.4em 0.8em 0.4em 0; border-block-end: 1px solid var(--line); vertical-align: top; }
  .prose th { font-size: 0.85em; font-weight: 600; color: var(--ink-2); }
  /* Чеклист: вся строка — цель касания, круг 20 px */
  .prose ul.tasks { list-style: none; padding-inline-start: 0; }
  .prose .task { display: flex; align-items: flex-start; gap: var(--sp-2); min-height: 28px; cursor: pointer; }
  .prose .task .check { width: 28px; height: 28px; margin-inline-start: -4px; }
  .prose .task .check-mark { width: 20px; height: 20px; }
  .prose .task:has(input:checked) > span { color: var(--ink-2); text-decoration: line-through; text-decoration-thickness: 1.5px; }

  /* Связи, комментарии, история */
  .links .row { min-height: 40px; }
  .comment { display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: var(--sp-2); row-gap: 2px; padding: var(--sp-3) 0; border-block-end: 1px solid var(--line); }
  .comment .dot { margin-block-start: 7px; }
  .comment-h { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--sp-2); font-size: var(--fs-meta); font-weight: 600; color: var(--ink-2); }
  .comment-h .stamp { font-weight: 600; }
  .comment-b { grid-column: 2; font-size: var(--fs-small); line-height: 1.5; }
  .history ul { list-style: none; margin: 0; padding: 0; }
  .history li { display: grid; grid-template-columns: auto auto minmax(0, 1fr); gap: var(--sp-2); align-items: center; padding: 5px 0; font-size: var(--fs-meta); color: var(--ink-2); }
  .history li .stamp { font-weight: 600; }
  details.fold > summary { list-style: none; cursor: pointer; display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); min-height: var(--tap); }
  details.fold > summary::-webkit-details-marker { display: none; }
  details.fold > summary .ic { width: 16px; height: 16px; transition: transform var(--t-base) var(--ease); }
  details.fold[open] > summary .ic { transform: rotate(180deg); }

  /* ======== Кнопки ======== */
  .btn { position: relative; display: inline-flex; align-items: center; justify-content: center; gap: 6px; min-height: 36px; padding: 6px 14px;
    border-radius: var(--r-pill); font-size: var(--fs-small); font-weight: 600; color: var(--ink-2); background: none; border: 0; cursor: pointer;
    text-decoration: none; white-space: nowrap; transition: color var(--t-fast), background-color var(--t-fast); }
  .btn::after { content: ""; position: absolute; inset: -4px 0; }       /* цель касания до 44 px */
  @media (hover: hover) { .btn:hover { color: var(--ink); background: var(--hover); } }
  .btn:active { background: var(--control); }
  .btn[aria-pressed="true"] { color: var(--accent); background: var(--accent-soft); }
  .btn:disabled, .btn[aria-disabled="true"] { color: var(--ink-3); background: none; cursor: default; }
  .btn-accent { color: var(--accent); }
  @media (hover: hover) { .btn-accent:hover { color: var(--accent); background: var(--accent-soft); } }
  .btn-danger { color: var(--danger); }
  @media (hover: hover) { .btn-danger:hover { color: var(--danger); background: var(--hover); } }
  .btn-primary { min-height: var(--tap); padding: 8px 20px; font-size: var(--fs-body); background: var(--accent); color: var(--on-accent); }
  @media (hover: hover) { .btn-primary:hover { background: color-mix(in oklab, var(--accent) 86%, var(--ink)); color: var(--on-accent); } }
  .btn-primary:active { background: color-mix(in oklab, var(--accent) 76%, var(--ink)); }
  .btn-primary:disabled { background: var(--control); color: var(--ink-3); }
  .btn-icon { width: var(--tap); height: var(--tap); min-height: 0; padding: 0; border-radius: 50%; }
  .btn-icon.fill { background: var(--accent); color: var(--on-accent); }
  @media (hover: hover) { .btn-icon.fill:hover { background: color-mix(in oklab, var(--accent) 86%, var(--ink)); color: var(--on-accent); } }
  /* Кнопка отправки у строки раздела — тихая, контурная: залитая «+» на экране одна (спека 027) */
  .btn-icon.outline { color: var(--accent); box-shadow: inset 0 0 0 1.5px var(--line-strong); }
  @media (hover: hover) { .btn-icon.outline:hover { background: var(--accent-soft); } }
  .btn .ic { width: 18px; height: 18px; }
  .actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }
  .actions.end { justify-content: flex-end; }
  /* Строка-предложение (PD-110): заметное, но не главное действие и одна фраза о том, что оно
     сделает; без рамки и заливки. Стоит над списком, а не среди тихих кнопок внизу. */
  .offer { display: flex; flex-wrap: wrap; align-items: center; gap: 0 var(--sp-3); margin-block: var(--sp-3); }
  .offer > .btn { flex: none; margin-inline-start: -14px; }   /* текст кнопки — по краю колонки */
  .offer > .meta { flex: 1 1 15rem; margin: 0; padding-inline-start: 0; }

  /* «♥ Спасибо» и сердца фильма */
  .thanks[aria-pressed="true"] { color: var(--accent); background: none; }
  .thanks[aria-pressed="true"] .ic { fill: currentColor; }
  .hearts .ic.person-1 { --c: var(--person-1); }
  .hearts .ic.person-2 { --c: var(--person-2); }
  .hearts .ic.person-3 { --c: var(--person-3); }
  .hearts .ic.person-4 { --c: var(--person-4); }
  .hearts .ic.person-5 { --c: var(--person-5); }
  .hearts .ic.person-6 { --c: var(--person-6); }
  .hearts { display: inline-flex; gap: 3px; align-items: center; }
  .hearts .ic { width: 18px; height: 18px; color: var(--ink-3); }
  .hearts .ic.me { color: var(--c, var(--me)); fill: currentColor; }
  .hearts .ic.you { color: var(--c, var(--you)); fill: currentColor; }

  /* ======== Чипы и пилюли ======== */
  .chip:has(input:checked) { background: var(--accent-soft); color: var(--accent); }
  .chip:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
  .chip > input:is([type="radio"], [type="checkbox"]):not(.sr-only) { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
  .chip .num { font-variant-numeric: tabular-nums; font-weight: 600; margin-inline-start: 2px; }
  .chips { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
  /* Переходы между страницами — линия ссылок; чипы ниже остаются условиями/значениями. */
  .section-nav { display: flex; flex-wrap: wrap; align-items: center; gap: 0 var(--sp-4); }
  .section-link { display: inline-flex; align-items: center; gap: var(--sp-1);
    min-block-size: var(--tap); color: var(--ink-2); font-size: var(--fs-meta);
    font-weight: 500; text-decoration: none; border-block-end: 2px solid transparent; }
  .section-link[aria-current="page"] { color: var(--ink); border-block-end-color: var(--ink); }
  .section-link .num { font-variant-numeric: tabular-nums; font-weight: 600; }
  .section-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
  @media (hover: hover) { .section-link:hover { color: var(--accent); } }
  .chip { position: relative; display: inline-flex; align-items: center; gap: 4px; min-height: 30px; padding: 2px 11px; border-radius: var(--r-pill);
    background: var(--control); color: var(--ink-2); font-size: var(--fs-meta); font-weight: 500; text-decoration: none; border: 0; cursor: pointer;
    transition: background-color var(--t-fast), color var(--t-fast); }
  .chip::after { content: ""; position: absolute; inset: -7px 0; }
  @media (hover: hover) { .chip:hover { color: var(--ink); } }
  .chip[aria-pressed="true"], .chip.on { background: var(--accent-soft); color: var(--accent); }
  .chip .x { display: inline-grid; place-items: center; width: 18px; height: 18px; margin-inline-end: -5px; border-radius: 50%; }
  .chip .x .ic { width: 12px; height: 12px; }

  /* ======== Формы ======== */
  .field { display: grid; gap: 6px; }
  .field > .label { font-size: var(--fs-meta); font-weight: 600; color: var(--ink-2); }
  .input, .textarea, .select { width: 100%; min-height: var(--tap); padding: 10px 14px; border: 0; border-radius: var(--r-field);
    background: var(--control); color: var(--ink); font-size: max(16px, 1em); line-height: 1.4; transition: background-color var(--t-fast), box-shadow var(--t-fast); }
  .input:focus-visible, .textarea:focus-visible, .select:focus-visible { outline: 2px solid var(--accent); outline-offset: 0; background: var(--paper); }
  .textarea { min-height: 7lh; line-height: 1.55; resize: vertical; }
  /* Safari на iPhone даёт полю даты свою ширину и центрирует значение — поле вылезает за край */
  .input[type="date"] { display: block; min-inline-size: 0; appearance: none; -webkit-appearance: none; }
  .input::-webkit-date-and-time-value { text-align: start; }
  /* Пустая дата (blankdate.js): без серой сегодняшней даты, пока поле не в фокусе */
  .input[data-empty]:not(:focus) { color: transparent; -webkit-text-fill-color: transparent; }
  .input[data-empty]:not(:focus)::-webkit-datetime-edit,
  .input[data-empty]:not(:focus)::-webkit-datetime-edit-day-field,
  .input[data-empty]:not(:focus)::-webkit-datetime-edit-month-field,
  .input[data-empty]:not(:focus)::-webkit-datetime-edit-year-field,
  .input[data-empty]:not(:focus)::-webkit-datetime-edit-text { color: transparent; }
  .select { appearance: none; -webkit-appearance: none; padding-inline-end: 40px;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23706760' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='m6 9 6 6 6-6'/></svg>");
    background-repeat: no-repeat; background-position: right 14px center; }
  .hint { font-size: var(--fs-meta); color: var(--ink-2); }
  .field.invalid .input, .field.invalid .textarea { box-shadow: inset 0 0 0 1.5px var(--danger); }
  .field.invalid .hint { color: var(--danger); font-weight: 500; }
  .form { display: grid; gap: var(--sp-4); max-inline-size: var(--sheet-w); }
  .form .actions { margin-block-start: var(--sp-1); }

  /* Строка быстрого ввода */
  .quick { display: flex; align-items: center; gap: var(--sp-2); }
  .quick .input { flex: 1; min-width: 0; border-radius: var(--r-pill); padding-inline: 18px; }
  .quick-hint { margin-block-start: 6px; }
  /* Живая подсказка разбора («Продукты · кофе · ×2 · суббота 24 окт»): одна строка, длинное — «…» */
  .quick-hint.live { color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

  /* Строка раздела (section_line.html, спека 027): первая под заголовком и чипами, кнопка — тихая
     .btn-icon.outline; «Детальная форма» раскрывается под строкой во всю ширину. «Дом» пока на своих
     .home-add* (home.css) — переведут на макрос позже */
  .section-line { margin-block: var(--sp-3) var(--sp-2); }
  .section-line-form { display: grid; gap: var(--sp-1); }
  .section-line .quick-hint { margin: 0; }
  .section-line .quick-hint:empty { display: none; }  /* ничего не набрано — подписью служит строка */
  .section-line-row { gap: var(--sp-1) var(--sp-2); }
  .section-line-more[open] { flex-basis: 100%; }
  .section-line-more > summary { justify-content: flex-start; width: fit-content; }
  .section-line-more-in { margin-block: var(--sp-2) var(--sp-3); }
  /* «+» ведёт к строке раздела (PD-095, capture.js): строка встаёт у верха экрана под липкой шапкой */
  [data-add-here] { scroll-margin-block-start: calc(var(--bar-h) + var(--sp-4)); }

  /* ======== Пустое состояние ======== */
  .empty { padding: var(--sp-6) var(--sp-4); text-align: center; color: var(--ink-2); display: grid; justify-items: center; gap: var(--sp-3); }
  .empty p { font-size: var(--fs-body); }
  /* Страница ошибки: заголовок крупнее и темнее строки под ним (иначе `.empty p` его выравнивает). */
  .empty .h-card { font-size: var(--fs-card); color: var(--ink); }

  /* ======== Записка — единственный стикер ======== */
  .note { background: var(--note); border-radius: var(--r-slip); padding: var(--sp-4) var(--sp-4) var(--sp-2); max-inline-size: 36rem; }
  .note-h { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-meta); font-weight: 600; color: var(--ink-2); }
  .note p { margin: var(--sp-2) 0 var(--sp-1); line-height: 1.5; }
  .note .actions { justify-content: flex-end; margin-inline-end: calc(-1 * var(--sp-2)); }

  /* ======== Баланс недели: две полосы без цифр ======== */
  .balance-bar svg { display: block; flex: 1 1 auto; min-width: 0; width: 100%; height: 6px; }
  .balance-bar rect.person-1 { fill: var(--person-1); }
  .balance-bar rect.person-2 { fill: var(--person-2); }
  .balance-bar rect.person-3 { fill: var(--person-3); }
  .balance-bar rect.person-4 { fill: var(--person-4); }
  .balance-bar rect.person-5 { fill: var(--person-5); }
  .balance-bar rect.person-6 { fill: var(--person-6); }
  .balance-bar rect.track { fill: var(--line); }
  .today-mark { font-size: var(--fs-meta); font-weight: 600; color: var(--accent); }
  .ai-honest { margin: 0; }
  .ai-thinking { margin: 0; color: var(--ink-2); font-weight: 500; }
  .balance { display: grid; gap: var(--sp-2); }
  .balance-bar { display: flex; gap: 2px; height: 6px; border-radius: 3px; overflow: hidden; }
  .balance-bar i { display: block; flex: var(--a, 1); background: var(--me); border-radius: 3px; }
  .balance-bar i + i { flex: var(--b, 1); background: var(--you); }
  .balance-legend { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4); }
  .balance-legend span { display: inline-flex; align-items: center; gap: 6px; }

  /* ======== Перетаскивание (islands/dnd.js) ======== */
  /* Поднятый листок — копия под пальцем с единственной тенью `--shadow-lift`; на исходном месте
     строка приглушена; цель подсвечена подложкой и рамкой акцента. Цветов и переходов новых нет. */
  [data-drag] { -webkit-touch-callout: none; }
  .dnd-active, .dnd-active * { user-select: none; -webkit-user-select: none; }
  .dnd-active { cursor: grabbing; }
  .dnd-ghost { position: fixed; z-index: var(--z-toast); margin: 0; pointer-events: none; box-sizing: border-box;
    padding: var(--sp-2) var(--sp-3); border-radius: var(--r-slip); background: var(--paper-2); color: var(--ink);
    box-shadow: var(--shadow-lift); max-inline-size: min(80vw, 20rem); font-weight: 600; }
  .dnd-origin { opacity: 0.35; }
  [data-dnd].dnd-on [data-drop] { outline: 1px dashed var(--line-strong); outline-offset: 2px; border-radius: var(--r-slip); }
  [data-dnd].dnd-on [data-drop].drop-over { background: var(--accent-soft); outline: 2px solid var(--accent); outline-offset: 2px; }
  [data-dnd][aria-busy="true"] { opacity: 0.6; }

  /* ======== Тост с «Отменить» ======== */
  .toast { position: fixed; inset-inline: var(--gutter); inset-block-end: calc(var(--bar-h) + var(--safe-b) + var(--sp-3)); z-index: var(--z-toast);
    margin-inline: auto; max-inline-size: 28rem; display: flex; align-items: center; gap: var(--sp-3);
    padding: 8px 8px 8px var(--sp-4); border-radius: var(--r-slip); background: var(--ink); color: var(--paper); box-shadow: var(--shadow-lift); font-weight: 500; }
  .toast span { flex: 1; min-width: 0; }
  .toast .btn { color: inherit; text-decoration: underline; text-underline-offset: 0.15em; }
  @media (hover: hover) { .toast .btn:hover { background: none; color: inherit; text-decoration-thickness: 2px; } }
  .toast.static { position: static; }
  @media (min-width: 700px) { .toast { inset-block-end: var(--sp-5); } }

  /* ======== Шит снизу (телефон) / диалог (компьютер) ======== */
  .dlg { border: 0; padding: 0; background: var(--paper); color: var(--ink); border-radius: var(--r-sheet); box-shadow: var(--shadow-lift);
    width: min(var(--sheet-w), calc(100% - 2 * var(--gutter))); }
  .dlg::backdrop { background: var(--scrim); }
  .dlg-in { padding: var(--sp-4) var(--sp-5) var(--sp-5); }
  .dlg-h { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); margin-block-end: var(--sp-4); }
  .dlg .grab { display: none; width: 36px; height: 4px; border-radius: 2px; background: var(--line-strong); margin: var(--sp-2) auto 0; }
  .dlg .list .row { padding-inline-start: var(--sp-1); }
  .dlg .list .row::before { display: none; }
  .dlg[open] { opacity: 1; transform: none; transition: opacity var(--t-slow) var(--ease), transform var(--t-slow) var(--ease), overlay var(--t-slow) allow-discrete, display var(--t-slow) allow-discrete; }
  @starting-style { .dlg[open] { opacity: 0; transform: translateY(12px); } }
  .dlg.static { position: static; display: block; width: 100%; max-inline-size: var(--sheet-w); margin: 0; }
  @media (max-width: 699px) {
    .dlg:not(.static) { margin: 0; inset: auto 0 0 0; width: 100%; max-inline-size: none; border-radius: var(--r-sheet) var(--r-sheet) 0 0;
      max-block-size: 90dvh; padding-block-end: var(--safe-b); }
    .dlg .grab { display: block; }
  }

  /* ======== Календарь (R2): полоска недели и ячейки месяца ======== */
  .week { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 2px; text-align: center; }
  .day { display: grid; justify-items: center; align-content: start; gap: 4px; min-height: var(--tap); padding: 6px 0 4px; border-radius: 8px; color: inherit; text-decoration: none; }
  @media (hover: hover) { .day:hover { background: var(--hover); } }
  .day .wd { font-size: 11px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-2); }
  .day .n { display: grid; place-items: center; width: 30px; height: 30px; border-radius: 50%; font-weight: 600; font-variant-numeric: tabular-nums; }
  .day.off .n { color: var(--ink-2); }
  .day.today .n { background: var(--accent); color: var(--on-accent); }
  .marks { display: flex; gap: 3px; height: 6px; align-items: center; }
  .marks i { display: block; width: 5px; height: 5px; border-radius: 50%; background: var(--hue, var(--ink-3)); }
  .cal { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); border-block-start: 1px solid var(--line); }
  .cell { min-width: 0; min-height: 76px; padding: 6px 5px; border-block-end: 1px solid var(--line); border-inline-end: 1px solid var(--line); display: grid; align-content: start; gap: 3px; }
  .cell:nth-child(7n) { border-inline-end: 0; }
  .cell .n { font-size: var(--fs-meta); font-weight: 600; font-variant-numeric: tabular-nums; width: 24px; height: 24px; display: grid; place-items: center; border-radius: 50%; }
  .cell.off .n { color: var(--ink-3); }
  .cell.today .n { background: var(--accent); color: var(--on-accent); }
  .cell .ev { display: flex; align-items: center; gap: 4px; min-width: 0; font-size: 12px; font-weight: 500; color: var(--ink-2); }
  .cell .ev span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .cell .ev .sdot { width: 6px; height: 6px; }
  /* На телефоне ячейка месяца слишком узка для слов: остаются число и точки разделов */
  @media (max-width: 699px) {
    .cell { display: block; min-height: 56px; }
    .cell .ev { display: inline-flex; margin: 4px 4px 0 2px; }
    .cell .ev span { display: none; }
  }

  /* ======== Экран «Сегодня» ======== */
  .today-h { display: grid; gap: 4px; }
  .today-h .greet { font-weight: 500; color: var(--ink-2); }
  .block { margin-block-start: var(--sp-6); }
  .block-h { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--sp-2) var(--sp-3); margin-block-end: var(--sp-3); }
  .block-h .h-block { display: inline-flex; align-items: center; gap: var(--sp-2); }
  .block-h > .btn, .block-h > .actions > .btn:last-child { margin-inline-end: -14px; }   /* текст и иконка — по краю колонки */
  .pick { display: grid; gap: var(--sp-2); padding: var(--sp-4) var(--sp-5) var(--sp-4); }
  .pick .actions { margin-block-start: var(--sp-2); }

  /* ======== Фото поверх страницы (islands/lightbox.js, спека 030) ======== */
  /* Во весь экран поверх страницы на ночной бумаге (--photo-scrim, в обеих темах одна, без
     просвета, как галерея телефона). Сверху счётчик и ×, снизу подпись; ‹ › — только с мышью, на
     телефоне — свайп в стороны, вниз — закрыть. Появление — прозрачностью за 160 мс; reduced
     motion обнуляет переходы в базовом слое. */
  html.lb-open { overflow: hidden; }
  .lightbox { position: fixed; inset: 0; width: 100%; height: 100%; max-width: none; max-height: none; margin: 0; padding: 0;
    border: 0; background: transparent; color: var(--photo-ink); overscroll-behavior: contain; }
  .lightbox[open] { display: grid; grid-template-rows: auto minmax(0, 1fr) auto; grid-template-columns: minmax(0, 1fr); opacity: 1;
    transition: opacity var(--t-slow) var(--ease), overlay var(--t-slow) allow-discrete, display var(--t-slow) allow-discrete; }
  @starting-style { .lightbox[open] { opacity: 0; } }
  .lightbox::backdrop { background: var(--photo-scrim); }
  .lightbox .btn { color: var(--photo-ink); }
  @media (hover: hover) { .lightbox .btn:hover { background: color-mix(in oklab, var(--photo-ink) 14%, transparent); color: var(--photo-ink); } }
  .lb-bar { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); min-height: var(--bar-h);
    padding: env(safe-area-inset-top, 0px) var(--gutter) 0; }
  .lb-count { font-size: var(--fs-meta); font-weight: 600; color: color-mix(in oklab, var(--photo-ink) 70%, transparent); font-variant-numeric: tabular-nums; }
  .lb-close { margin-inline: auto -10px; }
  /* Строка сетки — определённой высоты, иначе max-height фото не считается и высокое фото режется */
  .lb-stage { position: relative; display: grid; grid-template: minmax(0, 1fr) / minmax(0, 1fr); place-items: center; min-height: 0;
    padding-inline: var(--gutter); overflow: hidden; touch-action: pinch-zoom; user-select: none; -webkit-user-select: none; }
  .lb-img { display: block; max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain; border-radius: var(--r-sheet);
    transition: transform var(--t-slow) var(--ease), opacity var(--t-slow) var(--ease); -webkit-user-drag: none; }
  .lightbox.lb-dragging .lb-img { transition: none; }
  .lightbox.lb-zoomed .lb-stage { touch-action: auto; }
  .lb-cap { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px var(--sp-3); min-height: var(--tap); margin: 0;
    padding: var(--sp-3) var(--gutter) calc(var(--safe-b) + var(--sp-4)); }
  .lb-cap[hidden] { display: flex; visibility: hidden; }
  .lb-title { font-weight: 600; color: var(--photo-ink); }
  a.lb-title { text-decoration: underline; text-decoration-color: color-mix(in oklab, var(--photo-ink) 45%, transparent); text-underline-offset: 0.18em; }
  @media (hover: hover) { a.lb-title:hover { text-decoration-color: var(--photo-ink); } }
  .lb-meta { font-size: var(--fs-meta); font-weight: 500; color: color-mix(in oklab, var(--photo-ink) 70%, transparent); }
  .lb-prev, .lb-next { position: absolute; inset-block-start: 50%; translate: 0 -50%; display: none;
    background: color-mix(in oklab, var(--photo-ink) 12%, transparent); }
  .lb-prev { inset-inline-start: var(--sp-3); }
  .lb-next { inset-inline-end: var(--sp-3); }
  .lb-prev .ic { rotate: 90deg; }
  .lb-next .ic { rotate: -90deg; }
  .lb-prev:disabled, .lb-next:disabled { visibility: hidden; }
  @media (hover: hover) and (pointer: fine) {
    .lightbox:not(.lb-single) .lb-prev, .lightbox:not(.lb-single) .lb-next { display: inline-flex; }
    .lb-stage { padding-inline: calc(var(--tap) + var(--sp-5)); }
  }

  /* ---- Действия, кадр обложки и лента миниатюр (islands/photo-edit.js, спека 035) ---- */
  /* Кнопки — словами на тёмной плашке у нижнего края фото (островок ставит её по рамке снимка),
     «Убрать» — последней справа, цветом --danger, высветленным к --photo-ink: на ночной бумаге
     тёмно-красный не читается. Узкое фото — плашка шире снимка, не уже 300 px; не влезло — в две
     строки. Лента миниатюр — 56 px, текущее обведено --accent. Кадр: всё, кроме окна, затемнено. */
  .lb-acts { position: absolute; z-index: 1; display: flex; flex-wrap: wrap; align-items: center; gap: 2px var(--sp-1); padding: var(--sp-2);
    border-radius: 0 0 var(--r-sheet) var(--r-sheet); background: color-mix(in oklab, var(--photo-scrim) 72%, transparent); }
  .lb-acts.lb-acts-below { border-radius: var(--r-sheet); }
  .lb-acts[hidden], .lightbox.lb-dragging .lb-acts { display: none; }
  .lb-acts .btn { min-height: var(--tap); padding-inline: var(--sp-2); }
  .lb-acts .lb-del { margin-inline-start: auto; color: color-mix(in oklab, var(--danger) 55%, var(--photo-ink)); }
  /* «обложка» — метка, как на превью листа, а не кнопка; подпись кадра — то же слово-метка */
  .lb-word { margin-inline: var(--sp-2); padding: 2px var(--sp-2); border-radius: var(--r-pill); font-size: var(--fs-meta); font-weight: 600;
    background: color-mix(in oklab, var(--photo-ink) 14%, transparent); color: var(--photo-ink); }
  .lb-crop { position: absolute; overflow: hidden; border-radius: var(--r-sheet); touch-action: none; cursor: grab; }
  .lb-window { position: absolute; border: 2px solid var(--photo-ink); border-radius: var(--r-slip);
    box-shadow: 0 0 0 100vmax color-mix(in oklab, var(--photo-scrim) 70%, transparent); transition: left var(--t-fast), top var(--t-fast); }
  .lb-crop.lb-moving .lb-window { transition: none; }
  .lightbox.lb-editing .lb-prev, .lightbox.lb-editing .lb-next, .lightbox.lb-editing .lb-strip { visibility: hidden; }
  .lb-strip { display: flex; gap: var(--sp-2); overflow-x: auto; scrollbar-width: none; overscroll-behavior-x: contain;
    padding: 0 var(--gutter) calc(var(--safe-b) + var(--sp-3)); }
  .lb-strip[hidden] { display: none; }
  .lightbox:has(.lb-strip:not([hidden])) .lb-cap { padding-block-end: var(--sp-2); }
  .lb-thumb { flex: 0 0 56px; block-size: 56px; padding: 0; border: 2px solid transparent; border-radius: var(--r-slip); overflow: hidden;
    background: color-mix(in oklab, var(--photo-ink) 12%, transparent); cursor: pointer; opacity: 0.65; transition: opacity var(--t-fast); }
  .lb-thumb[aria-current="true"] { border-color: var(--accent); opacity: 1; }
  .lb-thumb:focus-visible { outline: 2px solid var(--photo-ink); outline-offset: 2px; }
  .lb-thumb img { display: block; inline-size: 100%; block-size: 100%; object-fit: cover; }
  /* плашка «Вернуть» — внизу, над подписью и лентой миниатюр: там, где был палец */
  .lightbox .toast { inset-block: auto calc(var(--safe-b) + var(--tap) + 56px + var(--sp-5)); }
  .lightbox .toast .btn { color: inherit; }  /* не --photo-ink: плашка — инверсия темы */
  @media (hover: hover) { .lightbox .toast .btn:hover { background: none; color: inherit; } }

  /* ======== Точка внимания обложки (спека 035, PD-182) ======== */
  /* Сервер пишет на <img> `data-fx`/`data-fy` шагом 5 % (`Attachment.focus_attrs`); style=""
     запрещён CSP, поэтому проценты — отсюда: 21 значение на ось. Без атрибутов — центр. */
  img[data-fx], img[data-fy] { object-position: var(--fx, 50%) var(--fy, 50%); }
  [data-fx="0"] { --fx: 0%; } [data-fx="5"] { --fx: 5%; } [data-fx="10"] { --fx: 10%; } [data-fx="15"] { --fx: 15%; }
  [data-fx="20"] { --fx: 20%; } [data-fx="25"] { --fx: 25%; } [data-fx="30"] { --fx: 30%; } [data-fx="35"] { --fx: 35%; }
  [data-fx="40"] { --fx: 40%; } [data-fx="45"] { --fx: 45%; } [data-fx="50"] { --fx: 50%; } [data-fx="55"] { --fx: 55%; }
  [data-fx="60"] { --fx: 60%; } [data-fx="65"] { --fx: 65%; } [data-fx="70"] { --fx: 70%; } [data-fx="75"] { --fx: 75%; }
  [data-fx="80"] { --fx: 80%; } [data-fx="85"] { --fx: 85%; } [data-fx="90"] { --fx: 90%; } [data-fx="95"] { --fx: 95%; }
  [data-fx="100"] { --fx: 100%; }
  [data-fy="0"] { --fy: 0%; } [data-fy="5"] { --fy: 5%; } [data-fy="10"] { --fy: 10%; } [data-fy="15"] { --fy: 15%; }
  [data-fy="20"] { --fy: 20%; } [data-fy="25"] { --fy: 25%; } [data-fy="30"] { --fy: 30%; } [data-fy="35"] { --fy: 35%; }
  [data-fy="40"] { --fy: 40%; } [data-fy="45"] { --fy: 45%; } [data-fy="50"] { --fy: 50%; } [data-fy="55"] { --fy: 55%; }
  [data-fy="60"] { --fy: 60%; } [data-fy="65"] { --fy: 65%; } [data-fy="70"] { --fy: 70%; } [data-fy="75"] { --fy: 75%; }
  [data-fy="80"] { --fy: 80%; } [data-fy="85"] { --fy: 85%; } [data-fy="90"] { --fy: 90%; } [data-fy="95"] { --fy: 95%; }
  [data-fy="100"] { --fy: 100%; }

  /* ======== Выбор из длинного списка: поле поиска и варианты под ним (islands/combo.js) ======== */
  /* Варианты — листком под полем, без тени; «Уже были» сверху заголовком группы; строка ≥ 44 px. */
  .combo { display: grid; gap: var(--sp-1); }
  /* Лупа справа — поле ищет, а не только показывает выбранное (как стрелка у .select) */
  .combo-q { padding-inline-end: 40px; background-repeat: no-repeat; background-position: right 14px center;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23706760' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='11' cy='11' r='8'/><path d='m21 21-4.3-4.3'/></svg>"); }
  .combo-list { list-style: none; margin: 0; padding: var(--sp-1) 0; max-block-size: min(18rem, 45dvh); overflow-y: auto;
    overscroll-behavior: contain; border-radius: var(--r-field); background: var(--paper-2); }
  .combo-list[hidden] { display: none; }
  .combo-group { padding: var(--sp-2) var(--sp-4) var(--sp-1); font-size: var(--fs-group); font-weight: 600; color: var(--ink-2); }
  .combo-opt { display: flex; align-items: center; min-height: var(--tap); padding: 0 var(--sp-4); cursor: pointer; }
  .combo-opt[aria-selected="true"] { color: var(--accent); font-weight: 600; }
  @media (hover: hover) { .combo-opt:hover { background: var(--control); } }
  .combo-opt.active { background: var(--accent-soft); color: var(--accent); }
  .combo-none { padding: var(--sp-3) var(--sp-4); color: var(--ink-2); }

  /* ======== «Добавить фото» кнопкой (islands/filepick.js) ======== */
  /* Как «Добавить фото» панели листа: терракотовое слово с «+», поле файла спрятано внутри и
     видно фокусом; справа — «Выбрано: 3 фото» тихой метой. */
  .file-pick { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-1) var(--sp-3); }
  .file-pick > .btn { min-height: var(--tap); margin-inline-start: -14px; color: var(--accent); cursor: pointer; }
  @media (hover: hover) { .file-pick > .btn:hover { background: var(--accent-soft); color: var(--accent); } }
  .file-pick > .btn:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
  .file-pick input[type="file"] { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .file-pick-count { font-size: var(--fs-meta); font-weight: 500; color: var(--ink-2); }

  /* ======== «Идея или ошибка»: форма страницы и лист поверх страницы (islands/feedback.js) ======== */
  /* Форма — как у повтора дела: чипы-радиокнопки, поле, «Отправить». Лист на телефоне — у нижнего
     края во всю ширину (большой палец достаёт до всего, «Отправить» на всю ширину внизу), над
     клавиатурой iPhone поднимается на --kb (ставит островок); на компьютере — по центру шириной
     шита. Картинки — плитками 84×112 с «×» в углу (цель касания 44 px), «+ Свой скрин» — такой же
     плиткой с пунктиром: это место, куда кладут. */
  .feedback .lead { color: var(--ink-2); line-height: var(--lh-prose); margin: 0 0 var(--sp-4); }
  .feedback .sent { color: var(--ok); font-weight: 600; margin: 0 0 var(--sp-4); }
  .feedback-form { display: grid; gap: var(--sp-4); }
  .feedback-form .textarea { font-size: max(16px, var(--fs-body)); }
  .feedback-form .actions { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
  .feedback-form .chip { min-height: var(--tap); padding-inline: 16px; }
  .feedback-form .invalid-hint { color: var(--danger); font-weight: 500; }
  a[data-feedback][aria-busy="true"] { opacity: 0.5; cursor: progress; }

  .fb-sheet { position: fixed; inset: auto 0 var(--kb, 0px); width: 100%; max-width: none; margin: 0; padding: 0;
    max-height: calc(100dvh - var(--kb, 0px) - env(safe-area-inset-top, 0px) - var(--sp-2)); overflow-y: auto; overscroll-behavior: contain;
    border: 0; border-block-start: 1px solid var(--line-strong); border-radius: var(--r-sheet) var(--r-sheet) 0 0;
    background: var(--paper); color: var(--ink); box-shadow: var(--shadow-lift); }
  .fb-sheet::backdrop { background: var(--scrim); }
  .fb-sheet[open] { transition: opacity var(--t-slow) var(--ease), transform var(--t-slow) var(--ease); }
  @starting-style { .fb-sheet[open] { opacity: 0; transform: translateY(12px); } }
  @media (min-width: 700px) {
    .fb-sheet { inset: 0; margin: auto; width: min(var(--sheet-w), calc(100% - 2 * var(--gutter))); height: fit-content;
      max-height: calc(100dvh - 2 * var(--sp-6)); border: 1px solid var(--line-strong); border-radius: var(--r-sheet); }
  }
  .fb-sheet-in { padding: var(--sp-2) var(--gutter) calc(var(--safe-b) + var(--sp-4)); }
  .fb-sheet .feedback { max-inline-size: none; }
  .fb-head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); }
  .fb-head .btn { margin-inline-end: -10px; }
  .fb-title { margin: 0; font-size: var(--fs-block); font-weight: 700; letter-spacing: var(--ls-tight); }
  .fb-sheet .lead { font-size: var(--fs-meta); line-height: var(--lh-meta); margin: 0 0 var(--sp-3); }
  .fb-sheet .feedback-form { gap: var(--sp-3); }
  .fb-sheet .textarea { min-height: 4lh; resize: none; }
  .fb-sheet .feedback-form .label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .fb-sheet .actions .btn-primary { flex: 1; min-height: 48px; }
  @media (min-width: 700px) { .fb-sheet .actions { justify-content: flex-end; } .fb-sheet .actions .btn-primary { flex: none; } }
  .fb-shots { display: flex; flex-wrap: wrap; gap: var(--sp-3); }
  .fb-thumb, .fb-add { position: relative; display: grid; width: 84px; height: 112px; margin: 0; border-radius: var(--r-slip); }
  .fb-thumb { display: block; }
  .fb-thumb img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: top; border-radius: inherit;
    box-shadow: inset 0 0 0 1px var(--line); outline: 1px solid var(--line); outline-offset: -1px; }
  .fb-thumb figcaption { position: absolute; inset: auto 0 0; padding: 2px 6px; border-radius: 0 0 var(--r-slip) var(--r-slip);
    background: color-mix(in oklab, var(--paper) 88%, transparent); font-size: var(--fs-stamp); font-weight: 600; color: var(--ink-2); text-align: center; }
  .fb-x { position: absolute; inset: -14px -14px auto auto; display: grid; place-items: center; width: var(--tap); height: var(--tap);
    padding: 0; border: 0; background: none; color: var(--ink); cursor: pointer; -webkit-tap-highlight-color: transparent; }
  .fb-x .ic { width: 26px; height: 26px; padding: 5px; border-radius: 50%; background: var(--paper); box-shadow: inset 0 0 0 1px var(--line-strong); }
  .fb-x:focus-visible { outline: none; }
  .fb-x:focus-visible .ic { outline: 2px solid var(--accent); outline-offset: 1px; }
  .fb-add { place-content: center; justify-items: center; gap: var(--sp-1); padding: var(--sp-1); text-align: center; cursor: pointer;
    border: 1.5px dashed var(--line-strong); color: var(--accent); font-size: var(--fs-meta); font-weight: 600; line-height: 1.2; }
  .fb-add .ic { width: 22px; height: 22px; }
  .fb-add[hidden] { display: none; }
  @media (hover: hover) { .fb-add:hover { background: var(--accent-soft); } }
  .fb-add:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
  .fb-add input { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0; overflow: hidden; clip-path: inset(50%); }
  .fb-sheet [data-feedback-status].invalid-hint { color: var(--danger); font-weight: 500; }
  .fb-sent { display: grid; justify-items: start; gap: var(--sp-3); padding-block: var(--sp-2); }
  .fb-sent[hidden], .fb-sheet .feedback-form[hidden] { display: none; }
  .fb-sent .sent { margin: 0; outline: none; }
  .fb-sent .btn { min-width: 8rem; }

  /* ======== Печать: список покупок на бумаге ======== */
  @media print {
    .topbar, .tabbar, .quick, .toast, .btn, .fab, .capture, .check, .row::before { display: none !important; }
    body { background: #fff; color: #000; font-size: 12pt; }
    .row { break-inside: avoid; border-block-end-color: #ccc; grid-template-columns: minmax(0, 1fr) auto; }
    .row-title { background: none; }
  }

  /* ======== Категории разделов (Покупки — спека 019, Дела — спека 041) ======== */
  /* Заголовок во всю ширину: название (ведёт на страницу категории), число, стрелка, «⋯» */
  .cat-h { align-items: center; gap: var(--sp-1); padding-block-end: 0; padding-inline-end: 0; min-height: var(--tap); }
  .cat-name { flex: 1; min-width: 0; display: flex; align-items: center; gap: 2px; text-decoration: none; }
  .cat-name-t { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .cat-go { flex: none; display: inline-grid; color: var(--ink-3); }   /* «›»: название открывает категорию */
  .cat-go .ic { width: 16px; height: 16px; transform: rotate(-90deg); }
  @media (hover: hover) { a.cat-name:hover, a.cat-name:hover .cat-go { color: var(--accent); } }
  .cat-num { flex: none; min-inline-size: 1.5em; text-align: end; font-size: var(--fs-meta); font-weight: 500;
    color: var(--ink-3); font-variant-numeric: tabular-nums; }
  .cat-h .btn-icon { color: var(--ink-2); flex: none; }
  .cat-fold[hidden] { display: none; }
  /* стрелка как у «Куплено»: раскрыто — вверх, свёрнуто — вниз */
  .cat-fold .ic { width: 18px; height: 18px; transform: rotate(180deg); transition: transform var(--t-base) var(--ease); }
  .cat.folded .cat-fold .ic { transform: none; }
  .cat.folded > .cat-body { display: none; }
  .cat.folded > .cat-h { border-block-end-color: transparent; }

  /* «Новая категория» внизу списка */
  .new-cat { margin-block-start: var(--sp-4); }
  .new-cat > summary.btn { justify-content: flex-start; margin-inline-start: -14px; color: var(--ink-2); }
  .new-cat > summary.btn .ic { width: 18px; height: 18px; transform: none; }
  .new-cat[open] > summary.btn .ic { transform: none; }
  .new-cat-form { padding-block: var(--sp-2) var(--sp-3); max-inline-size: var(--sheet-w); }
  .new-cat-form .quick .btn { flex: none; }

  /* Нижний лист (нативный popover): «В категорию…» и «⋯» у категории */
  .sheet-pop { margin: 0; inset: auto 0 0 0; inline-size: 100%; max-inline-size: none; block-size: auto; max-block-size: 60dvh;
    overflow-y: auto; overscroll-behavior: contain; border: 0; border-radius: var(--r-sheet) var(--r-sheet) 0 0;
    padding: var(--sp-4) var(--gutter) calc(var(--sp-4) + var(--safe-b)); background: var(--paper); color: var(--ink);
    box-shadow: var(--shadow-lift); }
  .sheet-pop::backdrop { background: transparent; }
  .sheet-pop:popover-open { transition: opacity var(--t-slow) var(--ease), transform var(--t-slow) var(--ease); }
  @starting-style { .sheet-pop:popover-open { opacity: 0; transform: translateY(12px); } }
  @media (min-width: 700px) {
    .sheet-pop { inset: 0; margin: auto; inline-size: min(var(--sheet-w), calc(100% - 2 * var(--gutter)));
      max-block-size: 70dvh; border: 1px solid var(--line-strong); border-radius: var(--r-sheet); }
  }
  .pick-h { display: grid; gap: 2px; padding-block-end: var(--sp-2); border-block-end: 1px solid var(--line); }
  .pick-h .meta { overflow-wrap: anywhere; }
  .pick-list { list-style: none; margin: 0; padding: 0; }
  .pick-item form { margin: 0; }
  .pick-btn { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); inline-size: 100%;
    min-height: var(--tap); padding: 0 var(--sp-1); border: 0; border-block-end: 1px solid var(--line); background: none;
    color: var(--ink); font: inherit; font-weight: 600; text-align: start; cursor: pointer; transition: background-color var(--t-fast); }
  @media (hover: hover) { .pick-btn:hover { background: var(--hover); } }
  .pick-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
  .pick-btn[aria-pressed="true"] { color: var(--accent); }
  .pick-mark svg { display: block; inline-size: 20px; block-size: 20px; fill: none; stroke: currentColor; stroke-width: 2;
    stroke-linecap: round; stroke-linejoin: round; }
  .pick-page { max-inline-size: var(--sheet-w); margin-block-start: var(--sp-3); }
  .cat-menu { display: none; }
  .cat-menu:popover-open { display: grid; gap: var(--sp-4); }
  .cat-menu-h { overflow-wrap: anywhere; }
  .cat-form { display: grid; gap: var(--sp-2); margin: 0; }
  .cat-form > .btn { justify-self: start; }
  .cat-form > .btn-accent { margin-inline-start: -14px; }
  .cat-form > .btn .ic { width: 18px; height: 18px; }
  .cat-remove { padding-block-start: var(--sp-3); border-block-start: 1px solid var(--line); }
  /* шапка страницы категории */
  .cat-page-h { margin-block-start: var(--sp-2); }
  .cat-page-h .title { overflow-wrap: anywhere; }

  /* Порядок категорий и убранные в настройках: поле «по одному в строке» без JS, список с
     перетаскиванием с dnd.js (до его загрузки поле скрыто атрибутом `hidden` у формы) */
  .textarea.short { min-height: 4lh; }
  .order-sort[hidden], [data-sort-fallback][hidden] { display: none; }
  .order-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; }
  /* ручка · название · выше · ниже: цели касания 44 px, строка на 390 px не шире экрана */
  .order-item { display: grid; grid-template-columns: var(--tap) minmax(0, 1fr) var(--tap) var(--tap); align-items: center;
    min-height: var(--tap); border-block-end: 1px solid var(--line); cursor: grab; }
  .order-grip { display: grid; place-items: center; color: var(--ink-3); transform: rotate(90deg); }
  .order-name { min-width: 0; overflow-wrap: anywhere; }
  .order-item .up .ic { transform: rotate(180deg); }
  .order-item.dnd-origin { background: var(--accent-soft); opacity: 1; }
  .order-item.dnd-ghost { padding: 0; border-block-end: 0; }
  .cat-retired { display: grid; gap: var(--sp-1); padding-block: var(--sp-2) var(--sp-3); max-inline-size: var(--sheet-w); }
  .cat-retired form { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2);
    min-height: var(--tap); border-block-end: 1px solid var(--line); }
  .cat-retired .label { font-size: var(--fs-meta); font-weight: 600; color: var(--ink-2); }

}
