/* ⚠️ THE SEND SCREEN'S CSS IS NOT IN THIS FILE ANY MORE — css/send-kit.css.
   10 rules for .bx-sendhero / .bx-mailframe / .bx-sched / .bx-wm-* /
   .bx-cal-* / .bx-sent-* / .bx-mailfull-* moved out with js/send-kit.js, so the
   marketplace and work.runmai.app render the same screen from the same rules.
   Adding a send-screen rule back here would style it in ONE of the two apps,
   which is indistinguishable from the rule not working. The shared chrome
   (.bx-sheet-*, .bx-btn, .bx-input, .bx-pick-row) is still here, because a dozen
   other sheets use it. */
/* ═══════════════════════════════════════════════════════════════════════════
   Browse — colour, hierarchy, and edit mode
   Owns: the group index (Departments / Roles / Workflows / Audiences), the
   group detail page, Bundles, and every admin editing control on them.

   Rendered by js/browse.js. Kept in its OWN file, not styles.css: this is a
   self-contained feature and styles.css is edited concurrently.

   TWO THINGS TO KNOW BEFORE EDITING
   1. COLOURWAYS. Every group carries [data-hue="…"] and the four vars below.
      Nothing in here hardcodes a colour outside the hue table — that's what
      lets 24 departments look like 24 different things.
   2. THE FORCED BUTTON RADIUS. dashboard-meta.js injects, at runtime,
        button:not(.ax-card):not(.tcd-view-btn)…{border-radius:var(--wt-theme-btn-radius)!important}
      — specificity (0,5,1), and this store pins that var to 999px. Every
      <button> here is therefore a pill unless a rule OUT-SPECIFIES that one.
      Pills are right for .bx-btn/.bx-icon-btn/.bx-swatch, wrong for the three
      controls in the "radius fights" block at the bottom. Add to that block
      rather than writing a plain !important that silently loses.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── The hue table ──────────────────────────────────────────────────────────
   --bx-h1  deep    (gradient start, solid fills)
   --bx-h2  bright  (gradient end, glows)
   --bx-ink darkest (text on a light tint — always AA on --bx-mist)
   --bx-mist palest (card tints, chips)                                      */
[data-hue] { --bx-h1:#334155; --bx-h2:#94a3b8; --bx-ink:#1e293b; --bx-mist:#f1f5f9; }
[data-hue="blue"]   { --bx-h1:#0369a1; --bx-h2:#38bdf8; --bx-ink:#075985; --bx-mist:#e0f2fe; }
[data-hue="teal"]   { --bx-h1:#0f766e; --bx-h2:#2dd4bf; --bx-ink:#115e59; --bx-mist:#ccfbf1; }
[data-hue="green"]  { --bx-h1:#15803d; --bx-h2:#4ade80; --bx-ink:#166534; --bx-mist:#dcfce7; }
[data-hue="lime"]   { --bx-h1:#4d7c0f; --bx-h2:#a3e635; --bx-ink:#3f6212; --bx-mist:#ecfccb; }
[data-hue="amber"]  { --bx-h1:#b45309; --bx-h2:#fbbf24; --bx-ink:#92400e; --bx-mist:#fef3c7; }
[data-hue="orange"] { --bx-h1:#c2410c; --bx-h2:#fb923c; --bx-ink:#9a3412; --bx-mist:#ffedd5; }
[data-hue="rose"]   { --bx-h1:#9f1239; --bx-h2:#fb7185; --bx-ink:#881337; --bx-mist:#ffe4e6; }
[data-hue="pink"]   { --bx-h1:#9d174d; --bx-h2:#f472b6; --bx-ink:#831843; --bx-mist:#fce7f3; }
[data-hue="violet"] { --bx-h1:#6d28d9; --bx-h2:#a78bfa; --bx-ink:#5b21b6; --bx-mist:#ede9fe; }
[data-hue="indigo"] { --bx-h1:#3730a3; --bx-h2:#818cf8; --bx-ink:#312e81; --bx-mist:#e0e7ff; }
[data-hue="cyan"]   { --bx-h1:#0e7490; --bx-h2:#22d3ee; --bx-ink:#155e75; --bx-mist:#cffafe; }
[data-hue="slate"]  { --bx-h1:#334155; --bx-h2:#94a3b8; --bx-ink:#1e293b; --bx-mist:#f1f5f9; }

/* ── Hero band ──────────────────────────────────────────────────────────────
   The index and the detail page both open with one. On a detail page it is the
   thing that says "you went INTO something" — full colour, big medallion. */
.bx-hero {
  position: relative;
  border-radius: 20px;
  padding: 26px 30px;
  margin: 0 0 22px;
  color: #fff;
  overflow: hidden;
  /* A bundle hero has no [data-hue] — it passes its own gradient in as inline
     --bx-h1/--bx-h2, so both must have fallbacks here. */
  background: linear-gradient(125deg, var(--bx-h1, #0369a1) 0%, var(--bx-h2, #0891b2) 100%);
  box-shadow: 0 18px 40px -18px color-mix(in srgb, var(--bx-h1, #0369a1) 60%, transparent), var(--shadow-sm);
  animation: viewIn var(--dur-3) var(--ease-out) both;
}

/* Two soft light sources so a flat gradient reads as a surface. */
.bx-hero::before,
.bx-hero::after {
  content: ""; position: absolute; border-radius: 50%; pointer-events: none;
}
.bx-hero::before {
  width: 420px; height: 420px; right: -120px; top: -220px;
  background: radial-gradient(circle, rgba(255,255,255,.28), transparent 70%);
}
.bx-hero::after {
  width: 260px; height: 260px; left: 12%; bottom: -180px;
  background: radial-gradient(circle, rgba(255,255,255,.16), transparent 70%);
}

.bx-hero-inner {
  position: relative; z-index: 1;
  display: flex; align-items: center; gap: 20px; flex-wrap: wrap;
}
.bx-hero-medallion {
  flex: none;
  width: 62px; height: 62px; border-radius: 18px;
  display: grid; place-items: center;
  font-size: 26px; color: #fff;
  background: rgba(255,255,255,.18);
  border: 1px solid rgba(255,255,255,.32);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.35), 0 10px 22px -10px rgba(0,0,0,.4);
  backdrop-filter: blur(4px);
}
.bx-hero-medallion-lg { width: 84px; height: 84px; border-radius: 24px; font-size: 36px; }

.bx-hero-body { flex: 1 1 320px; min-width: 0; }
.bx-hero-eyebrow {
  font-size: 11.5px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
  color: rgba(255,255,255,.82); margin-bottom: 4px;
}
.bx-hero-title {
  margin: 0; font-size: 30px; line-height: 1.12; font-weight: 800; color: #fff;
  text-shadow: 0 1px 12px rgba(0,0,0,.18);
}
.bx-hero-sub {
  margin-top: 6px; font-size: 14px; color: rgba(255,255,255,.9); max-width: 70ch;
}
.bx-hidden-flag {
  font-size: 12px; font-weight: 600; vertical-align: middle;
  background: rgba(0,0,0,.22); border-radius: 999px; padding: 3px 10px; margin-left: 8px;
}

.bx-hero-stats { display: flex; gap: 10px; flex: none; }
.bx-stat {
  min-width: 84px; text-align: center; padding: 10px 14px; border-radius: 14px;
  background: rgba(255,255,255,.16); border: 1px solid rgba(255,255,255,.26);
}
.bx-stat-n { display: block; font-size: 24px; font-weight: 800; line-height: 1; }
.bx-stat-l { display: block; font-size: 11px; text-transform: uppercase; letter-spacing: .07em; opacity: .85; margin-top: 3px; }

/* Edit controls sit INSIDE the hero on a detail page — the actions belong to
   the thing you are looking at, not to a floating toolbar. */
.bx-hero-edit {
  position: relative; z-index: 1;
  display: flex; flex-wrap: wrap; gap: 8px;
  margin-top: 18px; padding-top: 16px;
  border-top: 1px solid rgba(255,255,255,.22);
}

/* ── Back bar + breadcrumb ──────────────────────────────────────────────── */
.bx-backbar {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  margin: 0 0 14px;
  animation: viewIn var(--dur-2) var(--ease-out) both;
}
.bx-back {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 8px 16px 8px 12px; border-radius: 999px;
  background: var(--surface); border: 1px solid var(--line);
  color: var(--ink-2); font-size: 13.5px; font-weight: 650; text-decoration: none;
  box-shadow: var(--shadow-xs);
  transition: transform var(--dur-1) var(--ease-out), box-shadow var(--dur-1) var(--ease-out),
              border-color var(--dur-1), color var(--dur-1), background var(--dur-1);
}
.bx-back i { font-size: 11px; transition: transform var(--dur-1) var(--ease-out); }
.bx-back:hover {
  color: var(--brand); border-color: color-mix(in srgb, var(--brand) 40%, var(--line));
  box-shadow: var(--shadow-sm); transform: translateX(-2px);
}
.bx-back:hover i { transform: translateX(-3px); }
.bx-back:active { transform: translateX(-2px) scale(.98); }

/* ── Group grid ─────────────────────────────────────────────────────────── */
.bx-grid {
  display: grid; gap: 16px;
  grid-template-columns: repeat(auto-fill, minmax(262px, 1fr));
}

.bx-card {
  position: relative;
  border-radius: 18px;
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-xs);
  overflow: hidden;
  transition: transform var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out), border-color var(--dur-2);
}
/* The hue's signature: a colour bar across the top and a wash behind the
   medallion. Cheap to render, and it's what makes the grid read as a spectrum. */
.bx-card::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 5px;
  background: linear-gradient(90deg, var(--bx-h1), var(--bx-h2));
}
.bx-card:hover {
  transform: translateY(-4px);
  border-color: color-mix(in srgb, var(--bx-h2) 55%, var(--line));
  box-shadow: 0 20px 38px -20px color-mix(in srgb, var(--bx-h1) 55%, transparent), var(--shadow-sm);
}

.bx-card-main {
  display: block; padding: 20px 18px 16px; text-decoration: none; color: inherit;
}
.bx-card-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.bx-medallion {
  width: 46px; height: 46px; border-radius: 14px; flex: none;
  display: grid; place-items: center; font-size: 20px; color: #fff;
  background: linear-gradient(140deg, var(--bx-h1), var(--bx-h2));
  box-shadow: 0 8px 18px -8px color-mix(in srgb, var(--bx-h1) 70%, transparent);
  transition: transform var(--dur-2) var(--ease-out);
}
.bx-card:hover .bx-medallion { transform: rotate(-6deg) scale(1.06); }

.bx-count-pill {
  flex: none; font-size: 11.5px; font-weight: 700; letter-spacing: .01em;
  padding: 5px 11px; border-radius: 999px;
  background: var(--bx-mist); color: var(--bx-ink);
}
.bx-card-name { margin-top: 13px; font-size: 16.5px; font-weight: 750; color: var(--ink); line-height: 1.25; }
.bx-card-blurb {
  margin-top: 4px; font-size: 12.8px; color: var(--muted); line-height: 1.45;
  min-height: 18px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}

.bx-faces { display: flex; align-items: center; gap: 5px; margin-top: 14px; min-height: 30px; }
.bx-face { display: inline-flex; }
.bx-faces-empty { font-size: 12px; color: var(--muted); font-style: italic; opacity: .8; }
.bx-face-more {
  display: inline-grid; place-items: center;
  width: 28px; height: 28px; border-radius: 9px;
  font-size: 11px; font-weight: 700;
  background: var(--bx-mist); color: var(--bx-ink);
}
/* Not in styles.css — the group-card face size. */
.app-icon-xs { width: 28px !important; height: 28px !important; font-size: 12px !important; border-radius: 9px !important; }

.bx-card-go {
  display: flex; align-items: center; gap: 6px;
  margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line);
  font-size: 12.5px; font-weight: 700; color: var(--bx-ink);
  opacity: .75; transition: opacity var(--dur-1), gap var(--dur-1) var(--ease-out);
}
.bx-card:hover .bx-card-go { opacity: 1; gap: 10px; }
.bx-card-go i { font-size: 11px; }

/* ── New-group tile ─────────────────────────────────────────────────────── */
.bx-card-new {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px;
  min-height: 210px; padding: 20px; cursor: pointer;
  background: color-mix(in srgb, var(--brand) 4%, var(--surface));
  border: 2px dashed color-mix(in srgb, var(--brand) 45%, var(--line));
  color: var(--brand); font: inherit; text-align: center;
  transition: background var(--dur-2), border-color var(--dur-2), transform var(--dur-2) var(--ease-out);
}
.bx-card-new::before { display: none; }
.bx-card-new:hover {
  background: color-mix(in srgb, var(--brand) 9%, var(--surface));
  border-color: var(--brand); transform: translateY(-3px);
}
.bx-new-plus {
  width: 44px; height: 44px; border-radius: 50%; display: grid; place-items: center;
  font-size: 19px; color: #fff; background: linear-gradient(140deg, var(--brand), var(--accent));
  box-shadow: 0 10px 20px -10px color-mix(in srgb, var(--brand) 70%, transparent);
}
.bx-new-label { font-weight: 750; font-size: 14.5px; color: var(--ink); }
.bx-new-sub { font-size: 12px; color: var(--muted); }


/* ── Bundle cards: one height, one shape ─────────────────────────────────────
   `.bundle-card` (styles.css) is a flex column, but the grid let every ROW size
   itself, so a 5-chip card made row 1 tall and row 2 short — the cards read as
   different objects. `grid-auto-rows: 1fr` makes EVERY row the height of the
   tallest card in the grid, and the pieces below pin so the parts line up
   across cards: description clamped to a fixed block, chips in the middle, and
   the actions row always on the bottom edge. */
.bundle-grid { grid-auto-rows: 1fr; }
.bundle-card { height: 100%; }
.bundle-desc {
  font-size: 13.5px; line-height: 1.5;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
  min-height: calc(1.5em * 2);   /* two lines minimum so short blurbs still align */
}
/* The chips take the slack, so a 2-app card and a 5-app card both put their
   buttons on the same line. */
.bundle-apps { flex: 1 1 auto; align-content: flex-start; }
.bundle-actions { margin-top: auto; }
.bundle-card-new { grid-row: auto; }

/* ── "New bundle" tile ──────────────────────────────────────────────────────
   Fills the empty slot in the bundle grid in edit mode, the same way the group
   index offers "New department". It borrows .bundle-card for size so it lines up
   with the real ones, then undoes the parts that assume a gradient. */
.bundle-card-new {
  align-items: center; justify-content: center; text-align: center; gap: 6px;
  min-height: 200px; cursor: pointer; font: inherit;
  color: var(--brand);
  background: color-mix(in srgb, var(--brand) 4%, var(--surface));
  border: 2px dashed color-mix(in srgb, var(--brand) 45%, var(--line));
  box-shadow: none;
  transition: background var(--dur-2), border-color var(--dur-2), transform var(--dur-2) var(--ease-out);
}
.bundle-card-new::before { display: none; }
.bundle-card-new:hover {
  background: color-mix(in srgb, var(--brand) 9%, var(--surface));
  border-color: var(--brand); transform: translateY(-3px);
}

/* ── Edit-mode chrome on a card ─────────────────────────────────────────── */
.bx-grid.is-editing .bx-card:not(.bx-card-new) { padding-bottom: 44px; }
.bx-card-edit {
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; align-items: center; gap: 6px;
  padding: 7px 10px;
  background: color-mix(in srgb, var(--bx-mist) 70%, var(--surface));
  border-top: 1px solid color-mix(in srgb, var(--bx-h2) 30%, var(--line));
}
/* A bundle's controls sit IN FLOW above its header, not floating over it.
   Absolute-positioning them top-right meant a long bundle name either ran
   under the buttons or wrapped to three lines to avoid them. */
.bx-bundle-editrow {
  display: flex; justify-content: flex-end; gap: 6px;
  margin: -4px -4px 10px; position: relative; z-index: 2;
}
.bx-bundle-editrow .bx-icon-btn {
  color: #fff; background: rgba(255,255,255,.18); border: 1px solid rgba(255,255,255,.28);
  backdrop-filter: blur(6px);
}
.bx-bundle-editrow .bx-icon-btn:hover { background: rgba(255,255,255,.34); color: #fff; }
.bx-bundle-editrow .bx-icon-danger:hover { background: rgba(220,38,38,.75); color: #fff; }

.bx-drag { margin-right: auto; color: var(--muted); cursor: grab; padding: 4px 2px; font-size: 13px; }
.bx-drag:active { cursor: grabbing; }

.bx-icon-btn {
  width: 30px; height: 30px; display: grid; place-items: center;
  border: 0; cursor: pointer; font-size: 12.5px;
  background: rgba(255,255,255,.85); color: var(--ink-2);
  box-shadow: var(--shadow-xs);
  transition: background var(--dur-1), color var(--dur-1), transform var(--dur-1) var(--ease-out);
}
.bx-icon-btn:hover { background: #fff; color: var(--bx-ink, var(--brand)); transform: translateY(-1px); }
.bx-icon-danger:hover { background: #fee2e2; color: #b91c1c; }

.bx-card.is-dragging { opacity: .55; transform: scale(.97) rotate(-1deg); box-shadow: var(--shadow-lg); }
.bx-card.is-hidden-group { opacity: .62; }
.bx-hidden-tag {
  position: absolute; top: 12px; left: 50%; transform: translateX(-50%);
  font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em;
  background: rgba(15,23,42,.82); color: #fff; padding: 3px 10px; border-radius: 999px;
  pointer-events: none;
}
.bx-edited-flag {
  position: absolute; top: 12px; right: 12px;
  width: 22px; height: 22px; border-radius: 50%; display: grid; place-items: center;
  font-size: 9.5px; color: var(--bx-ink); background: var(--bx-mist);
  border: 1px solid color-mix(in srgb, var(--bx-h2) 40%, transparent);
}

/* ── Edit-mode bar above the grid ──────────────────────────────────────── */
.bx-dimbar {
  display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap;
  margin: 0 0 18px; padding: 12px 16px;
  border-radius: 14px;
  background: linear-gradient(100deg, color-mix(in srgb, var(--brand) 10%, var(--surface)), var(--surface));
  border: 1px solid color-mix(in srgb, var(--brand) 30%, var(--line));
  box-shadow: var(--shadow-xs);
  animation: viewIn var(--dur-2) var(--ease-out) both;
}
.bx-dimbar-lead { display: flex; align-items: center; gap: 9px; font-size: 13.5px; color: var(--ink-2); flex-wrap: wrap; }
.bx-dimbar-lead > i { color: var(--brand); }
.bx-dimbar-hint { color: var(--muted); font-size: 12.5px; }
.bx-dimbar-acts { display: flex; gap: 8px; flex-wrap: wrap; }

.bx-editnote {
  display: flex; align-items: center; gap: 8px;
  margin: 0 0 16px; padding: 10px 14px; border-radius: 12px;
  font-size: 13px; color: var(--ink-2);
  background: var(--surface-2); border: 1px dashed var(--line-strong);
}
.bx-editnote i { color: var(--brand); }

/* ── Buttons ───────────────────────────────────────────────────────────── */
.bx-btn {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 15px; border: 1px solid var(--line-strong);
  background: var(--surface); color: var(--ink-2);
  font: inherit; font-size: 13px; font-weight: 650; cursor: pointer;
  box-shadow: var(--shadow-xs);
  transition: background var(--dur-1), color var(--dur-1), border-color var(--dur-1),
              transform var(--dur-1) var(--ease-out), box-shadow var(--dur-1);
}
.bx-btn:hover { transform: translateY(-1px); box-shadow: var(--shadow-sm); border-color: var(--muted); }
.bx-btn:active { transform: translateY(0) scale(.985); }
.bx-btn i { font-size: 12px; }

.bx-btn-primary {
  background: linear-gradient(135deg, var(--brand), var(--accent));
  border-color: transparent; color: #fff;
}
.bx-btn-primary:hover { filter: brightness(1.06); }

.bx-btn-glass {
  background: rgba(255,255,255,.18); border-color: rgba(255,255,255,.34); color: #fff;
  backdrop-filter: blur(6px);
}
.bx-btn-glass:hover { background: rgba(255,255,255,.3); border-color: rgba(255,255,255,.5); color: #fff; }

.bx-btn-danger { background: #dc2626; border-color: transparent; color: #fff; }
.bx-btn-danger:hover { background: #b91c1c; color: #fff; }
.bx-btn-glass.bx-btn-danger { background: rgba(220,38,38,.42); border-color: rgba(255,255,255,.3); }
.bx-btn-glass.bx-btn-danger:hover { background: rgba(220,38,38,.72); }
.bx-btn-danger-ghost { background: var(--surface); border-color: #fecaca; color: #b91c1c; }
.bx-btn-danger-ghost:hover { background: #fee2e2; border-color: #fca5a5; color: #991b1b; }

/* ── App card in edit mode: the pull-out control ────────────────────────── */
.bx-app-wrap { position: relative; }
.bx-pull {
  position: absolute; top: -7px; right: -7px; z-index: 3;
  width: 28px; height: 28px; display: grid; place-items: center;
  border: 2px solid var(--surface); cursor: pointer;
  background: #dc2626; color: #fff; font-size: 12px;
  box-shadow: var(--shadow-sm);
  transition: transform var(--dur-1) var(--ease-out), background var(--dur-1);
}
.bx-pull:hover { transform: scale(1.12) rotate(90deg); background: #b91c1c; }
.bx-sheet {
  position: relative; z-index: 1;
  width: min(560px, 100%); max-height: min(88vh, 860px);
  display: flex; flex-direction: column;
  background: var(--surface); border-radius: 20px;
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  animation: bxSheetIn var(--dur-3) var(--ease-out) both;
}
/* The app record is the widest form in the hub — nine fieldsets in two columns.
   At 900px both columns wrap their own field labels and the repo names run out of
   room; this gives each side enough to read as a single line. Capped so it never
   outgrows the text it holds. */
.bx-sheet-xwide { width: min(1240px, 100%); }

/* An editor is two jobs side by side: what this thing IS (left) and what is IN
   it (right). Stacked, the apps list landed below the fold — which is exactly
   the thing you opened the sheet to work on. */
.bx-sheet-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; align-items: start; }
.bx-col { display: flex; flex-direction: column; gap: 15px; min-width: 0; }
.bx-col-apps { position: sticky; top: 0; }
.bx-col-apps .bx-pick-list { max-height: min(46vh, 420px); }
@media (max-width: 720px) {
.bx-sheet-cols { grid-template-columns: 1fr; }
  .bx-col-apps { position: static; }
  .bx-col-apps .bx-pick-list { max-height: 220px; }
}
.bx-sheet-wrap.is-out .bx-sheet,
.bx-sheet-wrap.is-out .bx-sheet-veil { animation: bxFadeOut 180ms var(--ease-soft) both; }

@keyframes bxVeilIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes bxSheetIn {
  from { opacity: 0; transform: translateY(14px) scale(.975); }
  to   { opacity: 1; transform: none; }
}
@keyframes bxFadeOut { to { opacity: 0; transform: translateY(6px); } }

.bx-sheet-body { padding: 18px 20px; overflow-y: auto; display: flex; flex-direction: column; gap: 15px; }
.bx-spacer { flex: 1; }

/* ── Remove an app ────────────────────────────────────────────────────────────
   Two claims, equally legible: what removing really does, and the one thing a web
   page cannot do (uninstall software from the machine). That second half is the
   whole reason this is a sheet and not a confirm() — see openRemoveDialog() in
   js/browse.js. */
.bx-sheet-rm { max-width: 560px; }
.bx-rm { display: flex; flex-direction: column; gap: 14px; }
.bx-rm-app { display: flex; align-items: center; gap: 12px; }
.bx-rm-icon { width: 44px; height: 44px; border-radius: 12px; object-fit: cover; flex: none; }
.bx-rm-icon-fa {
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--surface-2); color: var(--muted); font-size: 18px;
}
.bx-rm-name { font-size: 16px; font-weight: 800; letter-spacing: -.2px; }
.bx-rm-host {
  font-size: 11.5px; font-weight: 600; color: var(--muted);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
.bx-rm-row {
  display: flex; gap: 11px;
  padding: 13px 14px; border-radius: 12px;
  background: var(--surface-2); border: 1px solid var(--line);
}
.bx-rm-row > i { font-size: 14px; margin-top: 2px; flex: none; }
.bx-rm-row strong { display: block; font-size: 13px; font-weight: 800; margin-bottom: 3px; color: var(--ink); }
.bx-rm-row p { margin: 0; font-size: 12.5px; line-height: 1.55; color: var(--ink-2); }
.bx-rm-row.is-yes { background: color-mix(in srgb, var(--brand) 7%, var(--surface)); border-color: color-mix(in srgb, var(--brand) 28%, var(--line)); }
.bx-rm-row.is-yes > i { color: var(--brand); }
.bx-rm-row.is-no { background: #fffbeb; border-color: #fde68a; }
.bx-rm-row.is-no > i { color: #b45309; }
/* The one sentence about the app window the store does not touch. A quiet note,
   deliberately not a second warning panel: the numbered "uninstall it in Windows"
   steps and the chrome://apps copy button were REMOVED 2026-08-05 — the store does
   not offer, or explain how to work around, what it cannot do. */
.bx-rm-note { margin: 0; font-size: 12px; line-height: 1.55; color: var(--muted); }

/* Live preview of the card being edited — the point is that you never save to
   find out what it looks like. */
.bx-preview {
  display: flex; align-items: center; gap: 14px;
  padding: 16px; border-radius: 14px;
  background: linear-gradient(120deg, var(--bx-mist), var(--surface));
  border: 1px solid color-mix(in srgb, var(--bx-h2) 35%, var(--line));
}
.bx-preview-bundle { color: #fff; border-color: transparent; }
.bx-preview-bundle .bx-preview-name { color: #fff; }
.bx-preview-bundle .bx-preview-blurb { color: rgba(255,255,255,.86); }
.bx-preview-name { font-size: 16px; font-weight: 750; color: var(--ink); }
.bx-preview-blurb { font-size: 12.5px; color: var(--muted); margin-top: 2px; }


/* ── The Work app's per-field AI button ──────────────────────────────────────
   Declarations COPIED VERBATIM from vo-app-work `apps/Work/wk-ai-fill.js` (the
   `.wk-aifill-field` block it injects at runtime), so the control is pixel-identical
   to the ✨ button on every Work create/edit popup. Same class names on purpose.
   If it changes in Work, change it here too — there is no shared stylesheet
   between the two apps. Rendered by js/ai-field.js. */
.wk-aifill-field{display:inline-flex;align-items:center;gap:3px;padding:3px 7px;border:none;border-radius:6px;background:transparent;color:#6d5efc;font:600 10.5px/1 inherit;letter-spacing:.2px;cursor:pointer;position:relative;transition:background .15s ease,color .15s ease,box-shadow .15s ease;}
.wk-aifill-field svg{width:11px;height:11px;flex:0 0 auto;}
.wk-aifill-field:hover{background:#f3f1ff;color:#5145e3;}
.wk-aifill-field:disabled{opacity:.5;cursor:default;}
.wk-aifill-field.is-busy{color:transparent;}
.wk-aifill-field.is-busy svg,.wk-aifill-field.is-busy span{visibility:hidden;}
.wk-aifill-field.is-busy::after{content:"";position:absolute;left:50%;top:50%;width:11px;height:11px;margin:-5.5px 0 0 -5.5px;border:2px solid rgba(109,94,252,.3);border-top-color:#6d5efc;border-radius:50%;animation:wkAIFillSpin .7s linear infinite;}
@keyframes wkAIFillSpin{to{transform:rotate(360deg);}}
/* The button is a <button>, so the platform's forced pill radius applies —
   6px needs the six-class fight (see the radius block at the bottom). */
.wk-aifill-field.wk-aifill-field.wk-aifill-field.wk-aifill-field.wk-aifill-field.wk-aifill-field{border-radius:6px !important;}

/* Label line that carries the button, right-aligned — Work's .wk-aifill-lblrow. */
.bx-lblrow { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.bx-lblrow > span:first-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.bx-lblacts { display: inline-flex; align-items: center; gap: 6px; flex: none; }

/* ⚠️ "New type" is NOT a button out here any more. Adding to a list is a thing
   you do inside that list, so it lives pinned at the top of the picker's own menu
   (.rq-pick-add in css/requests.css) and takes its name from the search box. The
   label-line variant this replaced is gone — .bx-lblacts still carries the ✦ AI
   chip, which is a different kind of thing: it writes the field's value. */

.bx-field { display: flex; flex-direction: column; gap: 6px; }
.bx-field-label { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
.bx-field-hint { font-size: 11.5px; color: var(--muted); }
.bx-input {
  width: 100%; padding: 10px 12px; border-radius: 10px;
  border: 1px solid var(--line-strong); background: var(--surface); color: var(--ink);
  font: inherit; font-size: 14px;
  transition: border-color var(--dur-1), box-shadow var(--dur-1);
}
/* --sec-ink is the section's own colour where a section sets one (the app editor),
   and falls back to brand green everywhere else. The ring is the most-seen colour
   in a form — one green ring on every field in every section is most of what
   "it's all just too green" was describing. */
.bx-input:focus {
  outline: none; border-color: var(--sec-ink, var(--brand));
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--sec-ink, var(--brand)) 22%, transparent);
}
.bx-textarea { resize: vertical; min-height: 54px; line-height: 1.45; }

.bx-swatches { display: flex; flex-wrap: wrap; gap: 8px; }
.bx-swatch {
  width: 34px; height: 34px; padding: 3px; cursor: pointer;
  border: 2px solid transparent; background: transparent;
  transition: transform var(--dur-1) var(--ease-out), border-color var(--dur-1);
}
.bx-swatch-chip {
  display: block; width: 100%; height: 100%; border-radius: 50%;
  background: linear-gradient(140deg, var(--bx-h1), var(--bx-h2));
  box-shadow: inset 0 0 0 1px rgba(0,0,0,.08);
}
.bx-swatch-grad .bx-swatch-chip { background: none; }
.bx-swatch:hover { transform: scale(1.12); }
.bx-swatch.is-on { border-color: var(--ink); transform: scale(1.08); }

.bx-iconpick {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(42px, 1fr));
  gap: 6px; max-height: 176px; overflow-y: auto;
  padding: 8px; border-radius: 12px; background: var(--surface-2); border: 1px solid var(--line);
}
.bx-iconopt {
  height: 40px; display: grid; place-items: center; cursor: pointer;
  border: 1px solid transparent; background: var(--surface); color: var(--ink-2); font-size: 15px;
  transition: background var(--dur-1), color var(--dur-1), border-color var(--dur-1), transform var(--dur-1);
}
.bx-iconopt:hover { transform: translateY(-1px); color: var(--brand); border-color: var(--line-strong); }
.bx-iconopt.is-on { background: linear-gradient(140deg, var(--brand), var(--accent)); color: #fff; border-color: transparent; }
/* Claimed by something else in this area: still shown (so the grid never
   reshuffles) but plainly out of play, and the title says who has it. */
.bx-iconopt.is-used {
  opacity: .3; cursor: not-allowed; background: var(--surface-2);
  color: var(--muted); position: relative;
}
.bx-iconopt.is-used:hover { transform: none; color: var(--muted); border-color: transparent; }
.bx-iconopt.is-used::after {
  content: ""; position: absolute; left: 6px; right: 6px; top: 50%;
  height: 1.5px; background: currentColor; transform: rotate(-32deg); opacity: .75;
}

/* The apps section sits inside a sheet that already scrolls, so it gets its own
   bounded height — otherwise a 12-app list pushes Save off the bottom. */
.bx-field-apps .bx-pick-list { max-height: 232px; }
.bx-field-apps .bx-field-label { display: flex; align-items: center; gap: 8px; }

.bx-note {
  display: flex; gap: 8px; align-items: flex-start;
  font-size: 12.5px; color: var(--ink-2); line-height: 1.5;
  padding: 10px 12px; border-radius: 10px; background: var(--surface-2); border: 1px solid var(--line);
}
.bx-note i { color: var(--brand); margin-top: 2px; }
.bx-confirm { margin: 0; font-size: 14px; line-height: 1.6; color: var(--ink-2); }

/* ── App picker ─────────────────────────────────────────────────────────── */
.bx-pick-search { position: relative; display: flex; align-items: center; gap: 10px; }
.bx-pick-search > i { position: absolute; left: 12px; color: var(--muted); font-size: 13px; pointer-events: none; }
.bx-pick-search .bx-input { padding-left: 34px; }
.bx-pick-count {
  flex: none; font-size: 12px; font-weight: 700; padding: 6px 11px; border-radius: 999px;
  background: color-mix(in srgb, var(--brand) 12%, var(--surface)); color: var(--brand);
}
.bx-pick-list {
  display: flex; flex-direction: column; gap: 6px;
  max-height: 46vh; overflow-y: auto; padding-right: 2px;
}
.bx-pick-row {
  display: flex; align-items: center; gap: 11px; width: 100%; text-align: left;
  padding: 9px 12px; cursor: pointer; font: inherit;
  background: var(--surface); border: 1px solid var(--line); color: var(--ink);
  transition: background var(--dur-1), border-color var(--dur-1), transform var(--dur-1);
}
.bx-pick-row:hover { transform: translateX(2px); border-color: var(--line-strong); background: var(--surface-2); }
.bx-pick-row.is-on { background: color-mix(in srgb, var(--brand) 8%, var(--surface)); border-color: color-mix(in srgb, var(--brand) 45%, var(--line)); }
.bx-pick-check {
  flex: none; width: 24px; height: 24px; border-radius: 50%; display: grid; place-items: center;
  font-size: 10.5px; background: var(--surface-2); color: var(--muted); border: 1px solid var(--line-strong);
}
.bx-pick-row.is-on .bx-pick-check { background: var(--brand); color: #fff; border-color: transparent; }
.bx-pick-body { display: flex; flex-direction: column; min-width: 0; }
.bx-pick-name { font-size: 13.5px; font-weight: 650; }
.bx-pick-sub { font-size: 11.8px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ── Bundle install, step by step (js/bundle-install.js) ─────────────────────
   Lives here because browse.css is the one stylesheet on every route, and
   "Install all" fires from Bundles and from the dashboard alike.

   Shape of the thing: a stepper across the top (one segment per app, so six
   apps read as six steps), then a STAGE that shows the one app you are on — its
   own icon, its own title, "Step 2 of 6" — then the action for that app, then a
   collapsed roster of the whole run. The stage re-keys on every change so its
   entrance animation replays: that replay is what makes it feel like moving on
   to the next app rather than a list quietly mutating.

   Sits under the toast layer (2600) so its success toasts stay readable. */
.bi-wrap { position: fixed; inset: 0; z-index: 2450; display: grid; place-items: center; padding: 24px; }
.bi-veil {
  position: absolute; inset: 0; background: rgba(15,23,42,.62); backdrop-filter: blur(4px);
  animation: bxVeilIn var(--dur-2) var(--ease-out) both;
}
.bi-panel {
  position: relative; z-index: 1;
  width: min(480px, 100%); max-height: min(90vh, 860px);
  display: flex; flex-direction: column;
  background: var(--surface); border-radius: 22px;
  box-shadow: 0 40px 80px -24px rgba(15,23,42,.45), 0 0 0 1px rgba(15,23,42,.06);
  overflow: hidden;
  animation: bxSheetIn var(--dur-3) var(--ease-out) both;
}

/* ── header ── */
.bi-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; padding: 20px 22px 14px; }
.bi-head-text { min-width: 0; }
.bi-eyebrow {
  display: flex; align-items: center; gap: 6px;
  font-size: 11px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
  color: var(--brand);
}
.bi-eyebrow i { font-size: 10px; }
.bi-title {
  margin: 4px 0 0; font-size: 19px; font-weight: 780; color: var(--ink); line-height: 1.2;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bi-x {
  width: 32px; height: 32px; flex: none; display: grid; place-items: center;
  border: 0; background: var(--surface-2); color: var(--muted); cursor: pointer; font-size: 14px;
  transition: background var(--dur-1), color var(--dur-1);
}
.bi-x:hover { background: #fee2e2; color: #b91c1c; }

/* ── stepper: one segment per app ── */
.bi-steps { display: flex; gap: 5px; padding: 0 22px 4px; }
.bi-step {
  flex: 1 1 0; min-width: 6px; height: 5px; border-radius: 999px;
  background: var(--line); transition: background var(--dur-2) var(--ease-out);
}
.bi-step[data-step="done"] { background: linear-gradient(90deg, var(--brand), var(--accent)); }
.bi-step[data-step="already"] { background: color-mix(in srgb, var(--success) 45%, var(--line)); }
.bi-step[data-step="skipped"] { background: var(--line-strong); }
.bi-step[data-step="current"] {
  background: var(--brand);
  animation: biStepPulse 1.6s var(--ease-soft) infinite;
}
@keyframes biStepPulse { 0%,100% { opacity: 1; } 50% { opacity: .42; } }

/* ── stage: the app you are on ── */
.bi-stage { padding: 22px 22px 4px; text-align: center; }
.bi-stage-inner { animation: biStageIn 320ms var(--ease-out) both; }
@keyframes biStageIn {
  from { opacity: 0; transform: translateY(10px) scale(.985); }
  to   { opacity: 1; transform: none; }
}

.bi-hero-icon { display: flex; justify-content: center; margin-bottom: 14px; }
/* Already installed: the app's own icon, dimmed, with a tick pinned to it — the
   same shape as every other step so the run reads as one sequence.
   The wrapper must HUG the icon (inline-flex) while .bi-hero-icon does the
   centring — making the wrapper itself the centred box put the step pill beside
   the icon instead of under it. */
.bi-icon-wrap { position: relative; display: inline-flex; }
.bi-icon-wrap.is-ticked .bi-icon-xl { opacity: .55; filter: saturate(.7); }
.bi-tick {
  position: absolute; right: -6px; bottom: -6px;
  width: 30px; height: 30px; border-radius: 50%;
  display: grid; place-items: center; font-size: 13px; color: #fff;
  background: linear-gradient(140deg, #16a34a, #4ade80);
  border: 3px solid var(--surface);
  box-shadow: 0 6px 14px -6px rgba(22,163,74,.7);
  animation: biPop 380ms var(--ease-out) both;
}
.bi-icon { flex: none; width: 30px; height: 30px; border-radius: 9px; object-fit: cover; }
.bi-icon-fa { display: grid; place-items: center; color: #fff; font-size: 13px; }
.bi-icon-xl {
  width: 76px !important; height: 76px !important; border-radius: 20px !important; font-size: 32px !important;
  box-shadow: 0 18px 34px -14px rgba(15,23,42,.42), 0 0 0 1px rgba(15,23,42,.05);
}

.bi-step-pill {
  display: inline-block; margin-bottom: 8px;
  font-size: 11px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: var(--brand); background: color-mix(in srgb, var(--brand) 11%, var(--surface));
  padding: 4px 11px; border-radius: 999px;
}
.bi-step-pill-done {
  color: var(--success);
  background: color-mix(in srgb, var(--success) 12%, var(--surface));
}
.bi-hero-name { margin: 0; font-size: 22px; font-weight: 800; color: var(--ink); line-height: 1.2; }
.bi-hero-sub {
  margin: 7px auto 0; max-width: 34ch; font-size: 13px; color: var(--ink-2); line-height: 1.5;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
/* The 2-line clamp above exists for app descriptions of unknown length. The
   closing summary is ours and it must not be cut off mid-word. */
.bi-hero-sub-full { -webkit-line-clamp: unset; display: block; max-width: 38ch; }
.bi-hero-hint { margin: 12px auto 0; max-width: 36ch; font-size: 12.5px; color: var(--muted); line-height: 1.5; }

.bi-hero-check {
  width: 76px; height: 76px; margin: 0 auto 14px; border-radius: 50%;
  display: grid; place-items: center; font-size: 34px; color: #fff;
  background: linear-gradient(140deg, #16a34a, #4ade80);
  box-shadow: 0 18px 34px -14px rgba(22,163,74,.6);
  animation: biPop 420ms var(--ease-out) both;
}
.bi-hero-check.is-partial { background: linear-gradient(140deg, #b45309, #fbbf24); box-shadow: 0 18px 34px -14px rgba(180,83,9,.55); }
@keyframes biPop { from { transform: scale(.7); opacity: 0; } to { transform: none; opacity: 1; } }

/* ── actions ── */
.bi-actions {
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding: 18px 22px 16px;
}
.bi-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 11px 20px; border: 1px solid var(--line-strong);
  background: var(--surface); color: var(--ink-2);
  font: inherit; font-size: 14px; font-weight: 680; cursor: pointer;
  box-shadow: var(--shadow-xs);
  transition: transform var(--dur-1) var(--ease-out), box-shadow var(--dur-1), filter var(--dur-1), background var(--dur-1);
}
.bi-btn:hover { transform: translateY(-1px); box-shadow: var(--shadow-sm); }
.bi-btn:active { transform: translateY(0) scale(.99); }
.bi-btn-wide { width: 100%; padding: 13px 20px; font-size: 15px; }
.bi-btn-primary {
  background: linear-gradient(135deg, var(--brand), var(--accent));
  border-color: transparent; color: #fff;
  box-shadow: 0 12px 24px -10px color-mix(in srgb, var(--brand) 70%, transparent);
}
.bi-btn-primary:hover { filter: brightness(1.06); }
.bi-btn-quiet {
  border-color: transparent; background: transparent; color: var(--muted);
  box-shadow: none; font-size: 13px; font-weight: 600; padding: 6px 12px;
}
.bi-btn-quiet:hover { background: var(--surface-2); color: var(--ink-2); transform: none; box-shadow: none; }

.bi-waiting { display: flex; align-items: center; gap: 9px; font-size: 13.5px; font-weight: 650; color: var(--ink-2); }
.bi-waiting-quiet { color: var(--muted); font-weight: 600; font-size: 13px; }
.bi-pulse {
  width: 9px; height: 9px; border-radius: 50%; background: var(--brand);
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--brand) 55%, transparent);
  animation: biRing 1.5s var(--ease-soft) infinite;
}
@keyframes biRing {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--brand) 55%, transparent); }
  70%  { box-shadow: 0 0 0 10px color-mix(in srgb, var(--brand) 0%, transparent); }
  100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--brand) 0%, transparent); }
}

/* ── roster: the whole run, collapsed by default ── */
.bi-more { border-top: 1px solid var(--line); background: var(--surface-2); }
.bi-more > summary {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 13px 22px; cursor: pointer; list-style: none;
  font-size: 12.5px; color: var(--muted);
}
.bi-more > summary::-webkit-details-marker { display: none; }
.bi-more > summary:hover { color: var(--ink-2); }
.bi-more > summary i { font-size: 10px; transition: transform var(--dur-1) var(--ease-out); }
.bi-more[open] > summary i { transform: rotate(180deg); }
.bi-count strong { color: var(--ink); font-weight: 750; }

.bi-list {
  list-style: none; margin: 0; padding: 0 16px 14px;
  max-height: 240px; overflow-y: auto;
  display: flex; flex-direction: column; gap: 5px;
}
.bi-row {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; border-radius: 11px;
  border: 1px solid transparent; background: var(--surface);
}
.bi-row.is-current { border-color: color-mix(in srgb, var(--brand) 45%, var(--line)); background: color-mix(in srgb, var(--brand) 7%, var(--surface)); }
.bi-row[data-state="done"] .bi-name { color: var(--muted); }
.bi-row[data-state="skipped"] { opacity: .55; }
.bi-dot {
  flex: none; width: 22px; height: 22px; border-radius: 50%;
  display: grid; place-items: center; font-size: 10px; font-weight: 700;
  background: var(--surface-2); color: var(--muted); border: 1px solid var(--line);
}
.bi-row[data-state="done"] .bi-dot { background: var(--success); color: #fff; border-color: transparent; }
.bi-row[data-state="already"] .bi-dot {
  background: color-mix(in srgb, var(--success) 16%, var(--surface));
  color: var(--success); border-color: color-mix(in srgb, var(--success) 40%, transparent);
}
.bi-row[data-state="already"] .bi-name { color: var(--muted); }
.bi-row.is-current .bi-dot { background: var(--brand); color: #fff; border-color: transparent; }
.bi-spin { animation: biSpin 1s linear infinite; }
@keyframes biSpin { to { transform: rotate(360deg); } }

.bi-body { display: flex; flex-direction: column; min-width: 0; }
.bi-name { font-size: 13px; font-weight: 650; color: var(--ink); }
.bi-state { font-size: 11.5px; color: var(--muted); }

@media (max-width: 520px) {
.bi-wrap { padding: 12px; }
  .bi-icon-xl { width: 62px !important; height: 62px !important; font-size: 26px !important; }
  .bi-hero-name { font-size: 19px; }
}

@media (prefers-reduced-motion: reduce) {
.bi-panel, .bi-veil, .bi-stage-inner, .bi-hero-check, .bi-tick { animation: none !important; }
  .bi-step { transition: none !important; }
  .bi-spin, .bi-pulse, .bi-step[data-step="current"] { animation: none !important; }
}


/* ── App page: the Information header carries the Edit button ─────────────── */
.detail-sec-head {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  flex-wrap: wrap; margin-bottom: 10px;
}
.detail-sec-head h2 { margin: 0; }

/* ── App editor extras ───────────────────────────────────────────────────── */
/* Two short fields on one line (Category/Status, Owner/Version) — a full-width
   box for a version number reads as more important than it is. */
.bx-grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
@media (max-width: 720px) {
.bx-grid2 { grid-template-columns: 1fr; }
}

.bx-check {
  display: flex; align-items: flex-start; gap: 10px; cursor: pointer;
  padding: 11px 13px; border-radius: 12px;
  background: var(--surface-2); border: 1px solid var(--line);
  transition: border-color var(--dur-1), background var(--dur-1);
}
.bx-check:hover { border-color: var(--line-strong); }
.bx-check input { margin: 2px 0 0; width: 16px; height: 16px; flex: none; accent-color: var(--brand); }
.bx-check > span { display: flex; flex-direction: column; font-size: 13.5px; color: var(--ink); }
.bx-check-sub { font-size: 12px; color: var(--muted); font-weight: 400; }


/* ── App editor: sections, logo, and the coded pickers ────────────────────────
   The pickers themselves are .rq-* from css/requests.css (the Requests page's
   controls, reused wholesale). Only the sheet-specific bits live here. */
.bx-fieldset { display: flex; flex-direction: column; gap: 14px; }
.bx-fieldset + .bx-fieldset { margin-top: 20px; padding-top: 18px; border-top: 1px solid var(--line); }
.bx-fieldset-h {
  display: flex; align-items: center; gap: 8px;
  font-size: 11px; font-weight: 800; letter-spacing: .09em; text-transform: uppercase;
  color: var(--sec-ink, var(--brand));
}
.bx-fieldset-ico {
  width: 22px; height: 22px; flex: none;
  display: grid; place-items: center; border-radius: 7px;
  font-size: 10px; letter-spacing: 0;
  color: var(--sec-ink, var(--brand));
  background: color-mix(in srgb, var(--sec-ink, var(--brand)) 12%, #fff);
  border: 1px solid color-mix(in srgb, var(--sec-ink, var(--brand)) 22%, transparent);
}

/* ── Section tones ────────────────────────────────────────────────────────────
   Every heading and every control in this form used to be the one hub green, so
   a two-column sheet of six sections read as one undifferentiated block. Each
   section now owns a hue and passes it to its own pickers (--rq-a / the chips,
   ticks and focus rings in css/requests.css read those), which is what makes the
   sections findable. Green stays where green means something: the Save button. */
.bx-fieldset[data-tone="slate"]  { --sec-ink: #475569; }
.bx-fieldset[data-tone="blue"]   { --sec-ink: #0369a1; }
.bx-fieldset[data-tone="violet"] { --sec-ink: #6d28d9; }
.bx-fieldset[data-tone="teal"]   { --sec-ink: #0f766e; }
.bx-fieldset[data-tone="amber"]  { --sec-ink: #b45309; }
.bx-fieldset[data-tone="pink"]   { --sec-ink: #9d174d; }
.bx-fieldset[data-tone] { --rq-a: var(--sec-ink); --rq-accent-ink: var(--sec-ink); }

/* ── The app's own colour, at the top of its form ─────────────────────────────
   --app-a / --app-b are the app's accent pair out of the registry, set inline by
   openAppEditor. The head is a wash of them and the sheet gets a rule of them, so
   the first thing you see says WHICH app this is — twelve apps had twelve
   identical green forms. Text stays on --ink: this is a tint, not a banner. */
.bx-sheet-app { position: relative; overflow: hidden; }
.bx-sheet-app::before {
  content: ''; position: absolute; top: 0; left: 0; right: 0; height: 4px;
  background: linear-gradient(90deg, var(--app-a, var(--brand)), var(--app-b, var(--accent)));
}
.bx-sheet-app .bx-sheet-head {
  background: linear-gradient(180deg, color-mix(in srgb, var(--app-a, var(--brand)) 9%, #fff), var(--surface));
  border-bottom-color: color-mix(in srgb, var(--app-a, var(--brand)) 18%, var(--line));
}

/* The app head: logo, name, tagline, and what we can honestly say about installs. */
.bx-apphead {
  display: flex; align-items: flex-start; gap: 14px;
  padding: 15px 17px; border-radius: var(--radius-sm, 14px);
  background:
    linear-gradient(135deg,
      color-mix(in srgb, var(--app-a, var(--brand)) 22%, #fff),
      color-mix(in srgb, var(--app-b, var(--accent)) 13%, #fff));
  border: 1px solid color-mix(in srgb, var(--app-a, var(--brand)) 28%, transparent);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.6);
}
/* The logo sits in the app's own colour, not on the sheet's grey. */
.bx-apphead .bx-logo-img, .bx-apphead .app-icon {
  box-shadow: 0 0 0 3px rgba(255,255,255,.75), 0 6px 14px -8px color-mix(in srgb, var(--app-a, var(--brand)) 70%, transparent);
}
/* Pills on a tint need a solid ground or they read as smudges. */
.bx-apphead .bx-stat-pill {
  background: rgba(255,255,255,.82);
  border-color: color-mix(in srgb, var(--app-a, var(--brand)) 22%, var(--line));
}
.bx-apphead-id { min-width: 0; }
.bx-apphead-top { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.bx-logo-wrap { flex: none; width: 62px; height: 62px; }
.bx-logo-img {
  width: 62px; height: 62px; border-radius: 15px; object-fit: contain;
  background: #fff; border: 1px solid var(--line); box-shadow: var(--shadow-xs);
}
.bx-logo-empty {
  width: 62px; height: 62px; border-radius: 15px; display: grid; place-items: center;
  background: var(--surface-2); border: 1px dashed var(--line-strong); color: var(--muted); font-size: 20px;
}
.bx-apphead-name { font-size: 17px; font-weight: 780; color: var(--ink); }
.bx-apphead-sub { font-size: 13px; color: var(--muted); margin-top: 2px; }
.bx-apphead-stats { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 9px; }
.bx-stat-pill {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 11.5px; font-weight: 600; padding: 4px 10px; border-radius: 999px;
  background: var(--surface-2); color: var(--ink-2); border: 1px solid var(--line);
}
.bx-stat-pill i { font-size: 10px; opacity: .75; }
.bx-stat-muted { color: var(--muted); font-weight: 500; }

/* The picker popover is position:absolute (css/requests.css), which a scrolling
   sheet body would clip. Rather than un-scroll the sheet — this form is taller
   than the screen — browse.js re-anchors an open popover to the VIEWPORT
   (position:fixed) and flips it above the trigger when there is no room below.
   See unclipPickers(). */
.rq-pick-pop.is-unclipped { position: fixed; z-index: 2600; }
/* ⚠️ And it FADES, it does not slide. requests.css opens these on `rqPopIn`,
   which animates `transform` — fine for a menu the CSS itself positions, wrong
   for one whose coordinates JS computed: the transform lands it a few px off
   from where it was placed, and it makes every rect read during the animation
   (including the one that measures the containing block) wrong by the same
   amount. Measured: 4px left, 3px high, 9px narrow on every field in this form.
   Opacity alone has nothing to read through. */
.rq-pick-pop.is-unclipped { animation-name: rqPopFade; }
@keyframes rqPopFade { from { opacity: 0; } to { opacity: 1; } }

/* ── Toasts ─────────────────────────────────────────────────────────────── */
.bx-toast-host {
  position: fixed; z-index: 2600; bottom: 22px; left: 50%; transform: translateX(-50%);
  display: flex; flex-direction: column; gap: 8px; align-items: center; pointer-events: none;
}
.bx-toast {
  display: flex; align-items: center; gap: 9px;
  padding: 11px 18px; border-radius: 999px;
  font-size: 13.5px; font-weight: 600; color: #fff;
  background: #0f172a; box-shadow: var(--shadow-lg);
  animation: bxToastIn var(--dur-2) var(--ease-out) both;
  max-width: min(560px, 92vw);
}
.bx-toast-warn { background: #b45309; }
.bx-toast.is-out { animation: bxToastOut 280ms var(--ease-soft) both; }
@keyframes bxToastIn  { from { opacity: 0; transform: translateY(14px) scale(.96); } to { opacity: 1; transform: none; } }
@keyframes bxToastOut { to { opacity: 0; transform: translateY(10px) scale(.97); } }

/* Sidebar: a dimension an admin has hidden still shows for them, marked. */
.ph-sb-item.is-dim-hidden { opacity: .55; }
.ph-sb-item.is-dim-hidden::after {
  content: "hidden"; margin-left: auto;
  font-size: 9.5px; text-transform: uppercase; letter-spacing: .05em;
  background: var(--surface-2); color: var(--muted); padding: 2px 6px; border-radius: 999px;
}

/* ── Radius fights ──────────────────────────────────────────────────────────
   dashboard-meta.js injects, at runtime and AFTER this file:
     button:not(.ax-card):not(.tcd-view-btn):not(.tcd-filter-btn):not(.tcd-ai-btn):not(.tmbp-add-btn)
       { border-radius: var(--wt-theme-btn-radius) !important }
   That is specificity (0,5,1) with !important, and this store pins the var to
   999px — so every <button> here arrives as a pill. Pills are correct for
   .bx-btn / .bx-icon-btn / .bx-swatch / .bx-sheet-x / .bx-pull, so those are
   left alone. These three are card- and row-shaped and must not be pills.
   Beating it needs SIX classes (b=6 > b=5); repeating the class is the only way
   to get there without depending on an ancestor chain that might change. */
.bx-card-new.bx-card-new.bx-card-new.bx-card-new.bx-card-new.bx-card-new { border-radius: 18px !important; }
.bundle-card-new.bundle-card-new.bundle-card-new.bundle-card-new.bundle-card-new.bundle-card-new { border-radius: 18px !important; }
.bx-iconopt.bx-iconopt.bx-iconopt.bx-iconopt.bx-iconopt.bx-iconopt       { border-radius: 10px !important; }
.bx-pick-row.bx-pick-row.bx-pick-row.bx-pick-row.bx-pick-row.bx-pick-row { border-radius: 12px !important; }

/* ── Narrow screens ────────────────────────────────────────────────────── */
@media (max-width: 900px) {
.bx-hero { padding: 22px; border-radius: 16px; }
  .bx-hero-title { font-size: 24px; }
  .bx-hero-stats { width: 100%; }
  .bx-stat { flex: 1; }
  .bx-grid { grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 12px; }
  .bx-dimbar { flex-direction: column; align-items: stretch; }
}
@media (max-width: 560px) {
.bx-grid { grid-template-columns: 1fr 1fr; }
  .bx-card-main { padding: 16px 14px 12px; }
  .bx-card-blurb { display: none; }
  .bx-hero-medallion-lg { width: 62px; height: 62px; font-size: 26px; border-radius: 18px; }
}

@media (prefers-reduced-motion: reduce) {
.bx-hero, .bx-backbar, .bx-dimbar, .bx-card, .bx-sheet, .bx-sheet-veil, .bx-toast { animation: none !important; }
  .bx-card, .bx-btn, .bx-back, .bx-medallion, .bx-pull, .bx-pick-row { transition: none !important; }
}

/* ══════════════════════════════════════════════════════════════════════════
   THE INSTALL PAGE POPUP  (openInstallPage in js/browse.js)
   ══════════════════════════════════════════════════════════════════════════
   Two panels: what you change on the left, the page itself on the right. The
   right one is a real render of the real install screen, so the layout has to
   give it enough room to READ as the page — a postage stamp would be a
   decoration, not a preview. */

.bx-btn-soft {
  background: color-mix(in srgb, var(--brand) 10%, var(--surface));
  border-color: color-mix(in srgb, var(--brand) 32%, var(--line));
  color: var(--brand);
}
.bx-btn-soft:hover { background: color-mix(in srgb, var(--brand) 16%, var(--surface)); color: var(--brand); }
.bx-btn-sm { padding: 7px 11px; font-size: 12.5px; }
.bx-note-quiet { background: transparent; border-style: dashed; }

/* ── the call to action, on the app form ─────────────────────────────────── */
.bx-instcta { display: flex; align-items: center; gap: 13px; }
.bx-instcta-shots { display: flex; gap: 4px; flex: none; }
.bx-instcta-shots img {
  width: 52px; height: 33px; object-fit: cover; object-position: top center;
  border-radius: 5px; border: 1px solid var(--line); background: var(--surface-2);
}
.bx-instcta-none {
  width: 52px; height: 33px; display: grid; place-items: center; border-radius: 5px;
  border: 1px dashed var(--line-strong); color: var(--muted); font-size: 13px;
}
.bx-instcta-txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.bx-instcta-txt b { font-size: 13px; }
.bx-instcta-txt span { font-size: 12px; color: var(--muted); line-height: 1.5; }
.bx-instcta .bx-btn { flex: none; }
@media (max-width: 620px) {
.bx-instcta { flex-wrap: wrap; }
}

/* An app with no install page yet is the one thing on the registry row worth
   nudging about — everything else there is already done. */
.reg-edit.is-todo { color: #b45309; border-color: color-mix(in srgb, #f59e0b 45%, var(--line)); }

/* ── the popup ───────────────────────────────────────────────────────────── */
.bx-inst-cols { display: grid; grid-template-columns: minmax(0, 380px) minmax(0, 1fr); gap: 20px; align-items: start; }
.bx-inst-form { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.bx-inst-prev { position: sticky; top: 0; min-width: 0; }
@media (max-width: 900px) {
.bx-inst-cols { grid-template-columns: 1fr; }
  .bx-inst-prev { position: static; }
}

/* the ordered strip — the first one is the hero, and it says so */
.bx-shots { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
.bx-shot {
  position: relative; width: 104px; border-radius: 8px; overflow: hidden;
  border: 1px solid var(--line); background: var(--surface-2); line-height: 0;
}
.bx-shot.is-hero { border-color: color-mix(in srgb, var(--brand) 55%, var(--line)); box-shadow: 0 0 0 2px color-mix(in srgb, var(--brand) 18%, transparent); }
.bx-shot img { width: 100%; height: 66px; object-fit: cover; object-position: top center; display: block; }
.bx-shot-n {
  position: absolute; left: 5px; top: 5px; font-size: 9.5px; font-weight: 800; letter-spacing: .05em;
  text-transform: uppercase; padding: 2px 6px; border-radius: 4px; line-height: 1.4;
  background: rgba(15,23,42,.72); color: #fff;
}
.bx-shot-acts { position: absolute; inset: auto 0 0 0; display: flex; gap: 2px; justify-content: center; padding: 4px; background: linear-gradient(transparent, rgba(15,23,42,.75)); }
.bx-shot-acts button {
  width: 22px; height: 22px; border: 0; border-radius: 5px; cursor: pointer; line-height: 1;
  background: rgba(255,255,255,.9); color: #0f172a; font-size: 10px;
}
.bx-shot-acts button:hover { background: #fff; }
.bx-shots-empty {
  display: flex; align-items: center; gap: 9px; font-size: 12.5px; color: var(--muted);
  padding: 12px; border: 1px dashed var(--line-strong); border-radius: 9px;
}

/* colour */
.bx-accrow { display: flex; align-items: flex-end; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
.bx-accpick { display: flex; flex-direction: column; gap: 4px; font-size: 11.5px; color: var(--muted); font-weight: 600; }
.bx-accpick input[type=color] {
  width: 58px; height: 34px; padding: 2px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--surface); cursor: pointer;
}
.bx-accs { display: flex; gap: 7px; flex-wrap: wrap; }
.bx-acc { width: 34px; height: 24px; border-radius: 6px; border: 1px solid var(--line); cursor: pointer; padding: 0; }
.bx-acc:hover { transform: translateY(-1px); box-shadow: var(--shadow-sm); }

/* where it stands */
.bx-instwhere {
  display: flex; gap: 9px; align-items: flex-start; font-size: 12.5px; line-height: 1.55;
  padding: 11px 13px; border-radius: 10px; background: var(--surface-2); border: 1px solid var(--line); color: var(--ink-2);
}
.bx-instwhere i { margin-top: 2px; }
.bx-instwhere.is-ok { background: color-mix(in srgb, #16a34a 8%, var(--surface)); border-color: color-mix(in srgb, #16a34a 32%, var(--line)); }
.bx-instwhere.is-ok i { color: #16a34a; }
.bx-instwhere.is-warn { background: color-mix(in srgb, #f59e0b 10%, var(--surface)); border-color: color-mix(in srgb, #f59e0b 38%, var(--line)); }
.bx-instwhere.is-warn i { color: #b45309; }
.bx-instwhere code { font-size: 11.5px; background: var(--surface-2); padding: 1px 5px; border-radius: 4px; }

/* the preview: the real screen at 1440x900, scaled to whatever room there is */
.bx-prev-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 8px; font-size: 12px; font-weight: 700; color: var(--muted); }
.bx-prev-head i { margin-right: 5px; }
.bx-prev-open { font-size: 12px; font-weight: 700; color: var(--brand); text-decoration: none; }
.bx-prev-open:hover { text-decoration: underline; }
.bx-prev-stage {
  position: relative; width: 100%; aspect-ratio: 1440 / 900; overflow: hidden;
  border-radius: 12px; border: 1px solid var(--line); background: var(--surface-2);
  box-shadow: var(--shadow-sm);
}
/* Rendered at real size and scaled down, so the type inside is laid out exactly
   as it will be — shrinking the viewport instead would trip the screen's own
   responsive breakpoints and preview a layout nobody is going to see. */
.bx-prev-frame {
  position: absolute; top: 0; left: 0; width: 1440px; height: 900px; border: 0;
  transform-origin: top left; transform: scale(var(--prev-k, .38));
}
.bx-prev-none { padding: 24px; font-size: 13px; color: var(--muted); text-align: center; }
