/* ============================================================
   gbppl-docs-1 / gbppl-oro-icons-1 / gbppl-oro-drawer-1 /
   gbppl-oro-props-1
   — THE DOCUMENTATION ATOMS
   ------------------------------------------------------------
   gbppl-oro-props-1 (29.08) took the corner caption «properties»
   and `cursor: pointer` off the specimen slots, and put a door in
   their place: an icon button in the corner of the box, hung by
   inspect.js, seen on hover and on focus. Ton could not click a
   field or open a Select, because the caption was the visible half
   of a click the instrument was eating. See THE DOOR TO THE
   PROPERTIES below.

   gbppl-oro-icons-1 (28.08) added exactly one line: an inline mode
   for the quiet copy button, so it can stand in a table cell
   instead of hanging in the corner of a type row.

   gbppl-oro-drawer-1 (28.08) added exactly one class, at the foot
   of this file: `.gbdoc-panel`, which takes the drawer panel out
   of the corner of the window so that it can be a specimen.
   Nothing else in this file moved.
   ------------------------------------------------------------
   THE GROUND RULE (gbppl-oro-heads-1, Ton 29.08: «продуманная
   информационная архитектура и осмысленная игра цветами фона...
   светло-серый фон, но не рандомно»):
   A LIVE SPECIMEN STANDS ON GREY WITH A ZINC 200 HAIRLINE.
   EVERYTHING YOU READ OR OPERATE STANDS ON WHITE.
   One value, one meaning: the grey says «this is the product, not
   the document», so a stage, a specimen shelf, a preview tile and a
   scene are grey, while prose, reading tables and the axis controls
   are white.

   TWO GREYS, AND THEY DO NOT DO THE SAME JOB (gbppl-oro-props-1,
   Ton 12:59: «что-то одно, либо управление, либо превью, должно
   быть не на белом... блок сливается со страницей»). ZINC 100 is
   the GROUND A SPECIMEN STANDS ON — stage, shelf, preview tile,
   scene — and it moved there from Zinc 50 for one reason: at
   #FAFAFA against #FFFFFF the ground was a rule nobody could see,
   which is the same as no rule. ZINC 50 is a TINT ON A STRIP
   INSIDE an object, never a surface of its own: the header row of a
   reading table, a column head, the cap of a do/avoid pair, and the
   line under a stage. So a playground block now reads as three
   parts without being read at all — white controls, grey specimen,
   quiet closing strip — and the specimen is the darkest and largest
   thing in it.

   AND THEN TON TURNED IT ROUND ON THE PLAYGROUND (gbppl-lab-f-2,
   29.08 14:55): «перепутаны цвета: панель должна быть серее, а
   превью белым; вся превью-панель должна выделяться на фоне
   простыни, возможно добавить elevation.»

   So on a BENCH OR SHOWCASE PLAYGROUND — a card that holds a
   control rail beside a live specimen — the two grounds swap:
   THE CONTROL RAIL IS ZINC 100 AND THE SCENE IS WHITE, and the
   card itself is lifted off the page with --shadow-card and its
   hairline. The reasoning holds either way round: one of the two
   halves has to be off white or the block dissolves into the
   sheet, and here it is the rail, because the specimen is the
   thing being judged and a white stage judges a component the way
   a white wall judges a picture.

   AND ON 02.09 THE TWO RULES BECAME ONE (gbppl-playground-polish-1).
   Ton, on the Variants frame of button.html: «всё наоборот,
   инверсивно: хедер, где табы, светлый, а на превью серый цвет, что
   совершенно неправильно.» The question left open in the report of
   29.08 is answered, and it is answered the way the bench answers
   it: A SPECIMEN ZONE IS WHITE, AN INSTRUMENT ZONE IS ZINC 100,
   everywhere, with no second dialect. So .gbdoc-stage, .gbdoc-shelf
   and .gbdoc-scene__stage went white and .gbdoc-controls went grey;
   the full argument stands at THE ZONE LAW, beside .gbdoc-controls.
   Registry thumbnails keep Zinc 100 and say why there.
   ------------------------------------------------------------
   Ton-10, 26.08: «дизайн-система показывается только системно:
   витрина должна быть образцом системности». The showcase is a
   CONSUMER of the system exactly like live/ is, so the furniture
   it is built from — the component card, the specimen shelf, the
   matrix, the reading table, the provenance plaque, the code
   block, the property table inside the drawer — cannot live as
   page-local CSS in components.html. It lives here, it is spent
   out of tokens, and any showcase page can wear it.

   WHAT WENT WHERE
     oro.css      the page shell: rail, column, contents, the
                  document type roles.
     docs.css     THIS FILE. The atoms a documentation page is
                  assembled from.
     components.html   markup and composition only. What is still
                  local there is two documented antidotes and
                  nothing else.

   NOT ONE LITERAL COLOUR, RADIUS OR CURVE. Spacing comes off the
   --space-8..64 scale (25.08), type off TYPE-SCALE roles: body
   16, small 14, and Eyebrow (12 / 600 / 0.12em) for every caps
   caption. The old page-local furniture had 10px and 11px caps
   labels and a 17px lede; both are gone. Russell, 08-10:
   «мелкий блеклый текст = я не важен».

   The one number here that is not a token is the 1180px reading
   column of a documentation page and the min-widths that keep a
   matrix from crushing its cells. Both are layout measures, and
   they are marked below.
   ============================================================ */

/* ============================================================
   THE CARD: one shape, repeated per component
   ============================================================ */
/* gbppl-oro-heads-1, Ton 29.08. A card is a section of a document and
   opens the way every other section opens: --space-64 of air, a Zinc 200
   hairline, --space-32 under it (--space-48 from 1280). Same three lines
   as .oro-section in oro.css, because on a page like Typography the two
   stand in one run and must not step differently. The first card on a
   page draws no rule: .oro-head already ended in one. */
.gbdoc-card {
  margin-top: var(--space-64);
  padding: var(--space-32) 0 0;
  border-top: 1px solid var(--zinc-200);
}
@media (min-width: 1280px) { .gbdoc-card { padding-top: var(--space-48); } }
.oro-head + .gbdoc-card { margin-top: 0; border-top: 0; }

.gbdoc-card__head { padding-bottom: var(--space-8); }
/* gbppl-oro-pages-1. A card that stands ALONE on its own page has no
   head of its own: the crumb over it already says the eyebrow, the
   name, the status and the line, and saying them twice on one screen
   is the «оторванный элемент» of Ton-1. Then the first section
   caption inherits the card's own 48 / 64 of air and adds 32 to it,
   which reads as a gap rather than a rhythm. Zeroed once, here at the
   owner, so every component page starts at the same distance from the
   rule as a card with a head does. */
.gbdoc-card > .gbdoc-sub:first-child,
.gbdoc-card > .oro-section:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.gbdoc-card__line {
  margin: var(--space-8) 0 0;
  font-size: var(--font-size-root);
  line-height: 1.6;
  color: var(--zinc-600);
}
/* THE CAPTION OVER A SECTION TITLE (gbppl-oro-heads-1, Ton 29.08:
   «Eyebrow никогда не может быть заголовком; он может идти вместе с
   заголовком, чтобы его объяснить»). It is still the eyebrow role and
   still one size for every caption on the page; what changed is that it
   no longer stands alone. On a page this wave rewrote, the caption is
   .gb-eyebrow inside a <section> and this class is gone; on a page it
   has not reached yet, the class survives and carries the section
   boundary itself, so the two kinds of page read the same. */
.gbdoc-sub {
  display: block;
  margin: var(--space-64) 0 0;
  padding-top: var(--space-32);
  border-top: 1px solid var(--zinc-200);
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  line-height: 1;
  text-transform: uppercase;
  color: var(--zinc-400);
}
@media (min-width: 1280px) { .gbdoc-sub { padding-top: var(--space-48); } }
/* The two places a caption is a caption and not a section head: the
   table view of the type scale, where the section is the card around it,
   and any run where it labels a block inside a section. */
.gbdoc-sub--plain { margin-top: var(--space-32); padding-top: 0; border-top: 0; }

/* ============================================================
   THE RHYTHM OF A SECTION — ONE RUNG (gbppl-playground-polish-1)
   ------------------------------------------------------------
   Ton, 02.09, on button.html: «текст сверху к полю прямо липнет.
   Отступов по секциям до сих пор нормальных нет.»

   He was right twice over. The bench card carried NO margin at
   all, so the paragraph that introduces it ended one line above
   its hairline and the two read as one object; and the other six
   objects of a documentation page each had their own idea of the
   air above them: a table 24, a matrix, a shelf, a frame and a
   code block 16, a stage 0. Six numbers for one relationship is
   not a rhythm, it is six patches.

   SO A SECTION HAS THREE STEPS AND EACH IS A RUNG OF THE SCALE:
     the caption to the title      12   (oro.css, the head)
     the title to the prose        18   (oro.css, .oro-p)
     the prose to the OBJECT       --space-32, here.

   The object step is the loudest because the object is the loudest
   thing in the section: a card, a table, a matrix, a stage. One
   rung above the paragraph rhythm, one rung below the 48 that opens
   a section, and it is spent by every one of them — .gbdoc-pg,
   .gbdoc-frame, .gbdoc-tablewrap, .gbdoc-matrix, .gbdoc-shelf,
   .gbdoc-stage and .gbdoc-code — so a reader who learns the
   distance once reads every section with it.

   THE TWO EXCEPTIONS, AND BOTH ARE NESTING. An object standing
   INSIDE another object is a zone rather than a block, and a zone
   parts from its neighbour with the frame's hairline, not with air
   (.gbdoc-frame > .gbdoc-stage, .gbdoc-pg__code .gbdoc-code). And
   the instrument's drawer keeps the tighter 16 it was built on: it
   is a panel, not a page, and its rhythm is drawer.css's business.
   ============================================================ */
.gbd-panel .gbdoc-code { margin-top: var(--space-16); }

/* THE THIRD EXCEPTION IS A NAMED OBJECT (gbppl-oro-h3-air-1; Ton,
   15.09: «в Table View криво заголовки над таблицами — отступы
   снизу и сверху... и вообще не читается как заголовки»). A small
   heading that opens an object was spending the object rung on the
   wrong side: .oro-h3 carries no margin of its own (oro.css), so
   the name stood glued to whatever came before it while the 32
   pushed its OWN table away from it — the group read as a footnote
   of the previous table. The air belongs above the name: a named
   object opens with the section breath over the heading, and the
   object tucks under its name. Only adjacency pays this, so a
   heading inside a composed card (the front page's rule cards)
   keeps its local rhythm. */
.oro-h3:has(+ .gbdoc-pg, + .gbdoc-frame, + .gbdoc-tablewrap, + .gbdoc-matrix, + .gbdoc-shelf, + .gbdoc-stage, + .gbdoc-code) { margin-top: var(--space-48); }
.oro-h3 + .gbdoc-pg,
.oro-h3 + .gbdoc-frame,
.oro-h3 + .gbdoc-tablewrap,
.oro-h3 + .gbdoc-matrix,
.oro-h3 + .gbdoc-shelf,
.oro-h3 + .gbdoc-stage,
.oro-h3 + .gbdoc-code { margin-top: var(--space-16); }

/* ---- The plaque: provenance, status, a flag on a value.
   Zinc, never colour: a provenance is a fact about the value, not
   a state of the interface (Ton-5). ---- */
.gbdoc-flag {
  display: inline-block;
  padding: 3px 7px;
  background: var(--zinc-100);
  border-radius: var(--radius);
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  line-height: 1.3;
  text-transform: uppercase;
  color: var(--zinc-600);
  white-space: nowrap;
}
.gbdoc-flag--declared { background: var(--zinc-900); color: var(--zinc-100); }
.gbdoc-flag--none { background: transparent; border: 1px solid var(--zinc-200); color: var(--zinc-400); }
/* gbppl-oro-typography-1: a fourth plaque. A button number had two
   provenances, live or declared. A type role has four, because the
   scale was read twice by two different instruments and a third of
   it exists only in the design file. Soft is the middle one: read
   off the running product by hand and not yet re-read by the
   pipeline. Lighter than the live plaque, darker than the empty
   one, and on the same eyebrow voice as both. */
.gbdoc-flag--soft { background: var(--white); border: 1px solid var(--zinc-200); color: var(--zinc-600); }
.gbdoc-status { margin-left: var(--space-8); vertical-align: middle; }

/* gbppl-oro-levels-1: the two colourings the CATALOGUE needs, and
   they are not invented here. The page map already says the same
   three things about a page (studio.css: .gbs-chip--ready blue,
   .gbs-chip zinc, .gbs-chip--expected outlined), so the catalogue
   says them about a component in exactly the same colours and
   under the same two names. One status language across the
   studio (Ton-10), not a second dialect on the showcase.
     ready     documented: the component has a card on the page
     the plain flag   built and running, no card yet
     expected  not in the system: the place is held by hand, by a
               native control, or by nothing at all
   Blue for documented is Ton-5: coverage is a STATE, and state
   speaks in the accent.
   THE OUTLINE IS AN INSET SHADOW, NOT A BORDER, for the map's own
   reason: these chips stand in a row beside the zinc one, which
   has no border, and a real border would make them 2px taller. */
.gbdoc-flag--ready { background: var(--blue-600); color: var(--white); }
.gbdoc-flag--expected {
  background: transparent;
  box-shadow: inset 0 0 0 1px var(--zinc-500);
  color: var(--zinc-500);
}

/* ============================================================
   THE REGISTRY: one card per component on a catalogue shelf
   ------------------------------------------------------------
   gbppl-oro-levels-1, Ton 28.08: «в дизайн-системе готово много
   компонентов, но витрины сделаны далеко не для всех, витрины
   пустуют». A shelf of these tells the truth about coverage at a
   glance: a preview tile, the name, the status chip and one line
   of purpose, plus the way in or the words «showcase pending».
   It replaces the flat «Documented soon» table, which could only
   list what exists and had no way of showing a hole.

   gbppl-oro-cards-1, Ton 28.08: «сложно ли показывать превью
   компонента в квадратике вместо тонн текста? Я не хочу читать
   текст. Там, где ты мне листишь компоненты, миллиард текста, от
   которого эпилепсия. Вместо этого лучше превью показывать.» So
   the owner, the list of pages and the long description LEFT THE
   CARD. They are not lost: they ride in data-oro-* on the article,
   in the title of the tile, and in the drawer the tile opens.
   What is left on the face of a card is a picture and one line.

   240 is not a token: it is the same layout measure
   .gbdoc-slot--grow already uses in this file for a specimen that
   has to share a row. Everything else is off the --space scale,
   and the type is TYPE-SCALE: body 16 for the name, small 14
   under it.
   ============================================================ */
.gbdoc-reg {
  /* THE ONE NEW LENGTH OF THIS WAVE, and it is built out of the
     scale rather than typed: 64 + 64 + 32. It has to hold a live
     specimen at its NATURAL size with air around it (an L button
     is 48, a field with its caps label is about 70, the six cells
     of a code are 48) so nothing has to be scaled down to fit,
     and it has to letterbox a page snapshot at about 2 to 1, the
     shape a frame of a page reads in. 120 would clip the field
     and squeeze a snapshot to 3 to 1; 192 would push the name of
     the fourth row under the fold on a laptop. */
  --gbdoc-preview-h: calc(var(--space-64) * 2 + var(--space-32));

  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: var(--space-16);
  margin-top: var(--space-24);
}

/* A LEVEL IS AN EYEBROW OVER A ROW, not a shelf with a heading and a
   paragraph (gbppl-oro-cards-1, Ton 28.08 on where the Components
   section is going). It takes the full width of the grid, so the row
   under it starts clean, and it is the Eyebrow role and nothing else:
   the name of a level is a caption, not a title. 48 is the step on
   the scale that reads as «a new group» beside a 16 gap between
   cards; the first one takes no air, the grid has its own. */
/* gbppl-oro-heads-1. The level was an <h2> wearing the eyebrow role,
   which is the one thing Ton ruled out on 29.08: it now wears .oro-h2
   in the markup and opens its run of cards the way a section opens
   anywhere else on the showcase, hairline and all. The pair of
   selectors is two classes deep on purpose: oro.css loads after this
   file, so a single class would lose its margin to .oro-h2's own. */
.gbdoc-reg > .gbdoc-reg__group {
  grid-column: 1 / -1;
  margin: var(--space-64) 0 0;
  padding-top: var(--space-32);
  border-top: 1px solid var(--zinc-200);
  scroll-margin-top: var(--space-24);
}
@media (min-width: 1280px) { .gbdoc-reg > .gbdoc-reg__group { padding-top: var(--space-48); } }
.gbdoc-reg > .gbdoc-reg__group:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.gbdoc-regcard {
  display: flex;
  flex-direction: column;
  gap: var(--space-8);
  padding: var(--space-16);
  background: var(--white);
  border: 1px solid var(--zinc-200);
  border-radius: var(--radius);
}
.gbdoc-regcard__name {
  margin: 0;
  font-size: var(--font-size-root);
  font-weight: 600;
  line-height: 1.4;
  color: var(--zinc-900);
}
.gbdoc-regcard__name .gbdoc-flag { margin-left: var(--space-8); vertical-align: 2px; }
.gbdoc-regcard__line {
  margin: 0;
  font-size: 14px;
  line-height: 1.6;
  color: var(--zinc-600);
}
/* The way in sits on the floor of the card whatever the card above
   it does, so a shelf of cards has one line of exits. */
.gbdoc-regcard__go {
  margin-top: auto;
  padding-top: var(--space-8);
  font-size: 14px;
  line-height: 1.6;
  color: var(--blue-700);
}
.gbdoc-regcard__go:hover { color: var(--blue-600); }
/* No card, no link: the same line in the quiet voice, so the row
   of exits still reads as a row. */
.gbdoc-regcard__go--none { color: var(--zinc-400); }

/* ---- THE PREVIEW TILE (gbppl-oro-cards-1) -------------------
   The tile is a .gbdoc-slot as well, which is what makes it a
   specimen the inspector already knows how to pick up: the shelf
   carries data-inspect and the click opens the drawer with the
   registry entry behind this card. The two class selector is
   deliberate: .gbdoc-slot is declared further down this file and
   would otherwise win the properties they share.

   THE TILE IS A PICTURE, NOT A CONTROL. Whatever stands in it is
   real markup from the real component, so the shelf cannot drift
   from the system, but it does not answer the pointer, does not
   take the tab and is not read out: pointer-events none on the
   contents, tabindex -1 on anything focusable, aria-hidden on the
   specimen and one aria-label on the tile instead. */
.gbdoc-regcard > .gbdoc-regcard__preview {
  display: grid;
  place-items: center;
  gap: 0;
  width: 100%;
  height: var(--gbdoc-preview-h);
  padding: var(--space-16);
  overflow: hidden;
  background: var(--zinc-100);   /* the specimen ground, see THE GROUND RULE */
  border: 1px solid var(--zinc-200);
  border-radius: var(--radius);
  cursor: pointer;
}
.gbdoc-regcard__preview > * { max-width: 100%; }
.gbdoc-regcard__preview * { pointer-events: none; }

/* A frame of the page a composite component stands on: the picture
   fills the tile edge to edge, because a snapshot with a margin
   round it reads as a screenshot pasted into a card rather than a
   window onto the page. */
.gbdoc-regcard__preview--frame { padding: 0; background: var(--white); }
.gbdoc-regcard__preview--frame img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
}

/* A hole in the catalogue gets an empty tile: dashed, nothing in
   it, and the eyebrow saying so once. The dash is the same signal
   the map uses for a page that does not exist yet. */
.gbdoc-regcard__preview--none {
  background: transparent;
  border-style: dashed;
  border-color: var(--zinc-300);
}

/* ---- how a specimen stands inside the tile ---- */
.gbdoc-regcard__spec { display: flex; align-items: center; justify-content: center; }
.gbdoc-regcard__spec--row { gap: var(--space-16); }
.gbdoc-regcard__spec--wrap { flex-wrap: wrap; gap: var(--space-8); }
.gbdoc-regcard__spec--full { display: block; width: 100%; }
.gbdoc-regcard__spec--stack { flex-direction: column; width: 100%; gap: var(--space-16); }
.gbdoc-regcard__spec--floor { align-items: flex-end; }
.gbdoc-regcard__spec--band { width: 100%; gap: 0; }

/* ---- the schematics: foundations drawn out of their own values ----
   Not pictures of the tokens: the tokens themselves, spent. --sw,
   --sq, --dur and --curve are handed in from the markup as var()
   references, never as literals, so a token that moves moves the
   preview with it. */
.gbdoc-regcard__sw { flex: 1 1 0; height: var(--space-48); background: var(--sw); }
.gbdoc-regcard__plate {
  width: var(--space-32);
  height: var(--space-32);
  border-radius: var(--radius);
  background: var(--sw);
}
.gbdoc-regcard__plate--lift { box-shadow: var(--shadow-card); }
.gbdoc-regcard__sq { width: var(--sq); height: var(--sq); background: var(--zinc-300); }

/* The clock shown as the clock: four dots, each one travelling for
   its own duration on its own curve. Ton-7, the house motion plays
   and is not branched away. */
.gbdoc-regcard__track {
  position: relative;
  width: 100%;
  height: var(--space-8);
  border-radius: var(--radius-circle);
  background: var(--zinc-200);
}
.gbdoc-regcard__track i {
  position: absolute;
  top: 0;
  left: 0;
  width: var(--space-8);
  height: var(--space-8);
  border-radius: var(--radius-circle);
  background: var(--blue-600);
  animation: gbdoc-mo-run var(--dur) var(--curve) infinite alternate;
}
@keyframes gbdoc-mo-run {
  from { left: 0; }
  to   { left: calc(100% - var(--space-8)); }
}

/* ============================================================
   THE READING TABLE
   ============================================================ */
/* A READING TABLE IS AN OBJECT ON THE PAGE (gbppl-oro-props-1, Ton
   12:59: «таблиц много и они сливаются с полотном»). The outline
   and the radius belong to the WRAP and not to the table, for a
   reason that shows the moment a table is wider than the column:
   the wrap is what scrolls, so a border on the table scrolled away
   with it and the object lost its right-hand edge exactly when it
   most needed one. The step of air above it is THE RHYTHM OF A
   SECTION, the one rung every object of the documentation spends
   (see the block at the foot of this group). */
.gbdoc-tablewrap {
  overflow-x: auto;
  margin-top: var(--space-32);
  background: var(--white);
  border: 1px solid var(--zinc-200);
  border-radius: var(--radius);
}
.gbdoc-table {
  width: 100%;
  border: 1px solid var(--zinc-200);
  border-radius: var(--radius);
  border-collapse: separate;
  border-spacing: 0;
  background: var(--white);
  font-size: 14px;          /* TYPE-SCALE: Small 14 */
  line-height: 1.6;
  color: var(--zinc-700);
}
/* Inside a wrap the outline is the wrap's, or the two would draw
   twice. A table with no wrap — the one inspect.js writes into the
   drawer, and the two on components.html — keeps its own and reads
   exactly as it did. */
.gbdoc-tablewrap > .gbdoc-table { border: 0; border-radius: 0; }
.gbdoc-table th,
.gbdoc-table td {
  padding: var(--space-8) var(--space-16);
  text-align: left;
  vertical-align: top;
  border-top: 1px solid var(--zinc-200);
}
.gbdoc-table thead th {
  border-top: 0;
  background: var(--zinc-50);
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--zinc-500);
}
.gbdoc-table td:first-child,
.gbdoc-table th:first-child { font-weight: 600; color: var(--zinc-900); }
.gbdoc-table td b { font-weight: 600; color: var(--zinc-900); }
.gbdoc-num { font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Monospace is the one family outside BRAND.md, and it is here
   for the same reason the browser has one: code is not prose. */
.gbdoc-table code,
.gbdoc-code code,
.gbdoc-chip {
  font-family: ui-monospace, 'Cascadia Mono', 'Segoe UI Mono', monospace;
  font-size: 14px;
  color: var(--zinc-900);
}

/* ============================================================
   THE CODE BLOCK
   ============================================================ */
.gbdoc-code {
  position: relative;
  margin-top: var(--space-32);   /* THE RHYTHM OF A SECTION, see below */
  border: 1px solid var(--zinc-950);
  border-radius: var(--radius);
  background: var(--zinc-950);
  overflow: hidden;
}
.gbdoc-code pre {
  margin: 0;
  padding: var(--space-16) var(--space-64) var(--space-16) var(--space-16);
  overflow-x: auto;
  font-family: ui-monospace, 'Cascadia Mono', 'Segoe UI Mono', monospace;
  font-size: 14px;
  line-height: 1.7;
  color: var(--zinc-100);
  white-space: pre;
}
.gbdoc-code pre code { color: inherit; font-size: inherit; }
.gbdoc-copy {
  position: absolute;
  top: var(--space-8);
  right: var(--space-8);
  padding: 5px 10px;
  background: var(--zinc-800);
  border: 1px solid var(--zinc-700);
  border-radius: var(--radius);
  font-family: var(--font-sans);
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--zinc-300);
  cursor: pointer;
  transition: color var(--mo-micro) var(--mo-move), background-color var(--mo-micro) var(--mo-move);
}
.gbdoc-copy:hover { background: var(--zinc-700); color: var(--white); }

/* ============================================================
   THE FRAME: controls over a stage
   ------------------------------------------------------------
   One anatomy serves both interactive blocks on a component
   card: the playground, where the chips build a specimen, and
   the variant workbench, where the chips choose which variant
   the stage is showing. Storybook does the same thing with one
   canvas and one controls panel, and so does Carbon.
   ============================================================ */
.gbdoc-frame {
  margin-top: var(--space-32);   /* THE RHYTHM OF A SECTION, see below */
  border: 1px solid var(--zinc-200);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--white);
}
/* THE ZONE LAW, AND IT IS ONE LAW EVERYWHERE (gbppl-playground-polish-1,
   Ton 02.09: «ниже, где матрица Variants, всё наоборот, инверсивно:
   хедер, где табы, светлый, а на превью серый цвет, что совершенно
   неправильно»).

   Two zones, two grounds, and the SAME two on the bench and on the
   frame, because a reader who has just learned the bench must not
   have to unlearn it eight hundred pixels further down:

     THE SPECIMEN ZONE IS WHITE. The stage of a frame, the scene of
     the bench, a specimen shelf. A white wall judges a picture.
     THE INSTRUMENT ZONE IS ZINC 100. The rail of the bench, the
     control strip of a frame. One step of grey, no accent.

   This is Ton's own turn of 29.08 on the bench (gbppl-lab-f-2:
   «панель должна быть серее, а превью белым»), applied to the other
   half of the house, which had been left the way round props-1 set
   it. THE GROUND RULE at the head of this file records both sides of
   the argument; what this wave settles is that there is only one
   answer and every block gives it. Registry thumbnails keep Zinc 100:
   a tile in a catalogue is a picture of a page, not a zone of a
   bench, and it has no instrument beside it to be told apart from. */
.gbdoc-controls {
  padding: var(--space-16) var(--space-24);
  background: var(--gbdoc-pg-rail-ground);
  border-bottom: 1px solid var(--zinc-200);
}
.gbdoc-axis { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-8); }
/* An axis is allowed to disappear (gbppl-sandbox-projects-1: the shelf
   of sandboxes hides Group in the cards view, where the card already
   IS the group). Without this line the atom's own `display: flex`
   beats the [hidden] attribute, and the axis stays on screen while
   the page believes it is gone. Any atom that declares a display owes
   its consumers this line. */
.gbdoc-axis[hidden] { display: none; }
.gbdoc-axis + .gbdoc-axis { margin-top: var(--space-8); }
/* An axis standing on the page itself rather than on the grey band
   of a frame: it switches between two VIEWS of a section instead of
   driving one stage. (gbppl-oro-typography-2) */
.gbdoc-axis--bare { margin-top: var(--space-24); }
.gbdoc-axis__name {
  flex: 0 0 72px;
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--zinc-500);
}

/* ============================================================
   SEGMENT CONTROL — the instrument of the documentation
   ------------------------------------------------------------
   Ton 26.08: «the top buttons work as a showcase while they are meant
   to build the button below; it reads double». Mature systems give
   their controls a different voice from the component they drive
   (Storybook controls, Material form switches). So a segment is quiet
   text with a hairline under the row and a blue underline on the chosen
   one: chosen is a state, and state is blue (Ton-5). No fill, no frame,
   nothing that could be mistaken for a button.
   ============================================================ */
.gbdoc-seg {
  appearance: none;
  border: 0;
  background: transparent;
  padding: 6px 2px;
  margin-right: var(--space-16);
  font: inherit;
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.2px;
  line-height: 1.4;
  color: var(--zinc-500);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  transition: color var(--mo-micro) var(--mo-move), border-color var(--mo-micro) var(--mo-move);
}
.gbdoc-seg:hover { color: var(--zinc-900); }
.gbdoc-seg.is-on { color: var(--blue-600); border-bottom-color: var(--blue-600); }
.gbdoc-seg:focus-visible { outline: 2px solid var(--blue-600); outline-offset: 2px; border-radius: 2px; }
.gbdoc-axis .gbdoc-seg.is-unavailable { opacity: 0.4; pointer-events: none; }

/* A chip for a combination the system does not hold. Shown, not
   hidden: a rule nobody can see is a rule nobody learns. */
.gbdoc-axis .is-unavailable { opacity: 0.4; pointer-events: none; }

.gbdoc-stage {
  margin-top: var(--space-32);   /* THE RHYTHM OF A SECTION, see below */
  padding: var(--space-24);
  background: var(--white);      /* the specimen zone, see THE ZONE LAW */
  transition: background-color var(--mo-small) var(--mo-move);
}
/* Inside a frame the stage is a zone, not a block of the document:
   the frame's own hairline is the parting, and a margin here would
   open a white gutter between the two zones. */
.gbdoc-frame > .gbdoc-stage { margin-top: 0; }
.gbdoc-stage--center { display: flex; align-items: center; justify-content: center; min-height: 176px; padding: var(--space-32); }
.gbdoc-stage--dark { background: var(--zinc-950); }
/* The line under a stage is read, not shown: white. */
.gbdoc-foot {
  margin: 0;
  padding: var(--space-16);
  background: var(--zinc-50);
  border-top: 1px solid var(--zinc-200);
  font-size: 14px;
  line-height: 1.7;
  color: var(--zinc-600);
}
/* A strip with nothing to say is not drawn. The line under a stage
   exists for the sentence a reader cannot get from the stage — the
   combination the system does not hold, the reason a chip went
   quiet — and Ton-21 already threw out the version of it that
   repeated the chips above («On the stage: Underline, rest»). An
   empty foot with a hairline over it would be that sentence's
   furniture standing without the sentence. */
.gbdoc-foot:empty { display: none; }

/* ---- A band inside a stage: sizes, then states ---- */
.gbdoc-band + .gbdoc-band {
  margin-top: var(--space-24);
  padding-top: var(--space-24);
  border-top: 1px solid var(--zinc-200);
}
.gbdoc-stage--dark .gbdoc-band + .gbdoc-band { border-top-color: var(--zinc-800); }
.gbdoc-band__cap {
  display: block;
  margin-bottom: var(--space-16);
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--zinc-500);
}
.gbdoc-stage--dark .gbdoc-band__cap { color: var(--zinc-400); }

/* TRAP 3, ANSWERED WHERE THE SPECIMENS STAND (gbppl-oro-heads-1).
   .gba-input names a border COLOUR on four sides and a WIDTH on one,
   and leans on the live bundle's preflight for «solid, zero» on the
   other three. Off that page the browser default comes back and the
   field is drawn as a full inset box: Ton caught exactly one specimen
   like that, the typed field beside the picked select on select.html,
   because that page's own antidote covered select.gba-input and not
   input.gba-input. Every specimen surface in this file answers for it
   once, so no showcase has to remember. The permanent home is
   auth.css; it is open on another wave's desk this hour. */
.gbdoc-slot .gba-input,
.gbdoc-cell .gba-input,
.gbdoc-hold .gba-input,
.gbdoc-shelf .gba-input,
.gbdoc-stage .gba-input,
.gbdoc-scene .gba-input {
  border-style: solid;
  border-width: 0;
  border-bottom-width: 1px;
}

/* ---- The specimen row and its slots ---- */
.gbdoc-row { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--space-24); }
.gbdoc-slot { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-8); }
.gbdoc-slot--grow { flex: 1 1 240px; min-width: 220px; }
.gbdoc-slot__cap { font-size: 14px; line-height: 1.5; color: var(--zinc-500); font-variant-numeric: tabular-nums; }
.gbdoc-slot__cap b {
  display: block;
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--zinc-900);
}
.gbdoc-stage--dark .gbdoc-slot__cap { color: var(--zinc-400); }
.gbdoc-stage--dark .gbdoc-slot__cap b { color: var(--zinc-100); }

/* ---- The plain shelf: single specimens on the specimen ground ---- */
.gbdoc-shelf {
  margin-top: var(--space-32);   /* THE RHYTHM OF A SECTION, see below */
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-24);
  padding: var(--space-24);
  border: 1px solid var(--zinc-200);
  border-radius: var(--radius);
  background: var(--white);      /* the specimen zone, see THE ZONE LAW */
}
.gbdoc-shelf--cols { align-items: stretch; }

/* ---- gbppl-oro-typography-1: the furniture a type page needs ----
   A size ladder is read DOWN, not across: a 52px title and an 11px
   label cannot share a row of a wrapping shelf, and the step
   between two roles is the whole point of showing them together.
   So the shelf gets a stacked mode, the slot gets a full row, and
   the sample line itself gets a class, because a specimen of a
   type role is a line of text and nothing else.

   The sample carries NO type of its own on purpose. Its size,
   weight, line height, tracking and case come either from the
   class the role wears or, for a role the system has no class for
   yet, from the recorded ladder set inline by the page. A default
   here would be a role nobody declared. */
.gbdoc-shelf--stack { flex-direction: column; align-items: stretch; gap: var(--space-24); }
.gbdoc-slot--wide { width: 100%; }
.gbdoc-sample { margin: 0; color: var(--zinc-900); }

/* The page block of a specimen: roles in the order a page uses
   them, at one spacing step, so what the eye compares is the type
   and not a layout. */
.gbdoc-page { max-width: 720px; }
.gbdoc-page > * + * { margin-top: var(--space-16); }

/* ============================================================
   THE MATRIX
   ------------------------------------------------------------
   Rows are one axis, columns another, and every cell is a real
   component. Used for ONE question at a time — the icon slots
   against the size ladder — never for every variant against
   every state: that wall is the thing Ton sent back, and none of
   the mature systems draws one either.
   ============================================================ */
.gbdoc-matrix {
  margin-top: var(--space-32);   /* THE RHYTHM OF A SECTION, see below */
  border: 1px solid var(--zinc-200);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--white);
}
.gbdoc-scroll { overflow-x: auto; }
.gbdoc-grid { display: grid; align-items: center; }
/* LAYOUT MEASURE: the min widths below are the narrowest a cell
   can be before a button starts wrapping its own label. */
.gbdoc-grid--icons { grid-template-columns: 190px repeat(3, minmax(230px, 1fr)); min-width: 880px; }
.gbdoc-grid > * { padding: var(--space-16); border-top: 1px solid var(--zinc-200); }
.gbdoc-grid--icons > :nth-child(-n + 4) { border-top: 0; }
.gbdoc-colhead {
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--zinc-500);
  background: var(--zinc-50);
}
.gbdoc-rowhead { font-size: 14px; font-weight: 600; line-height: 1.4; color: var(--zinc-900); }
.gbdoc-rowhead small { display: block; margin-top: 3px; font-size: 14px; font-weight: 400; color: var(--zinc-500); }
.gbdoc-cell { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-16); }

/* ============================================================
   THE DOOR TO THE PROPERTIES (gbppl-oro-props-1, 29.08)
   ------------------------------------------------------------
   Тон, 12:34, со скрином: «Мне очень не нравится, как работает
   Properties. Я не могу кликнуть на field... Select не
   открывается, потому что вместо этого открывается Properties.
   Оно должно показываться иначе, не перекрывая действия
   компонентов.»

   What stood here was the corner caption «properties» plus
   `cursor: pointer` on the whole slot, and behind them a click
   handler that took the click away from the specimen. Both are
   gone. A specimen is a live component and it answers the pointer
   the way it does in the product; the drawer is opened by a door
   of its own, hung by inspect.js on every slot of every region.

   PERMANENT, ON THE CAPTION (gbppl-oro-door-1, 09.09). Ton, with two
   screenshots: «функционал выглядит ужасающе, нужно переделать»,
   the glyph lying across the E of MOBILE on the toggle and a mile to
   the right of the large row of the size matrix, on the tail of its
   measured caption. Two things were wrong and they were one thing:
   the door hung INSIDE the specimen's box and was pinned to the top
   right of it, so a box that hugged a control put it on the control,
   a box as wide as a shelf put it at the far end of the caption, and
   a box smaller than the button put it outside on the left. 65 of the
   107 doors on the eight engine pages overlapped something, measured.

   The mark now stands at the START of the line that names the
   specimen, which is the one place on a showcase that is never the
   component, never moves and is in the same spot on every page: the
   left edge of the caption. Where a specimen has no caption the
   engine makes one, and where a specimen stands alone on a canvas
   the mark takes the corner of the CANVAS, which centres its exhibit
   inside its own padding and has nothing in that corner by
   construction. inspect.js chooses between the four; this file
   dresses them.

   AND IT IS NOT THE ICON BUTTON ANY MORE. The button organism has no
   rung under 40px and a caption line is 18 tall, so an icon button
   on it would set the height of the line and move the page. What a
   quiet glyph on a line of documentation IS, in this house, is the
   copy mark five hundred lines below: 16px, Zinc 400, ink on hover,
   the standard focus ring. The door is its sibling, written in the
   same values, and both belong to the documentation rather than to
   the product.

   NO HOVER REVEAL. It faded in on approach so that forty doors would
   not compete with the things they belong to; on a caption there is
   nothing to compete with, and a mark that is always there is a mark
   a reader can find without discovering it first.
   ============================================================ */
[data-inspect] .gbdoc-slot,
[data-inspect] .gbdoc-cell,
[data-inspect] .gbdoc-hold,
[data-inspect] .gbdoc-type__live {
  position: relative;
  border-radius: var(--radius);
}

.gbdoc-props {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--zinc-400);
  cursor: pointer;
  vertical-align: -3px;               /* the 16 glyph on the 12 eyebrow line */
  transition: color var(--mo-micro) var(--mo-move);
}
.gbdoc-props svg { display: block; width: 16px; height: 16px; }
.gbdoc-props:hover { color: var(--zinc-900); }
.gbdoc-props:focus-visible {
  color: var(--zinc-900);
  outline: 2px solid var(--blue-600);
  outline-offset: 2px;
}

/* ON A CAPTION. The mark reads before the words, and the words keep
   their own line: one rung of air and nothing else. */
.gbdoc-slot__cap > .gbdoc-props,
.gbdoc-slot__cap b > .gbdoc-props,
.gbdoc-type__name > .gbdoc-props {
  margin-right: var(--space-8);
  /* AND IT DOES NOT SET THE HEIGHT OF THE LINE IT STANDS ON. A 16px
     atomic box dropped 3px below the baseline grew the 21px line of a
     type row by three pixels, times forty six rows: measured, and the
     one thing this wave was told not to do is move the page. The
     margin box is pulled back inside the line and the glyph paints
     over it, the way a marker does. */
  margin-block: -3px;
}

/* THE CAPTION A SPECIMEN DID NOT HAVE. A matrix cell holds a control
   and nothing else, so the engine gives it the line every other
   specimen already has, with the mark alone on it. Full width, so it
   wraps under the specimen in the cell's own flex row rather than
   standing beside it. */
.gbdoc-slot__cap--door {
  display: block;
  flex-basis: 100%;
  width: 100%;
  line-height: 1;
}

/* ON A CANVAS. A stage or a playground scene centres one exhibit
   inside its padding: the corner is empty, so the mark takes it and
   costs the canvas no layout at all. */
.gbdoc-stage:has(> .gbdoc-props) { position: relative; }
.gbdoc-stage > .gbdoc-props,
.gbdoc-pg__scene > .gbdoc-props {
  position: absolute;
  top: var(--space-8);
  left: var(--space-8);
  z-index: 2;
  vertical-align: baseline;
}

/* THE TWO DARK SURFACES OF THE SHOWCASE dress their captions here
   already (the stage a few hundred lines up, the canvas in the
   playground block below), so the mark on them is dressed in the
   same place and inspect.js no longer measures a ground to decide. */
.gbdoc-stage--dark .gbdoc-props,
.gbdoc-pg__view.is-dark .gbdoc-props { color: var(--zinc-500); }
.gbdoc-stage--dark .gbdoc-props:hover,
.gbdoc-stage--dark .gbdoc-props:focus-visible,
.gbdoc-pg__view.is-dark .gbdoc-props:hover,
.gbdoc-pg__view.is-dark .gbdoc-props:focus-visible { color: var(--white); }

/* INSPECT HAS ITS OWN WAY IN. There the click is the question and
   every element on the page answers it, so a door would be one
   more thing standing between the pointer and the page. */
html.gbi-on .gbdoc-props,
html.gbc-on .gbdoc-props { display: none; }

/* THE ONE REGION THAT IS NOT A SHELF OF SPECIMENS (gbppl-oro-pages-1).
   Тон, 28.08: «Показывать плавающую кнопку Properties, которая
   открывает Drawer, на карточках компонентов нужно только внутри
   самих компонентов. В превью и вообще где-либо ещё её быть не
   должно.» A tile on the catalogue is a PICTURE OF A COMPONENT and
   the thing to do with it is open that component's page. It is
   given no door: the kind says `inViewMode: false` and inspect.js
   reads that before it hangs one. Nothing is needed here any more —
   the caption this used to have to cancel no longer exists. */

/* THE WHOLE CARD IS THE WAY IN. The same pattern the studio door uses
   (studio.css): the card is the positioned box, the exit link spreads
   an invisible ::after over it, and nothing is ever an a inside an a.
   A card with no page to go to carries a span instead of a link, so
   it stays exactly as inert as it reads. */
.gbdoc-regcard { position: relative; }
.gbdoc-regcard__go[href]::after { content: ''; position: absolute; inset: 0; border-radius: var(--radius); }
/* And it stands DOWN in Inspect mode. The sheet over the card is what
   makes the card a door, but under the instrument it would be the only
   thing the pointer ever finds, and the tile behind it is exactly what
   a reader is pointing at. html.gbi-on is set by inspect.js on the
   root for the length of the mode, and comments.js sets html.gbc-on
   the same way: a pin belongs to the tile it is pointing at, not to
   the sheet over it. */
html.gbi-on .gbdoc-regcard__go[href]::after,
html.gbc-on .gbdoc-regcard__go[href]::after { pointer-events: none; }

.gbdoc-hold { display: flex; justify-content: center; max-width: 100%; }
.gbdoc-hold--block { width: 100%; max-width: 420px; }

/* ---- What the drawer body is made of ---- */
.gbdoc-cap {
  display: block;
  margin: var(--space-24) 0 var(--space-8);
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--zinc-400);
}
.gbdoc-cap:first-child { margin-top: 0; }
.gbdoc-chips { display: flex; flex-wrap: wrap; gap: var(--space-8); }
.gbdoc-chip {
  padding: 3px 8px;
  background: var(--zinc-100);
  border-radius: var(--radius);
  color: var(--zinc-800);
}

/* The token under the value it produced, in the drawer. */
.gbdoc-tokenline {
  display: block;
  margin-top: 3px;
  font-size: 14px;
  line-height: 1.4;
  color: var(--zinc-500);
  word-break: break-all;
}
.gbdoc-tokenline--none { font-family: var(--font-sans); color: var(--zinc-400); }

/* ---- The live readout line ---- */
.gbdoc-readout { margin: var(--space-16) 0 0; font-size: 14px; line-height: 1.7; color: var(--zinc-500); }
.gbdoc-readout b { color: var(--zinc-900); font-variant-numeric: tabular-nums; }

/* ---- The probes: off screen, never seen, measured on resize.
   Not display:none — a hidden element has no computed padding. ---- */
.gbdoc-probes { position: absolute; left: -9999px; top: 0; visibility: hidden; }

/* ============================================================
   gbppl-oro-typography-2 — SPECIMEN FIRST
   ------------------------------------------------------------
   Ton, 26.08: «по шрифтам ужасающее визуальное оформление, вообще
   ничего не понятно. Нужно сделать research и понять, как
   показывать шрифты людям, которые будут с этим работать, причём
   это и дизайнеры, и девелоперы.»

   The research (studio\docs\SHOWCASE-PATTERN.md, «Typography
   pages») says the same thing in every mature system: a type page
   is a COLUMN OF LIVE SPECIMENS, largest first, each with a quiet
   line of numbers beside it. The table of figures is the second
   view, never the first. Material, Carbon, Primer, Atlassian,
   Apple and Google Fonts all put the type itself in the reading
   column and the metadata in the margin.

   So the atoms below are three:
     .gbdoc-face   the family specimen: one big line, the
                   character set, the weights, the size row.
     .gbdoc-type   the role ladder: one row per role, live sample
                   on the left, quiet meta on the right.
     .gbdoc-pair   a do and an avoid, side by side, as real
                   layout rather than as a sentence.

   THE FURNITURE MUST NOT COMPETE WITH THE SPECIMEN. Every caption
   here is 14px Zinc 500 or the Eyebrow role; the only large type
   in these blocks is the type being documented. Numbers sit in
   the monospace of the documentation, tabular, so a column of
   sizes reads as a column.
   ============================================================ */

/* ---- THE FAMILY SPECIMEN ---- */
.gbdoc-face {
  margin-top: var(--space-16);
  padding: var(--space-24);
  border: 1px solid var(--zinc-200);
  border-radius: var(--radius);
  background: var(--white);
}
.gbdoc-face__head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-8) var(--space-16); }
/* The family names itself IN ITSELF. Size and family are set by the
   page from the record; nothing about a face is decided here. */
.gbdoc-face__name { line-height: 1.2; color: var(--zinc-950); }
.gbdoc-face__role { font-size: 14px; line-height: 1.5; color: var(--zinc-500); }
.gbdoc-face__big {
  margin: var(--space-24) 0 0;
  line-height: 1.1;
  color: var(--zinc-950);
  overflow-wrap: break-word;
}
.gbdoc-face__set {
  margin: var(--space-24) 0 0;
  line-height: 1.6;
  color: var(--zinc-700);
  overflow-wrap: break-word;
}
.gbdoc-face__set span { display: block; }
.gbdoc-face__band { margin-top: var(--space-24); padding-top: var(--space-16); border-top: 1px solid var(--zinc-100); }
.gbdoc-face__cap {
  display: block;
  margin-bottom: var(--space-16);
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--zinc-400);
}
.gbdoc-face__row { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--space-16) var(--space-24); }
.gbdoc-face__item { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
.gbdoc-face__glyph { line-height: 1; color: var(--zinc-900); }
.gbdoc-face__tag {
  font-family: ui-monospace, 'Cascadia Mono', 'Segoe UI Mono', monospace;
  font-size: 14px;
  line-height: 1.2;
  color: var(--zinc-500);
  font-variant-numeric: tabular-nums;
}

/* ---- THE ROLE LADDER, AS SPECIMENS ---- */
.gbdoc-type {
  margin-top: var(--space-16);
  border: 1px solid var(--zinc-200);
  border-radius: var(--radius);
  background: var(--white);
}
.gbdoc-type__group { padding: var(--space-24); }
.gbdoc-type__group + .gbdoc-type__group { border-top: 1px solid var(--zinc-200); }
/* gbppl-oro-heads-1. The name of a group in the scale is a heading and
   is now written as one (.oro-h3 in the markup that draws it); all this
   class still owns is that a span has to be told to be a block. It used
   to carry the eyebrow role, and a group name in caps was the same
   mistake as a section caption in caps. */
.gbdoc-type__gname { display: block; }
.gbdoc-type__gline { margin: 6px 0 0; font-size: 14px; line-height: 1.6; color: var(--zinc-500); }

.gbdoc-type__row { display: grid; gap: var(--space-8); padding: var(--space-24) 0 0; }
.gbdoc-type__row + .gbdoc-type__row { margin-top: var(--space-24); border-top: 1px solid var(--zinc-100); }
/* LAYOUT MEASURE: 300px is the narrowest column that holds
   «Inter 600 · 14/normal · 1px · caps» on one monospace line. */
@media (min-width: 1024px) {
  .gbdoc-type__row { grid-template-columns: minmax(0, 1fr) 300px; gap: var(--space-24); align-items: start; }
}
/* The live half. Overflow is hidden rather than scrolled: a 52px
   title on a 390px screen shortens, it does not push the page
   sideways. */
.gbdoc-type__live { min-width: 0; overflow: hidden; }
.gbdoc-type__meta { position: relative; display: flex; flex-direction: column; gap: 4px; padding-right: var(--space-32); }
.gbdoc-type__name { font-size: 14px; font-weight: 600; line-height: 1.5; color: var(--zinc-900); }
.gbdoc-type__name .gbdoc-flag { margin-left: var(--space-8); vertical-align: 1px; }
.gbdoc-type__num {
  font-family: ui-monospace, 'Cascadia Mono', 'Segoe UI Mono', monospace;
  font-size: 14px;
  line-height: 1.5;
  color: var(--zinc-500);
  font-variant-numeric: tabular-nums;
  overflow-wrap: break-word;
}
.gbdoc-type__num--dim { color: var(--zinc-400); }

/* ---- The copy button of a meta line. An instrument, not a
   button: no fill, no frame (Ton 26.08, same rule as the segment). */
.gbdoc-copybtn {
  position: absolute;
  top: -4px;
  right: -4px;
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  background: transparent;
  border-radius: var(--radius);
  color: var(--zinc-400);
  cursor: pointer;
  transition: color var(--mo-micro) var(--mo-move);
}
/* gbppl-oro-icons-1. The corner it hangs in belongs to the meta
   line of a type row. In a table cell there is no corner and no
   positioned host, so the button pins itself to the far right of
   the window and pushes the page four pixels sideways. Standing in
   the flow is the same instrument in the same place, said the
   other way round. */
.gbdoc-copybtn--inline { position: static; }
.gbdoc-copybtn svg { width: 16px; height: 16px; }
.gbdoc-copybtn:hover { color: var(--zinc-900); }
.gbdoc-copybtn.is-done { color: var(--blue-600); }
.gbdoc-copybtn:focus-visible { outline: 2px solid var(--blue-600); outline-offset: 2px; }

/* ---- ONE LINE, ONE VALUE, ONE MARK TO TAKE IT ----
   gbppl-inspect-select-1, 03.09. Ton, after Valerie asked to be able
   to highlight a colour in the Inspect drawer: «На каждом значении
   должен быть copy on hover: ховеришь на значение, справа появляется
   иконка Копировать. При этом должна оставаться возможность просто
   выделить текст и скопировать вручную. Это было бы самым правильным
   решением.» Two paths to the same string, and the mark is the
   shortcut, never the only way in.

   A row of the properties table says a value and, under it, the token
   behind that value. They are two different strings and a developer
   wants one or the other, never the pair, so each LINE is the unit
   here and each line carries its own mark. A line with nothing to
   paste — «No token», «In the organism» — carries none, and the
   absence is the answer.

   THE MARK DOES NOT MOVE THE LINE AND DOES NOT TAKE THE DRAG. It
   stands in the flow from the first frame, so nothing reflows when it
   appears; it is only faded in, and while it is faded out it is out
   of `pointer-events` entirely, so a selection dragged across the
   value cannot end on an invisible button. Revealed by hover on ITS
   OWN line, not on the row: hovering the value must not light up the
   token's mark as well, or the reader has to work out which of two
   marks belongs to what is under the pointer.

   NO HOVER, NO MARK, and that is the whole of the touch story
   (закон 0a.4: a new gesture is Ton's to declare, not a wave's). On a
   touch pointer the drawer behaves exactly as it did before this
   wave, and the value is still selectable by hand.

   OUT OF THE TAB RING on purpose (`tabindex="-1"` at the caller). A
   drawer of thirty measured rows would otherwise put sixty invisible
   stops between the close cross and the link at the foot. The
   keyboard path to the same string is the one this wave just gave
   back: select the line and press Ctrl+C. */
.gbdoc-vrow {
  display: flex;
  align-items: center;
  gap: var(--space-8);
}
/* The 3 that used to sit on the token line itself moves to the gap
   between the two lines: inside a flex row a margin on the item
   pushes the item away from the mark beside it. Same number, same
   picture, and it is still the NO TOKEN literal declared on
   .gbdoc-tokenline above. */
.gbdoc-vrow > .gbdoc-tokenline { margin-top: 0; }
.gbdoc-vrow + .gbdoc-vrow { margin-top: 3px; }
.gbdoc-vrow > :first-child { min-width: 0; }

.gbdoc-copybtn--row {
  flex: 0 0 auto;
  /* 20 for the pointer, 16 of glyph inside it, and the four pixels of
     difference are given back as negative block margin so the target
     OVERHANGS its line instead of stretching it. Measured before this
     line went in: the token line is 19.58 tall and a 20px item made
     every row that has a token 0.42px taller than it was at HEAD. A
     hit area is allowed to be bigger than the text; a row is not
     allowed to move because of it. NO TOKEN on either number: they
     are the size of a target and the size of a glyph, not lengths in
     the layout, and both are already named on .gb-icon. */
  width: 20px;
  height: 20px;
  margin-block: calc((16px - 20px) / 2);
  opacity: 0;
  pointer-events: none;
  transition:
    opacity var(--mo-micro) var(--mo-move),
    color var(--mo-micro) var(--mo-move);
}
.gbdoc-vrow:hover > .gbdoc-copybtn--row {
  opacity: 1;
  pointer-events: auto;
}

/* ---- DO AND AVOID, AS LAYOUT ----
   Carbon and Polaris both show the rule twice: once as a sentence
   and once as two compositions standing next to each other. The
   words alone do not teach a step in hierarchy. */
.gbdoc-pair { margin-top: var(--space-16); display: grid; gap: var(--space-16); }
@media (min-width: 900px) { .gbdoc-pair { grid-template-columns: 1fr 1fr; gap: var(--space-24); } }
.gbdoc-pair__cell {
  border: 1px solid var(--zinc-200);
  border-radius: var(--radius);
  background: var(--white);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.gbdoc-pair__cap {
  padding: var(--space-8) var(--space-16);
  background: var(--zinc-50);
  border-bottom: 1px solid var(--zinc-200);
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--zinc-500);
}
.gbdoc-pair__body { flex: 1 1 auto; padding: var(--space-24); }
/* The avoid side stands on the grey ground the system uses for
   «not the surface you ship on». No red: a rule of the system is a
   fact, and colour here belongs to state (Ton-5). */
.gbdoc-pair__cell--no .gbdoc-pair__body { background: var(--zinc-50); }
.gbdoc-pair__why {
  margin: 0;
  padding: var(--space-16);
  border-top: 1px solid var(--zinc-200);
  font-size: 14px;
  line-height: 1.6;
  color: var(--zinc-500);
}
/* A composed sample inside a pair carries no type of its own: the
   page sets every line from the record it is demonstrating. */
.gbdoc-pair__body > * { margin: 0; }
.gbdoc-pair__body > * + * { margin-top: var(--space-8); }

/* The type row is a slot like any other now: it is named in the
   door block above, and its own reading affordance went with the
   caption (gbppl-oro-props-1). */

/* ============================================================
   gbppl-oro-drawer-1 — A PANEL SHOWN IN THE PAGE, NOT OVER IT
   ------------------------------------------------------------
   One class, and it exists because a drawer is the one organism
   that cannot stand on a plinth. `.gbd-panel` is fixed to the
   right edge of the window and covers the page it would be a
   specimen of, so an anatomy diagram the reader can point at, and
   an Inspect target the reader can click, both need the panel out
   of the corner and in the flow.

   NOTHING ELSE IS TOUCHED. The width, the ground, the shadow and
   every rule of the head, the body and the foot stay with
   drawer.css; what goes is the corner, the layer, the transform
   that holds it off screen and the clock that moves it, because a
   specimen standing still has no arrival to play. The numbers the
   card prints are read off the real panel, never off this one:
   this is the drawing, not the instrument, and the card says so.
   ============================================================ */
.gbdoc-panel {
  position: static;
  inset: auto;
  z-index: auto;
  transform: none;
  transition: none;
}

/* ============================================================
   gbppl-oro-eyebrow-2 — THE CONTEXT SCENE
   ------------------------------------------------------------
   Тон, 28.08, глядя на Overview витрины Eyebrow (два образца
   в пустом контейнере): «Что можно понять по превью eyebrow
   здесь? Там как будто кто-то нагадил текстом просто
   в контейнер.» Согласовано: айбрау не читается сам по себе,
   только в своём месте.

   A specimen shelf works for an organism that keeps its shape
   when you take it out of the page: a button is a button on any
   ground. An Eyebrow is not that. It is a caption, and a caption
   with nothing under it is a word. So the smallest components of
   the system get a SCENE instead of a slot: a small piece of a
   real place, with the specimen standing where it actually
   stands, and a caption underneath naming the place.

   Why not `.gbdoc-shelf` with `--cols`: the shelf is ONE white
   card holding several specimens side by side on a shared floor,
   and its slots caption from above in Zinc 900. A scene is the
   opposite arrangement — several separate grounds, each its own
   little page, named quietly from below — so the two cannot be
   the same class. Everything else here is borrowed: the ground,
   the hairline, the radius and the padding are the plinth values
   `.gbdoc-shelf` already uses (only the ground steps from white
   to Zinc 50, because what stands on a scene is usually a white
   card), the caption is `.gb-eyebrow` itself, and the gap
   between an eyebrow and the thing under it is `--space-8`.

   THE 8 IS MEASURED, NOT CHOSEN. Two places in the house already
   stand an eyebrow over a title, and both say 8: the live
   checkout, where every section caption is `.gb-eyebrow mb-2`
   (measured 7.99 at 1280, gbppl-oro-eyebrow-2), and the registry
   card of this showcase, whose `gap` is `--space-8`. live/index
   was measured too and has no such pair at all: its heading strip
   is a serif h2 on its own.
   ============================================================ */
.gbdoc-scenes {
  display: grid;
  /* LAYOUT MEASURE, the same one .gbdoc-reg uses for its cards:
     240 is the narrowest a small scene reads at. Three across a
     1280 reading column, one at 390. */
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  /* One height for all of them at every width, stacked or in a row:
     three scenes of the same component are one comparison, and a
     row of different heights reads as three different things. */
  grid-auto-rows: 1fr;
  gap: var(--space-16);
  margin-top: var(--space-16);
}
/* The rows of the grid stretch, so the stages come out one height
   whatever stands in them. */
.gbdoc-scene { display: flex; flex-direction: column; }
.gbdoc-scene__stage {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: var(--space-24);
  background: var(--white);      /* the specimen zone, see THE ZONE LAW */
  border: 1px solid var(--zinc-200);
  border-radius: var(--radius);
}
/* The caption is the role itself, quiet and underneath: the scene
   above it is the loud half. */
.gbdoc-scene__cap { display: block; margin-top: var(--space-8); }

/* An eyebrow and the thing it stands over, as one block. Whatever
   the pair is made of brings its own type and its own colour; the
   pair brings only the rhythm. */
.gbdoc-scene__pair > * { margin: 0; }
.gbdoc-scene__pair > .gb-eyebrow { display: block; margin-bottom: var(--space-8); }
/* The preview tile of a registry card centres what stands in it, so
   a pair standing there centres with it. */
.gbdoc-regcard__spec > .gbdoc-scene__pair { text-align: center; }

/* ============================================================
   gbppl-lab-e-1 — THE TOGGLE ROW (a layout, not a component)
   ------------------------------------------------------------
   Ton, 29.08 13:31: «размер селектом норм, но у нас есть
   ToggleButton и куча других компонентов; люди не любят Select».
   And 13:02, about the underlined words the panels were built of:
   «ужасно не нравится делать всё управление табами».

   So a short named set of values is a ROW OF BUTTONS with one of
   them pressed, the shape PrimeVue calls SelectButton. Nothing is
   drawn here: every button in the row is the button organism, and
   the pressed one is the organism's own filled primary, because
   Ton-5 says blue is state. This rule is the row and the gap, and
   the day a bench variant is chosen it moves to button.css as
   .gb-toggle with a card of its own.

       <div class="gbdoc-toggle" role="group" aria-label="Size">
         <button class="gb-btn gb-btn--medium gb-btn--filled gb-btn--primary"
                 type="button" aria-pressed="true">
           <span class="gb-btn__label">S</span>
         </button>
         <button class="gb-btn gb-btn--medium gb-btn--outline gb-btn--secondary"
                 type="button" aria-pressed="false">
           <span class="gb-btn__label">M</span>
         </button>
       </div>

   The gap is --space-8: the buttons are one control read together,
   so they sit closer than two separate actions ever would, and the
   row wraps rather than scrolls, because a value a person cannot
   see is a value they will not use. */
.gbdoc-toggle {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-8);
}
/* A value the system does not hold stays visible and stops being
   pressable, the same way an unavailable segment does: a rule
   nobody can see is a rule nobody learns. */
.gbdoc-toggle .gb-btn[disabled] { opacity: 0.4; }

/* ============================================================
   .gbdoc-chips — WITHDRAWN (gbppl-lab-f-2, 29.08)
   ------------------------------------------------------------
   gbppl-lab-f-1 drew a quiet segment here for the playground
   rail: a Zinc 100 track with the chosen chip lifted out of it
   in white, at the reading size. Ton, 29.08 14:55, on variant F:
   «использованы сторонние компоненты, которых у нас нет: там
   должны быть toggle buttons, их нужно создать; на прототипе
   чекаута есть toggle button, его просто нужно сделать
   системным.»

   So it went. A control panel is built from components the house
   owns, and the house owns one segment: .gb-toggle, measured off
   the checkout and now living in system/components/toggle.css.
   The rail of F, its Light | Dark and its Preview | Code switch
   all wear it, and documentation furniture no longer carries a
   second segment of its own.

   .gbdoc-chips as a bare row of .gbdoc-chip labels stays where it
   always was, further up this file, in the Inspect drawer: those
   are read, not pressed, and they were never this control. This
   block's removal also takes off the track it had accidentally
   drawn around them since yesterday.
   ============================================================ */

/* ============================================================
   gbppl-oro-canon-1 — THE PLAYGROUND BLOCK, .gbdoc-pg
   ------------------------------------------------------------
   Ton, 31.08 13:17, on variant F of the bench and the canon of
   axes under it: «окей, давай попробуем так». So the layout the
   bench proved moves out of the bench and becomes furniture of
   the documentation, the way the card, the stage and the reading
   table did before it. The class was .labF-* on the bench and it
   is .gbdoc-pg-* here: the bench keeps no copy, it wears these.

   WHAT THE BLOCK IS, and every line of it points at a line of
   studio\docs\RECON-PREVIEW-CONTROLS-2026-08-29.md, ten systems
   read live rather than remembered:

     ONE CARD, ONE HAIRLINE (recon 2.2). Preview and controls
     inside one frame with a single line between them, so the
     panel never reads as a second block of the page. The card
     owns the border and the lift; nothing inside it draws
     another.
     THE RAIL IS A RAIL (recon 2.1). Fixed width, the preview
     takes the rest; at 1280 the specimen keeps 73 per cent of
     the card. Below 1024 the rail goes under the preview at full
     width and the hairline turns with it.
     THE PANEL IS QUIET (recon 2.3). One step of grey, no accent,
     and the only blue in the rail is the focus ring.
     THE CODE IS NOT A CONTROL (recon 2.6). It is a second VIEW of
     the same specimen, folded by default, and since
     gbppl-showcase-tools-1 the switch for it stands in the rail
     with every other control rather than in a band of its own.
     THE GROUND IS A CONTROL LIKE THE REST (gbppl-showcase-tools-1,
     02.09). Light | Dark dresses the stage rather than the
     specimen, and it used to say so by floating on the stage. Ton
     read that as a control loose on the canvas, so it says it a
     different way now: it is a row of the rail, in a group of its
     own named for the stage, under the axes of the component.

   ------------------------------------------------------------
   gbppl-showcase-tools-1, 02.09 — THE SCENE IS A CANVAS AND THE
   RAIL IS THE INSTRUMENT
   ------------------------------------------------------------
   Ton, 02.09, on a screenshot of button.html: «Как у нас висит
   переключатель Light / Dark? Он находится где-то посреди канваса,
   рядом с самой кнопкой... Почему тогглы вообще такие огромные?
   Почему кнопка не идеально отцентрована по вертикали и
   горизонтали? Зачем нам вообще этот странный футер с Preview и
   Code? Почему эта штука не в правой панели? Это полный
   винегрет.» And twice before, on the same block: «какой-то
   заповедник тогглов, хз что демо, а что управление», «зоопарк».

   FOUR ANSWERS, AND THEY ARE ALL THE SAME ANSWER: a control is
   furniture of the documentation and it may not wear the species
   of the thing it drives.

     1 THE STAGE HOLDS EXHIBITS ONLY. Nothing else is drawn on it,
       so there is never a question about which of two black cards
       is the specimen.
     2 THE EXHIBIT IS IN THE MIDDLE OF THE CANVAS, on both axes,
       and the canvas is the whole left column rather than a band
       at the top of it. Until this wave the specimen was centred
       in a 320 band that stuck to the top of a 640 column, which
       is centred in the band and a third of the way down the
       thing the reader calls the canvas. The band no longer
       sticks: a band that follows the scroll is a band whose
       centre moves, and Ton asked for a centre that does not.
     3 THE RAIL HOLDS EVERY CONTROL, the ground and the view
       included, and the footer band is gone. One place to look.
     4 THE RAIL SPEAKS THE VOICE OF docs.css, not of the system.
       Ton 26.08 settled this once for the segment: «the top
       buttons work as a showcase while they are meant to build
       the button below; it reads double». The playground was
       built on .gb-toggle, the checkout's black card, and that is
       the same defect with a different control. So a set of two
       to four values is .gbdoc-seg, the instrument of the
       documentation: quiet text at 14/500 in sentence case with a
       blue underline on the chosen one. A longer set is the tool
       select below, a hairline box 32 high, which is not the
       system's Select and does not pretend to be. Nothing in the
       rail is taller than 32; the specimen beside it is 48 and up.

   THE GROUNDS ARE THE ONES TON TURNED ROUND (gbppl-lab-f-2,
   29.08 14:55: «панель должна быть серее, а превью белым; вся
   превью-панель должна выделяться на фоне простыни, возможно
   добавить elevation»). Scene white, rail Zinc 100, card lifted
   with --shadow-card and its hairline kept. Since 02.09 this is no
   longer an exception but THE ZONE LAW of the whole file: the
   frame's stage and control strip were turned round to match it.

   THE KNOBS ARE ALL IN THE :root BLOCK BELOW. One place for the
   rail's width, the scene's floor, the grounds, the rhythm and
   the two label sizes; the rules under it only spend them.
   Whoever moves the rail moves the number in oro.js too, where
   the control rule costs a label against it (GbOro.controls,
   BUDGET.RAIL), and the run-time probe says out loud when the
   two have drifted.
   ============================================================ */
:root {
  /* THE RAIL. 320 = --space-64 * 5. The recon puts the convention
     at 250..360 (Mantine 250, Joy 300, Radix 360, Figma 300). 280
     was measured and rejected: at 280 the rail holds 231 and three
     rows wrap; at 320 it holds 271. */
  --gbdoc-pg-rail: calc(var(--space-64) * 5);
  /* THE SCENE, its floor rather than its height: it takes the whole
     of the left column and grows to whatever the rail needs, because
     one card with two columns of different heights is not one card,
     and because the canvas a reader sees is the coloured column
     rather than a band inside it (gbppl-showcase-tools-1). */
  --gbdoc-pg-scene-min: calc(var(--space-64) * 5);
  --gbdoc-pg-scene-pad: var(--space-48);
  --gbdoc-pg-ground-light: var(--white);
  --gbdoc-pg-ground-dark: var(--zinc-950);
  --gbdoc-pg-rail-ground: var(--zinc-100);
  --gbdoc-pg-line: var(--zinc-200);
  /* --shadow-card, the light one of the system's three: --shadow-panel
     belongs to things that float over a page, which a card sitting IN
     the page is not. */
  --gbdoc-pg-lift: var(--shadow-card);
  /* THE RHYTHM of the rail: air between two controls, more air
     between two groups, and the rail's own padding. */
  --gbdoc-pg-gap: var(--space-16);
  --gbdoc-pg-group-gap: var(--space-24);
  --gbdoc-pg-pad: var(--space-24);
  /* THE TYPE. The axis name is the eyebrow of the system, which is
     also what gb-field prints over its own control, so a Select and
     a toggle carry the same label; the label beside a checkbox is
     the reading size, the way Joy UI and Mantine letter a switch. */
  --gbdoc-pg-axis-size: var(--eyebrow-size);
  --gbdoc-pg-axis-ink: var(--zinc-500);
  --gbdoc-pg-bool-size: 14px;
  /* THE INSTRUMENT SIZE (gbppl-showcase-tools-1). One reading size
     for every control of the rail, and one height for the two that
     have a box. 14 is the documentation's secondary size, spent by
     .gbdoc-seg, the More summary and Reset already; 32 is --space-32,
     and it is deliberately the rung BELOW the smallest button the
     system draws, so that no control of the rail can be mistaken for
     a specimen. */
  --gbdoc-pg-tool-size: 14px;
  --gbdoc-pg-tool-h: var(--space-32);
  /* THE CEILING OF THE CARD (gbppl-playground-polish-1, Ton 02.09;
     RAISED by gbppl-oro-door-1, Ton 09.09).
     512 = --space-64 * 8 held the card to 64 per cent of the 800 a
     typical 1280 x 800 window gives a document, and the price was a
     rail that scrolled inside the card on every page of the engine:
     natural heights measured 521 to 892, so all eight of them had a
     nested scrollbar. Ton: the rail should not scroll and the preview
     area should look better for it. So the ceiling stops being the
     working height and becomes what a ceiling is, the honest maximum:
     896 = --space-64 * 14, the first rung of the ladder above the
     tallest rail in the house (892, the icons card, measured). The
     rung below it, 832, would leave that one card scrolling and the
     rung below that, 768, would leave the button card scrolling by
     three pixels, which is a scrollbar for nothing. The row takes the
     taller of its two
     columns, which is the rail, so the canvas now grows to the rail
     instead of the rail shrinking into the canvas, and the exhibit
     stays in the middle of it by the same construction as before. A
     rail that one day outgrows 896 scrolls rather than making a card
     no window can show whole; that is the case the number is for.
     THE PRICE, ON THE TALLEST CARD ONLY, and it is on Ton's desk: a
     44px glyph in the middle of 892 pixels of canvas is the very
     «lost object» the 512 ceiling was invented against. The answer is
     a shorter rail on that one page (its six axes and the fold), not
     a shorter card everywhere. */
  --gbdoc-pg-ceiling: calc(var(--space-64) * 14);
}

.gbdoc-pg {
  margin-top: var(--space-32);   /* THE RHYTHM OF A SECTION */
  background: var(--white);
  border: 1px solid var(--gbdoc-pg-line);
  border-radius: var(--radius);
  box-shadow: var(--gbdoc-pg-lift);
  overflow: hidden;
}
.gbdoc-pg__body { display: grid; }
@media (min-width: 1024px) {
  .gbdoc-pg__body { grid-template-columns: minmax(0, 1fr) var(--gbdoc-pg-rail); }
  /* The ceiling is spent on the RAIL and not on the canvas, and that
     is the whole of it: the two columns share one grid row, the row
     takes the tallest of them, and the tallest of them is always the
     rail. Cap the rail and the row is capped with it, so the canvas
     comes out exactly as tall as the card is allowed to be and the
     exhibit stays in the middle of it by construction. min-height 0
     is what lets a stretched grid item scroll at all. */
  .gbdoc-pg__rail {
    max-height: var(--gbdoc-pg-ceiling);
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
  }
}

/* ---- the left column: the specimen, or its markup ----
   THE CANVAS IS THE WHOLE COLUMN AND THE EXHIBIT IS IN THE MIDDLE
   OF IT (gbppl-showcase-tools-1, Ton 02.09: «почему кнопка не
   идеально отцентрована по вертикали и горизонтали?»). Until this
   wave the ground belonged to the column and the specimen stood in
   a band of --gbdoc-pg-scene-min at the top of it: centred in the
   band, and a third of the way down the coloured area a reader
   calls the canvas. The band now takes the column, so the two
   centres are one centre, and both gaps on both axes are equal by
   construction rather than by arithmetic.

   AND IT NO LONGER FOLLOWS THE SCROLL. The band used to stick clear
   of the studio bar, the way a canvas stays put in Storybook while
   the panel moves; a band that follows is a band whose centre
   moves, which is the one thing this block was just told not to do.
   The price is paid on the tallest rail in the house and it is one
   scroll; the centre is worth more. */
.gbdoc-pg__view {
  display: flex;
  flex-direction: column;
  min-width: 0;
  background: var(--gbdoc-pg-ground-light);
  transition: background-color var(--mo-small) var(--mo-move);
}
.gbdoc-pg__view.is-dark { background: var(--gbdoc-pg-ground-dark); }
.gbdoc-pg__scene {
  position: relative;          /* the properties door hangs here */
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: var(--gbdoc-pg-scene-min);
  padding: var(--gbdoc-pg-scene-pad) var(--space-24);
}
/* The markup, in the specimen's PLACE rather than under it: the two
   are one thing seen two ways, and a code block that pushes the
   stage down is the noise this block exists to remove. */
.gbdoc-pg__code {
  flex: 1 1 auto;
  display: flex;
  align-items: flex-start;     /* the markup keeps its own height */
  min-width: 0;
  padding: var(--gbdoc-pg-scene-pad) var(--space-24);
}
.gbdoc-pg__code .gbdoc-code { flex: 1 1 auto; margin: 0; }
.gbdoc-pg [hidden] { display: none !important; }
/* Trap 3, the local antidote: auth.css names a border colour on four
   sides and a width on one, and a field standing in the rail needs
   the other three said out loud. The same three lines every specimen
   surface in this file spends. */
.gbdoc-pg__row .gba-input {
  border-style: solid;
  border-width: 0;
  border-bottom-width: 1px;
}

/* ---- the right column: the rail ---- */
.gbdoc-pg__rail {
  padding: var(--gbdoc-pg-pad);
  background: var(--gbdoc-pg-rail-ground);
  border-top: 1px solid var(--gbdoc-pg-line);
}
@media (min-width: 1024px) {
  .gbdoc-pg__rail { border-top: 0; border-left: 1px solid var(--gbdoc-pg-line); }
}
/* Air between groups, and no rules between axes: the recon found
   headings in the panels with more than ten axes and hairlines in
   none of the small ones (2.5). */
.gbdoc-pg__group + .gbdoc-pg__group { margin-top: var(--gbdoc-pg-group-gap); }
/* The Stage group stands after the More fold, and a fold is not a
   group, so the adjacency above does not reach it. Same air, said
   twice because the markup has two shapes in the stack. */
.gbdoc-pg__more + .gbdoc-pg__group { margin-top: var(--gbdoc-pg-group-gap); }
/* THE TWO LABEL LEVELS ARE THE SAME SIZE AND DIFFERENT INK. Both the
   group name and the axis name are the eyebrow of the system, which
   is also what gb-field prints over its own Select. The group is
   Zinc 900 and the axis Zinc 500: the hierarchy is carried by ink
   rather than by a second size, because a second size here would be
   a heading, and an eyebrow is never a heading (Ton-21). */
.gbdoc-pg__gname {
  display: block;
  margin-bottom: var(--space-16);
  font-size: var(--gbdoc-pg-axis-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  line-height: 1.5;
  text-transform: uppercase;
  color: var(--zinc-900);
}
.gbdoc-pg__row + .gbdoc-pg__row { margin-top: var(--gbdoc-pg-gap); }
.gbdoc-pg__row[hidden] { display: none; }
/* A GROUP WITH NOTHING LEFT IN IT IS NOT A GROUP (gbppl-showcase-canon-1,
   01.09). An axis that does not apply is REMOVED rather than greyed, and on
   the field's one time code look both content axes go at once, which left
   the word CONTENT standing over air. The renderer cannot answer this
   itself: it builds the rail once and sets the hidden flags on every paint
   afterwards, so by the time a group is empty the markup is already
   written. The group therefore answers for itself, which is also the only
   version of the rule that keeps working when a page adds an axis. */
.gbdoc-pg__group:not(:has(.gbdoc-pg__row:not([hidden]))) { display: none; }
.gbdoc-pg__name {
  display: block;
  margin-bottom: var(--space-8);
  font-size: var(--gbdoc-pg-axis-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  line-height: 1.5;
  text-transform: uppercase;
  color: var(--gbdoc-pg-axis-ink);
}
/* A field inside the rail is a control of the rail: no margin of its
   own and no required asterisk, because every axis already has a
   value. Nothing draws one today — the rail's picker and its text box
   are the two tools below — and the line stays for a page that hands
   the renderer a gb-field of its own. */
.gbdoc-pg__row .gba-field { margin: 0; }

/* ============================================================
   gbppl-showcase-tools-1 — THE THREE TOOLS OF THE RAIL
   ------------------------------------------------------------
   A SET OF TWO TO FOUR VALUES IS .gbdoc-seg, the instrument the
   documentation already owns (SEGMENT CONTROL, further up this
   file, Ton 26.08). It arrives here unchanged: quiet text at
   14/500, sentence case, no fill and no frame, and the chosen one
   underlined in Blue 600 because chosen is a state. What changes
   is only where the segments sit, and that is one flex row that is
   allowed to wrap, because a rail is 272 wide and a label is a
   word rather than a share of a track.

   A LONGER SET IS THE PICKER, and it is NOT the system's Select.
   The system's Select is an underlined 48 tall form control with
   a caps label over it: standing in the rail it was a specimen
   driving a specimen, the same defect as the black toggle. The
   picker is a hairline box 32 high with the reading size in it —
   a tool, obviously on loan from nothing, and a rung below the
   smallest control the system draws. Its chevron is the one the
   More fold already spends, so the rail owns exactly one arrow.

   FREE TEXT IS THE SAME BOX WITHOUT THE CHEVRON, for the same
   reason.
   ============================================================ */
.gbdoc-pg__segs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 var(--space-16);
}
/* The row owns the air between two segments, so the atom's own
   right margin would count it twice. */
.gbdoc-pg__segs .gbdoc-seg { margin-right: 0; }
.gbdoc-pg__segs .gbdoc-seg[disabled] {
  opacity: 0.4;
  cursor: default;
  pointer-events: none;
}

.gbdoc-pg__pick { position: relative; display: block; }
.gbdoc-pg__pick select,
.gbdoc-pg__row input.gbdoc-pg__text {
  appearance: none;
  -webkit-appearance: none;
  display: block;
  width: 100%;
  height: var(--gbdoc-pg-tool-h);
  margin: 0;
  padding: 0 var(--space-8);
  border: 1px solid var(--zinc-300);
  border-radius: var(--radius);
  background: var(--white);
  font-family: var(--font-sans);
  font-size: var(--gbdoc-pg-tool-size);
  font-weight: 500;
  line-height: 1.4;
  color: var(--zinc-900);
  transition: border-color var(--mo-micro) var(--mo-move);
}
.gbdoc-pg__pick select { padding-right: var(--space-24); cursor: pointer; }
.gbdoc-pg__pick select:hover,
.gbdoc-pg__row input.gbdoc-pg__text:hover { border-color: var(--zinc-400); }
.gbdoc-pg__pick select:focus-visible,
.gbdoc-pg__row input.gbdoc-pg__text:focus-visible {
  outline: 2px solid var(--blue-600);
  outline-offset: 2px;
}
/* The chevron of the More fold, at the same seven pixels and the
   same hairline, parked against the padding edge. pointer-events
   off: the box under it is the control. */
.gbdoc-pg__pick::after {
  content: "";
  position: absolute;
  top: 50%;
  right: var(--space-8);
  width: 7px; height: 7px;
  margin-top: -5px;
  border-right: 1.5px solid var(--zinc-500);
  border-bottom: 1.5px solid var(--zinc-500);
  transform: rotate(45deg);
  pointer-events: none;
}
/* An option the current combination does not hold. Shown greyed
   rather than removed: a rule nobody can see is a rule nobody
   learns, which is the same argument the workbench makes. */
.gbdoc-pg__pick option:disabled { color: var(--zinc-400); }
/* THE BOOLEAN, ON LOAN. A native checkbox with our own label beside
   it and not one line of styling on the box: the system has no
   Switch until one is measured out of Figma (Ton 29.08 13:33, a
   component comes from a measurement or it does not get built), and
   a thing that is obviously on loan reads better than a hand drawn
   toggle that would have to be unlearned. Joy UI and Mantine both
   letter a switch this way, with the name at the reading size on the
   same baseline rather than as an eyebrow above it. */
.gbdoc-pg__bool {
  display: flex;
  align-items: center;
  gap: var(--space-8);
  min-height: var(--space-32);
  font-size: var(--gbdoc-pg-bool-size);
  font-weight: 500;
  line-height: 1.4;
  /* Zinc 700, not Zinc 900 (gbppl-showcase-tools-1). The rail has one
     voice now, and the loudest ink in it was the label of a borrowed
     checkbox: quieter than the segment it stands beside is wrong, and
     louder than the group name over it was worse. */
  color: var(--zinc-700);
  cursor: pointer;
}
/* The one line of styling the borrowed box gets, and it is not a
   style: a checked native checkbox is blue everywhere, and the rail
   holds no blue but the focus ring (Ton-5: blue is state, and this
   panel is not the specimen). */
.gbdoc-pg__bool input { accent-color: var(--zinc-900); }
/* THE SMOKE ALARM'S ROOM. The budget in oro.js decides; this box
   only checks the decision afterwards. One absolutely positioned,
   aria-hidden node per rail, parked off the sheet and clipped by the
   card's own overflow, into which a track already standing in the
   rail is re-rendered at its natural one-row width. It sits INSIDE
   the rail so it inherits the rail's face and size rather than the
   document's, and nothing in it is ever painted. */
.gbdoc-pg__probe {
  position: absolute;
  top: 0;
  left: -9999px;
  width: max-content;
  visibility: hidden;
  pointer-events: none;
}
/* The probe letters its row the way the RAIL letters it and then
   forbids it to wrap: the alarm has to measure the same row the
   budget costed, or it reports a drift of its own making. */
.gbdoc-pg__probe .gbdoc-pg__segs { flex-wrap: nowrap; width: max-content; }
.gbdoc-pg__probe .gbdoc-seg { white-space: nowrap; }

/* ---- the rare axes, behind one More ---- */
.gbdoc-pg__more { margin-top: var(--gbdoc-pg-group-gap); }
.gbdoc-pg__more > summary {
  display: inline-flex;
  align-items: center;
  gap: var(--space-8);
  padding: var(--space-8) 0;
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.2px;
  color: var(--zinc-600);
  cursor: pointer;
  list-style: none;
}
.gbdoc-pg__more > summary::-webkit-details-marker { display: none; }
.gbdoc-pg__more > summary::before {
  content: "";
  width: 7px; height: 7px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(-45deg);
  transition: transform var(--mo-micro) var(--mo-move);
}
.gbdoc-pg__more[open] > summary::before { transform: rotate(45deg); }
.gbdoc-pg__more > summary:hover { color: var(--zinc-900); }

/* The closing strip of the rail: Reset always, and to its left the
   one action a card may carry (the drawer's «Open the drawer»,
   which does not build the specimen, it opens the instrument). An
   action is a button and wears the button; a control that picks a
   value is not, and does not. */
.gbdoc-pg__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-8) var(--space-16);
  margin-top: var(--gbdoc-pg-group-gap);
  padding-top: var(--space-16);
  border-top: 1px solid var(--gbdoc-pg-line);
}
.gbdoc-pg__reset {
  padding: 0;
  border: 0;
  background: transparent;
  font-size: 14px;
  font-weight: 500;
  color: var(--zinc-500);
  cursor: pointer;
  transition: color var(--mo-micro) var(--mo-move);
}
.gbdoc-pg__reset:hover { color: var(--zinc-900); }
.gbdoc-pg__reset:focus-visible { outline: 2px solid var(--blue-600); outline-offset: 2px; border-radius: 2px; }

/* ---- the one measured line, UNDER the card ----
   gbppl-showcase-tools-1. It used to share a Zinc 50 footer band
   with the Preview | Code switch, and Ton asked what that band was
   for («зачем нам вообще этот странный футер... это полный
   винегрет»). The switch went into the rail with every other
   control, and what was left was a caption with a strip around it.
   A caption does not need a strip: the card is the canvas and the
   rail, two zones and no third, and the ruler speaks underneath it
   in the same quiet voice .gbdoc-foot uses two lines further down.
   The line says only what a ruler says: nothing on it repeats what
   the specimen shows (recon 2.10). */
.gbdoc-pg__read {
  margin: var(--space-8) 0 0;
  font-size: 14px;
  line-height: 1.7;
  color: var(--zinc-500);
}
.gbdoc-pg__read:empty { display: none; }
.gbdoc-pg__read b { color: var(--zinc-900); font-variant-numeric: tabular-nums; font-weight: 500; }
