/* westwing frontend — Flawless design system skin.
 *
 * Dark-canvas by default. Tokens are a working subset of
 * references/flawless-design-system/colors_and_type.css: only what the
 * frontend actually consumes is mirrored here (no holographic gradient,
 * no display-scale font sizes, no italic font-faces — those exist for
 * decks/social and would just bloat this file). Class names match the
 * pre-rebrand stylesheet so the 67 vitest cases keep selecting the same
 * DOM. The visual language changes; the contract doesn't.
 */
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&family=Fraunces:opsz,wght@9..144,400;9..144,600;9..144,700&display=swap');

:root {
  /* Primary palette */
  --flawless-red:      #D8332F;
  --flawless-night:    #111111;
  --flawless-silver:   #FAFAFA;
  --flawless-white:    #FFFFFF;

  /* Secondary palette */
  --flawless-daylight: #07B2CF;
  --flawless-teal:     #20B0AA;
  --flawless-orange:   #FEAC34;
  --flawless-amber:    #FEBD5D;
  --flawless-smoke:    #474747;

  /* Tints — only the few we use on hover lifts */
  --flawless-red-tint:      #E05C59;
  --flawless-teal-tint:     #4CBFBB;
  --flawless-daylight-tint: #3EC1D8;

  /* Grey scale — keep the steps the dark UI actually consumes */
  --grey-900: #0C0D0F;
  --grey-850: #111111;
  --grey-800: #1A1919;
  --grey-700: #242424;
  --grey-600: #3C3C3C;
  --grey-500: #474747;
  --grey-400: #636363;
  --grey-300: #888888;

  /* Semantic surface / foreground / border tokens */
  --bg-canvas:     var(--grey-850);
  --bg-surface:    var(--grey-800);
  --bg-elevated:   var(--grey-700);
  --bg-overlay:    rgba(0,0,0,0.55);

  --fg-primary:    var(--flawless-silver);
  --fg-secondary:  rgba(250,250,250,0.70);
  --fg-tertiary:   rgba(250,250,250,0.50);
  --fg-disabled:   rgba(250,250,250,0.30);
  --fg-accent:     var(--flawless-red);
  --fg-editorial:  var(--flawless-teal);

  --border-subtle: rgba(255,255,255,0.10);
  --border-muted:  rgba(255,255,255,0.18);
  --border-strong: rgba(255,255,255,0.30);

  /* Spacing — 4pt scale (only the steps in active use) */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;

  /* Radii — square-first; nothing above --radius-md except status pills */
  --radius-xs:   2px;
  --radius-sm:   4px;
  --radius-md:   8px;
  --radius-pill: 999px;

  /* Font stacks */
  --font-sans:    'Poppins', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  --font-display: 'Fraunces', Georgia, serif;
  --font-mono:    ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;

  /* Type scale — body + kicker (the UI doesn't need display-size tokens) */
  --fs-kicker-sm: 20px;
  --fs-body-sm:   13px;
  --fs-body:      15px;
  --fs-body-lg:   17px;

  --fw-regular:  400;
  --fw-medium:   500;
  --fw-semibold: 600;
  --fw-bold:     700;

  --track-kicker: 0.20em;

  /* Shadows — used only on the modal sheet */
  --shadow-md: 0 4px 12px rgba(0,0,0,0.35);
  --shadow-lg: 0 12px 32px rgba(0,0,0,0.55);

  /* Motion */
  --ease-out:  cubic-bezier(0.22, 0.61, 0.36, 1);
  --dur-fast:  120ms;
  --dur-base:  220ms;

  /* Legacy aliases — kept so any straggler reference to --danger / --bg /
     --fg / etc. still resolves to a Flawless-palette colour. Removing the
     underlying names entirely would risk breaking inline styles in
     toast.js / modal.js without changing those files. */
  --bg:        var(--bg-canvas);
  --fg:        var(--fg-primary);
  --muted:     var(--fg-secondary);
  --card:      var(--bg-surface);
  --border:    var(--border-subtle);
  --accent:    var(--flawless-red);
  --accent-fg: var(--flawless-white);
  --danger:    var(--flawless-red);
  --online:    var(--flawless-teal);
  --online-bg: rgba(32,176,170,0.16);
  --offline:   var(--grey-300);
  --offline-bg: rgba(255,255,255,0.06);
  --code-bg:   var(--bg-elevated);
  --code-fg:   var(--fg-primary);
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--bg-canvas);
  color: var(--fg-primary);
  font-family: var(--font-sans);
  font-weight: var(--fw-regular);
  font-size: var(--fs-body);
  line-height: 1.5;
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* ---------- Top bar ------------------------------------------------------- */

.topbar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 28px;
  background: var(--bg-canvas);
  border-bottom: 1px solid var(--border-subtle);
}
/* Brand block: red F mark + "Westwing" wordmark, clickable back to /.
 * The wordmark drops the kicker treatment (lowercase + tracked teal)
 * we reserve for section labels, since the brand is a proper noun and
 * lowercase would read as a slug, not a name. Mark is a fixed
 * 28x28 PNG flush against the wordmark with a small gap. */
.topbar .brand {
  display: flex; align-items: center; gap: 10px;
  text-decoration: none;
  color: inherit;
}
.topbar .brand-mark {
  display: block;
  width: 28px; height: 28px;
  /* Inline width/height attrs match these for layout stability before
   * the PNG decodes; CSS values win for retina sharpness. */
}
.topbar h1 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: 22px;
  letter-spacing: 0;
  color: var(--fg-primary);
  line-height: 1;
}
.topbar .brand:hover h1 { color: var(--fg-editorial); }
.topbar .brand:focus-visible {
  outline: 1px solid var(--flawless-teal);
  outline-offset: 4px;
  border-radius: var(--radius-xs);
}
.user-area { display: flex; align-items: center; gap: 12px; position: relative; }
.user-name {
  color: var(--fg-secondary);
  font-weight: var(--fw-medium);
}

/* Profile menu: avatar button + click-to-open dropdown. The dropdown
 * is absolutely positioned off .user-area (which has position:relative
 * above) so it floats below the avatar without disturbing the topbar
 * row's layout. */
.profile-menu { position: relative; display: inline-block; }
/* The `hidden` HTML attribute should win over our explicit display
 * declarations (display: flex on .profile-dropdown was making
 * dropdown.hidden = true a no-op, so the menu wouldn't collapse). */
.profile-menu[hidden],
.profile-dropdown[hidden] { display: none !important; }
.profile-trigger {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 50%;
  cursor: pointer;
  transition: border-color 0.12s, transform 0.12s;
}
.profile-trigger:hover,
.profile-trigger[aria-expanded="true"] {
  border-color: var(--flawless-teal);
}
.profile-trigger:focus-visible {
  outline: 1px solid var(--flawless-teal);
  outline-offset: 2px;
}
.profile-avatar {
  display: block;
  width: 32px; height: 32px;
  border-radius: 50%;
  background: var(--bg-elevated);
}
.profile-dropdown {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  min-width: 220px;
  background: var(--bg-surface);
  border: 1px solid var(--border-muted);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  padding: 6px;
  z-index: 100;
  display: flex; flex-direction: column;
}
.profile-dropdown-head {
  padding: 8px 10px 10px;
  border-bottom: 1px solid var(--border-subtle);
  margin-bottom: 4px;
}
.profile-dd-name {
  font-weight: var(--fw-semibold);
  color: var(--fg-primary);
  font-size: 14px;
}
.profile-dd-email {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--fg-tertiary);
  word-break: break-all;
}
.profile-dd-item {
  display: block;
  padding: 8px 10px;
  border: none;
  background: transparent;
  color: var(--fg-primary);
  text-align: left;
  text-decoration: none;
  border-radius: var(--radius-xs);
  cursor: pointer;
  font-size: 13px;
  font-family: var(--font-sans);
}
.profile-dd-item:hover,
.profile-dd-item:focus-visible {
  background: var(--bg-elevated);
  outline: none;
}
.profile-dd-danger { color: var(--flawless-red-tint); }
.profile-dd-danger:hover { background: rgba(216, 51, 47, 0.12); color: var(--flawless-red-tint); }

/* Profile page — rendered into #profile-panel by renderProfileRoute. */
.profile-card {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 12px 24px;
  background: var(--bg-canvas);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  padding: 20px;
  margin: 16px 0;
}
.profile-card-row { display: contents; }
.profile-card-label {
  color: var(--fg-tertiary);
  text-transform: uppercase;
  font-size: 11px;
  letter-spacing: 0.06em;
  align-self: center;
}
.profile-card-value {
  color: var(--fg-primary);
  word-break: break-all;
}
.profile-card-value.mono {
  font-family: var(--font-mono);
  font-size: 12px;
}
.profile-note {
  margin-top: 16px;
  font-size: 13px;
}

/* Profile preferences card — same chrome as `.profile-card`, lighter
 * grid so a row can hold (checkbox, label-block) without aligning to
 * a uniform max-content column the way the profile-card rows do. */
.profile-prefs {
  background: var(--bg-canvas);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  padding: 20px;
  margin: 16px 0;
}
.profile-prefs-row {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 4px 0;
}
.profile-prefs-row input[type="checkbox"] {
  margin-top: 3px;
  cursor: pointer;
}
.profile-prefs-row label {
  cursor: pointer;
  line-height: 1.45;
}
.profile-prefs-row .profile-prefs-hint {
  display: block;
  color: var(--fg-tertiary);
  font-size: 12px;
  margin-top: 2px;
}

/* "Show Cursor UI" preference. When the toggle is off (default), every
 * element marked with `data-cursor-feature` is hidden — the cursor
 * action buttons on Projects + Workspaces rows, the Cursor setup card,
 * and the Cursor cloud agents panel. Running cursor agent rows are
 * NOT marked, so they remain visible regardless of the toggle. */
html[data-show-cursor="0"] [data-cursor-feature] {
  display: none !important;
}

/* Top navigation — sits between the brand and the user-area. Each link
 * is a subdued chip that lights to teal when the user is on its route.
 * The active-state class is set by app.js on every hashchange. */
.top-nav {
  display: flex; align-items: center; gap: 4px;
  margin-left: 32px;
  flex: 1;
}
.top-nav-link {
  display: inline-block;
  padding: 6px 12px;
  color: var(--fg-secondary);
  font-weight: var(--fw-medium);
  text-align: center;
  text-decoration: none;
  border-radius: var(--radius-xs);
  transition: color 0.15s, background 0.15s;
}
.top-nav-link:hover {
  color: var(--fg-primary);
  background: var(--bg-elevated);
}
.top-nav-link.is-active {
  color: var(--flawless-teal);
  background: var(--bg-elevated);
}
.top-nav-link:focus-visible {
  outline: 1px solid var(--flawless-teal);
  outline-offset: 2px;
}

/* Server switcher — this IS the Servers top-nav item. The button
 * inherits .top-nav-link sizing / colour so it sits flush with the
 * surrounding nav links, then adds gap + caret to hint at the
 * dropdown affordance. */
.server-switcher { position: relative; display: inline-block; }
.server-switcher[hidden] { display: none !important; }
.server-switcher-trigger {
  display: inline-flex; align-items: center; gap: 6px;
  /* font + colour + padding come from .top-nav-link (applied as a
   * second class on the trigger). We add nothing here for the
   * neutral state so the button reads identically to the sibling
   * Spend / per-server nav links. */
  background: transparent;
  border: 1px solid transparent;
  cursor: pointer;
  font: inherit;
}
.server-switcher-trigger[aria-expanded="true"] {
  color: var(--flawless-teal);
  background: var(--bg-elevated);
}
.server-switcher-caret { font-size: 10px; color: var(--fg-tertiary); }
.server-switcher-menu {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  min-width: 200px;
  background: var(--bg-surface);
  border: 1px solid var(--border-muted);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  padding: 6px;
  z-index: 100;
  display: flex; flex-direction: column;
  max-height: 60vh;
  overflow-y: auto;
}
.server-switcher-menu[hidden] { display: none !important; }
.server-switcher-item {
  display: block;
  padding: 8px 10px;
  color: var(--fg-primary);
  text-decoration: none;
  border-radius: var(--radius-xs);
  font-size: 13px;
}
.server-switcher-item:hover,
.server-switcher-item:focus-visible {
  background: var(--bg-elevated);
  outline: none;
}
.server-switcher-item.is-active {
  color: var(--flawless-teal);
  background: var(--bg-elevated);
}
.server-switcher-empty {
  padding: 10px;
  font-size: 12px;
  color: var(--fg-tertiary);
}
.server-switcher-divider {
  height: 1px;
  background: var(--border-subtle);
  margin: 4px 0;
}

/* Per-server nav group — visible only when a server is active. */
.top-nav-server-group {
  display: inline-flex; align-items: center; gap: 4px;
}
.top-nav-server-group[hidden] { display: none !important; }

/* ---------- Mobile topbar (hamburger menu) ----------------------------------
 * The .topbar-nav-wrapper is a <details> element that wraps the existing
 * <nav class="top-nav"> for free disclosure semantics on small viewports.
 * - Desktop (> 700px): the wrapper is a passthrough — summary hidden,
 *   nav renders inline as before, .top-nav keeps `flex: 1` behaviour.
 * - Mobile (<= 700px): summary becomes a `≡` button; nav hides until
 *   the user taps it; opens as a full-width vertical popover anchored
 *   under the topbar. Topbar itself shrinks: the "Westwing" wordmark
 *   collapses to the F mark only, freeing horizontal room. */
.topbar-nav-wrapper {
  /* Default: act as if we weren't wrapping anything. Inherits .top-nav's
   * flex: 1 by being a direct child of .topbar. */
  flex: 1;
  margin-left: 32px;
}
.topbar-nav-wrapper > summary {
  list-style: none;
  cursor: pointer;
  -webkit-user-select: none;
  user-select: none;
}
.topbar-nav-wrapper > summary::-webkit-details-marker { display: none; }
.topbar-nav-wrapper > summary::marker { display: none; }
.topbar-nav-wrapper > .top-nav {
  /* When the wrapper takes over flex: 1, the nav inside doesn't need
   * its own flex/margin-left — clear them out so they don't double up
   * on desktop. */
  margin-left: 0;
  flex: 0 0 auto;
}

@media (min-width: 701px) {
  /* Desktop: hide hamburger, show nav inline. */
  .topbar-nav-wrapper > summary { display: none; }
  .topbar-nav-wrapper { display: flex; align-items: center; }
  .topbar-nav-wrapper > .top-nav { display: flex; }
}

@media (max-width: 700px) {
  /* Mobile: drop the wordmark to free room. The F mark + the new
   * hamburger keep the topbar usable at 390px wide. */
  .topbar { padding: 10px 14px; }
  .topbar h1 { display: none; }
  .topbar-nav-wrapper {
    /* Don't grow; the hamburger is a fixed-size button. The user-area
     * takes the right edge. */
    flex: 0 0 auto;
    margin-left: 0;
    margin-right: 8px;
    position: static;
  }
  .topbar-nav-wrapper > summary {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    background: var(--bg-elevated);
    color: var(--fg-primary);
    font-size: 24px;
    line-height: 1;
    font-weight: var(--fw-semibold);
  }
  .topbar-nav-wrapper:not([open]) > .top-nav { display: none; }
  .topbar-nav-wrapper[open] > .top-nav {
    /* Full-width popover under the topbar. position: absolute relative
     * to the topbar (which we make position: relative below for this
     * to anchor correctly). */
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    margin: 0;
    background: var(--bg-surface);
    border-bottom: 1px solid var(--border-muted);
    box-shadow: var(--shadow-md);
    padding: 8px 14px;
    z-index: 100;
  }
  /* Anchor the popover to the topbar. */
  .topbar { position: relative; }
  /* Stack the server-switcher / server-group / Spend vertically in the
   * popover. The server-switcher's dropdown menu still works — it
   * opens INSIDE the popover (also full-width because of the column
   * layout). */
  .topbar-nav-wrapper[open] .top-nav-server-group {
    display: flex; flex-direction: column; align-items: stretch; gap: 2px;
  }
  .topbar-nav-wrapper[open] .top-nav-link {
    padding: 10px 12px;
    border-radius: var(--radius-xs);
  }
  .topbar-nav-wrapper[open] .server-switcher,
  .topbar-nav-wrapper[open] .server-switcher-trigger {
    width: 100%;
    justify-content: space-between;
  }
  .topbar-nav-wrapper[open] .server-switcher-menu {
    position: static;
    box-shadow: none;
    border: 1px solid var(--border-subtle);
    margin-top: 4px;
  }
}

/* ---------- Main app shell ------------------------------------------------ */

.app { max-width: 960px; margin: 32px auto; padding: 0 20px; }

.panel {
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  padding: 20px 22px;
}
.panel + .panel { margin-top: 16px; }
.panel-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 16px; gap: 12px; flex-wrap: wrap;
}
/* Panel and detail headings render as Flawless kickers — lowercase teal,
 * 20px, tracked 0.20em. The h2/h3 elements stay; only the look changes. */
.panel-head h2,
.panel-head h3 {
  margin: 0;
  font-family: var(--font-sans);
  font-weight: var(--fw-regular);
  font-size: var(--fs-kicker-sm);
  letter-spacing: var(--track-kicker);
  text-transform: lowercase;
  color: var(--fg-editorial);
}
.panel-head h3.panel-heading { display: inline-flex; align-items: baseline; gap: 6px; }
.panel-head h3.panel-heading:hover { color: var(--fg-primary); }
.panel-caret {
  color: var(--fg-secondary);
  display: inline-block;
  width: 1em;
  letter-spacing: 0;
  font-size: 0.85em;
}
.panel.panel-collapsed { padding-bottom: 18px; }
.panel.panel-collapsed .panel-head { margin-bottom: 0; }

/* Cap chip on the shares panel head. Visually distinct from Refresh
 * (which is the action) so a user scanning the row sees the cap value
 * as data with a subtle "click to edit" affordance, not a primary CTA. */
.cap-chip {
  display: inline-flex; align-items: center;
  padding: 4px 10px;
  background: var(--bg-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-pill);
  color: var(--fg-secondary);
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0;
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out);
}
.cap-chip:hover { color: var(--fg-primary); border-color: var(--border-muted); }
.cap-chip:focus-visible { outline: 1px solid var(--flawless-teal); outline-offset: 2px; }

/* Copy-URL button on a share row. Tiny, mono, lives flush with the
 * URL link so triple-click still grabs the URL cleanly. */
.copy-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px;
  margin-left: 4px;
  background: transparent;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xs);
  color: var(--fg-tertiary);
  font: 11px/1 var(--font-mono);
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out),
              background var(--dur-fast) var(--ease-out);
}
.copy-btn:hover {
  color: var(--fg-primary);
  border-color: var(--border-muted);
  background: var(--bg-elevated);
}
.copy-btn[data-copied="1"] {
  color: var(--flawless-teal);
  border-color: var(--flawless-teal);
}

/* Compact button for in-table actions (bgr kill/remove). Same colour
 * tokens as the regular .btn variants; just smaller padding so the
 * table row doesn't blow up vertically. Selector is `.btn.btn-xs` (not
 * bare `.btn-xs`) so it wins on specificity against the later `.btn`
 * rule's `padding: 8px 14px` regardless of source order. */
.btn.btn-xs {
  padding: 4px 10px;
  font-size: var(--fs-body-sm);
  line-height: 1.2;
}

/* Pair-modal copy row: pre/code or code on the left, copy button on the
 * right, vertically centred. The pair button is slightly larger than the
 * in-row copy-btn used in the shares panel — pair codes are a one-shot
 * "click this once" surface so the affordance can be more prominent. */
.pair-row { display: flex; align-items: center; gap: 8px; margin: 6px 0; }
.pair-row > pre.code,
.pair-row > .pair-code { flex: 1; margin: 0; }
.copy-btn.pair-copy { width: auto; height: 28px; padding: 0 10px; font-size: 12px; }

.muted { color: var(--fg-secondary); }
.empty {
  padding: 18px;
  border: 1px dashed var(--border-muted);
  border-radius: var(--radius-sm);
  color: var(--fg-secondary);
}

/* ---------- Per-panel help button ---------------------------------------- *
 * A small `?` icon next to the panel head's Refresh action. Click opens a
 * modal with a structured explanation of the page (see PANEL_HELP +
 * buildHelpContent in views.js). Circular, sized to match other panel-head
 * controls; subtle by default, teal on hover/focus. */
.panel-help-btn {
  width: 26px; height: 26px;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent;
  border: 1px solid var(--border-subtle);
  border-radius: 50%;
  color: var(--fg-tertiary);
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: var(--fw-semibold);
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out),
              background var(--dur-fast) var(--ease-out);
}
.panel-help-btn:hover {
  color: var(--flawless-teal);
  border-color: var(--flawless-teal);
}
.panel-help-btn:focus-visible {
  outline: 1px solid var(--flawless-teal);
  outline-offset: 2px;
}

/* ---------- Agent portfolio sort pills ----------------------------------- */
.projects-sort-pill {
  display: inline-flex; align-items: center;
  padding: 3px 10px;
  background: var(--bg-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-pill);
  color: var(--fg-secondary);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out),
              background var(--dur-fast) var(--ease-out);
}
.projects-sort-pill:hover {
  color: var(--fg-primary);
  border-color: var(--border-muted);
}
.projects-sort-pill.is-active {
  color: var(--flawless-teal);
  border-color: var(--flawless-teal);
}
.projects-sort-pill:focus-visible {
  outline: 1px solid var(--flawless-teal);
  outline-offset: 2px;
}

/* ---------- Shared Directories panel ------------------------------------- *
 * Each row shows one shared directory. Currently-attached projects appear
 * as removable chips; a per-row "Share with project…" search reveals
 * unattached project suggestions as the user types. */
.shared-folder-search {
  width: 100%;
  max-width: 320px;
  padding: 6px 10px;
  background: var(--bg-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xs);
  color: var(--fg-primary);
  font: inherit;
  transition: border-color var(--dur-fast) var(--ease-out);
}
.shared-folder-search:focus-visible {
  outline: 1px solid var(--flawless-teal);
  outline-offset: 1px;
  border-color: var(--flawless-teal);
}
.shared-folder-search:disabled { opacity: 0.55; cursor: not-allowed; }
/* Dropdown panel anchored under the row's search input. Hidden until
 * the input gains focus (`.is-open` class). Vertical list inside the
 * panel reads as a typical autocomplete dropdown — each unattached
 * project is one full-width row the user can click. */
.shared-folder-suggestions {
  display: none;
}
.shared-folder-suggestions.is-open {
  display: flex;
  flex-direction: column;
  gap: 2px;
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  margin-top: 4px;
  padding: 4px;
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.35);
  z-index: 10;
  max-height: 260px;
  overflow-y: auto;
}
.shared-folder-suggestion {
  display: flex; align-items: center;
  width: 100%;
  padding: 6px 10px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-xs);
  color: var(--fg-secondary);
  font: inherit;
  font-family: var(--font-mono);
  font-size: 12px;
  text-align: left;
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease-out),
              background var(--dur-fast) var(--ease-out);
}
.shared-folder-suggestion:hover {
  color: var(--fg-primary);
  background: var(--bg-elevated);
}
.shared-folder-suggestion:focus-visible {
  outline: 1px solid var(--flawless-teal);
  outline-offset: -1px;
}
.shared-folder-suggestion::before { content: "+ "; color: var(--fg-tertiary); }
.shared-folder-suggestion:disabled { opacity: 0.55; cursor: not-allowed; }

/* Chip representing an active attachment. The × inside is the detach button. */
.shared-folder-chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 4px 2px 10px;
  background: var(--bg-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-pill);
  color: var(--fg-secondary);
  font-family: var(--font-mono);
  font-size: 12px;
}
.shared-folder-chip-remove {
  width: 18px; height: 18px;
  background: transparent;
  border: none;
  border-radius: var(--radius-pill);
  color: var(--fg-tertiary);
  font: 14px/1 var(--font-mono);
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease-out),
              background var(--dur-fast) var(--ease-out);
}
.shared-folder-chip-remove:hover {
  color: var(--fg-primary);
  background: var(--bg-surface);
}
.shared-folder-chip-remove:focus-visible {
  outline: 1px solid var(--flawless-teal);
  outline-offset: 1px;
}
.shared-folder-chip-remove:disabled { opacity: 0.4; cursor: not-allowed; }

/* ---------- Workspaces list (the home card grid) ------------------------- */

.workspaces { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.workspace {
  display: grid; grid-template-columns: 1fr auto; gap: 8px 16px;
  padding: 14px 16px;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  background: var(--bg-elevated);
  transition: border-color var(--dur-fast) var(--ease-out),
              background var(--dur-fast) var(--ease-out);
}
.workspace .meta {
  display: flex; flex-wrap: wrap; gap: 8px 14px;
  color: var(--fg-secondary); font-size: var(--fs-body-sm);
}
.workspace .name {
  font-weight: var(--fw-semibold);
  color: var(--fg-primary);
  font-size: var(--fs-body-lg);
}
.workspace .actions { display: flex; align-items: center; gap: 10px; }

.workspace-clickable { cursor: pointer; }
.workspace-clickable:hover {
  background: var(--bg-surface);
  border-color: var(--border-muted);
}
.workspace-clickable:focus-visible {
  outline: 1px solid var(--flawless-teal);
  outline-offset: 1px;
}

/* ---------- Pills ---------------------------------------------------------
 * Two flavour families share radius + sizing:
 *   .pill-online / .pill-offline — the workspace online/offline indicator.
 *   .status-pill.status-{done,failed,running,dead} — bgr-table rows.
 * Saturated fills sit on a low-opacity tinted background so they hold up
 * on the dark canvas without screaming. */
.pill {
  display: inline-block; padding: 3px 10px;
  border-radius: var(--radius-pill);
  font-size: 11px; font-weight: var(--fw-semibold);
  letter-spacing: 0.06em; text-transform: uppercase;
}
.pill-online  { color: var(--flawless-teal);  background: rgba(32,176,170,0.16); }
.pill-offline { color: var(--fg-secondary);   background: rgba(255,255,255,0.06); }
/* Update status pills (detail-view header). The teal "up to date"
 * shares the online tint; "update available" gets amber so a stale
 * workspace doesn't compete visually with the destructive-red palette
 * we reserve for revoke. "checking" is muted while the daemon round-
 * trips its first update_check on mount. */
.pill-up-to-date   { color: var(--flawless-teal);   background: rgba(32,176,170,0.16); }
.pill-behind       { color: var(--flawless-amber);  background: rgba(254,189,93,0.16); }
.pill-update-check { color: var(--fg-secondary);    background: rgba(255,255,255,0.06); }
.pill-update-error { color: var(--flawless-red-tint); background: rgba(216,51,47,0.14); }

.status-pill {
  display: inline-block; padding: 3px 10px;
  border-radius: var(--radius-pill);
  font-size: 11px; font-weight: var(--fw-semibold);
  letter-spacing: 0.06em; text-transform: uppercase;
  font-family: var(--font-sans);
}
.status-pill.status-done    { color: var(--flawless-teal);     background: rgba(32,176,170,0.16); }
.status-pill.status-failed  { color: var(--flawless-red);      background: rgba(216,51,47,0.16); }
.status-pill.status-running { color: var(--flawless-daylight); background: rgba(7,178,207,0.16); }
.status-pill.status-dead    { color: var(--fg-secondary);      background: rgba(255,255,255,0.06); }

/* ---------- Buttons ------------------------------------------------------- */

.btn {
  font: inherit;
  font-family: var(--font-sans);
  font-weight: var(--fw-medium);
  padding: 8px 14px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  border: 1px solid transparent;
  background: transparent;
  color: var(--fg-primary);
  transition: background var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out);
}
.btn:focus-visible {
  outline: 1px solid var(--flawless-teal);
  outline-offset: 1px;
}
.btn-primary {
  background: var(--flawless-red);
  color: var(--flawless-white);
  border-color: var(--flawless-red);
}
.btn-primary:hover {
  background: var(--flawless-red-tint);
  border-color: var(--flawless-red-tint);
}
.btn-secondary {
  background: transparent;
  color: var(--fg-primary);
  border-color: var(--border-strong);
}
.btn-secondary:hover {
  border-color: var(--fg-primary);
  background: rgba(255,255,255,0.04);
}
.btn-danger {
  background: transparent;
  color: var(--flawless-red);
  border-color: var(--flawless-red);
}
.btn-danger:hover {
  background: var(--flawless-red);
  color: var(--flawless-white);
}
/* Stop / pause actions — closer to "this halts work" than "this is
 * destructive". Uses --flawless-amber, the brand's nearest-to-yellow,
 * to set them apart from the red Kill / Delete buttons. */
.btn-warn {
  background: transparent;
  color: var(--flawless-amber);
  border-color: var(--flawless-amber);
}
.btn-warn:hover {
  background: var(--flawless-amber);
  color: var(--flawless-night);
}
.btn-icon {
  background: transparent; border: 0;
  font-size: 22px; line-height: 1; cursor: pointer;
  color: var(--fg-secondary);
}
.btn-icon:hover { color: var(--fg-primary); }

button[data-todo]:disabled,
.btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* ---------- Modal --------------------------------------------------------- */

.modal[hidden] { display: none; }
.modal {
  position: fixed; inset: 0;
  display: flex; align-items: center; justify-content: center;
  z-index: 50;
}
.modal-backdrop {
  position: absolute; inset: 0;
  background: var(--bg-overlay);
}
.modal-card {
  position: relative;
  background: var(--bg-surface);
  color: var(--fg-primary);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  width: min(520px, 92vw);
  padding: 0;
  box-shadow: var(--shadow-lg);
}
/* Wide variant for terminal-output modals (Tail). 1100px comfortably
 * holds an 80-col mono dump at 12px; capped at 96vw so it doesn't
 * touch the screen edges on small displays. */
.modal-card.modal-card-wide { width: min(1100px, 96vw); }

/* ANSI palette for the Tail pane. The numeric class names are the
 * SGR foreground / background codes the parser emits (30–37 standard,
 * 90–97 bright, 40–47 / 100–107 for bg). The hues are picked to read
 * cleanly on the Flawless night canvas; bright variants are a notch
 * lighter than the standard counterparts.
 *
 * 256-colour fg/bg and 24-bit truecolour come through as inline
 * style="color:#…;background:#…" — no class needed for those. */
.ansi-pane {
  white-space: pre;
  font-family: var(--font-mono);
  font-size: 12px;
  background: var(--bg-elevated);
  color: var(--fg-primary);
  padding: 12px 14px;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  margin: 0;
  max-height: 70vh;
  overflow: auto;
}
.ansi-pane .a-b      { font-weight: var(--fw-bold); }
.ansi-pane .a-d      { opacity: 0.6; }
.ansi-pane .a-u      { text-decoration: underline; }
.ansi-pane .a-r      { /* reverse — handled inline via swap */ }
/* Standard 16 — foreground */
.ansi-pane .a-fg-0   { color: #1a1a1a; }
.ansi-pane .a-fg-1   { color: #D8332F; } /* Flawless red for red */
.ansi-pane .a-fg-2   { color: #20B0AA; } /* Flawless teal for green */
.ansi-pane .a-fg-3   { color: #FEBD5D; }
.ansi-pane .a-fg-4   { color: #07B2CF; }
.ansi-pane .a-fg-5   { color: #C77CC9; }
.ansi-pane .a-fg-6   { color: #4CBFBB; }
.ansi-pane .a-fg-7   { color: #C8C8C8; }
.ansi-pane .a-fg-8   { color: #636363; } /* bright black / grey */
.ansi-pane .a-fg-9   { color: #FF6F6B; }
.ansi-pane .a-fg-10  { color: #54D9D3; }
.ansi-pane .a-fg-11  { color: #FFD080; }
.ansi-pane .a-fg-12  { color: #5DD5EA; }
.ansi-pane .a-fg-13  { color: #E0A6E2; }
.ansi-pane .a-fg-14  { color: #80E5E0; }
.ansi-pane .a-fg-15  { color: #FAFAFA; }
/* Standard 16 — background */
.ansi-pane .a-bg-0   { background: #1a1a1a; }
.ansi-pane .a-bg-1   { background: #D8332F; }
.ansi-pane .a-bg-2   { background: #20B0AA; }
.ansi-pane .a-bg-3   { background: #FEBD5D; color: #111; }
.ansi-pane .a-bg-4   { background: #07B2CF; }
.ansi-pane .a-bg-5   { background: #C77CC9; }
.ansi-pane .a-bg-6   { background: #4CBFBB; color: #111; }
.ansi-pane .a-bg-7   { background: #C8C8C8; color: #111; }
.ansi-pane .a-bg-8   { background: #636363; }
.ansi-pane .a-bg-9   { background: #FF6F6B; color: #111; }
.ansi-pane .a-bg-10  { background: #54D9D3; color: #111; }
.ansi-pane .a-bg-11  { background: #FFD080; color: #111; }
.ansi-pane .a-bg-12  { background: #5DD5EA; color: #111; }
.ansi-pane .a-bg-13  { background: #E0A6E2; color: #111; }
.ansi-pane .a-bg-14  { background: #80E5E0; color: #111; }
.ansi-pane .a-bg-15  { background: #FAFAFA; color: #111; }
.modal-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border-subtle);
}
/* Modal title is a kicker, same treatment as panel headings. */
.modal-head h3 {
  margin: 0;
  font-family: var(--font-sans);
  font-weight: var(--fw-regular);
  font-size: var(--fs-kicker-sm);
  letter-spacing: var(--track-kicker);
  text-transform: lowercase;
  color: var(--fg-editorial);
}
.modal-body  { padding: 18px 20px; }
.modal-foot  {
  padding: 14px 20px;
  border-top: 1px solid var(--border-subtle);
  display: flex; justify-content: flex-end; gap: 8px;
}
.modal-label {
  display: block;
  font-size: 11px; letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--fg-tertiary);
  margin-bottom: 8px;
}

/* ---------- Code / mono blocks ------------------------------------------- */

.code {
  background: var(--bg-elevated); color: var(--fg-primary);
  padding: 12px 14px;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  font-family: var(--font-mono); font-size: 13px;
  overflow-x: auto; margin: 6px 0 14px;
}
.pair-code {
  font-family: var(--font-mono); font-size: 26px; letter-spacing: 4px;
  font-weight: var(--fw-bold); color: var(--fg-primary);
  padding: 14px 18px;
  border: 1px dashed var(--border-muted);
  border-radius: var(--radius-sm);
  text-align: center; margin: 4px 0 12px;
  background: var(--bg-elevated);
}
.error {
  background: rgba(216,51,47,0.12);
  color: var(--flawless-red);
  border: 1px solid var(--flawless-red);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  margin-bottom: 12px;
}

/* ---------- Detail view layout ------------------------------------------- */

.detail-header .panel-head { align-items: flex-start; flex-direction: column; gap: 10px; }
.detail-title { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
/* The workspace name keeps display weight rather than the kicker treatment
 * — it's the primary identifier, not an editorial label. */
.detail-title h2 {
  margin: 0;
  font-family: var(--font-sans);
  font-weight: var(--fw-semibold);
  font-size: 22px;
  letter-spacing: -0.01em;
  text-transform: none;
  color: var(--fg-primary);
}
.back-link {
  color: var(--flawless-teal);
  text-decoration: none;
  font-size: var(--fs-body-sm);
  letter-spacing: 0.04em;
}
.back-link:hover { color: var(--flawless-teal-tint); text-decoration: underline; }

.detail-panel { margin-top: 14px; }
.detail-panel .detail-body { display: block; }

/* ---------- Responsive row actions ---------------------------------------
 * Above 700px (tablet / desktop): row-action buttons render inline as a
 * flex strip — the existing convention.
 * At or below 700px (phone): buttons collapse into a `⋯` disclosure button
 * that opens a floating popover anchored to the row. Implemented with
 * <details>/<summary> so it's keyboard-accessible + needs zero JS to
 * toggle. The buttons are still in the DOM (querySelector still finds
 * them for vitest selectors / e2e), just hidden behind the disclosure.
 * --------------------------------------------------------------------- */
.row-overflow {
  /* relative so the popover positions to this element on mobile. */
  position: relative;
  /* On desktop the details acts purely as a passthrough. */
}
.row-overflow > summary {
  /* Strip the default <details> marker; on desktop we hide the summary
   * entirely. */
  list-style: none;
  cursor: pointer;
  -webkit-user-select: none;
  user-select: none;
}
.row-overflow > summary::-webkit-details-marker { display: none; }
.row-overflow > summary::marker { display: none; }
.row-overflow > .overflow-content {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}
@media (min-width: 701px) {
  /* Desktop: hide the dots, show buttons inline. */
  .row-overflow > summary { display: none; }
  .row-overflow > .overflow-content { display: flex; }
}
@media (max-width: 700px) {
  /* Mobile: show the dots; hide the buttons unless the user opens the
   * disclosure. */
  .row-overflow > summary {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    background: var(--bg-elevated);
    color: var(--fg-primary);
    font-size: 20px;
    line-height: 1;
    font-weight: var(--fw-semibold);
  }
  .row-overflow > summary:hover {
    background: var(--bg-row-hover, var(--bg-elevated));
  }
  .row-overflow:not([open]) > .overflow-content { display: none; }
  .row-overflow[open] > .overflow-content {
    /* Float anchored to the right edge of the row. z-index keeps it
     * above subsequent rows when expanded near the bottom of a list. */
    position: absolute;
    right: 0;
    top: calc(100% + 4px);
    flex-direction: column;
    min-width: 160px;
    background: var(--bg-elevated);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    padding: 6px;
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.35);
    z-index: 10;
  }
  .row-overflow[open] > .overflow-content > * {
    /* Full-width buttons in the popover so the tap targets are big. */
    width: 100%;
    justify-content: flex-start;
  }
  /* Same treatment for window-row-actions (tmux window list inside an
   * expanded session row). */
  .window-row-overflow > summary { display: inline-flex; }
}

/* ---------- bgr-table mobile horizontal scroll ----------------------------
 * The bgr ls table has 6 columns (ID, STATUS, AGE, EXIT, CMD, action).
 * On narrow viewports the CMD column gets squished to unreadable. Wrap
 * the table in a horizontally-scrollable container so the columns keep
 * their natural width and the user scrolls sideways instead.
 */
.bgr-table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

/* ---------- Row lists (sessions, projects) ------------------------------- */

.rowlist { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.rowlist .row {
  display: grid; grid-template-columns: 1fr auto; gap: 8px 16px;
  padding: 12px 14px;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  background: var(--bg-elevated);
  align-items: center;
}
.rowlist .row-main { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.rowlist .row-name {
  font-weight: var(--fw-semibold);
  color: var(--fg-primary);
}

/* ---------- bgr-table ---------------------------------------------------- */

.bgr-output {
  font-family: var(--font-mono); font-size: 12px;
  background: var(--bg-elevated); color: var(--fg-primary);
  padding: 12px 14px;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  max-height: 360px; overflow: auto; white-space: pre;
  margin: 0;
}
.bgr-table { width: 100%; border-collapse: collapse; font-size: var(--fs-body-sm); }
.bgr-table th, .bgr-table td {
  text-align: left; padding: 8px 12px;
  border-bottom: 1px solid var(--border-subtle);
  vertical-align: top;
}
.bgr-table th {
  font-weight: var(--fw-semibold);
  color: var(--fg-tertiary);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-size: 11px;
  border-bottom-width: 1px;
  border-bottom-color: var(--border-muted);
}
.bgr-table td { font-family: var(--font-mono); }
.bgr-table tbody tr:hover { background: rgba(255,255,255,0.03); }
.bgr-table th.bgr-sort-th { transition: color var(--dur-fast) var(--ease-out); }
.bgr-table th.bgr-sort-th:hover { color: var(--fg-secondary); }
.bgr-table th.bgr-sort-th[data-bgr-sort-active="1"] { color: var(--flawless-teal); }
.bgr-table th.bgr-sort-th:focus-visible {
  outline: 1px solid var(--flawless-teal);
  outline-offset: -1px;
}
.bgr-table .bgr-cmd-cell {
  max-width: 360px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ---------- Session expander + per-window rows --------------------------- */

.row-expander { user-select: none; }
.row-caret { color: var(--fg-secondary); display: inline-block; width: 1em; }
.windows-container {
  grid-column: 1 / -1;
  margin-top: 10px;
  border-top: 1px dashed var(--border-subtle);
  padding-top: 10px;
  display: grid;
  gap: 6px;
}
.pair-action {
  display: flex; justify-content: flex-start;
  margin-top: 24px;
  padding-top: 16px;
  border-top: 1px solid var(--border-subtle);
}
/* `display: flex` above overrides the UA `[hidden] { display: none }`
 * — same trap as the profile dropdown. app.js toggles
 * pair-action.hidden between routes; this rule makes the attribute
 * authoritative so the pair CTA only appears on the servers list. */
.pair-action[hidden] { display: none !important; }

.window-row {
  /* Two columns top row (main + actions) + a full-width recap row
   * underneath. The recap div is a child of .window-row and spans
   * both columns via the rule below. align-items: start so the
   * actions cell doesn't stretch vertically to the recap's height. */
  display: grid; grid-template-columns: 1fr auto; gap: 6px 12px;
  align-items: start;
  padding: 8px 10px;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  background: var(--bg-surface);
}

/* Agent recap surface — inline under each Claude agent's main row.
 * The container spans both grid columns so the summary text + the
 * expandable compact-history details get the full row width. */
.window-row .agent-recap {
  grid-column: 1 / -1;
  font-size: var(--fs-body-sm);
  color: var(--fg-secondary);
  margin-top: 2px;
}
.agent-recap-tldr-text {
  font-family: var(--font-sans);
  font-size: 12px;
  line-height: 1.4;
  white-space: pre-wrap;
  word-break: break-word;
  margin: 4px 0 0;
  padding: 6px 8px;
  background: var(--bg-elevated);
  border-radius: var(--radius-xs);
  border-left: 2px solid var(--accent);
  color: var(--fg-primary);
}
.agent-last-activity {
  font-size: var(--fs-body-sm);
  margin-left: 8px;
  white-space: nowrap;
}
.window-row .window-name {
  font-weight: var(--fw-semibold);
  color: var(--fg-primary);
}
.window-row .window-index { font-family: var(--font-mono); color: var(--fg-secondary); }
.window-row-main {
  display: flex; align-items: center; gap: 8px; min-width: 0;
}

/* Agent-kind badge — a uniform 18×18 rounded-square chassis with a
 * brand-coloured fill (set via `color` on the per-kind class →
 * `currentColor` on the chassis rect inside the SVG) and a white
 * glyph centred inside. Same shape / size / radius for all three
 * kinds so the row reads as a tidy icon column rather than three
 * arbitrary shapes. */
.agent-kind-icon {
  flex: 0 0 18px;
  width: 18px; height: 18px;
  display: inline-block;
}
.agent-kind-claude { color: var(--flawless-orange); }
.agent-kind-cursor { color: var(--flawless-daylight); }
.agent-kind-bash   { color: var(--grey-500); }

/* ---------- Spend dashboard ----------------------------------------------- */

.spend-window-picker {
  display: flex; gap: 6px;
}
.spend-window-picker .btn.is-active {
  background: var(--flawless-teal);
  color: var(--flawless-night);
  border-color: var(--flawless-teal);
}

.spend-team-head-actions {
  display: flex; gap: 12px; align-items: center;
}

.spend-loading,
.spend-team-empty,
.spend-daily-empty {
  padding: 24px 12px;
}
.spend-error {
  padding: 12px;
  border-radius: var(--radius-sm);
  background: rgba(216, 51, 47, 0.12);
  color: var(--flawless-red-tint);
}

/* Big-number totals — three columns, full-bleed on the panel. */
.spend-totals {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
  margin: 16px 0 8px;
}
.spend-total {
  padding: 16px 20px;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  background: var(--bg-surface);
}
.spend-total-label {
  font-size: 12px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--fg-secondary);
  margin-bottom: 6px;
}
.spend-total-value {
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: 28px;
  color: var(--fg-primary);
  line-height: 1.1;
}
.spend-total-sum .spend-total-value { color: var(--flawless-teal); }
.spend-total-claude .spend-total-value { color: var(--flawless-red-tint); }
.spend-total-cursor .spend-total-value { color: var(--flawless-daylight-tint); }

/* Chart container — clamp to readable width on wide displays. */
.spend-chart-wrap {
  margin: 12px 0 4px;
  padding: 8px 0;
}
.spend-chart {
  width: 100%;
  height: auto;
  max-height: 260px;
  display: block;
}
.spend-chart-axis {
  stroke: var(--border-subtle);
  stroke-width: 1;
}
.spend-chart-gridline {
  stroke: var(--border-subtle);
  stroke-width: 1;
  stroke-dasharray: 2 4;
  opacity: 0.5;
}
.spend-chart-tick {
  font-family: var(--font-mono);
  font-size: 11px;
  fill: var(--fg-tertiary);
}
.spend-chart-empty {
  font-size: 13px;
  fill: var(--fg-tertiary);
}
.spend-chart-claude {
  fill: rgba(216, 51, 47, 0.55);
  stroke: var(--flawless-red);
  stroke-width: 1;
}
.spend-chart-cursor {
  fill: rgba(7, 178, 207, 0.45);
  stroke: var(--flawless-daylight);
  stroke-width: 1;
}

.spend-chart-legend {
  display: flex; gap: 16px; align-items: center;
  font-size: 12px;
  color: var(--fg-secondary);
  margin: 4px 0 12px;
}
.spend-legend-item {
  display: inline-flex; align-items: center; gap: 6px;
}
.spend-legend-swatch {
  display: inline-block;
  width: 12px; height: 12px;
  border-radius: 2px;
}
.spend-legend-swatch.is-claude {
  background: var(--flawless-red);
  opacity: 0.7;
}
.spend-legend-swatch.is-cursor {
  background: var(--flawless-daylight);
  opacity: 0.7;
}

.spend-section-head {
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: 16px;
  margin: 20px 0 8px;
  color: var(--fg-primary);
}

/* Daily breakdown table. */
.spend-daily-table,
.spend-team-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}
.spend-daily-table th,
.spend-team-table th {
  text-align: left;
  font-weight: var(--fw-semibold);
  color: var(--fg-secondary);
  border-bottom: 1px solid var(--border-subtle);
  padding: 8px 10px;
}
.spend-daily-table td,
.spend-team-table td {
  border-bottom: 1px solid var(--border-subtle);
  padding: 8px 10px;
  vertical-align: top;
}
.spend-daily-table .right,
.spend-team-table .right { text-align: right; font-variant-numeric: tabular-nums; font-family: var(--font-mono); }
.spend-daily-table .strong,
.spend-team-table .strong { color: var(--fg-primary); font-weight: var(--fw-semibold); }
.spend-daily-table tbody tr:last-child td,
.spend-team-table tbody tr:last-child td { border-bottom: none; }

/* Sortable header cells on the team table. Cursor changes to
 * pointer so the affordance reads as "click me"; hover lifts the
 * text colour, and the column currently driving the sort gets
 * a fully-saturated foreground + a small teal underline so the
 * eye finds it without searching the column header for the
 * tiny arrow glyph. */
.spend-team-table th.spend-team-sortable {
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
  transition: color 0.12s;
}
.spend-team-table th.spend-team-sortable:hover {
  color: var(--fg-primary);
}
.spend-team-table th.spend-team-sortable.is-active {
  color: var(--flawless-teal);
  box-shadow: inset 0 -2px 0 var(--flawless-teal);
}
.spend-team-table th.spend-team-sortable:focus-visible {
  outline: 1px solid var(--flawless-teal);
  outline-offset: -2px;
}

/* Team table — clickable rows + filter chips + seat pills + user cell. */
.spend-filter-chips {
  display: flex; flex-wrap: wrap; gap: 6px;
  margin: 8px 0 16px;
}
.spend-filter-chips .btn.is-active {
  background: var(--flawless-teal);
  color: var(--flawless-night);
  border-color: var(--flawless-teal);
}
.spend-team-row { cursor: pointer; }
.spend-team-row:hover td { background: var(--bg-elevated); }
.spend-team-row:focus-visible {
  outline: 1px solid var(--flawless-teal);
  outline-offset: -1px;
}
.spend-user-cell { display: flex; flex-direction: column; gap: 2px; }
.spend-user-name { color: var(--fg-primary); font-weight: var(--fw-medium); }
.spend-user-email { color: var(--fg-tertiary); font-family: var(--font-mono); font-size: 11px; }
.spend-seat-row { display: flex; gap: 4px; }
.spend-seat-pill {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: var(--fw-medium);
}
.spend-seat-pill.is-claude {
  background: rgba(216, 51, 47, 0.18);
  color: var(--flawless-red-tint);
}
.spend-seat-pill.is-cursor {
  background: rgba(7, 178, 207, 0.18);
  color: var(--flawless-daylight-tint);
}

.spend-detail-head { display: flex; align-items: center; gap: 12px; }
.spend-detail-head h2 { margin: 0; }

/* ============================================================
 *  /admin overview
 * ============================================================
 *
 * Layout mirrors .spend-totals — same card metric pattern, but the
 * grid is four-up so the workspaces / users / sessions / spend
 * tiles fit on a single row at desktop widths. Below 720px the
 * grid collapses to a 2×2.
 *
 * Clickable tiles (only Spend MTD at the moment) get a teal outline
 * on hover to telegraph that they're navigation, mirroring the
 * row-hover state on .spend-team-row.
 */
.admin-tile-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 16px;
  margin: 16px 0 8px;
}
@media (max-width: 720px) {
  .admin-tile-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.admin-tile {
  padding: 16px 20px;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  background: var(--bg-surface);
}
.admin-tile.is-clickable {
  cursor: pointer;
  transition: outline-color 80ms ease-out;
}
.admin-tile.is-clickable:hover,
.admin-tile.is-clickable:focus-visible {
  outline: 1px solid var(--flawless-teal);
  outline-offset: -1px;
}
.admin-tile-title {
  font-size: 12px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--fg-secondary);
  margin-bottom: 6px;
}
.admin-tile-value {
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: 28px;
  color: var(--fg-primary);
  line-height: 1.1;
}
.admin-tile-sub {
  margin-top: 6px;
  font-size: 12px;
}
.admin-head-actions { display: flex; align-items: center; gap: 8px; }
.admin-loading, .admin-error { margin: 12px 0; }
.admin-footnote { margin-top: 24px; font-size: 12px; }

/* Window picker — mirrors .spend-window-picker so the active-state
 * highlighting reads the same in both panels. */
.admin-window-picker { display: flex; gap: 4px; }
.admin-window-picker .btn.is-active {
  background: var(--bg-elevated);
  color: var(--fg-primary);
}

/* Chart layout — two stacked sections, full panel width. */
.admin-charts {
  display: flex;
  flex-direction: column;
  gap: 24px;
  margin-top: 24px;
}
.admin-chart-block { display: flex; flex-direction: column; gap: 8px; }
.admin-section-head {
  margin: 0;
  font-size: 13px;
  font-weight: var(--fw-semibold);
  color: var(--fg-secondary);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.admin-chart-wrap {
  max-width: 100%;
  overflow-x: auto;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  background: var(--bg-surface);
  padding: 12px;
}
.admin-chart { width: 100%; height: auto; display: block; }
.admin-chart-axis {
  stroke: var(--border-subtle);
  stroke-width: 1;
}
.admin-chart-gridline {
  stroke: var(--border-subtle);
  stroke-width: 1;
  stroke-dasharray: 2 4;
  opacity: 0.6;
}
.admin-chart-tick {
  fill: var(--fg-tertiary);
  font-size: 11px;
  font-family: var(--font-mono);
}
.admin-chart-empty {
  fill: var(--fg-tertiary);
  font-size: 13px;
}
.admin-chart-line {
  stroke-width: 1.5;
  fill: none;
}
.admin-chart-fill { opacity: 0.18; }
/* Series-specific colours — sessions on teal (mirrors spend total),
 * concurrency on the daylight tint so the eye doesn't try to compare
 * them as the same metric. */
.admin-chart-line.is-sessions,
.admin-chart-fill.is-sessions {
  stroke: var(--flawless-teal);
  fill: var(--flawless-teal);
}
.admin-chart-line.is-concurrency,
.admin-chart-fill.is-concurrency {
  stroke: var(--flawless-daylight-tint);
  fill: var(--flawless-daylight-tint);
}
.admin-chart-loading,
.admin-chart-error {
  padding: 12px;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
}

/* ============================================================
 *  /admin/users + /admin/users/:oid
 * ============================================================ */

.admin-link-row { margin-top: 16px; }
.admin-detail-head {
  display: flex;
  align-items: center;
  gap: 12px;
}
.admin-detail-head h2 { margin: 0; }

.admin-filter-input {
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  padding: 4px 8px;
  color: var(--fg-primary);
  font-size: 13px;
  min-width: 240px;
}

/* Users / sessions tables — same look as the spend team table. */
.admin-table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 12px;
  font-size: 13px;
}
.admin-table th {
  text-align: left;
  font-weight: var(--fw-medium);
  font-size: 11px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--fg-tertiary);
  padding: 8px 12px;
  border-bottom: 1px solid var(--border-subtle);
}
.admin-table th.right { text-align: right; }
.admin-table th.left { text-align: left; }
.admin-table td {
  padding: 10px 12px;
  border-bottom: 1px solid var(--border-subtle);
  color: var(--fg-primary);
  vertical-align: middle;
}
.admin-table td.right { text-align: right; font-variant-numeric: tabular-nums; }
.admin-table td.left { text-align: left; }
.admin-table-row.is-clickable { cursor: pointer; }
.admin-table-row.is-clickable:hover {
  background: var(--bg-elevated);
  outline: 1px solid var(--flawless-teal);
  outline-offset: -1px;
}

.admin-user-cell { display: flex; flex-direction: column; gap: 2px; }
.admin-user-name { color: var(--fg-primary); font-weight: var(--fw-medium); }
.admin-user-email {
  color: var(--fg-tertiary);
  font-family: var(--font-mono);
  font-size: 11px;
}

.admin-seat-row { display: flex; gap: 4px; }
.admin-seat-pill {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: var(--fw-medium);
}
.admin-seat-pill.is-claude {
  background: rgba(216, 51, 47, 0.18);
  color: var(--flawless-red-tint);
}
.admin-seat-pill.is-cursor {
  background: rgba(7, 178, 207, 0.18);
  color: var(--flawless-daylight-tint);
}

/* State pill — live / idle / ended */
.admin-state-pill {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: var(--fw-medium);
}
.admin-state-pill.is-live {
  background: rgba(7, 178, 207, 0.18);
  color: var(--flawless-daylight-tint);
}
.admin-state-pill.is-idle {
  background: rgba(216, 196, 51, 0.18);
  color: #d8c433;
}
.admin-state-pill.is-ended {
  background: var(--bg-elevated);
  color: var(--fg-tertiary);
}

/* User detail page */
.admin-identity-card {
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  background: var(--bg-surface);
  padding: 16px 20px;
  margin: 16px 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px 24px;
}
@media (max-width: 720px) {
  .admin-identity-card { grid-template-columns: 1fr; }
}
.admin-identity-row { display: flex; flex-direction: column; gap: 2px; }
.admin-identity-label {
  font-size: 11px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--fg-tertiary);
}
.admin-identity-value {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--fg-primary);
  font-size: 14px;
}
.admin-identity-value.mono { font-family: var(--font-mono); }
.admin-link-btn { margin-left: 8px; }

.admin-workspace-block {
  margin-top: 24px;
  padding-top: 16px;
  border-top: 1px solid var(--border-subtle);
}
.admin-workspace-head {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-bottom: 12px;
}
.admin-workspace-name {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: var(--fw-semibold);
  font-size: 16px;
}
.admin-workspace-display { color: var(--fg-primary); }
.admin-workspace-meta { font-size: 11px; }

.admin-workspace-meta-row {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 12px;
  margin-bottom: 12px;
}
@media (max-width: 720px) {
  .admin-workspace-meta-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.admin-meta-item { display: flex; flex-direction: column; gap: 2px; }
.admin-meta-label {
  font-size: 11px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--fg-tertiary);
}
.admin-meta-value {
  color: var(--fg-primary);
  font-size: 13px;
}
.admin-meta-value.mono { font-family: var(--font-mono); }

.admin-sessions-table { margin-top: 4px; }
.admin-agent-cell { display: flex; flex-direction: column; gap: 2px; }
.admin-agent-name {
  color: var(--fg-primary);
  font-weight: var(--fw-medium);
}
.admin-agent-tldr {
  color: var(--fg-secondary);
  font-size: 12px;
  font-style: italic;
  line-height: 1.4;
  max-width: 60ch;
}

.admin-empty { padding: 8px 0; }

/* Audit log */
.admin-link-row { display: flex; gap: 8px; flex-wrap: wrap; }
.admin-audit-when { font-size: 13px; }
.admin-audit-iso { font-size: 11px; }
.admin-audit-actor { font-size: 13px; }
.admin-audit-actor-oid { font-size: 11px; }
.admin-audit-target { color: var(--fg-primary); }
.admin-audit-target.is-clickable {
  cursor: pointer;
  text-decoration: underline;
  text-decoration-style: dotted;
  text-underline-offset: 2px;
}
.admin-audit-target.is-clickable:hover {
  color: var(--flawless-teal);
}
.admin-audit-meta { color: var(--fg-secondary); font-size: 12px; }
