/* ==========================================================================
   Plek Design System v6 — product UI
   --------------------------------------------------------------------------
   The application layer. Everything here is evidenced by the one product
   screen the Framer file contains (the dashboard in the hero frame):
   white-gray panels separated by 1px rules, a 220px sidebar with icon+label
   rows and a tinted active row, ruled stat cards, a dense table, thin
   charcoal progress bars and bordered list rows with a footer strip.

   Components the dashboard does not show — forms, status colors, alerts,
   modal, empty state, tooltip, pagination — are marked EXTENSION in their
   section comment. They are derived from the same rules: 1px rules, radius
   2/4, no shadow, no gradient, no loop.

   Load order: tokens.css -> base.css -> components.css -> app.css
              -> loader.css (any surface that shows a busy state)
   Depends on components.css for: .pk-btn (+ --solid/--ghost/--quiet/--sm),
   .pk-iconbtn (+ --sm), .pk-seg/.pk-seg__btn, .pk-icon, .pk-icons, .pk-tag,
   .pk-skip. It depends on base.css for the type roles it composes on in
   markup: .pk-stat carries the stat-card number. It refers to, but never
   styles, .plek-loader — the official loader in css/loader.css, which is the
   system's ONE sanctioned looping animation and its only busy indicator.

   Doubled class names (.pk-box__title.pk-box__title) are deliberate. Those
   classes are worn by bare h2/h3/p/a/li elements, and a host page — the
   documentation shell included — may style those elements at (0,1,1). The
   component has to win wherever it is dropped in, so its own rule is raised
   to (0,2,0). Nothing else in this file needs it.

   Dense-UI type: the product screen runs 12-13px, on --pk-fs-caption (12)
   and --pk-fs-ui (13); 12 is the smallest size the system has. Nothing is
   raw: no hex, no font size, no radius, no layer and no duration in this
   file is written by hand.

   Targets: every control in this file is at least 24x24 CSS px (WCAG 2.2
   Target Size (Minimum), 2.5.8). Where a label is smaller than that, the
   padding — never the type — carries it to 24.
   ========================================================================== */

/* ==========================================================================
   1. SHELL — .pk-app
   --------------------------------------------------------------------------
   Two columns: a sticky sidebar and a main column with its own sticky
   header. The three layout constants live as scoped custom properties on
   .pk-app (mechanics, not design tokens) so the responsive steps only have
   to change a number.

   Responsive: >=1200 full sidebar, 810-1199 icon rail (64px), <810 the
   sidebar becomes a horizontally scrollable top bar. CSS only.
   ========================================================================== */

.pk-app {
  --pk-app-side: 220px;      /* sidebar width, desktop */
  --pk-app-rail: 200px;      /* sub-menu rail, general page */
  --pk-app-bar: 56px;        /* brand row = header row */
  --pk-app-band: 44px;       /* the second band: rail head = content head */
  --pk-app-gutter: var(--pk-sp-6);

  display: grid;
  grid-template-columns: var(--pk-app-side) minmax(0, 1fr);
  min-height: 100vh;
  background: var(--pk-ground);
  color: var(--pk-ink);
  font-family: var(--pk-font-body);
  font-size: var(--pk-fs-ui);
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-ui);
}
/* documentation / preview: the shell inside an example stage is not the page */
.pk-app--embedded { min-height: 0; }

.pk-app__side {
  position: sticky;
  top: 0;
  align-self: start;
  height: 100vh;
  min-width: 0;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  background: var(--pk-surface);
  border-right: var(--pk-line) solid var(--pk-rule);
}
.pk-app--embedded .pk-app__side { position: static; height: auto; }

/* logo + wordmark + collapse control */
.pk-app__brand.pk-app__brand {
  display: flex;
  align-items: center;
  gap: var(--pk-sp-2);
  height: var(--pk-app-bar);
  flex: none;
  padding-inline: var(--pk-sp-5);
  border-bottom: var(--pk-line) solid var(--pk-rule);
  text-decoration: none;
  color: var(--pk-ink);
}
.pk-app__brand > img,
.pk-app__brand > svg { width: 20px; height: 20px; flex: none; }
.pk-app__name {
  font-family: var(--pk-font-body);
  font-size: var(--pk-fs-lead);
  font-weight: 500;
  letter-spacing: var(--pk-ls-display);
  color: var(--pk-ink-strong);
}
/* --------------------------------------------------------------------------
   PRODUCT EXTENSION OF .pk-iconbtn (components.css owns the base: 48px, and
   --sm at 32px). Product chrome runs at two densities components.css does not
   carry, so both are added here and nowhere else:

     --xs     24x24 — the smallest square the target rule allows, and the
              only size that fits the 44px --pk-app-band beside a 30px
              control without stretching it.
     --quiet  no border, no fill: a glyph that belongs to the chrome rather
              than to the content. It keeps the 24px hit area.

   Every bespoke chrome button below is now COMPOSED on .pk-iconbtn:
     class="pk-iconbtn pk-iconbtn--xs pk-iconbtn--quiet pk-app__collapse"
   and the bespoke class carries only its placement, never a second copy of
   the button recipe.
   -------------------------------------------------------------------------- */
.pk-iconbtn--xs { width: 24px; height: 24px; }
.pk-iconbtn--xs > svg { width: 16px; height: 16px; }
.pk-iconbtn.pk-iconbtn--quiet {
  border-color: transparent;
  background: transparent;
  color: var(--pk-muted);
  transition: background-color var(--pk-dur-fast) var(--pk-ease-in),
              color var(--pk-dur-fast) var(--pk-ease-in);
}
.pk-iconbtn.pk-iconbtn--quiet:hover { background: var(--pk-card); color: var(--pk-ink); }
.pk-iconbtn.pk-iconbtn--quiet:active { background: var(--pk-card-hover); }

/* Placement only: the recipe is .pk-iconbtn above. */
.pk-app__collapse { margin-left: auto; }

.pk-app__main {
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.pk-app__header {
  position: sticky;
  top: 0;
  z-index: var(--pk-z-nav);
  display: flex;
  align-items: center;
  gap: var(--pk-sp-4);
  min-height: var(--pk-app-bar);
  flex: none;
  padding-inline: var(--pk-app-gutter, var(--pk-sp-6));
  background: var(--pk-ground);
  border-bottom: var(--pk-line) solid var(--pk-rule);
}
.pk-app--embedded .pk-app__header { position: static; }
.pk-app__title.pk-app__title {
  margin: 0;
  font-family: var(--pk-font-body);
  font-size: var(--pk-fs-title);
  font-weight: 400;
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-display);
  color: var(--pk-ink-strong);
}
.pk-app__actions {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: var(--pk-sp-2);
}

.pk-app__body { flex: 1 1 auto; min-width: 0; }

/* the content grid: cells are separated by 1px rules, never by gutters */
.pk-app__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--pk-line);
  background: var(--pk-rule);
  align-content: start;
}
.pk-app__grid > * { background: var(--pk-surface); }
.pk-app__grid--split { grid-template-columns: minmax(0, 1fr) 380px; }

@media (max-width: 1199.98px) {
  .pk-app { --pk-app-side: 64px; --pk-app-gutter: var(--pk-sp-5); }
  .pk-app__brand.pk-app__brand { padding-inline: 0; justify-content: center; gap: 0; }
  .pk-app__name,
  .pk-app__collapse { display: none; }
  .pk-app__grid--split { grid-template-columns: minmax(0, 1fr) 320px; }
}
/* A COMPONENT breakpoint, not a system one. --split is main + a 380px rail;
   at 1000px the sidebar is already the 64px icon rail, so the main cell would
   be under 600px with the rail still beside it — narrower than the table it
   holds. The rail drops under the main cell here and nowhere else, which is
   why this number is not one of the two system breakpoints. */
@media (max-width: 999.98px) {
  .pk-app__grid--split { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 809.98px) {
  .pk-app {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr);
    --pk-app-gutter: var(--pk-sp-4);
  }
  .pk-app__side {
    position: static;
    height: auto;
    flex-direction: row;
    align-items: center;
    overflow-x: auto;
    overflow-y: hidden;
    border-right: 0;
    border-bottom: var(--pk-line) solid var(--pk-rule);
  }
  .pk-app__brand.pk-app__brand {
    border-bottom: 0;
    border-right: var(--pk-line) solid var(--pk-rule);
    padding-inline: var(--pk-sp-4);
  }
}

/* ==========================================================================
   2. GENERAL PAGE — .pk-app__work, .pk-submenu, .pk-content, .pk-search
   --------------------------------------------------------------------------
   The second layout. The dashboard is rail-less: one header, one content
   grid. Every other section of the product has a second menu — the section's
   own pages — and that is this layout: primary menu, sub-menu rail, content.
   It is the shape the production shell already has
   (product/templates/product/app_base.html), reduced to three bands instead
   of four and re-hung on the system's tokens.

   Heights: the app header is --pk-app-bar (56px); the rail head and the
   content head share --pk-app-band (44px) so their bottom rules join into one
   line across the layout, exactly as the production shell's two 48px bands
   do. Widths: sidebar 220px, rail 200px — the rail is narrower on purpose,
   because it is the secondary menu.

   .pk-app--fill bounds the shell to the viewport so the rail and the content
   scroll on their own, which is what an application does. Without it the
   whole page scrolls, which is what the documentation needs.
   ========================================================================== */

.pk-app--fill { height: 100vh; }
.pk-app--fill .pk-app__main { min-height: 0; }
.pk-app--embedded.pk-app--fill { height: auto; }

/* the work area: rail | content, separated by one hairline, no gutter */
.pk-app__work {
  display: grid;
  grid-template-columns: var(--pk-app-rail) minmax(0, 1fr);
  gap: var(--pk-line);
  background: var(--pk-rule);
  flex: 1 1 auto;
  min-width: 0;
  min-height: 0;
}
.pk-app__work > * { background: var(--pk-ground); }

/* ---- the rail ---------------------------------------------------------- */
.pk-submenu {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
}
.pk-submenu__head {
  display: flex;
  align-items: center;
  gap: var(--pk-sp-2);
  flex: none;
  height: var(--pk-app-band);
  padding: 0 var(--pk-sp-2) 0 var(--pk-sp-5);
  border-bottom: var(--pk-line) solid var(--pk-rule);
}
/* The rail is labeled, not titled: the section is named once, by the page
   header. This band says what the list is. */
.pk-submenu__title.pk-submenu__title {
  /* The same voice as the rows it heads and as the workspace name in the band
     beside it (.pk-switcher): Inter 13 / 500 in black. Not a mono caption —
     Space Mono is for section labels and counts, and this is a menu heading. */
  margin: 0;
  font-family: var(--pk-font-body);
  font-size: var(--pk-fs-ui);
  font-weight: 500;
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink-strong);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pk-submenu__collapse { margin-left: auto; }

.pk-submenu__nav {
  display: flex;
  flex-direction: column;
  gap: var(--pk-sp-1);
  flex: 1 1 auto;
  min-height: 0;
  padding: var(--pk-sp-2);
  overflow-y: auto;
}
.pk-submenu__group.pk-submenu__group {
  margin: var(--pk-sp-3) 0 0;
  padding: 0 var(--pk-sp-3) var(--pk-sp-1);
  font-family: var(--pk-font-mono);
  font-size: var(--pk-fs-caption);
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-body);
  color: var(--pk-muted);
}
.pk-submenu__group.pk-submenu__group:first-child { margin-top: 0; }

/* The same tinted row as .pk-sidenav, one step quieter: inset inside a 2px
   pill instead of running full bleed, 16px icons instead of 18. */
.pk-submenu__item.pk-submenu__item {
  display: flex;
  align-items: center;
  gap: var(--pk-sp-3);
  width: 100%;
  min-height: 30px;
  margin: 0;
  padding: var(--pk-sp-2) var(--pk-sp-3);
  border: 0;
  border-radius: var(--pk-radius-s);
  background: transparent;
  font-family: var(--pk-font-body);
  font-size: var(--pk-fs-ui);
  font-weight: 400;
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink-strong);   /* same rule as the primary menu: black at rest */
  text-align: left;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--pk-dur-fast) var(--pk-ease-in),
              color var(--pk-dur-fast) var(--pk-ease-in);
}
.pk-submenu__item > svg { width: 16px; height: 16px; flex: none; color: var(--pk-ink); }
.pk-submenu__label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pk-submenu__count {
  margin-left: auto;
  flex: none;
  font-family: var(--pk-font-mono);
  font-size: var(--pk-fs-caption);
  letter-spacing: var(--pk-ls-body);
  font-variant-numeric: tabular-nums;
  color: var(--pk-muted);
}
.pk-submenu__item:hover { background: var(--pk-card-hover); color: var(--pk-ink-strong); }
.pk-submenu__item:hover > svg { color: var(--pk-ink-strong); }
/* One state, two spellings: a pane button is selected, a link is current. */
.pk-submenu__item[aria-selected="true"],
.pk-submenu__item[aria-current="page"] {
  background: var(--pk-card);
  color: var(--pk-ink-strong);
  font-weight: 500;
}
.pk-submenu__item[aria-selected="true"] > svg,
.pk-submenu__item[aria-current="page"] > svg { color: var(--pk-ink-strong); }
.pk-submenu__item[aria-selected="true"] .pk-submenu__count,
.pk-submenu__item[aria-current="page"] .pk-submenu__count { color: var(--pk-ink-2); }

.pk-submenu__foot {
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--pk-sp-3);
  padding: var(--pk-sp-3) var(--pk-sp-5);
  border-top: var(--pk-line) solid var(--pk-rule);
  font-size: var(--pk-fs-caption);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-muted);
}

/* ---- the content column ------------------------------------------------ */
.pk-content {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
}
.pk-content__head {
  display: flex;
  align-items: center;
  gap: var(--pk-sp-3);
  flex: none;
  /* A FIXED height, not a minimum: this band and .pk-submenu__head draw one
     continuous rule, so a tall control must never be able to stretch it. */
  height: var(--pk-app-band);
  padding: 0 var(--pk-app-gutter, var(--pk-sp-6));
  border-bottom: var(--pk-line) solid var(--pk-rule);
}
/* controls in the band are sized to it (30px in a 44px band) */
.pk-content__tools .pk-input,
.pk-content__tools .pk-select { min-height: 30px; height: 30px; padding-block: 0; }
.pk-content__expand { display: none; margin-right: var(--pk-sp-1); }
.pk-content__title.pk-content__title {
  margin: 0;
  min-width: 0;
  font-family: var(--pk-font-body);
  font-size: var(--pk-fs-body);
  font-weight: 400;
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-display);
  color: var(--pk-ink-strong);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* the size of the collection, beside its name in the band */
.pk-content__count.pk-content__count {
  margin: 0;
  flex: none;
  font-size: var(--pk-fs-caption);
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-ui);
  font-variant-numeric: tabular-nums;
  color: var(--pk-muted);
  white-space: nowrap;
}
.pk-content__tools {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: var(--pk-sp-2);
  min-width: 0;
}

.pk-content__body {
  flex: 1 1 auto;
  min-height: 0;
  min-width: 0;
  overflow-y: auto;
}
/* Sections carry the gutter, not the scroll area: the rule under a section
   has to reach both edges, or it reads as a card on a ground. */
.pk-content__section {
  display: grid;
  gap: var(--pk-sp-5);
  align-content: start;
  padding: var(--pk-sp-7) var(--pk-app-gutter, var(--pk-sp-6));
  border-bottom: var(--pk-line) solid var(--pk-rule);
}
.pk-content__section:last-child { border-bottom: 0; }
.pk-content__section-head {
  display: flex;
  align-items: flex-start;
  gap: var(--pk-sp-4);
  flex-wrap: wrap;
}
.pk-content__section-title.pk-content__section-title {
  margin: 0;
  font-family: var(--pk-font-body);
  font-size: var(--pk-fs-body);
  font-weight: 400;
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-display);
  color: var(--pk-ink-strong);
}
.pk-content__section-text.pk-content__section-text {
  margin: var(--pk-sp-1) 0 0;
  max-width: var(--pk-measure-text);
  font-size: var(--pk-fs-caption);
  letter-spacing: var(--pk-ls-ui);
  line-height: var(--pk-lh-snug);
  color: var(--pk-muted);
}
.pk-content__section-actions {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: var(--pk-sp-2);
}
/* settings and forms: the rules still span the column, the reading does not */
.pk-content--narrow .pk-content__section > * { max-width: var(--pk-measure-text); }

/* ---- expandable search ------------------------------------------------- */
/* Without script there is no data-collapsed attribute, so the field is simply
   visible and the toggle is not rendered at all: a plain labeled input. */
.pk-search { display: flex; align-items: center; min-width: 0; }
.pk-search__toggle { display: none; }
.pk-search__field {
  display: flex;
  align-items: center;
  gap: var(--pk-sp-2);
  min-height: 24px;
  min-width: 0;
  padding-inline: var(--pk-sp-2);
  border: var(--pk-line) solid var(--pk-control-border);
  border-radius: var(--pk-radius-s);
  background: var(--pk-surface);
}
.pk-search__field > svg { width: 14px; height: 14px; flex: none; color: var(--pk-muted); }
.pk-search__input {
  width: 150px;
  max-width: 100%;
  min-width: 0;
  min-height: 24px;            /* the field is the control; the input is its target */
  padding: var(--pk-sp-1) 0;
  border: 0;
  background: transparent;
  font-family: var(--pk-font-body);
  font-size: var(--pk-fs-ui);
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink);
}
.pk-search__input::placeholder { color: var(--pk-muted); }
.pk-search__input:focus { outline: 0; }
.pk-search__field:focus-within { border-color: var(--pk-ink); outline: 2px solid var(--pk-ink); outline-offset: 1px; }
.pk-search[data-collapsed="true"] .pk-search__toggle { display: inline-flex; }
.pk-search[data-collapsed="true"] .pk-search__field { display: none; }

/* ---- collapsed rail ----------------------------------------------------- */
/* The rail does not shrink to an icon strip: it leaves, and the content takes
   the width. The way back is the expand control in the content header, which
   only exists while the rail is away. */
@media (min-width: 810px) {
  .pk-submenu[data-collapsed="true"] { display: none; }
  .pk-app__work:has(> .pk-submenu[data-collapsed="true"]) {
    grid-template-columns: minmax(0, 1fr);
    gap: 0;
  }
  .pk-app__work:has(> .pk-submenu[data-collapsed="true"]) .pk-content__expand {
    display: inline-flex;
  }
}

@media (max-width: 1199.98px) {
  .pk-app { --pk-app-rail: 180px; }
}
/* Phone: the rail becomes a scrollable row of entries under the header. No
   collapse control — there is nothing to give the width back to. */
@media (max-width: 809.98px) {
  .pk-app--fill { height: auto; min-height: 100vh; }
  .pk-app__work {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr);
  }
  .pk-submenu,
  .pk-submenu[data-collapsed="true"] {
    display: flex;
    flex-direction: row;
    align-items: center;
    overflow-x: auto;
    overflow-y: hidden;
  }
  .pk-submenu__head,
  .pk-submenu__foot,
  .pk-content__expand { display: none; }
  .pk-submenu__nav {
    flex-direction: row;
    overflow-y: hidden;
    overflow-x: visible;
    padding: var(--pk-sp-2);
  }
  .pk-submenu__item.pk-submenu__item { width: auto; flex: none; }
  .pk-content__body { overflow-y: visible; }
  .pk-content__section { padding-block: var(--pk-sp-6); }
  .pk-search__input { width: 120px; }
}

/* ==========================================================================
   3. SIDE NAVIGATION — .pk-sidenav, .pk-switcher
   --------------------------------------------------------------------------
   Rows are full-bleed: the active tint runs edge to edge, as it does in the
   design. One row carries aria-current="page" — that attribute, not a class,
   is the state.
   ========================================================================== */

.pk-switcher {
  display: flex;
  align-items: center;
  gap: var(--pk-sp-2);
  width: 100%;
  flex: none;
  min-height: 44px;
  padding: var(--pk-sp-2) var(--pk-sp-5);
  border: 0;
  border-bottom: var(--pk-line) solid var(--pk-rule);
  background: var(--pk-surface);
  font-family: var(--pk-font-body);
  font-size: var(--pk-fs-ui);
  font-weight: 500;
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink-strong);
  text-align: left;
  cursor: pointer;
  transition: background-color var(--pk-dur-fast) var(--pk-ease-in);
}
/* The switcher is the button of a .pk-menu (section 15). The wrapper must
   not shrink in the sidebar's column, and must not stretch in the phone bar. */
.pk-app__side > .pk-menu { flex: none; min-width: 0; }
.pk-switcher:hover { background: var(--pk-card); }
.pk-switcher > svg { width: 16px; height: 16px; margin-left: auto; color: var(--pk-muted); }
.pk-switcher__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pk-switcher__mark {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; flex: none;
  border: var(--pk-line) solid var(--pk-rule);
  border-radius: var(--pk-radius-s);
  background: var(--pk-card);
  font-size: var(--pk-fs-caption);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink);
}

.pk-sidenav {
  display: flex;
  flex-direction: column;
  gap: var(--pk-sp-1);
  padding-block: var(--pk-sp-2);
  min-width: 0;
}
.pk-sidenav__title.pk-sidenav__title {
  margin: 0;
  padding: var(--pk-sp-2) var(--pk-sp-5) var(--pk-sp-1);
  font-family: var(--pk-font-mono);
  font-size: var(--pk-fs-caption);
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-body);
  color: var(--pk-muted);
}
.pk-sidenav__item.pk-sidenav__item {
  display: flex;
  align-items: center;
  gap: var(--pk-sp-4);
  min-height: 34px;
  padding: var(--pk-sp-2) var(--pk-sp-5);
  border: 0;
  background: transparent;
  font-family: var(--pk-font-body);
  font-size: var(--pk-fs-ui);
  font-weight: 400;
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink-strong);   /* menu text is black at rest; the current row is told apart by its fill and weight, not by ink */
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--pk-dur-fast) var(--pk-ease-in),
              color var(--pk-dur-fast) var(--pk-ease-in);
}
.pk-sidenav__item > svg { width: 18px; height: 18px; flex: none; color: var(--pk-ink); }
.pk-sidenav__label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pk-sidenav__count {
  margin-left: auto;
  font-family: var(--pk-font-mono);
  font-size: var(--pk-fs-caption);
  letter-spacing: var(--pk-ls-body);
  color: var(--pk-muted);
}
.pk-sidenav__item:hover { background: var(--pk-card-hover); color: var(--pk-ink-strong); }
.pk-sidenav__item:hover > svg { color: var(--pk-ink-strong); }
.pk-sidenav__item[aria-current="page"] {
  background: var(--pk-card);
  color: var(--pk-ink-strong);
  font-weight: 500;
}
.pk-sidenav__item[aria-current="page"] > svg { color: var(--pk-ink-strong); }

/* The global band under the workspace's modules (production: .menu-bottom —
   Library, Settings). A second .pk-sidenav, pinned to the foot of the sidebar
   behind a hairline; on the phone top bar it simply continues the row. */
.pk-sidenav--bottom {
  margin-top: auto;
  flex: none;
  border-top: var(--pk-line) solid var(--pk-rule);
}
@media (max-width: 809.98px) {
  .pk-sidenav--bottom { margin-top: 0; border-top: 0; border-left: var(--pk-line) solid var(--pk-rule); }
}

.pk-sidenav__foot {
  margin-top: auto;
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--pk-sp-3);
  padding: var(--pk-sp-4) var(--pk-sp-5);
  border-top: var(--pk-line) solid var(--pk-rule);
  font-size: var(--pk-fs-caption);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-muted);
}

@media (max-width: 1199.98px) {
  .pk-switcher { justify-content: center; padding-inline: 0; }
  .pk-switcher > svg,
  .pk-switcher__name,
  .pk-sidenav__title.pk-sidenav__title,
  .pk-sidenav__count,
  .pk-sidenav__foot { display: none; }
  .pk-sidenav__item.pk-sidenav__item { justify-content: center; padding-inline: 0; }
  .pk-sidenav__label { display: none; }
}
@media (max-width: 809.98px) {
  .pk-switcher {
    width: auto; min-height: 0; padding: var(--pk-sp-2) var(--pk-sp-4);
    border-bottom: 0; border-right: var(--pk-line) solid var(--pk-rule);
  }
  .pk-switcher__name { display: inline; }
  .pk-app__side > .pk-menu.pk-menu--block { width: auto; }
  /* the bar scrolls sideways; nothing in it may shrink, or eight icons overlap */
  .pk-app__brand.pk-app__brand, .pk-switcher { flex: none; }
  .pk-sidenav { flex: none; flex-direction: row; padding: var(--pk-sp-2) var(--pk-sp-2); gap: var(--pk-sp-1); }
  .pk-sidenav__item.pk-sidenav__item { flex: none; min-width: 40px; min-height: 32px; padding-inline: var(--pk-sp-3); border-radius: var(--pk-radius-s); }
}

/* ==========================================================================
   4. STAT CARDS — .pk-statcards / .pk-statcard
   --------------------------------------------------------------------------
   The "Overview" row. Every card carries its own hairline and the cards are
   set 10px apart, so the grid reads as a double rule between cells — the
   drafted frame the marketing page uses, at product density.
   ========================================================================== */

.pk-statcards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--pk-sp-3);
}
.pk-statcards--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.pk-statcards--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

.pk-statcard {
  display: grid;
  gap: var(--pk-sp-4);
  align-content: start;
  padding: var(--pk-sp-6);
  border: var(--pk-line) solid var(--pk-rule);
  border-radius: var(--pk-radius-s);
  background: var(--pk-ground);
}
.pk-statcard__label.pk-statcard__label {
  margin: 0;
  font-size: var(--pk-fs-ui);
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-muted);
}
/* The number is .pk-stat (base.css) — it is the same type role the marketing
   page's "$49.3M" wears, and it is declared once, there. This element adds
   only what a stat inside a card needs: tabular figures so a column of cards
   lines up. It sets no font, no size, no tracking and no color. */
.pk-statcard__value.pk-statcard__value {
  margin: 0;
  font-variant-numeric: tabular-nums;
}
.pk-statcard__meta.pk-statcard__meta {
  display: flex;
  align-items: center;
  gap: var(--pk-sp-2);
  font-size: var(--pk-fs-caption);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-muted);
}
/* exactly one dark card per row — the system's only emphasis */
.pk-statcard--dark {
  background: var(--pk-charcoal);
  border-color: var(--pk-charcoal-2);
}
.pk-statcard--dark .pk-statcard__label,
.pk-statcard--dark .pk-statcard__meta { color: var(--pk-on-dark-2); }
.pk-statcard--dark .pk-statcard__value { color: var(--pk-on-dark); }

/* The ACCENT card: the one number the screen is about (on the dashboard, the
   AI-exposed cost). Sky-wash ground, sky hairline, navy figure — the language
   of an info alert and a selected row. It is COLOR ONLY: it adds no text and
   changes no size, so it never alters the row's height. At most one per row,
   never beside a --dark card. Navy on the wash is 9.0:1, the label 6.5:1. */
.pk-statcard--accent { background: var(--pk-sky-wash); border-color: var(--pk-sky); }
.pk-statcard--accent .pk-statcard__label,
.pk-statcard--accent .pk-statcard__meta { color: var(--pk-ink-2); }
.pk-statcard--accent .pk-statcard__value { color: var(--pk-navy); }

@media (max-width: 809.98px) {
  .pk-statcards--2,
  .pk-statcards--4 { grid-template-columns: minmax(0, 1fr); }
  .pk-statcard { padding: var(--pk-sp-5); }
}

/* ==========================================================================
   5. TITLED PANEL — .pk-box
   --------------------------------------------------------------------------
   The cell every product screen is built from: a title, an optional
   subtitle, optional right-hand actions, a 20px body. It carries no border
   of its own — the .pk-app__grid rules draw the edges — so a box used on its
   own gets .pk-box--ruled.
   ========================================================================== */

.pk-box {
  display: flex;
  flex-direction: column;
  min-width: 0;
  background: var(--pk-surface);
}
.pk-box--ruled { border: var(--pk-line) solid var(--pk-rule); border-radius: var(--pk-radius); }

.pk-box__head {
  display: flex;
  align-items: flex-start;
  gap: var(--pk-sp-4);
  flex-wrap: wrap;
  padding: var(--pk-sp-6) var(--pk-sp-6) var(--pk-sp-5);
}
.pk-box__title.pk-box__title {
  margin: 0;
  font-family: var(--pk-font-body);
  font-size: var(--pk-fs-body);
  font-weight: 400;
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-display);
  color: var(--pk-ink-strong);
}
.pk-box__sub.pk-box__sub {
  margin: var(--pk-sp-1) 0 0;
  font-size: var(--pk-fs-caption);
  letter-spacing: var(--pk-ls-ui);
  line-height: var(--pk-lh-snug);
  color: var(--pk-muted);
}
.pk-box__actions {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: var(--pk-sp-2);
}
.pk-box__body {
  padding: 0 var(--pk-sp-6) var(--pk-sp-6);
  min-width: 0;
}
.pk-box__body--flush { padding: 0; }
.pk-box__foot {
  margin-top: auto;
  display: flex;
  align-items: center;
  gap: var(--pk-sp-4);
  padding: var(--pk-sp-4) var(--pk-sp-6);
  border-top: var(--pk-line) solid var(--pk-rule);
  font-size: var(--pk-fs-caption);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-muted);
}
/* a toolbar line between head and body (the "AI Impact" row with its toggle) */
.pk-box__bar {
  display: flex;
  align-items: center;
  gap: var(--pk-sp-4);
  flex-wrap: wrap;
  padding: 0 var(--pk-sp-6) var(--pk-sp-4);
  font-size: var(--pk-fs-ui);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink);
}
.pk-box__bar > .pk-seg { margin-left: auto; }

@media (max-width: 809.98px) {
  .pk-box__head { padding: var(--pk-sp-5) var(--pk-sp-5) var(--pk-sp-4); }
  .pk-box__body { padding: 0 var(--pk-sp-5) var(--pk-sp-5); }
  .pk-box__body--flush { padding: 0; }
  .pk-box__bar { padding: 0 var(--pk-sp-5) var(--pk-sp-4); }
}

/* ==========================================================================
   6. DATA TABLE — .pk-table
   --------------------------------------------------------------------------
   Dense, ruled, right-aligned numbers. The header is a 12px muted line; rows
   are separated by --pk-rule and nothing else — no zebra, no vertical rules.
   Sorting is a real <button> inside the <th>, and the state lives on the th's
   aria-sort.
   ========================================================================== */

.pk-table-wrap { overflow-x: auto; min-width: 0; }

.pk-table {
  --pk-table-gutter: 0px;
  width: 100%;
  border-collapse: collapse;
  font-family: var(--pk-font-body);
  font-size: var(--pk-fs-ui);
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink);
}
/* inside a flush box body the table keeps the panel's 20px gutter, so the
   row rules still run the full width of the cell */
.pk-box__body--flush .pk-table { --pk-table-gutter: var(--pk-sp-6); }

.pk-table th,
.pk-table td {
  padding: var(--pk-sp-3) var(--pk-sp-4);
  text-align: left;
  vertical-align: middle;
}
.pk-table th:first-child,
.pk-table td:first-child { padding-left: var(--pk-table-gutter); }
.pk-table th:last-child,
.pk-table td:last-child { padding-right: var(--pk-table-gutter); }

/* The header row gives its vertical padding to the sort button, which has to
   reach 24px on its own: the band keeps the height it had, the target grows. */
.pk-table thead th {
  padding-block: var(--pk-sp-1h);
  font-size: var(--pk-fs-caption);
  letter-spacing: var(--pk-ls-ui);
  font-weight: 400;
  color: var(--pk-muted);
  white-space: nowrap;
  border-bottom: var(--pk-line) solid var(--pk-rule);
}
/* a header cell with no button keeps the old rhythm */
.pk-table thead th:not(:has(> .pk-table__sort)) { padding-block: var(--pk-sp-3); }
.pk-table tbody td { border-bottom: var(--pk-line) solid var(--pk-rule); color: var(--pk-ink); }
.pk-table tbody tr:last-child td { border-bottom: 0; }
.pk-table__name { color: var(--pk-ink); }
.pk-table__sub { display: block; margin-top: 2px; font-size: var(--pk-fs-caption); letter-spacing: var(--pk-ls-ui); color: var(--pk-muted); }

/* numeric column: right aligned, tabular figures so digits line up */
/* (0,2,0) on purpose: `.pk-table th, .pk-table td { text-align: left }` is (0,1,1)
   and was silently winning, so numeric columns rendered left-aligned. */
.pk-table .pk-table__num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* --center: a short numeric column read as a value, not summed down the page
   (the dashboard's Cost and AI FTEs). Header and cells center together. */
.pk-table .pk-table__num--center { text-align: center; }

/* rows */
.pk-table tbody tr {
  transition: background-color var(--pk-dur-fast) var(--pk-ease-in);
}
.pk-table tbody tr:hover { background: var(--pk-card-hover); }
/* selection: aria-selected on a row inside role="grid", .is-selected on a
   plain table where the ARIA attribute would not be valid */
.pk-table tbody tr[aria-selected="true"],
.pk-table tbody tr.is-selected { background: var(--pk-sky-wash); }
.pk-table tbody tr[aria-selected="true"]:hover,
.pk-table tbody tr.is-selected:hover { background: var(--pk-sky-wash); }

/* sortable header. The button is the target, so it carries a 24px minimum
   and its own side padding; the negative inline margin pulls the label back
   to the column's edge, so the growth is in the hit area, not in the grid. */
.pk-table__sort {
  display: inline-flex;
  align-items: center;
  gap: var(--pk-sp-1);
  min-height: 24px;
  margin-inline: calc(var(--pk-sp-1h) * -1);
  padding: 0 var(--pk-sp-1h);
  border: 0;
  border-radius: var(--pk-radius-s);
  background: none;
  font: inherit;
  letter-spacing: inherit;
  color: inherit;
  cursor: pointer;
}
.pk-table__sort > svg { width: 12px; height: 12px; color: var(--pk-deco); }
.pk-table__num .pk-table__sort { flex-direction: row-reverse; }
.pk-table__num--center .pk-table__sort { flex-direction: row; }
.pk-table__sort:hover { color: var(--pk-ink); }
.pk-table th[aria-sort="ascending"] .pk-table__sort,
.pk-table th[aria-sort="descending"] .pk-table__sort { color: var(--pk-ink); }
.pk-table th[aria-sort="ascending"] .pk-table__sort > svg { color: var(--pk-ink); }
.pk-table th[aria-sort="descending"] .pk-table__sort > svg { color: var(--pk-ink); transform: rotate(180deg); }
.pk-table th[aria-sort="none"] .pk-table__sort > svg { opacity: 0.6; }

/* A column that holds one control is 1px wide: the cell shrinks to it.
   __pick is the checkbox in front of the row, __act the row's own menu at
   the end of it. */
.pk-table__pick,
.pk-table__act { width: 1px; white-space: nowrap; }
.pk-table__act { text-align: right; }

.pk-table--roomy th,
.pk-table--roomy td { padding-block: var(--pk-sp-4); }

@media (max-width: 809.98px) {
  .pk-box__body--flush .pk-table { --pk-table-gutter: var(--pk-sp-5); }
}

/* ==========================================================================
   7. PROGRESS — .pk-progress
   --------------------------------------------------------------------------
   Determinate ONLY. A thin charcoal bar on a rule-gray track. There is no
   indeterminate variant and there will not be one: a bar that does not know
   how far along it is has nothing to draw, and the thing to show instead is
   the loader (.plek-loader, css/loader.css) with the layout held by a static
   .pk-skeleton.
   ========================================================================== */

.pk-progress { display: grid; gap: var(--pk-sp-2); min-width: 0; }
.pk-progress__track {
  height: var(--pk-sp-1);
  border-radius: var(--pk-radius-xs);
  background: var(--pk-rule);
  overflow: hidden;
}
.pk-progress__bar {
  height: 100%;
  width: 0;
  border-radius: var(--pk-radius-xs);
  background: var(--pk-charcoal);
  transition: width var(--pk-dur) var(--pk-ease);
}
.pk-progress__meta {
  display: flex;
  align-items: baseline;
  gap: var(--pk-sp-3);
  font-size: var(--pk-fs-caption);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-muted);
}
.pk-progress__value { margin-left: auto; font-variant-numeric: tabular-nums; color: var(--pk-ink); }
.pk-progress--tall .pk-progress__track { height: var(--pk-sp-1h); }
.pk-progress--positive .pk-progress__bar { background: var(--pk-positive); }
.pk-progress--warning  .pk-progress__bar { background: var(--pk-warning); }
.pk-progress--negative .pk-progress__bar { background: var(--pk-negative); }
/* --accent: a measure of Plek's own work (coverage, completion, agent success).
   --pk-blue is the data-mark color: 3.3:1 on the track. A status variant wins. */
.pk-progress--accent .pk-progress__bar { background: var(--pk-blue); }

/* ==========================================================================
   8. LIST ROWS — .pk-listrow
   --------------------------------------------------------------------------
   The "Work Tracking" and "Deployed Agents" cards: an icon tile and a name,
   optional right-hand meta, a progress bar, then a ruled footer strip with
   the number on the left and the action on the right.
   ========================================================================== */

.pk-listrows { display: grid; gap: var(--pk-sp-3); }

.pk-listrow {
  display: flex;
  flex-direction: column;
  border: var(--pk-line) solid var(--pk-rule);
  border-radius: var(--pk-radius);
  background: var(--pk-ground);
  min-width: 0;
}
.pk-listrow__body { display: grid; gap: var(--pk-sp-4); padding: var(--pk-sp-4) var(--pk-sp-5); }
.pk-listrow__head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--pk-sp-3);
  min-width: 0;
}
.pk-listrow__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  flex: none;
  border-radius: var(--pk-radius-s);
  background: var(--pk-card);
  color: var(--pk-ink);
}
.pk-listrow__icon > svg { width: 14px; height: 14px; }
/* --accent: the icon tile in the accent family (navy glyph on the sky wash, 9.0:1). */
.pk-listrow__icon--accent { background: var(--pk-sky-wash); color: var(--pk-navy); }
.pk-listrow__name.pk-listrow__name {
  margin: 0;
  flex: 1 1 auto;
  min-width: 8ch;
  font-family: var(--pk-font-body);
  font-size: var(--pk-fs-ui);
  font-weight: 400;
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink-strong);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pk-listrow__meta {
  margin-left: auto;
  flex: none;
  font-size: var(--pk-fs-caption);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-muted);
  white-space: nowrap;
}
/* The strip gives its vertical padding to the action, which has to reach 24px
   on its own; the strip keeps the height it had. */
.pk-listrow__foot {
  display: flex;
  align-items: center;
  gap: var(--pk-sp-3);
  min-height: 36px;
  padding: var(--pk-sp-1h) var(--pk-sp-5);
  border-top: var(--pk-line) solid var(--pk-rule);
  font-size: var(--pk-fs-caption);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-muted);
}
.pk-listrow__stat { font-variant-numeric: tabular-nums; }
.pk-listrow__action.pk-listrow__action {
  display: inline-flex;
  align-items: center;
  gap: var(--pk-sp-1);
  min-height: 24px;                    /* the label is 12px: the padding carries the target, not the type */
  /* auto on the start side pushes the action to the row's far edge; the negative
     end margin lets its padding hang so the label still aligns with the rule */
  margin-inline: auto calc(var(--pk-sp-1h) * -1);
  padding-inline: var(--pk-sp-1h);
  border-radius: var(--pk-radius-s);
  font-family: var(--pk-font-body);
  font-size: var(--pk-fs-caption);
  letter-spacing: var(--pk-ls-caps);   /* the one place the system tracks out: a 12px uppercase label */
  text-transform: uppercase;
  color: var(--pk-muted);
  text-decoration: none;
  white-space: nowrap;
}
.pk-listrow__action > svg { width: 12px; height: 12px; }
.pk-listrow__action:hover { color: var(--pk-ink); background: var(--pk-card); }
/* --accent: the row's one way forward reads as a link (navy, 9.5:1). */
.pk-listrow__action--accent.pk-listrow__action { color: var(--pk-navy); }
.pk-listrow__action--accent.pk-listrow__action:hover { color: var(--pk-blue-text); background: var(--pk-sky-wash); }
/* a whole row that links */
.pk-listrow--link.pk-listrow--link {
  color: inherit;
  text-decoration: none;
  transition: background-color var(--pk-dur-fast) var(--pk-ease-in);
}
.pk-listrow--link:hover { background: var(--pk-card-hover); }

/* ==========================================================================
   9. FORM CONTROLS — EXTENSION
   --------------------------------------------------------------------------
   Not in the Framer file: the product screen shows no input. Derived from
   the system: 2px radius, 1px --pk-control-border (the WCAG 1.4.11 line),
   surface fill, ink focus ring. Every field carries a label; help and error
   text are 12px and sit under the control.
   ========================================================================== */

.pk-form { display: grid; gap: var(--pk-sp-5); }
.pk-form--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.pk-form__row { display: flex; align-items: center; gap: var(--pk-sp-3); flex-wrap: wrap; }

.pk-field { display: grid; gap: var(--pk-sp-2); min-width: 0; align-content: start; }   /* in a 2-up form a field without help text must not stretch its input */
/* A group of related choices is a real <fieldset> with a real <legend> — that
   is how "Cost basis" is announced before its three radios. The UA's own
   border and legend notch are not part of this system, and a fieldset is laid
   out as a block rather than a grid because a legend is not a grid item. */
fieldset.pk-field { display: block; margin: 0; padding: 0; border: 0; min-width: 0; }
fieldset.pk-field > legend { padding: 0 0 var(--pk-sp-2); }
.pk-field__label {
  font-size: var(--pk-fs-caption);
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink);
}
.pk-field__label .pk-field__opt { color: var(--pk-muted); }
/* The required marker is the word, not a star. An asterisk alone means
   nothing until a legend somewhere explains it, and a legend that has to be
   found is a legend that will not be. Pair it with the real `required`
   attribute: this is the visible half of the same statement. */
.pk-field__label .pk-field__req {
  font-size: var(--pk-fs-caption);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink-2);
}
.pk-field__help.pk-field__help {
  font-size: var(--pk-fs-caption);
  letter-spacing: var(--pk-ls-ui);
  line-height: var(--pk-lh-snug);
  color: var(--pk-muted);
}
.pk-field__error.pk-field__error {
  display: flex;
  align-items: center;
  gap: var(--pk-sp-1);
  font-size: var(--pk-fs-caption);
  letter-spacing: var(--pk-ls-ui);
  line-height: var(--pk-lh-snug);
  color: var(--pk-negative);
}
.pk-field__error > svg { width: 14px; height: 14px; }

.pk-input,
.pk-select,
.pk-textarea {
  width: 100%;
  min-height: 32px;
  padding: var(--pk-sp-2) var(--pk-sp-3);
  border: var(--pk-line) solid var(--pk-control-border);
  border-radius: var(--pk-radius-s);
  background: var(--pk-surface);
  font-family: var(--pk-font-body);
  font-size: var(--pk-fs-ui);
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink);
  transition: border-color var(--pk-dur-fast) var(--pk-ease-in),
              background-color var(--pk-dur-fast) var(--pk-ease-in);
}
.pk-textarea { min-height: 84px; padding: var(--pk-sp-3); line-height: var(--pk-lh-body); resize: vertical; }
.pk-input::placeholder,
.pk-textarea::placeholder { color: var(--pk-muted); }
.pk-input:hover,
.pk-select:hover,
.pk-textarea:hover { border-color: var(--pk-ink-2); }
.pk-input:focus-visible,
.pk-select:focus-visible,
.pk-textarea:focus-visible {
  border-color: var(--pk-ink);
  outline: 2px solid var(--pk-ink);
  outline-offset: 1px;
}
.pk-input[disabled],
.pk-select[disabled],
.pk-textarea[disabled] {
  background: var(--pk-card);
  border-color: var(--pk-rule);
  color: var(--pk-muted);
  cursor: not-allowed;
}
.pk-input[readonly] { background: var(--pk-card); }
.pk-input[aria-invalid="true"],
.pk-select[aria-invalid="true"],
.pk-textarea[aria-invalid="true"] { border-color: var(--pk-negative); }

/* ---- date and time: parity with the text input --------------------------
   A native date control is a real <input type="date">: the browser's own
   picker is better than anything this library could draw, and it is the one
   users already know. The only work here is making it the same size, the
   same box and the same ink as every other field — Safari and Chrome both
   ship their own metrics — and tinting the picker button so it reads as ink
   rather than as the browser's blue.
   `field-sizing: content` is deliberately NOT set: a date field that resizes
   as it fills makes the row jump. */
.pk-input[type="date"],
.pk-input[type="time"],
.pk-input[type="month"],
.pk-input[type="datetime-local"] {
  min-width: 0;
  font-variant-numeric: tabular-nums;
  /* Safari centres the value in a taller box than the one it was given */
  -webkit-appearance: none;
  appearance: none;
}
.pk-input[type="date"]::-webkit-date-and-time-value,
.pk-input[type="time"]::-webkit-date-and-time-value,
.pk-input[type="month"]::-webkit-date-and-time-value,
.pk-input[type="datetime-local"]::-webkit-date-and-time-value { text-align: left; }
.pk-input::-webkit-calendar-picker-indicator {
  padding: var(--pk-sp-1);
  border-radius: var(--pk-radius-s);
  opacity: 0.55;                       /* the UA glyph is black; this is the --pk-muted step */
  cursor: pointer;
}
.pk-input::-webkit-calendar-picker-indicator:hover { opacity: 1; background: var(--pk-card); }
.pk-input::-webkit-datetime-edit { padding: 0; }

/* the select keeps a real <select>; the chevron is an inline SVG laid over it */
.pk-select { appearance: none; padding-right: var(--pk-sp-8); }
.pk-select-wrap { position: relative; display: block; min-width: 0; }
.pk-select-wrap > svg {
  position: absolute;
  top: 50%;
  right: var(--pk-sp-3);
  width: 14px;
  height: 14px;
  margin-top: -7px;
  color: var(--pk-muted);
  pointer-events: none;
}

/* check, radio and switch: appearance stripped, boundaries redrawn with the
   control border so they satisfy 1.4.11 in every browser */
.pk-check,
.pk-radio {
  display: inline-flex;
  align-items: flex-start;
  gap: var(--pk-sp-3);
  /* The label IS the target — it wraps the input, so the whole line is the
     hit area. A 13px line is 17px tall, so the box carries it to 24. */
  min-height: 24px;
  padding-block: var(--pk-sp-1);
  font-size: var(--pk-fs-ui);
  line-height: var(--pk-lh-snug);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink);
  cursor: pointer;
}
.pk-check > input,
.pk-radio > input {
  appearance: none;
  flex: none;
  width: 16px;
  height: 16px;
  margin: 0;
  position: relative;
  top: 1px;
  border: var(--pk-line) solid var(--pk-control-border);
  border-radius: var(--pk-radius-s);
  background: var(--pk-surface);
  cursor: pointer;
  transition: background-color var(--pk-dur-fast) var(--pk-ease-in),
              border-color var(--pk-dur-fast) var(--pk-ease-in);
}
/* The radio is square like everything else: the system's radius ceiling is
   4px, so a circle is out. It is told apart from a checkbox by its mark —
   a filled block, not a tick — and by being one of a named group. */
.pk-check > input:checked,
.pk-radio > input:checked { background: var(--pk-charcoal); border-color: var(--pk-charcoal); }
.pk-check > input:checked::after {
  content: "";
  position: absolute;
  left: 4.5px; top: 1.5px;
  width: 4px; height: 8px;
  border: solid var(--pk-on-dark);
  border-width: 0 1.5px 1.5px 0;
  transform: rotate(45deg);
}
.pk-radio > input:checked::after {
  content: "";
  position: absolute;
  left: 4px; top: 4px;
  width: var(--pk-sp-1h); height: var(--pk-sp-1h);
  border-radius: var(--pk-radius-xs);
  background: var(--pk-on-dark);
}
.pk-check > input:indeterminate::after {
  content: "";
  position: absolute;
  left: 3px; top: 6.5px;
  width: 8px; height: 1.5px;
  background: var(--pk-on-dark);
}
.pk-check > input:indeterminate { background: var(--pk-charcoal); border-color: var(--pk-charcoal); }
.pk-check > input[disabled],
.pk-radio > input[disabled] { background: var(--pk-card); border-color: var(--pk-rule); cursor: not-allowed; }
.pk-check:has(> input[disabled]),
.pk-radio:has(> input[disabled]) { color: var(--pk-muted); cursor: not-allowed; }

/* the switch is a rectangle: the system has no pill */
.pk-switch {
  display: inline-flex;
  align-items: center;
  gap: var(--pk-sp-3);
  min-height: 24px;            /* the label is the target; the knob is 18px */
  font-size: var(--pk-fs-ui);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink);
  cursor: pointer;
}
.pk-switch > input {
  appearance: none;
  position: relative;
  flex: none;
  width: 34px;
  height: 18px;
  margin: 0;
  border: var(--pk-line) solid var(--pk-control-border);
  border-radius: var(--pk-radius-s);
  background: var(--pk-surface);
  cursor: pointer;
  transition: background-color var(--pk-dur) var(--pk-ease),
              border-color var(--pk-dur) var(--pk-ease);
}
.pk-switch > input::after {
  content: "";
  position: absolute;
  top: 2px; left: 2px;
  width: 12px; height: 12px;
  border-radius: var(--pk-radius-xs);
  background: var(--pk-control-border);
  transition: transform var(--pk-dur) var(--pk-ease), background-color var(--pk-dur) var(--pk-ease);
}
.pk-switch > input:checked { background: var(--pk-charcoal); border-color: var(--pk-charcoal); }
.pk-switch > input:checked::after { background: var(--pk-on-dark); transform: translateX(16px); }
.pk-switch > input[disabled] { background: var(--pk-card); border-color: var(--pk-rule); cursor: not-allowed; }
.pk-switch > input[disabled]::after { background: var(--pk-rule); }
.pk-switch:has(> input[disabled]) { color: var(--pk-muted); cursor: not-allowed; }

.pk-check > input:focus-visible,
.pk-radio > input:focus-visible,
.pk-switch > input:focus-visible { outline: 2px solid var(--pk-ink); outline-offset: 2px; }

@media (max-width: 809.98px) {
  .pk-form--2 { grid-template-columns: minmax(0, 1fr); }
}

/* ==========================================================================
   10. STATUS AND ALERT — EXTENSION
   --------------------------------------------------------------------------
   The Framer file has one accent family and no status color. These four
   are the flagged extension tokens, desaturated to sit beside the grays.
   Color is never the only signal: every status carries a word.
   ========================================================================== */

.pk-status {
  display: inline-flex;
  align-items: center;
  gap: var(--pk-sp-2);
  padding: 2px var(--pk-sp-2);
  border-radius: var(--pk-radius-s);
  background: var(--pk-card);
  font-family: var(--pk-font-body);
  font-size: var(--pk-fs-caption);
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink-2);
  white-space: nowrap;
}
.pk-status__dot { width: var(--pk-sp-1h); height: var(--pk-sp-1h); flex: none; border-radius: var(--pk-radius-xs); background: currentColor; }
.pk-status--positive { background: var(--pk-positive-tint); color: var(--pk-positive); }
.pk-status--warning  { background: var(--pk-warning-tint);  color: var(--pk-warning); }
.pk-status--negative { background: var(--pk-negative-tint); color: var(--pk-negative); }
.pk-status--info     { background: var(--pk-info-tint);     color: var(--pk-info); }

.pk-alert {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--pk-sp-3) var(--pk-sp-4);
  padding: var(--pk-sp-4) var(--pk-sp-5);
  border: var(--pk-line) solid var(--pk-rule);
  border-left: 2px solid var(--pk-navy);
  border-radius: var(--pk-radius-s);
  background: var(--pk-info-tint);
  font-size: var(--pk-fs-ui);
  letter-spacing: var(--pk-ls-ui);
  line-height: var(--pk-lh-snug);
  color: var(--pk-ink);
}
.pk-alert > svg { width: 18px; height: 18px; color: var(--pk-info); }
.pk-alert__body { display: grid; gap: var(--pk-sp-1); min-width: 0; }
.pk-alert__title.pk-alert__title { margin: 0; font-size: var(--pk-fs-ui); font-weight: 500; letter-spacing: var(--pk-ls-ui); color: var(--pk-ink-strong); }
.pk-alert__text.pk-alert__text { margin: 0; font-size: var(--pk-fs-caption); letter-spacing: var(--pk-ls-ui); line-height: var(--pk-lh-snug); color: var(--pk-ink-2); }
.pk-alert__actions { display: flex; gap: var(--pk-sp-2); margin-top: var(--pk-sp-2); }
/* The error summary a form puts at the top of itself: one line per failed
   field, each one a link to the control that failed. */
.pk-alert__list.pk-alert__list {
  display: grid;
  gap: var(--pk-sp-1);
  margin: var(--pk-sp-1) 0 0;
  padding-left: var(--pk-sp-5);
  font-size: var(--pk-fs-caption);
  letter-spacing: var(--pk-ls-ui);
  line-height: var(--pk-lh-snug);
  color: var(--pk-ink-2);
}
.pk-alert__list.pk-alert__list li { max-width: none; color: inherit; }
/* A block, not an inline-block: an inline-block that wraps puts the list
   marker beside its LAST line, which reads as a bullet in the wrong place. */
.pk-alert__list a {
  display: block;
  min-height: 24px;                 /* the line is 12px: the padding carries the target */
  padding-block: var(--pk-sp-1h);
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.pk-alert__list a:hover { color: var(--pk-ink-strong); }
/* Placement only: the recipe is .pk-iconbtn (composed in the markup). */
.pk-alert__close { grid-column: 3; align-self: start; }
.pk-alert:has(> .pk-alert__close) { grid-template-columns: auto minmax(0, 1fr) auto; }

.pk-alert--positive { border-left-color: var(--pk-positive); background: var(--pk-positive-tint); }
.pk-alert--positive > svg { color: var(--pk-positive); }
.pk-alert--warning  { border-left-color: var(--pk-warning);  background: var(--pk-warning-tint); }
.pk-alert--warning > svg { color: var(--pk-warning); }
.pk-alert--negative { border-left-color: var(--pk-negative); background: var(--pk-negative-tint); }
.pk-alert--negative > svg { color: var(--pk-negative); }
/* the quiet one: no tint, for a note inside a panel */
.pk-alert--plain { background: var(--pk-surface); border-left-color: var(--pk-rule); }
.pk-alert--plain > svg { color: var(--pk-muted); }

/* ==========================================================================
   11. FEEDBACK — empty, skeleton, tooltip, modal — EXTENSION
   --------------------------------------------------------------------------
   Three ways to say "not yet", and they are not interchangeable:

     .pk-skeleton   a STATIC block in the shape of the content that is
                    coming, so the layout does not jump when it arrives. It
                    never pulses — pulsing is an animation, and animation is
                    the loader's job alone.
     .plek-loader   the official loader (css/loader.css), the system's one
                    sanctioned loop and its only busy indicator. Use --block
                    for a whole area, --xs inside a control.
     .pk-progress   a determinate bar, when the share done is known.

   There is no spinner in this system, and there never was one.
   ========================================================================== */

.pk-empty {
  display: grid;
  justify-items: center;
  gap: var(--pk-sp-3);
  padding: var(--pk-sp-9) var(--pk-sp-6);
  border: var(--pk-line) dashed var(--pk-rule);
  border-radius: var(--pk-radius);
  background: var(--pk-ground);
  text-align: center;
}
.pk-empty > svg { width: 28px; height: 28px; color: var(--pk-deco); }
.pk-empty__title.pk-empty__title {
  margin: 0;
  font-family: var(--pk-font-body);
  font-size: var(--pk-fs-ui);
  font-weight: 500;
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink-strong);
}
.pk-empty__text.pk-empty__text { margin: 0; max-width: 46ch; font-size: var(--pk-fs-caption); letter-spacing: var(--pk-ls-ui); line-height: var(--pk-lh-snug); color: var(--pk-muted); }
.pk-empty__actions { display: flex; gap: var(--pk-sp-2); margin-top: var(--pk-sp-1); }

/* Static placeholder blocks — no animation, ever. A skeleton holds the shape
   of what is coming; the loader says that something is coming. A pulsing
   skeleton tries to do both and does neither. */
.pk-skeleton {
  display: block;
  height: 12px;
  width: 100%;
  border-radius: var(--pk-radius-s);
  background: var(--pk-card);
}
.pk-skeleton--title { height: 20px; width: 40%; }
.pk-skeleton--text  { height: 10px; }
.pk-skeleton--block { height: 72px; }
.pk-skeletons { display: grid; gap: var(--pk-sp-3); }
.pk-skeletons > .pk-skeleton:nth-child(2) { width: 88%; }
.pk-skeletons > .pk-skeleton:nth-child(3) { width: 64%; }

.pk-tooltip { position: relative; display: inline-flex; }
.pk-tooltip__bubble {
  position: absolute;
  bottom: calc(100% + var(--pk-sp-2));
  left: 50%;
  transform: translateX(-50%);
  z-index: var(--pk-z-popover);
  padding: var(--pk-sp-1) var(--pk-sp-2);
  border-radius: var(--pk-radius-s);
  background: var(--pk-charcoal);
  color: var(--pk-on-dark);
  font-size: var(--pk-fs-caption);
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-ui);
  white-space: nowrap;
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--pk-dur-fast) var(--pk-ease-in), visibility var(--pk-dur-fast) var(--pk-ease-in);
}
.pk-tooltip:hover > .pk-tooltip__bubble,
.pk-tooltip:focus-within > .pk-tooltip__bubble,
.pk-tooltip--open > .pk-tooltip__bubble { opacity: 1; visibility: visible; }
/* WCAG 1.4.13: content shown on hover or focus must be dismissable without
   moving the pointer. plek.js writes this attribute on Escape and clears it
   when the pointer or the focus leaves, so the tooltip can be summoned again.
   It comes last so it beats the three rules above at equal specificity. */
.pk-tooltip[data-pk-tip="off"] > .pk-tooltip__bubble { opacity: 0; visibility: hidden; }

/* The modal is a native <dialog>. The element does the work the system would
   otherwise have to reinvent badly: the top layer (so it needs no z-index of
   its own — --pk-z-modal is the number it would occupy if it ever had to be
   faked), a real focus trap, Escape, inertness of the page behind it, and a
   ::backdrop to paint the scrim on. plek.js only opens it and hands focus
   back; everything above is the browser's. */
.pk-modal {
  width: min(480px, calc(100% - var(--pk-sp-6) * 2));
  max-height: calc(100% - var(--pk-sp-6) * 2);
  padding: 0;
  overflow: hidden;
  border: var(--pk-line) solid var(--pk-rule);
  border-radius: var(--pk-radius);
  background: var(--pk-surface);
  color: var(--pk-ink);
  font-family: var(--pk-font-body);
  font-size: var(--pk-fs-ui);
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-ui);
}
.pk-modal:not([open]) { display: none; }
/* flat charcoal scrim, mixed from the token — the system has no shadow */
.pk-modal::backdrop { background: color-mix(in srgb, var(--pk-charcoal) 55%, transparent); }
.pk-modal__head {
  display: flex;
  align-items: flex-start;
  gap: var(--pk-sp-4);
  padding: var(--pk-sp-5) var(--pk-sp-6);
  border-bottom: var(--pk-line) solid var(--pk-rule);
}
.pk-modal__title.pk-modal__title {
  margin: 0;
  font-family: var(--pk-font-body);
  font-size: var(--pk-fs-body);
  font-weight: 400;
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-display);
  color: var(--pk-ink-strong);
}
/* Placement only: the recipe is .pk-iconbtn (composed in the markup). */
.pk-modal__close { margin-left: auto; }
.pk-modal__body {
  padding: var(--pk-sp-6);
  max-height: 60vh;
  overflow-y: auto;
  font-size: var(--pk-fs-ui);
  letter-spacing: var(--pk-ls-ui);
  line-height: var(--pk-lh-body);
  color: var(--pk-ink-2);
  display: grid;
  gap: var(--pk-sp-5);
}
.pk-modal__body p { margin: 0; }
.pk-modal__foot {
  display: flex;
  justify-content: flex-end;
  gap: var(--pk-sp-2);
  padding: var(--pk-sp-4) var(--pk-sp-6);
  border-top: var(--pk-line) solid var(--pk-rule);
  background: var(--pk-ground);
}
/* Shown in place, for documentation and for print. A <dialog open> that was
   never given to showModal() renders in normal flow with no backdrop and no
   top layer — which is exactly what a page of documentation wants, and what
   a reader with no script gets until plek.js closes the ones that have an
   opener to bring them back. */
.pk-modal--static { margin: 0; max-height: none; }
.pk-modal--static .pk-modal__body { max-height: none; }

/* ==========================================================================
   12. NAVIGATION — breadcrumb, pagination — EXTENSION
   ========================================================================== */

/* The block class is doubled in the list selectors below. A host page may
   carry its own rules for bare <ol>/<ul>/<li> (the documentation shell does),
   and a component must win against them wherever it is dropped in. */
.pk-breadcrumb { min-width: 0; }
.pk-breadcrumb.pk-breadcrumb ol {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--pk-sp-2);
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--pk-fs-caption);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-muted);
}
.pk-breadcrumb.pk-breadcrumb li {
  display: flex;
  align-items: center;
  gap: var(--pk-sp-2);
  max-width: none;
  color: inherit;
}
.pk-breadcrumb.pk-breadcrumb li + li::before { content: "/"; color: var(--pk-deco); }
/* 12px type, 24px target: the padding carries it, and the negative inline
   margin keeps the trail reading as one line rather than as five chips. */
.pk-breadcrumb.pk-breadcrumb a {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  margin-inline: calc(var(--pk-sp-1) * -1);
  padding-inline: var(--pk-sp-1);
  border-radius: var(--pk-radius-s);
  color: var(--pk-muted);
  text-decoration: none;
}
.pk-breadcrumb.pk-breadcrumb a:hover { color: var(--pk-ink); text-decoration: underline; text-underline-offset: 3px; }
.pk-breadcrumb.pk-breadcrumb [aria-current="page"] { color: var(--pk-ink); }

.pk-pagination {
  display: flex;
  align-items: center;
  gap: var(--pk-sp-3);
  flex: 1 1 auto;
  flex-wrap: wrap;
  font-size: var(--pk-fs-caption);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-muted);
}
.pk-pagination__info { font-variant-numeric: tabular-nums; }
.pk-pagination.pk-pagination ul {
  display: flex;
  align-items: center;
  gap: var(--pk-sp-1);
  margin: 0 0 0 auto;
  padding: 0;
  list-style: none;
}
.pk-pagination.pk-pagination li { max-width: none; }
.pk-pagination__link.pk-pagination__link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 26px;
  height: 26px;
  padding: 0 var(--pk-sp-2);
  border: var(--pk-line) solid var(--pk-rule);
  border-radius: var(--pk-radius-s);
  background: var(--pk-surface);
  font-family: var(--pk-font-body);
  font-size: var(--pk-fs-caption);
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink-2);
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--pk-dur-fast) var(--pk-ease-in), color var(--pk-dur-fast) var(--pk-ease-in);
}
.pk-pagination__link > svg { width: 14px; height: 14px; }
.pk-pagination__link:hover { background: var(--pk-card); color: var(--pk-ink); }
.pk-pagination__link[aria-current="page"] {
  background: var(--pk-charcoal);
  border-color: var(--pk-charcoal);
  color: var(--pk-on-dark);
  cursor: default;
}
.pk-pagination__link[aria-disabled="true"] {
  color: var(--pk-muted);
  border-color: var(--pk-rule);
  background: var(--pk-card);
  pointer-events: none;
}
/* The ellipsis is read as text, so it takes the text gray. --pk-deco is a
   decorative mark color (2.45:1) and never sets type. */
.pk-pagination__gap { padding-inline: var(--pk-sp-1); color: var(--pk-muted); }

/* ==========================================================================
   13. SMALL PARTS — avatar, kbd
   ========================================================================== */

.pk-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  flex: none;
  border: var(--pk-line) solid var(--pk-rule);
  border-radius: var(--pk-radius-s);
  background: var(--pk-card);
  font-family: var(--pk-font-body);
  font-size: var(--pk-fs-caption);
  font-weight: 500;
  letter-spacing: var(--pk-ls-none);
  color: var(--pk-ink);
  text-transform: uppercase;
  overflow: hidden;
}
.pk-avatar > img { width: 100%; height: 100%; object-fit: cover; }
/* An avatar is never a control: it names a person or a workspace, it does not open anything. */
/* letter-spacing in em is inherited as PIXELS, so a rule that changes the
   font size restates its own tracking — here, the avatar's untracked one. */
.pk-avatar--sm { width: 22px; height: 22px; font-size: var(--pk-fs-caption); letter-spacing: var(--pk-ls-none); }
.pk-avatar--lg { width: 36px; height: 36px; font-size: var(--pk-fs-ui); letter-spacing: var(--pk-ls-none); }
.pk-avatar--navy { background: var(--pk-navy); border-color: var(--pk-navy); color: var(--pk-on-dark); }
.pk-avatar--dark { background: var(--pk-charcoal); border-color: var(--pk-charcoal); color: var(--pk-on-dark); }
.pk-avatars { display: inline-flex; align-items: center; gap: var(--pk-sp-1); }

.pk-kbd {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  padding: 1px var(--pk-sp-1);
  border: var(--pk-line) solid var(--pk-control-border);
  border-bottom-width: 2px;
  border-radius: var(--pk-radius-s);
  background: var(--pk-surface);
  font-family: var(--pk-font-mono);
  font-size: var(--pk-fs-caption);
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-body);
  color: var(--pk-ink);
}

/* ==========================================================================
   14. TOAST — EXTENSION
   --------------------------------------------------------------------------
   The message that arrives on its own and leaves on its own: "Changes saved".
   It is not a new component so much as a new PLACE for one — a toast IS a
   .pk-alert (section 10), composed in the markup as
   class="pk-alert pk-alert--positive pk-toast", and everything below adds
   only what a transient message needs that a fixed one does not:

     - it lives in .pk-toasts, a fixed region that is announced;
     - it is clickable inside a region that is not;
     - it enters and leaves with ONE transition, and never loops.

   Tone therefore comes from the alert (--positive / --negative / --warning /
   --plain), so there is exactly one set of tone rules in this file.

   What a toast is NOT: a failure the user has to act on. That is an inline
   .pk-alert with role="alert", next to the thing that failed, and it stays.
   A toast may be missed, so nothing may depend on having read it.
   ========================================================================== */

/* The region is announced, so it must already be in the document before the
   first message is put into it — an aria-live element inserted together with
   its text is not reliably read. Author it once, empty, at the end of body. */
.pk-toasts {
  position: fixed;
  right: var(--pk-sp-6);
  bottom: var(--pk-sp-6);
  z-index: var(--pk-z-toast);
  display: grid;
  gap: var(--pk-sp-2);
  justify-items: end;
  width: min(380px, calc(100% - var(--pk-sp-6) * 2));
  margin: 0;
  padding: 0;
  list-style: none;
  /* the empty region covers a corner of the page: it must not eat clicks */
  pointer-events: none;
}

.pk-toast {
  pointer-events: auto;
  width: 100%;
  opacity: 0;
  transform: translateY(var(--pk-sp-2));
  transition: opacity var(--pk-dur) var(--pk-ease),
              transform var(--pk-dur) var(--pk-ease);
}
.pk-toast.is-in { opacity: 1; transform: none; }
/* The close control is the alert's own .pk-alert__close: there is one close
   button in this file, not two. */

@media (max-width: 809.98px) {
  .pk-toasts { left: var(--pk-sp-4); right: var(--pk-sp-4); bottom: var(--pk-sp-4); width: auto; }
}

/* ==========================================================================
   15. MENU / POPOVER — .pk-menu — EXTENSION
   --------------------------------------------------------------------------
   The short list of actions a control owns: the workspace switcher, the
   account menu, a table row's "more". Not a navigation — navigation is the
   sidebar and the rail. A menu holds VERBS, and it holds few of them.

   Markup:
     .pk-menu
       button[aria-haspopup="menu"][aria-expanded][aria-controls]
       .pk-menu__list[role="menu"][aria-labelledby]
         .pk-menu__item[role="menuitem"]        (a <button> or an <a>)
         hr.pk-menu__sep                        (maps to role="separator")
         div[role="group"][aria-labelledby] > p.pk-menu__group + items

   Without script the list is NOT hidden: it renders in flow under its
   button as a plain bordered list, every item reachable by keyboard, and
   the button is inert. plek.js hides it and makes it a popover — that is
   why every positioning rule below is behind [data-pk-menu="ready"], which
   only the script ever writes.
   ========================================================================== */

.pk-menu {
  /* component-scoped mechanics for the floating variant below; plek.js
     writes them on the panel when it opens one */
  --pk-menu-top: 0px;
  --pk-menu-left: 0px;
  position: relative;
  display: inline-flex;
  min-width: 0;
}
.pk-menu--block { display: flex; width: 100%; }

.pk-menu__list {
  display: grid;
  gap: var(--pk-line);
  min-width: 180px;
  max-width: 100%;
  margin: var(--pk-sp-1) 0 0;
  padding: var(--pk-sp-1);
  border: var(--pk-line) solid var(--pk-rule);
  border-radius: var(--pk-radius);
  background: var(--pk-surface);
  list-style: none;
}
.pk-menu__list[hidden] { display: none; }

/* enhanced: the list leaves the flow and becomes the popover */
.pk-menu[data-pk-menu="ready"] .pk-menu__list {
  position: absolute;
  top: 100%;
  right: 0;
  z-index: var(--pk-z-popover);
  width: max-content;
  max-width: min(280px, 90vw);
}
.pk-menu[data-pk-menu="ready"] .pk-menu__list--start { right: auto; left: 0; }
.pk-menu[data-pk-menu="ready"] .pk-menu__list--up {
  top: auto;
  bottom: 100%;
  margin: 0 0 var(--pk-sp-1);
}
/* --float is for a menu whose button sits inside a scroll container: the
   phone's sidebar bar, a .pk-table-wrap. Such a container clips on BOTH
   axes — overflow-x:auto with overflow-y:hidden is still a clip — so an
   absolutely positioned panel would be cut off at the container's edge. A
   fixed panel escapes it; plek.js measures the button and writes the two
   custom properties, and closes the menu if the page scrolls under it. */
.pk-menu[data-pk-menu="ready"] .pk-menu__list--float {
  position: fixed;
  top: var(--pk-menu-top);
  left: var(--pk-menu-left);
  right: auto;
  bottom: auto;
  margin: 0;
}

.pk-menu__item.pk-menu__item {
  display: flex;
  align-items: center;
  gap: var(--pk-sp-3);
  width: 100%;
  min-height: 30px;
  margin: 0;
  padding: var(--pk-sp-2) var(--pk-sp-3);
  border: 0;
  border-radius: var(--pk-radius-s);
  background: transparent;
  font-family: var(--pk-font-body);
  font-size: var(--pk-fs-ui);
  font-weight: 400;
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink-strong);   /* menu text is black at rest, in both menus */
  text-align: left;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--pk-dur-fast) var(--pk-ease-in),
              color var(--pk-dur-fast) var(--pk-ease-in);
}
.pk-menu__item > svg { width: 16px; height: 16px; flex: none; color: var(--pk-ink); }
.pk-menu__item:hover { background: var(--pk-card-hover); }
.pk-menu__item[aria-checked="true"] { background: var(--pk-card); font-weight: 500; }
.pk-menu__item[aria-disabled="true"] { color: var(--pk-muted); pointer-events: none; }
.pk-menu__item[aria-disabled="true"] > svg { color: var(--pk-muted); }
/* the one destructive entry a menu is allowed, and it is always the last */
.pk-menu__item.pk-menu__item--danger { color: var(--pk-negative); }
.pk-menu__item--danger > svg { color: var(--pk-negative); }
.pk-menu__item--danger:hover { background: var(--pk-negative-tint); }

.pk-menu__hint {
  margin-left: auto;
  padding-left: var(--pk-sp-5);
  font-family: var(--pk-font-mono);
  font-size: var(--pk-fs-caption);
  letter-spacing: var(--pk-ls-body);
  color: var(--pk-muted);
}
.pk-menu__sep {
  margin: var(--pk-sp-1) 0;
  border: 0;
  border-top: var(--pk-line) solid var(--pk-rule);
}
.pk-menu__group.pk-menu__group {
  margin: var(--pk-sp-2) 0 var(--pk-sp-1);
  padding: 0 var(--pk-sp-3);
  font-family: var(--pk-font-mono);
  font-size: var(--pk-fs-caption);
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-body);
  color: var(--pk-muted);
}
.pk-menu__group.pk-menu__group:first-child { margin-top: 0; }

/* ==========================================================================
   16. CONTENT TABS — .pk-ctabs — EXTENSION
   --------------------------------------------------------------------------
   Views of one thing, INSIDE the content: an underline bar over a panel.
   Where each control belongs, and it is not a matter of taste:

     .pk-seg      2-3 options that FILTER one view ("Process" / "Job").
                  Both readings answer the same question.
     .pk-ctabs    4+ VIEWS of one object that each answer a different
                  question, and that live under one page title.
     .pk-submenu  the section's own PAGES — a rail, not a bar. If an entry
                  deserves its own title in the content head, it is a rail
                  entry, not a tab.

   ARIA is the same tablist contract .pk-seg and .pk-tabs use, so plek.js
   enhances all three with one implementation: role="tablist" on the list,
   role="tab" + aria-selected + aria-controls on each tab, one [hidden]
   panel per tab. With no script the authored tab is selected and its panel
   is the only one not hidden — the page is still readable, it just does not
   switch.
   ========================================================================== */

.pk-ctabs { min-width: 0; }
/* Inside a content column the bar carries the column's gutter, so its rule
   reaches both edges exactly as a .pk-content__section's does and the two
   read as one ruled stack rather than as a card on a ground. */
.pk-ctabs--flush .pk-ctabs__list { padding-inline: var(--pk-app-gutter, var(--pk-sp-6)); }
.pk-ctabs__list {
  display: flex;
  align-items: stretch;
  gap: var(--pk-sp-6);
  min-width: 0;
  border-bottom: var(--pk-line) solid var(--pk-rule);
  /* on a phone the bar scrolls sideways rather than wrapping: a tab bar that
     wraps to two lines stops reading as one row of alternatives */
  overflow-x: auto;
  overflow-y: hidden;
}
.pk-ctabs__tab {
  display: inline-flex;
  align-items: center;
  gap: var(--pk-sp-2);
  flex: none;
  min-height: 34px;
  margin: 0 0 calc(var(--pk-line) * -1);
  padding: var(--pk-sp-2) 0;
  border: 0;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  background: none;
  font-family: var(--pk-font-body);
  font-size: var(--pk-fs-ui);
  font-weight: 400;
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink-2);
  white-space: nowrap;
  cursor: pointer;
  transition: color var(--pk-dur-fast) var(--pk-ease-in),
              border-color var(--pk-dur-fast) var(--pk-ease-in);
}
.pk-ctabs__tab:hover { color: var(--pk-ink-strong); }
/* The weight does NOT change on selection: a bar whose labels grow bolder
   shifts every tab to its right the moment you move along it. */
.pk-ctabs__tab[aria-selected="true"] {
  color: var(--pk-ink-strong);
  border-bottom-color: var(--pk-charcoal);
  cursor: default;
}
.pk-ctabs__tab:focus-visible { outline: 2px solid var(--pk-ink); outline-offset: -2px; }
.pk-ctabs__count {
  font-family: var(--pk-font-mono);
  font-size: var(--pk-fs-caption);
  letter-spacing: var(--pk-ls-body);
  font-variant-numeric: tabular-nums;
  color: var(--pk-muted);
}
.pk-ctabs__tab[aria-selected="true"] .pk-ctabs__count { color: var(--pk-ink-2); }

/* ==========================================================================
   17. BUSY BUTTON — PRODUCT EXTENSION OF .pk-btn (components.css) — EXTENSION
   --------------------------------------------------------------------------
   .pk-btn lives in components.css and this file does not own it. What it
   owns is the one product state a marketing page never needs: the control
   that has been pressed and is waiting.

   Two things happen, and the markup carries both so that neither needs a
   script:

     1. the label swaps to a progressive verb — "Save changes" becomes
        "Saving…" — because a control that is working should say what it is
        doing, not merely look different;
     2. the Plek loader (css/loader.css, .plek-loader--xs) rides in front of
        that label. It is the system's ONE sanctioned looping animation and
        its ONLY busy indicator: no spinner anywhere, and .pk-skeleton stays
        static — a skeleton is a placeholder for layout, the loader is the
        statement that work is happening.

   Inside a --solid button the loader takes --on-dark, so its ink and its
   signal strand read on charcoal.

   aria-busy="true" is the state. The control keeps its focus (removing it
   would drop a keyboard user out of the form they were filling in), and
   pointer-events: none plus a guard in plek.js stop a second press. Both
   labels are authored, the swap is CSS, and the loader is inline markup —
   so the busy state renders correctly with no script at all.
   ========================================================================== */

.pk-btn__label,
.pk-btn__busy {
  display: inline-flex;
  align-items: center;
  gap: var(--pk-sp-2);
}
/* display:none keeps the hidden loader from rendering at all, so the one
   animation in the system is only ever running while it is being looked at */
.pk-btn__busy { display: none; }
.pk-btn[aria-busy="true"] { pointer-events: none; }
.pk-btn[aria-busy="true"] .pk-btn__label { display: none; }
.pk-btn[aria-busy="true"] .pk-btn__busy { display: inline-flex; }
/* the mark is 16px in a 16px label: it sits on the text, not above it */
.pk-btn__busy > .plek-loader { flex: none; }

/* ==========================================================================
   18. FILE UPLOAD — .pk-file — EXTENSION
   --------------------------------------------------------------------------
   A drop zone that is a real <input type="file"> inside a <label>. The input
   is never hidden: with no script at all this is a working, labeled file
   picker that shows the browser's own file name, and the drop target, the
   picked row and the remove control are the enhancement on top.

   Dashed is the system's "put something here" line. Until now .pk-empty
   owned it alone, and the meaning was "nothing here yet"; the drop zone is
   the same statement in the imperative. Nothing else in the system is
   dashed.

   States: idle · over (dragging above it) · picked · invalid.
   ========================================================================== */

.pk-file {
  display: grid;
  justify-items: center;
  gap: var(--pk-sp-3);
  padding: var(--pk-sp-6);
  border: var(--pk-line) dashed var(--pk-control-border);
  border-radius: var(--pk-radius);
  background: var(--pk-surface);
  text-align: center;
  cursor: pointer;
  transition: background-color var(--pk-dur-fast) var(--pk-ease-in),
              border-color var(--pk-dur-fast) var(--pk-ease-in);
}
.pk-file > svg { width: 24px; height: 24px; color: var(--pk-muted); }
.pk-file__text {
  font-size: var(--pk-fs-ui);
  line-height: var(--pk-lh-snug);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink);
}
.pk-file__text b { font-weight: 500; color: var(--pk-ink-strong); }
.pk-file__hint {
  font-size: var(--pk-fs-caption);
  line-height: var(--pk-lh-snug);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-muted);
}
.pk-file__input {
  max-width: 100%;
  font-size: var(--pk-fs-caption);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink-2);
}
/* the UA's own button, pulled back into the system: it is a small ghost */
.pk-file__input::file-selector-button {
  margin-right: var(--pk-sp-3);
  padding: var(--pk-sp-1) var(--pk-sp-4);
  min-height: 24px;
  border: var(--pk-line) solid var(--pk-control-border);
  border-radius: var(--pk-radius-s);
  background: var(--pk-surface);
  font-family: var(--pk-font-body);
  font-size: var(--pk-fs-caption);
  font-weight: 400;
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink-2);
  cursor: pointer;
}
.pk-file__input::file-selector-button:hover { background: var(--pk-card); color: var(--pk-ink); }
.pk-file:hover { background: var(--pk-card); }
.pk-file:focus-within { outline: 2px solid var(--pk-ink); outline-offset: 2px; }
.pk-file[data-state="over"] {
  border-style: solid;
  border-color: var(--pk-ink);
  background: var(--pk-sky-wash);
}
.pk-file[data-state="picked"] {
  border-style: solid;
  border-color: var(--pk-rule);
  background: var(--pk-ground);
}
.pk-file:has(> .pk-file__input[aria-invalid="true"]) {
  border-style: solid;
  border-color: var(--pk-negative);
  background: var(--pk-negative-tint);
}

/* The picked row sits OUTSIDE the label: a button inside a label would open
   the file picker instead of removing the file. */
.pk-file__picked {
  display: flex;
  align-items: center;
  gap: var(--pk-sp-3);
  min-width: 0;
  margin: 0;
  padding: var(--pk-sp-2) var(--pk-sp-3);
  border: var(--pk-line) solid var(--pk-rule);
  border-radius: var(--pk-radius-s);
  background: var(--pk-ground);
  font-size: var(--pk-fs-caption);
  line-height: var(--pk-lh-snug);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink-2);
}
.pk-file__picked[hidden] { display: none; }
.pk-file__picked > svg { width: 16px; height: 16px; flex: none; color: var(--pk-muted); }
.pk-file__name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--pk-ink);
}
.pk-file__size { flex: none; font-variant-numeric: tabular-nums; }
.pk-file__remove { margin-left: auto; flex: none; }

/* ==========================================================================
   19. TOOLBAR, FILTER CHIPS AND BULK BAR — EXTENSION
   --------------------------------------------------------------------------
   The band a collection wears under its content head: what is filtering it on
   the left, what shapes and exports it on the right. It is the production
   Directory's `.workers-toolbar` (count, chips, the Columns popover pushed
   right) re-hung on v6 — with the count moved up into the content head, where
   this system already names the view.

   It is NOT the 44px band: the content head is a fixed height and may never
   stretch, while this band wraps onto a second line on a phone. Two bands,
   two rules, one hairline each.

   Density is deliberately not offered. The product has one density.
   ========================================================================== */

.pk-toolbar {
  display: flex;
  align-items: center;
  gap: var(--pk-sp-4);
  flex-wrap: wrap;
  flex: none;
  min-height: 44px;
  padding: var(--pk-sp-2) var(--pk-app-gutter, var(--pk-sp-6));
  border-bottom: var(--pk-line) solid var(--pk-rule);
  font-size: var(--pk-fs-ui);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink-2);
}
.pk-toolbar__side {
  display: flex;
  align-items: center;
  gap: var(--pk-sp-2);
  flex-wrap: wrap;
  min-width: 0;
}
.pk-toolbar__side--end { margin-left: auto; }

/* ---- filter chips ------------------------------------------------------
   A chip is a filter that is ON, and the whole of it is legible: the column
   it filters, the value it keeps, and a control that removes it. It is a
   <span> holding a label and a real <button>, never one button doing both
   jobs — "remove" must be reachable and named on its own. */
.pk-chips {
  display: flex;
  align-items: center;
  gap: var(--pk-sp-2);
  flex-wrap: wrap;
  min-width: 0;
}
.pk-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--pk-sp-2);
  max-width: 24ch;
  min-height: 24px;
  padding-left: var(--pk-sp-3);
  border: var(--pk-line) solid var(--pk-control-border);
  border-radius: var(--pk-radius-s);
  background: var(--pk-surface);
  font-size: var(--pk-fs-caption);
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink);
}
.pk-chip__label {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pk-chip__label b { font-weight: 500; color: var(--pk-ink-strong); }
/* Placement only: the recipe is .pk-iconbtn (composed in the markup). */
.pk-chip__remove { flex: none; border-radius: 0 var(--pk-radius-s) var(--pk-radius-s) 0; }
.pk-chips__clear {
  flex: none;
  min-height: 24px;
  padding-inline: var(--pk-sp-2);
  border: 0;
  border-radius: var(--pk-radius-s);
  background: none;
  font-family: var(--pk-font-body);
  font-size: var(--pk-fs-caption);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-muted);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.pk-chips__clear:hover { color: var(--pk-ink-strong); }

/* ---- bulk-action bar ---------------------------------------------------
   It replaces the toolbar's LEFT side while rows are selected, rather than
   sliding in over the table: the filters and the selection are two answers
   to the same question — what these rows are — and only one of them is being
   acted on at a time. */
.pk-bulkbar {
  display: flex;
  align-items: center;
  gap: var(--pk-sp-4);
  flex-wrap: wrap;
  min-width: 0;
  min-height: 24px;
  font-size: var(--pk-fs-ui);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink-strong);
}
.pk-bulkbar[hidden] { display: none; }
.pk-bulkbar__count { font-weight: 500; font-variant-numeric: tabular-nums; }
.pk-bulkbar__actions { display: flex; align-items: center; gap: var(--pk-sp-2); flex-wrap: wrap; }

@media (max-width: 809.98px) {
  .pk-toolbar { align-items: flex-start; }
  .pk-toolbar__side--end { margin-left: 0; }
}

/* ==========================================================================
   20. TABLE LAYOUT — .pk-table--bleed, .pk-table-wrap--fill
   --------------------------------------------------------------------------
   The collection screen: a table that IS the content area rather than a panel
   inside it. Its hairlines reach both edges of the column, its header stays
   while the rows scroll, and its first two cells — the checkbox and the name
   — stay while the columns scroll sideways.

   The wrap, not .pk-content__body, is the scroller. One element scrolling in
   both directions is what makes `position: sticky` mean anything here, and it
   is what keeps the page itself from ever scrolling sideways.
   ========================================================================== */

.pk-table-wrap--fill {
  height: 100%;
  overflow: auto;
  scrollbar-gutter: stable;
}
/* the body hands its scrolling to whatever fills it */
.pk-content__body:has(> .pk-table-wrap--fill) { overflow: hidden; }
.pk-content__body:has(> .pk-studio) { display: flex; overflow: hidden; }

.pk-table--bleed {
  --pk-table-pick-w: 40px;   /* the checkbox column, so the name can pin beside it */
  --pk-table-gutter: var(--pk-app-gutter, var(--pk-sp-6));
  min-width: 100%;
}
.pk-table--bleed thead th {
  position: sticky;
  top: 0;
  z-index: var(--pk-z-raised);
  background: var(--pk-ground);
}
/* The two pinned cells carry their own fill, because a sticky cell with no
   background is a cell you can read the scrolled columns through. The row
   states have to be repeated onto them for the same reason. */
.pk-table--bleed th.pk-table__pick,
.pk-table--bleed td.pk-table__pick,
.pk-table--bleed th.pk-table__lead,
.pk-table--bleed td.pk-table__lead {
  position: sticky;
  background: var(--pk-surface);
}
.pk-table--bleed th.pk-table__pick,
.pk-table--bleed td.pk-table__pick { left: 0; width: var(--pk-table-pick-w); }
.pk-table--bleed th.pk-table__lead,
.pk-table--bleed td.pk-table__lead { left: var(--pk-table-pick-w); }
.pk-table--bleed thead th.pk-table__pick,
.pk-table--bleed thead th.pk-table__lead { z-index: var(--pk-z-nav); background: var(--pk-ground); }
.pk-table--bleed tbody tr:hover td.pk-table__pick,
.pk-table--bleed tbody tr:hover td.pk-table__lead { background: var(--pk-card-hover); }
.pk-table--bleed tbody tr.is-selected td.pk-table__pick,
.pk-table--bleed tbody tr.is-selected td.pk-table__lead,
.pk-table--bleed tbody tr[aria-selected="true"] td.pk-table__pick,
.pk-table--bleed tbody tr[aria-selected="true"] td.pk-table__lead { background: var(--pk-sky-wash); }
/* the pinned pair carries the seam the vertical rules otherwise would */
.pk-table--bleed th.pk-table__lead,
.pk-table--bleed td.pk-table__lead { box-sizing: border-box; border-right: var(--pk-line) solid var(--pk-rule); }

/* the name is a link, and only the name: a whole <tr> that links cannot hold
   a checkbox, a menu or a second destination */
.pk-table__link.pk-table__link {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  color: var(--pk-ink-strong);
  text-decoration: none;
}
.pk-table__link:hover { text-decoration: underline; text-underline-offset: 3px; }

/* a footer band under the table, outside the scroller */
.pk-content__foot {
  display: flex;
  align-items: center;
  gap: var(--pk-sp-4);
  flex: none;
  min-height: 44px;
  padding: var(--pk-sp-2) var(--pk-app-gutter, var(--pk-sp-6));
  border-top: var(--pk-line) solid var(--pk-rule);
}

/* ==========================================================================
   21. RECORD — .pk-record, .pk-deflist, .pk-timeline — EXTENSION
   --------------------------------------------------------------------------
   One item of a collection, on a page of its own. Production shows this in
   place, inside the Directory pane, with a back control to the list; the
   shape is the same either way and the back control is the same link.

   It is deliberately NOT .pk-content--narrow: a record is a grid of facts,
   and capping it at a reading measure would put two columns of definitions
   into one.
   ========================================================================== */

.pk-record { min-width: 0; }
.pk-record__head {
  display: grid;
  gap: var(--pk-sp-4);
  padding: var(--pk-sp-6) var(--pk-app-gutter, var(--pk-sp-6));
  border-bottom: var(--pk-line) solid var(--pk-rule);
}
.pk-record__back.pk-record__back {
  display: inline-flex;
  align-items: center;
  gap: var(--pk-sp-2);
  justify-self: start;
  min-height: 24px;
  margin-inline: calc(var(--pk-sp-1) * -1);
  padding-inline: var(--pk-sp-1);
  border-radius: var(--pk-radius-s);
  font-size: var(--pk-fs-caption);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-muted);
  text-decoration: none;
}
.pk-record__back > svg { width: 14px; height: 14px; }
.pk-record__back:hover { color: var(--pk-ink-strong); background: var(--pk-card); }
.pk-record__title-row {
  display: flex;
  align-items: center;
  gap: var(--pk-sp-3);
  flex-wrap: wrap;
  min-width: 0;
}
.pk-record__name.pk-record__name {
  margin: 0;
  min-width: 0;
  font-family: var(--pk-font-body);
  font-size: var(--pk-fs-title);
  font-weight: 400;
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-display);
  color: var(--pk-ink-strong);
}
.pk-record__code {
  font-family: var(--pk-font-mono);
  font-size: var(--pk-fs-caption);
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-body);
  color: var(--pk-muted);
}
.pk-record__actions { margin-left: auto; display: flex; align-items: center; gap: var(--pk-sp-2); }
.pk-record__meta.pk-record__meta {
  display: flex;
  align-items: center;
  gap: var(--pk-sp-3);
  flex-wrap: wrap;
  margin: 0;
  font-size: var(--pk-fs-caption);
  line-height: var(--pk-lh-snug);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-muted);
}

/* ---- definition rows ---------------------------------------------------
   A real <dl>. Hairline rows, the term in mono at caption size, the value in
   ink. Two columns of rows from 1200 up, one below — the rows are what wrap,
   never the pair. */
.pk-deflist.pk-deflist {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0 var(--pk-sp-9);
  margin: 0;
  padding: 0;
  min-width: 0;
}
.pk-deflist__row {
  display: grid;
  grid-template-columns: minmax(8rem, 12rem) minmax(0, 1fr);
  gap: var(--pk-sp-4);
  align-items: baseline;
  padding: var(--pk-sp-3) 0;
  border-top: var(--pk-line) solid var(--pk-rule);
}
/* The term is a field label and wears .pk-field__label's voice: Inter. */
.pk-deflist__row > dt {
  font-size: var(--pk-fs-caption);
  line-height: var(--pk-lh-snug);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-muted);
}
.pk-deflist__row > dd {
  margin: 0;
  min-width: 0;
  font-size: var(--pk-fs-ui);
  line-height: var(--pk-lh-snug);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink);
  overflow-wrap: anywhere;
}
.pk-deflist__row > dd.pk-deflist__num { font-variant-numeric: tabular-nums; }
/* A value that is a list (a job profile's responsibilities, the licenses a
   seat requires): one real <ul> inside one <dd>, square markers — the shape
   language has no circles — and a row per item at the value's own size. */
.pk-deflist__list {
  margin: 0;
  padding: 0 0 0 var(--pk-sp-4);
  display: grid;
  gap: var(--pk-sp-1);
  list-style: square;
}
@media (min-width: 1200px) {
  .pk-deflist.pk-deflist { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ---- timeline ----------------------------------------------------------
   A vertical hairline with square markers. No circles: the shape language is
   2px and 4px, and a dot on a spine would be the only round thing in the
   product layer. */
.pk-timeline.pk-timeline {
  display: grid;
  gap: 0;
  margin: 0;
  padding: 0 0 0 var(--pk-sp-6);
  list-style: none;
  border-left: var(--pk-line) solid var(--pk-rule);
}
.pk-timeline__item.pk-timeline__item {
  position: relative;
  max-width: none;
  padding: 0 0 var(--pk-sp-6);
}
.pk-timeline__item:last-child { padding-bottom: 0; }
.pk-timeline__item::before {
  content: "";
  position: absolute;
  left: calc(var(--pk-sp-6) * -1 - var(--pk-line));
  top: var(--pk-sp-1);
  width: 7px;
  height: 7px;
  transform: translateX(-50%);
  border-radius: var(--pk-radius-s);
  background: var(--pk-control-border);
}
.pk-timeline__item--now::before { background: var(--pk-charcoal); }
.pk-timeline__date {
  display: block;
  font-family: var(--pk-font-mono);
  font-size: var(--pk-fs-caption);
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-body);
  color: var(--pk-muted);
}
.pk-timeline__title.pk-timeline__title {
  margin: var(--pk-sp-1) 0 0;
  font-family: var(--pk-font-body);
  font-size: var(--pk-fs-ui);
  font-weight: 500;
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink-strong);
}
.pk-timeline__note.pk-timeline__note {
  margin: var(--pk-sp-1) 0 0;
  max-width: var(--pk-measure-text);
  font-size: var(--pk-fs-caption);
  line-height: var(--pk-lh-snug);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink-2);
}

/* ==========================================================================
   22. STUDIO — .pk-studio and what fills it — EXTENSION
   --------------------------------------------------------------------------
   The layout for ONE complex object you explore rather than read: a
   catalogue of things on the left, the thing itself in the middle, and the
   evidence for whatever is selected on the right. It is the production
   Process hub's `.pd-dictionary-layout` + `.pd-map-area` reduced to three
   regions instead of five, and re-hung on this system's hairlines.

   Three regions, three scrollers, one page that never scrolls. The seams are
   the same mechanic as .pk-app__work: a 1px gap over a rule-colored ground.

   Responsive, and these are the only two steps:
     < 1200  the inspector leaves the grid and becomes a right-hand drawer
             over the map, opened from the content head.
     <  810  the catalogue does the same from the left, and the map keeps its
             own two-way scrolling inside its region.
   ========================================================================== */

.pk-studio {
  --pk-studio-rail: 280px;
  --pk-studio-inspector: 340px;
  display: grid;
  grid-template-columns: var(--pk-studio-rail) minmax(0, 1fr) var(--pk-studio-inspector);
  gap: var(--pk-line);
  background: var(--pk-rule);
  flex: 1 1 auto;
  min-width: 0;
  min-height: 0;
}
.pk-studio > * { background: var(--pk-ground); min-width: 0; min-height: 0; }

.pk-studio__rail,
.pk-studio__inspector {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.pk-studio__map {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
/* the catalogue's own search sits in a band of its own, above the list */
.pk-studio__search {
  flex: none;
  padding: var(--pk-sp-3) var(--pk-sp-4);
  border-bottom: var(--pk-line) solid var(--pk-rule);
}

/* ---- the catalogue ------------------------------------------------------ */
.pk-catalog {
  display: flex;
  flex-direction: column;
  gap: var(--pk-sp-1);
  flex: 1 1 auto;
  min-height: 0;
  padding: var(--pk-sp-2);
  overflow-y: auto;
}
.pk-catalog__group.pk-catalog__group {
  margin: var(--pk-sp-3) 0 var(--pk-sp-1);
  padding: 0 var(--pk-sp-3);
  font-family: var(--pk-font-mono);
  font-size: var(--pk-fs-caption);
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-body);
  color: var(--pk-muted);
}
.pk-catalog__group.pk-catalog__group:first-child { margin-top: 0; }
.pk-catalog__item.pk-catalog__item {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 2px var(--pk-sp-3);
  width: 100%;
  min-height: 44px;
  margin: 0;
  padding: var(--pk-sp-2) var(--pk-sp-3);
  border: 0;
  border-radius: var(--pk-radius-s);
  background: transparent;
  font-family: var(--pk-font-body);
  font-size: var(--pk-fs-ui);
  font-weight: 400;
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink-strong);   /* menu text is black at rest, here too */
  text-align: left;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--pk-dur-fast) var(--pk-ease-in);
}
.pk-catalog__item:hover { background: var(--pk-card-hover); }
.pk-catalog__id {
  grid-column: 1;
  font-family: var(--pk-font-mono);
  font-size: var(--pk-fs-caption);
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-body);
  color: var(--pk-muted);
}
.pk-catalog__title { grid-column: 1; overflow: hidden; text-overflow: ellipsis; }
.pk-catalog__count {
  grid-column: 2;
  grid-row: 1 / span 2;
  align-self: center;
  font-family: var(--pk-font-mono);
  font-size: var(--pk-fs-caption);
  letter-spacing: var(--pk-ls-body);
  font-variant-numeric: tabular-nums;
  color: var(--pk-muted);
}
.pk-catalog__item[aria-current="true"],
.pk-catalog__item[aria-current="page"] {
  background: var(--pk-card);
  font-weight: 500;
}
.pk-catalog__item[aria-current="true"] .pk-catalog__id,
.pk-catalog__item[aria-current="page"] .pk-catalog__id,
.pk-catalog__item[aria-current="true"] .pk-catalog__count,
.pk-catalog__item[aria-current="page"] .pk-catalog__count { color: var(--pk-ink-2); }

/* ---- the overview band over the map ------------------------------------- */
.pk-overview {
  display: grid;
  gap: var(--pk-sp-3);
  flex: none;
  padding: var(--pk-sp-6) var(--pk-app-gutter, var(--pk-sp-6));
  border-bottom: var(--pk-line) solid var(--pk-rule);
}
.pk-overview__eyebrow.pk-overview__eyebrow {
  margin: 0;
  font-family: var(--pk-font-mono);
  font-size: var(--pk-fs-caption);
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-body);
  color: var(--pk-muted);
}
.pk-overview__title.pk-overview__title {
  margin: 0;
  font-family: var(--pk-font-body);
  font-size: var(--pk-fs-title);
  font-weight: 400;
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-display);
  color: var(--pk-ink-strong);
}
.pk-overview__text.pk-overview__text {
  margin: 0;
  max-width: var(--pk-measure-text);
  font-size: var(--pk-fs-ui);
  line-height: var(--pk-lh-body);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink-2);
}

/* ---- compact metric row -------------------------------------------------
   Five numbers on one hairline row. It is NOT .pk-statrow (patterns.css, the
   marketing band) and it does not depend on it: this is product density, the
   cells are rule-separated rather than card-separated, and the product layer
   may not reach into the marketing layer for a layout. */
/* Flex, not grid: an auto-fit grid leaves a HOLE when the count does not
   divide by the column count, and a hole with a hairline round it reads as a
   missing cell. Wrapped flex items stretch instead. */
.pk-metrics {
  display: flex;
  flex-wrap: wrap;
  gap: var(--pk-line);
  background: var(--pk-rule);
  border: var(--pk-line) solid var(--pk-rule);
  border-radius: var(--pk-radius-s);
  overflow: hidden;
}
.pk-metric {
  display: grid;
  gap: 2px;
  align-content: start;
  flex: 1 1 110px;
  min-width: 0;
  padding: var(--pk-sp-4) var(--pk-sp-5);
  background: var(--pk-surface);
}
.pk-metric__value.pk-metric__value {
  margin: 0;
  font-family: var(--pk-font-body);
  font-size: var(--pk-fs-lead);
  font-weight: 400;
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-display);
  font-variant-numeric: tabular-nums;
  color: var(--pk-ink-strong);
}
/* The same voice as .pk-statcard__label: a number's label is Inter, not mono. */
.pk-metric__label.pk-metric__label {
  margin: 0;
  font-size: var(--pk-fs-caption);
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-muted);
}
.pk-metric__note.pk-metric__note {
  margin: 0;
  font-size: var(--pk-fs-caption);
  line-height: var(--pk-lh-snug);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink-2);
}

/* ---- a hairline group of icon buttons -----------------------------------
   The zoom cluster: cells sharing one outline, the way the nav rail's cells
   do. Any .pk-iconbtn--xs may sit in it; a readout may sit between them. */
.pk-btngroup {
  display: inline-flex;
  align-items: stretch;
  flex: none;
  border: var(--pk-line) solid var(--pk-control-border);
  border-radius: var(--pk-radius-s);
  overflow: hidden;
}
.pk-btngroup > * { border-radius: 0; }
.pk-btngroup > * + * { border-left: var(--pk-line) solid var(--pk-rule); }
.pk-btngroup .pk-iconbtn { border: 0; }
.pk-btngroup__value {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 48px;
  padding-inline: var(--pk-sp-2);
  background: var(--pk-surface);
  font-family: var(--pk-font-mono);
  font-size: var(--pk-fs-caption);
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-body);
  font-variant-numeric: tabular-nums;
  color: var(--pk-ink-2);
}
.pk-btngroup__text {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  padding-inline: var(--pk-sp-3);
  border: 0;
  background: var(--pk-surface);
  font-family: var(--pk-font-body);
  font-size: var(--pk-fs-caption);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink-2);
  cursor: pointer;
}
.pk-btngroup__text:hover { background: var(--pk-card); color: var(--pk-ink); }

/* ---- the map ------------------------------------------------------------
   The map reads TOP TO BOTTOM, as production's does: one .pk-flow__layer per
   depth, parallel branches side by side across a layer, and a connector in
   every gap. Nodes are real buttons in reading order, so Tab walks the
   process the way the eye does.

   There is no pan-and-zoom engine here. The stage scales with one custom
   property and nothing else moves; the region scrolls. A library ships the
   shape, not a canvas. */
.pk-flow {
  --pk-flow-zoom: 1;
  --pk-flow-node-w: 200px;
  --pk-flow-gap: var(--pk-sp-6);
  --pk-flow-link-h: 44px;
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
  background-color: var(--pk-surface);
}
.pk-flow__stage {
  display: grid;
  justify-items: center;
  gap: 0;
  width: max-content;
  min-width: 100%;
  padding: var(--pk-sp-8) var(--pk-sp-6);
  transform: scale(var(--pk-flow-zoom));
  transform-origin: top center;
  transition: transform var(--pk-dur) var(--pk-ease);
}
.pk-flow__layer {
  display: flex;
  align-items: stretch;
  justify-content: center;
  gap: var(--pk-flow-gap);
}

.pk-flow__node {
  display: grid;
  gap: var(--pk-sp-2);
  align-content: start;
  width: var(--pk-flow-node-w);
  padding: var(--pk-sp-4);
  border: var(--pk-line) solid var(--pk-control-border);
  border-radius: var(--pk-radius);
  background: var(--pk-canvas);
  font-family: var(--pk-font-body);
  text-align: left;
  cursor: pointer;
  transition: background-color var(--pk-dur-fast) var(--pk-ease-in),
              border-color var(--pk-dur-fast) var(--pk-ease-in);
}
.pk-flow__node:hover { background: var(--pk-card); }
.pk-flow__index {
  display: block;
  font-family: var(--pk-font-mono);
  font-size: var(--pk-fs-caption);
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-body);
  font-variant-numeric: tabular-nums;
  color: var(--pk-muted);
}
.pk-flow__title {
  display: block;
  font-size: var(--pk-fs-ui);
  font-weight: 500;
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink-strong);
}
.pk-flow__meta {
  display: block;
  font-size: var(--pk-fs-caption);
  line-height: var(--pk-lh-snug);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink-2);
}
.pk-flow__node > .pk-tag { justify-self: start; }

/* At most ONE selected node, and it is the view's single dark cell — the same
   emphasis budget the marketing row spends on one charcoal card. */
.pk-flow__node[aria-pressed="true"] {
  background: var(--pk-charcoal);
  border-color: var(--pk-charcoal-2);
}
.pk-flow__node[aria-pressed="true"] .pk-flow__title { color: var(--pk-on-dark); }
.pk-flow__node[aria-pressed="true"] .pk-flow__index,
.pk-flow__node[aria-pressed="true"] .pk-flow__meta { color: var(--pk-on-dark-2); }
.pk-flow__node[aria-pressed="true"] .pk-tag { border-color: var(--pk-on-dark-rule); color: var(--pk-on-dark); }
/* a node that is not on the path the reader is following */
.pk-flow__node--dim { border-style: dashed; background: var(--pk-ground); }
.pk-flow__node--dim .pk-flow__title { color: var(--pk-ink-2); }

/* endpoints: a small charcoal cell, not a circle */
.pk-flow__node--endpoint {
  display: inline-flex;
  align-items: center;
  gap: var(--pk-sp-2);
  width: auto;
  min-height: 28px;
  padding: var(--pk-sp-1) var(--pk-sp-4);
  border-color: var(--pk-charcoal);
  border-radius: var(--pk-radius-s);
  background: var(--pk-charcoal);
  font-family: var(--pk-font-mono);
  font-size: var(--pk-fs-caption);
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-body);
  color: var(--pk-on-dark);
  cursor: default;
}
.pk-flow__node--endpoint:hover { background: var(--pk-charcoal-2); }

/* A gateway is a 45°-rotated SQUARE with a 2px radius, beside its label. It
   is not a pill and not a circle: the shape language still holds at 45°. */
.pk-flow__node--gateway {
  display: flex;
  align-items: center;
  gap: var(--pk-sp-3);
  width: var(--pk-flow-node-w);
  min-height: 24px;               /* the 22px mark alone is under the target */
  border-style: none;
  background: transparent;
  padding: var(--pk-sp-1) 0;
}
.pk-flow__node--gateway:hover { background: transparent; }
.pk-flow__gate {
  flex: none;
  width: 22px;
  height: 22px;
  transform: rotate(45deg);
  border: var(--pk-line) solid var(--pk-control-border);
  border-radius: var(--pk-radius-s);
  background: var(--pk-canvas);
}
.pk-flow__node--gateway:hover .pk-flow__gate { border-color: var(--pk-ink); background: var(--pk-card); }
.pk-flow__node--gateway[aria-pressed="true"] .pk-flow__gate {
  border-color: var(--pk-charcoal);
  background: var(--pk-charcoal);
}
.pk-flow__node--gateway[aria-pressed="true"] { background: transparent; }
.pk-flow__node--gateway[aria-pressed="true"] .pk-flow__title { color: var(--pk-ink-strong); }
/* Layout only: the label IS the node's title, and .pk-flow__title — worn in
   the markup beside this class — is what gives it its voice. */
.pk-flow__gate-label {
  min-width: 0;
  line-height: var(--pk-lh-snug);
  text-align: left;
}

/* ---- connectors ---------------------------------------------------------
   One element per gap. A straight run is drawn with a border and a rotated
   square for the head — no SVG needed and nothing to measure. A split or a
   join is an inline SVG with a FIXED viewBox, because the branch layer's
   width is fixed by --pk-flow-node-w and the gap: the geometry is known at
   authoring time, so nothing has to be computed at run time. */
.pk-flow__link {
  position: relative;
  width: 100%;
  height: var(--pk-flow-link-h);
}
.pk-flow__link--straight::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 0;
  bottom: 7px;
  border-left: var(--pk-line) solid var(--pk-control-border);
}
.pk-flow__link--straight::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 2px;
  width: 7px;
  height: 7px;
  transform: translateX(-50%) rotate(45deg);
  border-right: var(--pk-line) solid var(--pk-control-border);
  border-bottom: var(--pk-line) solid var(--pk-control-border);
}
.pk-flow__link > svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
  color: var(--pk-control-border);
}
.pk-flow__link > svg path,
.pk-flow__link > svg polyline { fill: none; stroke: currentColor; stroke-width: 1; }
.pk-flow__link > svg polygon { fill: currentColor; stroke: none; }
/* a branch's condition, on a surface chip so the line does not read through it */
.pk-flow__edge-label {
  position: absolute;
  top: 32%;
  transform: translate(-50%, -50%);
  padding: 2px var(--pk-sp-2);
  border: var(--pk-line) solid var(--pk-rule);
  border-radius: var(--pk-radius-s);
  background: var(--pk-surface);
  font-family: var(--pk-font-mono);
  font-size: var(--pk-fs-caption);
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-body);
  color: var(--pk-ink-2);
  white-space: nowrap;
}
/* The branch centers are a known distance from the middle of the stage —
   half a node plus half a gap, each way — so the chips are placed by the same
   arithmetic the SVG's viewBox uses and nothing has to be measured. */
.pk-flow__edge-label--start { left: calc(50% - (var(--pk-flow-node-w) + var(--pk-flow-gap)) / 2); }
.pk-flow__edge-label--end { left: calc(50% + (var(--pk-flow-node-w) + var(--pk-flow-gap)) / 2); }

/* ---- the same steps as a list ------------------------------------------- */
.pk-steps.pk-steps {
  display: grid;
  gap: var(--pk-line);
  margin: 0;
  padding: 0;
  list-style: none;
  background: var(--pk-rule);
  border-block: var(--pk-line) solid var(--pk-rule);
}
.pk-steps__item.pk-steps__item {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: var(--pk-sp-2) var(--pk-sp-4);
  align-items: center;
  width: 100%;
  max-width: none;
  margin: 0;
  padding: var(--pk-sp-4) var(--pk-app-gutter, var(--pk-sp-6));
  border: 0;
  background: var(--pk-surface);
  font-family: var(--pk-font-body);
  font-size: var(--pk-fs-ui);
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink-strong);
  text-align: left;
  cursor: pointer;
}
.pk-steps__item:hover { background: var(--pk-card-hover); }
.pk-steps__item[aria-pressed="true"] { background: var(--pk-card); font-weight: 500; }
.pk-steps__index {
  font-family: var(--pk-font-mono);
  font-size: var(--pk-fs-caption);
  letter-spacing: var(--pk-ls-body);
  font-variant-numeric: tabular-nums;
  color: var(--pk-muted);
}
.pk-steps__meta {
  font-size: var(--pk-fs-caption);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-muted);
  white-space: nowrap;
}

/* ---- the inspector ------------------------------------------------------ */
.pk-inspector {
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
  background: var(--pk-surface);
}
.pk-inspector__head {
  display: flex;
  align-items: center;
  gap: var(--pk-sp-3);
  flex: none;
  min-height: 44px;
  padding: var(--pk-sp-2) var(--pk-sp-5);
  border-bottom: var(--pk-line) solid var(--pk-rule);
}
.pk-inspector__index {
  font-family: var(--pk-font-mono);
  font-size: var(--pk-fs-caption);
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-body);
  color: var(--pk-muted);
}
.pk-inspector__title.pk-inspector__title {
  margin: 0;
  min-width: 0;
  font-family: var(--pk-font-body);
  font-size: var(--pk-fs-ui);
  font-weight: 500;
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink-strong);
}
.pk-inspector__close { margin-left: auto; }
.pk-inspector__body { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.pk-inspector__panel[hidden] { display: none; }
.pk-inspector__section {
  display: grid;
  gap: var(--pk-sp-3);
  padding: var(--pk-sp-5);
  border-bottom: var(--pk-line) solid var(--pk-rule);
}
.pk-inspector__section:last-child { border-bottom: 0; }
/* A heading, so it is in the app chrome's own voice — Inter, 500, black. Mono
   in this file is reserved for ids, counts, step indexes, dates, group
   run-labels and eyebrows; a section heading is none of those. 12 rather than
   13, so it sits one step under the inspector's own title. */
.pk-inspector__section-title.pk-inspector__section-title {
  margin: 0;
  font-family: var(--pk-font-body);
  font-size: var(--pk-fs-caption);
  font-weight: 500;
  line-height: var(--pk-lh-tight);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink-strong);
}
.pk-inspector__text.pk-inspector__text {
  margin: 0;
  font-size: var(--pk-fs-ui);
  line-height: var(--pk-lh-body);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink-2);
}
/* a role or an evidence line: name on the left, figure on the right */
.pk-inspector__rows.pk-inspector__rows { display: grid; gap: var(--pk-sp-1); margin: 0; padding: 0; list-style: none; }
.pk-inspector__row.pk-inspector__row {
  display: flex;
  align-items: baseline;
  gap: var(--pk-sp-3);
  max-width: none;
  padding: var(--pk-sp-2) 0;
  border-top: var(--pk-line) solid var(--pk-rule);
  font-size: var(--pk-fs-ui);
  line-height: var(--pk-lh-snug);
  letter-spacing: var(--pk-ls-ui);
  color: var(--pk-ink);
}
.pk-inspector__row:first-child { border-top: 0; }
.pk-inspector__row > b { font-weight: 400; min-width: 0; }
.pk-inspector__figure {
  margin-left: auto;
  flex: none;
  font-size: var(--pk-fs-caption);
  letter-spacing: var(--pk-ls-ui);
  font-variant-numeric: tabular-nums;
  color: var(--pk-muted);
}

/* ---- drawers ------------------------------------------------------------
   Below 1200 the inspector leaves the grid; below 810 the catalogue does
   too. A drawer is the same element in a different place — no second markup
   and no second component — so what is inside it never has to be authored
   twice. --pk-z-popover, because a drawer is a popover over one region, not
   a modal over the page. */
/* The map's two views (Map / Steps) are .pk-seg panels that must FILL the
   region rather than size to their content. */
.pk-studio__view { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.pk-studio__view[hidden] { display: none; }
/* the one region inside a view that scrolls */
.pk-studio__scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; }

/* A control that only exists at the widths where its region is a drawer; and
   one that only exists at the widths where the map has room for it. */
.pk-studio__drawer-only,
.pk-studio__drawer-only-narrow { display: none; }
.pk-studio__wide-only { display: inline-flex; }
.pk-studio__rail[hidden],
.pk-studio__inspector[hidden] { display: none; }

@media (max-width: 1199.98px) {
  .pk-studio { grid-template-columns: var(--pk-studio-rail) minmax(0, 1fr); }
  .pk-studio__inspector {
    position: absolute;
    z-index: var(--pk-z-popover);
    top: 0;
    right: 0;
    bottom: 0;
    width: min(var(--pk-studio-inspector), 92%);
    border-left: var(--pk-line) solid var(--pk-rule);
    transition: transform var(--pk-dur) var(--pk-ease);
  }
  .pk-studio { position: relative; }
  .pk-studio__drawer-only { display: inline-flex; }
}
@media (max-width: 809.98px) {
  .pk-studio { grid-template-columns: minmax(0, 1fr); }
  .pk-studio__rail {
    position: absolute;
    z-index: var(--pk-z-popover);
    top: 0;
    left: 0;
    bottom: 0;
    width: min(var(--pk-studio-rail), 92%);
    border-right: var(--pk-line) solid var(--pk-rule);
  }
  .pk-studio__drawer-only-narrow { display: inline-flex; }
  .pk-studio__wide-only { display: none; }
  .pk-flow__stage { padding: var(--pk-sp-6) var(--pk-sp-4); }
  .pk-steps__item.pk-steps__item { padding-inline: var(--pk-sp-4); }
}

/* Fullscreen: the platform's, with a class the page can fall back to when an
   embedded browser refuses it. Neither one animates. */
.pk-studio:fullscreen { background: var(--pk-rule); }
.pk-studio--expanded {
  position: fixed;
  inset: 0;
  z-index: var(--pk-z-modal);
}

/* ==========================================================================
   23. MOTION
   --------------------------------------------------------------------------
   Every transition above is a state change. There is no @keyframes in this
   file and there is no loop: the system's one sanctioned looping animation
   lives in css/loader.css and nowhere else.

   base.css already stops transitions inside .pk-page under
   prefers-reduced-motion; this repeats it for app markup used on its own,
   and for the two components that render outside .pk-page — the toast
   region and the dialog's top layer. Only transition-duration is touched,
   because the loader answers prefers-reduced-motion itself, in its own file,
   by showing the finished mark.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .pk-app *, .pk-app *::before, .pk-app *::after,
  .pk-toasts *, .pk-toast, .pk-modal * { transition-duration: 0.01ms !important; }
}
