/* ============================================================
   STUDIO CHROME — хаб, полки, двери, подвал студийных страниц
   (gbppl-hub-13, Тон 2026-08-25; серый холст и дерево
   страниц gbppl-panel-9 2026-08-27; полка контролов, список и
   бейджи песочниц gbppl-sandboxes-4 2026-08-28, блок в конце
   файла)
   ------------------------------------------------------------
   ЗАГОЛОВКИ ХАБА НАЗВАНЫ РОЛЯМИ КАРТЫ (hub-13, Тон 25.08,
   дословно): «Мне нравится, как ты переделал Хаб, выглядит
   великолепно. Единственное, я бы сделал заголовки карточек Live
   Prototype / Sandboxes / Design System нашим системным H3-
   заголовком, а Design Studio пусть будет нашим системным H1-
   заголовком.»

   Сверка с TYPE-SCALE.md, роль за ролью:

     H1 = «Hero H1» (`Hedings/BP: XL/H1 - Hero`), verified-live
     (public-home, 17.08): Noto Serif 400, 36 → 48 @1280 → 52
     @2258, lh 54/72/78, ls 0.9/1.2/1.3. Это ровно то, что hub-12
     снял с live\index.html и надел на .gbs-h1 (36 → 48 → 52,
     lh 1.5 = 54/72/78, ls 0.025em = 0.9/1.2/1.3 на этих кеглях).
     Роль карты и живой замер СОШЛИСЬ цифра в цифру, поэтому
     .gbs-h1 не изменился ни на пиксель — изменилось только то,
     что теперь он назван своим именем.

     H3 = `Hedings/BP: XL/H3 - Block`: Noto Serif Regular, 32.
     Живого САЙТОВОГО H3 в карте нет вовсе: серифная лестница
     публичного сайта — герой (36/48/52), секция (28/40), колонка
     футера (18/22), между секцией и колонкой ступени 32 сайт не
     показывал. Провенансов у 32 два, оба неполные:
       figma-only  H3 - Block, 32 / Regular / ls 1px;
       recorded-live титул метапанели портала (H1 «My Gifts»),
                     12.08: 32 / 300 / lh 40 / ls -0.4, каскад
                     18/26/32 (base/md/xl).
     Взято: РАЗМЕР 32 @1280 (обе строки согласны) и ВЫСОТА СТРОКИ
     40 (lh 1.25 × 32 = 40, ровно живые 32/40 портала). Вес 400 и
     трекинг normal остались от живой серифной роли секции, в
     которой заголовок двери жил с hub-12: два источника из трёх
     дают Regular, а -0.4 портала — портальная частность, на
     публичном сайте серифные титулы её не носят. База 24 (до
     1280) НЕ ЗАМЕРЕНА НИГДЕ и выведена пропорцией живой лестницы
     H1 (36/48 = 0.75; 0.75 × 32 = 24) — помечена ниже LIVE-RATIO,
     как LIVE-STEP помечает такой же честный вывод у лида.
     Портальный каскад 18/26/32 сюда не взят: 18 на 390 равно
     описанию под ним, и иерархия схлопывается.

   Разница с hub-12 в цифрах: заголовок двери был РОЛЬЮ СЕКЦИИ
   (28 → 40), стал H3 (24 → 32). Титул полки .gbs-h2 остался
   РОЛЬЮ СЕКЦИИ (28 → 40): это заголовок раздела страницы, а не
   карточки, и Тон правил именно карточки. Гейт .gate-h1 (в
   index.html) ушёл на ту же H3, что и двери.
   ------------------------------------------------------------
   ТИПОГРАФИКА СТУДИИ ПЕРЕЕХАЛА НА РОЛИ САЙТА (hub-12, Тон 25.08):
   «Мелковатые шрифты, и она выглядит немного непохожей на
   дизайн-систему GildedBox. Структурно она ок, но общее ощущение
   не то.» Лечится не «сделать на пару пикселей больше», а взять
   роли ЖИВОЙ ГЛАВНОЙ и надеть их сюда целиком (ловушка 11: роль
   берётся вместе с весом, трекингом и высотой строки).

   Замер прибором 25.08, headed Chrome, live\index.html на 1280 и
   1920 (значения на обеих ширинах одинаковые — обе выше порога
   1280; в скобках базовая ступень компонента):

     РОЛЬ ГЕРОЯ      .gbhm-heroTitle    Noto Serif 400,
                     36 → 48 @1280 → 52 @2000, lh 1.5, ls 0.025em
     РОЛЬ СЕКЦИИ     .gbhm-headingTitle Noto Serif 400,
                     («Curated Gifts For:», «The Unboxing»)
                     28 → 40 @1280, lh 1.25, ls normal, Zinc 900
     РОЛЬ КОЛОНКИ    footer .subMenu__title  Noto Serif 400, 18 →
                     22 @768, lh 1.45, ls 0.2 (TYPE-SCALE,
                     verified-live 17.08)
     БАЗОВЫЙ ТЕКСТ   Inter 400 / 16 / normal (TYPE-SCALE)

   Кто что носит теперь:
     .gbs-h1          заголовок страницы  = РОЛЬ ГЕРОЯ = H1 карты,
                      чернилами Zinc 900 (на сайте роль лежит на
                      видео и потому белая; единственное
                      отклонение, оно же то, что делает роль
                      читаемой на Zinc 50)
     .gbs-door-title  заголовок двери     = H3 карты (hub-13)
     .gbs-h2          титул полки         = РОЛЬ СЕКЦИИ
     .gbs-door--box   заголовок малой     = РОЛЬ КОЛОНКИ (22)
     .gbs-plink       имя проекта в рельсе = БАЗОВЫЙ 16, Zinc 700
                      (gbppl-sandbox-md-1; строка .gbs-proto,
                      прожившая один день, выросла обратно в
                      карточку и своей роли больше не носит)
     .gbs-door-desc   описание            = БАЗОВЫЙ + ступень 18
                      с 1280                          ← LIVE-STEP
     .gbs-hub-sub     сабтайтл страницы   = 18 → 20 @1280
                                                      ← LIVE-STEP

   LIVE-STEP и почему это не выдумка: у лайва РОЛИ ЛИДА на Inter
   нет вовсе. Единственный лид сайта — .gbhm-convSub, и он сериф
   18 → 22 @1280; единственная Inter-роль тела — базовые 16. Фигма
   даёт Body/Lead 22/2px, но это figma-only и в колонке 411px не
   живёт. Поэтому лид студии = базовая роль, поднятая на одну
   ступень (16 → 18, сабтайтл 18 → 20): размер честно помечен
   LIVE-STEP, а семейство, вес, трекинг и цвет остались базовой
   роли. NO TOKEN: токенов размера у типографики нет ни у одной из
   этих ролей, шкала живёт в компонентах.

   Ничего мельче 14 на студийных страницах не осталось. Eyebrow
   (12) с дверей хаба СНЯТ: он повторял заголовок слово в слово
   («Live» над «Live Prototype»), а известное не выпячивают
   (Рассел, П2). На песочницах eyebrow остаётся — там он называет
   группу, а не карточку.
   ------------------------------------------------------------
   ХАБ ВЕРНУЛСЯ (hub-10, Тон 24.08, второй заход): «У нас нет
   какой-то одной страницы входа. Наша страница входа — это хаб из
   трёх точек входа, которые к тому же дублируются в верхней
   навигации. Сейчас пользователь попадает сразу на Live, и я не
   могу зайти на саму точку входа». В hub-9 я прочитал «нав должен
   переносить на страницы» как «index = только гейт, дальше сразу
   Live» — и потерял саму точку входа. Нав переносит на страницы, а
   index за гейтом показывает ОБЗОР этих страниц: три равные двери.
   Отсюда блок ТРИ ДВЕРИ ХАБА в конце файла.

   И вторая правка того же захода: «Мелкие шрифты. На GildedBox
   вообще нет таких мелких шрифтов. Стандартный размер 16 пикселей.
   Здесь у тебя какой, 14?» Основной текст студийных страниц
   (лиды полок, описания дверей) поднят 13/14 → 16, вторичное
   (пути, подвал, остановки) — до 14/15, заголовки подросли следом,
   чтобы иерархия не слиплась. Кнопка не тронута: её лестница
   14/15/16 выверена отдельно (с 26.08 это .gb-btn --large, button.css).

   Тон, 24.08: «Live Prototype / Sandboxes / Design System —
   навигация вверху должна тебя переносить на эти страницы, а не
   скроллить к этим секциям».

   Хаб перестал быть одностраничником: гейт остался в index.html,
   а полки разъехались по страницам (sandboxes.html; Design System =
   витрина system\oro\). Своей полки не осталось только у Live: с
   gbppl-liveindex-1 он ведёт прямо на сайт (live\index.html), и
   промежуточная страница live.html удалена.

   Мебель хаба и песочниц — карточка-дверь, полка, подвал — общая, и
   как только страниц стало больше одной, копия этих правил в каждом
   файле превратилась бы ровно в тот двойник, который система
   запрещает (Тон-6). Поэтому мебель живёт здесь, к остальным
   компонентам, и страницы её ПОТРЕБЛЯЮТ.

   Что здесь есть и чего здесь нет:
     ЕСТЬ  полка (заголовок + лид), дверь-карточка в двух ростах,
           список остановок, чип IN PROGRESS, подвал страницы.
     НЕТ   бара (это header.css, вариант --studio), грунта (это
           shell.css, класс gb-demo), кнопки (это button.css,
           организм .gb-btn), токенов (tokens.css).

   Ни одного нового цвета, радиуса, кривой и длительности: всё
   тратится из system\assets\tokens.css. Цифры компоновки
   (1080 колонка, отступы полок) — те же, что стояли на хабе с
   hub-3; они переехали строка в строку, ничего не перемерено.
   ------------------------------------------------------------
   ЧИСЛА СВЕДЕНЫ К ШКАЛЕ (gbppl-studio-tokens-1, Тон 27.08:
   «система не только в компонентах, но и в паттернах, в отступах,
   в шрифтах, абсолютно во всём; строим систему, начиная с нашей
   собственной студии»).

   Что сделано с каждым числом файла: ступень шкалы, записанная
   цифрой, стала токеном (--space-8/16/24/32/48/64, --eyebrow-*,
   --radius); сумма двух ступеней стала calc() с объяснением
   (40 = 32+8, 56 = 32+24, 72 = 48+24, 96 = 64+32: этих ступеней на
   шкале нет, а сумма точная); остальное носит единый коммент
   `NO TOKEN: <почему>` и стоит в отчёте волны.

   ОДИН ЗАЗОР МЕЖДУ ОДНОТИПНЫМИ ЭЛЕМЕНТАМИ (6a.3 скилла). Строки
   внутри карточки стояли на трёх разных числах: 12 у большой
   двери, 14 и 10 у малой. Отношение одно, «текст под текстом внутри
   карточки», значит и число одно: 12 везде. Сдвиги 2px у двух
   правил малой двери, оба в отчёте. 12 = половина ступени
   --space-24, на шкале её нет; решение о --space-12 за Тоном.
   ============================================================ */

/* Страница-студия: бар, тело, подвал прижат к низу. */
.gbs-page { display: flex; flex-direction: column; min-height: 100vh; }

.gbs-body { flex: 1 0 auto; padding: var(--space-48) 0 var(--space-64); }
/* 72 = --space-48 + --space-24, 96 = --space-64 + --space-32: выше
   64 шкала не идёт, поэтому крупные поля страницы записаны суммой
   ступеней, а не новой цифрой. */
@media (min-width: 1280px) {
  .gbs-body { padding: calc(var(--space-48) + var(--space-24)) 0 calc(var(--space-64) + var(--space-32)); }
}

/* Колонка документа. Бар шире — он спанит страницу, как на лайве.
   gbppl-cards-1 (Тон 24.09: «враппер узкий, названия переносятся,
   растянуть для всей студии»): колонка встала на ПЕРВЫЙ КЛЭМП
   КОНТЕЙНЕРА --container-max-lg (1600), единственную названную ширину
   системы. Была 1080 (NO TOKEN, цифра компоновки с hub-3) на полке и
   карте и 1280 (NO TOKEN) на хабе: два числа мимо шкалы стали одним
   токеном. 1920 (второй клэмп) не взят: на 2258 он дал бы карточкам
   хаба ~600 и строкам карты полосу во всю ширину, а 1600 и есть мера,
   с которой контейнер лайва перестаёт расти впервые. Ниже 1648 колонка
   упирается в сам контейнер, то есть на 1280 она 1232. Тексты не
   растягиваются вместе с ней: у лидов и описаний свой потолок 60ch. */
.gbs-wrap { max-width: var(--container-max-lg); margin: 0 auto; }

/* 56 = --space-32 + --space-24, 72 = --space-48 + --space-24. */
.gbs-shelf + .gbs-shelf { margin-top: calc(var(--space-32) + var(--space-24)); }
@media (min-width: 1280px) { .gbs-shelf + .gbs-shelf { margin-top: calc(var(--space-48) + var(--space-24)); } }

/* Титул полки = РОЛЬ СЕКЦИИ лайва (.gbhm-headingTitle, «Curated
   Gifts For:»): Noto Serif 400, 28 → 40 @1280, lh 1.25, ls normal.
   Было своё 24/30/500/-0.025em — своя типографика там, где у сайта
   есть роль ровно на это место (hub-12). */
.gbs-h2 {
  margin: 0;
  font-family: var(--font-serif);
  font-size: 28px;
  font-weight: 400;
  line-height: 1.25;
  letter-spacing: normal;
  color: var(--zinc-900);
}
@media (min-width: 1280px) { .gbs-h2 { font-size: 40px; } }
/* Лид полки — базовая роль, поднятая на ступень с 1280 (LIVE-STEP,
   см. шапку). 16 → 18. */
.gbs-lede {
  margin: 12px 0 0;   /* NO TOKEN: общий зазор «текст под текстом», половина ступени --space-24, см. шапку */
  font-size: 16px;
  line-height: 1.625;
  letter-spacing: 0.2px;
  color: var(--zinc-500);
}
@media (min-width: 1280px) { .gbs-lede { font-size: 18px; } }

/* Eyebrow, один голос на все студийные страницы
   (12 / 600 / 0.12em / uppercase / Zinc 500). */
.gbs-eyebrow {
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--eyebrow-color);
}

/* ---- Двери ----
   Покой Zinc 200, на ховере бордер уходит в Zinc 900 с тенью
   карточки под ним — выбранное состояние карточки метода из
   auth-организма, потраченное здесь как ховер. Не двигается
   ничего, кроме стрелки: 4px, шаг шевронов.
   NO TOKEN на 4: это ход жеста, а не отступ; ступень --space-8
   превратила бы кивок стрелки в прыжок. */
.gbs-door {
  position: relative;
  display: block;
  background: var(--white);
  border: 1px solid var(--zinc-200);
  border-radius: var(--radius);
  transition: border-color var(--mo-micro) var(--mo-move),
              box-shadow var(--mo-micro) var(--mo-move);
}
.gbs-door:hover { border-color: var(--zinc-900); box-shadow: var(--shadow-card); }
.gbs-arrow {
  display: inline-flex;
  color: var(--zinc-900);
  transition: transform var(--mo-micro) var(--mo-move);
}
.gbs-door:hover .gbs-arrow { transform: translateX(4px); }

/* Заголовок двери = TYPE-SCALE H3 (`Hedings/BP: XL/H3 - Block`,
   32; lh 40 = живые 32/40 титула метапанели портала, recorded-live
   12.08). Вес 400 и трекинг normal — от живой серифной роли секции,
   в которой заголовок жил с hub-12. База 24 = LIVE-RATIO (0.75
   живой лестницы H1 36/48), живого замера базы у H3 нет.
   Было 28 → 40 (РОЛЬ СЕКЦИИ = H2 карты), см. шапку файла, hub-13. */
.gbs-door-title {
  margin: 12px 0 0;   /* NO TOKEN: общий зазор «текст под текстом», см. шапку */
  font-family: var(--font-serif);
  font-size: 24px;
  font-weight: 400;
  line-height: 1.25;
  letter-spacing: normal;
  color: var(--zinc-900);
}
@media (min-width: 1280px) { .gbs-door-title { font-size: 32px; } }
/* Описание двери — базовая роль + ступень с 1280 (LIVE-STEP). */
.gbs-door-desc {
  margin: 12px 0 0;   /* NO TOKEN: общий зазор «текст под текстом», см. шапку */
  max-width: 60ch;
  font-size: 16px;
  line-height: 1.625;
  letter-spacing: 0.2px;
  color: var(--zinc-500);
}
@media (min-width: 1280px) { .gbs-door-desc { font-size: 18px; } }

/* Описание на КАРТОЧКЕ полки живёт обрезанным (Тон 21.09: «у версии 5
   чекаута описание делает тройной скролл на экране... там должен быть
   trim или truncate — во всех карточках»). Четыре строки и многоточие;
   полная история — на самой странице и в её Inspect, карточка = превью,
   не текст (правило 28.08). Двери index.html не трогаются: их тексты
   короткие и написаны под дверь. */
.gbs-door--proto .gbs-door-desc {
  display: -webkit-box;
  /* gbppl-cards-1 (модель карточки Тона 24.09): три строки, не четыре.
     Над описанием теперь стоит тумб, и карточка = превью + имя. */
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  /* line-clamp одним многоточием строки не прячет: прячет обрез по
     высоте. Карточка растягивает описание (flex: 1 0 auto у --box),
     и без потолка следующая строка выглядывала под многоточием.
     Потолок = ровно три строки текущего line-height. */
  max-height: calc(3 * 1.625em);
  /* Базовая роль 16 на всех ширинах. Ступень 18 с 1280 (LIVE-STEP
     дверей) осталась дверям хаба: на карточке-превью над тихой
     мета-строкой 14 она растягивала лестницу текста до трёх кеглей
     Inter (18 / 14 / айбрау 12) вместо двух соседних (16 / 14). */
  font-size: 16px;
}
/* Мета прижимается к полу карточки сама, раз описание больше не
   растёт: авто-зазор забирает освободившийся рост. */
.gbs-door--proto .gbs-pcard__meta { margin-top: auto; padding-top: 12px; }

/* ---- Остановки СНЯТЫ (gbppl-panel-10, Тон 27.08) ----
   «Нужно убрать вот эти штуки внизу: портал, каталог, check-out,
   book a meeting. Это ненужный шум. Всё, что внизу в футерах
   карточек, поубирать.» Ряд .gbs-stops жил в подвале трёх дверей
   хаба с hub-12 и был единственным их потребителем, поэтому вместе
   с разметкой ушли и правила. Ссылок внутри карточки больше нет:
   растянутая ::after заголовка осталась единственным кликом, и
   спорить с ней некому. */

/* ---- Сетка малых дверей ---- */
.gbs-grid {
  margin-top: var(--space-24);
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-16);
  /* КАЖДАЯ КАРТОЧКА РОСТОМ ПО СВОЕМУ СОДЕРЖИМОМУ
     (gbppl-sandbox-projects-1, решение по скрину, 6a.4). Пока
     карточка была вариантом, у всех был один состав, и растяжка до
     высоты ряда держала полку ровной. У проекта прототипов от одного
     до скольких угодно, и та же растяжка дала карточке с одним
     прототипом двести пикселей белой дыры между строкой и тегами.
     Правило «высоты равны» (Тон 27.08) осталось там, где оно и было
     сказано: три двери хаба, .gbs-entries. */
  align-items: start;
}
@media (min-width: 768px)  { .gbs-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1100px) { .gbs-grid { grid-template-columns: repeat(3, 1fr); } }

/* NO TOKEN на 20 и 28: поля малой двери. 20 на 4px тише ступени
   --space-24 в узкой колонке ~336px, 28 это её ступенька с 1280.
   Ступени между 16 и 24 и между 24 и 32 на шкале нет, а сдвиг на
   4px меняет высоту карточек, которые Тон принял 27.08 («высоты
   равны»). Расхождение полей двух карточек студии (эта 24/20, дверь
   хаба 20) вынесено Тону отдельным решением. */
.gbs-door--box {
  display: flex;
  flex-direction: column;
  /* Поле по горизонтали объявлено переменной с тех пор, как внутри
     карточки жила строка, выходившая за поля отрицательными полями
     (gbppl-sandbox-projects-1). Строки больше нет
     (gbppl-sandbox-md-1), переменная осталась: числа не менялись ни
     разу, а следующая внутренняя строка спросит то же самое. */
  --gbs-card-padx: 20px;
  padding: var(--space-24) var(--gbs-card-padx);
}
@media (min-width: 1280px) {
  .gbs-door--box { --gbs-card-padx: var(--space-24); padding: 28px var(--gbs-card-padx); }
}
/* Малая дверь стоит в трёхколоночной сетке ~336px, роль секции
   (40) туда не встаёт. Её заголовок носит РОЛЬ КОЛОНКИ подвала
   лайва целиком: Noto Serif 400 / 22 / lh 1.45 / ls 0.2
   (TYPE-SCALE, verified-live 17.08, ступень @768). Было 20/500. */
.gbs-door--box .gbs-door-title {
  margin-top: 12px;   /* было 14: тот же зазор «текст под текстом», что у всех карточек студии */
  font-size: 22px;
  line-height: 1.45;
  letter-spacing: 0.2px;
}
@media (min-width: 1280px) { .gbs-door--box .gbs-door-title { font-size: 22px; } }
/* Описание малой двери идёт по общей лестнице (16 → 18 @1280).
   На полке песочниц у карточки описания больше нет (описание есть у
   КАЖДОГО прототипа внутри неё), но правило живёт: .gbs-door--box —
   форма малой двери, а не имя одной страницы, и следующий её
   потребитель придёт с описанием. */
.gbs-door--box .gbs-door-desc { margin-top: 12px; flex: 1 0 auto; }   /* было 10: тот же зазор, что у всех карточек */

/* ============================================================
   ШАПКА ПРОЕКТА (gbppl-sandbox-projects-1, Тон 2026-08-31; переехала
   в мастер-деталь тем же вечером, gbppl-sandbox-md-1)
   ------------------------------------------------------------
   «Мы работаем как Figma: проект, внутри которого прототипы?» Да.
   Утром проект был карточкой со строками прототипов внутри; вечером
   того же дня проект стал ПУНКТОМ РЕЛЬСЫ слева, а его прототипы —
   карточками справа (полный разбор в блоке МАСТЕР-ДЕТАЛЬ в конце
   файла). Из карточки-проекта пережила переезд ровно эта пара:
   заголовок слева, тихий счётчик справа. Теперь она стоит шапкой
   правой половины, и это единственное место, где имя проекта
   называется во весь голос.

   Что ушло вместе с карточкой-проектом: .gbs-door--project и всё
   семейство .gbs-proto* (строка прототипа внутри карточки). Строка
   прожила один день и выросла обратно в карточку — ту самую
   .gbs-door--box, которой вариант и был до утра. Окрас без предмета
   это долг, а не запас: правила сняты в той же волне, что сняла
   предмет (тот же счёт, по которому ушли .gbs-door-variant и
   .gbs-door-foot).
   ============================================================ */
.gbs-proj__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;   /* NO TOKEN: зазор внутри ряда, половина ступени --space-24 */
}
.gbs-proj__head .gbs-door-title { margin-top: 0; }
/* Счётчик — вторичный голос полки (14 / Zinc 400), тот же, что у
   дат. Он не eyebrow: eyebrow здесь занят именами групп. */
.gbs-proj__count {
  flex: 0 0 auto;
  font-size: 14px;
  letter-spacing: 0.2px;
  color: var(--zinc-400);
  white-space: nowrap;
}

/* ---- Комнаты по страницам (gbppl-sandboxes-2, Тон 25.08) ----
   Двери сгруппированы страницей, к которой относятся: с этим
   вопросом на страницу и приходят («что пробуют на чекауте, что в
   портале»). Имя группы — роль Eyebrow из shell.css, ничего
   нового: это ярлык, а не заголовок, титул на полке один. */
.gbs-rooms { margin-top: var(--space-32); }
/* 40 = --space-32 + --space-8: ступени 40 на шкале нет. */
.gbs-room + .gbs-room { margin-top: calc(var(--space-32) + var(--space-8)); }
@media (min-width: 1280px) { .gbs-room + .gbs-room { margin-top: var(--space-48); } }
.gbs-room .gbs-grid { margin-top: var(--space-16); }   /* было 14: ступень ближе на 2px */

/* Дверь, за которой ещё нет комнаты (ready:false в реестре), утром
   уходила вместе с карточкой-вариантом (gbppl-sandbox-projects-1) и
   вечером вернулась вместе с ней же: карточка снова равна прототипу,
   и `.gbs-door--coming` объявлена заново в блоке МАСТЕР-ДЕТАЛЬ в
   конце файла, без пунктирной рамки. Ушли и не вернулись
   .gbs-door-variant, .gbs-door-foot, .gbs-door-note и
   .gbs-door-updated: у всех четырёх не осталось ни одного
   потребителя, а окрас без предмета — это долг, а не запас. */

/* Чип IN PROGRESS. Zinc, не янтарь: янтаря в системе нет, а
   единственное тёплое, что в ней есть, — легаси-золото, которое
   Тон с этих страниц вывел. Zinc 100 в eyebrow-голосе говорит
   «не закончено», не добавляя цвета в палитру. */
.gbs-chip {
  display: inline-block;
  align-self: flex-start;   /* карточка — flex-колонка; без этого
                               чип растягивается в полосу */
  padding: 4px var(--space-8);   /* NO TOKEN на 4: пол ступени, поле чипа вокруг строки 12/1.2 */
  /* Чип — одна нерушимая надпись: «BOOK A MEETING», сломанное на две
     строки в узкой строке списка, перестаёт быть бейджем и становится
     абзацем (замер 390, gbppl-sandboxes-4). */
  white-space: nowrap;
  background: var(--zinc-100);
  border-radius: var(--radius);
  font-size: var(--eyebrow-size);   /* 12: голос eyebrow, не мельче */
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  line-height: 1.2;
  text-transform: uppercase;
  color: var(--eyebrow-color);
}

/* ---- Тихая строка внизу ---- */
.gbs-foot {
  flex: 0 0 auto;
  padding: var(--space-24) 0 var(--space-32);
  border-top: 1px solid var(--zinc-200);
}
.gbs-foot p {
  max-width: var(--container-max-lg);   /* та же колонка, что у .gbs-wrap (gbppl-cards-1) */
  margin: 0 auto;
  font-size: 14px;   /* вторичное, нижняя граница шкалы (Тон 24.08) */
  letter-spacing: 0.2px;
  color: var(--zinc-400);
}

/* ============================================================
   ТРИ ДВЕРИ ХАБА (gbppl-hub-13, Тон 2026-08-25)
   ------------------------------------------------------------
   Точка входа студии: за гейтом index.html показывает ОБЗОР трёх
   разделов, которые дублируются в баре (hub-10, Тон 24.08).
   Композиция та же, изменилось три вещи, все три — по фидбеку
   Тона 25.08.

   1. ТИПОГРАФИКА РОЛЯМИ КАРТЫ. Сперва «мелковатые шрифты, и она
      выглядит немного непохожей на дизайн-систему GildedBox»
      (hub-12), затем, по готовому хабу: «я бы сделал заголовки
      карточек нашим системным H3-заголовком, а Design Studio
      пусть будет нашим системным H1-заголовком» (hub-13).
      Провенанс каждой роли — в шапке файла. Коротко:
        .gbs-h1          = TYPE-SCALE H1 «Hero H1», verified-live
                           (Noto Serif 400, 36 → 48 @1280 → 52,
                           lh 1.5, ls 0.025em) — не изменился, роль
                           карты и живой замер совпали
        .gbs-door-title  = TYPE-SCALE H3 (Noto Serif 400, 24 → 32
                           @1280, lh 1.25 = 30/40, ls normal);
                           было 28 → 40 (H2 карты = живая роль
                           секции)
        .gbs-door-desc   = live body base + LIVE-STEP (16 → 18)
        .gbs-hub-sub     = live body base + LIVE-STEP (18 → 20)
      Eyebrow с дверей снят: он повторял заголовок.
      Описания hub-13 не трогал: 18 утверждено.

   2. ЖИВОЕ ПРЕВЬЮ. «Она выглядит немного непохожей на дизайн-
      систему GildedBox» — хаб был страницей из одних слов, а
      GildedBox это страница с картинками. Каждая дверь показывает
      СНИМОК настоящей страницы за ней (system\assets\studio\,
      снято прибором 1440×900 → 960×600). Рамка Zinc 200, радиус 5,
      cover, соотношение 16:10 — то же, что у снимка.

   3. ПЕРЕХОДЫ ВНУТРЬ. «Оттуда у меня нет возможности перейти на
      нужную мне страницу.» Под описанием стоял ряд .gbs-stops, и он
      СНЯТ с gbppl-panel-10 (Тон 27.08: «Всё, что внизу в футерах
      карточек, поубирать»). Дорога внутрь теперь одна и настоящая:
      дверь Live Prototype открывает карту страниц, дверь Sandboxes —
      полку комнат, дверь Design System — витрину.

   КАРТОЧКА С РАСТЯНУТОЙ ССЫЛКОЙ. Дверь осталась div-ом, каким её
   сделал hub-12 ради ряда остановок, и остаётся им дальше: ссылка
   в заголовке уже несёт ::after на всю площадь, а переписывать
   карточку в один <a> значит трогать её ховер, фокус и порядок
   чтения ради того же результата. Устройство:
     обёртка   div.gbs-door (position: relative)
     главная   a.gbs-door-link внутри заголовка; её ::after
     ссылка    растянут inset 0 на всю карточку — кликается вся
               площадь, включая превью, а в дереве доступности
               ссылка ровно одна и её имя — заголовок двери
   Ховер и фокус карточки живут на самой .gbs-door через :hover и
   :focus-within, поэтому клавиатура видит то же, что мышь.

   Ничего нового не нарисовано (Тон-6): карточка — та же .gbs-door
   (белое поле, Zinc 200, радиус 5, ховер «Zinc 900 + тень
   карточки», стрелка +4px). Ховер-пара сверена с карточкой
   каталога лайва (a.gbcCard:hover → box-shadow --shadow-card +
   смена цвета рамки, catalog.css): подъёма-трансформа у лайва
   нет, и здесь его нет тоже.

   Грунт хаба — Zinc 50 вместо near-white лайва: три белые
   карточки обязаны читаться как предметы на поверхности, а на
   #fcfdfd они растворяются — та самая бледность.
   ============================================================ */

.gbs-page--hub { background: var(--zinc-50); }

/* Хаб — короткая композиция: строка, подстрока и ряд карточек.
   На высоком экране она стоит по центру тела, а не висит под баром
   над полем пустоты. Центрирование срабатывает только когда место
   есть: содержимое выше тела просто растит тело (flex: 1 0 auto). */
.gbs-page--hub .gbs-body { display: flex; align-items: center; }
.gbs-page--hub .gbs-body > .gb-container { width: 100%; }

/* Колонка хаба была шире полочной (1280 против 1080, NO TOKEN).
   С gbppl-cards-1 обе стоят на --container-max-lg (см. .gbs-wrap),
   и отдельное правило хаба снято: одна колонка у всей студии. */

/* Шапка хаба: заголовок страницы (РОЛЬ ГЕРОЯ = TYPE-SCALE H1,
   verified-live public-home 17.08) и одна строка под ним. Никаких
   вводных. Кегль и ритм hub-13 не менял: роль карты совпала с тем,
   что hub-12 снял прибором, значит и отступ сабтайтла (8) остался
   тем, что уже утверждён. */
.gbs-hubhead { max-width: 1080px; }
.gbs-h1 {
  margin: 0;
  font-family: var(--font-serif);
  font-size: 36px;
  font-weight: 400;
  line-height: 1.5;
  letter-spacing: 0.025em;
  color: var(--zinc-900);
}
@media (min-width: 1280px) { .gbs-h1 { font-size: 48px; } }
@media (min-width: 2000px) { .gbs-h1 { font-size: 52px; } }
.gbs-hub-sub {
  margin: var(--space-8) 0 0;
  max-width: 60ch;
  font-size: 18px;
  line-height: 1.625;
  letter-spacing: 0.2px;
  color: var(--zinc-500);
}
@media (min-width: 1280px) { .gbs-hub-sub { font-size: 20px; } }

/* Ряд дверей. Три — число неделимое: либо все три в ряд, либо
   стек. Двух-колоночной ступени нет намеренно, иначе третья
   карточка стоит сиротой в половину ряда. */
.gbs-entries {
  margin-top: var(--space-32);
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-16);
}
/* 40 = --space-32 + --space-8. NO TOKEN на 20: средняя ступень
   зазора между 16 и 24, которой на шкале нет; ряд из трёх карточек
   на ней стоит с hub-12 и утверждён. */
@media (min-width: 900px)  { .gbs-entries { margin-top: calc(var(--space-32) + var(--space-8)); grid-template-columns: repeat(3, 1fr); gap: 20px; } }
@media (min-width: 1280px) { .gbs-entries { margin-top: var(--space-48); gap: var(--space-24); } }

.gbs-door--entry {
  display: flex;
  flex-direction: column;
  padding: 20px;   /* NO TOKEN: те же поля, что у зазора ряда, см. выше */
}
@media (min-width: 1280px) { .gbs-door--entry { padding: var(--space-24); } }

/* Клавиатура должна видеть то же, что мышь: фокус на любой ссылке
   внутри поднимает карточку так же, как ховер. */
.gbs-door--entry:focus-within { border-color: var(--zinc-900); box-shadow: var(--shadow-card); }
.gbs-door--entry:focus-within .gbs-arrow { transform: translateX(4px); }

/* ---- Превью: снимок страницы за дверью ----
   Рамка и радиус — системная пара карточки; соотношение 16:10
   держит ряд ровным независимо от веса картинки, cover обрезает
   лишнее. Никакой трансформы на ховере: у карточки каталога лайва
   её нет (см. шапку блока). */
.gbs-door-shot {
  display: block;
  overflow: hidden;
  border: 1px solid var(--zinc-200);
  border-radius: var(--radius);
  background: var(--zinc-100);
  aspect-ratio: 16 / 10;
}
.gbs-door-shot img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
}

/* Заголовок двери и стрелка стоят одной строкой: стрелка — знак
   того, что заголовок ведёт наружу, и ей место рядом с ним, а не
   в подвале под остановками. */
.gbs-door--entry .gbs-door-title {
  /* NO TOKEN на 20: заголовок отбит от ПРЕВЬЮ, а не от текста, и
     стоит на той же мере, что поля карточки. */
  margin-top: 20px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-16);
}
@media (min-width: 1280px) { .gbs-door--entry .gbs-door-title { margin-top: var(--space-24); } }
.gbs-door--entry .gbs-arrow { flex: 0 0 auto; }

/* Растянутая главная ссылка. Цвет объявлен парой — ловушка 1. */
a.gbs-door-link,
body.gb-demo a.gbs-door-link { color: var(--zinc-900); }
.gbs-door-link::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--radius);
}

/* flex: 1 держит низы трёх карточек на одной линии, даже если одно
   описание всё-таки уехало на строку длиннее соседей (grid и без
   того тянет карточки ряда в одну высоту); max-width снят — колонка
   сама узкая. */
.gbs-door--entry .gbs-door-desc { max-width: none; flex: 1 0 auto; }


/* ============================================================
   СЕРЫЙ ХОЛСТ ПОД БЕЛЫМИ КАРТОЧКАМИ (gbppl-panel-9, Тон 27.08)
   ------------------------------------------------------------
   Тон о полке песочниц: «Сейчас карточки белые на белом фоне.
   Нужно добавить контраста: либо фон бэкграунда сделать Zinc 100,
   либо сами карточки покрасить в Zinc 100». Взята первая половина:
   серый холст, белые карточки — ровно та пара, что стоит на
   каталоге и на лайве, и та, в которой карточка означает «предмет
   на столе», а не «пятно на бумаге».

   Модификатор, а не правило .gbs-page: хаб живёт на собственном
   .gbs-page--hub с Zinc 50 и этой волной не тронут (у него своя
   композиция и свои двери во весь экран). Носят холст две
   страницы: sandboxes.html и live\map.html.

   Волосок подвала остаётся Zinc 200: на Zinc 100 он тише, чем был
   на белом, но читается (проверено скрином на 390 / 1280 / 1920).
   Бар студии белый и стоит на Zinc 100 своей нижней границей.
   ============================================================ */
.gbs-page--canvas { background: var(--zinc-100); }


/* ============================================================
   ДЕРЕВО СТРАНИЦ ПРОТОТИПА (gbppl-panel-9, Тон 27.08)
   ------------------------------------------------------------
   Тон: «Сделать так, чтобы Live Prototype начинался не сразу с
   сайта, а с экрана выбора (как в Sandboxes): сделать красивую
   визуализацию дерева страниц (Home и остальные), где будет видно,
   какие страницы уже готовы и покрыты, а какие ещё ожидаются».

   Мебель у дерева ЧУЖАЯ, своей заведено ровно столько, сколько
   нужно на линии и отступы: узел — та же белая карточка с рамкой
   Zinc 200 и ховером Zinc 900 + --shadow-card, что у дверей
   (.gbs-door), статус — тот же .gbs-chip в голосе Eyebrow, только
   с двумя новыми окрасами. Тон-6 в чистом виде.

   ЛИНИИ Zinc 300 (слово Тона). Ствол — левая граница списка детей,
   отвод — горизонтальный волосок от ствола к карточке. Отвод
   ловится на середину ПЕРВОЙ строки карточки, а не на её середину:
   у карточек разная высота, и линия, приходящая в имя, читается,
   а линия, приходящая в пустоту под именем, нет.

   МОУШЕН ПО ТОН-7: дерево появляется само, без веток
   prefers-reduced-motion. Приход --mo-small на кривой --mo-arrive,
   подъём с одной ступени шкалы отступов, каскад 40ms на узел —
   тот же шаг, которым в MOTION.md №3 тело шага отстаёт от своего
   заголовка.
   ============================================================ */
.gbs-tree { margin: 0; padding: 0; list-style: none; }
.gbs-tree--top { margin-top: var(--space-32); }
.gbs-branch { position: relative; }
.gbs-branch + .gbs-branch { margin-top: var(--space-16); }

/* Ствол ветки и воздух под него. 24 = ступень шкалы; левое поле 8
   отодвигает ствол от кромки карточки-родителя, чтобы линия не
   касалась её рамки. */
.gbs-tree--kids {
  margin-top: var(--space-16);
  margin-left: var(--space-8);
  padding-left: var(--space-24);
  border-left: 1px solid var(--zinc-300);
}
.gbs-tree--kids > .gbs-branch::before {
  content: "";
  position: absolute;
  left: calc(var(--space-24) * -1);
  /* NO TOKEN: 28 это привязка к СТРОКЕ, а не отступ. Поле карточки 16
     плюс половина строки имени 12: отвод обязан прийти в имя, а не
     в пустоту под ним, и число считается от текста. */
  top: 28px;
  width: var(--space-24);
  border-top: 1px solid var(--zinc-300);
}

/* Узел. Белая карточка на сером холсте, ряд: имя, статус, тихая
   правая колонка. Цвет объявлен парой — ловушка 1 скилла. */
.gbs-node {
  position: relative;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-8) var(--space-16);
  padding: var(--space-16);
  background: var(--white);
  border: 1px solid var(--zinc-200);
  border-radius: var(--radius);
  text-decoration: none;
  transition: border-color var(--mo-small) var(--mo-move),
              box-shadow var(--mo-small) var(--mo-move);
}
/* Каскад объявлен ОДИН РАЗ на все поверхности, которые им живут:
   узел карты, карточка песочницы и строка списка (gbppl-sandboxes-4).
   Раньше он стоял внутри .gbs-node; вынесен без единого изменения
   числа, потому что вторая копия той же хореографии — это и есть
   вторая хореография. */
.gbs-node,
.gbs-door--box,
.gbs-row {
  animation: gbsNodeIn var(--mo-small) var(--mo-arrive) both;
  /* NO TOKEN: 40ms это ШАГ каскада, а не длительность: у --mo-* названы
     длины движения, а не расстояние между их началами. Число живое,
     из MOTION.md №3 (тем же шагом тело шага отстаёт от заголовка). */
  animation-delay: calc(var(--gbs-step, 0) * 40ms);
}
a.gbs-node,
body.gb-demo a.gbs-node { color: var(--zinc-900); }
a.gbs-node:hover,
body.gb-demo a.gbs-node:hover { border-color: var(--zinc-900); box-shadow: var(--shadow-card); }

@keyframes gbsNodeIn {
  from { opacity: 0; transform: translateY(var(--space-8)); }
  to   { opacity: 1; transform: none; }
}

/* Имя узла = роль колонки малой двери (22 → 24 с 1280 у .gbs-door--box
   стоит 22; здесь на ступень тише, потому что узлов на экране много). */
.gbs-node__name {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 18px;
  line-height: 1.35;
}
/* Корень ветки на ступень крупнее детей: вложенность рисуется
   отступом и линией, а вес имени говорит то же самое вторым
   голосом, и вместе они читаются с одного взгляда. */
.gbs-tree--top > .gbs-branch > .gbs-node .gbs-node__name {
  font-size: 20px;
  font-weight: 500;
}

/* Правая колонка: провенанс имени (откуда мы про эту страницу
   знаем) и покрытие песочницами. Обе строки — данные, не украшение,
   поэтому 14 Zinc 500, а не мельче. */
.gbs-node__aside {
  /* Ужимается и переносится, когда строке не хватает места: у
     пересечений правая колонка длиннее имени, и на 390 она вылезала
     за окно на 70px (замер gbppl-panel-10). Там, где она помещалась,
     ничего не изменилось: flex-basis прежний auto. */
  flex: 0 1 auto;
  min-width: 0;
  color: var(--zinc-500);
  font-size: 14px;
  line-height: 1.35;
}

/* Страница, которой у нас ещё нет: не ссылка и по разметке, рамка
   пунктиром, ховер не поднимает — тот же язык, что у двери
   .gbs-door--coming этажом выше. */
.gbs-node--expected {
  background: var(--zinc-50);
  border-style: dashed;
}
.gbs-node--expected .gbs-node__name { color: var(--zinc-400); }

/* Статус чипом. ready — состояние, значит синий (Тон-5); expected —
   контур Zinc 500, потому что состояния ещё нет, есть только
   обещание. Оба носят .gbs-chip, у которого уже есть голос Eyebrow
   и радиус системы; здесь меняется только окрас. */
.gbs-node .gbs-chip { align-self: center; }
.gbs-chip--ready {
  background: var(--blue-600);
  color: var(--white);
}
.gbs-chip--expected {
  background: transparent;
  border: 1px solid var(--zinc-500);
  color: var(--zinc-500);
}

/* Полка ожидаемых: те же узлы, но без дерева — у страниц, которых
   нет, нет и родителя. */
.gbs-flat { margin-top: var(--space-32); }
.gbs-flat .gbs-branch + .gbs-branch { margin-top: var(--space-8); }


/* ============================================================
   ДВА ДЕРЕВА И ТОЧКИ ПЕРЕСЕЧЕНИЯ (gbppl-panel-10, Тон 27.08)
   ------------------------------------------------------------
   Тон, посмотрев карту: «портал не может быть ready, потому что
   портал это контейнер, а не страница. Дерево сделано неправильно:
   веб-сайт и портал должны быть двумя отдельными деревьями с
   точками пересечения между собой».

   Отсюда две новые вещи, обе на уже готовой мебели.

   1. КОРЕНЬ-КОНТЕЙНЕР. Статус бывает у страницы и у состояния, у
      места не бывает: ready и expected — оба ответа на вопрос,
      который контейнеру не задают. Поэтому чипа у него нет вовсе,
      а правая колонка говорит словом, что это за строка. Карточка
      та же, только не ссылка и без ховера: контейнер никуда не
      ведёт, у него есть дети.
   2. ПЕРЕСЕЧЕНИЕ. Строка «откуда → куда», и между именами
      пунктирный волосок Zinc 500 со стрелкой дверей хаба на конце.
      Пунктир потому, что это не ветка дерева, а переход между
      двумя деревьями; Zinc 500 потому, что синий у нас значит
      состояние (Тон-5), а переход не состояние.
   ============================================================ */
.gbs-node--place {
  background: var(--zinc-50);
  cursor: default;
}
.gbs-node--place .gbs-node__name { flex: 0 1 auto; }

.gbs-cross { margin-top: var(--space-32); }
.gbs-cross .gbs-branch + .gbs-branch { margin-top: var(--space-8); }

/* Имена в строке пересечения не тянутся: тянется волосок между
   ними, и это он показывает переход. Правая колонка уходит на свою
   строку там, где ряд не помещается. */
.gbs-node--cross { cursor: default; }
.gbs-node--cross .gbs-node__name { flex: 0 1 auto; }
.gbs-cross__link {
  flex: 1 1 var(--space-24);
  min-width: var(--space-24);
  display: flex;
  align-items: center;
  color: var(--zinc-500);
}
/* Волосок и стрелка — одна фигура: линия дорастает до стрелки, а
   стрелка стоит вплотную, поэтому переход читается как один жест. */
.gbs-cross__link::before {
  content: "";
  flex: 1 1 auto;
  border-top: 1px dashed var(--zinc-500);
}
.gbs-cross__link svg { display: block; flex: 0 0 auto; margin-left: -4px; }   /* NO TOKEN: наконечник садится на конец линии, это стык фигур, а не отступ */


/* ============================================================
   МЕНЕДЖЕР ПРОЕКТОВ НА СТРАНИЦЕ SANDBOXES (gbppl-sandboxes-4,
   Тон 2026-08-28)
   ------------------------------------------------------------
   Тон, дословно: «что если страница Sandboxes будет выполнять роль
   менеджера проектов в Figma? Сейчас один view: большие карточки,
   сгруппированные по принадлежности. 1. View должен быть и списком,
   и карточками. 2. Группировку стоит делать через теги (показывать
   бейджем принадлежность к чему-либо). Можно сделать фильтрацию или
   группировку на странице, группировка опциональная. 3. Можно
   смотреть проекты по последнему активному (что последнее
   изменялось).»

   ЧТО ЗДЕСЬ НОВОГО И ЧТО ВЗЯТО ГОТОВЫМ (Тон-6, 6a.2 скилла):
     контролы   .gbdoc-axis / .gbdoc-axis__name / .gbdoc-seg из
                docs.css, БЕЗ единой правки: сегмент документации и
                есть инструмент студии, а инструмент не должен
                выглядеть предметом (Тон 26.08). docs.css уже
                линкуется этой страницей ради дровера Inspect.
     карточка   та же .gbs-door--box, ей добавлен ряд бейджей и
                строка даты в подвале.
     заголовок  та же .gbs-room + .gb-eyebrow, что рисовала группы
                по страницам; теперь она рисует любую группировку.
     чип        тот же .gbs-chip: три окраса вместо одного.
     каскад     та же анимация gbsNodeIn с шагом 40ms, что у карты.
   Своего заведено ровно два предмета: полка контролов и строка
   списка. Оба ниже.

   ТРИ ОКРАСА ЧИПА И ПОЧЕМУ ИМЕННО ТАК (Тон-5). Страница, которой
   принадлежит комната, — вечная мебель, значит Zinc 900 сплошным.
   Статус остаётся тем, чем его принял Тон 25.08: Zinc 100 в голосе
   eyebrow, цвета в палитру не добавляет. Тег — тихий контур: он не
   состояние и не мебель, он ярлык. Выбранный тег в фильтре — Blue
   600: выбор это состояние.

   КОНТУР ЧИПА РИСУЕТСЯ inset box-shadow, А НЕ БОРДЕРОМ. Чипы стоят
   в один ряд с соседями без контура, и настоящая рамка сделала бы
   их на 2px выше. Тень внутрь даёт ту же линию, не трогая
   размерную коробку и не заводя второго набора паддингов.
   ============================================================ */

/* ---- Полка контролов над содержимым ----
   Воздух симметричен относительно волоска (6a.3): 32 сверху,
   32 снизу, 32 до первой группы. */
.gbs-controls {
  margin-top: var(--space-32);
  padding-bottom: var(--space-32);
  border-bottom: 1px solid var(--zinc-200);
}

/* ---- Чип: фильтр ----
   .gbs-chip--page (плашка Zinc 900, чернила белые) снят вместе со
   своим единственным потребителем: имя страницы поднялось из бейджа
   в заголовок карточки и в первую колонку списка
   (gbppl-sandbox-names-1, 31.08), и правило осталось бы окрасом без
   предмета. Тем же счётом ушёл .gbs-chip--tag (gbppl-cards-1, Тон
   24.09: «теги с карточек убрать, живут только в фильтрах»): тег на
   карточке был его единственным потребителем. */

/* Чип тега в фильтре, мишень. Кольцо фокуса — DECLARED Blue 600
   2px/2px, как у .gbdoc-seg. */
.gbs-tagbtn {
  appearance: none;
  border: 0;
  font-family: inherit;
  cursor: pointer;
  background: transparent;
  box-shadow: inset 0 0 0 1px var(--zinc-200);
  color: var(--zinc-500);
  transition: color var(--mo-micro) var(--mo-move),
              background-color var(--mo-micro) var(--mo-move),
              box-shadow var(--mo-micro) var(--mo-move);
}
.gbs-tagbtn:hover { color: var(--zinc-900); box-shadow: inset 0 0 0 1px var(--zinc-400); }
.gbs-tagbtn.is-on { background: var(--blue-600); color: var(--white); box-shadow: none; }
.gbs-tagbtn:focus-visible { outline: 2px solid var(--blue-600); outline-offset: 2px; }

/* ---- Карточка: ряд бейджей сверху, теги внизу, дата в подвале ----
   Ряд бейджей встал на место одиночного чипа статуса, поэтому зазор
   до заголовка (12) не менялся. Имя страницы ушло из подвала в
   бейдж: печатать его дважды незачем, а подвал был единственным
   местом, куда просилась дата.

   И ВЕРНУЛОСЬ К ОДНОМУ ЧИПУ (gbppl-sandbox-names-1, 31.08). Имя
   страницы поднялось из бейджа в ЗАГОЛОВОК карточки, и чип под ним
   говорил бы то же слово вторично. В ряду снова один предмет —
   статус, — и это та же однострочная гарантия, ради которой теги
   стоят внизу: ряд не переносится, заголовки шести карточек стоят
   на одной высоте.

   ТЕГИ СТОЯТ ВНИЗУ, А НЕ В ВЕРХНЕМ РЯДУ, И ЭТО РЕШЕНИЕ ПО СКРИНУ
   (6a.4). В одном ряду с бейджами четыре тега переносились на три
   строки в колонке 336px, заголовки шести карточек вставали на
   четырёх разных высотах, и ряд, который должен читаться первым,
   становился самым громким пятном карточки. Верхний ряд оставлен
   ОДНОСТРОЧНЫМ по составу: страница и статус, их всегда ровно два.
   Теги живут в подвижной части карточки, под описанием, где перенос
   не двигает ничего.

   И ВЕРХНЕГО РЯДА БОЛЬШЕ НЕТ ВОВСЕ (gbppl-sandbox-projects-1,
   31.08). Карточка стала проектом, а статус принадлежит прототипу,
   не проекту: чип уехал в строку прототипа, слева от дат, ровно
   туда, куда Тон показал. У .gbs-badges остался один потребитель —
   ряд тегов внизу.

   И ТЕГОВ НА КАРТОЧКЕ БОЛЬШЕ НЕТ (gbppl-cards-1, Тон 24.09): они живут
   в фильтре, .gbs-badges и .gbs-badges--tags сняты вместе с последним
   потребителем. Статус из чипа ушёл словом в мета-строку. */

/* ---- Список ----
   Одна белая карточка, внутри строки через волосок: та же пара
   «белое на Zinc 100 с рамкой Zinc 200», что у двери и у узла
   карты, только не по карточке на песочницу, а одна на все.
   Ховер строки — цинковое мытьё (ghost-состояние организма
   кнопки): рамку внутри общей карточки подсветить нечем. */
.gbs-list {
  background: var(--white);
  border: 1px solid var(--zinc-200);
  border-radius: var(--radius);
  padding: 0 var(--space-16);
  overflow: hidden;
}
.gbs-room .gbs-list { margin-top: var(--space-16); }
/* Без группировки заголовка над содержимым нет, и весь воздух даёт
   .gbs-rooms (32). Собственный отступ сетки в этом случае удвоил бы
   его: один зазор между однотипными вещами (6a.3). */
.gbs-rooms > .gbs-grid,
.gbs-rooms > .gbs-list { margin-top: 0; }

/* Мытьё ховера обязано доходить до кромок карточки, поэтому строка
   выходит из её полей отрицательными полями и возвращает их
   паддингом.

   ТРИ РОСТА ОДНОЙ СТРОКИ. База (узкий экран) — ДВЕ СТРОКИ: имя со
   стрелкой сверху, вся мета под ним слева. С 768 обе половины
   встают в один ряд. С 1100 ряд становится КОЛОНКАМИ: список
   читают сверху вниз, и статус с датой обязаны находиться на одном
   и том же месте в каждой строке. Порог 1100 — тот же, на котором
   сетка карточек становится трёхколоночной; ниже него шести
   колонкам просто не хватает меры. */
.gbs-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-8) var(--space-16);
  margin: 0 calc(var(--space-16) * -1);
  padding: var(--space-16);
  text-decoration: none;
  transition: background-color var(--mo-micro) var(--mo-move);
}
.gbs-row + .gbs-row { border-top: 1px solid var(--zinc-200); }
a.gbs-row:hover,
body.gb-demo a.gbs-row:hover { background: var(--zinc-50); }
a.gbs-row,
body.gb-demo a.gbs-row { color: var(--zinc-900); }
a.gbs-row:hover .gbs-arrow { transform: translateX(4px); }

/* ДВЕ ИМЕННЫЕ КОЛОНКИ, В ТОМ ЖЕ ПОРЯДКЕ, ЧТО НА КАРТОЧКЕ
   (gbppl-sandbox-names-1, Тон 31.08): первая — страница, вторая —
   вариант. Обе базовая роль, 16 (Тон 24.08: ничего мельче), обе
   Zinc 900: это два имени одного места, а не имя и подпись к нему.
   Чип страницы из меты ушёл вместе с этим — он и был той колонкой,
   только сжатой в бейдж и стоявшей ПОСЛЕ имени варианта. */
.gbs-row__name,
.gbs-row__variant {
  min-width: 0;
  font-size: 16px;
  line-height: 1.45;
}
.gbs-row__name { order: 0; flex: 1 1 auto; }
/* Пока ряд не стал сеткой, вторая колонка — ВТОРАЯ СТРОКА: имя
   страницы и имя варианта, поставленные рядом в 390, дрались за
   место и гнали дату с стрелкой то в конец первой строки, то в
   середину второй (скрин 31.08, 6a.4). Порядок в узком: страница с
   датой и стрелкой, под ними вариант, под ним мета. */
.gbs-row__variant { order: 3; flex: 1 1 100%; }
.gbs-row--coming .gbs-row__variant { color: var(--zinc-400); }
/* ПОРЯДОК ЯЧЕЕК ЗАДАН order, А НЕ РАЗМЕТКОЙ, потому что на узком
   экране он ДРУГОЙ: дата и стрелка уходят наверх, к имени, а мета
   падает под них целой строкой. Разметка одна на три роста. */
.gbs-row__updated {
  order: 1;
  flex: 0 0 auto;
  font-size: 14px;
  letter-spacing: 0.2px;
  color: var(--zinc-400);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.gbs-row .gbs-arrow { order: 2; flex: 0 0 auto; }
.gbs-row__meta {
  order: 4;   /* было 3: между датой и метой встала строка варианта */
  flex: 1 1 100%;
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  gap: var(--space-8);
  min-width: 0;
}
/* Теги в СПИСКЕ — строка, а не чипы: строка плотная, и четыре чипа
   в ней подняли бы её вдвое. Чип остаётся там, где он предмет: на
   карточке (ярлык) и в фильтре (мишень). Полный список в title. */
.gbs-row__tags {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 14px;
  letter-spacing: 0.2px;
  color: var(--zinc-500);
}
/* Причина, по которой у строки нет стрелки, стоит РЯДОМ С ИМЕНЕМ, а
   не в конце ряда: конец ряда — колонка стрелки шириной со стрелку,
   и слово в ней сдвинуло бы дату у одной строки из шести. */
.gbs-row__note {
  margin-left: var(--space-8);
  font-size: 14px;
  color: var(--zinc-500);
  white-space: nowrap;
}
/* Строка без комнаты: тот же язык, что у .gbs-door--coming, но без
   пунктирной рамки — рамки у строки нет вовсе. */
.gbs-row--coming { background: var(--zinc-50); }
.gbs-row--coming .gbs-row__name { color: var(--zinc-400); }

/* ПОРОГ ОДНОСТРОЧНОГО РЯДА ПОДНЯТ 768 → 1100 (gbppl-sandbox-names-1).
   Имён в ряду стало два, и в полосе 768..1099 они вставали в одну
   строку с чипом, тегами, датой и стрелкой — шесть предметов на
   ~700px, где «Book a meeting form» переносился внутри своей ячейки и
   поднимал строку. Теперь ряд живёт ровно в двух видах: сложенный
   (страница с датой, под ней вариант, под ним мета) до 1100 и сетка
   с 1100, там же, где он и был сеткой. Одна ступень вместо двух. */
@media (min-width: 1100px) {
  .gbs-row { flex-wrap: nowrap; }
  .gbs-row__variant { order: 0; flex: 1 1 auto; }
  .gbs-row__meta { order: 1; flex: 0 1 auto; gap: var(--space-16); justify-content: flex-end; }
  .gbs-row__updated { order: 2; }
  .gbs-row .gbs-arrow { order: 3; }
}

/* Колонки. Меры в ch — это мера ТЕКСТА (тем же ch описание двери
   ограничено 60ch), а не длина со шкалы отступов: 20ch держит самое
   длинное имя страницы («Book a meeting form», 19 знаков), 12ch —
   самый длинный статус («in progress»), 10ch — самую длинную дату
   («3 weeks ago»). Колонка стрелки шириной ровно в ступень 24.
   Порядок колонок: страница, вариант, статус, теги, дата, стрелка
   (gbppl-sandbox-names-1; было имя варианта, чип страницы 18ch,
   статус, теги, дата, стрелка). */
@media (min-width: 1100px) {
  .gbs-row {
    display: grid;
    grid-template-columns: 20ch minmax(0, 1.2fr) 12ch minmax(0, 1fr) 10ch var(--space-24);
    align-items: center;
  }
  /* Полка сгруппирована страницей — колонки страницы нет вовсе, и
     имя варианта стоит первым. Один и тот же ряд в двух сетках,
     разметка при этом на одну ячейку короче: её не прячут, её не
     печатают. */
  .gbs-list--ingroup .gbs-row {
    grid-template-columns: minmax(0, 1.2fr) 12ch minmax(0, 1fr) 10ch var(--space-24);
  }
  /* Обёртка меты растворяется, и её три ячейки становятся колонками
     сами: на узком экране она нужна как строка, здесь — только как
     имя для группы. order у неё при этом перестаёт значить что-либо
     (у элемента с display: contents нет своего бокса), и порядок
     колонок задают DOM плюс order даты и стрелки. */
  .gbs-row__meta { display: contents; }
  .gbs-row .gbs-chip { justify-self: start; }
  .gbs-row__updated { justify-self: end; }
  .gbs-row .gbs-arrow { justify-self: end; }
}

/* Пусто после фильтра. Тот же голос лида полки. */
.gbs-empty {
  margin: var(--space-32) 0 0;
  font-size: 16px;
  line-height: 1.625;
  letter-spacing: 0.2px;
  color: var(--zinc-500);
}

/* ---- Табы страницы (gbppl-map-2, 28.08) ----
   Тон: «Вверху всего два таба: Website и Portal. Я не хочу скроллить
   далеко вниз, чтобы найти портал: переключиться на него сразу вверху.
   Завязать наш компонент табов и подумать, как красиво интегрировать
   его на страницу.»

   ТОН-6, ПЕРЕИСПОЛЬЗОВАНИЕ ПРЕЖДЕ РИСОВАНИЯ. Кнопка таба — это
   `.gbdoc-seg` из docs.css, тот же сегмент, что носят верстак кнопок в
   витрине и фильтры на sandboxes.html: прозрачная земля, 2px Blue 600
   под выбранным, свой переход на --mo-micro. Живой <gb-brand-tabs>
   (home.css) не подошёл и это записано: его таб — логотип LogoFont в
   PUA-лигатуре, а полоса под ним меряется по этим логотипам; текстового
   таба в нём нет вовсе.

   Здесь только РИТМ страницы, ни одного нового числа: кегль идёт по
   лестнице `.gbs-hub-sub` (18 → 20 с 1280), зазор и воздух — ступени
   шкалы, волосок — тот же Zinc 200, что у всех разделителей студии.
   Сегмент подрезан ровно в двух местах: свой правый отступ он отдаёт
   гриду полосы, а нижнюю кромку опускает на волосок, чтобы подчёркивание
   активного стояло НА линии, а не над ней. */
.gbs-tabs {
  display: flex;
  gap: var(--space-24);
  margin-top: var(--space-32);
  border-bottom: 1px solid var(--zinc-200);
}
.gbs-tabs .gbdoc-seg {
  margin-right: 0;
  margin-bottom: -1px;   /* NO TOKEN: подчёркивание садится на волосок полосы, это стык фигур, а не отступ (та же оговорка, что у наконечника стрелки пересечения) */
  padding: 0 0 var(--space-8);
  font-size: 18px;
  line-height: 1.625;
  letter-spacing: 0.2px;
}
@media (min-width: 1280px) { .gbs-tabs .gbdoc-seg { font-size: 20px; } }
/* Полка под табами и полка ПОСЛЕ вида дышат тем же зазором, каким полка
   отделена от полки: между ними теперь стоит панель вида, и правило
   `.gbs-shelf + .gbs-shelf` перестало их видеть. Числа те же. Сосед
   ОБЩИЙ (~), а не смежный: у второй панели вида слева стоит первая, и
   с `+` заголовок второго дерева садился на табы. */
.gbs-tabs ~ [role="tabpanel"] > .gbs-shelf,
[role="tabpanel"] + .gbs-shelf { margin-top: calc(var(--space-32) + var(--space-24)); }
@media (min-width: 1280px) {
  .gbs-tabs ~ [role="tabpanel"] > .gbs-shelf,
  [role="tabpanel"] + .gbs-shelf { margin-top: calc(var(--space-48) + var(--space-24)); }
}
/* Панель вида не рисует фокус-кольца вокруг всей страницы: она получает
   фокус только программно, с таба. */
[role="tabpanel"]:focus { outline: none; }


/* ============================================================
   ЧИП ОТКРЫТЫХ КОММЕНТАРИЕВ НА УЗЛЕ КАРТЫ (gbppl-map-3, 28.08)
   ------------------------------------------------------------
   Спека Comment mode, §4.3: «Карта live/map.html: у узла чип
   „N open“ из /api/comments/summary». Чип ведёт на ту же страницу
   в режиме Comment, то есть ссылок в узле стало ДВЕ, и узел-строка
   с адресом перешёл на тот же паттерн, каким живёт дверь хаба
   («КАРТОЧКА С РАСТЯНУТОЙ ССЫЛКОЙ» выше в этом файле): обёртка div,
   главная ссылка на имени с растянутой ::after, вторая ссылка над
   ней. Никогда a в a. Ховер и фокус переехали со ссылки на
   карточку, поэтому клавиатура видит то же, что мышь.

   ОКРАС ВЗЯТ СУЩЕСТВУЮЩИЙ, БАЗОВЫЙ .gbs-chip: плашка Zinc 100,
   чернила Eyebrow. Это ровно тот окрас, которым комментарий уже
   говорит на светлом грунте (.gbc-chip в дровере треда,
   comments.css). Blue 600 в этом ряду занят статусом ready и по
   Тон-5 значит состояние страницы; контуры (--expected, --tag)
   значат «ещё нет» и «ярлык» (плашка Zinc 900 .gbs-chip--page,
   которая стояла здесь третьей, снята с gbppl-sandbox-names-1
   вместе со своим бейджем). Нового окраса не заведено, и
   заметность чип берёт не цветом, а присутствием: он появляется
   только там, где счёт больше нуля.

   Ховер и кольцо фокуса — те же, что у чипа-мишени .gbs-tagbtn
   (чернила в Zinc 900, кольцо Blue 600 2px/2px). Приход — та же
   gbsNodeIn, которой приходит узел: счётчик приезжает ответом
   сервиса, уже после дерева, и появиться молча не может (Тон-7).

   Пара `a.gbs-node` выше по файлу осталась стоять и больше ни на
   что не смотрит: узлов-ссылок в разметке больше нет, все узлы
   стали div. Не снята нарочно: правка этой волны идёт только в
   конец файла; уберёт её ближайшая волна, которая и так
   открывает середину studio.css.
   ============================================================ */
.gbs-node--link:hover,
.gbs-node--link:focus-within { border-color: var(--zinc-900); box-shadow: var(--shadow-card); }

/* Растянутая главная ссылка. Цвет объявлен парой — ловушка 1. */
a.gbs-node__link,
body.gb-demo a.gbs-node__link { color: var(--zinc-900); text-decoration: none; }
.gbs-node__link::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--radius);
}

.gbs-node__open {
  position: relative;   /* над растянутой ::after имени */
  z-index: 1;
  animation: gbsNodeIn var(--mo-small) var(--mo-arrive) both;
  transition: color var(--mo-micro) var(--mo-move);
}
a.gbs-node__open,
body.gb-demo a.gbs-node__open { color: var(--eyebrow-color); text-decoration: none; }
a.gbs-node__open:hover,
body.gb-demo a.gbs-node__open:hover { color: var(--zinc-900); }
.gbs-node__open:focus-visible { outline: 2px solid var(--blue-600); outline-offset: 2px; }


/* ============================================================
   МАСТЕР-ДЕТАЛЬ НА ПОЛКЕ ПЕСОЧНИЦ (gbppl-sandbox-md-1,
   Тон 2026-08-31, вечер)
   ------------------------------------------------------------
   «Пересмотреть, как показываем проекты: проекты списком слева,
   нажимаешь на проект, справа его прототипы карточками. Фильтры
   сейчас как основной контент, слишком шумно: свернуть по дефолту
   (по умолчанию показывается всё), или открывать в дровере:
   подумать, что лучше.»

   ДВЕ ПРАВКИ ЗА ДЕНЬ, И ВТОРАЯ ОТМЕНЯЕТ ФОРМУ ПЕРВОЙ, НЕ ЕЁ МЫСЛЬ.
   Утром карточка перестала быть вариантом и стала проектом со
   строками прототипов внутри (gbppl-sandbox-projects-1). Вечером
   проект перестал быть карточкой вовсе: слева столбец проектов,
   справа прототипы ВЫБРАННОГО проекта карточками. Мысль та же
   («проект, внутри которого прототипы»), а форма — та, в которой
   проект не обязан помещаться в колонку 300px вместе со всем своим
   содержимым.

   ПОЧЕМУ РАЗВОРОТ НА МЕСТЕ, А НЕ ДРОВЕР (вторая половина заказа).
   Фильтров на полке два с половиной: вид, теги и сортировка. Дровер
   в этом доме — поверхность 520px с собственной шапкой, бэкдропом и
   запертым фокусом; открывать его ради девяти чипов значит уводить
   человека со страницы, чтобы он поставил галочку и вернулся.
   Разворот на месте стоит один клик и не отнимает контекста. Дровер
   ждёт своего дня: когда фильтров станет больше, чем помещается в
   одну развёрнутую полку, ответ поменяется, и поменяется он в этом
   же блоке.

   ГДЕ ЧИСЛА, И ОТКУДА ОНИ ВЗЯТЫ.
     столбец   256 = --space-64 * 4. Заказана вилка 240..280;
               ступеней ШИРИНЫ в системе нет вовсе, и 256 —
               единственное кратное шкале число внутри вилки (240 =
               --space-48 * 5 стоит у оглавления витрины, но там
               колонка ТЕКСТА, а здесь колонка ИМЁН: «Book a meeting
               form» базовым 16 просит 224 чистых, и 256 без 32
               полей даёт ровно их).
     зазор     --space-32 между столбцом и деталью.
     колонка   .gbs-wrap не тронут: 1080, как у всех студийных
     страницы  документов. Рельса со своим зазором съедает 288, и
               деталь получает 792 на 1280 и выше, 688 на 1024.
     карточки  ДВЕ колонки, не три. 792 на три карточки дают 253 —
               уже меры 301..336, на которой карточку принимали; на
               две выходит 388, и это ровно тот же предмет, что стоял
               на полке до сегодня. Своих порогов у сетки внутри
               детали ровно один (1024): общий порог .gbs-grid (1100)
               считает окно, а деталь уже окна на 288, и с 1100 он
               ставил бы те самые три колонки по 253.
     рельса    поля 12 / --space-16 (12 — тот же «плотнее блока»
               зазор, что стоял у строк внутри карточки), зазор 2px
               между пунктами — число .oro-nav витрины, скопировано,
               а не выведено.

   ПОДСВЕТКА АКТИВНОГО ПРОЕКТА = СЕМЬЯ РЕЛЬСЫ ORO, И ОНА НЕ СЕРАЯ.
   В брифе стояло «Zinc 100 плита или волосок слева»; у владельца
   (.oro-link, system/oro/oro.css) Zinc 100 — это ХОВЕР, а активный
   пункт носит Blue 50 на волоске Blue 200 чернилами Blue 700, и
   рядом с правилом стоит его обоснование: Тон-5 называет «активный
   пункт» поимённо, состояние говорит акцентом. Взята эта пара
   целиком, до веса 500 и до серого ховера под ней. Серый активный
   пункт спорил бы и с принципом, и с витриной, которая объясняет
   принцип двумя дверями отсюда.

   НА УЗКОМ РЕЛЬСА ЛОЖИТСЯ СТРОКОЙ, И ЭТО ТОЖЕ ГОТОВАЯ МЕХАНИКА.
   Лежачая версия взята у оглавления витрины (.oro-toc-list): ряд
   прокручивается ВНУТРИ СЕБЯ (overflow-x: auto, тонкий скроллбар —
   ряд, который прокручивается и не говорит об этом, это ряд, у
   которого последних пунктов не существует), пункты не переносятся.
   Подсветка в обоих положениях ОДНА И ТА ЖЕ плита: у оглавления
   лёжа подчёркивание, а стоя волосок слева, потому что там пункт —
   строка текста; здесь пункт — предмет с плитой, и две разные
   подсветки у одного объекта читались бы как два объекта.
   ============================================================ */

/* ---- Раскладка ---- */
.gbs-md { min-width: 0; }
@media (min-width: 1024px) {
  .gbs-md {
    display: grid;
    grid-template-columns: calc(var(--space-64) * 4) minmax(0, 1fr);
    gap: var(--space-32);
    align-items: start;
  }
}

/* ---- Столбец проектов ---- */
.gbs-md__master {
  display: flex;
  flex-direction: row;
  gap: var(--space-8);
  margin-bottom: var(--space-24);
  overflow-x: auto;
  scrollbar-width: thin;
  min-width: 0;
}
@media (min-width: 1024px) {
  .gbs-md__master {
    flex-direction: column;
    gap: 2px;   /* NO TOKEN: число .oro-nav, зазор между пунктами одной рельсы */
    margin-bottom: 0;
    /* Рельса остаётся на экране, пока едет деталь. Обе цифры — те
       же, что у оглавления витрины: низ студийного бара плюс поле
       контейнера. */
    position: sticky;
    top: calc(var(--header-h) + var(--space-24));
    max-height: calc(100vh - var(--header-h) - var(--space-24) * 2);
    overflow-x: visible;
    overflow-y: auto;
  }
}

/* Пункт рельсы. Метрика наша (базовая роль 16: Рассел, ничего мельче
   для главных имён страницы), окрас и состояние — .oro-link целиком.
   Пара a / body.gb-demo a обязательна: правило демо-грунта весит
   0-1-2 и одиночный класс проигрывает ему (ловушка 1). */
.gbs-plink {
  flex: 0 0 auto;
  display: flex;
  align-items: baseline;
  gap: var(--space-8);
  padding: 12px var(--space-16);   /* NO TOKEN на 12: тот же «плотнее блока» зазор, что у строк внутри карточек */
  border: 1px solid transparent;
  border-radius: var(--radius);
  font-size: 16px;
  line-height: 1.45;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color var(--mo-micro) var(--mo-move),
              border-color var(--mo-micro) var(--mo-move),
              color var(--mo-micro) var(--mo-move);
}
a.gbs-plink,
body.gb-demo a.gbs-plink { color: var(--zinc-700); }
a.gbs-plink:hover,
body.gb-demo a.gbs-plink:hover { background: var(--zinc-100); color: var(--zinc-900); }
.gbs-plink:focus-visible { outline: 2px solid var(--blue-600); outline-offset: 2px; }

a.gbs-plink[aria-current="page"],
body.gb-demo a.gbs-plink[aria-current="page"],
a.gbs-plink[aria-current="page"]:hover,
body.gb-demo a.gbs-plink[aria-current="page"]:hover {
  background: var(--blue-50);
  border-color: var(--blue-200);
  color: var(--blue-700);
  font-weight: 500;
}

/* Счётчик прототипов — тот же вторичный голос, что у счётчика в
   шапке проекта (14 / Zinc 400). Он считает ВИДИМЫЕ прототипы:
   когда стоит фильтр, число обязано совпадать с тем, что человек
   найдёт за пунктом. */
.gbs-plink__count {
  flex: 0 0 auto;
  margin-left: auto;
  font-size: 14px;
  letter-spacing: 0.2px;
  color: var(--zinc-400);
  font-variant-numeric: tabular-nums;
}
.gbs-plink__name { min-width: 0; }
@media (min-width: 1024px) {
  /* Стоя пункт может дышать в две строки: имя длиннее колонки
     бывает, и многоточие в рельсе прячет ровно то слово, ради
     которого в неё смотрят. */
  .gbs-plink { white-space: normal; }
}

/* ---- Правая половина ---- */
.gbs-md__detail { min-width: 0; }
/* Шапка проекта = .gbs-proj__head выше по файлу (заголовок слева,
   тихий счётчик справа), поэтому здесь только воздух под ней:
   сетка карточек несёт свой --space-24 сама, списку он объявлен. */
.gbs-md__detail .gbs-list { margin-top: var(--space-24); }
/* ВЫСОТЫ КАРТОЧЕК В ДЕТАЛИ РАВНЫ, И ЭТО НЕ ОТМЕНА УТРЕННЕГО РЕШЕНИЯ.
   Утром растяжку сняли с .gbs-grid, потому что карточки-ПРОЕКТЫ имели
   разный состав (один прототип против трёх) и ряд получал двести
   пикселей белой дыры. В детали стоят карточки одного проекта, состав
   у них один и тот же, и разница между ними — одна строка тегов;
   растянутые, они кладут ряды статуса и тегов на общую линию. Правило
   «высоты равны» (Тон 27.08) возвращается ровно туда, где предметы
   однотипны. */
.gbs-md .gbs-grid { align-items: stretch; }
@media (min-width: 1024px) { .gbs-md .gbs-grid { grid-template-columns: repeat(2, 1fr); } }
/* ТРИ КОЛОНКИ С 1600 (gbppl-cards-1). Колонка студии выросла до
   --container-max-lg, и деталь на 1600+ получает 1264..1312: на две
   колонки это 624..648 на карточку, плита, а не карточка. На три
   выходит 410..426, то есть «чуть шире» прежних 388 — ровно заказ.
   Порог = тот же клэмп контейнера, числа нового нет. На 1280..1599
   остаются две по 464..624. */
@media (min-width: 1600px) { .gbs-md .gbs-grid { grid-template-columns: repeat(3, 1fr); } }

/* ---- Карточка прототипа ----
   Это .gbs-door--box, то есть та же малая дверь, которой вариант и
   был до утра: белая на Zinc 200, ховер в Zinc 900 с тенью, каскад
   прихода, поля 20 / 24 с 1280. Модификатор добавляет ровно две
   вещи, которых у двери не было: ряд «имя и стрелка» и ряд «статус
   слева, даты справа». Второй — тот самый, на который Тон показал
   утром («дата должна быть вверху справа, где Proposal, только
   справа»), перенесённый со строки прототипа число в число. */
a.gbs-door--proto,
body.gb-demo a.gbs-door--proto { color: var(--zinc-900); text-decoration: none; }
a.gbs-door--proto:focus-visible { outline: 2px solid var(--blue-600); outline-offset: 2px; }

/* Заголовок карточки выравнивается со стрелкой по ЦЕНТРУ, а шапка
   проекта — по базовой линии: там встречаются два текста, здесь
   текст и глиф. Поэтому у ряда свой класс, а не .gbs-proj__head. */
.gbs-pcard__head {
  display: flex;
  align-items: center;
  gap: 12px;   /* NO TOKEN: тот же зазор внутри ряда, что у шапки проекта, половина ступени --space-24 */
}
.gbs-pcard__head .gbs-door-title { margin-top: 0; flex: 1 1 auto; min-width: 0; }
.gbs-pcard__head .gbs-arrow { flex: 0 0 auto; }

/* ============================================================
   МОДЕЛЬ КАРТОЧКИ ПРОТОТИПА (gbppl-cards-1, Тон 24.09, пакет владельца)
   ------------------------------------------------------------
   «Вся информация с карточки говорит»: (1) тип, Live или Sandbox;
   (2) чей ресурс и какая страница, Portal или Website + имя страницы;
   (3) версия и её короткое имя; (4) created и last edited; (5) метрики,
   число комментариев и метка новых. Плюс настоящий скриншот первого
   экрана сверху. Теги с карточки сняты, они живут в фильтре.

   ЧТО ВЗЯТО ГОТОВЫМ (Тон-6):
     тумб      .gbs-door-shot дверей хаба целиком (рамка Zinc 200,
               --radius, 16:10, cover от верха, земля Zinc 100);
     айбрау    .gbs-eyebrow студии (12 / 600 / 0.12em / Zinc 500);
     заголовок .gbs-door-title малой двери (роль колонки 22);
     счёт      глиф chat из icon.js (16) и .gbh-count header.css как
               метка новых, поставленная в строку (прецедент
               .gbppa-door .gbh-count в gift-approvals.html).
   Своего здесь только раскладка строк.

   ГОЛОСА (закон поверхности, Тон 10.09): ведущий = сериф 22 заголовка,
   рабочий = Inter 400 Zinc 500: описание 16 и тихая мета-строка 14
   (вторичная ступень той же роли, голос дат студии; ВОПРОС ТОНУ в
   отчёте волны, считать ли её третьим голосом), айбрау = тип, ресурс,
   страница и счёт комментариев. Бейдж новых — чип состояния, не текст.

   ОДНА СТРОКА = ОДНА СТРОКА. Айбрау, заголовок и мета не переносятся:
   многоточие и полная строка в title. Высоты карточек ряда от этого
   равны без подгонки, а длинное имя версии не ломает ряд.
   ============================================================ */
/* Ячейка сетки не растёт под свою самую длинную строку: без min-width 0
   однострочные айбрау, заголовок и мета раздвигали колонку 1fr по
   min-content и карточки вылезали за окно (замер 1280: 1347 против 1280). */
.gbs-door--proto { min-width: 0; }
.gbs-pcard__shot { flex: 0 0 auto; }
/* Айбрау отбит от тумба полем карточки (20 / 24 с 1280), как заголовок
   двери хаба от своего превью: картинку от текста отделяет та же мера,
   что текст от рамки. Дальше ритм карточки 12 «текст под текстом». */
.gbs-pcard__top {
  display: flex;
  align-items: center;
  gap: var(--space-16);
  margin-top: var(--gbs-card-padx);
}
.gbs-pcard__kind {
  flex: 1 1 auto;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.gbs-door--proto .gbs-pcard__head { margin-top: 12px; }   /* NO TOKEN: общий зазор «текст под текстом», см. шапку файла */
.gbs-door--proto .gbs-pcard__head .gbs-door-title {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Мета-строка: статус и даты одной тихой строкой, многоточие на узком.
   14 Zinc 500 = вторичный голос дат студии (.gbs-proj__count,
   .gbs-plink__count, дата строки списка): замер 1280, строки 323..352
   на 14 против 367..401 на 16 при колонке 414 и 363 у трёх колонок с
   1600. На 16 строка «created 25 Aug · updated 3 weeks ago» резалась
   на всех ширинах выше 1280, на 14 цела везде от 1280. */
.gbs-pcard__meta {
  display: flex;
  align-items: center;
  font-size: 14px;
  letter-spacing: 0.2px;
  color: var(--zinc-500);
  font-variant-numeric: tabular-nums;
}
.gbs-pcard__line {
  flex: 1 1 auto;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Счёт комментариев стоит справа в строке айбрау и говорит её голосом:
   в мета-строке рядом с датами он резал бы их на каждой ширине. Число
   не ужимается никогда. */
.gbs-pcard__comments {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: var(--space-8);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.gbs-pcard__comments[hidden] { display: none; }
/* Бейдж новых стоит В СТРОКЕ, а не в углу круга (у колокольчика он
   прибит к углу 44px). Больше ему не говорится ничего. */
.gbs-pcard__comments .gbh-count { position: static; }

/* Прототип, у которого комнаты ещё нет (ready:false в реестре).
   Тот же язык, что носила снятая .gbs-door--coming: земля Zinc 50,
   чернила тише, никакого обещания перехода. Пунктирной рамки нет —
   она обещала бы «скоро будет», а реестр говорит только «сегодня
   страница этого параметра не читает». */
.gbs-door--coming { background: var(--zinc-50); cursor: default; }
.gbs-door--coming:hover { border-color: var(--zinc-200); box-shadow: none; }
.gbs-door--coming .gbs-door-title,
.gbs-door--coming .gbs-door-desc { color: var(--zinc-400); }
.gbs-pcard__note {
  flex: 0 0 auto;
  font-size: 14px;
  color: var(--zinc-500);
  white-space: nowrap;
}

/* ---- Полка контролов, свёрнутая ----
   Видимой остаётся одна тихая строка: сортировка сегментами слева,
   кнопка Filters у правого края. Сортировка не спрятана вместе с
   фильтрами нарочно: она НЕ УБИРАЕТ со страницы ничего, а фильтр
   убирает, и вопрос «почему тут пусто» родится только у второго. */
.gbs-controls__bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-16);
}
/* Развёрнутая половина отбита от строки ступенью и волоском: без
   линии два ряда сегментов читаются как один длинный ряд, ровно тот
   шум, от которого волна и заводилась. */
.gbs-controls__panel {
  margin-top: var(--space-24);
  padding-top: var(--space-24);
  border-top: 1px solid var(--zinc-200);
}
.gbs-controls__panel[hidden] { display: none; }
/* Шеврон кнопки переворачивается, а не подменяется вторым глифом:
   один предмет в двух положениях. */
.gbs-filters .gb-btn__icon { transition: transform var(--mo-micro) var(--mo-move); }
.gbs-filters[aria-expanded="true"] .gb-btn__icon { transform: rotate(180deg); }
/* Чип внутри кнопки центрируется: .gbs-chip живёт в колонках
   карточек и потому по умолчанию прижат к началу оси. */
.gbs-filters .gbs-chip { align-self: center; }
/* display: inline-block у чипа перебивает браузерное [hidden]:
   счётчик без фильтров показывал «0» вместо того, чтобы исчезнуть. */
.gbs-chip[hidden] { display: none; }
/* Счёт активных фильтров = ВЫБОР, то есть состояние (Тон-5), и
   говорит он тем же Blue 600 с белыми чернилами, каким говорит
   выбранный чип-мишень .gbs-tagbtn.is-on. Нового окраса нет. */
.gbs-chip--on { background: var(--blue-600); color: var(--white); }

/* Строка активных фильтров при СВЁРНУТОЙ полке. Без неё человек
   закрывает панель, забывает про тег и не понимает, почему полка
   короткая. Развёрнутая панель эту строку не рисует: там те же чипы
   стоят зажжёнными в своём ряду, и печатать их дважды незачем. */
.gbs-filtered {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-8);
  margin: var(--space-16) 0 0;
  font-size: 14px;
  letter-spacing: 0.2px;
  color: var(--zinc-500);
}
.gbs-filtered[hidden] { display: none; }
