/* =========================================================================
   wireon design system — components (v2 / functional disruption)
   Canonical source. Vendored verbatim into every wireon.ch app.
   Re-copy whenever the version comment below bumps.

   Version: wireon-design-system v2 — see VENDOR_VERSIONS

   Depends on tokens.css. Pairs with wireon-ui.js for modal / confirm /
   toast / dropdown / split-button / combobox behaviour.

   Sections:
     1. base, type, wordmark
     2. atoms     — hover-invert, btn, field, panel, card, table, banner,
                    empty, badge, kv, avatar, patterns, sidebar, toolbar,
                    page-header, icon
     3. molecules — shell, dropdown / menu, split, combobox, scrim,
                    modal, toast
   ========================================================================= */


/* -------------------------------------------------------------------------
   base
   ------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-ui);
  font-size: var(--t-body);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  font-variant-numeric: tabular-nums lining-nums;
}
body { margin: 0; }

::selection { background: var(--ink); color: var(--paper); }

img { display: block; max-width: 100%; }

/* skip link — first focusable element, off-screen until focused */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--ink);
  color: var(--paper);
  padding: var(--s-3) var(--s-4);
  font: 700 var(--t-xs)/1 var(--font-ui);
  text-transform: uppercase;
  letter-spacing: var(--tr-wide);
  text-decoration: none;
  z-index: 9999;
}
.skip-link:focus { left: var(--s-4); top: var(--s-4); outline: none; }

/* -------------------------------------------------------------------------
   type roles
   ------------------------------------------------------------------------- */
.t-display, .t-h1, .t-h2 {
  font-family: var(--font-display);
  font-weight: 900;
  text-transform: lowercase;
  letter-spacing: var(--tr-display);
  margin: 0;
  text-wrap: balance;
}
.t-display { font-size: var(--t-display); line-height: var(--lh-display); }
.t-h1      { font-size: var(--t-h1);      line-height: var(--lh-h1); }
.t-h2      { font-size: var(--t-h2);      line-height: var(--lh-h2); }

.t-h3, .t-h4, .t-h5 {
  font-family: var(--font-display);
  margin: 0;
  text-wrap: balance;
}
.t-h3 { font-size: var(--t-h3); line-height: var(--lh-h3); font-weight: 800; letter-spacing: var(--tr-tight); text-transform: lowercase; }
.t-h4 { font-size: var(--t-h4); line-height: var(--lh-h4); font-weight: 700; letter-spacing: var(--tr-tight); }
.t-h5 { font-size: var(--t-h5); line-height: var(--lh-h4); font-weight: 700; letter-spacing: var(--tr-tight); }

.t-lead   { font-size: var(--t-lead);  line-height: 1.45; font-weight: 500; }
.t-body   { font-size: var(--t-body);  line-height: var(--lh-body); font-weight: 400; }
.t-small  { font-size: var(--t-small); line-height: 1.5; font-weight: 400; }

.t-overline, .t-label, .t-tag {
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: var(--t-xs);
  line-height: 1;
  letter-spacing: var(--tr-wide);
  text-transform: uppercase;
}

.t-mono { font-family: var(--font-mono); font-feature-settings: "ss01" on; }

/* type colors */
.fg        { color: var(--fg); }
.fg-muted  { color: var(--fg-muted); }
.fg-meta   { color: var(--fg-meta); }
.fg-success{ color: var(--success); }
.fg-danger { color: var(--danger); }
.fg-inverse{ color: var(--fg-inverse); }

/* -------------------------------------------------------------------------
   wordmark
   ------------------------------------------------------------------------- */
.wordmark {
  font-family: var(--font-display);
  font-weight: 900;
  text-transform: lowercase;
  letter-spacing: -0.05em;
  line-height: 1;
  color: var(--fg);
}
.wordmark--inline { font-size: 22px; }
.wordmark--med    { font-size: 40px; }
.wordmark--lg     { font-size: 96px; }
.wordmark--xl     { font-size: 160px; }
.wordmark-row {
  display: inline-flex;
  align-items: baseline;
  gap: var(--s-3);
}
.wordmark-tag {
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: var(--t-xs);
  letter-spacing: var(--tr-wide);
  text-transform: uppercase;
  border: var(--bw-hair) solid var(--fg);
  padding: 4px 6px;
  line-height: 1;
}

/* -------------------------------------------------------------------------
   hover-invert primitive
   the signature interaction. paper ⇄ ink. no shadow, no scale, no shift.
   apply .hv-invert to any tappable rectangle.
   ------------------------------------------------------------------------- */
.hv-invert {
  background: var(--paper);
  color: var(--ink);
  transition: background var(--dur-fast) var(--ease),
              color      var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease);
}
.hv-invert:hover,
.hv-invert:focus-visible {
  background: var(--ink);
  color: var(--paper);
  border-color: var(--ink);
}
/* an .hv-invert that starts inverted (filled ink) reads the other way: */
.hv-invert.is-filled {
  background: var(--ink);
  color: var(--paper);
}
.hv-invert.is-filled:hover,
.hv-invert.is-filled:focus-visible {
  background: var(--paper);
  color: var(--ink);
  border-color: var(--ink);
}

/* -------------------------------------------------------------------------
   buttons
   ------------------------------------------------------------------------- */
.btn {
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: var(--t-xs);
  letter-spacing: var(--tr-wide);
  text-transform: uppercase;
  line-height: 1;
  border: var(--bw-hair) solid var(--ink);
  padding: 0 var(--s-5);
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  cursor: pointer;
  text-decoration: none;
  background: var(--paper);
  color: var(--ink);
  transition: background var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease);
  user-select: none;
  white-space: nowrap;
}
.btn:focus-visible {
  outline: var(--bw-rule) solid var(--ink);
  outline-offset: 2px;
}
.btn--sm { height: 32px; padding: 0 var(--s-4); font-size: 10px; }
.btn--icon { width: 44px; padding: 0; }
.btn--icon.btn--sm { width: 32px; }

/* primary: ink fill, paper text. hover → outlined. */
.btn--primary { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.btn--primary:hover,
.btn--primary:focus-visible { background: var(--paper); color: var(--ink); }

/* secondary: outlined. hover → filled. */
.btn--secondary { background: var(--paper); color: var(--ink); }
.btn--secondary:hover,
.btn--secondary:focus-visible { background: var(--ink); color: var(--paper); }

/* danger: red outline, red text. hover → filled red. */
.btn--danger {
  background: var(--paper);
  color: var(--danger);
  border-color: var(--danger);
}
.btn--danger:hover,
.btn--danger:focus-visible {
  background: var(--danger);
  color: var(--paper);
  border-color: var(--danger);
}

/* success: filled green. hover → outlined green. */
.btn--success {
  background: var(--success);
  color: var(--paper);
  border-color: var(--success);
}
.btn--success:hover,
.btn--success:focus-visible {
  background: var(--paper);
  color: var(--success);
}

.btn:disabled,
.btn[aria-disabled="true"] {
  color: var(--grey-30);
  border-color: var(--grey-30);
  background: var(--paper);
  cursor: not-allowed;
  pointer-events: none;
}
.btn--primary:disabled,
.btn--primary[aria-disabled="true"] {
  background: var(--grey-10);
  border-color: var(--grey-10);
  color: var(--grey-30);
}

/* -------------------------------------------------------------------------
   form field
   ------------------------------------------------------------------------- */
.field { display: flex; flex-direction: column; gap: var(--s-2); }
.field__label {
  font-weight: 700;
  font-size: var(--t-xs);
  letter-spacing: var(--tr-wide);
  text-transform: uppercase;
  color: var(--fg);
}
.field__input {
  font-family: var(--font-ui);
  font-size: var(--t-body);
  line-height: 1.2;
  border: var(--bw-hair) solid var(--ink);
  background: var(--paper);
  color: var(--ink);
  padding: 12px 14px;
  height: 44px;
  outline: none;
  border-radius: 0;
  width: 100%;
}
.field__input::placeholder { color: var(--grey-30); }
.field__input:focus-visible,
.field__input:focus {
  outline: var(--bw-rule) solid var(--ink);
  outline-offset: 2px;
}
.field__hint  { font-size: var(--t-small); color: var(--fg-muted); }
.field__error { font-size: var(--t-small); color: var(--danger); font-weight: 600; }

.field.is-error .field__input { border-color: var(--danger); color: var(--danger); }
.field.is-error .field__input::placeholder { color: var(--danger); opacity: 0.6; }
.field.is-error .field__label { color: var(--danger); }

.field.is-disabled .field__label,
.field.is-disabled .field__input {
  color: var(--grey-30);
  border-color: var(--grey-30);
  background: var(--paper);
  cursor: not-allowed;
}

textarea.field__input { height: auto; min-height: 96px; resize: vertical; }
select.field__input { appearance: none; background-image:
  linear-gradient(45deg, transparent 50%, var(--ink) 50%),
  linear-gradient(135deg, var(--ink) 50%, transparent 50%);
  background-position: right 16px top 50%, right 11px top 50%;
  background-size: 5px 5px;
  background-repeat: no-repeat;
  padding-right: 36px;
}

/* -------------------------------------------------------------------------
   panel
   ------------------------------------------------------------------------- */
.panel {
  border: var(--bw-hair) solid var(--ink);
  background: var(--paper);
  padding: var(--s-6);
}
.panel__title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--t-h4);
  letter-spacing: var(--tr-tight);
  text-transform: lowercase;
  margin: 0 0 var(--s-4);
  padding-bottom: var(--s-4);
  border-bottom: var(--bw-rule) solid var(--ink);
}

/* -------------------------------------------------------------------------
   card — tappable surface representing an object.
   hover inverts everything inside, including muted text.
   ------------------------------------------------------------------------- */
.card {
  border: var(--bw-hair) solid var(--ink);
  background: var(--paper);
  color: var(--ink);
  padding: var(--s-6);
  display: block;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease);
}
.card:hover,
.card:focus-visible {
  background: var(--ink);
  color: var(--paper);
  outline: none;
}
.card:hover .card__meta,
.card:focus-visible .card__meta { color: var(--paper); }
.card__overline {
  font-weight: 700;
  font-size: var(--t-xs);
  letter-spacing: var(--tr-wide);
  text-transform: uppercase;
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: var(--s-4);
}
.card__title {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: var(--t-h4);
  letter-spacing: var(--tr-tight);
  text-transform: lowercase;
  margin: 0 0 var(--s-2);
}
.card__meta {
  color: var(--grey-60);
  font-size: var(--t-small);
  transition: color var(--dur-fast) var(--ease);
}

/* -------------------------------------------------------------------------
   data table
   ------------------------------------------------------------------------- */
.table {
  width: 100%;
  border-collapse: collapse;
  font-variant-numeric: tabular-nums lining-nums;
}
.table thead th {
  font-weight: 700;
  font-size: var(--t-xs);
  letter-spacing: var(--tr-wide);
  text-transform: uppercase;
  text-align: left;
  padding: var(--s-3) var(--s-4);
  border-bottom: var(--bw-hair) solid var(--ink);
  color: var(--fg);
  background: var(--paper);
}
.table tbody td {
  padding: var(--s-3) var(--s-4);
  border-bottom: var(--bw-hair) solid var(--rule-soft);
  font-size: var(--t-body);
  vertical-align: middle;
}
.table tbody tr {
  transition: background var(--dur-fast) var(--ease);
}
.table tbody tr:hover td { background: var(--grey-10); }
.table tbody tr:last-child td { border-bottom: var(--bw-hair) solid var(--ink); }
.table th.is-num,
.table td.is-num { text-align: right; font-variant-numeric: tabular-nums lining-nums; }
.table th.is-actions,
.table td.is-actions { text-align: right; width: 1%; white-space: nowrap; }

/* -------------------------------------------------------------------------
   banner
   ------------------------------------------------------------------------- */
.banner {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  border: var(--bw-hair) solid var(--ink);
  font-size: var(--t-small);
  font-weight: 500;
}
.banner__label {
  font-weight: 700;
  font-size: var(--t-xs);
  letter-spacing: var(--tr-wide);
  text-transform: uppercase;
}
.banner--error   { background: var(--ink);    color: var(--paper); border-color: var(--ink); }
.banner--error .banner__label { color: var(--paper); }
.banner--success { background: var(--paper); color: var(--ink); border-color: var(--success); }
.banner--success .banner__label { color: var(--success); }
.banner--ok      { background: var(--paper); color: var(--success); border-color: var(--success); }
.banner--ok .banner__label { color: var(--success); }
.banner--info    { background: var(--paper); color: var(--fg-muted); border-color: var(--grey-30); }
.banner--info .banner__label { color: var(--fg); }

/* -------------------------------------------------------------------------
   empty state
   ------------------------------------------------------------------------- */
.empty {
  border: var(--bw-hair) dashed var(--grey-30);
  padding: var(--s-7) var(--s-5);
  text-align: center;
  color: var(--fg-muted);
  font-size: var(--t-small);
}
.empty__title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--t-h5);
  text-transform: lowercase;
  letter-spacing: var(--tr-tight);
  color: var(--fg);
  margin: 0 0 var(--s-2);
}

/* -------------------------------------------------------------------------
   badge / mode tag
   ------------------------------------------------------------------------- */
.badge {
  display: inline-flex;
  align-items: center;
  padding: 4px 8px;
  font-weight: 700;
  font-size: 10px;
  letter-spacing: var(--tr-wide);
  text-transform: uppercase;
  line-height: 1;
  border: var(--bw-hair) solid var(--ink);
  background: var(--paper);
  color: var(--ink);
}
.badge--filled { background: var(--ink); color: var(--paper); }
.badge--muted  { border-color: var(--grey-30); color: var(--grey-60); }
.badge--success{ border-color: var(--success); color: var(--success); }
.badge--danger { border-color: var(--danger);  color: var(--danger); }

/* -------------------------------------------------------------------------
   KV list — two-column definition list for object detail.
   ------------------------------------------------------------------------- */
.kv {
  display: grid;
  grid-template-columns: 160px 1fr;
  gap: var(--s-3) var(--s-5);
  margin: 0;
}
.kv dt {
  font-weight: 700;
  font-size: var(--t-xs);
  letter-spacing: var(--tr-wide);
  text-transform: uppercase;
  color: var(--fg);
  padding-top: 3px;
}
.kv dd { margin: 0; font-size: var(--t-body); color: var(--fg); }
.kv dd.fg-muted { color: var(--fg-muted); }

/* -------------------------------------------------------------------------
   avatar — square. always.
   ------------------------------------------------------------------------- */
.avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px; height: 36px;
  background: var(--ink);
  color: var(--paper);
  font-weight: 800;
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0;
}
.avatar--lg { width: 64px; height: 64px; font-size: 22px; }
.avatar--inverse { background: var(--paper); color: var(--ink); border: var(--bw-hair) solid var(--ink); }

/* -------------------------------------------------------------------------
   patterns — radial dots, halftone, stripes, dither, double line.
   all are ink on paper. all inherit currentColor — so hover-invert flips
   them for free.
   ------------------------------------------------------------------------- */

/* dot wash — three densities */
.pat-dot-faint,
.pat-dot-mid,
.pat-dot-dense {
  background-color: var(--paper);
  background-image: radial-gradient(circle at 50% 50%, currentColor 0.9px, transparent 1.3px);
}
.pat-dot-faint  { background-size: 18px 18px; color: rgba(0,0,0,0.30); }
.pat-dot-mid    { background-size: 12px 12px; color: rgba(0,0,0,0.65); }
.pat-dot-dense  { background-size:  8px  8px; color: rgba(0,0,0,1); }

/* halftone band — dot wash + directional mask (top→bottom by default) */
.pat-halftone-band {
  background-color: var(--paper);
  background-image: radial-gradient(circle, currentColor 1.2px, transparent 1.6px);
  background-size: 8px 8px;
  color: rgba(0,0,0,0.85);
  -webkit-mask-image: linear-gradient(to top, #000 0%, #000 30%, transparent 100%);
          mask-image: linear-gradient(to top, #000 0%, #000 30%, transparent 100%);
}
.pat-halftone-band--top {
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 30%, transparent 100%);
          mask-image: linear-gradient(to bottom, #000 0%, #000 30%, transparent 100%);
}
.pat-halftone-band--left {
  -webkit-mask-image: linear-gradient(to right, #000 0%, #000 30%, transparent 100%);
          mask-image: linear-gradient(to right, #000 0%, #000 30%, transparent 100%);
}
.pat-halftone-band--right {
  -webkit-mask-image: linear-gradient(to left, #000 0%, #000 30%, transparent 100%);
          mask-image: linear-gradient(to left, #000 0%, #000 30%, transparent 100%);
}

/* stripes — diagonal ink on paper */
.pat-stripes {
  background-color: var(--paper);
  background-image: repeating-linear-gradient(
    45deg,
    currentColor 0,
    currentColor var(--stripe-w),
    var(--paper) var(--stripe-w),
    var(--paper) calc(var(--stripe-w) + var(--stripe-gap))
  );
  color: var(--ink);
}
.pat-stripes--90  { background-image: repeating-linear-gradient(90deg,  currentColor 0, currentColor var(--stripe-w), var(--paper) var(--stripe-w), var(--paper) calc(var(--stripe-w) + var(--stripe-gap))); }
.pat-stripes--135 { background-image: repeating-linear-gradient(135deg, currentColor 0, currentColor var(--stripe-w), var(--paper) var(--stripe-w), var(--paper) calc(var(--stripe-w) + var(--stripe-gap))); }
.pat-stripes--tight { --stripe-w: 3px; --stripe-gap: 5px; }
.pat-stripes--wide  { --stripe-w: 16px; --stripe-gap: 24px; }

/* dither — 4×4 bayer-style two-color pattern, scaled small */
.pat-dither {
  background-color: var(--paper);
  background-image:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='8' height='8' shape-rendering='crispEdges'><rect width='2' height='2' x='0' y='0' fill='%23000'/><rect width='2' height='2' x='4' y='4' fill='%23000'/><rect width='2' height='2' x='4' y='0' fill='%23000' opacity='0.5'/><rect width='2' height='2' x='0' y='4' fill='%23000' opacity='0.5'/></svg>");
  background-size: 8px 8px;
  image-rendering: pixelated;
}
.pat-dither--dense {
  background-image:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='8' height='8' shape-rendering='crispEdges'><rect width='2' height='2' x='0' y='0' fill='%23000'/><rect width='2' height='2' x='2' y='2' fill='%23000'/><rect width='2' height='2' x='4' y='4' fill='%23000'/><rect width='2' height='2' x='6' y='6' fill='%23000'/><rect width='2' height='2' x='4' y='0' fill='%23000'/><rect width='2' height='2' x='6' y='2' fill='%23000'/><rect width='2' height='2' x='0' y='4' fill='%23000'/><rect width='2' height='2' x='2' y='6' fill='%23000'/></svg>");
}
.pat-dither--light {
  background-image:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='8' height='8' shape-rendering='crispEdges'><rect width='2' height='2' x='0' y='0' fill='%23000'/></svg>");
}

/* double-line — divider + frame */
.pat-double-line {
  border-top: var(--bw-hair) solid var(--ink);
  border-bottom: var(--bw-hair) solid var(--ink);
  height: 5px;
}
.pat-double-frame {
  outline: var(--bw-hair) solid var(--ink);
  outline-offset: 4px;
  border: var(--bw-hair) solid var(--ink);
}

/* hover-invert for patterns: when the parent inverts, currentColor flips. */
.hv-invert:hover [class*="pat-dot"],
.hv-invert:hover [class*="pat-stripes"],
.hv-invert:hover .pat-halftone-band,
.hv-invert:hover .pat-double-line,
.hv-invert:hover .pat-double-frame {
  background-color: var(--ink);
  color: var(--paper);
}

/* -------------------------------------------------------------------------
   sidebar shell
   ------------------------------------------------------------------------- */
.shell-sidebar {
  background: var(--ink);
  color: var(--paper);
  width: 248px;
  padding: var(--s-5);
  display: flex;
  flex-direction: column;
  gap: var(--s-5);
}
.shell-sidebar__wm {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: 28px;
  letter-spacing: -0.05em;
  text-transform: lowercase;
  margin-bottom: var(--s-4);
}
.shell-sidebar__group {
  font-weight: 700;
  font-size: var(--t-xs);
  letter-spacing: var(--tr-wide);
  text-transform: uppercase;
  color: rgba(255,255,255,0.45);
  margin: 0 0 var(--s-2);
}
.shell-sidebar__item {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-2) 0 var(--s-2) var(--s-3);
  color: rgba(255,255,255,0.65);
  text-decoration: none;
  font-size: var(--t-small);
  font-weight: 500;
  border-left: var(--bw-rule) solid transparent;
  cursor: pointer;
}
.shell-sidebar__item:hover { color: var(--paper); }
.shell-sidebar__item.is-active {
  color: var(--paper);
  border-left-color: var(--paper);
  font-weight: 700;
}

/* sidebar extensions (v2.1, V1-GOLIVE-PLAN D4) — trailing adornments
   on an item, sub-items, metrics and dividers. Adornments are spans
   INSIDE a .shell-sidebar__item; __count/__kbd push themselves to the
   right edge with margin-left:auto (use at most one per item). */
.shell-sidebar__count {
  margin-left: auto;
  font-size: var(--t-xs);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  padding: 0 var(--s-2);
  border: var(--bw-rule) solid rgba(255,255,255,0.35);
  color: rgba(255,255,255,0.75);
  line-height: 18px;
  min-width: 18px;
  text-align: center;
}
.shell-sidebar__item.is-active .shell-sidebar__count {
  border-color: var(--paper);
  color: var(--paper);
}
.shell-sidebar__dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--paper);
  flex: none;
  align-self: center;
}
.shell-sidebar__kbd {
  margin-left: auto;
  font-family: var(--font-mono, monospace);
  font-size: var(--t-xs);
  letter-spacing: var(--tr-wide);
  text-transform: uppercase;
  color: rgba(255,255,255,0.45);
  border: var(--bw-rule) solid rgba(255,255,255,0.25);
  padding: 0 var(--s-1);
  line-height: 16px;
}
.shell-sidebar__metric {
  padding: var(--s-2) 0 var(--s-2) var(--s-3);
  border-left: var(--bw-rule) solid rgba(255,255,255,0.25);
}
.shell-sidebar__metric .v {
  display: block;
  font-family: var(--font-display);
  font-weight: 900;
  font-size: var(--t-h3);
  letter-spacing: -0.03em;
  color: var(--paper);
  font-variant-numeric: tabular-nums;
}
.shell-sidebar__metric .lbl {
  display: block;
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: var(--tr-wide);
  text-transform: uppercase;
  color: rgba(255,255,255,0.45);
}
.shell-sidebar__sub {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-1) 0 var(--s-1) calc(var(--s-3) * 2 + var(--s-2));
  color: rgba(255,255,255,0.5);
  text-decoration: none;
  font-size: var(--t-xs);
  font-weight: 500;
  border-left: var(--bw-rule) solid transparent;
  cursor: pointer;
}
.shell-sidebar__sub:hover { color: var(--paper); }
.shell-sidebar__sub.is-active {
  color: var(--paper);
  border-left-color: rgba(255,255,255,0.45);
  font-weight: 700;
}
.shell-sidebar__divider {
  border: 0;
  border-top: var(--bw-hair) solid rgba(255,255,255,0.25);
  margin: var(--s-3) 0;
}

/* -------------------------------------------------------------------------
   editor toolbar — 52px hairline-divided cells
   ------------------------------------------------------------------------- */
.toolbar {
  display: flex;
  align-items: stretch;
  border-top: var(--bw-hair) solid var(--ink);
  border-bottom: var(--bw-hair) solid var(--ink);
  height: 52px;
  background: var(--paper);
}
.toolbar__cell {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  padding: 0 var(--s-4);
  border-right: var(--bw-hair) solid var(--ink);
  font-size: var(--t-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--tr-wide);
  cursor: pointer;
  background: var(--paper);
  color: var(--ink);
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.toolbar__cell:hover,
.toolbar__cell.is-active {
  background: var(--ink);
  color: var(--paper);
}
.toolbar__cell--brand {
  background: var(--ink);
  color: var(--paper);
  font-family: var(--font-display);
  font-weight: 900;
  font-size: 18px;
  letter-spacing: -0.05em;
  text-transform: lowercase;
}
.toolbar__cell--brand:hover { background: var(--ink); color: var(--paper); cursor: default; }
.toolbar__spacer { flex: 1; border-right: 0; cursor: default; background: transparent; }
.toolbar__spacer:hover { background: transparent; color: var(--ink); }

/* -------------------------------------------------------------------------
   page-header — 4px top border, 2px bottom rule, lowercase h1
   ------------------------------------------------------------------------- */
.page-header {
  border-top: var(--bw-bar) solid var(--ink);
  border-bottom: var(--bw-rule) solid var(--ink);
  padding: var(--s-6) 0 var(--s-5);
}
.page-header__crumb {
  font-weight: 700;
  font-size: var(--t-xs);
  letter-spacing: var(--tr-wide);
  text-transform: uppercase;
  color: var(--fg-muted);
  margin-bottom: var(--s-3);
}
.page-header__title {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: var(--t-h2);
  line-height: 0.95;
  text-transform: lowercase;
  letter-spacing: var(--tr-display);
  margin: 0;
}

/* -------------------------------------------------------------------------
   icon — Carbon-style 1px-stroke SVG, inline, inherits currentColor
   ------------------------------------------------------------------------- */
.icon {
  display: inline-block;
  width: 16px;
  height: 16px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: square;
  stroke-linejoin: miter;
  vertical-align: middle;
}
.icon--20 { width: 20px; height: 20px; }
.icon--24 { width: 24px; height: 24px; }
.icon--lg { width: 48px; height: 48px; stroke-width: 1; }

/* =========================================================================
   MOLECULES — the high-surface layer the apps used to hand-roll.
   App shell, dropdown menu, split button, modal, confirm, toast.
   Every one obeys the six foundations: ink & paper, hard 1px rules,
   no radius, lowercase display, hover-invert, always light. Overlays
   earn depth from a flat ink scrim — never a shadow, never a blur.
   Driven by wireon-v2.js (window.wireon + data-wireon-* attributes).
   ========================================================================= */

/* -------------------------------------------------------------------------
   app shell — sidebar + topbar + content scaffold.
   the canonical full-app frame. pairs with .shell-sidebar (above).
   ------------------------------------------------------------------------- */
.shell {
  display: grid;
  grid-template-columns: 248px minmax(0, 1fr);
  min-height: 100vh;
  background: var(--bg);
}
.shell__main {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.shell__topbar {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  height: 64px;
  flex: none;
  padding: 0 var(--s-6);
  background: var(--paper);
  border-bottom: var(--bw-hair) solid var(--ink);
  position: sticky;
  top: 0;
  z-index: 40;
}
.shell__title {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}
.shell__crumb {
  font-weight: 700;
  font-size: var(--t-xs);
  letter-spacing: var(--tr-wide);
  text-transform: uppercase;
  color: var(--fg-muted);
  line-height: 1;
}
.shell__heading {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--t-h5);
  line-height: 1;
  letter-spacing: var(--tr-tight);
  text-transform: lowercase;
  margin: 0;
}
.shell__spacer { flex: 1 1 auto; }
.shell__actions {
  display: flex;
  align-items: center;
  gap: var(--s-2);
}
.shell__content {
  flex: 1 1 auto;
  padding: var(--s-7) var(--s-6);
  min-width: 0;
}

/* -------------------------------------------------------------------------
   dropdown menu — the popover list. anchored to a trigger by JS.
   item hover is the full invert (paper ⇄ ink) — the signature, the same
   move the toolbar cell makes. a danger item flips to red instead.
   ------------------------------------------------------------------------- */
.dropdown { position: relative; display: inline-flex; }

.menu {
  background: var(--paper);
  border: var(--bw-hair) solid var(--ink);
  min-width: 208px;
  display: flex;
  flex-direction: column;
  padding: 0;
  margin: 0;
  list-style: none;
  z-index: 1050;
}
.menu--pop {                /* positioned popover; JS sets top/left */
  position: absolute;
  top: calc(100% + var(--s-1));
  left: 0;
}
.menu--right { left: auto; right: 0; }

.menu__label {
  font-weight: 700;
  font-size: var(--t-xs);
  letter-spacing: var(--tr-wide);
  text-transform: uppercase;
  color: var(--fg-muted);
  padding: var(--s-3) var(--s-4) var(--s-2);
}
.menu__sep {
  height: var(--bw-hair);
  background: var(--rule-soft);
  border: 0;
  margin: 0;
}
.menu__item {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  width: 100%;
  padding: var(--s-3) var(--s-4);
  font-family: var(--font-ui);
  font-size: var(--t-small);
  font-weight: 500;
  line-height: 1.2;
  text-align: left;
  text-decoration: none;
  color: var(--ink);
  background: var(--paper);
  border: 0;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease);
}
.menu__item:hover,
.menu__item:focus-visible,
.menu__item.is-active {
  background: var(--ink);
  color: var(--paper);
  outline: none;
}
.menu__item .icon { flex: none; }
.menu__item-key {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: var(--t-xs);
  color: var(--fg-muted);
  letter-spacing: 0;
}
.menu__item:hover .menu__item-key,
.menu__item:focus-visible .menu__item-key,
.menu__item.is-active .menu__item-key { color: var(--paper); }

.menu__item--danger { color: var(--danger); }
.menu__item--danger:hover,
.menu__item--danger:focus-visible,
.menu__item--danger.is-active { background: var(--danger); color: var(--paper); }

.menu__item[aria-disabled="true"],
.menu__item:disabled {
  color: var(--grey-30);
  pointer-events: none;
  cursor: not-allowed;
}

/* -------------------------------------------------------------------------
   split button — a primary action welded to a caret that opens a menu.
   the two cells collapse to a single 1px seam; on an ink fill the seam
   is drawn in paper so it stays visible.
   ------------------------------------------------------------------------- */
.split { display: inline-flex; align-items: stretch; }
.split > .btn:first-child { border-right-width: 0; }
.split__toggle { width: 40px; padding: 0; }
.split__toggle.btn--sm { width: 32px; }
.split--primary .split__toggle { border-left: var(--bw-hair) solid var(--paper); }
.split--primary .split__toggle:hover,
.split--primary .split__toggle:focus-visible { border-left-color: var(--ink); }

/* -------------------------------------------------------------------------
   combobox — a .field input welded to a popover listbox. type to filter,
   arrows to move, Enter to pick. the list speaks the same visual language
   as .menu: paper, 1px ink, full invert on the active row. no shadow,
   no radius — depth is the hairline, as everywhere else.
   .combobox--select is the constrained variant: a searchable select with
   a caret, for closed value sets (currencies, instances).
   ------------------------------------------------------------------------- */
.combobox { position: relative; }
.combobox .field__input { width: 100%; }

/* select-only variant — caret drawn like select.field__input's */
.combobox--select .field__input {
  cursor: pointer;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--ink) 50%),
    linear-gradient(135deg, var(--ink) 50%, transparent 50%);
  background-position: right 16px top 50%, right 11px top 50%;
  background-size: 5px 5px;
  background-repeat: no-repeat;
  padding-right: 36px;
}

.combobox__list {
  position: absolute;
  top: calc(100% + var(--s-1));
  left: 0;
  right: 0;
  background: var(--paper);
  border: var(--bw-hair) solid var(--ink);
  max-height: 280px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  padding: 0;
  margin: 0;
  list-style: none;
  z-index: 1050;
}
.combobox__option {
  display: flex;
  flex-direction: column;
  gap: 2px;
  width: 100%;
  padding: var(--s-3) var(--s-4);
  font-family: var(--font-ui);
  font-size: var(--t-small);
  font-weight: 500;
  line-height: 1.2;
  text-align: left;
  color: var(--ink);
  background: var(--paper);
  border: 0;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease);
}
.combobox__option:hover,
.combobox__option--active {
  background: var(--ink);
  color: var(--paper);
  outline: none;
}
.combobox__option-hint {
  font-size: var(--t-xs);
  font-weight: 400;
  color: var(--fg-muted);
  transition: color var(--dur-fast) var(--ease);
}
.combobox__option:hover .combobox__option-hint,
.combobox__option--active .combobox__option-hint { color: var(--paper); }

.combobox__empty {
  padding: var(--s-3) var(--s-4);
  font-size: var(--t-small);
  color: var(--fg-muted);
}

/* -------------------------------------------------------------------------
   scrim — the flat ink wash behind any overlay. no blur, no shadow.
   depth is this one rectangle of ink at 55%, nothing more.
   ------------------------------------------------------------------------- */
.scrim {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--s-7) var(--s-5);
  background: rgba(0, 0, 0, 0.55);
  animation: wo-scrim-in var(--dur) var(--ease);
}
@keyframes wo-scrim-in { from { opacity: 0; } to { opacity: 1; } }
.scrim.is-leaving { animation: wo-scrim-out var(--dur) var(--ease) forwards; }
@keyframes wo-scrim-out { to { opacity: 0; } }
html.wo-locked { overflow: hidden; }

/* -------------------------------------------------------------------------
   modal / dialog — paper panel, hairline border, 2px title rule.
   header (overline + lowercase title + close) · body · footer actions.
   ------------------------------------------------------------------------- */
.modal {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 560px;                       /* md, default */
  max-height: calc(100vh - var(--s-7) * 2);
  background: var(--paper);
  border: var(--bw-hair) solid var(--ink);
  animation: wo-modal-in var(--dur) var(--ease);
}
@keyframes wo-modal-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}
.scrim.is-leaving .modal { animation: wo-modal-out var(--dur) var(--ease) forwards; }
@keyframes wo-modal-out { to { opacity: 0; transform: translateY(8px); } }

.modal--sm { max-width: 420px; }
.modal--md { max-width: 560px; }
.modal--lg { max-width: 760px; }

.modal__hazard {                          /* destructive-moment striped edge */
  flex: none;
  height: 6px;
  background-image: repeating-linear-gradient(
    45deg,
    var(--ink) 0, var(--ink) 7px,
    var(--paper) 7px, var(--paper) 14px
  );
}
.modal__header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--s-4);
  flex: none;
  padding: var(--s-6) var(--s-6) var(--s-4);
  border-bottom: var(--bw-rule) solid var(--ink);
}
.modal__heading { display: flex; flex-direction: column; gap: var(--s-2); min-width: 0; }
.modal__overline {
  font-weight: 700;
  font-size: var(--t-xs);
  letter-spacing: var(--tr-wide);
  text-transform: uppercase;
  color: var(--fg-muted);
}
.modal__title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--t-h4);
  line-height: var(--lh-h4);
  letter-spacing: var(--tr-tight);
  text-transform: lowercase;
  margin: 0;
}
.modal__close {
  flex: none;
  width: 36px; height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--paper);
  color: var(--ink);
  border: var(--bw-hair) solid var(--ink);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.modal__close:hover,
.modal__close:focus-visible { background: var(--ink); color: var(--paper); outline: none; }
.modal__body {
  padding: var(--s-6);
  overflow-y: auto;
  font-size: var(--t-body);
  line-height: var(--lh-body);
}
.modal__body > * + * { margin-top: var(--s-4); }
.modal__footer {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--s-2);
  flex: none;
  padding: var(--s-4) var(--s-6);
  border-top: var(--bw-hair) solid var(--ink);
}
.modal__footer--spread { justify-content: space-between; }

/* -------------------------------------------------------------------------
   toast — top-right, stack downward, auto-dismiss. paper card, 1px ink,
   a shrinking 2px ink timer along the bottom edge. error toasts shout in
   ink-fill / paper-text, the same voice as the error banner.
   ------------------------------------------------------------------------- */
.toast-region {
  position: fixed;
  top: var(--s-5);
  right: var(--s-5);
  z-index: 1100;
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  width: 360px;
  max-width: calc(100vw - var(--s-5) * 2);
  pointer-events: none;
}
.toast {
  position: relative;
  overflow: hidden;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: stretch;
  background: var(--paper);
  color: var(--ink);
  border: var(--bw-hair) solid var(--ink);
  pointer-events: auto;
  animation: wo-toast-in var(--dur) var(--ease);
}
@keyframes wo-toast-in {
  from { opacity: 0; transform: translateX(16px); }
  to   { opacity: 1; transform: none; }
}
.toast.is-leaving { animation: wo-toast-out var(--dur) var(--ease) forwards; }
@keyframes wo-toast-out { to { opacity: 0; transform: translateX(16px); } }

.toast__body {
  padding: var(--s-3) var(--s-4);
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  min-width: 0;
}
.toast__label {
  font-weight: 700;
  font-size: var(--t-xs);
  letter-spacing: var(--tr-wide);
  text-transform: uppercase;
}
.toast__msg { font-size: var(--t-small); line-height: 1.5; }
.toast__close {
  flex: none;
  width: 40px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  color: inherit;
  border: 0;
  border-left: var(--bw-hair) solid currentColor;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.toast__close:hover,
.toast__close:focus-visible { background: var(--ink); color: var(--paper); outline: none; }
.toast__timer {
  position: absolute;
  left: 0;
  bottom: 0;
  height: 2px;
  width: 100%;
  background: var(--ink);
  transform-origin: left center;
  animation: wo-toast-timer linear forwards;
}
@keyframes wo-toast-timer { from { transform: scaleX(1); } to { transform: scaleX(0); } }

.toast--success { border-color: var(--success); }
.toast--success .toast__label { color: var(--success); }
.toast--success .toast__timer { background: var(--success); }
.toast--success .toast__close { border-left-color: var(--success); }
.toast--success .toast__close:hover { background: var(--success); color: var(--paper); }

.toast--info { border-color: var(--grey-30); }
.toast--info .toast__label { color: var(--fg); }
.toast--info .toast__msg { color: var(--fg-muted); }
.toast--info .toast__timer { background: var(--grey-30); }

.toast--error {
  background: var(--ink);
  color: var(--paper);
  border-color: var(--ink);
}
.toast--error .toast__timer { background: var(--paper); }
.toast--error .toast__close:hover { background: var(--paper); color: var(--ink); }

/* -------------------------------------------------------------------------
   motion — overlays animate, but never against a user's wishes.
   ------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .scrim, .modal, .toast { animation: none !important; }
  .toast__timer { animation-name: none; }
}

/* -------------------------------------------------------------------------
   config editor — wireon-config-editor.js structural styles. the fields
   themselves are plain .field atoms; this block only arranges them: the
   numeric line (input + currency + "unlimited" toggle), list rows with
   their remove button, and the nested-group inset.
   ------------------------------------------------------------------------- */
.config-editor { display: flex; flex-direction: column; gap: var(--s-4); }
.config-editor__group { display: flex; flex-direction: column; gap: var(--s-4); }
.config-editor__numline { display: flex; align-items: center; gap: var(--s-3); }
.config-editor__numline .field__input { max-width: 12rem; }
.config-editor__null,
.config-editor__check {
  display: inline-flex; align-items: center; gap: var(--s-2);
  font-size: var(--t-small); color: var(--fg); cursor: pointer;
  white-space: nowrap;
}
.config-editor__json { font-family: var(--font-mono, monospace); font-size: var(--t-small); }
.config-editor__nested {
  border-left: 2px solid var(--rule);
  padding-left: var(--s-4);
  margin-top: var(--s-2);
}
.config-editor__list { display: flex; flex-direction: column; gap: var(--s-4); }
.config-editor__row {
  display: flex; align-items: flex-start; gap: var(--s-4);
  border: 1px solid var(--rule); padding: var(--s-4);
}
.config-editor__row .config-editor__group { flex: 1; }
