/* =============================================================
   Velund theme for Basecoat — loaded AFTER basecoat.cdn.min.css.

   Two jobs:
     1. Re-point Basecoat's shadcn-style tokens at the Velund palette
        (tokens.css), so every component renders in the house style.
     2. Carry over the app shell (lime sidebar, topbar, user menu) and
        the shared .bfl backfill line verbatim from app.css — the v2
        page does not load app.css, Basecoat owns the content area.
   ============================================================= */

/* ---------------------------------------------------- 1. token bridge */
/* The portal is dark-only: both light and dark resolve to Velund dark. */
:root, .dark {
  --radius: 0.5rem;                      /* buttons 6px, cards 12px    */

  --background:            var(--vl-bg-app);
  --foreground:            var(--vl-fg-soft);
  --card:                  var(--vl-bg-card);
  --card-foreground:       var(--vl-fg-soft);
  --popover:               var(--vl-bg-card-2);
  --popover-foreground:    var(--vl-fg-soft);
  --primary:               var(--vl-lime);
  --primary-foreground:    var(--vl-ink-logo);
  --secondary:             var(--vl-bg-card-2);
  --secondary-foreground:  var(--vl-fg-soft);
  --muted:                 var(--vl-bg-card-2);
  --muted-foreground:      var(--vl-fg-dim);
  --accent:                var(--vl-bg-card-2);
  --accent-foreground:     var(--vl-white);
  --destructive:           var(--vl-danger);
  --border:                var(--vl-stroke-2);
  --input:                 var(--vl-stroke-3);
  --ring:                  var(--vl-lime);

  --font-sans: 'Inter', system-ui, sans-serif;
  --font-mono: 'Inter', system-ui, sans-serif;  /* mono retired 2026-09-04 */

  --chart-1: var(--vl-lime);
  --chart-2: var(--vl-info-cyan);
  --chart-3: var(--vl-success);
  --chart-4: var(--vl-warn);
  --chart-5: var(--vl-danger);

  /* Sidebar tokens map to the signature lime rail, in case Basecoat's
     own sidebar component ever gets used here. */
  --sidebar:                    var(--vl-lime);
  --sidebar-foreground:         var(--vl-bg-ink);
  --sidebar-primary:            var(--vl-bg-ink);
  --sidebar-primary-foreground: var(--vl-lime);
  --sidebar-accent:             rgba(0, 0, 0, 0.08);
  --sidebar-accent-foreground:  var(--vl-bg-ink);
  --sidebar-border:             rgba(21, 23, 4, 0.15);
  --sidebar-ring:               var(--vl-bg-ink);
}

html, body { background: var(--vl-bg-app); color: var(--vl-fg-soft); }
body { font-family: var(--font-sans); }
h1, h2, h3 { font-family: var(--vl-ff-display); }

/* Focus rings in pure lime read as buttons; soften them. */
:root, .dark { --ring: color-mix(in srgb, var(--vl-lime) 55%, transparent); }

/* ------------------------------------------------- 2. app shell (copy) */
/* Verbatim from app.css so the frame is pixel-identical to the rest of
   the portal. Content-area classes (.btn, .card, .badge …) are Basecoat's. */

.shell { display: grid; grid-template-columns: 232px 1fr; min-height: 100vh; }

aside.vl-sidebar {
  background: var(--vl-lime);
  padding: 22px 14px 18px;
  position: sticky; top: 0; height: 100vh;
  display: flex; flex-direction: column; gap: 2px;
}
.brand { display: flex; align-items: center; gap: 10px; padding: 0 8px; margin-bottom: 6px; }
.brand img { width: 30px; height: 30px; display: block; }
.brand .brand-name {
  font-family: var(--vl-ff-display); font-weight: 800; font-size: 21px;
  color: var(--vl-ink-logo); letter-spacing: -0.01em; line-height: 1;
}
.brand .brand-by {
  font-size: 10px; color: rgba(21,23,4,0.55); font-weight: 600;
  letter-spacing: 0.08em; text-transform: uppercase; margin-top: 3px; display: block;
}
.nav-sep {
  font-size: 10px; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase;
  color: rgba(21,23,4,0.45); padding: 14px 12px 4px;
}
.nav-sep.push { margin-top: auto; }
.nav-item {
  display: flex; align-items: center; gap: 12px; padding: 9px 12px;
  border-radius: var(--vl-r-md); font-family: var(--vl-ff-ui); font-size: 15px;
  color: var(--vl-bg-ink); cursor: pointer; font-weight: 600; text-decoration: none;
  transition: background var(--vl-dur-1) var(--vl-ease);
}
.nav-item.active { background: var(--vl-bg-ink); color: var(--vl-lime); font-weight: 700; }
.nav-item:hover:not(.active) { background: rgba(0,0,0,0.08); }
.nav-item svg { width: 19px; height: 19px; stroke: currentColor; fill: none; stroke-width: 1.7; flex: none; }

/* A rail entry whose screen does not exist yet: visible in the IA, inert. */
.nav-item.soon { cursor: default; opacity: 0.5; }
.nav-item.soon:hover { background: none; }
/* A paid feature the workspace is not entitled to: reachable, explains itself. */
.nav-item.locked { opacity: 0.62; }
.nav-item.locked.active { opacity: 1; }
.nav-item.locked .soon-tag { background: var(--vl-lime); color: var(--vl-bg-ink); }
.nav-item .soon-tag {
  margin-left: auto; font-size: 9px; font-weight: 700; letter-spacing: 0.1em;
  text-transform: uppercase; padding: 2px 6px; border-radius: var(--vl-r-pill);
  background: rgba(21,23,4,0.14); color: rgba(21,23,4,0.7);
}
.side-help {
  margin-top: 14px; padding: 13px 14px; border-radius: 10px;
  background: rgba(0,0,0,0.08); font-size: 12px; color: var(--vl-bg-ink);
}
.side-help b { display: block; margin-bottom: 3px; }
.side-help a { color: inherit; text-decoration: none; font-weight: 700; }

main.content { padding: 22px 32px 70px; overflow-x: hidden; min-width: 0; }

.topbar { display: flex; align-items: center; gap: 14px; margin-bottom: 26px; }
.topbar-spacer { flex: 1; }
.sim-badge {
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--vl-warn); border: 1px solid rgba(249,212,73,0.45);
  border-radius: var(--vl-r-pill); padding: 5px 11px; white-space: nowrap;
}
.avatar-toggle {
  width: 38px; height: 38px; border-radius: 50%; border: 0; cursor: pointer;
  background: linear-gradient(135deg, #09BC7C, #2CD8DE);
  display: flex; align-items: center; justify-content: center;
  color: var(--vl-bg-ink); font-weight: 800; font-size: 13px;
}

.menu { position: relative; }
.menu-panel {
  display: none; position: absolute; right: 0; top: calc(100% + 8px); z-index: 60;
  min-width: 250px; background: var(--vl-bg-card); border: 1px solid var(--vl-stroke-3);
  border-radius: var(--vl-r-lg); padding: 8px; box-shadow: var(--vl-shadow-pop);
}
.menu.open .menu-panel { display: block; }
.menu-head { padding: 8px 11px 4px; }
.menu-head .m-name { font-weight: 700; color: #fff; font-size: 13.5px; }
.menu-head .m-mail { font-size: 12px; color: var(--vl-fg-dim); margin-top: 1px; }
.menu-label {
  font-size: 10px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--vl-fg-dim); padding: 10px 11px 4px;
}
.menu-item {
  display: flex; width: 100%; text-align: left; align-items: center; gap: 8px;
  background: none; border: 0; color: var(--vl-fg-soft); font-size: 13.5px;
  padding: 8px 11px; border-radius: var(--vl-r-md); cursor: pointer; text-decoration: none;
}
.menu-item:hover { background: rgba(255,255,255,0.06); }
.menu-item.current { background: rgba(224,255,30,0.09); color: var(--vl-lime); font-weight: 700; }
.menu-item .tick { margin-left: auto; font-size: 12px; }
.menu-sep { border-top: 1px solid var(--vl-stroke); margin: 6px 4px; }
.menu-form-inline { padding: 6px 11px 8px; display: flex; gap: 6px; }
.menu-form-inline input {
  flex: 1; min-width: 0; background: rgba(255,255,255,0.05); color: #fff;
  border: 1px solid var(--vl-stroke-2); border-radius: var(--vl-r-md); padding: 6px 9px;
  font-family: inherit; font-size: 13px;
}

.verify-banner {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  background: rgba(249,212,73,0.06); border: 1px solid rgba(249,212,73,0.3);
  border-radius: 10px; padding: 9px 15px; margin-bottom: 18px;
  font-size: 13px; color: var(--vl-warn);
}
.verify-banner form { margin-left: auto; }

.page-head { margin-bottom: 20px; }
.page-head h1 { font-weight: 700; color: #fff; font-size: 26px; margin: 0 0 4px; letter-spacing: -0.01em; }
.page-head .sub { font-size: 13px; color: var(--vl-fg-dim); }
.page-head-row { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.head-actions { display: flex; gap: 10px; flex-wrap: wrap; }

.muted { color: var(--vl-fg-dim); }
.tiny { font-size: 11.5px; }
.mono { font-family: var(--vl-ff-mono); }

@media (max-width: 900px) {
  .shell { grid-template-columns: 1fr; }
  aside.vl-sidebar { position: static; height: auto; flex-direction: row; flex-wrap: wrap; align-items: center; gap: 4px; padding: 12px 14px; }
  .brand { margin-bottom: 0; margin-right: 8px; }
  .nav-sep, .side-help { display: none; }
  .nav-item { padding: 7px 11px; font-size: 13.5px; }
  main.content { padding: 16px 16px 60px; }
}

/* -------------------------------------------- 3. shared bits (copies) */

.chain-ico, .brand-ico {
  width: 26px; height: 26px; border-radius: 7px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 800; color: #000;
}
.cell-source { display: flex; align-items: center; gap: 10px; min-width: 0; }
.cell-source .cs-name { font-weight: 600; color: #fff; font-size: 13.5px; }
.cell-source .cs-sub { font-size: 11.5px; color: var(--vl-fg-dim); margin-top: 1px; }

/* Backfill line — the one approved component, verbatim from app.css. */
.bfl { margin-top: 10px; }
.bfl-top { display: flex; align-items: center; gap: 10px; margin-bottom: 7px; }
.bfl-what { font-size: 11.5px; color: var(--vl-fg-dim); }
.bfl-sp { flex: 1; }
.bfl-hint { font-size: 10.5px; color: var(--vl-fg-faint); white-space: nowrap; }
.bfl-step { font-family: var(--vl-ff-mono); font-size: 11.5px; color: var(--vl-fg-soft); white-space: nowrap; }
.bfl-step b { color: #fff; }
.bfl-pct { font-family: var(--vl-ff-mono); font-size: 11.5px; color: var(--vl-fg-dim); min-width: 34px; text-align: right; }
.bfl-track { height: 5px; border-radius: var(--vl-r-pill); background: rgba(255,255,255,0.08); overflow: hidden; }
.bfl-track i { display: block; height: 100%; border-radius: var(--vl-r-pill);
               background: var(--vl-lime); transition: width .6s var(--vl-ease); }
.bfl-track i.done { background: var(--vl-success); }
.bfl-track i.failed { background: var(--vl-danger); }
.bfl-under { display: flex; align-items: center; gap: 9px; margin-top: 7px; font-size: 11.5px; color: var(--vl-fg-dim); }
.bfl-now { color: var(--vl-fg-soft); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 55%; }
.bfl-sim { font-family: var(--vl-ff-mono); font-size: 9.5px; letter-spacing: .1em; text-transform: uppercase;
           color: var(--vl-warn); border: 1px solid rgba(249,212,73,0.35); border-radius: var(--vl-r-pill); padding: 1px 7px; }
.bfl-ago { white-space: nowrap; }
.bfl-pct.err { color: #F0A088; }
.bfl-recon { font-size: 11.5px; color: var(--vl-fg-dim); margin-top: 8px; padding-top: 9px;
             border-top: 1px solid var(--vl-stroke); }
/* Since "option A" a settled row drops the progress chrome, so the recon line
   is often the FIRST thing in the cell — its divider would then float at the
   top with nothing above it to divide. */
.bfl > .bfl-recon:first-child { margin-top: 0; padding-top: 0; border-top: 0; }

/* The single line a failed run still owes: where it stopped, and when. */
.bfl-failline { display: flex; align-items: center; gap: 7px; font-size: 11.5px; color: #F0A088; }
.bfl-failline svg { width: 13px; height: 13px; flex: none; stroke: currentColor; fill: none;
                    stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.bfl-failline .fl-what { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bfl-failline .fl-what b { color: #F6BCA8; font-weight: 600; }
.bfl-failline .fl-ago { color: var(--vl-fg-dim); white-space: nowrap; }
.bfl-recon b { color: var(--vl-fg-soft); font-weight: 600; }
.bfl-recon.ok b { color: var(--vl-success); }
.bfl-recon.stale { color: var(--vl-fg-faint); }
.bfl-recon.stale b { color: #F0A088; }
/* Reconciled books (2026-09-08): a connection with more than one book lists
   them under its recon line — label, verdict chip, honest window. */
/* Collapsed by default (2026-09-08): the summary is the scannable part, the
   per-book lines open on demand. Same chevron vocabulary as .inc-more. */
details.bfl-books { margin-top: 6px; font-size: 11.5px; color: var(--vl-fg-dim); }
details.bfl-books > summary {
  list-style: none; cursor: pointer; user-select: none;
  display: inline-flex; align-items: center; gap: 5px; padding: 2px 0;
}
details.bfl-books > summary::-webkit-details-marker { display: none; }
details.bfl-books > summary::before { content: '\25B8'; font-size: 9px; line-height: 1; }
details.bfl-books[open] > summary::before { content: '\25BE'; }
details.bfl-books > summary:hover { color: var(--vl-fg-soft); }
details.bfl-books > summary .warn { color: var(--vl-warn); }
/* 3px between 20px-tall filled pills read as one stacked block — the badge
   backgrounds all but touched. Space the rows to the pill's own rhythm. */
.bfl-books-list { display: grid; gap: 7px; margin-top: 7px; }
.bfl-book { display: flex; align-items: center; gap: 8px; min-width: 0; }
.bfl-book-label { flex: 0 0 9.5em; color: var(--vl-fg-soft); }
.bfl-book .badge { font-size: 10px; padding: 0 6px; line-height: 16px; }

/* ------------------------------------- 4. semantic badge tints (Velund) */
/* Basecoat badges know primary/secondary/outline/destructive; the sync
   vocabulary (ok / warn / error / running / idle) gets Velund tints. */
.badge.vl-ok    { color: var(--vl-success);   background: rgba(9,188,124,0.1);   border-color: transparent; }
.badge.vl-error { color: #F0A088;             background: rgba(215,108,74,0.12); border-color: transparent; }
.badge.vl-warn  { color: var(--vl-warn);      background: rgba(249,212,73,0.1);  border-color: transparent; }
.badge.vl-run   { color: var(--vl-info-cyan); background: rgba(44,216,222,0.1);  border-color: transparent; }
.badge.vl-idle  { color: var(--vl-fg-dim);    background: rgba(255,255,255,0.06); border-color: transparent; }
.badge .dot { width: 5px; height: 5px; border-radius: 50%; background: currentColor; margin-right: 5px; }
.badge.vl-run .dot { animation: vl-pulse 1.8s infinite; }
@keyframes vl-pulse { 50% { opacity: 0.25; } }

/* --------------------------------------------- 5. page-specific tuning */

/* Account rows: the ledger column may hold the .bfl line — let it breathe,
   but let long labels wrap so the table fits without a horizontal scroll. */
.table td { vertical-align: middle; }

/* Basecoat's .table-container is overflow-x: auto — a scroll container, so
   row menus opening inside it get clipped and grow an inner scrollbar (worst
   on short tables). overflow-x: clip still cuts horizontal overflow but is
   NOT a scroll container, so overflow-y stays truly visible and the menus
   float over the card. On narrow screens the scrollable behaviour returns
   (a wide table must stay reachable there). */
@media (min-width: 1100px) {
  .table-container { overflow-x: clip; overflow-y: visible; }
}

/* The card and the content column are the remaining menu-clippers: Basecoat
   cards are overflow: hidden, and an overflow-x that isn't `visible`/`clip`
   turns overflow-y into a scroll context. Neither may swallow a row menu. */
.card:has(.table-container), .card:has(.row-menu) { overflow: visible; }
main.content { overflow-x: clip; }

/* Data-table cards: the table IS the card. Basecoat's card padding is a
   24px vertical band with no horizontal inset — the header ends up floating
   below empty space with text 8px from the card edge. Flush instead, with
   real column insets.

   `> .table-container` (direct child) is load-bearing: without it any card that
   merely CONTAINS a table somewhere — e.g. Connectors' Delivery card, whose
   table sits inside a padded <section> — was flattened too, losing all vertical
   padding so its first line sat hard against the card's top edge. */
.card:has(> .table-container) { padding: 0; gap: 0; }
.table th { height: 42px; }
.table th, .table td { padding-inline: 12px; }
.table th:first-child, .table td:first-child { padding-inline-start: 16px; }
.table td { padding-block: 12px; }
.table td .bfl { margin-top: 0; min-width: 210px; max-width: 340px; }
.table td .cs-sub, .table td .cs-name { white-space: normal; overflow-wrap: anywhere; }
.table th:last-child, .table td:last-child { width: 1%; }

/* A table nested INSIDE a padded card section — rather than BEING the card, as
   on Accounts and Status — is already inset by that section. The first/last
   column inset above then stacks on top of it and the header text sits 16px to
   the right of every other label in the same card. Cancel it: the section
   already provides the gutter. (`.card > section` keeps flush table-cards,
   where the container is a direct child of the card, untouched.) */
.card > section .table th:first-child,
.card > section .table td:first-child { padding-inline-start: 0; }
.card > section .table th:last-child,
.card > section .table td:last-child { padding-inline-end: 0; }
.table tr.row-waiting td { background: rgba(249,212,73,0.03); }

/* Filter chips row */
.filter-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 14px; }
.filter-row .count { opacity: 0.6; font-weight: 400; margin-left: 4px; }

/* Provider fieldsets hidden until their provider is picked in the dialog */
[data-provider-fields][hidden], [data-type-form][hidden] { display: none; }

/* Row kebab menus sit at the table's right edge — open them leftwards. */
.row-menu { display: inline-flex; }
.row-menu [data-popover] { left: auto; right: 0; }

/* Menus float over dark-on-dark rows: give them the Velund pop shadow and a
   stronger stroke so they read as a layer (same treatment as the user menu). */
.dropdown-menu [data-popover] {
  box-shadow: var(--vl-shadow-pop);
  border-color: var(--vl-stroke-3);
}

/* Dialog: keep the connect forms comfortable */
dialog.dialog form .field + .field { margin-top: 12px; }
/* Field descriptions render like the provider note — small, dim, no negative
   margins (Basecoat's field rules pull them up into the next label). */
dialog.dialog .field > p {
  font-size: 11.5px; color: var(--vl-fg-dim);
  margin: 5px 0 0; line-height: 1.45;
}
/* The per-provider credential fields live in a wrapper div, so the plain
   .field + .field spacing rule skips them — space the wrapper itself. */
dialog.dialog [data-provider-fields]:not([hidden]) { margin-top: 12px; }
dialog.dialog [data-provider-fields] .field + .field { margin-top: 12px; }
dialog.dialog .type-switch { display: flex; gap: 8px; margin-bottom: 16px; }

/* IP allowlist strip inside the connect forms — compact by design */
.ip-allow {
  margin: 10px 0; padding: 7px 10px 8px; border-radius: var(--vl-r-md);
  border: 1px solid rgba(224,255,30,0.25); background: rgba(224,255,30,0.04);
}
.ip-allow .ipa-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  font-size: 12px; font-weight: 600; color: #EDFF9C; margin-bottom: 6px;
}
.ip-allow .ipa-head .btn { height: 22px; padding: 0 8px; font-size: 11.5px; }
.ip-allow .ipa-list { display: flex; flex-wrap: wrap; gap: 5px; }
.ip-allow .ipa-ip {
  font-size: 11.5px; padding: 2px 8px; border-radius: var(--vl-r-chip);
  background: rgba(255,255,255,0.05); border: 1px solid var(--vl-stroke-2);
  color: var(--vl-fg-soft);
}

/* Basecoat dialogs have no height cap — tall content ran off-screen with the
   fields below the fold unreachable. Cap and scroll inside instead. */
dialog.dialog > div { max-height: calc(100vh - 48px); overflow-y: auto; }

[data-family-note]:not([hidden]) { margin-top: 6px; }

/* ------------------------------------------------------ settings page */
.settings-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; align-items: start; }
.settings-col { display: flex; flex-direction: column; gap: 16px; }
@media (max-width: 1080px) { .settings-grid { grid-template-columns: 1fr; } }

.kv-list { display: flex; flex-direction: column; }
.kv { display: flex; align-items: baseline; justify-content: space-between; gap: 14px;
      padding: 7px 0; border-bottom: 1px solid var(--vl-stroke); font-size: 13px; }
.kv:last-child { border-bottom: 0; }
.kv .k { color: var(--vl-fg-dim); }

.sec-row { display: flex; align-items: center; gap: 10px; }
.sec-row > div:first-child { flex: 1; min-width: 0; }
.sec-title { font-weight: 600; color: #fff; font-size: 13.5px; margin-bottom: 2px; }

/* Statement hand-off rows: collapsed by default, "Fix it" reveals the lane. */
.stmt-fix summary { list-style: none; display: flex; align-items: center; gap: 10px;
                    cursor: pointer; padding: 6px 0; }
.stmt-fix summary::-webkit-details-marker { display: none; }
.stmt-fix-who { flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px;
                color: var(--vl-fg-soft); }
.stmt-fix[open] summary > .btn { visibility: hidden; }
.stmt-fix-body { padding: 2px 0 10px; }
.stmt-fix-body form { display: inline-flex; gap: 6px; align-items: center; margin-top: 8px; }
.stmt-fix-body .input { max-width: 260px; padding: 4px 8px; }

/* Padded footer under a flush table-card (pager row on Status). */
.table-foot { padding: 10px 16px; border-top: 1px solid var(--vl-stroke); }
.table-foot .pager { margin: 0; }

.sess-row { display: flex; align-items: center; gap: 12px; padding: 9px 0;
            border-bottom: 1px solid var(--vl-stroke); }
.sess-row:last-child { border-bottom: 0; }
.sess-main { flex: 1; min-width: 0; }
.sess-ip { color: var(--vl-fg-soft); display: flex; align-items: center; gap: 8px; }

/* ------------------------------------------------------- status board */
.status-banner {
  display: flex; align-items: center; gap: 10px; font-weight: 600; font-size: 14px;
  border-radius: var(--vl-r-md); padding: 12px 16px; margin-bottom: 8px;
}
.status-banner .dot { width: 8px; height: 8px; border-radius: 50%; background: currentColor; }
.status-banner.ok   { color: var(--vl-success); background: rgba(9,188,124,0.08);
                      border: 1px solid rgba(9,188,124,0.3); }
.status-banner.warn { color: var(--vl-warn); background: rgba(249,212,73,0.07);
                      border: 1px solid rgba(249,212,73,0.35); }

.section-head { color: #fff; font-size: 15px; font-weight: 700; margin: 22px 0 10px; }

/* X-3 (2026-09-07): a failed job's detail now names every failing dataset
   ("13 dataset error(s): ..."). It WRAPS — the whole stored string (250 chars)
   has to be readable; a one-line clamp would stop at the first name. */
.job-detail { margin-top: 5px; font-size: 11.5px; line-height: 1.45;
              color: var(--vl-fg-dim); white-space: normal;
              overflow-wrap: anywhere; max-width: 52ch; }
.status-grid { display: grid; gap: 8px;
               grid-template-columns: repeat(auto-fill, minmax(215px, 1fr)); }
.comp-card {
  display: flex; align-items: center; gap: 9px; min-width: 0;
  background: var(--vl-bg-card); border: 1px solid var(--vl-stroke);
  border-radius: var(--vl-r-md); padding: 9px 11px;
}
.comp-card .comp-name { flex: 1; min-width: 0; font-size: 12.5px; font-weight: 600;
                        color: var(--vl-fg-soft); overflow: hidden;
                        text-overflow: ellipsis; white-space: nowrap; }
.comp-card.dim { opacity: 0.55; }
.comp-card .brand-ico { width: 22px; height: 22px; font-size: 10px; border-radius: 6px; }
.brand-ico img { width: 62%; height: 62%; display: block; }

.pager { display: flex; align-items: center; gap: 12px; justify-content: center;
         padding: 10px 0 2px; border-top: 1px solid var(--vl-stroke); margin-top: 8px; }

.incident-feed section { padding-top: 4px; }
.inc-day { font-size: 12px; font-weight: 700; letter-spacing: 0.04em; color: var(--vl-fg-dim);
           text-transform: uppercase; padding: 12px 0 4px; border-bottom: 1px solid var(--vl-stroke);
           margin-bottom: 10px; }
.incident { margin-bottom: 16px; }
.inc-title { font-size: 14.5px; font-weight: 700; margin-bottom: 8px;
             display: flex; align-items: center; gap: 10px; }
.inc-title.sev-degraded { color: var(--vl-warn); }
.inc-title.sev-outage   { color: #F0A088; }
.inc-update { font-size: 13px; color: var(--vl-fg-soft); margin-bottom: 7px; }
.inc-update b { color: #fff; }
.inc-ts { font-size: 11.5px; color: var(--vl-fg-dim); margin-top: 2px; }
.inc-more summary {
  cursor: pointer; font-size: 11.5px; color: var(--vl-fg-dim);
  list-style: none; padding: 2px 0 6px; user-select: none;
}
.inc-more summary::before { content: '▸ '; }
.inc-more[open] summary::before { content: '▾ '; }
.inc-more summary::-webkit-details-marker { display: none; }
.inc-more summary:hover { color: var(--vl-fg-soft); }
.incident { margin-bottom: 12px; }

.tfs-secret { display: flex; align-items: center; gap: 8px; font-size: 12px;
              overflow-wrap: anywhere; color: var(--vl-fg-soft); margin-bottom: 10px; }
.tfs-form { display: flex; gap: 8px; align-items: center; }
/* 2FA setup as a dialog (2026-09-11): QR on a white tile, secret, code. */
.tfs-dialog { display: flex; flex-direction: column; align-items: stretch; }
.tfs-dialog .tfs-qr { display: flex; justify-content: center; }
.tfs-dialog .tfs-qr img { background: #fff; padding: 10px; border-radius: 12px;
                          border: 1px solid var(--vl-stroke); display: block; }
.tfs-dialog .tfs-noqr { padding: 24px; text-align: center; border: 1px dashed var(--vl-stroke);
                        border-radius: 12px; }
.tfs-dialog .tfs-form { margin-top: 10px; }

/* =============================================================
   6. Screens migrated off app.css (2026-09-08)

   Overview / Balances / Cash flows / Reconciliation / Reports /
   Wallets / Connect / auth moved from the app.css shell to this one.
   Basecoat owns the primitives (.card, .table, .btn, .badge, .input);
   what follows is only what Basecoat has no equivalent for, ported
   from app.css and re-pointed at the Velund tokens.
   ============================================================= */

/* ------------------------------------------------ table-card headers */
/* Section 5 flattens a card that holds a .table-container so the table IS
   the card. A header inside one then sits flush against the first row with
   no breathing room, and Basecoat's 24px inline padding does not line up
   with the table's 16px first-column inset. Restore both deliberately. */
.card:has(> .table-container) > header { padding: 18px 16px 14px; }
.card:has(> .table-container) > section { padding-inline: 16px; }
.card:has(> .table-container) > header + .table-container { border-top: 1px solid var(--vl-stroke); }

/* Basecoat parks a .card-action in the header's right-hand column at the top;
   a one-line chip ("Sample data") reads better centred against the two-line
   title+caption block. */
.card > header > .card-action.sample-chip,
.card > header > a.card-action,
.card > header > span.card-action { place-self: center flex-end; }

/* --------------------------------------------------- numeric tables */
/* Financial columns are read by scanning down, so they align right and
   share one tabular figure width; colour carries the sign. */
.table th.right, .table td.right, .table .num { text-align: right; }
.table .num {
  font-variant-numeric: tabular-nums;
  white-space: nowrap; color: var(--vl-fg-soft);
}
.table .num.pos  { color: var(--vl-success); }
.table .num.neg  { color: #E4785A; }
.table .num.mute { color: var(--vl-fg-dim); }
.table tr.tot td {
  border-top: 1px solid var(--vl-stroke-3); border-bottom: 0;
  font-weight: 700; color: #fff;
}
.table .dim { color: var(--vl-fg-dim); }

/* ------------------------------------------------------- stat cards */
.stats-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin-bottom: 24px; }
.card + .stats-row { margin-top: 24px; }
.stat-card {
  background: var(--vl-bg-card); border-radius: var(--vl-r-lg);
  padding: 17px 20px; border: 1px solid var(--vl-stroke);
}
.stat-card .cap {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.1em;
  color: var(--vl-fg-dim); margin-bottom: 9px; font-weight: 600;
}
.stat-card .val {
  font-family: var(--vl-ff-display); font-weight: 700; color: #fff;
  font-size: 25px; letter-spacing: -0.01em; line-height: 1;
}
.stat-card .val small { font-size: 13px; color: var(--vl-fg-dim); font-weight: 600; margin-left: 4px; }
.stat-card .val.good { color: var(--vl-success); }

/* ---------------------------------------------------- column layouts */
.panel-row { display: grid; grid-template-columns: 2fr 1fr; gap: 16px; align-items: start; }
.grid-2    { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; align-items: start; }
@media (max-width: 1080px) {
  .stats-row { grid-template-columns: repeat(2, 1fr); }
  .panel-row, .grid-2 { grid-template-columns: 1fr; }
}

/* ------------------------------------------------ onboarding checklist */
.steps { display: flex; flex-direction: column; }
.step {
  display: flex; align-items: center; gap: 13px; padding: 11px 2px;
  border-bottom: 1px solid var(--vl-stroke); text-decoration: none;
}
.step:last-child { border-bottom: 0; }
.step .s-idx {
  width: 26px; height: 26px; border-radius: 50%; flex: none;
  display: flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 800;
  border: 1.5px solid var(--vl-stroke-3); color: var(--vl-fg-dim);
}
.step.done .s-idx { background: var(--vl-lime); border-color: var(--vl-lime); color: var(--vl-bg-ink); }
.step .s-text b { display: block; color: #fff; font-size: 13.5px; }
.step .s-text span { font-size: 12px; color: var(--vl-fg-dim); }
.step.done .s-text b { color: var(--vl-fg-dim); text-decoration: line-through; }
.step .s-go { margin-left: auto; color: var(--vl-fg-dim); font-size: 15px; }
.step:hover:not(.done) .s-go { color: var(--vl-lime); }
/* Guided setup (connectors): a step row, then its instructions underneath.
   The row border moves to the block so the body sits inside the same band. */
.step-block { border-bottom: 1px solid var(--vl-stroke); }
.step-block:last-child { border-bottom: 0; }
.step-block > .step { border-bottom: 0; }
.step-block .s-text { min-width: 0; }
.step-block .s-text span code { font-size: 11.5px; }
.step .s-action { margin-left: auto; flex: none; }
.step-body { padding: 0 0 14px 41px; }
.step-body p { margin: 0; }
.cmd-row { display: flex; gap: 8px; align-items: flex-start; margin-top: 8px; }
.cmd-row .btn { flex: none; }
pre.cmd {
  flex: 1; min-width: 0; margin: 0; overflow-x: auto; white-space: pre;
  font-family: var(--vl-ff-data); font-size: 11.5px; line-height: 1.55; color: var(--vl-fg-soft);
  background: rgba(255,255,255,0.04); border: 1px solid var(--vl-stroke); border-radius: 8px; padding: 9px 12px;
}
/* Setup tracker inside the provider card: each row opens its step dialog. */
.setup-steps { display: flex; flex-direction: column; margin: 2px 0 14px; border-top: 1px solid var(--vl-stroke); }
.setup-step {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  padding: 9px 2px; border: 0; border-bottom: 1px solid var(--vl-stroke); background: none;
  color: #fff; font: inherit; font-size: 13px; cursor: pointer; min-width: 0;
}
.setup-step:hover { background: rgba(255,255,255,0.03); }
.setup-step:focus-visible { outline: 2px solid var(--vl-lime); outline-offset: -2px; }
.setup-step .s-idx {
  width: 22px; height: 22px; border-radius: 50%; flex: none; font-size: 11px; font-weight: 800;
  display: flex; align-items: center; justify-content: center;
  border: 1.5px solid var(--vl-stroke-3); color: var(--vl-fg-dim);
}
.setup-step.done .s-idx { background: var(--vl-lime); border-color: var(--vl-lime); color: var(--vl-bg-ink); }
.setup-step .ss-name { flex: 1; min-width: 0; }
.setup-step.done .ss-name { color: var(--vl-fg-dim); }
.setup-step .ss-state { font-size: 11.5px; color: var(--vl-fg-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 55%; }
.setup-step .ss-state code { font-size: 11px; }
.check-result {
  margin-top: 12px; padding: 10px 12px; border-radius: 8px; font-size: 13px; line-height: 1.5;
  border: 1px solid var(--vl-stroke); color: var(--vl-fg-soft); background: rgba(255,255,255,0.03);
}
.check-result.ok { border-color: rgba(52,211,153,0.35); }
.check-result.bad { border-color: rgba(248,113,113,0.4); }
dialog.dialog.dialog-wide > div { max-width: 780px; }
.grant-lines { display: grid; gap: 6px; margin-bottom: 10px; }
.grant-line { display: flex; align-items: center; gap: 10px; min-width: 0; font-size: 13px; }
.grant-line .gl-k { width: 70px; flex: none; font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.1em; color: var(--vl-fg-dim); }
.grant-line code.gl-v {
  font-family: var(--vl-ff-data); font-size: 12px; color: #fff; overflow-wrap: anywhere;
  background: rgba(255,255,255,0.05); border: 1px solid var(--vl-stroke); border-radius: 6px; padding: 3px 8px;
}
.sql-details summary { cursor: pointer; display: flex; align-items: center; gap: 10px; font-size: 13px; color: var(--vl-fg-soft); }
.sql-details summary .btn { margin-left: auto; }
.sql-details[open] summary { margin-bottom: 8px; }
.vl-run { color: var(--vl-run, var(--vl-warn)); }

/* ------------------------------------------------- connection rows */
.conn-list { display: flex; flex-direction: column; gap: 10px; }
.conn-row {
  display: flex; align-items: center; gap: 13px;
  background: rgba(0,0,0,0.25); border: 1px solid var(--vl-stroke);
  border-radius: 10px; padding: 12px 14px; flex-wrap: wrap;
}
.conn-row .c-main { min-width: 140px; flex: 1; }
.conn-row .c-label { font-weight: 700; color: #fff; font-size: 13.5px; }
.conn-row .c-sub { font-size: 11.5px; color: var(--vl-fg-dim); margin-top: 1px; }

/* --------------------------------------------- headline figure + chip */
.big-metric { display: flex; align-items: baseline; gap: 12px; margin: 2px 0 16px; }
.big-metric .bm-val {
  font-family: var(--vl-ff-display); font-weight: 700; color: #fff;
  font-size: 38px; letter-spacing: -0.02em; white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.big-metric .bm-delta { font-size: 12.5px; color: var(--vl-success); font-variant-numeric: tabular-nums; }

/* "Sample data" / "soon" — the honesty marker on placeholder content. */
.sample-chip {
  display: inline-flex; align-items: center; gap: 6px; width: fit-content;
  font-size: 9.5px; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--vl-warn); border: 1px solid rgba(249,212,73,0.4);
  border-radius: var(--vl-r-pill); padding: 3px 10px; white-space: nowrap;
}

/* The dashed "this fills in once you connect something" strip. */
.fill-note {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  border: 1px dashed rgba(185,185,185,0.25); border-radius: var(--vl-r-lg);
  padding: 16px 20px; color: var(--vl-fg-dim); font-size: 13.5px; margin-bottom: 18px;
}
.fill-note b { color: var(--vl-fg-soft); }
.fill-note .btn { margin-left: auto; }

/* -------------------------------------------- reconciliation workbench */
.recon-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.recon-col .rc-head {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.1em;
  color: var(--vl-fg-dim); font-weight: 600; margin-bottom: 8px;
}
.recon-row {
  display: flex; align-items: center; gap: 10px;
  background: rgba(0,0,0,0.25); border: 1px solid var(--vl-stroke);
  border-radius: 9px; padding: 10px 13px; margin-bottom: 8px; font-size: 12.5px;
}
.recon-row .rr-main { min-width: 0; flex: 1; }
.recon-row .rr-title { color: #fff; font-weight: 600; }
.recon-row .rr-sub { font-size: 10.5px; color: var(--vl-fg-dim); margin-top: 2px; overflow-wrap: anywhere; }
.recon-row .rr-amt { font-size: 12px; white-space: nowrap; font-variant-numeric: tabular-nums; }
.recon-row .rr-amt.neg { color: #E4785A; }
.recon-row .rr-amt.mute { color: var(--vl-fg-dim); }
.recon-row.matched   { border-color: rgba(9,188,124,0.35); }
.recon-row.suggested { border-color: rgba(249,212,73,0.4); }
@media (max-width: 1080px) { .recon-grid { grid-template-columns: 1fr; } }

/* ------------------------------------------------------ report tiles */
.choose-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
.choose-card {
  display: flex; flex-direction: column; gap: 10px; text-decoration: none;
  background: var(--vl-bg-card); border: 1px solid var(--vl-stroke);
  border-radius: var(--vl-r-lg); padding: 22px;
}
.choose-card svg { width: 26px; height: 26px; stroke: var(--vl-lime); fill: none; stroke-width: 1.7; }
.choose-card b { color: #fff; font-size: 15px; }
.choose-card span { color: var(--vl-fg-dim); font-size: 12.5px; line-height: 1.5; }
.choose-card:hover { border-color: var(--vl-stroke-2); }
.choose-card.locked svg { stroke: var(--vl-fg-dim); }
.choose-card .sample-chip { margin-top: auto; color: var(--vl-bg-ink); background: var(--vl-lime); border-color: transparent; }
@media (max-width: 1080px) { .choose-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 760px)  { .choose-grid { grid-template-columns: 1fr; } }

/* ------------------------------------------------- addresses + copy */
.addr { display: inline-flex; align-items: center; gap: 7px; min-width: 0; }
.addr a { color: var(--vl-fg-soft); text-decoration: none; border-bottom: 1px dotted rgba(255,255,255,0.25); }
.addr a:hover { color: var(--vl-lime); border-color: var(--vl-lime); }
.copy-btn {
  background: none; border: 0; cursor: pointer; color: var(--vl-fg-dim);
  padding: 2px; line-height: 0; flex: none;
}
.copy-btn:hover { color: var(--vl-lime); }
.copy-btn svg { width: 13px; height: 13px; stroke: currentColor; fill: none; stroke-width: 2; }
.copy-btn.copied { color: var(--vl-lime); }

/* Inline sync progress inside a table cell (wallets). */
.prog { width: 130px; height: 5px; border-radius: var(--vl-r-pill);
        background: rgba(255,255,255,0.08); overflow: hidden; }
.prog i { display: block; height: 100%; background: var(--vl-lime);
          border-radius: var(--vl-r-pill); transition: width .6s var(--vl-ease); }
.prog i.done   { background: var(--vl-success); }
.prog i.failed { background: var(--vl-danger); }

/* ------------------------------------------------------ empty states */
.empty {
  border: 2px dashed rgba(185,185,185,0.22); border-radius: 10px;
  padding: 38px 20px; text-align: center; color: var(--vl-fg-dim); font-size: 13.5px;
}
.empty b { color: var(--vl-fg-soft); display: block; margin-bottom: 4px; font-size: 14.5px; }
.empty .btn { margin-top: 14px; }

/* ----------------------------------------------------- form extras */
/* Basecoat styles .field/.input; these are the bits it has no name for. */
.field .hint, .hint { font-size: 11.5px; color: var(--vl-fg-dim); margin-top: 5px; line-height: 1.5; }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.form-row .field { margin: 0; }
.form-actions { display: flex; gap: 10px; align-items: center; margin-top: 18px; }
.form-error {
  background: rgba(215,108,74,0.09); border: 1px solid rgba(215,108,74,0.4);
  color: #F0A088; border-radius: var(--vl-r-md); padding: 10px 13px;
  font-size: 13px; margin-bottom: 15px;
}
@media (max-width: 900px) { .form-row { grid-template-columns: 1fr; } }

/* Collapsible add-forms (wallets). The summary IS the button, so strip the
   marker and let the .btn inside it carry the affordance. */
details.reveal { margin-bottom: 14px; }
details.reveal > summary { list-style: none; cursor: pointer; display: inline-flex; }
details.reveal > summary::-webkit-details-marker { display: none; }
details.reveal[open] > summary { margin-bottom: 12px; }
/* The summary wraps a <span class="btn"> rather than a <button> (a button
   inside a summary swallows the toggle), so give it the button's hover. */
details.reveal > summary .btn { pointer-events: none; }
details.reveal > summary:hover .btn[data-variant="outline"] { background: var(--vl-bg-card-2); }

/* Inline row actions at a table's right edge. */
.row-actions { display: inline-flex; gap: 6px; justify-content: flex-end; align-items: center; }
.row-actions form { margin: 0; }
.btn.btn-danger { color: var(--vl-danger); }
.btn.btn-danger:hover { background: rgba(215,108,74,0.12); color: #F0A088; }

/* =========================================== 7. auth pages (no shell) */
/* Sign-in / sign-up render outside the app frame: a single centred card on
   the app ground. base_auth.html loads Basecoat + this file, so the card
   contents (.field, .input, .btn) are Basecoat's; only the frame is ours. */
body.auth-body {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  min-height: 100vh; padding: 30px 16px;
  background:
    radial-gradient(600px 320px at 50% -80px, rgba(224,255,30,0.06), transparent 70%),
    var(--vl-bg-app);
}
.auth-card {
  width: 100%; max-width: 420px; background: var(--vl-bg-card);
  border: 1px solid var(--vl-stroke-2); border-radius: var(--vl-r-xl);
  padding: 34px 34px 28px; box-shadow: var(--vl-shadow-pop);
}
.auth-brand { display: flex; align-items: center; justify-content: center; gap: 11px; margin-bottom: 22px; }
.auth-brand img { width: 34px; height: 34px; }
.auth-brand .brand-name {
  font-family: var(--vl-ff-display); font-weight: 800; font-size: 24px; color: #fff;
  letter-spacing: -0.01em;
}
.auth-card h1 { font-size: 19px; color: #fff; margin: 0 0 4px; text-align: center; font-weight: 700; }
.auth-card .auth-sub {
  font-size: 13px; color: var(--vl-fg-dim); text-align: center;
  margin: 0 0 22px; line-height: 1.5;
}
.auth-card .field + .field { margin-top: 14px; }
.auth-card form > .btn { width: 100%; justify-content: center; margin-top: 18px; }
.auth-alt { text-align: center; font-size: 13px; color: var(--vl-fg-dim); margin-top: 18px; }
.auth-alt a { color: var(--vl-lime); text-decoration: none; font-weight: 600; }
.auth-alt a:hover { text-decoration: underline; }
.auth-foot { margin-top: 26px; font-size: 11.5px; color: var(--vl-fg-faint); text-align: center; }
.auth-foot a { color: inherit; }

/* ------------------------------------ alert with a text action (2026-09-08) */
/* Basecoat's `.alert > footer` is position:absolute and reserves a flat 4.5rem
   inline-end padding — sized for a dismiss ✕, not for a labelled button. A
   147px "Review 7 accounts" therefore sat ON TOP of the heading and body text,
   and simply widening the reserve breaks again the moment the count reaches
   double digits. Give the action a real grid column instead: the text can
   never run under it at any label length.
   Usage: <div class="alert vl-alert-cta"> svg, h2, section, <div class="cta">. */
.alert.vl-alert-cta { padding-inline-end: calc(var(--spacing) * 4); }
.alert.vl-alert-cta:has(> svg) { grid-template-columns: auto 1fr auto; }
/* section is auto-placed, so without this it lands in the new third column. */
.alert.vl-alert-cta > section { grid-column: 2; }
.alert.vl-alert-cta > .cta {
  grid-column: 3; grid-row: 1 / span 2;
  align-self: center; justify-self: end;
  padding-left: 16px; white-space: nowrap;
}
/* Narrow: the action drops under the text rather than squeezing it. */
@media (max-width: 720px) {
  .alert.vl-alert-cta:has(> svg) { grid-template-columns: auto 1fr; }
  .alert.vl-alert-cta > .cta {
    grid-column: 2; grid-row: auto;
    justify-self: start; padding-left: 0; margin-top: 10px;
  }
}

/* Statement list inside the review dialog: one row per account, divided.
   Basecoat's default dialog is ~426px, which crams `name · venue [Attach…]`
   onto one line; these rows need the room. */
dialog.dialog:has(.stmt-list) > div { max-width: 560px; width: calc(100vw - 48px); }
.stmt-list .stmt-fix { border-bottom: 1px solid var(--vl-stroke); }
.stmt-list .stmt-fix:last-child { border-bottom: 0; }
.stmt-list .stmt-fix summary { padding: 10px 0; }
.stmt-list .stmt-fix .brand-ico { width: 22px; height: 22px; border-radius: 6px; }

/* ------------------------------------------- file attach (2026-09-08) */
/* Basecoat has NO file-upload component — it only styles input[type=file] as a
   plain box, leaving the browser's native "Choose Files / No file chosen".
   That string is misleading (two labels run together, the empty state reads as
   an error, it never says what to attach) and differs per browser. So: hide the
   native control, drive it from a real <label> button, and render the state
   ourselves. Drop-to-attach comes free and suits a "send us the export" flow. */
.vl-file {
  position: relative; display: inline-flex; align-items: center; gap: 10px;
  max-width: 100%; padding: 6px 10px 6px 6px;
  border: 1px dashed var(--vl-stroke-3); border-radius: var(--vl-r-md);
  transition: border-color var(--vl-dur-1) var(--vl-ease),
              background var(--vl-dur-1) var(--vl-ease);
}
.vl-file:hover { border-color: rgba(255,255,255,0.32); }
.vl-file.dragover { border-color: var(--vl-lime); background: rgba(224,255,30,0.06); }
/* Visually hidden, still focusable and still the submitted control. */
.vl-file > input[type="file"] {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.vl-file > label.btn { cursor: pointer; flex: none; }
.vl-file > input[type="file"]:focus-visible + label.btn {
  outline: 2px solid var(--ring); outline-offset: 2px;
}
.vl-file-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vl-file.has-files { border-style: solid; }
.vl-file.has-files .vl-file-name { color: var(--vl-fg-soft); }

/* ------------------------------------------------ connectors (2026-09-08) */
/* Destination tiles. All setup lives behind the Connect button in a dialog —
   the same shape as adding a venue on Accounts — so nothing on the card is a
   form and the page reads as a choice, not a settings screen. */
.dest-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 22px; }
@media (max-width: 1080px) { .dest-grid { grid-template-columns: 1fr; } }

.dest-card {
  display: flex; flex-direction: column; min-width: 0;
  background: var(--vl-bg-card); border: 1px solid var(--vl-stroke);
  border-radius: var(--vl-r-lg); padding: 17px 19px;
  transition: border-color var(--vl-dur-2) var(--vl-ease);
}
.dest-card:not(.dim):hover { border-color: var(--vl-stroke-2); }
.dest-card.dim { opacity: 0.62; }
.dest-head { display: flex; align-items: center; gap: 11px; margin-bottom: 11px; }
.dest-head .brand-ico { width: 36px; height: 36px; border-radius: 9px; font-size: 15px; }
/* Full-colour platform marks (devicon) keep their own fills on a white chip, so
   they are never inverted like the monochrome venue marks. The AWS mark is a
   wordmark rather than a glyph and goes illegible at the 62% the tinted chips
   use, so these fill more of the tile. */
.dest-head .brand-ico img { width: 80%; height: 80%; object-fit: contain; }
.dest-name { flex: 1; min-width: 0; }
.dest-title { font-weight: 700; color: #fff; font-size: 14.5px; }
.dest-sub { font-size: 11.5px; color: var(--vl-fg-dim); margin-top: 1px; }
.dest-body { font-size: 12.5px; color: var(--vl-fg-dim); line-height: 1.55; margin: 0 0 14px; }
.dest-foot { display: flex; align-items: center; gap: 10px; margin-top: auto; }
.dest-uri {
  flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Numbered steps — used in the connect dialog, because granting access and
   naming the bucket are two acts in an order, not two fields. */
.gcs-step { display: flex; gap: 13px; align-items: flex-start; }
.gcs-step + .gcs-step {
  margin-top: 18px; padding-top: 18px; border-top: 1px solid var(--vl-stroke);
}
.gcs-step > div { min-width: 0; flex: 1; }
.card.prep { border: 1px solid rgba(224,255,30,0.22); }
.prep-n {
  width: 24px; height: 24px; border-radius: 50%; flex: none;
  display: flex; align-items: center; justify-content: center;
  background: var(--vl-lime); color: var(--vl-bg-ink); font-weight: 800; font-size: 12px;
}
.table code, .kv code, .card code {
  background: rgba(255,255,255,0.06); border-radius: 4px;
  padding: 1px 6px; font-size: 11.5px; color: #EDFF9C;
}
