/*
 * zpe-bar.css: the panel's sheet, and the one bar rule the library does not carry.
 *
 * WHERE THE BAR'S RULES LIVE NOW (2026-10-29). They live in the page library's `components.css`, in the block headed
 * "the estate bar", and this worker serves that sheet from the import below. `zpe-nav` still serves the bar's markup
 * and its registry (`zpe-bar.js`, `apps.json`), but every rule that draws the bar is the library's: its box, its row,
 * its items, the account corner, the fade variant the apex uses, the empty host's reserve, the no-script row, and the
 * phone rule that keeps one line. Two copies of those rules is how a page comes to render a bar nobody drew.
 *
 * The stylesheet was 62 rule groups on 2026-10-29: 31 drew the bar (the organization chip's cap among them) and 31
 * drew the panel. Thirty of the bar's are the library's now, and they were deleted here rather than kept "just in
 * case"; `test/nav.test.mjs` asserts the deletion, so a rule re-added to this file fails the suite.
 *
 * WHAT IS STILL HERE, and why: the panel. Its search row, its scrim, its group columns and its lifecycle marks are an
 * app's data surface, not a nav component, which is the line the library block's own comment draws. A page that wants
 * the bar gets those rules with the bar; a page that does not gets nothing.
 *
 * ONE BAR RULE IS ALSO STILL HERE, because the library block does not carry it: the organization chip's width cap.
 * Measured 2026-10-29 by selector diff: 30 of the bar's 31 rule groups are in `components.css` and this one is not.
 * `components.css` is not this task's file, so the gap is named rather than patched around: it is the only bar
 * selector in this sheet, it sits alone below the import, and the test names it as the one exception.
 *
 * AND THE APP SKIN, which is new on 2026-10-29 and has no home in the library yet: the vendored copy above is
 * GENERATED from the zone's published sheets, so a rule written here is the only way to ship a skin the library
 * has not taken. It is a named block, not a paste of the bar's chrome: the library still draws the box, the row,
 * the items, the account corner, the fade variant and the phone rule, and this block adds only the app variant
 * and the crumb inside it. The test names the block's selectors beside the chip's rule; when the library carries
 * the app skin, the block moves there and the exception with it.
 */
@import url('./system.local.css');

/* THE ORGANIZATION'S NAME, when the page declares one (`zpe-kit`'s `bar.org`). It rides INSIDE the account corner so
 * it inherits that row's 24px floor, its truncation and the fade variant's own opacity, rather than repeating any of
 * the three. The separator is a sibling span because a border on the chip would draw a rule the fade variant forbids.
 * The one bar rule the library does not carry, see the header. */
body .zpe-nav .zpe-nav-account .zpe-nav-org {
  max-width: 14rem;
}

/* ── the app skin: the bar as an app screen's OWN header ───────────────────────────────────────────
 * WHAT THIS IS FOR. Measured 2026-10-28: a 40px strip built from the site bar's classes over `/home/` read as "an
 * extra top/global chrome-like layer above the app's own header, not as the app header itself", and the divider
 * under the strip is the tell. So the third variant does not draw a strip over the app: it is placed where the
 * app's own row was, in the app's flow, on the app's own ground, with the app's own row moved inside it. Three
 * controls, and nothing else: the mark, the app's own row, the account corner. No marketing items, no Apps index,
 * no scrim, no dialog, and no rule under it in any state. The falsifier is in DECISIONS.md; if this reads as a
 * second layer again, the app keeps its own header and this block goes.
 *
 * WHY THE RULES ARE HERE RATHER THAN IN THE LIBRARY. See the file header: the vendored library is generated from
 * the zone's published sheets, and the library has no app-skin block yet. The library's own box rules still
 * apply; this block only turns them off where the app screen needs them off and adds the crumb.
 */
.zpe-nav-app {
  /* In the app's flow, where its row was, NOT sticky over it. A page glow is `background-attachment: fixed`, so a
   * sticky bar with a ground would cut the glow off at its own edge: the band this variant exists to remove. */
  position: static;
  z-index: auto;
  /* THE HEADER'S OWN EDGE, ADDED 2026-10-29. This block shipped with no rule under it in any state, because a
   * page-wide divider under a strip is the tell of chrome sitting above the app. The owner's cold read of
   * `/crew` named what that left behind: the header and the body shared one plane, so the row read flat while
   * every card under it had a container. The bar is placed inside the app's own column, so a hairline here is
   * the bottom edge of that app's header and stops at the column rather than crossing the viewport. 12% ink:
   * lighter than the containers the body's cards carry, and never a band. */
  border-bottom: 1px solid color-mix(in srgb, var(--ink) 12%, transparent);
  /* The page's own ground, glow included. `background: none` also clears the library's 88% wash, and no blur. */
  background: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  /* The app supplies the measure: its own row already sits in the app's column, with the app's own gutter. A bar
   * that insets itself again would misalign the first row from everything under it. */
  padding: 0.25rem 0;
  gap: 0.35rem 1rem;
  min-height: 2.5rem;
}

/* The placeholder, before the script lands: an app row reserves the row's own height, not the site bar's 3.4rem. */
[data-zpe-bar][data-zpe-variant='app'] {
  min-height: 2.5rem;
}

/* The app's row, moved in as nodes. It keeps its own classes and its own sheet; this only gives it a place and
 * lets it give ground before the account corner does. */
.zpe-nav-app .zpe-nav-approw {
  display: flex;
  align-items: center;
  gap: 0.35rem 0.9rem;
  min-width: 0;
  flex-shrink: 1;
}

/* The app's block margins were measured for the PAGE's flow, not for the bar's row: crew's own tabs nav carried
 * its `mt-2` into the bar and pushed the row to 48px against a 40px row. The bar places the block, so the page's
 * margins around it do not apply; the links themselves keep every rule their own sheet gives them. */
.zpe-nav-app .zpe-nav-approw > * {
  margin: 0;
}

/* The app's name, in the app's own voice: the crumb the page drew, not an estate item uppercased at 0.2em. The
 * slash is decoration, so a screen reader hears "/crew" as "crew". */
.zpe-nav-app .zpe-nav-crumb {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  min-height: 24px;
  font-size: var(--fs-sm);
  color: var(--muted);
  white-space: nowrap;
}

.zpe-nav-app .zpe-nav-slash {
  color: var(--muted);
}

.zpe-nav-app .zpe-nav-appname {
  color: var(--ink2);
}

/* THE LIBRARY'S PHONE RULE SETS THE CORNER'S MARGIN TO 0, which is right for a bar whose items have left the row.
 * An app's row never leaves: its links are the app's only navigation. So the corner keeps its push, and the crumb
 * goes instead, because the app's own current tab already says where the reader is. */
.zpe-nav-app .zpe-nav-account {
  margin-left: auto;
  /* The switcher's panel anchors to this corner: absolute under the chip, never over the page's own layout. */
  position: relative;
}

/* THE CHIP IS A CONTROL, AND IT HAS TO LOOK LIKE ONE. Measured 2026-10-29 on `/crew`, signed in, and read cold: the
 * corner's workspace name carried no caret, no box and no underline, so the one thing a person needs to press in an
 * app's header read as a label. The press is a NAVIGATION (the account home's organization pane, where the session's
 * switch lives), so the affordance is a box rather than a caret: a caret promises a list that opens in place, and
 * one organization is not a list (D39). `box-sizing` is set here because the vendored library declares none anywhere,
 * and a 14rem cap that grew by its own padding on one page and not another is two chips.
 *
 * The border is ink at 40%, the same mix-at-the-use the panel's roles are built from, and it measures 3.4:1 on the
 * dark theme's ground at crew (the 3:1 floor for a control boundary: measured 2026-10-30 in the render, #6a6a6e on
 * #111114). Hover and keyboard focus take it to full ink; the ring itself is the browser's, because the vendored
 * sheet draws none and a hand-drawn one here would be the second ring on the estate. Scoped to the app skin: the
 * site bar's corner is the person's and its chip is drawn by the library. */
body .zpe-nav-app .zpe-nav-account .zpe-nav-org {
  box-sizing: border-box;
  /* A BUTTON DOES NOT INHERIT ITS FAMILY OR ITS ROOM. Measured 2026-10-30 on `/crew` after the chip became the switcher:
   * a `<button>` renders in the browser's own Arial at 13.33px, with a 17px box, inside a bar whose every other word is
   * the page's system font. So the chip takes the parent's font outright, and its box is held at the 24px floor the
   * pointer target needs rather than at whatever the UA's line box happens to be. */
  font: inherit;
  /* AND ITS OWN SIZE. Inheriting the family is right; inheriting the corner's 11px is not, because this text is a
   * workspace's name rather than a label, and 11px read as a control is the smallest legible thing on the row. */
  font-size: 0.8125rem;
  min-height: 1.5rem;
  /* THE CAP IS THE NAME'S, NOT THE BOX'S. The one bar rule the library block does not carry caps the chip at
   * 14rem so a long workspace cannot take the row; with `border-box` that cap would now include the padding and
   * border this rule adds, and the name the box exists to show would ellipsize four pixels early. So the box's own
   * width rides outside the text's room. */
  max-width: calc(14rem + 1rem + 2 * var(--border));
  padding: 0 0.5rem;
  border: 1px solid color-mix(in srgb, var(--ink) 40%, transparent);
  border-radius: var(--radius-sm);
  /* THE NAME AND ITS CHEVRON SHARE ONE BOX. Added with the chevron on 2026-10-29: two children in an anchor would
   * otherwise sit as inline boxes with the gap of the space between them, which differs per page font. `inline-flex`
   * with one 0.3rem gap makes the box's inside a fixed thing, and the svg takes its size from its own attributes. */
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  /* A REST WASH, ADDED 2026-10-29. The body's buttons carry fills, and an outline drawn on the page's own
   * ground left the one pressable thing in the header with less presence than text that is only text. 6% ink
   * reads as a surface at rest while still sharing the page's ground; hover and focus stay the border and the
   * ink, never a lift. */
  background: color-mix(in srgb, var(--ink) 6%, transparent);
  color: var(--ink2);
  transition: border-color var(--dur-2) ease, color var(--dur-2) ease;
}

body .zpe-nav-app .zpe-nav-account .zpe-nav-org:is(:hover, :focus-visible) {
  border-color: var(--ink);
  color: var(--ink);
}

/* REDUCED MOTION. The chip's border and its ink are the only things this file ever fades, and a reader who asked
 * for less motion gets the state change without the fade. Measured 2026-10-29 by the design gate: this file
 * animates and carried no branch, which is a finding rather than a taste, so it is answered here instead of in
 * the ratchet's baseline. The selector is the chip's own, so the skin still declares no rule the library owns. */
@media (prefers-reduced-motion: reduce) {
  body .zpe-nav-app .zpe-nav-account .zpe-nav-org {
    transition: none;
  }
}

/* ── the switcher's panel: which workspace am I acting in ──────────────────────────────────────────
 * A MENU, NOT A SECOND LAYER. It opens under the chip, on a card surface the library already defines, and closes on a
 * click away or Escape. No shadow and no scrim: the app skin's whole argument is that an app screen carries no estate
 * chrome above it, and a popover anchored to its own control is part of that control rather than chrome over the page.
 * The ground is the card token, the edge is the card line, and the rows are the library's own radius and ink. */
.zpe-nav-switch {
  position: absolute;
  top: calc(100% + 0.4rem);
  right: 0;
  z-index: 30;
  min-width: 13rem;
  max-width: 20rem;
  padding: 0.35rem;
  background: var(--card-bg);
  border: 1px solid var(--card-line);
  border-radius: var(--radius-sm);
  text-align: left;
  /* THE PANEL IS PROSE, NOT A LABEL. The corner it hangs from is uppercased and letter-spaced by the library, and a
   * sentence that inherits both reads as a shout that is clipped at the panel's edge. Measured 2026-10-30 in the owner's
   * own screenshot ("YOU ARE NOT ACTING IN AN ORGANIZATI…"). So the panel resets the three typographic rules it would
   * otherwise inherit, and every sentence inside it wraps. */
  text-transform: none;
  letter-spacing: normal;
  white-space: normal;
}

/* A hidden panel is hidden, not merely attribute-marked: `display` wins over the library's own block layout. */
.zpe-nav-switch[hidden] {
  display: none;
}

.zpe-nav-switch-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  min-height: 2rem;
  padding: 0 0.5rem;
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--ink2);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

/* A HIDDEN ROW IS HIDDEN. The filter sets the attribute, and this class's own `display: flex` would win over it
 * without this rule, which is the one line that makes a filtered list actually filtered. */
.zpe-nav-switch-row[hidden] {
  display: none;
}

/* THE MARK DOES NOT SHRINK. A workspace name is free text and the panel is 13 to 20 rem wide, so the row ellipsizes
 * the name; a mark cut with it would be the first thing lost, and the mark is the row's shape. The name owns the
 * truncation and the mark keeps its size, which is the whole of this feature's layout. The mark is ink on a hairline
 * and never a hue: this sheet cannot name a colour (the estate sheet owns the palette) and the hues it could name are
 * the status ones, which would read as an alert about the workspace beside them. */
.zpe-nav-switch-mark {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 1.25rem;
  height: 1.25rem;
  border: 1px solid var(--card-line);
  border-radius: 6px;
  background: color-mix(in srgb, var(--ink) 5%, transparent);
  color: var(--ink2);
  font-size: 0.6875rem;
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

.zpe-nav-switch-name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* THE FILTER IS A MENU'S FIELD, NOT A PAGE'S. It is drawn at four rows and up, so it takes the panel's hairline and
 * ground rather than the site panel's larger 40px search box; the field and the rows are one control. */
.zpe-nav-switch-search {
  display: block;
  width: 100%;
  min-height: 1.9rem;
  margin: 0 0 0.25rem;
  padding: 0 0.5rem;
  font: inherit;
  color: var(--ink);
  background: color-mix(in srgb, var(--ink) 5%, transparent);
  border: 1px solid var(--card-line);
  border-radius: var(--radius-sm);
  -webkit-appearance: none;
  appearance: none;
}

.zpe-nav-switch-search::placeholder {
  color: var(--muted);
}

/* A FIELD THAT TAKES THE KEYBOARD HAS TO SHOW IT. `outline: none` on `:focus` deletes the only affordance a keyboard
 * user has (the estate's own gate refuses it), so the field keeps its outline and only styles the ring it draws. */
.zpe-nav-switch-search:focus-visible {
  outline: 2px solid color-mix(in srgb, var(--ink) 55%, transparent);
  outline-offset: 1px;
}

.zpe-nav-switch-row:is(:hover, :focus-visible) {
  background: color-mix(in srgb, var(--ink) 8%, transparent);
  color: var(--ink);
}

.zpe-nav-switch-row[aria-current='true'] {
  color: var(--ink);
}

.zpe-nav-switch-tick {
  flex: 0 0 auto;
  color: var(--ink);
}

.zpe-nav-switch-rule {
  height: 1px;
  margin: 0.3rem 0.25rem;
  background: var(--card-line);
}

.zpe-nav-switch-note,
.zpe-nav-switch-empty {
  margin: 0.35rem 0.5rem 0.15rem;
  color: var(--muted);
  font-size: 0.8125rem;
  line-height: 1.35;
  /* A sentence wraps, and a long word breaks rather than widening the panel. */
  white-space: normal;
  overflow-wrap: anywhere;
}

.zpe-nav-switch-more {
  display: block;
  margin: 0.35rem 0.5rem 0.2rem;
  color: var(--ink2);
  font-size: 0.8125rem;
  text-decoration: none;
}

@media (max-width: 34rem) {
  /* ON A PHONE THE BAR IS TWO LINES, and the split is the app's: the mark, the app's name and the app's own row
   * share the first line, and the account strip (the organization, then the person) takes the second. Measured at
   * 390 on crew's ledger: mark 29 + crumb 40 + tabs 173 fits a 358px column, and the organization's 210 + the
   * person's 107 fit the second line together. The first draft put the account on line one and deleted the crumb
   * to make room; a cold read called that out by name, because the word that names the app was the one thing
   * responsive-deleted rather than compressed. */
  .zpe-nav-app {
    flex-wrap: wrap;
  }
  .zpe-nav-app .zpe-nav-account {
    /* Full width and spread, so the strip shares the header's LEFT rail with the mark above it: the cold read
     * measured the first draft's line two starting at CSS 42 against line one's 16, which read as a second bar
     * inset into the first. The organization takes the rail, the person takes the right edge. */
    flex-basis: 100%;
    justify-content: space-between;
  }
}

/* ── the panel: the universe, one press from any page ───────────────────────────────────────────── */

/* THE PANEL'S OWN PALETTE, IN THE LIBRARY'S ROLES. Until 2026-10-29 every value below was one of the site sheet's
 * own tokens (--zpe-ink-dim, --zpe-line, --zpe-ground-raised ...), which arrived through the sheet this file imports.
 * That sheet is the page library's four sheets now (plan: one-vocabulary, task 7), and the library names no dim,
 * faint or rule role: components.css mixes ink at the use, and so does the door. So the panel mixes them here, at the
 * ratios it rendered before the move (measured on the live panel 2026-10-29: dim 55%, faint 34%, rule 14%, strong
 * rule 26%). The names are prefixed `--bar-` so a page's own `--dim`/`--rule` is never shadowed by the bar it wears. */
/* ON THE ELEMENTS THE BAR DRAWS, NOT ON :root. A custom property declared at :root is computed THERE, so
 * `color-mix(in srgb, var(--ink) ...)` froze against :root's ink: the page library's default palette, which is
 * light (#18181b), on a page that draws dark. Measured on the live door 2026-10-29 07:52 ICT: the panel opened from
 * APPS was rgb(255,255,255) with 43 rows at 55% of #18181b, and its scrim covered the page in white at 62%. Declaring
 * the same roles on the chrome's own elements computes them from the ink that element actually inherits, so a panel
 * opened over any surface renders in that surface's palette. No colour is named here: the ratios are the ones the
 * panel rendered before the move (dim 55%, faint 34%, rule 14%, strong rule 26%). */
.zpe-nav,
.zpe-nav-panel,
.zpe-nav-scrim {
  --bar-dim: color-mix(in srgb, var(--ink) 55%, transparent);
  --bar-faint: color-mix(in srgb, var(--ink) 34%, transparent);
  --bar-rule: color-mix(in srgb, var(--ink) 14%, transparent);
  --bar-rule2: color-mix(in srgb, var(--ink) 26%, transparent);
}

/* The dialog's own name. It exists for a screen reader, which is the point: measured 2026-10-28, the panel had no
 * accessible name at all while a scrim covered the page. Not drawn, and never announced twice. */
.zpe-nav-panel-title {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: calc(-1 * var(--border));
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.zpe-nav-panel {
  position: fixed;
  inset-inline: 0;
  top: var(--zpe-nav-h, 3.5rem);
  z-index: 55;
  max-height: min(70vh, 40rem);
  overflow: auto;
  background: var(--raised);
  border-top: 1px solid var(--bar-rule);
  border-bottom: 1px solid var(--bar-rule2);
}

/* The page behind an open panel is dimmed, so the edge of the menu is a change of light and not a guess. It
   is also the click target that closes: no shadow, because the system does not have one. */
.zpe-nav-scrim {
  position: fixed;
  inset: 0;
  z-index: 50;
  background: var(--scrim);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
}

.zpe-nav-scrim[hidden] {
  display: none;
}

.zpe-nav-panel[hidden] {
  display: none;
}

.zpe-nav-panel-inner {
  /* The same measure as the pages themselves, so a panel opens over the column a reader is already in. */
  max-width: 68rem;
  margin: 0 auto;
  padding: 1.6rem clamp(1.25rem, 4vw, 2.5rem) 1.2rem;
}

.zpe-nav-loading {
  margin: 0;
  font-size: 0.86rem;
  color: var(--bar-dim);
}

/* A field in the panel, not a field in a form: 40px, one line, over the whole list. Measured on the 42-link
   build, the tallest column carried 19 rows and a person looking for one of them was reading, not choosing. */
.zpe-nav-searchrow {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin: 0 0 1.3rem;
}

body .zpe-nav-panel .zpe-nav-search {
  flex: 1;
  min-width: 0;
  min-height: 40px;
  padding: 0 0.9rem;
  font: 400 0.94rem/1.2 var(--font-sans);
  color: var(--ink);
  background: color-mix(in srgb, var(--ink) 5%, var(--raised));
  border: 1px solid var(--bar-rule2);
  border-radius: 8px;
  -webkit-appearance: none;
  appearance: none;
}

body .zpe-nav-panel .zpe-nav-search::placeholder {
  color: var(--bar-faint);
}

body .zpe-nav-panel .zpe-nav-search:focus {
  outline: none;
  border-color: var(--bar-rule2);
}

.zpe-nav-count {
  margin: 0;
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  color: var(--bar-faint);
  white-space: nowrap;
}

.zpe-nav-none {
  margin: 0;
  font-size: 0.9rem;
  color: var(--bar-dim);
}

.zpe-nav-groups {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(11.5rem, 1fr));
  gap: 1.2rem 1.6rem;
}

/* The estate sheet styles `body.zpe h2` at 1.45rem, which is the page's section head and not a column label:
 * unscoped, every group title rendered at page-heading size and the panel read as ten sections rather than
 * one map. One class more than `body.zpe h2` is what wins it. */
body .zpe-nav-panel .zpe-nav-group h2 {
  margin: 0 0 0.5rem;
  font-size: 0.62rem;
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--bar-faint);
}

/* A group past ten rows takes two of the panel's columns and flows its list into two, so the panel's height is
   not set by its worst column. On one column of screen it takes one, because two lists at 390px is a scrollbar. */
.zpe-nav-group-wide {
  grid-column: span 2;
}

@media (max-width: 44rem) {
  .zpe-nav-group-wide {
    grid-column: auto;
  }
}

body .zpe-nav-panel .zpe-nav-group-wide ul {
  columns: 2;
  column-gap: 1.4rem;
}

body .zpe-nav-panel .zpe-nav-group-wide li {
  break-inside: avoid;
}

.zpe-nav-group-n {
  margin-left: 0.45rem;
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: 0.6rem;
  letter-spacing: 0.02em;
  color: var(--bar-faint);
  opacity: 0.7;
}

body .zpe-nav-panel .zpe-nav-group ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

/* One row per app, and the status mark sits in its own column: measured on the first render, an inline mark
 * after labels of different lengths made a ragged right edge that read as noise rather than a mark. */
body .zpe-nav-panel .zpe-nav-group li {
  margin: 0;
}

body .zpe-nav-panel .zpe-nav-group a {
  display: grid;
  grid-template-columns: 1fr 2.6rem;
  align-items: baseline;
  column-gap: 0.5rem;
  min-height: 26px;
  font-size: 0.92rem;
  line-height: 1.45;
  color: var(--bar-dim);
  border: 0;
  text-decoration: none;
}

body .zpe-nav-panel .zpe-nav-group a:hover {
  color: var(--ink);
}

body .zpe-nav-panel .zpe-nav-group a[aria-current='page'] {
  color: var(--ink);
  font-weight: 500;
  text-decoration: underline;
  text-underline-offset: 4px;
}

.zpe-nav-mark-beta,
.zpe-nav-mark-wip,
.zpe-nav-mark-draft {
  justify-self: end;
  text-align: end;
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: 0.62rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.zpe-nav-mark-beta {
  color: var(--bar-faint);
}

.zpe-nav-mark-wip,
.zpe-nav-mark-draft {
  color: var(--warn);
}

.zpe-nav-source {
  margin: 1.2rem 0 0;
  padding-top: 0.9rem;
  border-top: 1px solid var(--bar-rule);
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  color: var(--bar-faint);
}

body .zpe-nav-panel .zpe-nav-source a {
  color: var(--bar-dim);
  border: 0;
}

/* A phone keeps one panel: the group columns narrow so a 390px screen still reads two of them. The bar's own
   phone rule, which hides the four section links, is the library's. */
@media (max-width: 34rem) {
  .zpe-nav-groups {
    grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
  }
}
