/* ================================================================
   Waypoint — style.css  (structure & style: sunday.ai)
   Palette: #FFF · #E5E5E5 · #A1DCFE · #262626
   Grid: 6 columns · 40px margins · 20px gutters · full width
   ================================================================ */

/* ---------- Fonts ----------
   ascent/descent overrides recenter Helvetica Neue vertically:
   measured cap height = 0.712em, so ascent − descent must equal it
   (0.86 − 0.14 = 0.72) or caps sit high in every centered box. */
@font-face {
  font-family: "Helvetica Neue W";
  src: url("../assets/fonts/HelveticaNeue-Roman.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  ascent-override: 86%;
  descent-override: 14%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Helvetica Neue W";
  src: url("../assets/fonts/HelveticaNeue-Medium.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
  ascent-override: 86%;
  descent-override: 14%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Helvetica Neue W";
  src: url("../assets/fonts/HelveticaNeue-Bold.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
  ascent-override: 86%;
  descent-override: 14%;
  line-gap-override: 0%;
}

/* ---------- Tokens ---------- */
:root {
  --white: #ffffff;
  --grey: #e5e5e5;
  --card: #f2f2f2;   /* card surfaces (lighter than --grey) */
  /* span between the ‹ › brackets — shared by the preloader logo and the hero
     so the blink hand-off is seamless. The word font caps at 140px (~573px wide)
     around 1647px, so the span must already clear it there: 51vw hits ~840px at
     that point, and it caps at 900px on wider screens. */
  --hero-span: clamp(520px, 51vw, 900px);
  --sky: #a1dcfe;
  --ink: #262626;

  --margin: 40px;   /* grid margin */
  --gutter: 20px;   /* grid gutter */
  --bleed: 40px;    /* inset for full-width media cards */

  --r-lg: 18px;
  --r-md: 14px;

  --ease: cubic-bezier(0.22, 1, 0.36, 1);
}


/* ================================================================
   COLOUR TOKENS (2026-09-02). Every colour in this app derives from these.
   Two RGB bases (ink, white) carry every tint; the alpha tiers are the ONLY
   greys allowed; semantic colours are named once. The dark theme (below)
   swaps the bases and surfaces — nothing else has to know.
   ================================================================ */
:root {
  --ink-rgb: 38, 38, 38;
  --white-rgb: 255, 255, 255;
  --ink-2: #333333;                      /* ink, lifted: hover on black surfaces */
  /* text tiers */
  --text-2: rgba(var(--ink-rgb), 0.7);   /* secondary copy */
  --text-3: rgba(var(--ink-rgb), 0.5);   /* muted: labels, captions, meta */
  --text-4: rgba(var(--ink-rgb), 0.4);   /* faint: placeholders, disabled */
  /* surfaces on white */
  --mute-fill: rgba(var(--ink-rgb), 0.28);   /* tracks, idle marks */
  --wash-2: rgba(var(--ink-rgb), 0.12);      /* pressed / selected wash */
  --line: rgba(var(--ink-rgb), 0.08);        /* hairlines, borders */
  --wash: rgba(var(--ink-rgb), 0.06);        /* hover wash, chip fill */
  /* shadows */
  --scrim: rgba(0, 0, 0, 0.45);          /* modal / drawer backdrops: always darken, in both themes */
  --shadow-1: rgba(var(--ink-rgb), 0.06);
  --shadow-2: rgba(var(--ink-rgb), 0.12);
  /* semantic */
  --ok: #30a46c;
  --ok-bright: #28c840;
  --ok-deep: #22a04a;
  --bad: #e5484d;
  --bad-bright: #ff5f57;
  --warn: #febc2e;
  --ok-wash: rgba(40, 200, 64, 0.06);   --ok-wash-2: rgba(40, 200, 64, 0.12);   --ok-text: #1c7c33;
  --bad-wash: rgba(229, 72, 77, 0.10);   --sky-wash: rgba(161, 220, 254, 0.35);
  --sky-2: #cdeeff;
  --sky-3: #d8effd;
  /* Apple system colours — light */
  --sys-red: #ff3b30; --sys-orange: #ff9500; --sys-yellow: #ffcc00; --sys-green: #34c759;
  --sys-mint: #00c7be; --sys-teal: #30b0c7; --sys-cyan: #32ade6; --sys-blue: #007aff;
  --sys-indigo: #5856d6; --sys-purple: #af52de; --sys-pink: #ff2d55; --sys-brown: #a2845e; --sys-gray: #8e8e93;
  color-scheme: light;
}
/* ---- dark ---- */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --white: #141414; --white-rgb: 20, 20, 20;
    --ink: #f2f2f2;   --ink-rgb: 242, 242, 242;
    --grey: #2a2a2a;  --card: #1c1c1c;
    --ink-2: #dcdcdc;
    --shadow-1: rgba(0, 0, 0, 0.35); --shadow-2: rgba(0, 0, 0, 0.5); --scrim: rgba(0, 0, 0, 0.65);
    --sys-red: #ff453a; --sys-orange: #ff9f0a; --sys-yellow: #ffd60a; --sys-green: #30d158;
    --sys-mint: #63e6e2; --sys-teal: #40c8e0; --sys-cyan: #64d2ff; --sys-blue: #0a84ff;
    --sys-indigo: #5e5ce6; --sys-purple: #bf5af2; --sys-pink: #ff375f; --sys-brown: #ac8e68; --sys-gray: #8e8e93;
    /* the app's states in the dark set: same hues, lifted for a dark ground */
    --ok: #3ddc84; --bad: #ff5c62; --warn: #ffd166; --ok-text: #7fe0a3;
    color-scheme: dark;
  }
}
:root[data-theme="dark"] {
  --white: #141414; --white-rgb: 20, 20, 20;
  --ink: #f2f2f2;   --ink-rgb: 242, 242, 242;
  --grey: #2a2a2a;  --card: #1c1c1c;
  --ink-2: #dcdcdc;
  --shadow-1: rgba(0, 0, 0, 0.35); --shadow-2: rgba(0, 0, 0, 0.5); --scrim: rgba(0, 0, 0, 0.65);
  --sys-red: #ff453a; --sys-orange: #ff9f0a; --sys-yellow: #ffd60a; --sys-green: #30d158;
  --sys-mint: #63e6e2; --sys-teal: #40c8e0; --sys-cyan: #64d2ff; --sys-blue: #0a84ff;
  --sys-indigo: #5e5ce6; --sys-purple: #bf5af2; --sys-pink: #ff375f; --sys-brown: #ac8e68; --sys-gray: #8e8e93;
  /* the app's states in the dark set: same hues, lifted for a dark ground */
  --ok: #3ddc84; --bad: #ff5c62; --warn: #ffd166; --ok-text: #7fe0a3;
  color-scheme: dark;
}
/* black artwork on a dark ground: protocol marks and venue logos invert */
:root[data-theme="dark"] img.act-logo, :root[data-theme="dark"] .pdir-logo img, :root[data-theme="dark"] .svc-logo img,
:root[data-theme="dark"] .modal-logo img, :root[data-theme="dark"] .venue-mark img { filter: invert(1); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) img.act-logo, :root:not([data-theme="light"]) .pdir-logo img, :root:not([data-theme="light"]) .svc-logo img,
  :root:not([data-theme="light"]) .modal-logo img, :root:not([data-theme="light"]) .venue-mark img { filter: invert(1); }
}

* { margin: 0; padding: 0; box-sizing: border-box; }
html { scroll-behavior: smooth; }
html.lock { overflow: hidden; }
body {
  font-family: "Helvetica Neue W", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 400;
  color: var(--ink);
  background: var(--white); /* == the site: the footer underlay is .egg (site-shell.css), not the body */
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}
a { color: inherit; text-decoration: none; }
/* Form controls take the page face. Without this every button, select and input fell back
   to the UA default (Arial) — the app's most visible type bug until 2026-09-02. */
button, input, select, textarea { font: inherit; }
video { display: block; }
::selection { background: var(--sky); color: var(--ink); }

/* the white page container — contracts near the footer (see main.js) */
.page {
  background: var(--white);
  position: relative;
}

/* ---------- Layout primitives ---------- */
.grid {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  column-gap: var(--gutter);
  width: 100%;
  padding-inline: var(--margin);
}
.bleed { padding-inline: var(--bleed); width: 100%; }

.media-card {
  position: relative;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--grey);
}
.media-card > video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  position: absolute;
  inset: 0;
}

.chip {
  position: absolute;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--white);
  background: var(--text-3);
  backdrop-filter: blur(8px);
  padding: 8px 13px;
  border-radius: 999px;
  white-space: nowrap;
}
.chip-top { top: 14px; left: 14px; }
.chip-bottom { bottom: 14px; left: 14px; }
.chip-play { top: 50%; left: 50%; translate: -50% -50%; }

.card-label { font-size: 12px; line-height: 16px; font-weight: 500; letter-spacing: 0.01em; }
.card-body { font-size: 14px; line-height: 20px; }

.reveal {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.9s var(--ease), transform 0.9s var(--ease);
}
.reveal.is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; }
  .hero-line, .hero-brackets { animation: none; }
  html { scroll-behavior: auto; }
}

/* ================================================================
   Wordmark  ‹ Waypoint ›  (shared by preloader + hero)
   ================================================================ */
.wordmark {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(28px, 5vw, 110px);
  font-size: clamp(48px, 8.5vw, 150px);
  font-weight: 500;
  letter-spacing: -0.03em;
  line-height: 1;
  white-space: nowrap;
}
.wordmark .bracket { height: 0.62em; width: auto; flex: 0 0 auto; }
.bracket.flip { transform: scaleX(-1); }
.wm-word { display: grid; grid-template-columns: 1fr; }
.wm-word i {
  font-style: normal;
  min-width: 0;
  overflow: hidden;              /* clips horizontally for the reveal */
  padding-block: 0.2em;          /* room so ascenders/descenders aren't clipped */
  margin-block: -0.2em;          /* cancel the padding in layout */
}

/* ================================================================
   Preloader — folded mark rotates + unfolds into ‹ Waypoint ›
   ================================================================ */
.preloader {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: grid;
  place-items: center;
}
/* dark cover — sits behind the mark; swipes away right→left to unveil the hero */
.pre-cover {
  position: absolute;
  inset: 0;
  z-index: 0;
  background: var(--ink);
  clip-path: inset(0 0 0 0);
  transition: clip-path 0.2s cubic-bezier(0.76, 0, 0.24, 1);
}
.preloader .pre-mark { position: relative; z-index: 1; }
/* percentage loader — bottom-right, styled like the hero "Scroll" element */
.pre-pct {
  position: absolute;
  z-index: 1;
  right: var(--margin);
  bottom: 30px;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: var(--white);
  font-size: 14px; line-height: 20px;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  transition: opacity 0.35s var(--ease);
}
.pre-spin {
  width: 15px;
  height: 15px;
  animation: preSpin 0.9s linear infinite;
}
@keyframes preSpin { to { rotate: 360deg; } }
/* stage 0 (folded): brackets rotated into the folded plus mark, no text
   stage 1 (.spin):  brackets rotate upright
   stage 2 (.unfold): brackets spread to the EXACT hero-bracket positions
                      (width + space-between match .hero-brackets), word reveals
   stage 3 (.blink):  word + dark bg dissolve away, leaving the brackets in place */
.pre-mark {
  /* --bh = bracket height, matched to the hero brackets so the sizes line up */
  --bh: clamp(56px, 8vw, 150px);
  color: var(--white);
  font-size: clamp(52px, 8.5vw, 140px);   /* matches the hero text size (brackets use --bh) */
  width: var(--bh);                       /* folded: tight, brackets overlap */
  gap: 0.06em;
  transition: width 0.9s var(--ease), gap 0.9s var(--ease);
}
.pre-mark .bracket {
  height: var(--bh);
  rotate: 135deg;
  /* folded offsets are kept as a fixed fraction of the bracket height so the
     plus stays aligned at any bracket size (X = 0.21·bh, Y = 0.129·bh). */
  translate: calc(var(--bh) * 0.21) calc(var(--bh) * 0.129);
  transition: rotate 0.8s var(--ease), translate 0.8s var(--ease);
}
.pre-mark .bracket.flip { translate: calc(var(--bh) * -0.21) calc(var(--bh) * -0.129); }
.preloader.spin .pre-mark .bracket { rotate: 0deg; translate: 0 0; }
.pre-mark .wm-word {
  grid-template-columns: 0fr;
  opacity: 0;
  transition: grid-template-columns 0.9s var(--ease), opacity 0.5s var(--ease);
}
/* unfold: spread the brackets to the hero positions, reveal the word */
.preloader.unfold .pre-mark { width: var(--hero-span); justify-content: space-between; gap: 0; }
.preloader.unfold .pre-mark .wm-word { grid-template-columns: 1fr; opacity: 1; }
/* swipe: cover wipes away right→left unveiling the hero; word fades, brackets stay */
.preloader.swipe { pointer-events: none; }
.preloader.swipe .pre-cover { clip-path: inset(0 100% 0 0); }
.preloader.swipe .pre-mark .wm-word { opacity: 0; }
.preloader.swipe .pre-pct { opacity: 0; }
.preloader.gone { display: none; }

/* ================================================================
   Header — REMOVED (2026-09-02). The pill header now comes verbatim from
   the marketing site: css/site-shell.css + js/site/shell.js.
   ================================================================ */

/* ================================================================
   Scroll progress rail
   ================================================================ */
.rail {
  position: fixed;
  right: 14px;
  top: 50%;
  translate: 0 -50%;
  z-index: 90;
  background: var(--white);
  border-radius: 999px;
  box-shadow: 0 1px 2px var(--shadow-1), 0 8px 24px var(--shadow-2);
  padding: 12px 8px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}
.rail i {
  width: 3px;
  height: 5px;
  border-radius: 2px;
  background: var(--mute-fill);
  transition: height 0.4s var(--ease), background 0.4s var(--ease);
}
.rail i.on { height: 18px; background: var(--ink); }

/* ================================================================
   Hero — full-bleed sky video with ‹ Waypoint ›
   ================================================================ */
.hero {
  /* --p: 0 → 1 tucks the video into a rounded inset card on scroll */
  --p: 0;
  position: relative;
  height: 100vh;
  height: 100svh;
  color: var(--white);
}
.hero-video {
  position: absolute;
  top: calc(var(--p) * var(--bleed));
  left: calc(var(--p) * var(--bleed));
  width: calc(100% - 2 * var(--p) * var(--bleed));
  height: calc(100% - 2 * var(--p) * var(--bleed));
  object-fit: cover;
  border-radius: calc(var(--p) * var(--r-lg));
}
.hero-inner {
  position: relative;
  z-index: 1;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /* open central band so the object + brackets sit between the lines */
  gap: clamp(200px, 34vh, 420px);
  text-align: center;
  padding-inline: var(--margin);
}
.hero-line {
  font-size: clamp(52px, 8.5vw, 140px);
  font-weight: 500;
  letter-spacing: -0.03em;
  line-height: 1.0;
  /* delayed so the rise happens as the preloader blinks away (blink at 4.3s) */
  animation: heroRise 1.2s var(--ease) 4.35s both;
}
.hero-line:last-child { animation-delay: 4.55s; }
/* brackets pinned to the viewport's vertical centre, at the side edges,
   framing whatever object sits in the middle of the footage */
.hero-brackets {
  position: absolute;
  z-index: 1;
  top: 50%;
  left: 50%;
  width: var(--hero-span);
  translate: -50% -50%;
  display: flex;
  justify-content: space-between;
  align-items: center;
  pointer-events: none;
  /* always visible — hidden behind the preloader until the blink reveals them
     exactly where the preloader's brackets already sit */
}
.hero-brackets .bracket { height: clamp(56px, 8vw, 150px); }
@keyframes heroRise {
  from { opacity: 0; transform: translateY(36px); }
  to   { opacity: 1; transform: none; }
}
.hero-foot {
  position: absolute;
  z-index: 1;
  left: 0;
  right: 0;
  bottom: 30px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-inline: var(--margin);
  font-size: 14px; line-height: 20px;
  font-weight: 500;
}
.hero-foot a { display: inline-flex; align-items: center; gap: 7px; }
.scroll-arrow {
  width: 15px;
  height: 15px;
  display: inline-block;
  animation: nudge 2.2s ease-in-out infinite;
}
@keyframes nudge { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(4px); } }

/* ================================================================
   Statement + story card
   ================================================================ */
.statement { padding-block: clamp(90px, 13vh, 170px) 0; }
.statement-text {
  grid-column: 1 / 7;
  font-size: clamp(26px, 3.4vw, 52px);
  font-weight: 500;
  letter-spacing: -0.02em;
  line-height: 1.16;
}
/* stat cards — big-number metrics with an arrow, divider and caption */
.stat-grid {
  margin-top: clamp(70px, 10vh, 130px);
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--gutter);
}
.stat-card {
  background: var(--card);
  border-radius: var(--r-lg);
  padding: 24px;
  min-height: clamp(300px, 40vh, 420px);
  display: flex;
  flex-direction: column;
}
.stat-label {
  font-size: 14px; line-height: 20px;
  font-weight: 500;
  color: var(--text-3);
}
.stat-main {
  margin-top: auto;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px;
}
.stat-arrow {
  font-size: clamp(22px, 2.4vw, 34px);
  line-height: 1;
  color: var(--ink);
}
.stat-arrow.down { color: var(--bad); }   /* red — reduction */
.stat-arrow.up { color: var(--ok); }     /* green — increase */
.stat-value {
  font-size: clamp(40px, 4.6vw, 78px);
  font-weight: 500;
  letter-spacing: -0.03em;
  line-height: 0.9;
}
.stat-divider {
  border-top: 1px solid var(--grey);
  margin: 22px 0 18px;
}
.stat-desc {
  font-size: 14px;
  line-height: 20px;
  color: var(--text-2);
  max-width: 30ch;
}

/* ================================================================
   Staircase
   ================================================================ */
.stair { height: 230vh; }
.stair-sticky {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  background: var(--white);
}
.stair-line {
  display: flex;
  gap: 0.28em;
  font-size: clamp(48px, 8.5vw, 150px);
  font-weight: 500;
  letter-spacing: -0.03em;
  line-height: 1;
}
.stair-word {
  transform: translate(calc(var(--sp, 1) * var(--sx, 0) * 1vw),
                       calc(var(--sp, 1) * var(--sy, 0) * 1vh));
  will-change: transform;
}
.stair-copy {
  margin-top: 44px;
  max-width: 52ch;
  text-align: center;
  font-size: clamp(16px, 1.5vw, 19px);
  line-height: 1.55;
  padding-inline: var(--margin);
  opacity: var(--cp, 0);
  translate: 0 calc((1 - var(--cp, 0)) * 20px);
}
.stair-copy a { text-decoration: underline; text-underline-offset: 3px; }

/* ================================================================
   Feature blocks
   ================================================================ */
.feature { padding-top: clamp(70px, 10vh, 120px); }
.feature-card {
  height: 88vh;
  min-height: 420px;
  display: grid;
  place-items: center;
}

/* capability card grid ("What agents call") */
.cap-heading {
  font-size: clamp(30px, 3.4vw, 52px);
  font-weight: 500;
  letter-spacing: -0.02em;
  margin-bottom: clamp(28px, 4vh, 48px);
}
.capability-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--gutter);
  margin-top: var(--gutter);   /* tight gap below the video */
}
.cap-card {
  position: relative;
  background: var(--card);
  border-radius: var(--r-lg);
  aspect-ratio: 3 / 4;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 28px;
  padding: 24px;
  transition: background 0.3s var(--ease);
}
.cap-card:hover { background: var(--grey); }
.cap-plus {
  position: absolute;
  top: 16px;
  right: 16px;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--line);
  transition: background 0.25s var(--ease);
}
.cap-plus::before,
.cap-plus::after {
  content: "";
  position: absolute;
  inset: 0;
  margin: auto;
  background: var(--ink);
  border-radius: 2px;
}
.cap-plus::before { width: 12px; height: 1.6px; }
.cap-plus::after { width: 1.6px; height: 12px; }
.cap-card:hover .cap-plus { background: var(--ink); }
.cap-card:hover .cap-plus::before,
.cap-card:hover .cap-plus::after { background: var(--white); }
.cap-icon { width: clamp(48px, 5vw, 68px); height: auto; color: var(--ink); }
.cap-label { font-size: clamp(15px, 1.4vw, 18px); font-weight: 500; }

/* dot-grid icons — rebuild dot-by-dot on card hover */
.dot-icon {
  width: clamp(64px, 6.5vw, 92px);
  height: auto;
  color: var(--ink);
}
.dot-icon circle {
  transform-box: fill-box;
  transform-origin: center;
}
/* on hover the dots pop back in, staggered by their --i index → a "rebuild" */
.cap-card:hover .dot-icon circle {
  animation: dotPop 0.42s var(--ease) both;
  animation-delay: calc(var(--i) * 45ms);
}
@keyframes dotPop {
  0%   { transform: scale(0);    opacity: 0; }
  55%  { transform: scale(1.35); opacity: 1; }
  100% { transform: scale(1);    opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .cap-card:hover .dot-icon circle { animation: none; }
}
.feature-title {
  position: relative;
  z-index: 1;
  color: var(--white);
  font-size: clamp(34px, 4.6vw, 76px);
  font-weight: 500;
  letter-spacing: -0.025em;
  line-height: 1.05;
  text-align: center;
  padding-inline: 20px;
  text-shadow: 0 2px 24px var(--mute-fill);
}

.sub-row {
  display: grid;
  gap: var(--gutter);
  margin-top: var(--gutter);
  align-items: stretch;
}
.sub-row.cols-2 { grid-template-columns: 1fr 1.35fr; }
.sub-row.cols-3 { grid-template-columns: 1fr 1fr 1fr; }
.sub-row .media-card { aspect-ratio: 16 / 10; }
.sub-row.cols-2 .media-card { aspect-ratio: 16 / 8.5; }

.text-card {
  background: var(--card);
  border-radius: var(--r-lg);
  padding: 22px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 60px;
}
.text-card .card-body { max-width: 46ch; }

/* ================================================================
   Technology
   ================================================================ */
.tech {
  /* --tp: 0 → 1 while scrolling through the section; insets + rounds the
     gradient band into a card, the same tuck-in move as the hero video */
  --tp: 0;
  margin-top: clamp(90px, 13vh, 160px);
  padding: clamp(90px, 12vh, 150px) var(--bleed);
  background: linear-gradient(to bottom, var(--white), var(--sky-3) 26%, var(--sky) 100%);
  text-align: center;
  clip-path: inset(0 calc(var(--tp) * var(--bleed)) round calc(var(--tp) * var(--r-lg)));
  will-change: clip-path;
}
.tech-title {
  position: relative;
  z-index: 0;
  font-size: clamp(40px, 6vw, 96px);
  font-weight: 500;
  letter-spacing: -0.03em;
  margin-bottom: 0;
}
.tech-terminal {
  width: min(680px, 100%);
  /* starts below the heading, then --cy (scroll-driven, in js) lifts it up and
     over the heading as you scroll — parallax rather than a static overlap */
  margin: clamp(70px, 10vh, 150px) auto 0;
  translate: 0 var(--cy, 0px);
  position: relative;
  z-index: 2;
  background: var(--ink);
  border-radius: var(--r-lg);
  overflow: hidden;
  text-align: left;
  box-shadow: 0 24px 70px var(--mute-fill);
  transition: box-shadow 0.4s var(--ease);
  will-change: translate;
}
/* deeper shadow when hovering the console window */
.tech-terminal:hover { box-shadow: 0 44px 110px var(--text-3); }
.term-bar {
  position: relative;
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 14px 18px;
  border-bottom: 1px solid rgba(var(--white-rgb), 0.12);
}
.term-bar i {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: rgba(var(--white-rgb), 0.22);
  transition: background 0.3s var(--ease);
}
/* traffic-light colours light up on hover, like a mac window */
.tech-terminal:hover .term-bar i:nth-child(1) { background: var(--bad-bright); }
.tech-terminal:hover .term-bar i:nth-child(2) { background: var(--warn); }
.tech-terminal:hover .term-bar i:nth-child(3) { background: var(--ok-bright); }
/* title centred in the bar */
.term-bar span {
  position: absolute;
  left: 50%;
  translate: -50% 0;
  font-size: 12px; line-height: 16px;
  color: rgba(var(--white-rgb), 0.45);
}
.tech-terminal pre {
  padding: 26px 24px 30px;
  overflow-x: auto;
  font: 400 13.5px/1.75 "SF Mono", ui-monospace, "Menlo", monospace;
  color: rgba(var(--white-rgb), 0.88);
}
.tech-terminal .c { color: rgba(var(--white-rgb), 0.38); }
.tech-terminal .k { color: var(--sky); }
.tech-terminal .s { color: var(--sky-2); }
.tech-terminal .f { color: var(--sky); }
.tech-terminal .n { color: var(--sky-2); }

.tech-copy {
  margin: clamp(44px, 6vh, 70px) auto 0;
  max-width: 54ch;
  font-size: clamp(16px, 1.6vw, 20px);
  line-height: 1.55;
}
.tech-copy a { text-decoration: underline; text-underline-offset: 3px; }
.tech-actions {
  display: flex;
  justify-content: center;
  gap: 10px;
  margin-top: 28px;
}
.btn-pill {
  display: inline-flex;
  align-items: center;
  background: var(--white);
  color: var(--ink);
  font-size: 14px;
  font-weight: 500;
  padding: 12px 22px;
  border-radius: 999px;
  border: 1px solid var(--line);
  transition: background 0.25s var(--ease), color 0.25s var(--ease);
}
.btn-pill:hover { background: var(--ink); color: var(--white); }
/* carousel card typography — identical across media and text cards */
.car-card .card-label { font-size: 14px; line-height: 20px; }
.car-card .card-body { font-size: 14px; line-height: 20px; max-width: 44ch; }

/* ================================================================
   Designed / carousel
   ================================================================ */
.designed {
  /* full-width section (no card) so the carousel can bleed past the edges */
  padding-block: clamp(70px, 9vh, 110px) 100px;
  position: relative;
}
.designed-title {
  text-align: center;
  padding-inline: var(--margin);
  font-size: clamp(48px, 8.5vw, 160px);
  font-weight: 500;
  letter-spacing: -0.03em;
  margin-bottom: clamp(48px, 7vh, 80px);
}
.carousel { position: relative; }
.car-track {
  display: flex;
  gap: var(--gutter);
  overflow-x: auto;
  scroll-behavior: smooth;
  scrollbar-width: none;
  padding-inline: var(--margin);
  scroll-padding-inline: var(--margin);
  scroll-snap-type: x mandatory;
}
.car-track::-webkit-scrollbar { display: none; }
.car-card {
  flex: 0 0 auto;
  scroll-snap-align: start;
  border-radius: var(--r-lg);
  overflow: hidden;
  height: clamp(380px, 55vh, 560px);
}
.car-media { position: relative; width: min(480px, 78vw); background: var(--ink); }
.car-media video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.car-overlay {
  position: absolute;
  inset: 0;
  z-index: 1;
  padding: 22px;
  color: var(--white);
  background: linear-gradient(to bottom, var(--text-3), rgba(var(--ink-rgb), 0) 55%);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.car-overlay .card-body { color: rgba(var(--white-rgb), 0.85); }
.car-text {
  width: min(760px, 88vw);
  background: var(--card);
  display: grid;
  grid-template-columns: 1fr 1fr;
}
.car-text-copy { padding: 22px; display: flex; flex-direction: column; gap: 10px; }
.car-text-media { position: relative; }
.car-text-media video {
  position: absolute;
  inset: 14px;
  width: calc(100% - 28px);
  height: calc(100% - 28px);
  object-fit: cover;
  border-radius: var(--r-md);
}
.car-tint { background: var(--sky); }

.car-tabs {
  position: absolute;
  left: 50%;
  bottom: 30px;
  translate: -50% 0;
  display: flex;
  gap: 4px;
  background: var(--white);
  border-radius: 999px;
  padding: 4px;
  box-shadow: 0 1px 2px var(--shadow-1), 0 10px 30px var(--shadow-2);
}
.designed .car-tabs { bottom: 34px; }
/* THE SITE'S TAB (2026-09-02): copied from waypoint.world's "Enabled by Waypoint"
   strip — idle tabs hover light grey, the dark backdrop is ONE sliding pill
   (.car-tab-pill, placed by js/tabs.js) that glides between them. */
.car-tab {
  border: 0;
  background: transparent;
  font: 500 14px/1 "Helvetica Neue W", sans-serif;
  color: var(--ink);
  display: inline-flex;
  align-items: center;
  height: 40px;
  padding: 0 16px;
  border-radius: 999px;
  cursor: pointer;
  transition: background 0.3s var(--ease), color 0.3s var(--ease);
}
.car-tab:hover { background: var(--wash); color: var(--ink); }
.car-tab { position: relative; z-index: 1; }
.car-tab.active { background: transparent; color: var(--white); }
.car-tab.active:hover { background: transparent; }
.car-tab-pill {
  position: absolute;
  top: 4px;
  bottom: 4px;
  left: 0;
  width: 0;
  border-radius: 999px;
  background: var(--ink);
  z-index: 0;
  overflow: hidden;
  transform: translateX(4px);
  transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1),
              width 0.35s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: transform;
}
.car-tab-pill.snap { transition: none; }
/* the app's old indicator span, still emitted by a few templates — inert */
.tab-ind { display: none !important; }

/* ================================================================
   Interlude band
   ================================================================ */
.interlude {
  margin: var(--bleed);
  background: var(--sky);
  border-radius: var(--r-lg);
  padding: clamp(90px, 14vh, 180px) var(--margin);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 56px;
}
.inter-inner {
  width: 100%;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 40px;
}
.inter-left, .inter-right { font-size: clamp(15px, 1.3vw, 18px); font-weight: 500; }
.inter-left { text-align: left; }
.inter-right { text-align: right; }
.inter-logo { width: clamp(72px, 9vw, 130px); color: var(--ink); }
.btn-dark {
  background: var(--ink);
  color: var(--white);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.04em;
  padding: 13px 22px;
  border-radius: 999px;
  transition: background 0.25s var(--ease), color 0.25s var(--ease);
}
.btn-dark:hover { background: var(--ink-2); color: var(--white); }

/* ================================================================
   FAQ
   ================================================================ */
.faq { padding-block: clamp(90px, 13vh, 160px); }
.faq-label { grid-column: 1 / 3; font-size: 14px; line-height: 20px; font-weight: 500; }
.faq-list { grid-column: 4 / 7; }
.faq-list details { border-bottom: 1px solid var(--grey); }
.faq-list details:first-child { border-top: 1px solid var(--grey); }
.faq-list summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 21px 2px;
  font-size: 14px; line-height: 20px;
  font-weight: 500;
}
.faq-list summary::-webkit-details-marker { display: none; }
.faq-list summary:hover { color: var(--text-2); }
.chev {
  flex: 0 0 auto;
  width: 9px;
  height: 9px;
  border-right: 1.6px solid var(--ink);
  border-bottom: 1.6px solid var(--ink);
  transform: rotate(45deg);
  transition: transform 0.35s var(--ease);
  margin-right: 4px;
}
.faq-list details.expanded .chev { transform: rotate(225deg); }
/* animated open/close: height via grid-rows + a sweeping gradient mask that
   softly unveils/hides the text (--reveal animated via @property) */
@property --reveal {
  syntax: "<percentage>";
  inherits: false;
  initial-value: 0%;
}
.faq-body {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.42s var(--ease);
}
.faq-body-inner {
  min-height: 0;
  overflow: hidden;
  --reveal: 0%;
  -webkit-mask-image: linear-gradient(to bottom, #000 var(--reveal), transparent calc(var(--reveal) + 26%));
          mask-image: linear-gradient(to bottom, #000 var(--reveal), transparent calc(var(--reveal) + 26%));
  transition: --reveal 0.5s var(--ease);
}
.faq-list details.expanded .faq-body { grid-template-rows: 1fr; }
.faq-list details.expanded .faq-body-inner { --reveal: 120%; }
.faq-list details p {
  padding: 0 2px 24px;
  font-size: 14px;
  line-height: 20px;
  color: var(--text-2);
  max-width: 60ch;
}
@media (prefers-reduced-motion: reduce) {
  .faq-body, .faq-body-inner { transition: none; }
}

/* ================================================================
   Pre-footer band (dark)
   ================================================================ */
.band { padding-inline: var(--bleed); }
.band-inner {
  background: var(--ink);
  border-radius: var(--r-lg);
  min-height: 56vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 22px;
  text-align: center;
  padding: 60px var(--margin);
}
.band-inner p { color: var(--white); font-size: 14px; line-height: 20px; font-weight: 500; }
.band-inner p span { color: var(--sky); }
.band-inner .btn-pill { border-color: transparent; }
.band-inner .btn-pill:hover { background: var(--sky); color: var(--ink); }

/* ================================================================
   Footer · Easter-egg band · Tooltip — REMOVED (2026-09-02). All three
   now come verbatim from the marketing site: css/site-shell.css.
   ================================================================ */

/* ================================================================
   Responsive
   ================================================================ */
@media (max-width: 1000px) {
  :root { --margin: 40px; }
  .capability-grid { grid-template-columns: repeat(2, 1fr); }
  .stat-grid { grid-template-columns: repeat(2, 1fr); }
  .sub-row.cols-3 { grid-template-columns: 1fr 1fr; }
  .sub-row.cols-3 .text-card { grid-column: 1 / 3; min-height: 240px; }
  .faq-label { grid-column: 1 / 7; margin-bottom: 24px; }
  .faq-list { grid-column: 1 / 7; }
}

@media (max-width: 760px) {
  :root { --margin: 20px; }

  .statement-text { grid-column: 1 / 7; }
  .stat-grid { grid-template-columns: 1fr; }
  .stat-card { min-height: 260px; }

  .sub-row.cols-2, .sub-row.cols-3 { grid-template-columns: 1fr; }
  .sub-row.cols-3 .text-card { grid-column: auto; }
  .sub-row .media-card, .sub-row.cols-2 .media-card { aspect-ratio: 16 / 11; }
  .text-card { min-height: 220px; gap: 40px; }

  .feature-card { height: 72svh; min-height: 0; }
  .cap-card { aspect-ratio: 1 / 1; }

  .car-text { grid-template-columns: 1fr; width: min(420px, 88vw); }
  .car-text-media { min-height: 180px; }

  .inter-inner { grid-template-columns: 1fr; text-align: center; gap: 28px; justify-items: center; }
  .inter-left, .inter-right { text-align: center; }


  .rail { display: none; }
}

/* ================================================================
   APP EXTENSIONS  (waypoint-app only — not in the marketing site)
   Every value below is copied from an existing selector/token above.
   Provenance is noted per block so nothing is invented.
   ================================================================ */

/* --- App page shell ---
   .page is copied wholesale; min-height fills the white surface so the
   blue body (--sky) never shows on short app pages (the site relied on the
   long scroll + .egg reveal instead). */
.page.app { min-height: 100vh; }

/* Content width cap (2026-07-22): the marketing site's .grid/.bleed/.page
   never cap width — full-bleed at every viewport, at every size checked in
   this file (no max-width rule exists on them). Copying that: .page stays
   full-bleed here too (the white surface always fills the viewport), and
   only the app's own content wrappers — .app-main and the footer — are
   capped at 1440px and centered, so rows of stat-cards/tables don't stretch
   edge-to-edge on very wide monitors.

   THE FRAME, NAMED (2026-08-31). The 1440 above was a literal in two rules,
   which was fine while everything that had to obey it lived inside .app-main.
   The fixed wallet square does not: it is positioned against the VIEWPORT, so
   at 1900px it sat 134px outside the frame every other element lines up on.
   --frame is that cap; --frame-gap is the whitespace either side of it, and it
   is exactly what an element pinned to the viewport has to add to its own
   offset to land on the frame's edge instead. 100vw (not 100%) because the
   pinned element's containing block is the viewport — the same reading .pill
   already takes at :264. */
:root {
  --frame: 1440px;
  --frame-gap: max(0px, calc((100vw - var(--frame)) / 2));
}
.app-main { max-width: var(--frame); margin-inline: auto; }   /* the footer is the site's own, full-bleed (site-shell.css) */

/* Clears the fixed pill header:
   .site-header padding-top (20px) + .pill-bar height (56px) + --margin (40px). */
.app-main { padding-top: calc(20px + 56px + var(--margin)); padding-bottom: 40px; }

/* Vertical rhythm between app blocks — from .stat-grid { margin-top }. */
.app-block { margin-top: clamp(70px, 10vh, 130px); }
.app-block:first-child { margin-top: 0; }

/* ----------------------------------------------------------------
   iOS text-style scale (2026-07-22). Every app text element below is
   retyped onto Apple's 11-step HIG scale (pt treated as px). Font stays
   Helvetica Neue W throughout — only size/weight/line-height move. The
   family only ships Roman(400)/Medium(500)/Bold(700), so every
   "Semibold" role below substitutes Medium(500) — noted per rule.
     Large Title  34/41  Regular
     Title 1      28/34  Regular
     Title 2      22/28  Regular
     Title 3      20/25  Regular   (unused on these two pages)
     Headline     17/22  Medium  (HIG Semibold, substituted)
     Body         17/22  Regular
     Callout      16/21  Regular  (unused on these two pages)
     Subhead      15/20  Regular
     Footnote     13/18  Regular
     Caption 1    12/16  Regular
     Caption 2    11/13  Regular  (unused on these two pages)
   The pill/drawer/footer nav (shared with the marketing site) and the
   terminal's monospace code block keep their own existing treatment —
   see the notes on those rules further down.
   ---------------------------------------------------------------- */

/* Section head: title only — the decorative .app-eyebrow label above every
   title/section was removed (2026-07-22); .app-title now always leads its
   block, so it carries no top margin (== .cap-heading with margin dropped).
   Page titles (h1: "Dashboard"/"Directory") → Large Title.
   Section titles (h2: "Agent activity") → Title 1 — same .app-title class,
   split by tag because the two roles need different sizes. */
.app-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 24px; flex-wrap: wrap; }
h1.app-title { font-size: 34px; font-weight: 400; line-height: 41px; letter-spacing: -0.02em; }
h2.app-title { font-size: 28px; font-weight: 400; line-height: 34px; letter-spacing: -0.02em; }

/* 3-up stat grid — same as .stat-grid but three columns (gap = --gutter). */
.stat-grid.cols-3 { grid-template-columns: repeat(3, 1fr); }
/* inside app blocks the grid leads its section directly (no eyebrow above it
   any more), so it carries no extra top margin — .app-block's own margin-top
   already provides the rhythm between sections. */
.app-block > .stat-grid,
.app-block > .sub-row { margin-top: 0; }

/* Budget stat cards read a touch shorter than the marketing hero metrics.
   min-height retuned (2026-07-22): the iOS retype below shrinks .stat-value
   from a ~40-78px display number to a fixed 28px (Title 1), which left the
   old clamp(220px,26vh,300px) card looking cavernous. Tightened to the flat
   220px already used for min-height elsewhere in this file (.svc-card, and
   .text-card at the ≤760px breakpoint) — no new spacing value invented. */
.stat-card.compact { min-height: 220px; }

/* Stat card text (2026-07-22 iOS retype).
   .stat-label ("Monthly budget"/"Spent"/"Remaining") → Footnote.
   .stat-value ($5,000 etc., the big-three budget cards) → Title 1.
   .stat-arrow (the ↓ beside "Remaining") isn't a mapped text style — it's
   a glyph paired with the value, resized to match stat-value's new 28px
   instead of its old ~22-34px clamp so the pair stays visually balanced.
   .stat-desc ("Ceiling your agent may transact...") → Subhead. */
.stat-label { font-size: 12px; font-weight: 400; line-height: 16px; }
.stat-value { font-size: 28px; font-weight: 400; line-height: 34px; }
.stat-arrow { font-size: 28px; }
.stat-desc { font-size: 14px; font-weight: 400; line-height: 20px; }

/* Progress meter (DERIVED — no direct analog on the site).
   track = --grey (as .stat-divider border colour); fill = --ink;
   radius 999px from .btn-pill; height 6px derived from .rail i width (3px)·2. */
.meter { height: 6px; border-radius: 999px; background: var(--grey); overflow: hidden; margin-top: 14px; }
.meter > i { display: block; height: 100%; background: var(--ink); border-radius: 999px; }
.meter.sky > i { background: var(--sky); }

/* Allowance category cards — .text-card with a tighter gap so the meter sits
   under the copy (gap from .car-text-copy = 10px).
   .card-label (allowance name, "Trading" etc.) → Footnote — same treatment
   as .stat-label above, so budget and allowance cards read as one family.
   .alloc-value ($1,800 etc.) → Title 2, one step below the big-three budget
   cards' Title 1, per the requested hierarchy between the two card types.
   .alloc-meta ("of $2,500 · 72% used") → Footnote (already 13px; weight and
   line-height brought onto the scale). */
.text-card.allowance { gap: 10px; justify-content: flex-start; }
.card-label { font-size: 12px; font-weight: 400; line-height: 16px; }
.text-card.allowance .alloc-value { font-size: 22px; font-weight: 400; letter-spacing: -0.03em; line-height: 28px; margin-top: 6px; }
.text-card.allowance .alloc-meta { font-size: 14px; font-weight: 400; line-height: 20px; color: var(--text-3); margin-top: 8px; }

/* Status dot (colour-coded) — geometry from .panel-meta .dot (8px circle);
   colours are the site's existing semantic set:
   green var(--ok) (.stat-arrow.up), red var(--bad) (.stat-arrow.down),
   amber var(--warn) (.tech-terminal traffic light). */
.sdot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; display: inline-block; }
.sdot.ok { background: var(--ok); }
.sdot.wait { background: var(--warn); }
.sdot.stop { background: var(--bad); }

/* Activity / data list (DERIVED — data-table pattern).
   Row chrome copied from .faq-list details + summary:
   border-bottom 1px var(--grey); first row border-top; row padding 21px 2px;
   flex space-between.
   Column headers → Footnote. Primary cell (service/capability name) →
   Subhead, Medium — one deliberate step up from plain Subhead so the
   primary column still reads as the anchor of the row (documented
   deviation from the flat Subhead below). Secondary cells (action, amount,
   time) → Subhead. Status chip text → Footnote. */
.dlist { width: 100%; }
.dlist .drow {
  display: grid;
  align-items: center;
  gap: 24px;
  padding: 21px 2px;
  border-bottom: 1px solid var(--grey);
  font-size: 14px;
  font-weight: 400;
  line-height: 20px;
}
.dlist .drow:first-child { border-top: 1px solid var(--grey); }
.dlist .drow.head { font-size: 12px; font-weight: 400; line-height: 16px; color: var(--text-3); padding: 12px 2px; }
.dlist .drow.head { border-top: 0; }
/* activity columns: service · action · amount · status · time */
.dlist.activity .drow { grid-template-columns: 1.3fr 1.6fr 1fr 1.1fr 0.9fr; }
/* capability columns: name · description · call schema hint */
.dlist.caps .drow { grid-template-columns: 1fr 2fr auto; }
.cell-name { font-size: 14px; font-weight: 500; letter-spacing: 0.01em; line-height: 20px; }   /* Subhead, Medium */
.cell-sub { font-size: 14px; font-weight: 400; line-height: 20px; color: var(--text-2); } /* Subhead */
.cell-num { font-weight: 400; font-variant-numeric: tabular-nums; }            /* Subhead — size/line-height inherited from .drow */
.cell-status { display: inline-flex; align-items: center; gap: 8px; font-size: 14px; font-weight: 400; line-height: 20px; } /* Footnote */
.cell-time { font-size: 14px; font-weight: 400; line-height: 20px; color: var(--text-3); font-variant-numeric: tabular-nums; } /* Subhead */

/* Directory service card — composed from .cap-card (surface, radius, hover,
   cap-plus corner) but left-aligned with auto height for text content.
   .svc-name → Headline, Medium. .svc-meta ("category · calls") and its
   nested .svc-cat chip → Footnote (same family as the table's column
   headers — both spans sit on one line so they share a size). .svc-verified
   badge → Caption 1. */
.svc-card {
  position: relative;
  background: var(--card);
  border-radius: var(--r-lg);
  padding: 24px;
  min-height: 220px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 18px;
  cursor: pointer;
  transition: background 0.3s var(--ease);
}
/* colour inverts on the smooth flip — transition set copied from .pill-logo
   (background + colour, 0.3s var(--ease)); base .svc-card only animated bg. */
.svc-card, .svc-card .dot-icon, .svc-name, .svc-meta, .svc-cat {
  transition: background 0.3s var(--ease), color 0.3s var(--ease);   /* == .pill-logo */
}
.svc-card:hover { background: var(--grey); }
.svc-card .dot-icon { width: clamp(40px, 4vw, 54px); margin-bottom: auto; }
.svc-name { font-size: 18px; font-weight: 500; letter-spacing: -0.01em; line-height: 24px; }
.svc-meta { display: flex; align-items: center; gap: 10px; font-size: 12px; font-weight: 400; line-height: 16px; color: var(--text-3); }
.svc-cat { font-size: 12px; font-weight: 400; line-height: 16px; }
.svc-verified { display: inline-flex; align-items: center; gap: 7px; font-size: 12px; font-weight: 400; line-height: 16px; }
.svc-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--gutter); margin-top: var(--gutter); }
/* Hover flip: exactly one black card at a time. The black treatment is driven
   entirely by .active (toggled in JS on hover / rest), so the resting card and
   the hovered card swap black↔white through the transition above. .svc-card's
   own :hover grey is suppressed while flip logic owns .active so it never
   flashes grey between states. */
.svc-grid:hover .svc-card:hover:not(.active) { background: var(--card); }
.svc-card.active { background: var(--ink); color: var(--white); }
.svc-card.active .svc-meta, .svc-card.active .svc-cat { color: rgba(var(--white-rgb), 0.6); }
.svc-card.active .dot-icon { color: var(--white); }
/* dot symbols "rebuild" as the card flips black — EXACT reuse of the marketing
   site's .cap-card:hover .dot-icon rule (dotPop 0.42s var(--ease), staggered by
   calc(var(--i) * 45ms)); --i is set per circle in js. */
.svc-card.active .dot-icon circle {
  animation: dotPop 0.42s var(--ease) both;
  animation-delay: calc(var(--i) * 45ms);
}
@media (prefers-reduced-motion: reduce) {
  .svc-card.active .dot-icon circle { animation: none; }
}
/* Added marker — green .sdot pinned in the card corner, geometry from .cap-plus
   (top/right 16px). Shown only on services the user has added. */
.svc-added {
  position: absolute;
  top: 16px;
  right: 16px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  line-height: 16px;
  color: var(--text-3);
  opacity: 0;
  transition: opacity 0.25s var(--ease);   /* == .tip transition */
}
.svc-added::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--ok);   /* == .sdot.ok / .stat-arrow.up */
}
.svc-card.is-added .svc-added { opacity: 1; }
.svc-card.active .svc-added { color: rgba(var(--white-rgb), 0.65); }

/* ----------------------------------------------------------------
   Service detail MODAL (2026-07-22 — replaces the on-page .svc-detail
   split + .tech-terminal, both deleted). Notion-style centered popup.
   Every value below is copied from an existing selector, cited inline.
   ---------------------------------------------------------------- */

/* Backdrop dim: no overlay token exists on the site. The one existing
   translucent-ink scrim is .chip's background rgba(38,38,38,0.45) — reused
   verbatim as a plain ink scrim over the whole viewport. z above .site-header
   (100) and .tip (400). */
.modal { position: fixed; inset: 0; z-index: 500; display: grid; place-items: center; padding: var(--bleed); }
.modal[hidden] { display: none; }
.modal-backdrop {
  position: absolute;
  inset: 0;
  background: var(--scrim);   /* == .chip background */
  opacity: 0;
  transition: opacity 0.25s var(--ease);   /* == .tip transition */
}
.modal.show .modal-backdrop { opacity: 1; }
/* Card: surface + shadow copied from .pill (the site's floating panel);
   largest radius in the system (--r-lg); width pattern mirrors .pill's
   min(px, calc(100vw - 2*--bleed)); padding 34px from .panel-main. */
.modal-card {
  position: relative;
  z-index: 1;
  width: min(880px, calc(100vw - 2 * var(--bleed)));
  max-height: min(85vh, 760px);
  display: flex;
  flex-direction: column;
  background: var(--white);
  border-radius: var(--r-lg);
  box-shadow: 0 1px 2px var(--shadow-1), 0 10px 34px var(--shadow-2);   /* == .pill */
  opacity: 0;
  transform: translateY(12px) scale(0.99);
  transition: opacity 0.25s var(--ease), transform 0.35s var(--ease);   /* .tip 0.25s + .modal-card scale */
}
.modal.show .modal-card { opacity: 1; transform: none; }
/* X — two 1.8px ink lines, geometry from .pill-toggle span (17px / 1.8px / var(--ink)). */
.modal-x {
  position: absolute;
  top: 22px;
  right: 22px;
  width: 42px;   /* == .pill-toggle */
  height: 42px;
  border: 0;
  background: transparent;
  border-radius: 12px;   /* == .pill-toggle */
  cursor: pointer;
  display: grid;
  place-items: center;
  transition: background 0.3s var(--ease);   /* == .pill-toggle */
}
.modal-x:hover { background: var(--ink); }
.modal-x span {
  grid-area: 1 / 1;
  width: 17px;
  height: 1.8px;
  background: var(--ink);
  border-radius: 2px;
  transition: background 0.3s var(--ease);   /* == .pill-toggle span */
}
.modal-x span:first-child { transform: rotate(45deg); }
.modal-x span:last-child { transform: rotate(-45deg); }
.modal-x:hover span { background: var(--white); }

/* Header zone (2026-07-22 refine) — the clicked card's dotted symbol + name +
   category/verified, closed by a divider. Ties the modal to its card and gives
   the left side weight the old sparse column lacked. */
.modal-header {
  display: flex;
  align-items: flex-start;
  gap: 18px;                              /* == .svc-card gap */
  padding: 34px 72px 24px 34px;          /* right clears the 42px X at right:22 */
  border-bottom: 1px solid var(--grey);   /* == .stat-divider colour */
}
/* symbol sized to sit with the Title 1 line; overrides base .dot-icon width. */
.modal-symbol { width: 44px; height: auto; flex: 0 0 auto; margin-top: 3px; color: var(--ink); }
.modal-symbol circle { transform-box: fill-box; transform-origin: center; }   /* == .dot-icon circle */
/* SAME staggered rebuild as the cards on hover — dotPop 0.42s + --i * 45ms,
   copied verbatim from the marketing .cap-card:hover .dot-icon rule. */
.modal-symbol:hover circle {
  animation: dotPop 0.42s var(--ease) both;
  animation-delay: calc(var(--i) * 45ms);
}
@media (prefers-reduced-motion: reduce) { .modal-symbol:hover circle { animation: none; } }
.modal-head-text { display: flex; flex-direction: column; gap: 10px; min-width: 0; }   /* gap == .svc-meta */
.modal-title { font-size: 28px; font-weight: 400; line-height: 34px; letter-spacing: -0.02em; overflow-wrap: anywhere; }   /* Title 1 */
.modal-cat { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; }   /* wraps for long name + badge */

/* Scroll region — header + footer stay pinned; the body scrolls (card capped at
   85vh). The two dividers frame the scroll region as the affordance. */
.modal-body { min-height: 0; overflow-y: auto; padding: 28px 34px 32px; display: flex; flex-direction: column; gap: 28px; }   /* gap == .cap-card */
.modal-desc { font-size: 14px; font-weight: 400; line-height: 20px; color: var(--text-2); max-width: 62ch; }   /* Body, full-width under header */
/* Info order: description, then the Chains | Platforms two-up pair, then
   Functions and Stats full-width below. The pair uses an even split from
   .car-text (1fr 1fr) with the inter-column gap var(--gutter) used between
   .stat-grid / .sub-row columns; align-items:start so an uneven pair (one list
   longer) top-aligns rather than stretches. Stacks to one column ≤1000px. */
.modal-pair { display: grid; grid-template-columns: 1fr 1fr; gap: var(--gutter); align-items: start; }
.modal-sec-label { font-size: 12px; font-weight: 400; line-height: 16px; color: var(--text-3); margin-bottom: 4px; }   /* Footnote, == .dlist .drow.head colour */
/* Chain/platform glyph — sized to the Footnote/Caption line, ink-coloured.
   15px matches .pre-spin / .scroll-arrow icon box. */
.chain-row { display: flex; align-items: center; gap: 10px; font-size: 14px; font-weight: 400; line-height: 20px; }   /* Subhead */
.chain-glyph { width: 15px; height: 15px; flex: 0 0 auto; color: var(--ink); }
.chain-list { display: flex; flex-direction: column; gap: 10px; }   /* gap == .car-text-copy */
/* modal list column layout — same per-variant grid pattern as .dlist.caps /
   .dlist.activity above. Functions: name + description. */
.dlist.fn .drow { grid-template-columns: minmax(84px, auto) 1fr; }
/* Footer — pinned action bar, right-aligned like a CTA row (arrangement from
   .agent-strip: a flex row with the action pushed to one end + adjacent copy).
   Confirmation sits immediately left of the button. Add button uses .btn-dark's
   ink fill, .app-main .btn-pill's 15/500 type; fade via .tip's 0.25s. */
.modal-foot {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 14px;
  padding: 18px 34px;
  border-top: 1px solid var(--grey);   /* == .stat-divider colour */
}
/* modal lives outside .app-main, so the 15/500 normalisation there doesn't
   reach it — repeat it here so the Add/Remove button lands on Subhead (15). */
.modal-foot .btn-pill { font-size: 14px; font-weight: 500; line-height: 20px; }
.btn-pill.ink { background: var(--ink); color: var(--white); border-color: transparent; }   /* == .btn-dark fill */
.btn-pill.ink:hover { background: var(--ink-2); color: var(--white); border-color: transparent; }   /* a slight lift — the same hover the modal's Continue button had */
.modal-confirm {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  font-weight: 400;
  line-height: 20px;   /* Footnote */
  color: var(--text-2);
  opacity: 0;
  transition: opacity 0.25s var(--ease);   /* == .tip transition */
}
.modal-confirm.show { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .modal-backdrop, .modal-card, .modal-confirm { transition: none; }
}

/* Category filter — reuses .car-tabs / .car-tab, laid out inline (not absolute).
   .car-tab text bumped from the marketing scale's 13px to Subhead (15),
   scoped to .cat-tabs so the base .car-tab rule (carousel component, not
   used on these pages) is left untouched. */
.cat-tabs {
  position: static;
  translate: none;
  left: auto;
  bottom: auto;
  display: inline-flex;
  flex-wrap: wrap;
  gap: 4px;
  background: var(--white);
  border-radius: 999px;
  padding: 4px;
  box-shadow: 0 1px 2px var(--shadow-1), 0 10px 30px var(--shadow-2);
}
.cat-tabs .car-tab { font-size: 14px; }   /* weight/height from .car-tab (the site's) */

/* Pill-logo page toggle (2026-07-22, both pages). Inverted rest/hover state:
   ink mark on a light tile, outlined with var(--grey) for definition on the
   white pill bar. The invert rides .pill-logo's existing 0.3s var(--ease)
   background+colour transition (defined above), nothing new added. */
.pill-logo.inverted { background: var(--white); box-shadow: inset 0 0 0 1px var(--grey); }   /* var(--grey) outline */
.pill-logo.inverted svg { color: var(--ink); }
.pill-logo.inverted:hover { background: var(--ink); }
.pill-logo.inverted:hover svg { color: var(--white); }

/* Connected-agent strip — reuses .news-strip; left-aligned content.
   Agent name ("Claude · Sonnet") → Headline, Medium. Its meta text
   ("Connected · last call...") → Subhead. */
.agent-strip { justify-content: space-between; }
.agent-strip .agent-id { display: inline-flex; align-items: center; gap: 10px; }
.agent-strip .agent-id strong { font-size: 18px; font-weight: 500; line-height: 24px; }
.agent-strip .agent-id span { color: var(--text-3); font-size: 14px; font-weight: 400; line-height: 20px; }

/* App-content buttons (.btn-pill inside .app-main — "Manage agent",
   "View all calls"). The marketing scale gave these 14px (bare .btn-pill)
   or 13px (.news-strip .btn-pill) — neither lands on the iOS scale, so
   both are normalised to Subhead (15) here; .app-main's equal specificity
   + later source order wins over both base rules. Weight kept at Medium
   (500) rather than Subhead's default Regular — a deliberate judgment call
   for pill-button legibility, per the task's "judge and report" allowance
   for buttons specifically. */
.app-main .btn-pill { font-size: 14px; font-weight: 500; line-height: 20px; }

@media (max-width: 1000px) {
  .stat-grid.cols-3 { grid-template-columns: repeat(2, 1fr); }
  .svc-grid { grid-template-columns: repeat(2, 1fr); }
  .modal-pair { grid-template-columns: 1fr; }   /* pair stacks — covers ~900px */
}
@media (max-width: 760px) {
  .stat-grid.cols-3 { grid-template-columns: 1fr; }
  .svc-grid { grid-template-columns: 1fr; }
  .dlist.activity .drow { grid-template-columns: 1fr 1fr; row-gap: 6px; }
  .dlist.activity .drow.head { display: none; }
  .dlist.caps .drow { grid-template-columns: 1fr; }
  .agent-strip { flex-direction: row; text-align: left; }
}

/* ================================================================
   IA REWORK  (2026-07-22 — dashboard + agents page. The dashboard was
   scoped by an account filter until 2026-07-28; it is one wallet now.)
   APPEND-ONLY block. Nothing above this line is touched. Every value
   below is copied from an existing selector/token in this file (or the
   iOS text scale already documented above); provenance cited inline.
   Nothing invented except the two DERIVED patterns flagged as such.
   ================================================================ */

/* --- Shared utilities --- */
/* Monospace address/key treatment — the only mono in the system is the
   terminal code block; reuse its exact stack for truncated 0x…/sk-… strings. */
.mono { font-family: "SF Mono", ui-monospace, "Menlo", monospace; }   /* == .tech-terminal pre */
/* Neutral status dot — grey from the scroll-rail idle tick colour. */
.sdot.mute { background: var(--mute-fill); }   /* == .rail i */

/* --- 1. Aggregate strip: 4-up stat grid (== .stat-grid.cols-3, four cols) --- */
.stat-grid.cols-4 { grid-template-columns: repeat(4, 1fr); }

/* --- Dismissible agent-filter indicator (URL ?agent=…) ---
   Pill shape from .chip-lite (marketing egg chips); background recoloured to
   the ink wash (.cap-plus 0.08) so it reads on the white app surface. Caption 1
   type. Top gap == .meter margin-top (14px). */
.filter-chip {
  display: none;                       /* JS reveals when ?agent is present */
  align-items: center;
  gap: 10px;                           /* == .svc-meta */
  background: var(--line);  /* == .cap-plus */
  border-radius: 999px;                /* == .btn-pill */
  font-size: 12px; font-weight: 500; line-height: 16px;   /* Caption 1 */
  padding: 9px 14px;                   /* == .chip-lite */
  margin-top: 14px;                    /* == .meter margin-top */
}
.filter-chip.show { display: inline-flex; }
.filter-chip .filter-x {
  border: 0; background: transparent; cursor: pointer;
  font-size: 12px; line-height: 1; color: var(--text-3);   /* Caption 1, matches the chip text */
  padding: 0; transition: color 0.25s var(--ease);   /* == .tip */
}
.filter-chip .filter-x:hover { color: var(--ink); }

/* --- 3. (was: per-account sections — removed 2026-07-28. There is ONE wallet,
   so the per-account section header, its address/balance/priority meta and the
   account filter tabs are all gone. The delegation list below is grouped by
   session instead; see "SESSION-GROUPED DELEGATIONS".) --- */

/* Delegation table columns: agent · budget(+meter) · services · expiry · status · action */
.dlist.dels .drow { grid-template-columns: 1.1fr 1.25fr 1.7fr 0.85fr 1fr auto; }
.del.is-hidden { display: none; }
/* Budget cell: remaining/cap on one line, meter stacked beneath (tighter than
   the standalone .meter's 14px top gap). */
.cell-budget { display: flex; flex-direction: column; }
.cell-budget .meter { margin-top: 8px; }   /* == .foot-col / .panel-meta gap */
.bud-cap { font-size: 12px; font-weight: 400; line-height: 16px; color: var(--text-3); }   /* Footnote */
.cell-exp { font-size: 14px; font-weight: 400; line-height: 20px; color: var(--text-2); font-variant-numeric: tabular-nums; }   /* Subhead == .cell-sub */

/* Small pill (Revoke) — geometry from the compact .news-strip .btn-pill; border
   + hover inversion from .btn-pill. Footnote type. */
.btn-mini {
  display: inline-flex; align-items: center; justify-self: end;
  background: var(--white); color: var(--ink);
  font-size: 14px; font-weight: 500; line-height: 18px;   /* Footnote, Medium (button legibility, per brief) */
  padding: 9px 16px;                   /* == .news-strip .btn-pill */
  border-radius: 999px;                /* == .btn-pill */
  border: 1px solid var(--line);   /* == .btn-pill */
  cursor: pointer;
  transition: background 0.25s var(--ease), color 0.25s var(--ease);   /* == .btn-pill */
}
.btn-mini:hover { background: var(--ink); color: var(--white); }

/* Text-link action (Reduce / Remove / empty-state link) == .foot-col a. */
.row-link {
  border: 0; background: transparent; cursor: pointer;
  font: inherit; font-size: 14px; font-weight: 400; line-height: 20px;   /* Footnote */
  color: var(--text-2); transition: color 0.25s;   /* == .foot-col a */
}
.row-link:hover { color: var(--ink); }

/* Acquired-position sub-rows under a delegation (indented, no full separators). */
.pos-list { display: flex; flex-direction: column; gap: 10px; padding: 12px 2px 16px; }   /* pad echoes .dlist head 12 / .drow inset 2 */
.pos-row { display: flex; align-items: center; gap: 12px; }   /* == .pill-bar gap */
.pos-tok { font-size: 14px; font-weight: 500; line-height: 20px; }   /* Footnote, Medium == .cell-name weight */
.pos-amt { font-size: 14px; font-weight: 400; line-height: 20px; color: var(--text-2); font-variant-numeric: tabular-nums; }   /* Footnote */
.pos-tag { font-size: 12px; font-weight: 400; line-height: 16px; color: var(--text-3); }   /* Caption 1 == .svc-verified */
.pos-actions { margin-left: auto; display: flex; align-items: center; gap: 14px; }
.pos-row .sdot { transition: background 0.25s var(--ease); }   /* quiet feedback flash == .tip timing */
.pos-row.gone { opacity: 0; transition: opacity 0.25s var(--ease); }
/* Spend-only badge / managed-empty note — Caption 1, sit where positions would. */
.badge-spend, .pos-note { display: inline-flex; align-items: center; gap: 7px; font-size: 12px; font-weight: 400; line-height: 16px; padding: 12px 2px 16px; }   /* Caption 1 */
.badge-spend { color: var(--text-3); }
.pos-note { color: var(--text-3); }

/* Empty-state (nothing under the active filter). Class name is historic. */
.acct-empty { display: none; padding: 24px 2px; font-size: 14px; font-weight: 400; line-height: 20px; color: var(--text-3); }   /* Subhead */
.acct-empty.show { display: block; }
.acct-empty a { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }   /* == .tech-copy a */

/* --- 4. Activity table (2026-07-28: the Account column is gone — one wallet.
   The base .dlist.activity 5-column grid at the top of this file governs:
   tool · action · amount · status · time). --- */
.dlist.activity .drow.is-hidden { display: none; }

/* ================================================================
   AGENTS PAGE
   ================================================================ */
/* Agent list — .text-card-grade card surface, laid out 2-up (== .svc-grid,
   two cols). Card chrome copied from .svc-card (surface/radius/padding/min-h). */
.agent-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--gutter); margin-top: var(--gutter); }   /* == .svc-grid */
.agent-card {
  position: relative;
  background: var(--card); border-radius: var(--r-lg); padding: 24px;   /* == .svc-card */
  min-height: 220px;                    /* == .svc-card */
  display: flex; flex-direction: column; gap: 18px;   /* == .svc-card gap */
}
.agent-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 18px; }
.agent-name { font-size: 18px; font-weight: 500; line-height: 24px; letter-spacing: -0.01em; }   /* Headline == .svc-name */
.agent-status { display: inline-flex; align-items: center; gap: 7px; font-size: 12px; font-weight: 400; line-height: 16px; color: var(--text-3); }   /* Caption 1 == .svc-verified */
.agent-meta { display: flex; flex-direction: column; gap: 8px; }   /* == .foot-col gap */
.agent-kv { display: flex; gap: 10px; font-size: 14px; line-height: 20px; }   /* Footnote */
.agent-kv .k { color: var(--text-3); flex: 0 0 auto; }
.agent-kv .v { color: var(--text-2); overflow-wrap: anywhere; }   /* == .stat-desc / .cell-sub tone */
.agent-chips { display: flex; flex-wrap: wrap; gap: 8px; }   /* == .egg-chips gap */
/* Small status chip — .chip-lite shape on an ink wash so it reads on --card.
   Used for the session card's delegation count and the dashboard's connected-
   wallet chip beside the H1 (2026-07-28; it carried account names before). */
.chip-acct { display: inline-flex; align-items: center; gap: 7px; background: var(--line); border-radius: 999px; font-size: 12px; font-weight: 400; line-height: 16px; padding: 6px 12px; }   /* Caption 1; bg == .cap-plus */
.chip-acct .sdot { width: 6px; height: 6px; }   /* == .rail i idle width doubled → small dot */
.agent-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: auto; }   /* == .tech-actions gap */

/* ================================================================
   FORM CONTROLS — DERIVED PATTERN (flagged in report)
   The design system ships NO inputs/selects anywhere. The marketing
   newsletter is a mailto .btn-pill with no field; the app had none. These
   controls are composed minimally from existing values only:
     surface  var(--white)
     border   1px var(--grey)      (== .stat-divider colour)
     radius   var(--r-md)          (== .panel-media)
     padding  12px 14px            (== .btn-pill vert 12 + .panel-nav a horiz 14)
     type     15/20 Subhead        (== app text scale)
     focus    border var(--ink)    (== app ink)
   ================================================================ */
.field { display: flex; flex-direction: column; gap: 8px; }   /* == .foot-col gap */
.field-label { font-size: 14px; font-weight: 400; line-height: 20px; color: var(--text-3); }   /* Footnote == .modal-sec-label */
.input, .select {
  width: 100%; font-family: inherit;
  font-size: 14px; font-weight: 400; line-height: 20px;   /* Subhead */
  color: var(--ink); background: var(--white);
  border: 1px solid var(--grey);        /* == .stat-divider colour */
  border-radius: var(--r-md);           /* == .panel-media */
  padding: 12px 14px;                   /* derived (see block header) */
  transition: border-color 0.25s var(--ease);   /* == .tip timing */
}
.input:focus, .select:focus { outline: none; border-color: var(--ink); }
.input::placeholder { color: var(--text-3); }   /* == .chip / .modal-backdrop ink tone */
.field-hint { font-size: 12px; font-weight: 400; line-height: 16px; color: var(--text-3); }   /* Caption 1 */
.gen-addr { font-size: 14px; line-height: 20px; color: var(--text-2); }   /* Footnote (+ .mono on the value) */

/* Toggle / function-permission rows — .dlist .drow chrome; the checked state is
   the directory's "Add" pattern (a green .sdot), grey (.mute) when off. */
.tog-list { display: flex; flex-direction: column; }
.tog-row {
  display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 24px;   /* == .dlist .drow */
  padding: 14px 2px; border-bottom: 1px solid var(--grey); cursor: pointer;         /* == .dlist .drow */
}
.tog-list .tog-row:first-child { border-top: 1px solid var(--grey); }   /* == .dlist .drow:first-child */
/* name+desc pair was two bare inline spans with no separating rule, so they ran
   together with zero gap. Fixed by reusing the directory modal's function-row
   layout verbatim: .dlist.fn .drow's minmax(84px, auto) 1fr column split, and
   .dlist .drow's 24px column gap (style.css:1517, :1324). */
.tog-row > div { display: grid; grid-template-columns: minmax(84px, auto) 1fr; gap: 24px; align-items: center; }   /* == .dlist.fn .drow + .dlist .drow gap */
.tog-name { font-size: 14px; font-weight: 500; line-height: 20px; }   /* Subhead, Medium == .cell-name */
.tog-sub  { font-size: 14px; font-weight: 400; line-height: 20px; color: var(--text-2); }   /* Footnote == .cell-sub */
.tog-row .sdot { transition: background 0.25s var(--ease); }   /* == .tip timing */

/* Feature toggle (Manage acquired assets) — same row visual, given its own block. */
.acq-toggle { margin-top: 4px; }

/* Segmented control (expiry presets) — reuse .cat-tabs / .car-tab; laid flush-left. */
.seg { display: inline-flex; }

@media (max-width: 1000px) {
  .stat-grid.cols-4 { grid-template-columns: repeat(2, 1fr); }
  .agent-grid { grid-template-columns: 1fr; }
}
@media (max-width: 760px) {
  .stat-grid.cols-4 { grid-template-columns: 1fr; }
  .dlist.dels .drow { grid-template-columns: 1fr 1fr; row-gap: 8px; }
}

/* ================================================================
   SESSIONS REWORK  (2026-07-22 — Agents → Sessions rename + bearer
   credential model). APPEND-ONLY; nothing above is touched. Every value
   copied from an existing selector/token; provenance cited inline.
   ================================================================ */

/* Per-card manage row (Rotate credential · Revoke) — pure layout, sits below
   the primary .agent-actions (which carries margin-top:auto). */
.agent-manage { display: flex; align-items: center; justify-content: space-between; gap: 12px; }   /* gap == .pos-row / .pill-bar */

/* Revoked session — muted card + frozen actions; the .sdot goes .mute (per brief). */
.agent-card.is-disabled { opacity: 0.55; }   /* == .agent-status ink alpha (0.55) reused as card dim */
.agent-card.is-disabled .agent-actions,
.agent-card.is-disabled .agent-manage { pointer-events: none; }

/* Two-step Create-session modal: only one .modal-body / footer Copy shows at a
   time. Both set display (flex / inline-flex), so [hidden] must be re-asserted —
   same reason .modal[hidden] is declared explicitly above. */
.modal-body[hidden] { display: none; }
.btn-pill[hidden] { display: none; }

/* One-time credential block — the ink console treatment of .tech-terminal, in a
   modal-sized surface. Token wraps rather than scrolls out of reach. */
.cred-block {
  background: var(--ink);               /* == .tech-terminal */
  border-radius: var(--r-md);           /* == .panel-media / .input */
  padding: var(--gutter);               /* 20px == grid gutter */
  overflow-x: auto;
}
.cred-token {
  display: block;
  font-size: 14px; line-height: 20px;   /* Subhead (on iOS scale; .mono adds the stack) */
  color: rgba(var(--white-rgb), 0.88);     /* == .tech-terminal pre */
  word-break: break-all;
}
/* "Shown once" caution — Footnote, led by the amber .sdot.wait traffic light. */
.cred-warn {
  display: inline-flex; align-items: center; gap: 8px;   /* gap == .modal-confirm */
  font-size: 14px; font-weight: 400; line-height: 20px;  /* Footnote */
  color: var(--text-2);         /* == .stat-desc tone */
}
/* "Connect your AI" steps — Subhead list, gutter-indented markers. */
.cred-steps { display: flex; flex-direction: column; gap: 10px; margin: 0; padding-left: var(--gutter); }   /* gap == .chain-list; indent == gutter */
.cred-steps li { font-size: 14px; font-weight: 400; line-height: 20px; color: var(--text-2); }   /* Subhead == .modal-desc tone */

/* ================================================================
   SERVICE VERIFICATION REWORK  (2026-07-22) — APPEND-ONLY. The old
   .svc-verified text badge ("● Verified" / "● In review") is removed
   from directory.html and the modal header markup (js/app.js buildModal,
   unmodifiable in this pass); .svc-meta already carried "category ·
   calls" (see its own comment above), so unverified cards just fold
   "In review" into that same line instead. Verified status now reads as
   a small inline glyph next to the service name.
   Colour: currentColor was picked over a fixed ink/green token
   (both offered) specifically so the glyph inherits automatically —
   var(--ink) on a resting white card, var(--white) once .svc-card.active
   sets color:white (the same cascade .svc-name already rides, per its
   own transition comment above), and var(--ink) again inside the
   always-white modal. A single fixed colour would need a second
   override rule for the black-card state; currentColor needs none.
   Shape: a bare stroke check (not a filled circle+check) — judged more
   legible at this inline size next to Headline/Title 1 text; a circle
   backdrop this small tends to blob with the glyph. Sized in em units
   (0.62em) so one rule serves both the card's Headline (17px) and the
   modal's larger Title 1 (28px) name line it sits next to, each scaled
   to "the line it sits on" as asked, without a second size rule.
   ================================================================ */
.verify-mark {
  display: inline-block;
  width: 0.62em;
  height: 0.62em;
  margin-left: 6px;
  vertical-align: middle;
}
/* modal-cat, once JS replaces its content with the cloned .svc-meta row
   (see app.js DIRECTORY VERIFICATION + SEARCH append block), needs no
   extra rule: .svc-meta / .svc-cat already carry their own type. */

/* ================================================================
   DASHBOARD REWORK  (2026-07-22) — APPEND-ONLY block. Nothing above
   this line is touched. Portfolio chart + asset panel, and the
   session-grouped delegation list with budget slider / expiry timeline
   / edit mode. Every value copied from an existing selector/token in
   this file; provenance cited inline. DERIVED patterns flagged.

   Provenance summary of reused tokens:
     surfaces  var(--card) / var(--white); radii var(--r-lg)=18 (== .stat-card),
               var(--r-md)=14 (== .panel-media); grid gap var(--gutter)=20.
     type      iOS scale already documented above (Title 1 28/34, Headline
               17/22 Medium, Subhead 15/20, Footnote 13/18, Caption 12/16).
     wash      rgba(38,38,38,0.08) == .cap-plus / .filter-chip ink wash.
     muted ink rgba(38,38,38,0.28) == .sdot.mute / .rail i idle.
     semantic  green var(--ok) (.stat-arrow.up), red var(--bad) (.stat-arrow.down).
     meter     .meter chrome (h6, radius 999, grey track, ink fill) reused
               verbatim for both the budget slider track and the timeline bar.
   ================================================================ */

/* --- 1. PORTFOLIO — DERIVED PATTERN (no chart precedent on the site).
   Two-up: chart ~2/3 left, asset panel ~1/3 right (2fr:1fr == the
   .stat-main space-between intent, gap == --gutter). Stacks at the
   existing 900/760 app breakpoints. --- */
.pf { display: grid; grid-template-columns: 2fr 1fr; gap: var(--gutter); margin-top: var(--gutter); align-items: start; }   /* gap == .svc-grid; top gap == .agent-grid margin-top */
.pf-chart {
  background: var(--card); border-radius: var(--r-lg); padding: 24px;   /* == .stat-card surface */
  display: flex; flex-direction: column; gap: 18px;                     /* == .svc-card gap */
}
.pf-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 18px; flex-wrap: wrap; }   /* == .agent-top */
.pf-readout { display: flex; flex-direction: column; gap: 4px; }   /* 4px == .stat-divider inner rhythm smallest step */
.pf-scope { font-size: 12px; font-weight: 400; line-height: 16px; color: var(--text-3); }   /* Footnote == .dlist head */
.pf-value { font-size: 28px; font-weight: 400; line-height: 34px; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }   /* Title 1 == h2.app-title */
.pf-delta { font-size: 12px; font-weight: 400; line-height: 16px; color: var(--text-3); font-variant-numeric: tabular-nums; }   /* Footnote */
.pf-delta.up { color: var(--ok); }    /* == .stat-arrow.up */
.pf-delta.down { color: var(--bad); }  /* == .stat-arrow.down */
/* Range tabs — .cat-tabs / .car-tab pattern reused verbatim; the .cat-tabs
   rule already sits inline (not absolute) and bumps .car-tab to Subhead. */
.pf-ranges { align-self: flex-start; }

/* Chart canvas — the SVG fills the box; height fixed to a comfortable
   ratio (aspect close to .car-media's landscape media). */
.pf-canvas { width: 100%; flex: 1 1 auto; min-height: 0; position: relative; }
.pf-canvas svg { display: block; width: 100%; height: 100%; }
/* SVG element colours — kept here so all provenance lives in CSS, not the
   JS string that assembles the geometry. */
.pf-area { fill: var(--line); }   /* == .cap-plus / .filter-chip wash */
.pf-line { fill: none; stroke: var(--ink); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.pf-grid { stroke: var(--grey); stroke-width: 1; }   /* == .stat-divider / .meter track colour */
.pf-lbl  { fill: var(--text-3); font-family: "Helvetica Neue W", sans-serif; font-size: 12px; line-height: 16px; }   /* Footnote, muted */
.pf-dot  { fill: var(--ink); }   /* current-value marker == line ink */

/* Asset panel — rows in .dlist chrome, NO header row (per brief).
   columns: symbol · amount · usd(right) · delta. */
.pf-alist .pf-arow {
  display: grid; grid-template-columns: 1fr auto; align-items: center;
  column-gap: 14px; row-gap: 2px;
  padding: 14px 2px; border-bottom: 1px solid var(--grey); cursor: pointer;   /* == .tog-row / .dlist .drow */
}
.pf-alist .pf-arow:first-child { border-top: 1px solid var(--grey); }   /* == .dlist .drow:first-child */
.pf-arow .pf-sym { font-size: 14px; font-weight: 500; line-height: 20px; }   /* Subhead Medium == .cell-name */
.pf-arow .pf-usd { font-size: 14px; font-weight: 400; line-height: 20px; justify-self: end; font-variant-numeric: tabular-nums; }   /* Subhead */
.pf-arow .pf-amt { font-size: 14px; font-weight: 400; line-height: 20px; color: var(--text-2); font-variant-numeric: tabular-nums; }   /* Footnote */
.pf-arow .pf-adelta { font-size: 12px; font-weight: 400; line-height: 16px; justify-self: end; font-variant-numeric: tabular-nums; color: var(--text-3); }   /* Caption 1 */
.pf-arow .pf-adelta.up { color: var(--ok); }
.pf-arow .pf-adelta.down { color: var(--bad); }
.pf-arow.active { background: var(--line); border-radius: var(--r-md); }   /* selected-asset highlight == ink wash; radius == .panel-media */
.pf-arow.active + .pf-arow { border-top: 0; }
.pf-arow.pf-all .pf-sym { color: var(--text-2); }   /* "All assets" reset row reads a touch quieter */

/* --- 2. SESSION-GROUPED DELEGATIONS --- */
.sgroup { margin-top: var(--margin); }   /* 40px rhythm between groups == --margin / .footer pad */
.sgroup:first-child { margin-top: 0; }
.sgroup.is-hidden { display: none; }
/* Group header — baseline flex row (== old .acct-head), name + status + total + revoke. */
.sg-head { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; padding-bottom: 12px; }   /* gap == .pos-row/.pill-bar; pad == .dlist head */
.sg-name { font-size: 18px; font-weight: 500; line-height: 24px; }   /* Headline Medium == .agent-name / .svc-name */
.sg-budget { font-size: 14px; font-weight: 400; line-height: 20px; color: var(--text-2); font-variant-numeric: tabular-nums; }   /* Subhead muted == .cell-sub tone */
.sg-head .btn-mini { margin-left: auto; }

/* Delegation row grid: waypoint · spend · receive · budget(slider + label) · actions.
   Reuses .dlist / .drow chrome from the base sheet. */
.dlist.sg-dels .drow { grid-template-columns: 1.1fr 0.55fr 0.55fr 1.7fr minmax(140px, auto); }   /* Waypoint · Spend · Receive · Budget · Actions — the last column is floored so the head ("Actions") and the row (Reduce · Revoke) size it identically */
.del-leg { font-variant-numeric: tabular-nums; align-self: center; }
/* Column 1 — the compact permissions chip (2026-07-28: the account chip that
   used to sit above it is gone; see the PERMISSIONS subsection below). */
.del-acct { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }   /* gap == .tl / .car-text-copy */
/* Wallet address on a chip (standing rule: account addresses are surfaced) —
   Caption 1, muted mono (.mono adds the family; 0.5 ink == .cell-time tone). */
.chip-addr { margin-left: 6px; font-size: 12px; font-weight: 400; line-height: 16px; color: var(--text-3); }
.del.is-hidden { display: none; }
.del.gone { opacity: 0; transition: opacity 0.25s var(--ease); }   /* == .pos-row.gone */

/* Budget meter — .meter chrome as the track. Fill = spent/cap, so 100% IS the
   approval cap. Read-only: it was a draggable slider until 2026-09-02, when the
   drag came off because a live grant's cap is the approval its owner signed and
   dragging it moved only the picture. */
.cell-budget { display: flex; flex-direction: column; }
.bud-track {
  position: relative; height: 6px; border-radius: 999px;   /* == .meter */
  background: var(--grey); margin-bottom: 8px;              /* track colour == .meter; gap == .foot-col */
}
.bud-fill { display: block; height: 100%; background: var(--ink); border-radius: 999px; }   /* == .meter > i */
/* .bud-handle lived here: the drag grip on the budget track. It was
   display:none outside .del.editing, and nothing can enter .editing now. */
.cell-budget .cell-num { font-size: 14px; font-weight: 400; line-height: 20px; font-variant-numeric: tabular-nums; }   /* Subhead */

/* THREE FAMILIES LIVED HERE, all orphaned by the 2026-09-02 Waypoints row.
   .tl / .tl-meter / .tl-days  the expiry meter and its "58d left" label. The
                               row has no Expires column any more.
   .del-edit-btn               the row-end "Edit" link.
   .del-edit                   the Save / Cancel footer the cap slider revealed.
   The slider itself is gone (see ROW ACTIONS in js/app.js) — a live grant's cap
   IS the approval its owner signed, so dragging it only moved the picture. */

/* Position stepper — only shown in edit mode; the +/- reuse .btn-mini geometry
   shrunk to a square grip; Remove stays a .row-link. Reduce/Remove of the old
   design fold in here. */
.pos-actions .pos-stepper { display: none; align-items: center; gap: 8px; }
.del.editing .pos-actions .pos-stepper { display: inline-flex; }
.del.editing .pos-actions .sdot { display: none; }   /* hide the quiet-feedback dot slot in edit mode */
.pos-step {
  width: 24px; height: 24px; display: grid; place-items: center;
  border: 1px solid var(--line); border-radius: 999px;   /* == .btn-mini border/radius */
  background: var(--white); color: var(--ink); cursor: pointer; line-height: 1;
  font-size: 14px; font-weight: 500;                                /* Subhead Medium glyph */
  transition: background 0.25s var(--ease), color 0.25s var(--ease);
}
.pos-step:hover { background: var(--ink); color: var(--white); }

/* --- 3. PERMISSIONS: slim-row chip + per-delegation popup --- */
/* Row permissions chip — replaces the old verbose .del-svc services text.
   Pill shape + ink wash from .chip-acct / .filter-chip; Footnote type (13/18,
   == the .del-svc it replaces). It is the click target for the popup, and the
   whole .del-acct service cell is clickable too. */
.del-acct[data-perms] { cursor: pointer; }
/* .perm-chip lived here. It styled the "swap · USDG → WETH" chip that led the
   budget row; the row now carries Spend and Receive as their own columns. */

/* Grant-facts strip — .dlist rows, label + value (two-up: 1fr + auto). */
.dlist.perm-facts .drow { grid-template-columns: 1fr auto; }
.dlist.perm-facts .cell-num { justify-self: end; }
/* A native fact's value carries its enforcement label beside it (v14). :has()
   so only those rows become a flex line — every other value cell is untouched. */
.dlist.perm-facts .cell-num:has(.del-wall) { display: inline-flex; align-items: center; gap: 8px; }   /* gap == .cell-status (:1355) */

/* Per-service group — service name over its function blocks (28px inter-block
   spacing is the .modal-body flex gap, so no extra margin is needed). */
.perm-svc-name { font-size: 18px; font-weight: 500; line-height: 24px; margin-bottom: 4px; }   /* Headline Medium == .sg-name */

/* Function block — name + badge, AI summary, then permitted-input lines.
   Top divider == the .dlist .drow separator; inner gap == .meter rhythm (14). */
.perm-fn { padding: 18px 0; border-top: 1px solid var(--grey); display: flex; flex-direction: column; gap: 14px; }
.perm-fn-head { display: flex; align-items: center; gap: 12px; }   /* == .sg-head / .pos-row gap */
.perm-fn-name { font-size: 14px; font-weight: 500; line-height: 20px; }   /* Subhead Medium == .cell-name */
/* Spending badge — green-dot chip, == .svc-verified "Verified" treatment.
   Read-only badge — same geometry, muted dot + muted text. */
.badge-spending, .badge-read { display: inline-flex; align-items: center; gap: 7px; font-size: 12px; font-weight: 400; line-height: 16px; }   /* Caption 1 == .svc-verified */
.badge-read { color: var(--text-3); }

/* AI summary block. */
.perm-sum { display: flex; flex-direction: column; gap: 6px; }   /* == .tl gap */
.perm-sum-head { display: inline-flex; align-items: center; gap: 8px; }
/* "AI" chip — small ink-wash pill; Caption 2 (11/13) from the documented iOS
   scale; wash == .chip-acct. */
.perm-ai {
  display: inline-flex; align-items: center;
  background: var(--line); border-radius: 999px;   /* == .chip-acct wash */
  font-size: 11px; font-weight: 500; line-height: 14px; letter-spacing: 0.04em;   /* Caption 2 */
  padding: 3px 7px; color: var(--text-2);
}
.perm-sum-label { font-size: 14px; font-weight: 400; line-height: 20px; color: var(--text-3); }   /* Footnote == .modal-sec-label */
.perm-sum-text { font-size: 14px; font-weight: 400; line-height: 20px; color: var(--text-2); max-width: 62ch; }   /* Subhead == .cell-sub tone */

/* Permitted-input lines — one constraint per row in .dlist chrome, tightened to
   the .tog-row / .pf-arow 14px inset so the stacked list reads compactly. */
.dlist.perm-inputs .drow { padding: 14px 2px; }   /* == .tog-row / .pf-arow */

/* --- Responsive: portfolio stacks (chart above assets), delegation rows fold. --- */
@media (max-width: 1000px) {
  .pf { grid-template-columns: 1fr; }   /* chart above assets == brief's stack */
}
@media (max-width: 760px) {
  .dlist.sg-dels .drow { grid-template-columns: 1fr 1fr; row-gap: 10px; }
  .sg-head .btn-mini { margin-left: 0; }
}

/* ================================================================
   SUBTAB IA  (2026-07-23) — APPEND-ONLY block. Nothing above is
   touched. The dashboard becomes one page with five hash-routed
   subtabs (Overview · Allowances · Sessions · Portfolio · Activity)
   directly under the H1. (A global account filter row sat below them
   until 2026-07-28; there is one wallet now, so it is gone.) The pill
   row itself is the EXISTING .cat-tabs / .car-tab component (no new
   tab visual invented); only layout spacing is added here, every
   value copied from an existing token. DERIVED: the Overview
   condensed-portfolio card reuses .pf-chart's surface verbatim.
   ================================================================ */

/* Subtab pill row — the shared .cat-tabs component, spaced below the H1.
   Gap == --gutter rhythm used between the old title and its first block,
   trimmed to 24px (== .stat-card padding step) so the two pill rows read
   as one control cluster. */
.dash-subtabs { margin-top: 24px; }   /* 24px == .stat-card / .pf-chart padding */

/* Panels — only the active subtab is shown; the rest carry [hidden]. Each
   panel's first .app-block is its :first-child, so the base rule already
   zeroes its top margin; the panel group is offset from the subtab row by
   --margin (the site's 40px section rhythm). */
.subpanels { margin-top: var(--margin); }   /* == --margin section rhythm */
.subpanel[hidden] { display: none; }

/* Overview condensed portfolio — total + delta readout over the asset list
   only (no chart, no range tabs). Card surface reused verbatim from
   .pf-chart (== .stat-card surface/radius/padding, .svc-card gap). */
.ov-portfolio {
  background: var(--card); border-radius: var(--r-lg); padding: 24px;   /* == .pf-chart / .stat-card */
  display: flex; flex-direction: column; gap: 18px;                     /* == .pf-chart / .svc-card gap */
  margin-top: var(--gutter);                                            /* == .pf margin-top */
}
/* Overview asset rows are display-only (the interactive chart lives on the
   Portfolio subtab), so drop the .pf-alist row's pointer cursor. */
.ov-alist .pf-arow { cursor: default; }

/* ================================================================
   ===== DESIGNER KIT (snippets) =====
   Visual component swaps ported from ../snippets/lab.css (the
   designer's UI kit). Selectors are adapted to the app's existing
   markup; lab.css values are the spec and WIN over the app's prior
   type/spacing on these three components (directory cards + search +
   filter, the portfolio dot-matrix chart + grouped asset panel, and
   the connect-to-account modal). Behaviours/markup/routing are
   unchanged — this block only restyles. Deviations from lab.css are
   noted inline where the app's structure forced one.
   ================================================================ */

/* ---------- SWAP 1 · Directory cards (lab.css .dir-card) ---------- */
/* re-skinned onto the app's .svc-card; keeps .active flip, dotPop,
   click-to-modal, verify-mark, and the added marker. */
.svc-grid .svc-card { padding: 22px; min-height: 200px; gap: 0; }           /* lab .dir-card */
.svc-card .dot-icon { width: 46px; height: 46px; margin-bottom: auto; }     /* lab .dir-icon 46px (app was clamp 40–54) */
/* corner go-arrow — lab .dir-go (the chain-card plus button, ↗ glyph) */
.svc-card .dir-go {
  position: absolute; top: 16px; right: 16px;
  width: 40px; height: 40px; border-radius: 50%;
  background: var(--line);
  display: grid; place-items: center; color: var(--ink);
  transition: background 0.25s var(--ease), color 0.25s var(--ease);
}
.svc-card .dir-go svg { width: 18px; height: 18px; }
.svc-card:hover .dir-go { background: var(--ink); color: var(--white); }
.svc-card.active .dir-go { background: rgba(var(--white-rgb), 0.12); color: var(--white); }
.svc-card.active:hover .dir-go { background: var(--white); color: var(--ink); }
.svc-card.active:hover { background: var(--ink-2); }                             /* lab .dir-card.dark:hover */
/* the added-marker dot would collide with the corner arrow — move it left */
.svc-card .svc-added { right: auto; left: 16px; }
/* name row w/ inline status — lab .dir-name (18px, flex, gap 8) */
.svc-card .svc-name {
  display: flex; align-items: center; gap: 8px;
  font-size: 18px; font-weight: 500; letter-spacing: -0.01em; line-height: 24px;
  margin-top: 40px;                                                         /* lab .dir-name */
}
.svc-card .svc-name .verify-mark { margin-left: 0; }                        /* flex gap already spaces it */
/* status tag — lab .dir-status (green/red/muted dot + label) */
.svc-card .dir-status {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11px; font-weight: 400; letter-spacing: 0.01em;
  padding: 3px 8px; border-radius: 999px;
  background: var(--wash); color: var(--text-3);
}
.svc-card .dir-status i { width: 6px; height: 6px; border-radius: 50%; background: var(--ok-bright); }
.svc-card .dir-status.offline i { background: var(--bad-bright); }
.svc-card .dir-status.review i { background: var(--mute-fill); }      /* Solstice "In review" muted dot */
.svc-card.active .dir-status { background: rgba(var(--white-rgb), 0.1); color: rgba(var(--white-rgb), 0.55); }
.svc-card .svc-meta { margin-top: 8px; }                                    /* lab .dir-meta */

/* ---------- SWAP 2 · Portfolio dot-matrix chart (lab.css .acc-chart) ---------- */
/* rendered into #pf-canvas by renderDots(); drives lab's dot columns
   from the app's own value series. */
#pf-canvas .acc-chart { --cell: 14px; padding-top: 20px; }
#pf-canvas .acc-dots { display: flex; height: calc(var(--cell) * 14); }
#pf-canvas .acc-mgroup { flex: 1; display: flex; align-items: flex-end; justify-content: space-between; }
#pf-canvas .acc-col {
  display: block; width: var(--cell);
  background-image: radial-gradient(circle, currentColor calc(var(--cell) * 0.26), transparent calc(var(--cell) * 0.26 + 0.5px));
  background-size: var(--cell) var(--cell);
}
#pf-canvas .acc-mgroup .acc-col { color: var(--mute-fill); transition: color 0.3s var(--ease); }
#pf-canvas .acc-mgroup:last-child .acc-col { color: var(--ink); }
#pf-canvas .acc-dots:has(.acc-mgroup:hover) .acc-col { color: var(--mute-fill); }
#pf-canvas .acc-dots .acc-mgroup:hover .acc-col { color: var(--ink); }
#pf-canvas .acc-months { display: flex; margin-top: 16px; font-size: 12px; line-height: 16px; letter-spacing: 0.01em; }
#pf-canvas .acc-months span { flex: 1; transition: color 0.3s var(--ease); }
#pf-canvas .acc-months .past { color: var(--text-4); }
#pf-canvas .acc-months .now { color: var(--ink); font-weight: 700; }
#pf-canvas .acc-chart:has(.acc-mgroup:hover) .acc-months span { color: var(--text-4); font-weight: 400; }
#pf-canvas .acc-chart:has(.acc-mgroup:nth-child(1):hover) .acc-months span:nth-child(1),
#pf-canvas .acc-chart:has(.acc-mgroup:nth-child(2):hover) .acc-months span:nth-child(2),
#pf-canvas .acc-chart:has(.acc-mgroup:nth-child(3):hover) .acc-months span:nth-child(3) { color: var(--ink); font-weight: 700; }
/* lab .acc-value size on the chart readout (scoped to the chart so the
   Overview readout, which shares .pf-value, is untouched) */
.pf-chart .pf-value { font-size: 44px; line-height: 48px; }

/* ---------- SWAP 2 · Asset rows (lab.css .acc-row / .acc-cell) ---------- */
.pf-alist .acc-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 14px 0; border-top: 1px solid var(--line);
}
.pf-alist .acc-row:first-child { border-top: 0; }
.pf-assets .pf-alist .acc-row { cursor: pointer; }
.ov-alist .acc-row { cursor: default; }
.acc-cell { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.acc-cell.right { align-items: flex-end; text-align: right; }
.acc-cell strong { font-size: 18px; font-weight: 500; letter-spacing: -0.01em; }
.acc-cell span { font-size: 12px; line-height: 16px; color: var(--text-3); }
.acc-cell span.up { color: var(--ok-deep); }
.acc-cell span.down { color: var(--bad); }
.pf-alist .acc-row.active { background: var(--wash); border-radius: var(--r-md); padding-left: 12px; padding-right: 12px; }
.pf-alist .acc-row.active + .acc-row { border-top: 0; }
.pf-alist .acc-row.pf-all .acc-cell strong { color: var(--text-2); }

/* ---------- SWAP 2 · (was: collapsible account groups + a "Connect account"
   tile under the asset list — removed 2026-07-28. One wallet means one flat
   .acc-flat asset list, styled by the .pf-alist .acc-row rules above.) ---------- */

/* ---------- SWAP 3 · New-delegation modal (lab.css .cn-*) ---------- */
#connect-modal .modal-card { width: min(880px, calc(100vw - 2 * var(--bleed))); }
#connect-modal .cn-body {
  position: relative; display: grid; grid-template-columns: 340px 1fr; gap: 40px;
  padding: 40px; height: min(74vh, 620px); min-height: 0;
}
#connect-modal .cn-close {
  position: absolute; top: 20px; right: 24px; z-index: 2;
  width: 34px; height: 34px; border: 0; border-radius: 50%;
  background: transparent; color: var(--text-3);
  display: grid; place-items: center; cursor: pointer;
  transition: background 0.25s var(--ease), color 0.25s var(--ease);
}
#connect-modal .cn-close:hover { background: var(--wash); color: var(--ink); }
#connect-modal .cn-close svg { width: 15px; height: 15px; }
#connect-modal .cn-left { display: flex; flex-direction: column; align-items: flex-start; min-height: 0; }
#connect-modal .cn-title { font-size: 28px; font-weight: 500; letter-spacing: -0.02em; line-height: 34px; }
#connect-modal .cn-tag {
  display: inline-flex; align-items: center; gap: 6px; margin: 16px 0 18px;
  font-size: 12px; font-weight: 500; padding: 5px 12px; border-radius: 999px;
  background: var(--card); color: var(--text-2);
}
#connect-modal .cn-tag i { width: 6px; height: 6px; border-radius: 50%; background: var(--ok-bright); }
#connect-modal .cn-copy { font-size: 14px; line-height: 20px; color: var(--text-3); max-width: 34ch; }
#connect-modal .cn-actions { margin-top: auto; display: flex; align-items: center; flex-wrap: wrap; gap: 16px 20px; }
#connect-modal .cn-approve {
  border: 0; background: var(--ink); color: var(--white);
  font-size: 14px; line-height: 20px; font-weight: 500; font-family: inherit;
  height: 44px; padding: 0 22px; border-radius: 999px; cursor: pointer;
  transition: background 0.25s var(--ease);
}
#connect-modal .cn-approve:hover { background: var(--ink-2); }
#connect-modal .cn-cancel {
  border: 0; background: transparent; font-size: 14px; line-height: 20px; font-weight: 500;
  font-family: inherit; color: var(--text-3); cursor: pointer;
  transition: color 0.25s var(--ease);
}
#connect-modal .cn-cancel:hover { color: var(--ink); }
#connect-modal .cn-confirm { flex-basis: 100%; }
#connect-modal .cn-form {
  min-height: 0; overflow-y: auto; scrollbar-width: none;
  display: flex; flex-direction: column; gap: 26px; padding-right: 8px;
}
#connect-modal .cn-form::-webkit-scrollbar { display: none; }
#connect-modal .cn-field { display: block; }
#connect-modal .cn-label { display: block; font-size: 14px; line-height: 20px; color: var(--text-3); margin-bottom: 8px; }
#connect-modal .cn-select { position: relative; }
#connect-modal .cn-select select,
#connect-modal .cn-input {
  -webkit-appearance: none; appearance: none; width: 100%; height: 46px;
  padding: 0 16px; background: var(--white); border: 1px solid var(--grey);
  border-radius: var(--r-md); font-size: 14px; font-family: inherit; color: var(--ink);
  outline: 0; cursor: pointer; transition: border-color 0.25s var(--ease);
}
#connect-modal .cn-input { cursor: text; }
#connect-modal .cn-select select:hover, #connect-modal .cn-select select:focus,
#connect-modal .cn-input:hover, #connect-modal .cn-input:focus { border-color: var(--text-4); }
#connect-modal .cn-select svg {
  position: absolute; right: 15px; top: 50%; translate: 0 -50%;
  width: 14px; height: 14px; color: var(--text-3); pointer-events: none;
}
#connect-modal .cn-help { font-size: 14px; line-height: 20px; color: var(--text-3); margin-top: 8px; }
#connect-modal .cn-list { list-style: none; display: block; }
#connect-modal .cn-list li {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 20px; padding: 13px 0; cursor: pointer;
}
#connect-modal .cn-list li + li { border-top: 1px solid var(--line); }
#connect-modal .cn-list strong { display: block; font-size: 14px; line-height: 20px; font-weight: 500; letter-spacing: 0.01em; }
#connect-modal .cn-list span { display: block; font-size: 14px; line-height: 20px; color: var(--text-3); margin-top: 3px; }
/* toggle switch — lab .cn-toggle (green when on) replaces the dot-toggle */
#connect-modal .cn-toggle {
  flex: 0 0 auto; position: relative; width: 40px; height: 22px; margin-top: 2px;
  border: 0; border-radius: 999px; background: var(--wash-2);
  cursor: pointer; transition: background 0.25s var(--ease);
}
#connect-modal .cn-toggle i {
  position: absolute; top: 2px; left: 2px; width: 18px; height: 18px;
  border-radius: 50%; background: var(--white); box-shadow: 0 1px 2px var(--shadow-2);
  transition: translate 0.25s var(--ease);
}
#connect-modal .cn-toggle.on { background: var(--ok-bright); }
#connect-modal .cn-toggle.on i { translate: 18px 0; }
/* expiry segmented control — lab .acc-seg */
#connect-modal .acc-seg { display: inline-flex; gap: 4px; background: var(--card); border-radius: 999px; padding: 4px; }
#connect-modal .acc-seg button {
  border: 0; background: transparent; font-size: 14px; line-height: 20px; font-weight: 500; font-family: inherit;
  color: var(--ink); display: inline-flex; align-items: center; height: 36px; padding: 0 14px;
  border-radius: 999px; cursor: pointer; white-space: nowrap;
  transition: background 0.3s var(--ease), color 0.3s var(--ease);
}
#connect-modal .acc-seg button:hover { background: var(--wash); }
#connect-modal .acc-seg button.active { background: var(--ink); color: var(--white); }
@media (max-width: 760px) {
  #connect-modal .cn-body { grid-template-columns: 1fr; gap: 24px; height: auto; padding: 28px; }
  #connect-modal .cn-actions { margin-top: 8px; }
}

/* ================================================================
   ===== PRODUCT REWORK (2026-07-28) — TOOLS · PULL MODEL · PROPOSALS =====
   Three new surfaces, all composed from values already in this file or in
   the DESIGNER KIT block above; provenance cited inline on every rule.
     1. the directory becomes a TOOL shelf (uses line + expert door)
     2. the tool modal gains context surfaces + an expandable USES layer
     3. the dashboard gains Proposals, "$0 at rest" and the wallet-side
        kill switch, and the grant modal becomes tool-first
   No new colours, radii, shadows or type sizes are introduced: the iOS
   scale documented at the top of the app section still governs
   (Title 1 28/34 · Headline 17/22 · Subhead 15/20 · Footnote 13/18 ·
   Caption 1 12/16 · Caption 2 11/13).
   ================================================================ */

/* ---------- 1a. Card "uses:" line (atoms + per-atom verified dot) ---------- */
/* Sits under .svc-meta as the third line of a tool card. Type == .svc-verified
   (Caption 1) so it reads a step below the category/calls meta; the dot is the
   6px .svc-card .dir-status i circle, in the .sdot semantic colours. */
.tool-uses {
  display: flex; align-items: center; flex-wrap: wrap; gap: 4px 10px;
  margin-top: 10px;                                              /* == .svc-meta gap */
  font-size: 12px; font-weight: 400; line-height: 16px;          /* Caption 1 == .svc-verified */
  color: var(--text-3);
}
.tool-uses-label { color: var(--text-4); }               /* == .modal-sec-label tone, one step muted */
.tool-atom { display: inline-flex; align-items: center; gap: 5px; }   /* == .svc-card .dir-status gap */
.tool-atom i {
  width: 6px; height: 6px; border-radius: 50%;                   /* == .svc-card .dir-status i */
  background: var(--mute-fill);                            /* == .sdot.mute */
}
.tool-atom i.ok { background: var(--ok); }                          /* == .sdot.ok */
/* the card flips to ink on .active — mirror .svc-card.active .svc-meta */
.svc-card.active .tool-uses { color: rgba(var(--white-rgb), 0.6); }
.svc-card.active .tool-uses-label { color: rgba(var(--white-rgb), 0.45); }
.svc-card.active .tool-atom i { background: rgba(var(--white-rgb), 0.3); }
/* one more line per card than before — keep the shelf's rows even */
.svc-grid .svc-card { min-height: 224px; }                        /* was 200px (DESIGNER KIT SWAP 1) */

/* ---------- 2a. Tool modal: context surfaces ---------- */
/* Rendered into a .dlist.fn, so the name/description column split is inherited.
   The stacked lines below the description are block children of .cell-sub. */
.dlist.ctx .cell-sub { display: block; }
.dlist.ctx .badge-spending, .dlist.ctx .badge-read { display: flex; margin-top: 8px; }
.ctx-line {
  display: block; margin-top: 8px;                                /* == .foot-col gap */
  font-size: 14px; font-weight: 400; line-height: 20px;           /* Footnote */
  color: var(--text-3);
}
.ctx-line b { font-weight: 500; color: var(--text-2); }   /* == .cell-name weight / .cell-sub tone */
/* Publisher copy is QUOTED, never paraphrased, and always labelled — the rule
   is left from .filter-chip's ink wash, at the divider colour. */
.ctx-hint {
  display: block; margin-top: 10px; padding-left: 14px;
  border-left: 1px solid var(--grey);                             /* == .stat-divider colour */
  font-size: 14px; font-weight: 400; line-height: 20px;           /* Footnote */
  color: var(--text-2);                                   /* == .cell-sub */
}
.ctx-hint-src {
  display: block; margin-top: 4px;                                /* == .modal-sec-label margin */
  font-size: 11px; font-weight: 500; line-height: 14px; letter-spacing: 0.04em;   /* Caption 2 == .perm-ai */
  text-transform: uppercase; color: var(--text-4);
}
/* Honesty label. Muted Caption 1, same family as .pos-tag / .badge-read. */
.ctx-enf {
  display: block; margin-top: 8px;
  font-size: 12px; font-weight: 400; line-height: 16px;           /* Caption 1 == .pos-tag */
  color: var(--text-3);
}

/* ---------- 2b. Tool modal: the USES stockroom (atoms, one level deep) ---------- */
.uses-note { margin-bottom: 12px; }                               /* == lab.css .acc-group stack gap */
.tool-atoms { display: flex; flex-direction: column; gap: 12px; } /* == lab.css .acc-group stack gap */
/* collapse chrome copied wholesale from the kit's lab.css .acc-group family */
.atom-item { background: var(--card); border-radius: var(--r-md); overflow: hidden; }
.atom-head {
  display: flex; align-items: center; gap: 12px; width: 100%;
  border: 0; background: transparent; font: inherit; color: var(--ink);
  text-align: left; padding: 16px; cursor: pointer;
  transition: background 0.25s var(--ease);
}
.atom-head:hover { background: var(--wash); }
.atom-head strong { font-size: 14px; line-height: 20px; font-weight: 500; letter-spacing: 0.01em; }
.atom-head .acc-chev { width: 16px; height: 16px; flex: 0 0 auto; color: var(--text-3); transition: rotate 0.35s var(--ease); }
.atom-item.open .acc-chev { rotate: 180deg; }
.atom-head .verify-mark { width: 14px; height: 14px; flex: 0 0 auto; }
.atom-listed, .atom-cat {
  font-size: 12px; font-weight: 400; line-height: 16px;           /* Caption 1 == .svc-verified */
  color: var(--text-3);
}
.atom-cat { margin-left: auto; }
.atom-body { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 0.45s var(--ease); }
.atom-item.open .atom-body { grid-template-rows: 1fr; }
.atom-inner { overflow: hidden; min-height: 0; }
.atom-inner > * { margin: 0 16px; }
.atom-desc {
  font-size: 14px; font-weight: 400; line-height: 20px;           /* Footnote */
  color: var(--text-2); padding-bottom: 4px;
}
.atom-fns { margin-bottom: 16px !important; width: auto; }        /* == lab.css .acc-group inner list bottom */
.atom-fns .drow:first-child { border-top: 1px solid var(--grey); }
.atom-fns .cell-sub { display: block; }
.atom-method {
  display: block; margin-bottom: 4px;
  font-size: 14px; line-height: 20px;                             /* Footnote (+ .mono stack) */
  color: var(--text-3);
}
/* the spend badge is its own statement, not a trailing clause */
.atom-fns .badge-spending, .atom-fns .badge-read { display: flex; margin-top: 8px; }
@media (prefers-reduced-motion: reduce) {
  .atom-body { transition: none; }
}

/* ---------- 3a. Subtab count badge (Proposals waiting) ---------- */
/* Inline pill inside the existing .car-tab; wash == .cap-plus / .chip-acct,
   inverted on the active ink tab exactly as .svc-card.active .dir-go does. */
.tab-badge {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; margin-left: 8px; padding: 0 5px;
  border-radius: 999px; background: var(--line);       /* == .cap-plus wash */
  font-size: 11px; font-weight: 500; line-height: 13px;           /* Caption 2 == .perm-ai */
  font-variant-numeric: tabular-nums; color: var(--text-2);
}
.car-tab.active .tab-badge { background: rgba(var(--white-rgb), 0.12); color: var(--white); }   /* == .svc-card.active .dir-go */
/* renderProposals() sets [hidden] when nothing is waiting; display above would
   otherwise win and leave a "0" pill sitting on the tab. */
.tab-badge[hidden] { display: none; }

/* ---------- 3b. Proposals list ---------- */
.prop-note {
  display: block; margin-top: 8px;                                /* == .foot-col gap */
  font-size: 14px; font-weight: 400; line-height: 20px;           /* Footnote == .stat-desc */
  color: var(--text-3);
}
/* columns: who · what · amount · actions (the account column went with the
   multi-account model, 2026-07-28; same shape family as .dlist.activity) */
.dlist.props .drow { grid-template-columns: 1fr 2fr 0.8fr auto; }
.prop-verb { font-weight: 400; color: var(--text-3); }    /* == .cell-time tone */
.prop-meta {
  display: block; margin-top: 6px;                                /* == .modal-head-text gap step */
  font-size: 12px; font-weight: 400; line-height: 16px;           /* Footnote */
  color: var(--text-3);
}
.prop-actions { display: flex; align-items: center; gap: 14px; justify-self: end; }   /* == .pos-actions */
.prop-approve { white-space: nowrap; }
#proposals.is-quiet .dlist.props { display: none; }

/* ---------- 3c. Pull-model facts on a delegation row ---------- */
/* Both reuse .pos-note (Caption 1, led by an .sdot traffic light) so they sit
   in the same slot as the spend-only / no-positions notes. */
/* display:flex so the fact takes its own line above the positions block */
.del-atrest { display: flex; color: var(--text-3); padding-bottom: 0; }   /* == .badge-spend */
.del-cutoff { display: flex; color: var(--text-2); padding-bottom: 0; }   /* == .cell-sub, one step louder */
.sg-cutoff { margin-left: 14px; white-space: nowrap; }            /* == .pos-actions gap */
.bud-cap { white-space: nowrap; }                                 /* "of $2,500 approval cap" stays on one line */

/* THE GAS FACT (2026-08-30) — the third member of the family above, and the
   only one that carries an action. It reads at .del-cutoff's tone because it
   is a blocker, not a reassurance, and it is led by the amber .sdot.wait every
   other caution in the app already uses. It renders only on a delegation whose
   executor deposit cannot cover one call; a healthy row emits nothing, and the
   removed standing gas chip stays removed. */
.del-gas { display: flex; flex-wrap: wrap; color: var(--text-2); padding-bottom: 0; }   /* == .del-cutoff, wrapping because it carries controls */
.del-gas-act { display: inline-flex; align-items: center; gap: 8px; }   /* == #connect-modal .cn-sell-cap */
/* The editable float. Field geometry == the grant modal's inline amount field
   (#connect-modal .cn-sell-amt); border/motion == .cn-input at rest. Same job
   as recovery.html's #deposit-amount, in this app's own chrome. */
.del-gas-amt {
  width: 96px; height: 34px; padding: 0 10px;                            /* == .cn-sell-amt */
  font-size: 14px; line-height: 20px; text-align: right; font-variant-numeric: tabular-nums; /* == .cn-sell-amt */
  font-family: inherit; color: var(--ink); background: var(--white);
  border: 1px solid var(--grey); border-radius: var(--r-md);              /* == .cn-input */
  outline: 0; transition: border-color 0.25s var(--ease);                 /* == .cn-input */
}
.del-gas-amt:hover, .del-gas-amt:focus { border-color: var(--text-4); }   /* == .cn-input:hover/:focus */
.del-gas-unit, .del-gas-calls { font-size: 12px; line-height: 16px; color: var(--text-3); }   /* Caption 1 == .cn-help / .pos-note */
.del-gas-manual { text-decoration: none; }                                /* == .row-link, which is a <button> everywhere else */
/* The collapsed session row's marker — .sess-badge with the traffic light in
   it, so the chip that says "Pool" and the chip that says "Needs gas" are the
   same chip. */
.sess-gas { display: inline-flex; align-items: center; gap: 7px; }        /* gap == .sess-status */

/* ---------- 3d. Grant modal: tool-first form ---------- */
/* All inside the kit's .cn-* scope, so only the new elements are styled. */
#connect-modal .cn-foot {
  flex-basis: 100%; order: 3;
  font-size: 14px; font-weight: 400; line-height: 20px;           /* Footnote */
  color: var(--text-3);                                   /* == .cn-help tone */
}
#connect-modal .cn-confirm { order: 4; }
#connect-modal .cn-surface-note { margin-top: -2px; margin-bottom: 6px; }
/* grant-surface rows carry a method line + a spend badge under the summary */
#connect-modal .cn-list .atom-method { display: block; margin: 4px 0 2px; color: var(--text-3); }
#connect-modal .cn-list .badge-spending,
#connect-modal .cn-list .badge-read { display: flex; margin-top: 8px; }
#connect-modal .cn-list .ctx-enf { margin-top: 4px; }
/* long grant-surface summaries: top-align the name column against the copy
   (the global .tog-row > div rule centres it, which floats short names) */
#connect-modal .cn-list li > div { align-items: start; }
/* custody badge — .cn-tag with the amber traffic light when parked is chosen */
#connect-modal .cn-custody { margin: 0 0 12px; }
#connect-modal .cn-custody.warn i { background: var(--warn); }        /* == .sdot.wait */
/* Advanced disclosure — the kit's .acc-group collapse, at form scale */
#connect-modal .cn-adv-head {
  display: flex; align-items: center; gap: 10px; width: 100%;
  border: 0; background: transparent; font: inherit; color: var(--ink);
  text-align: left; padding: 0; cursor: pointer;
}
#connect-modal .cn-adv-head strong { font-size: 14px; line-height: 20px; font-weight: 500; color: var(--text-3); }   /* == .cn-label */
#connect-modal .cn-adv-head .acc-chev { width: 14px; height: 14px; color: var(--text-3); transition: rotate 0.35s var(--ease); }
#connect-modal .cn-adv.open .acc-chev { rotate: 180deg; }
#connect-modal .cn-adv-body { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 0.45s var(--ease); }
#connect-modal .cn-adv.open .cn-adv-body { grid-template-rows: 1fr; }
#connect-modal .cn-adv-inner { overflow: hidden; min-height: 0; }
@media (prefers-reduced-motion: reduce) {
  #connect-modal .cn-adv-body { transition: none; }
}

/* ---------- 3e. Expert-door modal body ---------- */
#raw-modal .field { max-width: 420px; }                            /* == .cn-copy measure family */
#raw-modal .modal-foot .modal-confirm.show { opacity: 1; }

/* ---------- responsive: the shelf and the proposal rows ---------- */
@media (max-width: 1000px) {
  .dlist.props .drow { grid-template-columns: 1fr 1fr; gap: 12px 24px; }
  .prop-actions { justify-self: start; grid-column: 1 / -1; }
}

/* the "Listed" tag travels from the card into the modal title line — same pill
   as .svc-card .dir-status, restated here because the modal is outside .svc-grid */
.modal-title .dir-status {
  display: inline-flex; align-items: center; gap: 5px; vertical-align: middle;
  margin-left: 10px;                                              /* == .modal-cat gap */
  font-size: 11px; font-weight: 400; letter-spacing: 0.01em;      /* == .svc-card .dir-status */
  padding: 3px 8px; border-radius: 999px;
  background: var(--wash); color: var(--text-3);
}
.modal-title .dir-status i { width: 6px; height: 6px; border-radius: 50%; background: var(--mute-fill); }   /* == .sdot.mute */

/* A disabled action must LOOK disabled — the ink fill at the muted-copy
   opacity used everywhere else for inert text (.pos-note / .acct-empty tone). */
.btn-pill:disabled, .btn-pill.ink:disabled { opacity: 0.35; cursor: not-allowed; }
.btn-pill.ink:disabled:hover { background: var(--ink); color: var(--white); border-color: transparent; }

/* ================================================================
   3f. LIVE CONNECTION STATES (2026-07-29)
   Composed entirely from existing tokens: .chip-acct is the chip wash,
   .row-link the quiet inline control, .cn-help / .cn-foot the Footnote
   tone, .sdot the traffic light. Nothing new is invented — these rules
   only place the kit's own pieces into the four new states.
   ================================================================ */

/* The wallet slot beside the H1 holds the wallet chip plus, when the app is
   not live, one muted mode chip and any transient notice. */
.wp-wallet { display: flex; align-items: center; flex-wrap: wrap; gap: 10px 12px; }

/* Chip-scale button, so "Connect wallet" sits on the chip's own baseline
   rather than the app-content 15px scale. */
.wp-wallet .btn-pill { font-size: 14px; font-weight: 400; line-height: 18px; padding: 7px 15px; }
.app-main .wp-wallet .btn-pill { font-size: 14px; font-weight: 400; line-height: 18px; }

/* Quiet disconnect — .row-link, pushed off the address by the chip's own gap. */
.wp-disconnect { margin-left: 4px; font-size: 14px; line-height: 20px; }   /* == .chip-addr */

/* Mode + notice chips. Muted by default (they are meta, not content); the
   notice fades the way .modal-confirm does. */
.wp-mode { color: var(--text-3); }                       /* == .acct-empty tone */
.wp-mode[hidden] { display: none; }
.wp-note {
  opacity: 0; transition: opacity 0.25s var(--ease);              /* == .modal-confirm */
  color: var(--text-3);
  max-width: 46ch;
}
.wp-note.show { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .wp-note { transition: none; } }

/* THE GAS POSITION (v10 USER-PAYS-GAS). One more .chip-acct in the same slot —
   no new panel. The ETH figure wears .mono .chip-addr like the address does;
   the call count is Footnote-muted beside it, because the balance is the fact
   and the count is the reading of it. The low state is carried entirely by the
   amber .sdot.wait every other caution in the app already uses. */
.wp-gas[hidden] { display: none; }
.wp-gas-calls { font-size: 12px; line-height: 16px; color: var(--text-3); }   /* == .cn-help */

/* One-click gas funding, wherever a refusal or a step offers it: the same quiet
   inline .row-link as every other in-line control, just never wrapping away
   from the sentence it belongs to. */
.wp-gas-fund { white-space: nowrap; }
.wp-gas-fund:disabled { opacity: 0.5; pointer-events: none; }

/* The optional gas-float step's two controls, on their own line under the
   one-liner so the step still reads as one sentence plus a choice. */
#connect-modal .cn-gas-actions { display: flex; gap: 14px; margin-top: 4px; }         /* gap == .pos-actions */

/* Directory / other pages: the mode chip lands in the page head next to the
   title, where .app-head already spaces a trailing item. */
#registry .app-head > .wp-mode { align-self: flex-end; }

/* ---------- grant progress strip (New-delegation modal) ---------- */
/* One row per step of the real MetaMask sequence. Footnote type at .cn-foot's
   tone, led by the same traffic light every other status in the app uses. */
#connect-modal .cn-steps {
  flex-basis: 100%; order: 2;
  display: flex; flex-direction: column; gap: 8px;
  margin-top: 2px;
}
#connect-modal .cn-steps[hidden] { display: none; }
#connect-modal .cn-step {
  display: flex; align-items: flex-start; gap: 8px;                /* gap == .modal-confirm */
  font-size: 14px; font-weight: 400; line-height: 20px;            /* Footnote == .cn-foot */
  color: var(--text-3);
}
#connect-modal .cn-step .sdot { width: 6px; height: 6px; margin-top: 6px; }   /* == .chip-acct .sdot */
#connect-modal .cn-step.is-run,
#connect-modal .cn-step.is-done { color: var(--text-2); }
#connect-modal .cn-step.is-fail { color: var(--ink); }
#connect-modal .cn-step-note {
  display: block; margin-top: 2px;
  font-size: 14px; line-height: 20px; color: var(--text-3);   /* == .cn-help */
  word-break: break-word;
}
/* An approval moves nothing; a deposit moves money. In a batched grant that
   difference is the one fact in this strip that must not read as fine print,
   so the value sentence is lifted out of the note's muted tone. Size and
   line-height are the note's own — only tone and weight change. */
#connect-modal .cn-step-note strong {
  color: var(--text-2);   /* == #connect-modal .cn-step.is-run / .is-done */
  font-weight: 500;                /* == #connect-modal .cn-gas-once strong */
}

/* A prototype session card in live mode: its grant button is inert, and the
   existing :disabled treatment is the whole signal. */
.agent-card [data-connect]:disabled { pointer-events: none; }

/* A grant control that is a READ-OUT in live mode, not a choice: the on-chain
   policy is fixed by the route, so the switch shows state and refuses input.
   Dimmed to the same muted-ink the app uses for every other inert control. */
#connect-modal .is-locked { pointer-events: none; }
#connect-modal .is-locked .cn-toggle { opacity: 0.4; }

/* ================================================================
   ===== SESSIONS ACCORDION + PER-SESSION GRANT (2026-07-29) =====
   APPEND-ONLY block. Nothing above this line is rewritten. The dashboard's
   Overview surface becomes a list of SESSION DROPDOWNS: one collapsible row
   per session, its allowances as rows inside it.

   PROVENANCE. The collapse chrome is the designer kit's .acc-group family,
   verbatim — snippets/lab.css:386 (.acc-group: var(--card), var(--r-md),
   overflow hidden), :392 (.acc-group-head: flex, gap 12, full width, bare
   button, padding 16, background 0.25s var(--ease)), :406 (hover 0.04 wash),
   :407 (strong 14/700/0.01em), :408 (.acc-group-total margin-left auto,
   14px @0.55), :409 (.acc-chev 16px @0.55, rotate 0.35s), :416 (open →
   rotate 180deg), :418 (.acc-group-body, the 0fr→1fr grid-rows trick, 0.45s),
   :427 (.acc-group-inner overflow hidden, min-height 0). This app already
   carries the same family once, as .atom-item in the tool modal
   (style.css:2392 "collapse chrome copied wholesale from the kit's lab.css
   .acc-group family") — the rules below are that same port, so the two
   accordions in the app are visibly one component.

   Everything else is an existing token: type from the iOS scale documented at
   the top of the app section (Headline 17/22 Medium · Subhead 15/20 ·
   Footnote 13/18 · Caption 1 12/16), the ink wash rgba(38,38,38,0.08)
   (== .cap-plus / .chip-acct), the muted ink rgba(38,38,38,0.28)
   (== .sdot.mute / .rail i), the divider colour var(--grey), and the
   .btn-mini / .row-link / .meter / .dlist.sg-dels components unchanged.
   No new colour, radius, shadow or type size is introduced.

   NOW-UNUSED, kept only so no rule above is edited: .agent-grid /
   .agent-card* / .agent-top / .agent-meta / .agent-chips / .agent-actions /
   .agent-manage (the session CARD this accordion replaces), .sgroup / .sg-*
   (the session-grouped delegation list it replaces), and #connect-modal's
   .cn-custody / .cn-adv* (the Advanced custody disclosure removed from the
   minimised grant modal). .agent-kv / .agent-name / .agent-status keep
   earning their keep inside the accordion.
   ================================================================ */

/* --- 1. The list --- */
.sess-list { display: flex; flex-direction: column; gap: 12px; margin-top: var(--gutter); }   /* gap == lab .acc-groups / .tool-atoms; top gap == .agent-grid margin-top */

/* --- 2. The row (collapsed) --- */
.sess-item { background: var(--card); border-radius: var(--r-md); overflow: hidden; }   /* == lab .acc-group / .atom-item */
.sess-head { display: flex; align-items: center; gap: 12px; padding-right: 16px; }      /* gap/pad == lab .acc-group-head */
/* The whole left side of the head is the expand target. It is a real <button>,
   so the Add control has to sit outside it — buttons do not nest. */
.sess-toggle {
  flex: 1 1 auto; min-width: 0;
  display: flex; align-items: center; gap: 12px;
  border: 0; background: transparent; font: inherit; color: var(--ink);
  text-align: left; padding: 16px; cursor: pointer;
  transition: background 0.25s var(--ease);            /* == lab .acc-group-head */
}
/* The kit's head hover wash, applied to the WHOLE head rather than to the
   toggle alone — the Add button sits outside the toggle (buttons do not nest),
   and a wash that stopped short of it left a visible seam mid-row. :has() is
   already the mechanism the dot-matrix chart uses for its hover groups
   (#pf-canvas .acc-dots:has(...), style.css:2187). */
.sess-head:has(.sess-toggle:hover) { background: var(--wash); }   /* == lab .acc-group-head:hover */
.sess-toggle .acc-chev { width: 16px; height: 16px; flex: 0 0 auto; color: var(--text-3); transition: rotate 0.35s var(--ease); }   /* == lab .acc-chev */
.sess-item.open .acc-chev { rotate: 180deg; }           /* == lab .acc-group.open .acc-chev */
.sess-name { font-size: 18px; font-weight: 500; line-height: 24px; letter-spacing: -0.01em; overflow-wrap: anywhere; }   /* Headline Medium == .agent-name / .sg-name */
.sess-status { display: inline-flex; align-items: center; gap: 7px; flex: 0 0 auto; font-size: 12px; font-weight: 400; line-height: 16px; color: var(--text-3); }   /* Caption 1 == .agent-status */

/* The collapsed row's own numbers: cap / spent / remaining / count, inline.
   Value-over-label pairs in the kit's .acc-cell shape (lab .acc-row cell:
   column, 4px gap, 18px/500 value over 12px @0.5 label) — reused here at the
   app's tabular-nums treatment so four of them read as one strip. */
.sess-stats { margin-left: auto; display: flex; align-items: center; flex-wrap: wrap; gap: 6px 22px; }   /* == .acc-group-total margin-left; gap == .pos-actions / --gutter step */
.sess-stat { display: flex; flex-direction: column; gap: 2px; text-align: right; }
.sess-stat strong { font-size: 14px; font-weight: 500; line-height: 20px; font-variant-numeric: tabular-nums; }   /* Subhead Medium == .cell-name */
.sess-stat span { font-size: 12px; font-weight: 400; line-height: 16px; color: var(--text-3); }           /* Caption 1 == .acc-cell span */
/* The per-session Add affordance. .btn-mini unchanged; it only needs to stop
   stretching in the flex head. */
.sess-add { flex: 0 0 auto; white-space: nowrap; }
/* A revoked (offline-only) session reads muted and its controls are frozen —
   the treatment the session card used, moved onto the row. */
.sess-item.is-disabled .sess-name, .sess-item.is-disabled .sess-stats { opacity: 0.55; }   /* == .agent-card.is-disabled */
.sess-item.is-disabled .sess-manage { pointer-events: none; }

/* --- 3. The row (expanded) --- */
.sess-body { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 0.45s var(--ease); }   /* == lab .acc-group-body */
.sess-item.open .sess-body { grid-template-rows: 1fr; }
.sess-inner { overflow: hidden; min-height: 0; }        /* == lab .acc-group-inner */
.sess-inner > * { margin: 0 16px; }                     /* == .atom-inner > * (the head's own 16px inset) */
.sess-inner > *:last-child { margin-bottom: 16px; }     /* == .atom-fns bottom */
@media (prefers-reduced-motion: reduce) {
  .sess-body { transition: none; }
}
/* The allowance rows inside sit on the white sheet, not the card wash — the
   kit's own "white box within the grey card" (lab .acc-group-inner .acc-list). */
.sess-inner .dlist.sg-dels,
.sess-inner .sess-noalw {
  background: var(--white);
  border: 1.5px solid var(--line);           /* == lab .acc-group-inner .acc-list */
  border-radius: var(--r-md);
  padding: 2px 16px 6px;                                /* == lab .acc-group-inner .acc-list */
}
.sess-inner .dlist.sg-dels .drow:first-child { border-top: 0; }   /* == lab .acc-group-inner .acc-row:first-child */
.sess-inner .sess-noalw { padding: 18px 16px; }         /* the empty line needs its own breathing room */
.sess-noalw .row-link { text-decoration: underline; text-underline-offset: 3px; color: var(--ink); }   /* == .acct-empty a */

/* Credential actions, folded in from the old session card's manage row. */
.sess-manage {
  display: flex; align-items: center; flex-wrap: wrap; gap: 12px 18px;   /* gap == .sg-head / .svc-card */
  margin-top: 14px !important;                          /* == .meter rhythm */
}
.sess-manage .agent-kv { margin-right: auto; }          /* fingerprint left, controls right */

/* --- 4. Allowance-row actions (the two kill switches, per allowance) --- */
.del-actions { display: flex; align-items: center; gap: 14px; justify-self: end; }   /* == .pos-actions / .prop-actions */

/* --- 5. Permissions popup: the one read-only disclosure --- */
/* A single muted line at the foot of the popup. No rows, no toggles, no badge —
   a read-only capability moves nothing and draws nothing, so it is a footnote
   about the grant rather than a part of it. */
.perm-ro {
  font-size: 14px; font-weight: 400; line-height: 20px;   /* Caption 1 == .pos-tag / .badge-read */
  color: var(--text-3);                          /* == .pos-note */
}
/* "the route's full allowed set" — said under the token value it qualifies. */
.tok-src {
  display: block; margin-top: 2px;
  font-size: 11px; font-weight: 500; line-height: 14px; letter-spacing: 0.04em;   /* Caption 2 == .perm-ai / .ctx-hint-src */
  color: var(--text-4);
}

/* ================================================================
   6. GRANT MODAL: token pickers + verbatim error state
   All inside the kit's .cn-* scope, so only the new elements are styled and
   the modal's two-column shell, select, input, segmented control and toggle
   are untouched.
   ================================================================ */

/* A LOCKED leg. Not a disabled dropdown — a read-out, because a single legal
   value is a fact about the function, not a choice the user declined to make.
   Chrome == the kit's .cn-tag pill, widened to the field. */
#connect-modal .cn-tok-locked {
  display: flex; align-items: center; gap: 8px;
  background: var(--card); border-radius: var(--r-md);   /* == .cn-tag wash / .cn-input radius */
  padding: 12px 16px;                                    /* == .cn-input horizontal inset */
}
#connect-modal .cn-tok-locked strong { font-size: 14px; line-height: 20px; font-weight: 500; letter-spacing: 0.01em; }   /* == .cn-list strong */
#connect-modal .cn-tok-locked span { font-size: 12px; line-height: 16px; color: var(--text-3); }                 /* == .cn-list span / .cn-help */
#connect-modal .cn-lock { width: 13px; height: 13px; flex: 0 0 auto; color: var(--text-3); }  /* == .cn-select svg */

/* The picker itself: one chip per allowed token, multi-select. Chips use the
   kit's .cn-toggle "on" green for the selected state (the only affirmative
   colour in the modal) and the .cn-input border at rest. */
#connect-modal .cn-tok-opts { display: flex; flex-wrap: wrap; gap: 8px; }   /* == .agent-chips / .egg-chips gap */
#connect-modal .cn-tok-opt {
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  border: 1px solid var(--grey); border-radius: var(--r-md);   /* == .cn-input */
  background: var(--white); color: var(--ink); font-family: inherit;
  padding: 10px 14px; cursor: pointer; text-align: left;
  transition: border-color 0.25s var(--ease), background 0.25s var(--ease);   /* == .cn-input / .btn-pill */
}
#connect-modal .cn-tok-opt:hover { border-color: var(--text-4); }    /* == .cn-input:hover */
#connect-modal .cn-tok-opt strong { font-size: 14px; line-height: 20px; font-weight: 500; letter-spacing: 0.01em; }   /* == .cn-list strong */
#connect-modal .cn-tok-opt span { font-size: 12px; line-height: 16px; color: var(--text-3); }   /* Caption 2 == .cn-help tone */
#connect-modal .cn-tok-opt.on { border-color: var(--ok-bright); background: var(--ok-wash); }   /* == .cn-toggle.on green */
#connect-modal .cn-tok-opt.is-blocked { opacity: 0.4; cursor: not-allowed; }   /* == .btn-pill:disabled */
#connect-modal .cn-tok-opt em {
  font-style: normal; font-size: 12px; line-height: 16px;    /* Caption 2 */
  color: var(--text-3);
}
#connect-modal .cn-tok-opt .cn-tok-no { color: var(--bad); }    /* == .stat-arrow.down — the constraint, stated */
/* "+" — the kit's corner circle (.svc-card .dir-go) at chip scale. */
#connect-modal .cn-tok-add {
  align-self: stretch; width: 40px; flex: 0 0 auto;
  border: 1px dashed var(--mute-fill); border-radius: var(--r-md);
  background: transparent; color: var(--text-3);
  font-size: 18px; font-family: inherit; line-height: 1; cursor: pointer;
  transition: background 0.25s var(--ease), color 0.25s var(--ease);   /* == .svc-card .dir-go */
}
#connect-modal .cn-tok-add:hover { background: var(--ink); color: var(--white); }

/* The BUDGET token picker (2026-08-29). Same chips as the Receives leg, one
   field along — it is the same decision about the same kind of thing, so it
   gets the same chrome rather than a second vocabulary. It only needs the
   gap that separates it from the amount field above it. */
#connect-modal .cn-tok-bud { margin-top: 10px; }   /* == .cn-addtok */

/* OPEN MODE switch — "any token", on a route that pins no output. Reads as a
   row of the .cn-list toggle family (the copy underneath is the disclosure,
   so it gets .cn-list's own two-line treatment) inside .cn-tok-opt's border. */
#connect-modal .cn-anytok {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 12px 16px; margin-bottom: 10px;                     /* == .cn-tok-locked */
  border: 1px solid var(--grey); border-radius: var(--r-md);   /* == .cn-tok-opt */
  background: var(--white); cursor: pointer;
  transition: border-color 0.25s var(--ease), background 0.25s var(--ease);
}
#connect-modal .cn-anytok:hover { border-color: var(--text-4); }   /* == .cn-tok-opt:hover */
#connect-modal .cn-anytok.on { border-color: var(--ok-bright); background: var(--ok-wash); }   /* == .cn-tok-opt.on */
#connect-modal .cn-anytok input { margin-top: 2px; accent-color: var(--ink); flex: 0 0 auto; }
#connect-modal .cn-anytok span { display: flex; flex-direction: column; gap: 3px; }
#connect-modal .cn-anytok strong { font-size: 14px; line-height: 20px; font-weight: 500; letter-spacing: 0.01em; }   /* == .cn-list strong */
#connect-modal .cn-anytok em {
  font-style: normal; font-size: 12px; line-height: 16px;      /* Caption 2 == .cn-tok-opt em */
  color: var(--text-3);
}

/* Add-token disclosure. */
#connect-modal .cn-addtok { display: flex; flex-direction: column; gap: 10px; margin-top: 10px; }   /* gap == .chain-list */
#connect-modal .cn-addtok[hidden] { display: none; }
#connect-modal .cn-addtok-row { display: flex; align-items: center; gap: 14px; }   /* == .pos-actions */

/* Backend errors, verbatim. Led by the same red traffic light every other
   failure in the app uses; the code and the allowed set get their own lines
   because both are things the user copies or acts on. */
#connect-modal .cn-error {
  flex-basis: 100%; order: 2;
  display: flex; flex-direction: column; gap: 6px;      /* == .cn-steps */
}
#connect-modal .cn-error[hidden] { display: none; }
#connect-modal .cn-error-line {
  display: flex; align-items: flex-start; gap: 8px;     /* == .cn-step */
  font-size: 14px; font-weight: 400; line-height: 20px; /* Footnote == .cn-foot */
  color: var(--ink);                                    /* == .cn-step.is-fail */
}
#connect-modal .cn-error-line .sdot { width: 6px; height: 6px; margin-top: 6px; }   /* == .cn-step .sdot */
#connect-modal .cn-error-code,
#connect-modal .cn-error-allowed {
  font-size: 12px; line-height: 16px; color: var(--text-3);   /* == .cn-help */
  padding-left: 14px;                                   /* clears the dot column */
  word-break: break-word;
}
/* THE CREATE-SESSION MODAL'S REFUSAL (2026-09-01) — #ag-error. A failed
   create and a failed grant are the same kind of event, so they are the same
   component: every value here is the #connect-modal .cn-error rule directly
   above, restated for the second modal because those rules are id-scoped and
   this element is in the other one. No new value is introduced, and it needs
   no margin: .modal-body (:1525) is already a column flex with its own 28px
   gap, so the space above this line is the one the modal already uses. */
.ag-error {
  display: flex; flex-direction: column; gap: 6px;      /* == #connect-modal .cn-error */
}
.ag-error[hidden] { display: none; }
.ag-error .cn-error-line {
  display: flex; align-items: flex-start; gap: 8px;     /* == #connect-modal .cn-error-line */
  font-size: 14px; font-weight: 400; line-height: 20px; /* Footnote */
  color: var(--ink);
}
.ag-error .cn-error-line .sdot { width: 6px; height: 6px; margin-top: 6px; }   /* == #connect-modal .cn-error-line .sdot */

/* DECLUTTER (2026-08-29). Several .cn-help lines are now written only when
   they have something to say — the sell note when a budget token is chosen,
   the add-token line after a paste. An empty one must not still spend its
   margin, or the ticket keeps the gaps the sentences used to fill. */
#connect-modal .cn-help:empty { display: none; }

/* The kit sets no line-height on .cn-help, which reads cramped once a help
   line wraps (the function summary runs to four lines). 1.5 is the leading
   lab.css already uses for the same size of copy (.cn-list span). Scoped to
   this modal, appended rather than edited into the rule above. */
#connect-modal .cn-help { line-height: 1.5; }

/* --- 7. Responsive --- */
@media (max-width: 1000px) {
  /* four stats on one line stop fitting before the row does — let them wrap
     under the name rather than squeezing it. */
  .sess-toggle { flex-wrap: wrap; }
  .sess-stats { margin-left: 0; flex-basis: 100%; justify-content: flex-start; gap: 6px 18px; }
  .sess-stat { text-align: left; }
}
@media (max-width: 760px) {
  .sess-head { flex-wrap: wrap; padding: 0 16px 16px; }
  .sess-toggle { flex-basis: 100%; padding: 16px 0; }
  .sess-add { margin-left: 0; }
  .sess-manage { gap: 10px 14px; }
  .sess-manage .agent-kv { flex-basis: 100%; margin-right: 0; }
  .del-actions { justify-self: start; grid-column: 1 / -1; }
  #connect-modal .cn-tok-opt { flex: 1 1 100%; }
  #connect-modal .cn-tok-add { align-self: flex-start; height: 44px; }
}

/* ================================================================
   8. SELLABLE AUTHORITY (2026-07-29) — "may also sell" in the grant
   modal, and the unified position rows under an allowance.
   Two kinds of authority, said as two things: the USDC BUDGET (a cash cap,
   the ERC-20 approval the pull model is denominated in) and per-token
   SELLABLE CAPS over positions the user already holds (the v3 position
   model). Values are the ones already in this file — .cn-label /
   .cn-help / .cn-input / .cn-tok-* from the block above, .pos-row /
   .pos-tag / .row-link for the rows under an allowance.
   ================================================================ */

/* A field with more than one control needs a second heading level. Footnote
   weighted up one step from .cn-label, which stays the field's own label. */
#connect-modal .cn-sublabel {
  display: block; margin-bottom: 8px;                     /* == .cn-label */
  font-size: 14px; line-height: 20px; font-weight: 500; letter-spacing: 0.01em;   /* == .cn-list strong, at .cn-label size */
  color: var(--text-2);                           /* == .cell-sub tone */
}
#connect-modal .cn-sublabel-gap { margin-top: 22px; }     /* == .cn-form gap step (26) minus the help line */
#connect-modal .cn-sell { display: flex; flex-direction: column; gap: 8px; }   /* == .cn-tok-opts gap */

/* One granted sellable cap: token · "up to <amt> SYM" · what the wallet holds.
   Row chrome == .cn-tok-opt (the .cn-input border at rest, --r-md, white). */
#connect-modal .cn-sell-row {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px 12px;
  border: 1px solid var(--grey); border-radius: var(--r-md);   /* == .cn-tok-opt */
  background: var(--white); padding: 10px 12px;
}
#connect-modal .cn-sell-row.is-blocked { opacity: 0.4; border-style: dashed; }   /* == .cn-tok-opt.is-blocked */
#connect-modal .cn-sell-tok { display: flex; flex-direction: column; gap: 2px; min-width: 84px; }   /* == .cn-tok-opt */
#connect-modal .cn-sell-tok strong { font-size: 14px; line-height: 20px; font-weight: 500; letter-spacing: 0.01em; }
#connect-modal .cn-sell-tok span { font-size: 12px; line-height: 16px; color: var(--text-3); }
#connect-modal .cn-sell-cap { display: inline-flex; align-items: center; gap: 8px; margin-left: auto; }
#connect-modal .cn-sell-upto,
#connect-modal .cn-sell-unit { font-size: 12px; line-height: 16px; color: var(--text-3); }   /* == .cn-help */
/* the amount field is inline, so it overrides .cn-input's full-width block */
#connect-modal .cn-sell-amt {
  width: 96px; height: 34px; padding: 0 10px;
  font-size: 14px; line-height: 20px; text-align: right; font-variant-numeric: tabular-nums;
}
#connect-modal .cn-sell-held { flex-basis: 100%; font-size: 12px; line-height: 16px; color: var(--text-3); }
/* remove — the modal's own close glyph at row scale (== .cn-close) */
#connect-modal .cn-sell-x {
  width: 26px; height: 26px; flex: 0 0 auto; border: 0; border-radius: 50%;
  background: transparent; color: var(--text-3); font-family: inherit;
  font-size: 14px; line-height: 1; cursor: pointer;
  transition: background 0.25s var(--ease), color 0.25s var(--ease);   /* == .cn-close */
}
#connect-modal .cn-sell-x:hover { background: var(--wash); color: var(--ink); }
/* the adder: a select of what is left, and the same "+" as the Receives leg */
#connect-modal .cn-sell-add { display: flex; align-items: stretch; gap: 8px; }
#connect-modal .cn-sell-select { flex: 1 1 auto; }
#connect-modal .cn-sell-select select { height: 40px; font-size: 14px; }   /* == .cn-select select, one step down */
#connect-modal .cn-sell-add .cn-tok-add { align-self: stretch; }
#connect-modal .cn-sell-none,
#connect-modal .cn-sell-note { font-size: 14px; color: var(--text-3); line-height: 20px; }   /* == .cn-help */
#connect-modal .cn-sell-note { margin-top: 8px; }

/* Position rows under an allowance. .pos-row / .pos-tok / .pos-amt / .pos-tag /
   .pos-actions are unchanged; only the three additions are styled here. */
/* The source tag is the ONLY difference between an explicitly granted row and an
   auto-acquired one, so it gets the chip treatment rather than plain caption
   text — same wash as every other small chip in the app. */
.pos-tag {
  background: var(--line); border-radius: 999px;   /* == .chip-acct / .perm-ai wash */
  padding: 3px 9px;
}
/* the stepper is prototype fine-tuning; Reduce / Remove are the real controls
   and stay visible in both modes, on live rows too */
.pos-actions .row-link { white-space: nowrap; }
.pos-route { padding-top: 4px; padding-bottom: 0; }   /* == .del-atrest rhythm */

/* ================================================================
   9. THE POOL CUSTODY MODE (v8, 2026-07-29)
   A session CONVERTS to a pool and its accordion row changes character:
   the pot's composition replaces the budget meter (the pool IS the budget),
   there is no expiry meter (a pool is perpetual), and the four composition
   controls — add / remove / withdraw / dissolve — are owner-signed one-taps
   on the row itself.

   PROVENANCE. Not one new colour, radius, shadow or type size. Everything
   below is a value already in this file:
     · the composition list is the kit's .acc-row / .acc-cell asset row
       (style.css:2201 .pf-alist .acc-row — flex, space-between, 14px inset,
       0.08 top rule; :2209 .acc-cell 4px column, 18/500 over 12 @0.5), inside
       the same white-box-in-a-grey-card the allowance list already gets
       (style.css:2696 .sess-inner .dlist.sg-dels)
     · the semantic P&L colours are .acc-cell span.up var(--ok-deep) / .down var(--bad)
       (style.css:2213-2214), unchanged
     · the "Pool" badge is the .chip-acct / .pos-tag wash rgba(38,38,38,0.08)
       at 999px, Caption 1 12/16 (style.css:1736 / :2896)
     · the fact lines are .pos-note (style.css:1699-1701)
     · the inline panels (withdraw amount, remove/dissolve confirm) are the
       allowance row's own .del-edit reveal (style.css:2003) with the
       .cn-sell-row chrome (style.css:2860) — border var(--grey), --r-md, white
     · the modal's seed rows ARE .cn-sell-row, one scope along; its select and
       "+" are .cn-select / .cn-tok-add (style.css:2680 / :2773)
     · the step strip and error surface are #connect-modal's own (:2576 / :2790),
       re-declared for #pool-modal rather than edited into the rules above —
       the same discipline the .cn-help leading fix used.
   ================================================================ */

/* --- 1. The collapsed pool row --- */
/* Sits between the status and the stats strip. A pool is a KIND of session,
   not a state of one, so it reads as a label rather than a traffic light. */
.sess-badge {
  flex: 0 0 auto;
  background: var(--line); border-radius: 999px;   /* == .chip-acct / .pos-tag wash */
  padding: 3px 9px;                                           /* == .pos-tag */
  font-size: 12px; font-weight: 500; line-height: 16px;       /* Caption 1, Medium == .sess-stat span one weight up */
  color: var(--text-2);                               /* == .cell-sub tone */
}
/* P&L on the collapsed strip, in the same two semantic colours the asset rows
   use. Applied to the VALUE, because that is the number the eye lands on. */
.sess-stat strong.up { color: var(--ok-deep); }     /* == .acc-cell span.up */
.sess-stat strong.down { color: var(--bad); }   /* == .acc-cell span.down */

/* --- 2. The composition list (expanded) --- */
/* Same white box the allowance list gets, so a pool row and an allowance row
   sit at the same depth inside the card. */
.sess-inner .pool-comp {
  background: var(--white);
  border: 1.5px solid var(--line);   /* == .sess-inner .dlist.sg-dels */
  border-radius: var(--r-md);
  padding: 2px 16px 6px;
}
/* The kit's asset row, outside .pf-alist (which is where the base rule lives). */
.pool-comp .acc-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 14px 0; border-top: 1px solid var(--line);   /* == .pf-alist .acc-row */
}
.pool-comp .acc-row:first-child { border-top: 0; }                 /* == .pf-alist .acc-row:first-child */
.pool-comp .acc-cell.right { margin-left: auto; }                  /* value column, then the actions */
.pool-row-actions { display: flex; align-items: center; gap: 14px; flex: 0 0 auto; }   /* == .pos-actions */
.pool-row-actions .row-link { white-space: nowrap; }               /* == .pos-actions .row-link */
/* A token with no USDC pool cannot be priced, so it shows its amount and says
   why rather than a 0 that would be a lie. */
.pool-comp .acc-cell.right strong.mute { color: var(--text-3); }   /* == .pos-note tone */

/* --- 3. The fact lines under the composition --- */
/* Each is DOT + one text block. .pos-note centres its children, which is right
   for a one-line note and wrong here: these wrap, and a centred dot beside a
   three-line paragraph floats. Top-aligned, with the dot on the first line's
   optical centre (== .cn-step .sdot margin-top). */
.pool-facts { display: flex; flex-direction: column; gap: 2px; }
.pool-facts .pos-note { align-items: flex-start; padding: 6px 2px; }   /* tighter than .pos-list's 12/16 — three lines, one block */
.pool-facts .pos-note .sdot { margin-top: 5px; }
.pool-facts .pos-note > span { min-width: 0; }

/* --- 4. Pool controls + the inline panels --- */
/* Same shape as .sess-manage (the credential row it sits above), so the two
   control rows in an expanded pool read as one stack. */
.pool-manage {
  display: flex; align-items: center; flex-wrap: wrap; gap: 12px 18px;   /* == .sess-manage */
  margin-top: 14px !important;                                          /* == .sess-manage */
}
.pool-manage .pool-manage-label { margin-right: auto; font-size: 14px; line-height: 20px; color: var(--text-3); }   /* Footnote == .agent-kv .k */

/* An inline panel: the withdraw amount, or a confirm. Revealed in place, the
   way an allowance row reveals its Save/Cancel pair. */
.pool-panel {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px 12px;
  border: 1px solid var(--grey); border-radius: var(--r-md);   /* == .cn-sell-row */
  background: var(--white); padding: 12px;
  margin-top: 10px;                                            /* == .cn-addtok */
}
.pool-panel[hidden] { display: none; }
.pool-panel-t { font-size: 14px; font-weight: 500; line-height: 20px; }         /* Footnote Medium == .pos-tok */
.pool-panel-note { flex-basis: 100%; font-size: 14px; line-height: 20px; color: var(--text-3); }   /* Caption 1 == .cn-help */
.pool-panel-act { display: flex; align-items: center; gap: 14px; margin-left: auto; }   /* == .pos-actions */
.pool-panel-ctl { display: inline-flex; align-items: center; gap: 8px; margin-left: auto; }   /* == .cn-sell-cap */
.pool-panel-unit { font-size: 12px; line-height: 16px; color: var(--text-3); }   /* == .cn-sell-unit */
/* the amount field is inline here, so it overrides .input's full-width block */
.pool-amt {
  width: 116px; padding: 7px 10px;
  font-size: 14px; line-height: 20px; text-align: right; font-variant-numeric: tabular-nums;   /* == .cn-sell-amt */
}
/* The stepper is scoped OFF by `.pos-actions .pos-stepper { display:none }`
   (it is edit-mode-only on an allowance row); here it is a first-class control
   at the amount's own scale, so it is turned on with the kit's own values. */
.pool-panel .pos-stepper,
.pool-seed .pos-stepper { display: inline-flex; align-items: center; gap: 8px; }   /* == .pos-actions .pos-stepper */

/* --- 5. The recovery promise --- */
/* Muted, last, and present in BOTH modes: it is a property of the pot, not a
   feature of the server, so a prototype pool makes exactly the same promise. */
.pool-recovery {
  display: inline-flex; align-items: center; gap: 7px;
  margin-top: 12px !important;
  font-size: 14px; font-weight: 400; line-height: 20px;   /* Caption 1 == .pos-note */
  color: var(--text-3);
  text-decoration: underline; text-underline-offset: 3px;  /* == .acct-empty a */
}
.pool-recovery:hover { color: var(--ink); }   /* == .row-link:hover */

/* --- 6. The pool modal (convert / add token) --- */
/* The trust block: destination account chip + caption + the why-it's-safe list.
   Stacked, grouped tighter than the modal-body's 22px sections. */
.pool-trust { display: flex; flex-direction: column; gap: 10px; }   /* gap == .car-text-copy / .chain-list */
/* Destination account, on the connected-wallet chip's own .chip-acct chrome,
   hugging its content rather than stretching the column. */
.pool-acct { align-self: flex-start; max-width: 100%; }
.pool-acct.is-set { cursor: default; }
/* Why it's safe: 2-3 scannable points, each carrying the .pool-custody line's
   former chrome (== .cn-error-line row + .cn-foot Footnote + .cell-sub tone). */
.pool-safe { list-style: none; display: flex; flex-direction: column; gap: 8px; }   /* gap == .pool-seeds */
.pool-safe li {
  display: flex; align-items: flex-start; gap: 8px;        /* == .cn-error-line */
  font-size: 14px; font-weight: 400; line-height: 20px;    /* Footnote == .cn-foot */
  color: var(--text-2);                            /* == .cell-sub */
}
.pool-safe li .sdot { width: 6px; height: 6px; flex: 0 0 auto; margin-top: 6px; }   /* == .cn-step .sdot */
.pool-seeds { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; }   /* == .cn-sell */
/* One seed row == .cn-sell-row, verbatim. */
.pool-seed {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px 12px;
  border: 1px solid var(--grey); border-radius: var(--r-md);
  background: var(--white); padding: 10px 12px;
}
.pool-seed-tok { display: flex; flex-direction: column; gap: 2px; min-width: 84px; }   /* == .cn-sell-tok */
.pool-seed-tok strong { font-size: 14px; line-height: 20px; font-weight: 500; letter-spacing: 0.01em; }
.pool-seed-tok span { font-size: 12px; line-height: 16px; color: var(--text-3); }
.pool-seed-amt { display: inline-flex; align-items: center; gap: 8px; margin-left: auto; }   /* == .cn-sell-cap */
.pool-seed-unit { font-size: 12px; line-height: 16px; color: var(--text-3); }                          /* == .cn-sell-unit */
.pool-seed-held { flex-basis: 100%; font-size: 12px; line-height: 16px; color: var(--text-3); }   /* == .cn-sell-held */
.pool-seed-x {
  width: 26px; height: 26px; flex: 0 0 auto; border: 0; border-radius: 50%;
  background: transparent; color: var(--text-3); font-family: inherit;
  font-size: 14px; line-height: 1; cursor: pointer;
  transition: background 0.25s var(--ease), color 0.25s var(--ease);   /* == .cn-sell-x */
}
.pool-seed-x:hover { background: var(--wash); color: var(--ink); }
/* the adder — .cn-sell-add / .cn-select / .cn-tok-add, one scope along */
.pool-seed-add { display: flex; align-items: stretch; gap: 8px; margin-top: 8px; }   /* == .cn-sell-add */
.pool-seed-add[hidden] { display: none; }
.pool-select { position: relative; flex: 1 1 auto; }                                  /* == .cn-select */
.pool-select select {
  -webkit-appearance: none; appearance: none; width: 100%; height: 40px;
  padding: 0 16px; background: var(--white); border: 1px solid var(--grey);
  border-radius: var(--r-md); font-size: 14px; font-family: inherit; color: var(--ink);
  outline: 0; cursor: pointer; transition: border-color 0.25s var(--ease);   /* == .cn-sell-select select */
}
.pool-select select:hover, .pool-select select:focus { border-color: var(--text-4); }
.pool-select svg {
  position: absolute; right: 15px; top: 50%; translate: 0 -50%;
  width: 14px; height: 14px; color: var(--text-3); pointer-events: none;   /* == .cn-select svg */
}
.pool-add-btn {
  align-self: stretch; width: 40px; flex: 0 0 auto;
  border: 1px dashed var(--mute-fill); border-radius: var(--r-md);
  background: transparent; color: var(--text-3);
  font-size: 18px; font-family: inherit; line-height: 1; cursor: pointer;
  transition: background 0.25s var(--ease), color 0.25s var(--ease);   /* == .cn-tok-add */
}
.pool-add-btn:hover { background: var(--ink); color: var(--white); }
.pool-addtok-open { margin-top: 10px; text-decoration: underline; text-underline-offset: 3px; }   /* == .sess-noalw .row-link */
.pool-addtok { display: flex; flex-direction: column; gap: 10px; margin-top: 10px; }   /* == .cn-addtok */
.pool-addtok[hidden] { display: none; }
.pool-addtok-row { display: flex; align-items: center; gap: 14px; }                    /* == .cn-addtok-row */
#pool-modal .modal-body, #budget-modal .modal-body { gap: 22px; }   /* one step tighter than .modal-body's 28 — the sections here are short */

/* Step strip + verbatim errors, re-declared for this modal (the rules above are
   scoped to #connect-modal; appended rather than edited, == the .cn-help fix).
   #budget-modal is carried on the same selectors rather than given a copy: it
   is the same component doing the same job in the same shell, and two blocks
   with the same values are two blocks to keep in step. */
#pool-modal .cn-steps, #budget-modal .cn-steps { display: flex; flex-direction: column; gap: 6px; }
#pool-modal .cn-steps[hidden], #budget-modal .cn-steps[hidden] { display: none; }
#pool-modal .cn-step, #budget-modal .cn-step {
  display: flex; align-items: flex-start; gap: 8px;
  font-size: 14px; font-weight: 400; line-height: 20px;   /* Footnote == #connect-modal .cn-step */
  color: var(--text-3);
}
#pool-modal .cn-step .sdot, #budget-modal .cn-step .sdot { width: 6px; height: 6px; margin-top: 6px; flex: 0 0 auto; }
#pool-modal .cn-step.is-run, #budget-modal .cn-step.is-run,
#pool-modal .cn-step.is-done, #budget-modal .cn-step.is-done { color: var(--text-2); }
#pool-modal .cn-step.is-fail, #budget-modal .cn-step.is-fail { color: var(--ink); }
#pool-modal .cn-step-note, #budget-modal .cn-step-note { display: block; font-size: 14px; line-height: 20px; color: var(--text-3); }
#pool-modal .cn-error, #budget-modal .cn-error { display: flex; flex-direction: column; gap: 6px; }
#pool-modal .cn-error[hidden], #budget-modal .cn-error[hidden] { display: none; }
#pool-modal .cn-error-line, #budget-modal .cn-error-line {
  display: flex; align-items: flex-start; gap: 8px;
  font-size: 14px; font-weight: 400; line-height: 20px; color: var(--ink);
}
#pool-modal .cn-error-line .sdot, #budget-modal .cn-error-line .sdot { width: 6px; height: 6px; margin-top: 6px; flex: 0 0 auto; }
#pool-modal .cn-error-code, #budget-modal .cn-error-code,
#pool-modal .cn-error-allowed, #budget-modal .cn-error-allowed {
  font-size: 12px; line-height: 16px; color: var(--text-3);
  padding-left: 14px; word-break: break-word;
}

/* --- 7. Responsive --- */
@media (max-width: 760px) {
  .pool-comp .acc-row { flex-wrap: wrap; }
  .pool-row-actions { flex-basis: 100%; }
  .pool-panel-act, .pool-panel-ctl { margin-left: 0; }
  .pool-manage .pool-manage-label { flex-basis: 100%; margin-right: 0; }
  .pool-seed-amt { margin-left: 0; }
}

/* The pool row's own step strip. Same component as #connect-modal .cn-steps
   (style.css:2576) — one quiet dot per payload — declared here because the
   rules above are scoped to that modal and a row is not in it. */
.pool-row-steps { display: flex; flex-direction: column; gap: 6px; margin-top: 12px !important; }
.pool-row-steps[hidden] { display: none; }
.pool-row-steps .cn-step {
  display: flex; align-items: flex-start; gap: 8px;
  font-size: 14px; font-weight: 400; line-height: 20px;   /* Footnote == #connect-modal .cn-step */
  color: var(--text-3);
}
.pool-row-steps .cn-step .sdot { width: 6px; height: 6px; margin-top: 6px; flex: 0 0 auto; }
.pool-row-steps .cn-step.is-run,
.pool-row-steps .cn-step.is-done { color: var(--text-2); }
.pool-row-steps .cn-step.is-fail { color: var(--ink); }
.pool-row-steps .cn-step-note { display: block; font-size: 14px; line-height: 20px; color: var(--text-3); }

/* ================================================================
   ===== THE GRANT WIZARD (2026-08-29) — APPEND-ONLY =====
   The Add-allowance modal becomes three staged questions: which SERVICE in
   your registry, which of ITS FUNCTIONS, and then the order ticket. Nothing
   above this line is rewritten; the ticket itself (budget chips, Receives,
   may-also-sell, expiry) is the block at style.css:2755 unchanged.

   PROVENANCE — every value below is already in this file:
     type      the iOS scale documented at the top of the app section
               (Headline 17/22 Medium · Subhead 15/20 · Footnote 13/18 ·
               Caption 1 12/16 · Caption 2 11/14)
     surfaces  var(--card) wash + var(--r-md) == .atom-item / .cn-tok-locked
     borders   1px var(--grey) at rest, rgba(38,38,38,0.4) on hover
               == .cn-input / .cn-tok-opt (style.css:2270, :2773, :2780)
     rows      .dlist .drow — 24px column gap, 21px 2px padding, 1px
               var(--grey) bottom rule, first row gets a top rule
               (style.css:1321-1333)
     hover     rgba(38,38,38,0.04) == .atom-head:hover (style.css:2398)
     badges    .badge-spending / .badge-read + the .sdot traffic lights
               (style.css:2055, :1306) — reused verbatim, not restyled
     motion    0.25s var(--ease) == .cn-input / .btn-pill transitions
   No new colour, radius, shadow or type size is introduced.
   ================================================================ */

/* ---------- the credential IS the copy button ---------- */
/* .cred-block was an ink read-out (style.css:1823). It keeps every one of its
   values and gains the two things a button needs: a reason to hover and a
   place for the confirmation. The wash is the ink surface's own white at the
   .tech-terminal pre tone, stepped up — no new colour. */
.cred-block { position: relative; cursor: pointer; padding-right: calc(var(--gutter) + 62px); transition: background 0.25s var(--ease); }   /* transition == .cn-input */
.cred-block:hover, .cred-block:focus-visible { background: var(--ink-2); }   /* == #connect-modal .cn-approve:hover */
.cred-block:focus-visible { outline: 2px solid rgba(var(--white-rgb), 0.35); outline-offset: 2px; }
.cred-copy-hint {
  position: absolute; top: var(--gutter); right: var(--gutter);
  font-size: 12px; font-weight: 400; line-height: 16px;   /* Caption 1 == .badge-read */
  color: rgba(var(--white-rgb), 0.45);                       /* == .cred-token tone, muted */
  transition: color 0.25s var(--ease);
  white-space: nowrap;
}
.cred-block:hover .cred-copy-hint { color: rgba(var(--white-rgb), 0.88); }   /* == .cred-token */
/* Copied — the same green traffic light every other confirmation in the app
   uses, on the ink surface. Sticks for 1.8s == the #add-agent-confirm flash. */
.cred-block.is-copied .cred-copy-hint { color: var(--ok); }   /* == .sdot.ok */

/* ---------- where you are, in one line ---------- */
#connect-modal .cn-stepline {
  margin: -8px 0 18px;                                    /* pulls up to the .cn-tag's own 18px tail */
  font-size: 14px; font-weight: 400; line-height: 20px;   /* Footnote == .cn-foot */
  color: var(--text-3);                           /* == .cn-foot / .cn-help tone */
}
/* Back sits with Cancel and weighs the same — .cn-cancel verbatim. */
#connect-modal .cn-back[hidden] { display: none; }

/* ---------- the panes ---------- */
/* .cn-form is already a flex column with a 26px gap; a pane is simply the
   member of it that is showing, and inherits that column and that gap. */
#connect-modal .cn-step-pane { display: flex; flex-direction: column; gap: 26px; }   /* == .cn-form gap */
#connect-modal .cn-step-pane[hidden] { display: none; }
/* the fallback's reason, led by the amber traffic light every other caution in
   this app uses (== .cred-warn / .pos-note) */
#connect-modal .cn-degrade { margin-top: 0; }
#connect-modal .cn-degrade[hidden] { display: none; }
/* .cn-field is `display: block` (style.css:2267), which beats the UA's
   [hidden] rule — the wizard hides two whole fields (the flat <select>, the
   wizard's read-out) and needs [hidden] to actually win. */
#connect-modal .cn-field[hidden] { display: none; }

/* ---------- STEP 1 · the services in the registry ---------- */
/* One card per service. Surface and radius are .atom-item's (the tool modal's
   own collapsible service rows), so a registry service looks in the grant
   modal exactly like it looks in the directory modal. */
#connect-modal .cn-svc-list { display: flex; flex-direction: column; gap: 12px; }   /* == .tool-atoms */
#connect-modal .cn-svc {
  display: flex; align-items: flex-start; gap: 12px; width: 100%;   /* == .atom-head */
  border: 0; background: var(--card); border-radius: var(--r-md);   /* == .atom-item */
  font: inherit; color: var(--ink); text-align: left; padding: 16px; cursor: pointer;
  transition: background 0.25s var(--ease);                          /* == .atom-head */
}
#connect-modal .cn-svc:hover { background: var(--line); }   /* == .cap-plus wash — one step past .atom-head:hover, since the row IS the action */
#connect-modal .cn-svc:disabled { opacity: 0.4; cursor: not-allowed; }  /* == .cn-tok-opt.is-blocked */
#connect-modal .cn-svc-text { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
#connect-modal .cn-svc strong { font-size: 14px; line-height: 20px; font-weight: 500; letter-spacing: 0.01em; }   /* == .cn-list strong / .atom-head strong */
#connect-modal .cn-svc-desc {
  font-size: 14px; line-height: 20px; color: var(--text-3);   /* Caption 1 == .cn-list span */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
#connect-modal .cn-svc-meta {
  margin-top: 2px;
  font-size: 12px; line-height: 16px; color: var(--text-3);   /* Caption 2 == .cn-tok-opt span */
}
/* the chevron the .atom-head family already uses, at rest (no rotate here) */
#connect-modal .cn-svc .acc-chev { width: 16px; height: 16px; flex: 0 0 auto; margin-left: auto; color: var(--text-3); }   /* == .atom-head .acc-chev */

/* ---------- STEP 2 · that service's functions, as a table ---------- */
/* .dlist chrome, wrapped the way this sheet already wraps a three-fact row in a
   narrow column: the two SHORT facts share line one and the prose takes line
   two full-width. Precedent, both in this file: .cn-sell-row's
   `.cn-sell-held { flex-basis: 100% }` (style.css:2923) and .dlist.dels'
   responsive `row-gap: 8px` two-up (style.css:1797). The grant form's column is
   420px — a genuine 3-across left the description 105px, which is not a table,
   it is an ellipsis. */
#connect-modal .dlist.fn-pick { width: 100%; }
#connect-modal .dlist.fn-pick .drow {
  display: grid; grid-template-columns: 1fr auto;
  align-items: start; column-gap: 24px; row-gap: 6px;                  /* column gap == .dlist .drow */
  padding: 16px 12px;                                                  /* .dlist .drow 21/2, tightened for the second line, inset to a clickable card */
  border: 0; border-bottom: 1px solid var(--grey);                     /* == .dlist .drow */
  border-radius: var(--r-md);
  background: transparent; font: inherit; color: var(--ink);
  font-size: 14px; line-height: 20px;                                  /* Subhead == .dlist .drow */
  text-align: left; width: 100%; cursor: pointer;
  transition: background 0.25s var(--ease);                            /* == .atom-head */
}
#connect-modal .dlist.fn-pick .drow:first-child { border-top: 1px solid var(--grey); }   /* == .dlist .drow:first-child */
/* the header row keeps the base .dlist .drow.head treatment: Footnote, muted,
   tighter, and NO top rule (style.css:1332-1333) */
#connect-modal .dlist.fn-pick .drow.head {
  border-top: 0; padding: 12px 12px; cursor: default;
  font-size: 12px; font-weight: 400; line-height: 16px; color: var(--text-3);
}
#connect-modal .dlist.fn-pick button.drow:hover { background: var(--wash); }  /* == .atom-head:hover */
#connect-modal .dlist.fn-pick .drow.is-blocked { opacity: 1; cursor: default; background: transparent; }
/* goStep() focuses the first control on each pane, so the focus ring is seen on
   every transition — it has to be the app's own ink, not the UA's gold. Colour
   == .cn-input:focus / .cn-tok-opt:hover border. */
#connect-modal .cn-svc:focus-visible,
#connect-modal .dlist.fn-pick button.drow:focus-visible {
  outline: 2px solid var(--text-4); outline-offset: -2px; border-radius: var(--r-md);
}
#connect-modal .dlist.fn-pick .cell-name { font-size: 14px; font-weight: 500; letter-spacing: 0.01em; line-height: 20px; }   /* == .cell-name */
#connect-modal .dlist.fn-pick .atom-method { display: block; margin-top: 4px; color: var(--text-3); }   /* == #connect-modal .cn-list .atom-method */
/* the one-liner takes the whole second line */
#connect-modal .dlist.fn-pick .cell-sub {
  grid-column: 1 / -1;
  font-size: 14px; font-weight: 400; line-height: 20px;   /* Footnote — a one-liner, not a paragraph */
  color: var(--text-2);                           /* == .cell-sub tone */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
#connect-modal .dlist.fn-pick .cell-badge { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; white-space: nowrap; }
#connect-modal .dlist.fn-pick .fn-why {
  font-size: 12px; line-height: 16px; color: var(--text-3);   /* Caption 2 == .cn-tok-opt em */
  font-style: normal;
}

/* ---------- STEP 3 · the chosen route, as a read-out ---------- */
/* .cn-tok-locked's own chrome (style.css:2760): a settled fact in a card wash,
   with the one control that can unsettle it. */
#connect-modal .cn-picked {
  display: flex; align-items: center; gap: 8px;
  background: var(--card); border-radius: var(--r-md);   /* == .cn-tok-locked */
  padding: 12px 16px;                                    /* == .cn-tok-locked */
}
#connect-modal .cn-picked strong { font-size: 14px; line-height: 20px; font-weight: 500; letter-spacing: 0.01em; }   /* == .cn-tok-locked strong */
#connect-modal .cn-picked span { font-size: 12px; line-height: 16px; color: var(--text-3); }                 /* == .cn-tok-locked span */
#connect-modal .cn-picked .row-link { margin-left: auto; }   /* == .atom-cat / .sg-head .btn-mini push */

@media (max-width: 760px) {
  #connect-modal .dlist.fn-pick .drow { grid-template-columns: 1fr; row-gap: 8px; }   /* == .dlist.dels responsive */
  #connect-modal .dlist.fn-pick .cell-badge { align-items: flex-start; }
  /* a one-column table has no column headers == .dlist.activity .drow.head */
  #connect-modal .dlist.fn-pick .drow.head { display: none; }
  /* The corner label has nowhere to sit beside a wrapped token on a phone, so
     it becomes a second row. Flex column rather than a static child, because
     the block is an overflow-x scroller and an absolutely-positioned child
     taken out of flow does not simply fall back into it. Gap == .cred-steps.
     …and .modal-body is itself a scrolling flex COLUMN, so its children shrink
     below their content once the step overflows — which on a phone it does.
     flex 0 0 auto is what stops the ink block being squashed flat. */
  .cred-block { display: flex; flex-direction: column; gap: 10px; padding-right: var(--gutter); flex: 0 0 auto; }
  .cred-copy-hint { position: static; }
  /* the reveal step's footer is three controls wide since the wizard chaining
     landed (Copy credential · Later · Add a budget); at 375px they wrap rather
     than run off the card. Row gap == the .modal-foot column gap. */
  #add-agent-modal .modal-foot { flex-wrap: wrap; row-gap: 14px; }
}

/* ================================================================
   UI OVERHAUL (2026-08-29) — APPEND-ONLY block. Nothing above this
   line is edited. Every value below is copied from an existing
   selector or token in THIS file (or from the iOS text scale already
   documented at :1222); provenance is cited inline on every rule and
   the handful of DERIVED patterns are flagged as such.

   Six things: the sliding tab indicator, the pinned footer, the
   Overview three-column grid, the portfolio line chart, the activity
   table, and the fixed wallet square.
   ================================================================ */

/* ---------------------------------------------------------------
   1. SLIDING TAB INDICATOR
   ONE black shape that moves, instead of a background swapping from
   one button to another. The shape IS the old fill — .car-tab.active's
   ink background at .car-tab's own 999px radius (:934, :939) — lifted
   out into its own element so it can travel. The row keeps the .active
   fill until js/app.js has measured a laid-out button and added .slid,
   so a row that never gets a width never loses its selection marker.
   --------------------------------------------------------------- */
.cat-tabs { position: relative; }   /* the sliding pill's offset parent (js/tabs.js) */
@media (prefers-reduced-motion: reduce) { .car-tab-pill { transition: none; } }
}

/* ---------------------------------------------------------------
   2. THE FOOTER NEVER FLOATS
   .page.app already fills the viewport (:1202 min-height: 100vh); it
   just had no way to push its last child down, so a short page left
   the footer stranded mid-screen with white below it. Making the same
   box a column and letting <main> take the slack pins the footer to
   the bottom on short pages and leaves it in normal flow on tall ones.
   Applies to every app page: the shell is identical on all of them.
   --------------------------------------------------------------- */
.page.app { display: flex; flex-direction: column; }
.page.app > .app-main { flex: 1 0 auto; }
.page.app > .footer { flex: 0 0 auto; }
/* Both of these already carry `max-width: 1440px; margin-inline: auto` (:1211).
   An auto inline margin on a FLEX ITEM turns off the stretch that a block child
   got for free, so without this the two of them would size to their content and
   the whole app would shrink to whatever its widest row happened to be. The
   explicit 100% restores the block behaviour under the cap. */
.page.app > .app-main,
.page.app > .footer { width: 100%; }

/* ---------------------------------------------------------------
   3. THE OVERVIEW GRID — DERIVED PATTERN (flagged).
   Three columns: the four stat cards STACKED, the chart, the assets.
   The ratio extends .pf's own 2fr:1fr chart:assets split (:1901) with
   a 1fr stat column in front of it, and reuses .pf's gap and top gap
   verbatim so the block sits on the same rhythm as the Portfolio tab.
   --------------------------------------------------------------- */
/* THREE COLUMNS, ONE HEIGHT (2026-08-31). `align-items: start` let each column
   end wherever its content did — a 690px stat stack beside a 471px chart beside
   a 161px assets box, which is the raggedness the user called out. `stretch`
   is the grid default and the whole fix: every column now runs the full height
   of the row, and the row is as tall as whatever is genuinely tallest. The two
   cards then need to say what to do with the slack they are handed, which is
   the two rules under each of them below. */
/* TWO COLUMNS (2026-08-31c). The wallet-assets column is gone, and its 1fr
   goes to the chart rather than to whitespace: 1fr 2fr 1fr becomes 1fr 3fr, so
   the ratio is still derived from .pf's own chart:panel split (:1901) rather
   than picked. `stretch` stays — it is what keeps the stacked cards and the
   chart ending on the same line. */
.ov-grid { display: grid; grid-template-columns: 1fr 3fr; gap: var(--gutter); align-items: stretch; }   /* == .pf gap + column intent */
.stat-stack { display: flex; flex-direction: column; gap: var(--gutter); }   /* gap == .stat-grid */
/* A card in a narrow column has no room for the 220px floor the 4-up strip
   needed (:1268) — it only ever pushed the stack past the chart's height.
   Everything else about the card is untouched: surface, radius, the divider,
   the type. Padding steps 24px -> --gutter (20px), the app's own smallest
   layout step: cards that have to share one row height cannot each spend
   48px of it on inset. */
.ov-stats .stat-card.compact { min-height: 0; padding: var(--gutter); flex: 1 1 auto; }
.ov-stats .stat-value { font-size: 22px; line-height: 28px; }   /* Title 2 — the 4-up strip's Title 1 (:1278) does not fit a 1fr column */
.ov-stats .stat-divider { margin: 14px 0 12px; }                /* == .meter margin-top / .filter-chip top gap */
.ov-stats .stat-desc { font-size: 14px; line-height: 20px; }    /* Footnote == .bud-cap / .cell-exp tone step down */
/* "ONE BOX TAKES UP THESE TWO", said as a flex ratio: the AUM card grows at
   twice the rate of the budget card, so it occupies the two slots the removed
   Approved and Calls cards had while the budget card keeps the one slot
   Remaining had. `min-height: 0` lets the list inside it scroll rather than
   push the column past the chart. */
.ov-stats > .stat-card.compact { flex: 1 1 0; }
/* `.stat-card.aum-card` and not `.aum-card`: the rule above is (0,3,0) and a
   bare class would be (0,2,0), so the double height would silently lose to it. */
.ov-stats > .stat-card.aum-card { flex: 2 1 0; min-height: 0; }

/* ---- the BUDGET card's bars ----
   Pinned to the bottom of the card by the same `margin-top: auto` that puts
   every other stat card's .stat-main there (:538). One .bud-unit per
   denomination; the gap is .meter's own 14px rhythm. */
.bud-bars { margin-top: auto; display: flex; flex-direction: column; gap: 14px; }   /* gap == .meter margin-top (:1299) */
/* == .stat-main's own row (:538-543), which is what this replaces per unit. */
.bud-unit-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 12px; }
.bud-unit .meter { margin-top: 8px; }   /* == .cell-budget .meter (:1687) — the tight, in-row spacing */
.bud-unit .stat-value { white-space: nowrap; }
.bud-unit .bud-cap { white-space: nowrap; }

/* ---- the AUM card ----
   Label, then the list, then the total on the .stat-main line every other stat
   card puts its headline on. The list is the scrolling part because it is the
   only part whose length the app does not control. */
.aum-card { overflow: hidden; }
.aum-list { flex: 1 1 auto; min-height: 0; overflow-y: auto; margin-top: 12px; }   /* top gap == .ov-stats .stat-divider bottom (:3536) */
.aum-list .acc-row { padding: 10px 0; }             /* one step tighter than .ov-assets' 12px — this column also carries a total */
.aum-list .acc-cell strong { font-size: 18px; line-height: 24px; }     /* Callout == the removed .ov-assets rule — 18px crowds a 1fr column */
.aum-list .acc-row:first-child { border-top: 0; }   /* the .stat-label above is the divider */
.aum-list .acct-empty { padding: 0; }               /* == .ov-assets / .sp-card — the card already provides the inset */
.aum-list .is-wait { color: var(--text-4); }   /* == .stat-label's muted ink, for a figure still in flight */
.aum-card .stat-main { align-items: baseline; }
#aum-total-note { white-space: nowrap; }

/* The slack a stretched column hands the CHART goes to the canvas, which is
   already centred flex (:3538) — so the line keeps its own aspect and simply
   sits in the middle of a taller box, rather than the readout and the range
   pills drifting apart to fill it. */
.ov-grid > .pf-chart .pf-canvas { flex: 1 1 auto; }

/* ---- THE BLANK CHART (2026-08-31c) ----
   Disconnected there is no series, no total and no window to pick, so the
   readout and the range pills come out and the card is exactly what the user
   asked for: empty, with the text and the connect control in the middle of it.
   Nothing new is introduced — .pf-connect-btn is the .pill-logo tile (:285-291)
   at .act-logo's radius, and the copy is .acct-empty's own muted Subhead. */
.pf-chart.is-blank .pf-top { display: none; }
.pf-connect { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 18px; text-align: center; }   /* gap == .pf-chart / .svc-card (:1927) */
.pf-connect-line { font-size: 14px; line-height: 20px; color: var(--text-3); }   /* == .acct-empty (:1728) */
.pf-connect .cn-help { text-align: center; }
.pf-connect-btn {
  width: 48px; height: 48px;
  display: grid; place-items: center;
  background: transparent; color: var(--text-3);
  border: 0; border-radius: 0; cursor: pointer;
  transition: color 0.2s ease;
}
.pf-connect-btn svg { width: 38px; height: 38px; }
.pf-connect-btn:hover { background: transparent; color: var(--text-2); }

/* ---------------------------------------------------------------
   4. THE PORTFOLIO CHART
   The SVG line chart's element styles already exist, unused, at
   :1917-:1927 (.pf-area / .pf-line / .pf-grid / .pf-lbl / .pf-dot) —
   they are what this draws with, so no colour, stroke or type is
   added here. What IS added is a floor under the canvas, so an empty
   or one-point chart still occupies the space a full one does:
   14 cells x 14px + 20px pad + 16px gap + a label line == the height
   the dot-matrix chart held (:2177-:2189).
   --------------------------------------------------------------- */
.pf-canvas { min-height: 0; }
/* The svg keeps :1920's width:100% / height:auto — it scales by its own
   aspect ratio (720:260), which is what keeps the labels and the current-value
   dot round instead of stretched. The floor above only governs the EMPTY and
   one-point states, where there is less than a chart's worth to draw. */
/* The one-reading note. Footnote-quiet, at the muted copy tone every other
   caption in the app uses. Values == #connect-modal .cn-help (:2284, :2862). */
.pf-hist-note { font-size: 14px; line-height: 20px; color: var(--text-3); margin-top: 8px; }
.pf-hist-note[hidden] { display: none; }

/* ---------------------------------------------------------------
   5. THE ACTIVITY TABLE
   Six columns in the app's own .dlist chrome. The base
   .dlist.activity grid (:1335) is five columns; .acts restates it as
   six for the received column, on the same 24px column gap and the
   same row rule.
   --------------------------------------------------------------- */
.dlist.activity.acts .drow { grid-template-columns: 1.2fr 1.3fr 1fr 1fr 0.9fr 0.7fr; }
.act-venue { display: inline-flex; align-items: center; gap: 8px; min-width: 0; }   /* gap == .svc-card .svc-name */
.act-venue .cell-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The venue mark. 22px is .svc-card .dir-go's 40px tile at the scale a table
   row can carry; the monogram fallback wears .chip-acct's ink wash (:1736) at
   .pill-logo's radius family, so a protocol with no logo file still reads as
   the same kind of object as one that has. */
.act-logo { flex: 0 0 auto; width: 22px; height: 22px; border-radius: 7px; display: block; object-fit: contain; }
.act-mono {
  display: grid; place-items: center;
  background: var(--line);        /* == .chip-acct / .cap-plus wash */
  color: var(--text-2);              /* == .cell-sub / .agent-kv .v */
  font-size: 12px; font-weight: 500; line-height: 16px;   /* Caption 1, Medium */
}
/* The two directions money moved. Both tones are already in this sheet. */
.act-out { color: var(--bad); }   /* == .pf-delta.down / .acc-cell span.down */
.act-in  { color: var(--ok); }   /* == .pf-delta.up / .sdot.ok */
.act-nil { color: var(--text-4); }   /* == #pf-canvas .acc-months .past — the "nothing here" tone */
.act-amt { font-variant-numeric: tabular-nums; white-space: nowrap; }
.acts .act-action { font-size: 14px; line-height: 20px; overflow-wrap: anywhere; }   /* Footnote — a method name is data, not prose */
.acts .cell-status { text-transform: capitalize; }
.acts a.cell-status { color: inherit; text-decoration: none; }
.acts a.cell-status:hover, .acts a.cell-status:focus-visible { color: var(--ink); }
/* The venue filter row — the same .cat-tabs pill component as the subtabs,
   laid out under the section head at the subtab row's own offset (:2101). */
.act-venues { margin-top: 24px; }        /* == .dash-subtabs */
.act-venues[hidden] { display: none; }
.act-venues .car-tab { display: inline-flex; align-items: center; gap: 8px; }   /* == .act-venue */
.act-venues .car-tab .act-mono { background: var(--line); }
.act-venues .car-tab.active .act-mono { background: rgba(var(--white-rgb), 0.14); color: var(--white); }   /* == .svc-card.active .dir-status */
/* The protocol marks in assets/logos are the brands' own MONOCHROME variants
   (dark on transparent), which vanish on the selected pill's ink. Inverting the
   image is the same move .pill-logo.inverted (:1574) makes for the Waypoint
   mark on a light tile, and it introduces no colour of its own. */
.act-venues .car-tab.active img.act-logo { filter: invert(1); }
#activity .dlist.activity { margin-top: var(--gutter); }   /* == .pf margin-top */

/* ---------------------------------------------------------------
   6. THE WALLET SQUARE
   The header pill, mirrored to the right edge and starting square.
   Every value here is .pill / .pill-bar / .pill-logo / .pill-drawer
   (:262-:332) — the point of the control is that it is the same
   object as the header, so it is built out of the header's own rules.
   (The chips it replaces — .wp-mode at :2559 and .wp-gas at :2574 —
   are no longer rendered by js/app.js; their rules are left in place
   above rather than deleted, since nothing now matches them.)
   --------------------------------------------------------------- */
.wp-acct {
  position: fixed;
  top: 20px;                             /* == .site-header padding-top */
  /* ON THE FRAME, not on the viewport (2026-08-31). --bleed is still the inset
     it wants — the pill's own side margin — but it is measured from the 1440
     frame's right edge, which is where every other element on this page ends.
     Below 1440 --frame-gap is 0 and this is the original `right: var(--bleed)`
     exactly. */
  right: calc(var(--frame-gap) + var(--bleed));
  z-index: 101;                          /* one above .site-header (:256) */
  width: 56px;                           /* == .pill-bar height — a square */
  background: var(--white);                                                        /* == .pill */
  border-radius: 16px;                                                             /* == .pill */
  box-shadow: 0 1px 2px var(--shadow-1), 0 10px 34px var(--shadow-2); /* == .pill */
  overflow: hidden;                                                                /* == .pill */
  transition: width 0.6s var(--ease);                                              /* == .pill */
}
.wp-acct.open { width: min(300px, calc(100vw - 2 * var(--bleed))); }   /* == .pill.open shape, at panel scale */
.wp-acct-bar { display: flex; align-items: center; gap: 12px; padding: 7px; height: 56px; }   /* == .pill-bar */
.wp-acct-tile {
  flex: 0 0 auto; position: relative;
  width: 42px; height: 42px;             /* == .pill-logo */
  display: grid; place-items: center;    /* == .pill-logo */
  background: var(--ink);                /* == .pill-logo */
  border: 0; border-radius: 12px;        /* == .pill-logo */
  cursor: pointer;
  transition: background 0.3s var(--ease), color 0.3s var(--ease);   /* == .pill-logo */
}
.wp-acct-tile:hover { background: var(--ink-2); }   /* == .svc-card.active:hover (:2151) */
.wp-acct-glyph { display: grid; place-items: center; }
.wp-acct-glyph svg { width: 20px; height: 20px; color: var(--white); }   /* == .pill-logo svg */
/* Before connection the wallet mark is an icon, not a logo tile: no white slab behind it. */
.wp-acct.is-unconnected .wp-acct-tile { background: transparent; color: var(--text-3); }
.wp-acct.is-unconnected .wp-acct-tile:hover { background: var(--wash); color: var(--text-2); }
.wp-acct.is-unconnected .wp-acct-glyph svg { color: currentColor; width: 28px; height: 28px; }
.wp-acct.is-unconnected .wp-acct-dot { display: none; }
/* The status dot, pinned in the tile's corner — the .svc-added treatment
   (:1396), scaled to the smaller tile. THE ONLY place the app states offline. */
.wp-acct-dot { position: absolute; top: -1px; right: -1px; box-shadow: 0 0 0 2px var(--white); }
.wp-acct-name {
  flex: 1; min-width: 0;
  font-size: 14px; font-weight: 400; line-height: 20px;   /* Footnote — .pill-name's 17px is a wordmark's size, not an address's */
  color: var(--text-2);                           /* == .agent-kv .v */
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  opacity: 0; transition: opacity 0.3s var(--ease);       /* == .pill-logo timing */
}
.wp-acct.open .wp-acct-name { opacity: 1; }
.wp-acct-drawer { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 0.6s var(--ease); }   /* == .pill-drawer */
.wp-acct.open .wp-acct-drawer { grid-template-rows: 1fr; }                                                     /* == .pill.open .pill-drawer */
/* The 0fr -> 1fr reveal collapses the CONTENT box, not its padding, which is
   why .pill-panel (:333) carries none and puts it on .panel-main instead. Same
   split here: the panel is the clipping box, .wp-acct-inner is the padded one. */
.wp-acct-panel { min-height: 0; overflow: hidden; }   /* == .pill-panel */
.wp-acct-inner {
  display: flex; flex-direction: column;
  gap: 8px;                              /* == .agent-meta / .foot-col */
  padding: 4px 14px 16px;                /* 14px inset lines up with the bar's 7px pad + the tile edge */
}
.wp-acct-line { font-size: 14px; line-height: 20px; color: var(--text-3); }   /* == .pf-hist-note / .cn-help */
/* The address, click-to-copy. The credential block's affordance (.cred-block),
   at chip scale: the ink wash, a hover lift, and a corner label that flips to
   "Copied" for the same 1.8s. */
.wp-acct-addr {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%; border: 0; cursor: pointer; text-align: left;
  background: var(--line);    /* == .chip-acct */
  border-radius: var(--r-md);            /* == .pf-arow.active */
  padding: 9px 12px;                     /* == .chip-lite / .filter-chip */
  font-size: 14px; font-weight: 400; line-height: 20px;   /* Footnote */
  color: var(--ink);
  transition: background 0.25s var(--ease);   /* == .btn-mini */
}
.wp-acct-addr:hover { background: var(--wash-2); }   /* the wash, one step darker == .cap-plus:hover family */
.wp-acct-copy-hint { font-size: 11px; letter-spacing: 0.01em; color: var(--text-3); }   /* == .svc-card .dir-status */
.wp-acct-addr.is-copied .wp-acct-copy-hint { color: var(--ok); }   /* == .sdot.ok — the same green every "Copied" uses */
.wp-acct-acts { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-top: 4px; }   /* == .agent-actions */
.wp-acct-acts .btn-pill { font-size: 14px; font-weight: 400; line-height: 18px; padding: 7px 15px; }  /* == .wp-wallet .btn-pill (:2551) */
/* The notice slot beside the H1 is now notices only; with none showing it
   must not reserve a row of its own. */
.wp-wallet:empty { display: none; }

/* ---------------------------------------------------------------
   7. Responsive — at the app's own existing breakpoints (:1597, :2865).
   --------------------------------------------------------------- */
@media (max-width: 1200px) {
  /* Two columns held, at the ratio the row had before the assets column left
     (:3523). The stack narrows rather than the chart, because the chart is the
     one thing here that needs width to say anything. */
  .ov-grid { grid-template-columns: 1fr 2fr; }
}
@media (max-width: 1000px) {
  /* One column: the stack goes ABOVE the chart as a two-up row — budget beside
     AUM — == .stat-grid's own repeat(2, 1fr) default (:519-523). The double
     height is a column trick and has nothing to say on a row, so both cards go
     back to flexing equally. */
  .ov-grid { grid-template-columns: 1fr; }
  /* ONE CARD IN THE STACK SINCE 2026-09-02 (the budget box is gone), so the
     two-up row this was written for no longer exists — a repeat(2, 1fr) would
     leave the assets card at half width with dead space beside it. */
  .stat-stack { display: grid; grid-template-columns: 1fr; }
  .ov-stats > .stat-card.aum-card { flex: none; }
  .aum-list { max-height: 320px; }                                        /* it no longer has a chart's height to borrow */
  .ov-stats .stat-value { font-size: 28px; line-height: 34px; }           /* the 4-up strip's own Title 1 is back once there is room */
  .ov-stats .stat-card.compact { padding: 24px; }   /* the full inset is back: a full-width row is not fighting a chart for height */
}
@media (max-width: 760px) {
  .stat-stack { grid-template-columns: 1fr; }        /* == .stat-grid.cols-3 at :1603 */
  .sess-head-acts { width: 100%; justify-content: flex-start; }
  .sess-box { padding: 20px; }                       /* == --gutter, the app's smallest layout step */
  .dlist.activity.acts .drow { grid-template-columns: 1fr 1fr; row-gap: 6px; }   /* == .dlist.activity at :1605 */
  .dlist.activity.acts .drow.head { display: none; }                             /* == :1606 */
  .wp-acct.open { width: calc(100vw - 2 * var(--bleed)); }
}

@media (max-width: 620px) {
  /* The grey box gives its inset back to the rows it holds: the allowance row's
     budget meter and its action run are already tight at this width, and 24px
     of card padding on each side is 48px they do not have to spare. 12px is the
     app's own smallest inset step (== .cn-sell-row's 10-12px row padding). */
  .sess-box { padding: 12px; }
  /* Below this the 400px header pill and the square would collide, so the
     square drops under the header and .app-main makes room for it. Both
     offsets are the header's own stack: 20px top + 56px bar + 10px gap
     (== .pos-list gap) + 56px square + --margin. */
  .wp-acct { top: calc(20px + 56px + 10px); }
  .app-main { padding-top: calc(20px + 56px + 10px + 56px + var(--margin)); }
}

/* An attribution the registry could not make certain (two services publishing
   the same function at the same router, or an address-only match). Marked the
   way every other uncertain fact in this app is — quieter, with the whole
   reason in the tooltip — never with a new icon or colour. */
.act-venue.is-unsure .cell-name { color: var(--text-3); }   /* == .wp-mode / .acct-empty tone */

/* ================================================================
   BUDGET FLOW — Directory-gated, explicit cap, one clear review.
   ================================================================ */
#connect-modal .modal-card { width: min(920px, calc(100vw - 2 * var(--bleed))); }
#connect-modal .cn-body {
  grid-template-columns: 260px minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr) auto;
  height: min(82vh, 720px);
}
#connect-modal .cn-left { grid-column: 1; grid-row: 1 / 3; }
#connect-modal .cn-form { grid-column: 2; grid-row: 1; }
#connect-modal .cn-actions {
  grid-column: 2;
  grid-row: 2;
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--grey);
}
#connect-modal .cn-intro {
  max-width: 28ch;
  margin: -8px 0 20px;
  font-size: 14px;
  line-height: 20px;
  color: var(--text-3);
}
#connect-modal .cn-numbered .cn-label {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
  color: var(--text-2);
  font-size: 14px; line-height: 20px;
}
#connect-modal .cn-numbered .cn-label b {
  display: inline-grid;
  place-items: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--ink);
  color: var(--white);
  font-size: 12px; line-height: 16px;
  font-weight: 500;
}
#connect-modal .cn-cap-input { font-size: 18px; font-variant-numeric: tabular-nums; }
#connect-modal .cn-review {
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 16px;
  border-radius: var(--r-md);
  background: var(--card);
}
#connect-modal .cn-review > strong { font-size: 18px; line-height: 24px; font-weight: 500; }
#connect-modal .cn-review > span { font-size: 14px; line-height: 20px; color: var(--text-3); }
#connect-modal .cn-review ol { margin: 10px 0 0 18px; display: grid; gap: 7px; }
#connect-modal .cn-review li { padding-left: 3px; font-size: 14px; line-height: 20px; color: var(--text-2); }
#connect-modal .cn-review li b { color: var(--ink); font-weight: 500; }
#connect-modal .cn-advanced { border-top: 1px solid var(--grey); border-bottom: 1px solid var(--grey); }
#connect-modal .cn-advanced summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  list-style: none;
  padding: 16px 2px;
  cursor: pointer;
  font-size: 14px; line-height: 20px;
  font-weight: 500;
}
#connect-modal .cn-advanced summary::-webkit-details-marker { display: none; }
#connect-modal .cn-advanced summary span { display: inline-flex; align-items: center; gap: 8px; font-size: 12px; line-height: 16px; font-weight: 400; color: var(--text-3); }
#connect-modal .cn-advanced summary span::after { content: "+"; font-size: 14px; color: var(--ink); }
#connect-modal .cn-advanced[open] summary span::after { content: "−"; }
#connect-modal .cn-advanced-body { display: flex; flex-direction: column; gap: 26px; padding: 8px 2px 20px; }
#connect-modal .cn-empty-state {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
  padding: 20px;
  border-radius: var(--r-md);
  background: var(--card);
  color: var(--ink);
}
#connect-modal .cn-empty-state strong { font-size: 18px; line-height: 24px; font-weight: 500; }
#connect-modal .cn-empty-state span { font-size: 14px; line-height: 20px; color: var(--text-2); }
#connect-modal .cn-empty-state .btn-pill { margin-top: 4px; }
#connect-modal .cn-approve:disabled { opacity: 0.5; cursor: wait; }

/* Gas has two roles but only one user payment. This dedicated final screen
   replaces the easy-to-miss Send/Skip links in the transaction log. */
#connect-modal.gas-stage .cn-intro,
#connect-modal.gas-stage .cn-actions > .cn-cancel,
#connect-modal.gas-stage .cn-actions > .cn-foot { display: none; }
#connect-modal .cn-gas-stage { gap: 20px; }
#connect-modal .cn-gas-head { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; }
#connect-modal .cn-gas-head h3 { font-size: 22px; line-height: 28px; font-weight: 500; letter-spacing: -0.02em; }
#connect-modal .cn-gas-head p { font-size: 14px; line-height: 20px; color: var(--text-2); }
#connect-modal .cn-gas-flow { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
#connect-modal .cn-gas-flow > div {
  display: grid;
  grid-template-columns: 24px 1fr;
  gap: 5px 8px;
  align-content: start;
  padding: 16px;
  border-radius: var(--r-md);
  background: var(--card);
}
#connect-modal .cn-gas-flow b {
  grid-row: 1 / 3;
  display: grid;
  place-items: center;
  align-self: start;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--ink);
  color: var(--white);
  font-size: 12px; line-height: 16px;
  font-weight: 500;
}
#connect-modal .cn-gas-flow strong { font-size: 14px; line-height: 20px; font-weight: 500; }
#connect-modal .cn-gas-flow span { font-size: 14px; line-height: 20px; color: var(--text-3); }
#connect-modal .cn-gas-once { padding: 14px 16px; border-left: 3px solid var(--sky); font-size: 14px; line-height: 20px; background: rgba(161, 220, 254, 0.18); }
#connect-modal .cn-gas-once strong { font-weight: 500; }
#connect-modal .cn-gas-stage-actions { display: flex; align-items: center; gap: 18px; margin-top: auto; }

@media (max-width: 760px) {
  #connect-modal .cn-body { grid-template-columns: 1fr; grid-template-rows: auto minmax(0, 1fr) auto; height: min(88vh, 760px); }
  #connect-modal .cn-left { grid-column: 1; grid-row: 1; }
  #connect-modal .cn-form { grid-column: 1; grid-row: 2; }
  #connect-modal .cn-actions { grid-column: 1; grid-row: 3; }
  #connect-modal .cn-tag { margin: 8px 0; }
  #connect-modal .cn-stepline { margin: 0 0 10px; }
  #connect-modal .cn-intro { display: none; }
  #connect-modal .cn-actions { gap: 10px 14px; margin-top: 10px; padding-top: 10px; }
  #connect-modal .cn-foot { margin-top: 0; }
  #connect-modal .cn-gas-flow { grid-template-columns: 1fr; }
}

/* ================================================================
   BUDGET PICKER — protocol cards + compact action table
   ================================================================ */
#connect-modal .modal-card { width: min(780px, calc(100vw - 2 * var(--bleed))); }
#connect-modal .cn-body {
  display: grid;
  grid-template-columns: 1fr;
  grid-template-rows: auto minmax(0, 1fr) auto;
  grid-template-areas: "head" "form" "actions";
  gap: 24px;
  height: auto;
  max-height: min(90dvh, 680px);
  padding: 32px;
}
#connect-modal .cn-left { display: contents; }
#connect-modal .cn-head {
  grid-area: head;
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
  padding-right: 36px;
}
#connect-modal .cn-title { font-size: 28px; }
#connect-modal .cn-tag { margin: 0; }
#connect-modal .cn-stepline {
  margin: 0 0 0 auto;
  flex: 0 0 auto;
  font-variant-numeric: tabular-nums;
}
#connect-modal .cn-form {
  grid-area: form;
  gap: 18px;
  padding-right: 0;
}
#connect-modal .cn-actions {
  grid-area: actions;
  margin-top: 0;
  padding-top: 18px;
  border-top: 1px solid var(--grey);
  gap: 14px 18px;
}
#connect-modal .cn-foot { margin-left: auto; }
#connect-modal .cn-review { display: none !important; }
#connect-modal .cn-step-pane { gap: 18px; }

/* The same protocol marks used in the website's post-hero marquee. */
#connect-modal .cn-svc-list {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
}
#connect-modal .cn-svc {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: flex-start;
  aspect-ratio: 4 / 5;
  min-width: 0;
  padding: 18px;
  overflow: hidden;
  background: var(--card);
  border-radius: var(--r-lg);
}
#connect-modal .cn-svc-logo {
  position: absolute;
  inset: 0;
  width: 76px;
  height: 76px;
  margin: auto;
  background: var(--mute-fill);
  -webkit-mask: var(--logo) center / contain no-repeat;
  mask: var(--logo) center / contain no-repeat;
  transition: background 0.25s var(--ease), transform 0.35s var(--ease);
}
#connect-modal .cn-svc:hover .cn-svc-logo,
#connect-modal .cn-svc:focus-visible .cn-svc-logo {
  background: var(--ink);
  transform: scale(1.04);
}
#connect-modal .cn-svc-name {
  position: relative;
  font-size: 14px;
  font-weight: 500;
  line-height: 20px;
}
#connect-modal a.cn-svc { color: inherit; text-decoration: none; }
#connect-modal .cn-svc-add { background: transparent; box-shadow: inset 0 0 0 1px var(--line); }
#connect-modal .cn-svc-add .cn-svc-logo { width: 68px; height: 68px; }
/* Action / Budget: one reusable verb and a two-word explanation. */
#connect-modal #cn-fn-label {
  margin-bottom: 12px;
  font-size: 18px;
  font-weight: 500;
  line-height: 24px;
  color: var(--ink);
}
#connect-modal .dlist.fn-pick .drow {
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  min-height: 64px;
  padding: 12px;
  row-gap: 0;
  border-radius: 0;
}
#connect-modal .dlist.fn-pick .drow.head {
  min-height: 0;
  padding-block: 8px;
}
#connect-modal .dlist.fn-pick .fn-action { min-width: 0; }
#connect-modal .dlist.fn-pick .cell-name {
  display: block;
  font-size: 14px;
  line-height: 20px;
}
#connect-modal .dlist.fn-pick .cell-sub {
  display: block;
  grid-column: auto;
  margin-top: 1px;
  font-size: 14px;
  line-height: 20px;
  color: var(--text-3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
#connect-modal .dlist.fn-pick .cell-badge { display: block; }
#connect-modal .dlist.fn-pick .drow.is-blocked { color: var(--text-2); }
#connect-modal .cn-picked { padding: 10px 14px; }

@media (max-width: 760px) {
  #connect-modal .cn-body {
    grid-template-columns: 1fr;
    grid-template-rows: auto minmax(0, 1fr) auto;
    gap: 18px;
    height: auto;
    max-height: min(92dvh, 720px);
    padding: 24px;
  }
  #connect-modal .cn-head { flex-wrap: wrap; padding-right: 28px; }
  #connect-modal .cn-title { flex-basis: 100%; font-size: 22px; line-height: 28px; }
  #connect-modal .cn-stepline { margin-left: auto; }
  #connect-modal .cn-svc-list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  #connect-modal .cn-svc { padding: 14px; }
  #connect-modal .cn-svc-logo { width: 58px; height: 58px; }
  #connect-modal .dlist.fn-pick .drow { grid-template-columns: minmax(0, 1fr) auto; }
  #connect-modal .dlist.fn-pick .cell-badge { align-items: initial; }
  #connect-modal .cn-actions { margin-top: 0; }
  #connect-modal .cn-foot { display: none; }
}

/* Budget ticket: one visual language for Spend, Receive and Expires. */
#connect-modal .cn-budget-field { display: block; }
#connect-modal .cn-budget-field .cn-label {
  margin-bottom: 7px;
  font-size: 14px; line-height: 20px;
  font-weight: 500;
  color: var(--text-2);
}
#connect-modal .cn-budget-input {
  position: relative;
  display: flex;
  align-items: stretch;
  width: 100%;
  height: 52px;
  background: var(--white);
  border: 1px solid var(--grey);
  border-radius: var(--r-md);
  overflow: hidden;
  transition: border-color 0.25s var(--ease);
}
#connect-modal .cn-budget-input:focus-within { border-color: var(--text-4); }
#connect-modal .cn-budget-input > input {
  flex: 1 1 auto;
  min-width: 0;
  padding: 0 16px;
  border: 0;
  outline: 0;
  background: transparent;
  color: var(--ink);
  font-family: inherit; font-weight: 400; font-size: 14px; line-height: 20px;
}
#connect-modal .cn-inline-select {
  position: relative;
  display: flex;
  flex: 0 0 132px;
  border-left: 1px solid var(--grey);
}
#connect-modal .cn-inline-select select,
#connect-modal .cn-budget-select select {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 100%;
  padding: 0 42px 0 16px;
  border: 0;
  outline: 0;
  background: transparent;
  color: var(--ink);
  font-family: inherit; font-weight: 500; font-size: 14px; line-height: 20px;
  cursor: pointer;
}
#connect-modal .cn-inline-select svg,
#connect-modal .cn-budget-select > svg {
  position: absolute;
  top: 50%;
  right: 15px;
  width: 15px;
  height: 15px;
  translate: 0 -50%;
  color: var(--text-3);
  pointer-events: none;
}
/* A Waypoint with nothing budgetable, and a capability that cannot carry a cap
   (2026-08-31c). Both are SHOWN — hiding them is what made a service the user
   had added look as if it did not exist. The treatment is the app's own
   disabled tone (.cn-tok-opt.is-blocked, :2835) plus the neutral chip wash
   (.pos-tag, :2996); nothing here is red, because "cannot be budgeted yet" is
   a limitation of this app, not a fault of the service. */
#connect-modal .cn-svc.is-nobudget { opacity: 0.72; }
#connect-modal .cn-svc-tag {
  font-style: normal; font-size: 11px; line-height: 14px; letter-spacing: 0.02em;
  padding: 2px 7px; border-radius: 999px;                       /* == .pos-tag */
  background: var(--line); color: var(--text-3);
}
#connect-modal .dlist.fn-pick .drow.is-nobudget { opacity: 0.6; cursor: default; }
#connect-modal .fn-why { color: var(--text-3); }        /* == .cn-help tone */
#connect-modal .fn-none { padding: 10px 2px 2px; }               /* == .cn-help, on the row rhythm */

#connect-modal .cn-budget-select { display: block; }

/* ================================================================
   THE SWAP TICKET AND ITS TOKEN SEARCH (2026-08-31c).

   Nothing new is invented here. The pair row reuses .cn-budget-field's own
   label and .cn-budget-input's own 52px field; the picker's trigger IS the
   .cn-inline-select cell it replaces, at the same 132px and the same left
   border; the dropdown is .cn-tok-opt's border/radius/white on the modal's own
   popover elevation; and the rows are .cn-tok-opt's two-line strong+mono.
   ================================================================ */
/* FROM → TO. Two legs and the direction between them. On a narrow modal it
   stacks and the arrow rotates, so the sentence still reads top-to-bottom. */
#connect-modal .cn-swap { display: grid; grid-template-columns: 1fr auto 1fr; align-items: end; gap: 12px; }   /* gap == .cn-sell-row's own 12px */
#connect-modal .cn-swap .cn-label {
  margin-bottom: 7px; font-size: 14px; line-height: 20px; font-weight: 500;
  color: var(--text-2);                                 /* == .cn-budget-field .cn-label (:4083) */
}
#connect-modal .cn-swap-arrow {
  display: grid; place-items: center;
  width: 24px; height: 52px;                                     /* == .cn-budget-input height */
  color: var(--text-3);                                  /* == .cn-inline-select svg (:4139) */
}
#connect-modal .cn-swap-arrow svg { width: 18px; height: 18px; }
#connect-modal .cn-swap-note { margin-top: 8px; }                /* == .cn-sell-note (:2990) */
#connect-modal .cn-swap-leg { position: relative; }
#connect-modal .cn-swap-leg .cn-budget-input { width: 100%; }
/* The panel's anchor. Zero-height and out of flow's way: it exists only to
   give the absolutely-positioned dropdown a containing block OUTSIDE
   .cn-budget-input, which clips (overflow: hidden, :4089). */
#connect-modal .tok-host { position: relative; height: 0; }

/* The picker's TRIGGER — the cell the <select> used to fill. */
#connect-modal .cn-inline-select,
#connect-modal .cn-budget-select { position: relative; }
#connect-modal .tok-pick {
  -webkit-appearance: none; appearance: none;
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  width: 100%; height: 100%; min-height: 52px;                   /* == .cn-budget-input */
  padding: 0 15px; border: 0; outline: 0; background: transparent;
  color: var(--ink); font-family: inherit; font-weight: 500; font-size: 14px; line-height: 20px; cursor: pointer;   /* == .cn-inline-select select (:4118) */
  text-align: left;
}
#connect-modal .cn-budget-select .tok-pick {
  border: 1px solid var(--grey); border-radius: var(--r-md); background: var(--white);   /* == .cn-budget-input, which this one IS */
  transition: border-color 0.25s var(--ease);
}
#connect-modal .cn-budget-select .tok-pick:hover { border-color: var(--text-4); }   /* == .cn-budget-input:focus-within */
#connect-modal .tok-pick-sym { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#connect-modal .tok-pick svg { width: 15px; height: 15px; flex: 0 0 auto; color: var(--text-3); }   /* == .cn-inline-select svg */

/* The DROPDOWN. Anchored to the field, over everything else in the form. */
#connect-modal .tok-panel {
  position: absolute; z-index: 5; top: 6px; right: 0;
  width: min(340px, calc(100vw - 2 * var(--bleed)));
  max-height: 300px; display: flex; flex-direction: column;
  background: var(--white);
  border: 1px solid var(--grey); border-radius: var(--r-md);     /* == .cn-tok-opt (:2824) */
  box-shadow: 0 18px 40px var(--shadow-2);                /* == .wp-acct.open's own lift */
  overflow: hidden;
}
#connect-modal .tok-search { padding: 10px; border-bottom: 1px solid var(--grey); }   /* == .cn-tok-locked inset step */
#connect-modal .tok-search input {
  width: 100%; height: 38px; padding: 0 12px;
  border: 1px solid var(--grey); border-radius: var(--r-md);     /* == .cn-input at rest */
  outline: 0; background: var(--white); color: var(--ink); font-family: inherit; font-weight: 400; font-size: 14px; line-height: 20px;
}
#connect-modal .tok-search input:focus { border-color: var(--text-4); }   /* == .cn-input:hover */
#connect-modal .tok-scope { padding: 8px 12px 0; }               /* == .cn-help, inset to the panel */
#connect-modal .tok-list { overflow-y: auto; padding: 8px; display: flex; flex-direction: column; gap: 4px; }
#connect-modal .tok-list .cn-help { padding: 4px 4px 8px; }
#connect-modal .tok-row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%; padding: 9px 10px; border: 0; border-radius: var(--r-md);
  background: transparent; font-family: inherit; cursor: pointer; text-align: left;
  transition: background 0.2s var(--ease);
}
#connect-modal .tok-row:hover { background: var(--wash); }   /* == .cn-sell-x:hover wash */
#connect-modal .tok-row.on { background: var(--ok-wash); }     /* == .cn-tok-opt.on (:2834) */
#connect-modal .tok-row.is-blocked { opacity: 0.4; cursor: not-allowed; }   /* == .cn-tok-opt.is-blocked */
#connect-modal .tok-row-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }   /* == .cn-sell-tok (:2963) */
#connect-modal .tok-row-main strong { font-size: 14px; line-height: 20px; font-weight: 500; letter-spacing: 0.01em; }   /* == .cn-tok-opt strong */
#connect-modal .tok-row-main span { font-size: 12px; line-height: 16px; color: var(--text-3); }   /* == .cn-tok-opt span */
#connect-modal .tok-row-tags { display: flex; align-items: center; flex-wrap: wrap; justify-content: flex-end; gap: 4px; flex: 0 0 auto; }
#connect-modal .tok-tag {
  font-style: normal; font-size: 11px; line-height: 14px; letter-spacing: 0.02em;
  padding: 2px 7px; border-radius: 999px;                        /* == .pos-tag (:2996) */
  background: var(--line); color: var(--text-3);
}
#connect-modal .tok-tag.held { background: var(--ok-wash-2); color: var(--ok-text); }   /* == .cn-tok-opt.on green, as a chip */
/* "new to this app" is a FACT ABOUT THIS APP'S MEMORY, not a verdict, so it is
   the app's neutral chip wash — never the red the "not allowed" tag uses and
   never a green that would read as approval. */
#connect-modal .tok-tag.new { border: 1px dashed var(--mute-fill); background: transparent; }
#connect-modal .tok-tag.no { color: var(--bad); background: var(--bad-wash); }   /* == .cn-tok-no (:2840) */
#connect-modal .tok-row-any .tok-row-main span { color: var(--text-3); }

@media (max-width: 620px) {
  /* Stack the pair and turn the arrow down, so the sentence still reads in
     order. == the modal's own narrow breakpoint at :2930. */
  #connect-modal .cn-swap { grid-template-columns: 1fr; }
  #connect-modal .cn-swap-arrow { height: 24px; rotate: 90deg; justify-self: center; }
  #connect-modal .tok-panel { left: 0; right: auto; width: 100%; }
}
#connect-modal .dlist.fn-pick .drow { grid-template-columns: minmax(0, 1fr); }
#connect-modal .dlist.fn-pick .drow.head { grid-template-columns: minmax(0, 1fr); }

/* Protocol mark on live Directory cards, from the website logo set. */
.svc-protocol-logo {
  display: block;
  background: currentColor;
  -webkit-mask: var(--logo) center / contain no-repeat;
  mask: var(--logo) center / contain no-repeat;
}
.modal-symbol.svc-protocol-logo { height: 44px; }

/* ================================================================
   THE SESSION PAGE (2026-08-31) — #session/<id>.

   No new object is introduced here. Every surface below is an existing one
   named again in a new place, and the provenance is on each rule:
     the card         == .pf-chart / .stat-card (--card, --r-lg, 24px, 18px gap)
     its label        == .pf-scope (Footnote, 0.5 ink)
     the stat row     == .stat-grid.cols-3 with .ov-stats' compact treatment
     the rows         == .dlist / .drow, at .pf-alist's 1fr:auto split
     the venue mark   == .act-venue / .act-logo, the Activity table's own
     the status dot   == .sess-status / .sdot, the accordion row's own
   ================================================================ */

/* ================================================================
   THE SESSION BOX (2026-08-31c) — the whole session, in one grey box.

   The session page's five blocks now live inside #sess-box on the Overview.
   Nothing about them is restyled: .sp-card, .sp-stats, .sp-list, the moved
   #sess-list and the Activity table are all exactly the objects they were on
   the page. What is added here is only the BOX and the two things that
   changes — the inset (the blocks lose their own .bleed, because the box
   provides it) and the rhythm between them (the page's 70-130px .app-block
   gap is a PAGE gap; inside one card it steps down to the card's own 24px).
   ================================================================ */
.sess-box {
  background: var(--grey);              /* == .media-card (:101) — the app's own grey surface */
  border-radius: var(--r-lg);           /* == .stat-card / .pf-chart */
  padding: 24px;                        /* == .stat-card / .pf-chart inset */
  margin-top: var(--gutter);            /* == .sess-list's own top gap (:2713) */
}
.sess-box[hidden] { display: none; }
/* The blocks keep .app-block for everything except its page-scale top gap. */
.sess-box > .app-block { margin-top: 24px; }        /* == the box's own inset step */
.sess-box > .app-block:first-child { margin-top: 0; }
/* Cards ON grey read as raised because --card (#f2f2f2) is lighter than
   --grey (#e5e5e5) — the same pair the app already uses everywhere else. */
.sess-box .app-title { font-size: 22px; line-height: 28px; }   /* Title 2 — an H2 inside a card is one step down from an H2 on the page */
/* The moved #sess-list already zeroes its own head; it only needs the box's
   rhythm rather than the page's. */
.sess-box .sess-list.on-page { margin-top: 0; }
.sess-box #sp-alw-slot { margin-top: var(--gutter); }   /* == .sess-list's own top gap (:2713) */

/* The head row: the switcher and New session, side by side.
   == .app-head's own flex row, at .sess-meta's 12px gap. */
.sess-head-acts { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; }   /* gap == .sess-head (:4128 .sp-meta) */
.sess-switch { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }       /* gap == .sp-meta's row gap */
.sess-switch[hidden] { display: none; }

/* The back link above the H1. .row-link's own quiet-action treatment, sized
   to the Footnote step the .agent-kv line beneath the title already uses, and
   given the 8px it needs so it does not sit on the H1's cap height. */
.app-back { display: inline-block; margin-bottom: 8px; font-size: 14px; line-height: 20px; }   /* Footnote == .agent-kv */
.app-back[hidden] { display: none; }

/* Head — H1 (rewritten to the session's name by the router) over one line of
   facts. .sp-meta is .agent-chips' wrap-and-gap (:1756) at .sess-head's 12px. */
.sp-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 16px; }   /* gap == .agent-chips + .sess-head */
#sp-head .app-head { align-items: flex-start; }   /* the facts line pushes this block taller than the control beside it */

/* The tab row hides while the session page is showing — and .cat-tabs sets its
   own `display`, which beats the UA sheet's [hidden] rule, so it has to be told
   in the same way .act-venues already is at :3565. */
.cat-tabs[hidden] { display: none; }

/* The 3-up totals row. == .ov-stats (:3512-3515): the same compact stat card,
   here across a row instead of down a column — with .stat-value back at the
   4-up strip's own Title 1 (:1278), because a 1/3-page card has the room a
   1fr sidebar column did not. */
#sp-head .sp-stats { margin-top: var(--gutter); }   /* == .pf's own top gap (:1911) — .app-block > .stat-grid zeroes the 70-130px one */
.sp-stats .stat-card.compact { min-height: 0; padding: var(--gutter); }
.sp-stats .stat-value { font-size: 28px; line-height: 34px; }   /* Title 1 == :1278 */
.sp-stats .stat-divider { margin: 14px 0 12px; }                /* == .ov-stats */
.sp-stats .stat-desc { font-size: 14px; line-height: 20px; }    /* Footnote == .ov-stats */

/* Waypoints | Balances, side by side. .stat-grid's own repeat(2,1fr)/--gutter
   carries the split; .sp-card is .pf-chart's surface verbatim. */
.sp-card {
  background: var(--card); border-radius: var(--r-lg); padding: 24px;   /* == .pf-chart / .stat-card */
  display: flex; flex-direction: column; gap: 18px;                     /* == .pf-chart / .svc-card gap */
}
/* The note belongs to the label above it, not to the rows below: .prop-note
   already carries its own 8px top gap, so the card's 18px flex gap is pulled
   back to that same 8px rather than a new value being chosen. */
.sp-card > .pf-scope + .sp-note { margin-top: -18px; }
.sp-note { max-width: 46ch; }                            /* == .field-hint measure (:2601) */
.sp-card .acct-empty { padding: 0; }                     /* == .ov-assets — the card already provides the inset */
/* Rows: two columns, fact left and its qualifier right. == .pf-alist .pf-arow
   (:1938) with .dlist .drow's own padding stepped to the tighter card inset
   .ov-assets already uses (:3525). */
.dlist.sp-list .drow { grid-template-columns: minmax(0, 1fr) auto; gap: 14px; padding: 12px 2px; }
.sp-right { text-align: right; }

/* ---- the moved #sess-list ----
   openSession() relocates the element itself into #sp-alw-slot, so what is
   different on this page is only what would now be redundant: the collapsed
   head repeats the name, the status and the totals the page header already
   states, and the row cannot be collapsed here because collapsing the only
   thing on the page is not a state worth having. The head STAYS — it is where
   "Set budget" lives — with the toggle out and the control on the right. */
.sess-list.on-page { margin-top: var(--gutter); }   /* == .sess-list */
.sess-list.on-page .sess-toggle,
.sess-list.on-page .sess-open { display: none; }
.sess-list.on-page .sess-head { justify-content: flex-end; padding: 16px; }   /* == .sess-inner's own 16px inset */
.sess-list.on-page .sess-head:has(.sess-toggle:hover) { background: none; }   /* nothing left in the row to hover-target */
.sess-list.on-page .sess-body { grid-template-rows: 1fr; }                    /* == .sess-item.open (:2742) — permanently */

/* ---- THE BUDGETS TABLE SITS IN ITS CARD (2026-09-01) ----
   TWO THINGS WERE WRONG and they are separate. sessRowHTML now emits the body
   BEFORE the head on this page, which puts the table at the top and "Set
   budget" at the bottom; these rules are what makes that land square.

   1. IT OVERFLOWED THE CARD. `.sess-inner > *` spaces the accordion's children
      with `margin: 0 16px` (:2769) — but `.dlist` is `width: 100%` (:1334), so
      a 100%-wide box plus 32px of horizontal margin is wider than what holds
      it. It hung 16px past the card's right edge, saved from looking broken
      only by `.sess-inner`'s own `overflow: hidden`. Margins cannot inset a
      100%-wide child; PADDING ON THE PARENT can, so the inset moves there and
      the child's margins go to zero. Same 16px, correctly applied.
   2. THERE WAS A BAND OF NOTHING ABOVE THE HEADER ROW. The old order put the
      head — 16px of padding around one 38px pill — over the table, so the
      first thing in the card was 70px of empty grey. With the order swapped
      the table needs a top inset of its own, which is the same 16px.
   The result is one even 16px frame: 16 above the header row, 16 either side,
   16 between the last row and the pill, 16 under the pill (the head keeps its
   own padding, unchanged, and supplies the last two). */
.sess-list.on-page .sess-inner { padding: 16px 16px 0; }   /* == .sess-inner's own 16px inset (:2769) */
.sess-list.on-page .sess-inner > * { margin: 0; }          /* the inset is the parent's now, not each child's */

/* Requests — the .props row family (a request and a proposal are the same
   object at different stages), at the Activity table's status + time tail. */
/* The head row shares the request rows' template, and the two content-sized
   columns are floored so every row — head included — lands on the same tracks. */
#sp-req-list .drow, .dlist.props .drow[data-req] { grid-template-columns: 1.2fr 2fr minmax(96px, auto) minmax(72px, auto); }
.dlist.props .drow[data-req] .cell-status { text-transform: capitalize; }   /* == .acts .cell-status (:3561) */

/* .sp-split and .sp-stats need no breakpoints of their own: they ARE
   .stat-grid / .stat-grid.cols-3, which already stack at :1165 and :1622-1627.
   Only the request row, which is not a .stat-grid, has to be told. */
@media (max-width: 1000px) {
  .dlist.props .drow[data-req] { grid-template-columns: 1fr auto; row-gap: 6px; }   /* == .dlist.activity.acts at :3673 */
}
@media (max-width: 760px) {
  /* One column per row: side by side, the right-hand qualifier ("swap · WETH →
     0x6a6E…0bdC") crowds the venue name out of its own ellipsis. == the same
     stack .dlist.activity.acts takes at this width (:3673). */
  .dlist.sp-list .drow { grid-template-columns: minmax(0, 1fr); row-gap: 6px; }
  .sp-right { text-align: left; }
}

/* ================================================================
   ONE SESSION + CONNECT YOUR AGENT (2026-09-01) — APPEND-ONLY.
   Nothing above this line is edited. Every value below is copied from a
   selector already in this sheet; the provenance is on each line.
   ================================================================ */

/* ---- 1. THE OTHER SESSIONS (read-only disclosure) ----
   The switcher's row of pills is gone. What replaces it is a quiet .row-link
   in .sess-head-acts (which needs no new rule — it is already a flex row) and
   this panel, which is a list of rows, not a list of cards. */
.sess-others {
  display: flex; flex-direction: column; gap: 12px;   /* == .sess-list (:2721) */
  margin-top: var(--gutter);                          /* == .sess-list's own top gap */
}
.sess-others[hidden] { display: none; }
.sess-other {
  display: flex; align-items: center; flex-wrap: wrap; gap: 12px 18px;   /* == .sess-manage (:2785) */
  background: var(--card); border-radius: var(--r-md);                   /* == .sess-item (:2726 family) surface */
  padding: 16px;                                                         /* == .sess-inner's own inset (:4392) */
}
.sess-other .cell-name { margin-right: auto; }        /* name left, facts + control right == .sess-manage .agent-kv */
.sess-other .btn-mini { text-decoration: none; }      /* == .del-gas-manual (:2520): a .btn-mini that is an <a> */

/* ---- 2. WAYPOINTS, alone ----
   The Balances card that shared this grid is gone (the AUM box prices the same
   holdings). One card, full width: .stat-grid at one column. */
.stat-grid.sp-solo { grid-template-columns: 1fr; }    /* == .stat-grid.cols-3's own single-column form (:1627) */

/* ---- 3. USE WITH AI — one pill, top right of the session card ----
   REPLACES (2026-09-01) the six-tab strip and the full-width black snippet
   block that used to occupy a whole section of this card. Everything below is
   assembled from components already in this sheet; the block only has to say
   what is genuinely NEW, which is a popover anchored to a pill:
     the pill      .btn-mini (:1693) — the app's small white pill, hover-inverts
     the caret     .acc-chev (:2741 rotate-on-open) — same shape, same 180deg
     the surface   .pill (:262) — white, radius 16, that two-layer shadow
     a row title   .cell-name (:1352) — Subhead Medium
     a row line    .agent-kv .v (:1755) — Footnote, 0.7 ink
     the notes     .cred-warn (:1860) — Footnote, and .wpc-stale one step under
     the snippet   .cred-block / .cred-token (:1847) — for the no-clipboard
                   reveal only; it is display:none until then
   The host is a bare anchor, so it adds nothing of its own to the header row. */
.wpc { display: flex; }
.wpc-menu { position: relative; }
.wpc-pill { gap: 6px; }                                 /* == .act-venue's mark-to-name gap (:3636), at button scale */
.wpc-caret {
  width: 14px; height: 14px; flex: 0 0 auto;            /* == .acc-chev (:2736) */
  transition: rotate 0.35s var(--ease);                 /* == .acc-chev (:2736) */
}
.wpc-menu.open .wpc-caret { rotate: 180deg; }           /* == .sess-item.open .acc-chev (:2742) */

/* ---------- THE PILL GLYPHS (2026-09-01) ----------
   "Use with AI" became a plug and "Gas" became a pump. Both are inline SVG in
   currentColor, so both invert with .btn-mini:hover (:1703) for free — no rule
   here has to say a colour, and none does.
   Box 14px == .wpc-caret above, the other inline SVG in the same button: the
   two icons and the caret are one row of 14px marks and the pill's height does
   not move. flex 0 0 auto == .wpc-caret / .wpc-pill .sdot (:4660). */
.wpc-glyph { width: 14px; height: 14px; flex: 0 0 auto; }
/* An icon-only pill is square-ish, not a 100px-wide slab with a glyph adrift in
   it. The vertical padding and every other value stay .btn-mini's (:1693) —
   only the horizontal padding drops to the same 9px, which is the number
   .btn-mini already uses for its own vertical side. */
/* .wpc-pill-icon lived here: the icon-only sizing for the connect pill. The pill reads "Connect" in words now, so nothing wears the class. */
/* THE TWO PILLS ARE THE SAME HEIGHT, and this is what makes them so. The gas
   pill contains text, so .btn-mini's 18px line-height sets its content box; the
   connect pill contains only SVG, which is replaced content and ignores
   line-height — it came out 4px shorter. Giving its two marks that SAME 18px as
   their BOX height restores it. The glyphs do not stretch: both viewBoxes are
   square and preserveAspectRatio defaults to meet, so each still draws 14px
   wide and 14px tall, centred in an 18px slot. No new number — 18px is
   .btn-mini's own line-height (:1697). */
/* The gas balance. It is the pill's content, not a label: Footnote Medium,
   which is .btn-mini's own type, so this only has to stop it wrapping. */
.wpc-val { white-space: nowrap; }

/* The popover. Right-anchored to the pill so it opens INTO the card and never
   past its right edge, and clamped to the viewport at small widths. */
.wpc-pop {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 90;   /* z == .rail (:403), the app's other floating anchored control */
  width: 320px; max-width: calc(100vw - 2 * var(--bleed));            /* max == .pill's own viewport clamp (:263) */
  background: var(--white);                                          /* == .pill (:264) */
  border-radius: var(--r-md);                                        /* == .cred-block / .input (:1849) */
  box-shadow: 0 1px 2px var(--shadow-1), 0 10px 34px var(--shadow-2);   /* == .pill (:267) */
  padding: 8px;                                                      /* == .car-tabs' own pill-of-pills inset (:923) */
  /* Opens on the app's own curve, not a new one: --ease and the .pill-drawer
     duration (:327). visibility is stepped so a closed menu is not a click
     target, and it is the one property that does not ease. */
  opacity: 0; visibility: hidden; translate: 0 -6px;
  transition: opacity 0.35s var(--ease), translate 0.35s var(--ease), visibility 0s linear 0.35s;
}
.wpc-menu.open .wpc-pop {
  opacity: 1; visibility: visible; translate: 0 0;
  transition: opacity 0.35s var(--ease), translate 0.35s var(--ease), visibility 0s;
}
@media (prefers-reduced-motion: reduce) {                            /* == the app's own reduceMotion paths in js */
  .wpc-pop, .wpc-menu.open .wpc-pop { transition: none; translate: 0 0; }
}

/* One item: bold action over one grey line. Full-bleed row inside the 8px
   inset, so hover reads as a row and not as a floating chip. */
.wpc-item {
  display: block; width: 100%; text-align: left;
  border: 0; background: transparent; cursor: pointer; font: inherit;   /* == .row-link (:1706) */
  padding: 10px 12px;                                   /* == .car-tab (:932), the app's own pill-row cell */
  border-radius: 10px;                                  /* one step under --r-md, == .perm-chip's inner radius scale */
  color: var(--ink); text-decoration: none;             /* == .wpc-deep's predecessor: an <a> that is a control, not prose */
  transition: background 0.25s var(--ease);             /* == .btn-mini (:1701) */
}
.wpc-item:hover, .wpc-item:focus-visible { background: var(--wash); }   /* == .sess-head:hover (:2740) */
.wpc-item:focus-visible { outline: 2px solid var(--mute-fill); outline-offset: -2px; }   /* == .cred-block:focus-visible (:3286), on white */
.wpc-it { display: block; font-size: 14px; font-weight: 500; letter-spacing: 0.01em; line-height: 20px; }   /* == .cell-name (:1352) */
.wpc-is { display: block; font-size: 12px; font-weight: 400; line-height: 16px; color: var(--text-3); }   /* Footnote == .agent-kv .v (:1755), at .acct-empty's tone */
.wpc-item.is-copied .wpc-is { color: var(--ok); }         /* == .cred-block.is-copied .cred-copy-hint (:3297) */

/* A HOSTED LINK, WHEN IT CANNOT BE ONE (2026-09-01). All three link rows —
   Add to Claude, Install in Cursor, Install in VS Code — install the same
   endpoint and share this one state. The row stays and
   goes inert, with the reason in the line the subtitle already occupies — the
   same choice the wizard makes for a service with nothing budgetable
   (.cn-svc:disabled, :3334) rather than hiding the row and leaving the user to
   wonder where it went. */
.wpc-item.is-off { opacity: 0.4; cursor: default; }     /* == .cn-tok-opt.is-blocked (:2843) / .btn-pill:disabled (:2585) */
.wpc-item.is-off:hover { background: transparent; }     /* nothing to hover-target */
/* A subtitle that is a CAUTION, not a description — the hosted connector's
   local-key warning. Geometry copied whole from .cred-warn (:1860), the app's
   existing caution line: the same Footnote, the same 8px gap, led by the same
   amber .sdot.wait. It says nothing about colour, because .cred-warn does not
   either — the traffic light is the whole signal. */
.wpc-is.is-warn { display: flex; align-items: center; gap: 8px; }   /* == .cred-warn (:1860) */
.wpc-is.is-warn .sdot { flex: 0 0 auto; }                           /* == .wpc-pill .sdot (:4660) */
/* Rotate rides in a [data-sess] wrapper so the app's existing session-control
   handler can read whose credential it is; the wrapper is chrome-free. */
.wpc-pop-inner [data-sess] { display: block; }
.wpc-rotate .wpc-it { color: var(--text-2); }   /* == .row-link / .sp-danger (:4635) — a recovery control, not a verb the menu leads with */

/* (No closing notes, and no hover text: the tooltips came off this menu on
   2026-09-01. The security fact is a VISIBLE line at the reveal moment, on the
   credential itself (.cred-warn, index.html); the "shown once" fact sits on the
   credential fingerprint in the header line beside Rotate credential. Neither
   is standing prose on the card, because a fact that only matters once you are
   about to act belongs on the thing you act on.) */

/* THE SNIPPET IS NOT PART OF THIS MENU. It exists for exactly one path: no
   clipboard, so "Select and copy" needs something to select. Hidden until
   then, and it scrolls inside itself rather than growing the popover. */
.wpc-raw[hidden] { display: none; }
.wpc-raw {
  margin: 8px 0 0; padding: 12px;                       /* inset one step under .cred-block's --gutter (:1850), at popover scale */
  white-space: pre-wrap; word-break: break-word;
  max-height: 180px; overflow-y: auto;                  /* == the block it replaced; a payload must not outgrow the card */
}
.wpc-code { font-size: 14px; line-height: 20px; white-space: inherit; word-break: inherit; }   /* Footnote; .cred-token's break-all would split words mid-letter */

/* The pill sits in the session card's header row, which already wraps
   (.app-head is flex-wrap). At the app's smallest step the popover would
   overhang the card, so it pins to the left edge of the pill instead and takes
   the full available width. */
@media (max-width: 760px) {
  .sess-other .cell-name { flex-basis: 100%; margin-right: 0; }   /* unrelated component, unchanged — see .sess-manage (:2936) */
}

/* ---- HOSTED ONLY (2026-09-01, second pass) — NO CSS CHANGED, AND THAT IS
   THE POINT. The menu dropped its four local-install rows and its config-copy
   row (see the js block comment for the argument). NOTHING was deleted from
   this sheet with them and nothing was added: those rows were .wpc-item like
   every other row, their reasons were .wpc-is, their greyed state was
   .wpc-item.is-off, and the five that remain use exactly the same five
   selectors. There was never a per-item rule to strip.
   The first row is not given a "primary" treatment either. This sheet has no
   primary/secondary pair for a menu row to copy, and design fidelity here
   means not inventing one: "Add to Claude" leads by being first and by being
   the only row that is a live link by default, which is what the partition in
   paint() guarantees. A new visual weight bought for one row of five would be
   a rule with no provenance. ---- */


/* ================================================================
   v12 · POTS — the native (funded-executor) grant.

   TWO CUSTODY MODELS, ONE COMPONENT SET. A pot is not a new kind of card; it
   is the SAME allowance row and the SAME wizard step wearing different labels,
   so nothing below introduces a geometry, a radius, a tone or a type size that
   is not already somewhere in this file. Every declaration cites the selector
   it was copied from, per the design-fidelity rule.
   ================================================================ */

/* ---- the native line on an allowance row ----
   Same component as .del-gas: a .pos-note that carries controls, so it wraps
   and takes that rule's tone and padding verbatim. */
.del-native { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; color: var(--text-2); padding-bottom: 0; }   /* == .del-gas (:2506); gap == .cn-swap (:4187) */
.del-nat-act { display: inline-flex; align-items: center; gap: 8px; }   /* == .del-gas-act (:2507) */
/* A labelled value inside a row line. .agent-kv's grammar at .pos-note's size,
   because this sits in a caption-scale row and not in a facts panel. */
.del-nat-kv { display: inline-flex; align-items: baseline; gap: 6px; font-size: 12px; line-height: 16px; }   /* size == .del-gas-unit (:2519); gap == .chip-acct (:1760) */
.del-nat-kv .k { color: var(--text-3); }   /* == .del-gas-unit / .pos-note (:2519) */
.del-nat-kv .v { color: var(--text-2); }    /* == .agent-kv .v (:1755) */
/* WHO ENFORCES THIS WALL (v14, 2026-09-01). A KIND, not a state — so it is the
   sheet's own .sess-badge label pill, unchanged, exactly as the collapsed
   session row uses it to say "Pool" (:3047). The only thing added is that a
   baseline-aligned flex line needs it to sit on the text, not on the box. */
.del-wall { align-self: center; white-space: nowrap; }   /* == .sess-add / .bud-cap's own no-wrap (:1740, :2497) */
/* Gas stated once for a whole session sits where the allowance rows end, so it
   needs the top rule the manage row has and the same rhythm. */
.sess-shared-gas { align-items: center; gap: 12px; padding-top: 12px; }   /* gap == .del-native above; padding == .sess-manage rhythm */

/* ---- the pair, as tags, in the wizard's step 2 ----
   Both are .cn-svc-tag: the chip already used for "no budget yet", unchanged
   in every dimension. Only the wash separates a pot from a session, and the
   pot's is the app's own amber-adjacent caution wash rather than a new colour. */
#connect-modal .cn-nat-tag { background: var(--sky-wash); color: var(--text-2); }   /* wash == .cn-gas-once (:3930), which is the app's "money moves" surface */
#connect-modal .cn-sess-tag { background: var(--line); color: var(--text-3); }    /* == .cn-svc-tag at rest (:4165) */
#connect-modal .cn-nat-open { background: var(--line); color: var(--text-3); }    /* == .cn-svc-tag at rest (:4165) */
#connect-modal .dlist.fn-pick .drow .cn-svc-tag { margin-left: auto; align-self: center; }            /* the tag is the row's right edge, as .cn-svc-tag is on .cn-svc */

/* ---- the native ticket (step 3) ----
   Two independent limits, not two legs of one trade, so the .cn-swap grid loses
   its middle column and keeps everything else. */
#connect-modal .cn-nat-swap { grid-template-columns: 1fr 1fr; }   /* == .cn-swap (:4187) minus the arrow column */
/* A fixed unit beside an amount. .cn-inline-select is a <select> wrapper; this
   is the same cell with nothing to choose, so it borrows the geometry and drops
   the interaction. */
#connect-modal .cn-nat-unit {
  flex: 0 0 72px;                                   /* == .cn-inline-select (:4130), narrowed: "ETH" is not a token list */
  align-items: center; justify-content: center;
  text-align: center;
  font-family: inherit; font-weight: 500; font-size: 14px; line-height: 20px;                      /* == .cn-inline-select select (:4143) */
  color: var(--text-2);                     /* == .agent-kv .v (:1755) */
}
/* The labelled facts. A wrapping run of .agent-kv, at the .cn-help rhythm. */
.cn-nat-facts { display: flex; flex-wrap: wrap; gap: 8px 20px; margin-top: 12px; }   /* gap == .agent-chips (:1756) / .sess-manage; margin == .cn-swap-note (:4198) */
.cn-nat-facts .agent-kv { font-size: 14px; line-height: 20px; }                      /* == .agent-kv (:1753) */
/* #cn-nat-caps IS .dlist.fn-pick (see index.html), so it inherits that table's
   whole layout — grid columns, row height, the .cell-name / .cell-sub stack —
   and needs only the two things that differ: these rows are read-outs, and the
   risk line is a second muted line rather than a refusal. */
#connect-modal .cn-nat-caps .drow { cursor: default; }                               /* == .dlist.fn-pick .drow.is-nobudget (:4170) */
#connect-modal .cn-nat-caps .fn-why { white-space: normal; }                         /* == .fn-why (:4171); unclamped: a risk is not a one-liner */
/* ---- the deposit ticket (step 3, v14) ----
   ONE number, so the .cn-swap grid loses BOTH its arrow column and its second
   leg — the native ticket above drops one of the three for the same kind of
   reason (two limits are not two legs of a trade); a deposit has only one
   figure to ask for at all. Everything else on the pane is a class this sheet
   already defines: .cn-budget-input + .cn-inline-select.cn-nat-unit for the
   amount and its locked unit, .cn-nat-facts for the labelled facts, and
   .dlist.fn-pick (via .cn-nat-caps) for the allowed-calls rows. */
#connect-modal .cn-dep-swap { grid-template-columns: 1fr; }   /* == .cn-swap (:4207) with the arrow and second leg dropped */

/* The destination account on the funding stage, spelled out. Same chip the pool
   modal uses for exactly the same job (where the money is going). */
.cn-pot-acct { align-self: flex-start; }            /* == .pool-acct, which is .chip-acct (:1760) in a column */

/* ---- the two pot modals ----
   Label/field pairs on the .modal-card body's own two-column rhythm. */
.pons-grid { display: grid; grid-template-columns: 108px 1fr; align-items: center; gap: 10px 12px; }   /* gap == .cn-swap (:4187) / .agent-chips (:1756) */
.pons-grid .cn-label { margin: 0; font-size: 14px; line-height: 20px; font-weight: 500; color: var(--text-2); }  /* == .cn-swap .cn-label (:4188) */
.pons-grid .cn-budget-input { display: flex; align-items: center; height: 44px; border: 1px solid var(--grey); border-radius: var(--r-md); overflow: hidden; }   /* == .cn-budget-input (:4104), at .input height */
.pons-grid .cn-budget-input input { flex: 1 1 auto; min-width: 0; height: 100%; padding: 0 14px; border: 0; outline: 0; background: transparent; font-family: inherit; font-weight: 400; font-size: 14px; line-height: 20px; color: var(--ink); }   /* == .input (:1778) inside a split field */
.pons-grid .cn-nat-unit { display: flex; flex: 0 0 56px; height: 100%; align-items: center; justify-content: center; border-left: 1px solid var(--grey); font-family: inherit; font-weight: 500; font-size: 14px; line-height: 20px; color: var(--text-2); }   /* == .cn-inline-select (:4127) */
#pons-modal .cn-nat-facts, #nwd-modal .cn-nat-facts { margin: 0 0 18px; }   /* == .modal-sec rhythm */
#pons-modal .cn-gas-once, #nwd-modal .cn-gas-once { margin-top: 14px; padding: 14px 16px; border-left: 3px solid var(--sky); font-size: 14px; line-height: 20px; background: rgba(161, 220, 254, 0.18); }   /* == #connect-modal .cn-gas-once (:3930) */
#pons-modal .cn-steps, #nwd-modal .cn-steps { margin-top: 16px; }   /* == #pool-modal .cn-steps (:3205) */
#pons-modal .cn-error, #nwd-modal .cn-error { margin-top: 12px; }   /* == #pool-modal .cn-error */

@media (max-width: 760px) {
  /* Same collapse the ticket's own swap row takes: two amount fields side by
     side stop being two fields at this width. */
  #connect-modal .cn-nat-swap { grid-template-columns: 1fr; }   /* == .cn-swap at this width */
  .pons-grid { grid-template-columns: 1fr; gap: 6px; }          /* == .sess-manage stacking (:2935) */
  .del-native, .sess-shared-gas { gap: 10px 14px; }             /* == .sess-manage at this width (:2935) */
  /* Four controls in a row (amount, unit, Fund, Withdraw, Launch) do not fit a
     375px column. They wrap onto their own full-width line rather than pushing
     the page sideways — the same treatment .del-gas already takes by being
     flex-wrap, one level down. */
  .del-nat-act { flex-wrap: wrap; flex-basis: 100%; gap: 10px 12px; }   /* basis == .sess-manage .agent-kv at this width (:2936) */
  .del-nat-act .del-gas-amt { width: 84px; }                            /* == .del-gas-amt (:2511), narrowed to leave the buttons a line */
}


/* ================================================================
   THE SESSION CARD, RESTRUCTURED (2026-09-01)
   Header line with two pills on the right, then one tab strip over one panel.
   Every value below is copied from a selector already in this sheet.
   ================================================================ */

/* The header row. .app-head is already flex + space-between + wrap (:1264), so
   this only has to say that the facts take the room and the pills do not. */
.sp-head .sp-meta { margin-right: auto; }              /* == .sess-manage .agent-kv / .wpc-note's old push */
.sp-head-pills {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px;   /* gap == .sess-switch (:4335) */
  margin-left: auto;
}
.sp-head-pills .wpc { flex: 0 0 auto; }

/* The two session controls on the fact line. .row-link unchanged; they only
   need to sit as one group with the app's own inter-control gap. */
.sp-sess-acts { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 12px; }   /* == .sess-head-acts (:4334) */
.sp-danger { color: var(--text-2); }           /* == .row-link (:1707) — the destructive one is not louder, it is last */
.sp-danger:hover { color: var(--bad); }                   /* == .sdot.stop, the app's own alarm hue */

/* The GAS pill carries its dot inline; .btn-mini is otherwise untouched. */
.wpc-pill .sdot { margin-right: 7px; flex: 0 0 auto; }   /* == .sess-status gap (:2744) */
.wpc-pop-gas { width: 300px; padding: 14px; }          /* one step under .wpc-pop's 320 — a form, not a list of rows */
.gas-facts { display: flex; flex-direction: column; gap: 6px; margin-bottom: 12px; }   /* gap == .del-acct (:1986) */
.gas-acts { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }           /* == .del-gas-act, the row this replaces */
.gas-amt { max-width: 96px; }                          /* == .del-gas-amt's own width step */

/* ================================================================
   THE DASHBOARD IS ONE PAGE (2026-09-01)
   The Overview · Portfolio pill strip and the panels it switched are gone —
   see NO TAB STRIP in index.html. #panel-overview is what is left, and it
   inherits the gap the panel GROUP had, so the page below the title line sits
   exactly where it sat: nothing above this line is edited, and the three rules
   that served the strip (.dash-subtabs :2128, .subpanels :2134,
   .subpanel[hidden] :2135) join .agent-grid / .sgroup / .cn-adv in the sheet's
   standing set of now-unused-but-untouched selectors, along with .pf (:1925),
   .pf-assets (:2234) and the .pf-arow family (:1955) that the Portfolio
   panel's asset list used.
   ================================================================ */
#panel-overview { margin-top: var(--margin); }   /* == .subpanels (:2134), the rule it replaces */

/* The body (2026-09-01): the budgets table FIRST and permanently, then the
   app's ONE tab component, then a panel. #sp-body is itself a .app-block, so
   the box's own 24px inset (:4322) is the gap above the budgets — the slot adds
   nothing of its own, and the strip below it carries the rhythm instead. */
.sess-box #sp-alw-slot { margin-top: 0; }                            /* #sp-body's own 24px (:4322) is already the gap */
.sp-tabs { align-self: flex-start; margin: var(--gutter) 0; }        /* .cat-tabs is inline-flex; step == the list's own top gap (:4389) */
.sess-box .sp-panel > .dlist { margin-top: 0; }
.sess-box .sp-panel .act-venues { margin-bottom: 12px; }             /* == .uses-note stack gap (:2415) */

/* ---- THE EMPTY TABLE ----
   A list with nothing in it keeps its head row and says so in a ROW, not in a
   paragraph beside the table (see headRow/emptyRow in js/app.js). The row is
   ordinary .drow chrome; the only thing it needs is the whole width, because
   every .dlist variant is a multi-column grid and a single cell would sit in
   column one with the message trailing off into empty columns.
   Placed at the END of the sheet on purpose: it has to out-order the narrow-
   width grid overrides for .dlist.activity (:1629), .sg-dels (:2105) and
   .props (:2568), which it ties with on specificity. */
.dlist .drow.is-empty { grid-template-columns: 1fr; }                /* == .dlist.caps .drow at narrow (:1631) */
.dlist .drow.is-empty .row-link {
  text-decoration: underline; text-underline-offset: 3px; color: var(--ink);   /* == .acct-empty a (:1730) / .sess-noalw .row-link (:2782) */
}

/* THE WAYPOINT ON THE ALLOWANCE ROW. .act-venue / .act-logo / .cell-name are
   the Activity table's own venue mark, unchanged — this only stacks one or
   more of them above the capability chip inside the existing .del-acct column
   (:1986), which is already a 6px-gap flex column. */
.del-wp { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 12px; }   /* row gap == .del-acct (:1986); column gap == .sess-head (:2725) */

@media (max-width: 760px) {
  /* The header row has wrapped by here, so the pills lead their own line at the
     card's LEFT edge — and a menu anchored to the pill's right edge would then
     hang off the left of the screen. It hangs from the left instead, and takes
     whatever the card can give it. */
  .sp-head-pills { margin-left: 0; }
  .sp-head-pills .wpc-pop { left: 0; right: auto; width: min(320px, calc(100vw - 2 * var(--bleed))); }
  .sp-tabs { flex-wrap: nowrap; max-width: 100%; overflow-x: auto; }   /* == .wpc-tabs' old rule, same reason: the pills stay one row */
  .sp-tabs .car-tab { white-space: nowrap; }
  /* The head rows go where .dlist.activity's already goes (:1630): under 760px
     these grids fold to two columns, and four or six labels laid over two
     columns is not a legend, it is noise. The EMPTY row stays in every case —
     it is what tells the user the table is empty rather than broken. */
  .dlist.sg-dels .drow.head, .dlist.props .drow.head { display: none; }
}
@media (max-width: 1000px) {
  .dlist.props .drow.head { display: none; }   /* .dlist.props folds at 1000 (:2568), not 760 */
}

/* THE MENU INSIDE THE CREDENTIAL-REVEAL MODAL. Same pill, same open/close,
   same items — but it opens INLINE rather than floating. A modal body is a
   scroll container, and a floating panel inside one is either clipped by it or
   escapes the card; pushing the step down instead means the modal simply gets
   taller and scrolls the way it always has. It is the same component in a
   narrower room, not a second one. */
.modal-sec .wpc-pop {
  position: static; width: auto; max-width: none;
  box-shadow: none; background: transparent; border-radius: 0;
  padding: 8px 0 0;
  border-top: 1px solid var(--line);   /* == .btn-mini's hairline (:1699) — the sheet's only divider tone */
  margin-top: 10px;
}
/* Collapsed it must take NO room, which display:none does and an animated
   opacity does not — so in here the reveal is a height animation on the app's
   own curve, the .pill-drawer 0fr->1fr grid trick (:327). */
.modal-sec .wpc-pop { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 0.45s var(--ease); border-top-color: transparent; }
.modal-sec .wpc-menu.open .wpc-pop { grid-template-rows: 1fr; border-top-color: var(--line); }
.modal-sec .wpc-pop > * { min-width: 0; }
.modal-sec .wpc-pop-inner { overflow: hidden; min-height: 0; }   /* == .pill-panel / .sess-inner (:2765) */
@media (prefers-reduced-motion: reduce) {
  .modal-sec .wpc-pop { transition: none; }
}


/* ================================================================
   WAYPOINTS PAGE, UNFRAMED (2026-09-01)
   The grey .sess-box frame is gone: the budgets card sits full width on the
   page, with the tab strip and its table directly under it. The fact line
   is the credential + a rotate glyph; the pill row carries gas · Connect ·
   + Add budget; the table's own "Set budget" foot is hidden here.
   ================================================================ */
.sess-box { background: transparent; padding: 0; border-radius: 0; }
.sess-list.on-page .sess-head { display: none; }             /* "Set budget" moved to the pill row */
.sess-list.on-page .sess-inner { padding: 16px; }            /* the hidden head no longer supplies the bottom inset */
.sp-rotate {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: 50%;
  border: 0; background: transparent; color: var(--text-2); cursor: pointer;
}
.sp-rotate svg { width: 16px; height: 16px; }
.sp-rotate:hover { background: var(--grey); color: var(--ink); }
.sp-add { display: inline-flex; align-items: center; gap: 6px; }
.sp-add svg { width: 14px; height: 14px; }

/* ---- the waypoints table, unframed (2026-09-01) ----
   Same table as the actions table under it: no card, no border, no radius,
   full width, rows separated by the sheet's own dividers. */
.sess-list.on-page .sess-item { background: transparent; border-radius: 0; overflow: visible; }
.sess-list.on-page .sess-inner { padding: 0; }
.sess-list.on-page .sess-inner .dlist.sg-dels,
.sess-list.on-page .sess-inner .sess-noalw { background: transparent; border: 0; border-radius: 0; padding: 0; }
.sess-list.on-page .sess-inner .dlist.sg-dels .drow.head { padding: 12px 2px; }

/* ---- type scale on this page (2026-09-01) ----
   Everything in the Waypoints section is 14px, except the table head rows
   (12px) and the line under the budget bar (12px). Scoped to #sessions so
   the rest of the app keeps its own scale. */
#sessions .sp-meta, #sessions .agent-kv, #sessions .agent-kv .k, #sessions .agent-kv .v,
#sessions .dlist .drow, #sessions .cell-name, #sessions .cell-sub, #sessions .cell-num,
#sessions .cell-time, #sessions .cell-status, #sessions .cell-exp, #sessions .act-action,
#sessions .prop-meta, #sessions .prop-verb, #sessions .row-link, #sessions .btn-mini,
#sessions .btn-pill, #sessions .car-tab, #sessions .sess-noalw { font-size: 14px; line-height: 20px; }
#sessions .dlist .drow.head { font-size: 12px; line-height: 16px; }
#sessions .cell-budget .cell-num, #sessions .cell-budget .bud-cap { font-size: 12px; line-height: 16px; }

/* ---- the three header controls share one height (2026-09-01) ---- */
.sp-head-pills .btn-mini, .sp-head-pills .btn-pill {
  height: 40px; padding-top: 0; padding-bottom: 0; box-sizing: border-box;
  display: inline-flex; align-items: center;
}
.sp-head-pills .btn-mini { padding-left: 16px; padding-right: 16px; }
.sp-head-pills .btn-pill { padding-left: 18px; padding-right: 20px; }

/* ---- the two tables sit on cards (2026-09-01) ----
   Same surface as the charts above them: --card, --r-lg, 24px inset, rows
   separated by the sheet's dividers and no border on the first or last. */
.sess-list.on-page .sess-inner .dlist.sg-dels,
.sess-list.on-page .sess-inner .sess-noalw,
#sessions .sp-panel .dlist { background: var(--card); border-radius: var(--r-lg); padding: 4px 24px 8px; }
.sess-list.on-page .sess-inner .dlist.sg-dels .del:last-child > .drow,
.sess-list.on-page .sess-inner .dlist.sg-dels > .drow:last-child,
#sessions .sp-panel .dlist .drow:last-child { border-bottom: 0; }   /* a budget row is wrapped in .del (its edit footer follows it) */
#sessions .sp-panel .dlist .drow.head { border-top: 0; }

/* ---- the rotate glyph, tighter against the fingerprint (2026-09-01) ---- */
#sessions .sp-meta { gap: 8px 6px; }
.sp-rotate { width: 22px; height: 22px; }
.sp-rotate svg { width: 13px; height: 13px; }

/* ---- title row = header (2026-09-01) ----
   "Waypoints" + the credential pill on the left, gas · Connect · + Add budget
   on the right, one row; the table follows directly. */
#sessions > .app-head { align-items: center; }
.sess-title-row { display: flex; align-items: center; gap: 14px; }
#sessions .sess-head-acts { display: flex; align-items: center; gap: 8px; }
#sp-head[hidden] { display: none; }
.sess-box > #sp-body.app-block { margin-top: 0; }   /* nothing above it inside the box any more */
.sp-cred {
  display: inline-flex; align-items: center; gap: 6px;
  height: 24px; padding: 0 8px 0 10px; border-radius: 999px;
  border: 0; background: var(--grey); color: var(--ink); cursor: pointer;
  font: inherit; font-size: 12px; line-height: 16px;
  transition: background 0.25s var(--ease);
}
.sp-cred .mono { font-size: 12px; line-height: 16px; }
.sp-cred svg { width: 12px; height: 12px; color: var(--text-2); }
.sp-cred:hover { background: var(--ink); color: var(--white); }
.sp-cred:hover svg { color: var(--white); }

/* Action names read as words: "Swap", "Quote" (2026-09-02). */
#sessions .act-action { text-transform: capitalize; }

/* Budget cell (2026-09-02): the line under the bar is used ← → cap, and the
   cell keeps 24px clear of the Actions column. */
#sessions .sg-dels .cell-budget { padding-right: 24px; }
.bud-line { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
.sp-cred { background: var(--card); }   /* a step lighter than --grey */

/* ADD-TO-CLAUDE PLUG IN THE REVEAL FOOTER (2026-09-02).
   .modal-foot is justify-content:flex-end; this pushes the plug to the left
   edge without touching the layout of the pair on the right. The slot is empty
   on every step but the reveal, and an empty flex child of zero width changes
   nothing, so it needs no hidden state. The svg is centred rather than sitting
   on the text baseline it has no text to share. */
.modal-foot .wpc { margin-right: auto; }
.modal-foot .wpc .wpc-pill { display: inline-flex; align-items: center; justify-content: center; }

/* ================================================================
   THE WALLET SQUARE AND THE SITE HEADER (2026-09-02)
   .wp-acct sits at z-index 101 — under the site's .pill-scrim (9000) and
   .site-header (9010) — so an open menu dims it with the rest of the page
   and its panel can never open over the drawer. It also fades while the
   menu is open, so the two controls never read as one cluster.
   ================================================================ */
.wp-acct { transition: width 0.6s var(--ease), opacity 0.4s var(--ease); }
html.menu-open .wp-acct { opacity: 0; pointer-events: none; }

/* ================================================================
   THE DRAWER CHART (2026-09-02) — replaces the "Our story" film tile in the
   site header's drawer. Same 16:9 .panel-media box (site-shell.css), holding
   a compact second host of the dashboard's .pf-chart component.
   ================================================================ */
.panel-media.panel-chart { background: var(--card); cursor: default; }
.panel-media.panel-chart .pf-chart-mini {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; gap: 10px;
  padding: 16px 18px 14px; background: var(--card); border-radius: 6px;
}
.panel-chart .pf-chart-mini .pf-value { font-size: 22px; line-height: 28px; }
.panel-chart .pf-chart-mini .pf-scope, .panel-chart .pf-chart-mini .pf-delta { font-size: 12px; line-height: 16px; }
.panel-chart .pf-chart-mini .pf-canvas { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; justify-content: flex-end; }
.panel-chart .pf-chart-mini .pf-canvas svg { width: 100%; height: 100%; }
.panel-chart .pf-chart-mini .pf-connect, .panel-chart .pf-chart-mini .acct-empty { font-size: 12px; line-height: 16px; }
.panel-chart .pf-chart-mini.is-blank .pf-top { display: none; }

/* ---- Type scale, last stragglers (2026-09-02) ---- */
#connect-modal .tok-pick-sym, .tok-pick-sym { font-size: 14px; line-height: 20px; }   /* inherited 16px once buttons took the page font */
#connect-modal .cn-help, .cn-help { line-height: 20px; }                              /* a unitless 1.5 slipped past the per-size pass */
#connect-modal .cn-title { font-weight: 400; line-height: 34px; }                      /* == h2.app-title / .modal-title */
.tab-badge { line-height: 14px; }                                                       /* Caption 2 metric */
#connect-modal .cn-budget-input, #connect-modal .cn-inline-select, #connect-modal .cn-advanced summary,
#connect-modal select, #connect-modal option { font-size: 14px; line-height: 20px; }   /* the summary's "Optional" span stays a 12px caption */
#connect-modal .cn-cap-input { font-size: 18px; line-height: 24px; }   /* the one big number in the form: Title 3 */
.wp-acct-copy-hint { line-height: 14px; }
.btn-mini { line-height: 20px; }
select, option { font-size: 14px; line-height: 20px; }   /* the few selects outside the budget modal */

/* ---- the theme switch in the site drawer (replaces the three socials, 2026-09-02) ---- */
.theme-switch svg { width: 16px; height: 16px; color: var(--ink); display: block; transition: color 0.25s var(--ease); }
.theme-switch .moon { display: none; }
.soc:hover .theme-switch svg, .theme-switch:hover svg { color: var(--white); }
:root[data-theme="dark"] .theme-switch .sun { display: none; }
:root[data-theme="dark"] .theme-switch .moon { display: block; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-switch .sun { display: none; }
  :root:not([data-theme="light"]) .theme-switch .moon { display: block; }
}

/* ---- the theme slider in the drawer (2026-09-02) ---- */
.theme-tabs .car-tab { height: 36px; padding: 0 14px; }
.theme-tabs .car-tab-pill { top: 4px; bottom: 4px; }
/* ---- night in the footer underlay (2026-09-02) ---- */
.egg-night { display: none; }
:root[data-theme="dark"] .egg { background-image: url("../assets/images/footer-dark.jpg"); }
:root[data-theme="dark"] .egg-day { display: none; }
:root[data-theme="dark"] .egg-night { display: inline; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .egg { background-image: url("../assets/images/footer-dark.jpg"); }
  :root:not([data-theme="light"]) .egg-day { display: none; }
  :root:not([data-theme="light"]) .egg-night { display: inline; }
}
/* The footer underlay is a dark photograph in BOTH themes, so inside it the bases
   stay the light theme's: white text on the picture, never the dark theme's ink. */
.egg { --white-rgb: 255, 255, 255; --ink-rgb: 38, 38, 38; --white: #ffffff; --ink: #262626; }

/* ================================================================
   OVERVIEW CARDS, ALIGNED (2026-09-02)
   Budget · Assets under management · Balance share one grammar:
     24px inset · label 12/16 muted at the top · hero value 28/34
     (34/41 on the balance chart, the section's one large number) ·
     secondary lines 12/16 · rows as name/sub left, value/sub right.
   ================================================================ */
#aggregate.ov-grid { align-items: stretch; }
#aggregate .stat-card.compact, #aggregate .pf-chart { padding: 24px; }
#aggregate .stat-card.compact { display: flex; flex-direction: column; }
#aggregate .stat-label, #aggregate .pf-scope { font-size: 12px; line-height: 16px; color: var(--text-3); display: block; }
/* Budget */
#agg-budget .bud-bars { margin-top: auto; }
#agg-budget .bud-unit + .bud-unit { margin-top: 16px; }
#agg-budget .bud-unit-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
#agg-budget .stat-value { font-size: 28px; line-height: 34px; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
#agg-budget .bud-cap { font-size: 12px; line-height: 16px; }
#agg-budget .meter { margin-top: 10px; }
/* Assets under management */
#agg-aum .aum-list { margin-top: 8px; }
#agg-aum .acc-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 16px; align-items: start; padding: 12px 0; border-bottom: 1px solid var(--line); }
#agg-aum .acc-row:last-child { border-bottom: 0; }
#agg-aum .acc-cell { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
#agg-aum .acc-cell.right { align-items: flex-end; text-align: right; white-space: nowrap; }
#agg-aum .acc-cell strong { font-size: 14px; line-height: 20px; font-weight: 500; letter-spacing: 0; font-variant-numeric: tabular-nums; }
#agg-aum .acc-cell span { font-size: 12px; line-height: 16px; color: var(--text-3); }
#agg-aum .stat-divider { margin: auto 0 12px; }
#agg-aum .stat-main { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
#agg-aum .stat-value { font-size: 28px; line-height: 34px; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
/* Balance chart */
#aggregate .pf-chart { gap: 16px; }
#aggregate .pf-top { align-items: flex-start; }
#aggregate .pf-readout { gap: 4px; }
#aggregate .pf-chart .pf-value { font-size: 34px; line-height: 41px; letter-spacing: -0.02em; }
#aggregate .pf-delta { font-size: 12px; line-height: 16px; }
#aggregate .pf-ranges { margin-top: -4px; }   /* the 40px pill's cap sits on the label's line */

/* ---- theme switch: sun and moon beside the words ---- */
.theme-tabs .car-tab { gap: 6px; }
.theme-tabs .car-tab svg { width: 14px; height: 14px; display: block; }

/* ================================================================
   THE CHART, REBUILT (2026-09-02, js/chart.js)
   ================================================================ */
#aggregate.ov-grid { height: 550px; }                       /* the whole overview strip */
#aggregate .stat-card.compact, #aggregate .pf-chart { height: 100%; min-height: 0; }
#aggregate .ov-stats { display: flex; flex-direction: column; gap: var(--gutter); min-height: 0; }
#aggregate .pf-chart { display: flex; flex-direction: column; }
#aggregate .pf-canvas { flex: 1 1 auto; min-height: 0; }
.pf-svg { display: block; width: 100%; height: 100%; overflow: visible; }
.pf-lbl { font-size: 12px; line-height: 16px; fill: var(--text-3); font-family: "Helvetica Neue W", "Helvetica Neue", Helvetica, Arial, sans-serif; }
.pf-cross { stroke: var(--mute-fill); stroke-width: 1; stroke-dasharray: 1 6; stroke-linecap: round; }
.pf-cross-time { fill: var(--text-2); }
.pf-hdot { fill: var(--ink); stroke: var(--white); stroke-width: 2; }
.pf-hit { cursor: crosshair; }
html.has-cursor-dot .pf-hit { cursor: none; }
.pf-chart .pf-canvas .acct-empty { position: absolute; inset: 0; display: grid; place-items: center; }
.pf-chart .pf-canvas .pf-connect { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; }
.panel-chart .pf-chart-mini .pf-canvas { flex: 1 1 auto; min-height: 0; }
@media (max-width: 1000px) { #aggregate.ov-grid { height: auto; } #aggregate .pf-chart { height: 420px; } }
/* 80px of air between the last app block and the site footer (2026-09-02) */
.page.app > .footer { margin-top: 80px; }

/* ================================================================
   THE BUDGET WIZARD, REBUILT (2026-09-02)
   Three steps, one grammar: 14px throughout, 12px captions, one hairline
   between form and footer, real buttons on the right, the app's own
   dropdowns (js/select.js) instead of the system menu, the docs' grey pill
   search inside the token picker, and no arrow glyph between the legs.
   ================================================================ */
/* -- frame -- */
#connect-modal .cn-body { padding: 32px 36px 28px; gap: 28px; }
#connect-modal .cn-head { align-items: center; gap: 12px; }
#connect-modal .cn-tag { margin: 0; }
#connect-modal .cn-stepline { margin-left: auto; font-size: 14px; line-height: 20px; color: var(--text-3); }
#connect-modal .cn-close { top: 26px; right: 30px; }
#connect-modal .cn-form { gap: 24px; padding-right: 0; }
#connect-modal .cn-step-pane { gap: 24px; }
#connect-modal .cn-label { font-size: 14px; line-height: 20px; font-weight: 500; color: var(--text-2); margin-bottom: 8px; }
#connect-modal .cn-help { font-size: 14px; line-height: 20px; color: var(--text-3); margin-top: 8px; }
/* -- step 1: waypoint cards -- */
#connect-modal .cn-svc-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 12px; }
#connect-modal .cn-svc { border-radius: var(--r-lg); }
#connect-modal .cn-svc:hover { background: var(--grey); }
/* -- step 2: the action list -- */
#connect-modal #cn-fn-label { font-size: 18px; line-height: 24px; font-weight: 500; color: var(--ink); margin-bottom: 4px; }
#connect-modal .dlist.fn-pick .drow { border-radius: 0; padding: 14px 4px; align-items: center; }
#connect-modal .dlist.fn-pick .drow:first-child, #connect-modal .dlist.fn-pick .drow.head { border-top: 0; }
#connect-modal .dlist.fn-pick .drow.head { padding: 6px 4px; font-size: 12px; line-height: 16px; }
#connect-modal .dlist.fn-pick .drow.head + .drow { border-top: 1px solid var(--line); }
#connect-modal .dlist.fn-pick .drow { border-bottom: 1px solid var(--line); }
#connect-modal .dlist.fn-pick button.drow:hover { background: transparent; }
#connect-modal .dlist.fn-pick button.drow:hover .cell-name { text-decoration: underline; text-underline-offset: 3px; }
#connect-modal .dlist.fn-pick .fn-action { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
#connect-modal .dlist.fn-pick .cell-sub { font-size: 14px; line-height: 20px; color: var(--text-3); }
#connect-modal .dlist.fn-pick .drow .cn-svc-tag { margin: 0; align-self: center; justify-self: end; font-size: 12px; line-height: 16px; padding: 3px 10px; }
#connect-modal .dlist.fn-pick .drow.is-nobudget { opacity: 1; }
#connect-modal .dlist.fn-pick .drow.is-nobudget .cell-name { color: var(--text-3); }
#connect-modal .fn-none { padding: 12px 4px; }
/* -- step 3: the picked route -- */
#connect-modal .cn-picked { padding: 12px 16px; border-radius: var(--r-md); }
/* -- step 3: spend / receive, no arrow, one border per field -- */
#connect-modal .cn-swap { grid-template-columns: 1fr 1fr; gap: 16px; align-items: end; }
#connect-modal .cn-swap-arrow { display: none; }
#connect-modal .cn-swap .cn-label { font-size: 14px; line-height: 20px; font-weight: 500; color: var(--text-2); margin-bottom: 8px; }
#connect-modal .cn-budget-input { height: 48px; border: 1px solid var(--grey); border-radius: var(--r-md); }
#connect-modal .cn-budget-input:focus-within { border-color: var(--text-4); }
#connect-modal .cn-budget-input input { font-size: 14px; line-height: 20px; padding: 0 16px; }
#connect-modal .cn-inline-select { flex: 0 0 132px; border-left: 1px solid var(--grey); }
#connect-modal .cn-budget-select .tok-pick { border: 0; background: transparent; border-radius: 0; min-height: 0; height: 100%; }
#connect-modal .tok-pick { padding: 0 14px; font-weight: 400; }
#connect-modal .tok-pick svg { width: 14px; height: 14px; color: var(--text-3); }
/* -- the token panel: docs-style grey pill search -- */
#connect-modal .tok-panel { border-radius: var(--r-md); border: 1px solid var(--line); box-shadow: 0 18px 40px var(--shadow-2); }
#connect-modal .tok-search { position: relative; padding: 10px; border-bottom: 1px solid var(--line); }
#connect-modal .tok-search::before {
  content: ""; position: absolute; left: 22px; top: 50%; translate: 0 -50%; width: 15px; height: 15px;
  background: var(--text-3);
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='11' cy='11' r='7'/><path d='M20 20l-3.5-3.5'/></svg>") center / contain no-repeat;
  mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='11' cy='11' r='7'/><path d='M20 20l-3.5-3.5'/></svg>") center / contain no-repeat;
  pointer-events: none;
}
#connect-modal .tok-search input { height: 40px; padding: 0 14px 0 36px; border: 0; border-radius: 999px; background: var(--card); font-family: inherit; font-weight: 400; font-size: 14px; line-height: 20px; }
#connect-modal .tok-search input:focus { outline: 0; background: var(--grey); }
#connect-modal .tok-search input::placeholder { color: var(--text-3); }
/* -- expiry + every other select: the app's dropdown -- */
select.wp-select-native { position: absolute !important; width: 1px !important; height: 1px !important; opacity: 0 !important; pointer-events: none !important; }
#connect-modal .cn-budget-select > svg, #connect-modal .cn-select > svg { display: none; }
.wp-select {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  width: 100%; height: 100%; min-height: 46px; padding: 0 14px 0 16px;
  border: 0; background: transparent; color: var(--ink); font-family: inherit; font-weight: 400; font-size: 14px; line-height: 20px; cursor: pointer; text-align: left;
}
#connect-modal .cn-budget-select .wp-select { min-height: 46px; }
.wp-select svg { width: 14px; height: 14px; color: var(--text-3); flex: 0 0 auto; }
.wp-select-menu {
  position: fixed; z-index: 700; padding: 6px;
  background: var(--white); border: 1px solid var(--line); border-radius: var(--r-md);
  box-shadow: 0 18px 40px var(--shadow-2);
  opacity: 0; translate: 0 -4px; transition: opacity 0.18s var(--ease), translate 0.18s var(--ease);
}
.wp-select-menu.is-open { opacity: 1; translate: 0 0; }
.wp-select-item {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  width: 100%; padding: 9px 10px; border: 0; border-radius: 10px; background: transparent;
  color: var(--ink); font-family: inherit; font-weight: 400; font-size: 14px; line-height: 20px; text-align: left; cursor: pointer;
}
.wp-select-item:hover { background: var(--wash); }
.wp-select-item svg { width: 14px; height: 14px; visibility: hidden; color: var(--ink); }
.wp-select-item.is-on svg { visibility: visible; }
.wp-select-item.is-on { font-weight: 500; }
/* -- advanced: one hairline above, none below (the footer draws its own) -- */
#connect-modal .cn-advanced { border-top: 1px solid var(--line); border-bottom: 0; }
#connect-modal .cn-advanced summary { padding: 16px 0; }
#connect-modal .cn-advanced summary span { font-size: 12px; line-height: 16px; color: var(--text-3); }
/* -- footer: real buttons, right-aligned, one hairline -- */
#connect-modal .cn-actions { margin-top: auto; padding-top: 20px; border-top: 1px solid var(--line); display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 10px; }
#connect-modal .cn-actions .cn-approve { order: 3; height: 40px; padding: 0 20px; font-family: inherit; font-weight: 500; font-size: 14px; line-height: 20px; border-radius: 999px; background: var(--ink); color: var(--white); border: 0; }
#connect-modal .cn-actions .cn-approve:hover { background: var(--ink-2); }
#connect-modal .cn-actions .cn-cancel { height: 40px; padding: 0 18px; border-radius: 999px; border: 1px solid var(--line); background: var(--white); color: var(--ink); font-family: inherit; font-weight: 500; font-size: 14px; line-height: 20px; transition: background 0.25s var(--ease); }
#connect-modal .cn-actions .cn-cancel:hover { background: var(--card); color: var(--ink); }
#connect-modal .cn-actions .cn-back { order: 2; }
#connect-modal .cn-actions .cn-cancel[data-close] { order: 1; }
#connect-modal .cn-actions .cn-foot, #connect-modal .cn-actions .cn-steps, #connect-modal .cn-actions .cn-error { flex-basis: 100%; order: 0; }
#connect-modal .cn-actions .cn-foot { text-align: right; order: 4; }
/* wizard polish (2026-09-02): the tag is the row's right cell, vertically centred;
   the footnote sits left of the buttons on the same line */
#connect-modal .dlist.fn-pick .drow { grid-template-columns: minmax(0, 1fr) auto; grid-auto-flow: column; }
#connect-modal .dlist.fn-pick .drow > .fn-action { grid-column: 1; grid-row: 1; }
#connect-modal .dlist.fn-pick .drow > .cn-svc-tag { grid-column: 2; grid-row: 1; display: inline-flex; align-items: center; margin: 0; }
#connect-modal .cn-actions .cn-foot { flex-basis: auto; order: 0; margin-right: auto; text-align: left; }
/* every stage's buttons (grant, gas float, pot funding) share the footer's treatment */
#connect-modal .cn-approve { height: 40px; padding: 0 20px; font-family: inherit; font-weight: 500; font-size: 14px; line-height: 20px; border-radius: 999px; background: var(--ink); color: var(--white); border: 0; }
#connect-modal .cn-approve:hover { background: var(--ink-2); }
#connect-modal .cn-cancel { height: 40px; padding: 0 18px; border-radius: 999px; border: 1px solid var(--line); background: var(--white); color: var(--ink); font-family: inherit; font-weight: 500; font-size: 14px; line-height: 20px; transition: background 0.25s var(--ease); }
#connect-modal .cn-cancel:hover { background: var(--card); color: var(--ink); }
#connect-modal .cn-gas-actions, #connect-modal .cn-pot-actions, #connect-modal .cn-stage-actions { display: flex; justify-content: flex-end; gap: 10px; padding-top: 20px; border-top: 1px solid var(--line); margin-top: 8px; }
#connect-modal .cn-gas-actions .cn-approve, #connect-modal .cn-pot-actions .cn-approve { order: 2; }
#connect-modal .cn-gas-stage-actions { display: flex; justify-content: flex-end; gap: 10px; padding-top: 20px; border-top: 1px solid var(--line); margin-top: auto; }
#connect-modal .cn-gas-stage-actions .cn-approve { order: 2; }

/* ================================================================
   THE BUDGET WIZARD, PASS 2 (2026-09-02)
   ================================================================ */
/* 16px was the UA default leaking into anything without its own size; the
   modal's base is 14/20 like the rest of the app */
.modal, .modal-card { font-size: 14px; line-height: 20px; }
/* frame: head · scrolling form · footer, the card sized to its content */
#connect-modal .cn-body {
  display: grid; grid-template-columns: minmax(0, 1fr); grid-template-rows: auto minmax(0, 1fr) auto;
  grid-template-areas: "head" "form" "actions";
  height: auto; max-height: min(84vh, 760px); padding: 28px 32px 24px; gap: 20px;
}
#connect-modal .cn-left { grid-area: head; grid-column: auto; grid-row: auto; }
#connect-modal .cn-form { grid-area: form; grid-column: auto; grid-row: auto; overflow-y: auto; padding-right: 10px; margin-right: -10px;
  scrollbar-width: thin; scrollbar-color: var(--mute-fill) transparent; }
#connect-modal .cn-form::-webkit-scrollbar { display: block; width: 6px; }
#connect-modal .cn-form::-webkit-scrollbar-thumb { background: var(--mute-fill); border-radius: 999px; }
#connect-modal .cn-form::-webkit-scrollbar-track { background: transparent; }
#connect-modal .cn-actions { grid-area: actions; grid-column: auto; grid-row: auto; margin-top: 0; padding-top: 4px; border-top: 0; }
#connect-modal .cn-gas-stage-actions { border-top: 0; padding-top: 4px; }
/* head: title, then the step counter as the pill; the session chip is gone */
#connect-modal .cn-head { padding-right: 44px; }
#connect-modal .cn-tag { display: none; }
#connect-modal .cn-stepline { margin-left: 0; font-size: 12px; line-height: 16px; font-weight: 500; padding: 5px 12px; border-radius: 999px; background: var(--card); color: var(--text-2); }
#connect-modal .cn-close { top: 24px; right: 26px; }
/* step 2: the action list sits on the dashboard's card surface */
#connect-modal .dlist.fn-pick { background: var(--card); border-radius: var(--r-lg); padding: 4px 20px 6px; }
#connect-modal .dlist.fn-pick .drow { padding: 14px 0; }
#connect-modal .dlist.fn-pick .drow.head { padding: 10px 0 4px; }
#connect-modal .dlist.fn-pick .drow:last-child { border-bottom: 0; }
#connect-modal .dlist.fn-pick .drow.head + .drow { border-top: 0; }
#connect-modal .fn-none { padding: 12px 0; }
/* step 3: advanced token permissions */
#connect-modal .cn-advanced { border-top: 1px solid var(--line); }
#connect-modal .cn-advanced summary { padding: 18px 0 14px; }
#connect-modal .cn-advanced-body { display: flex; flex-direction: column; gap: 20px; padding-bottom: 4px; }
#connect-modal .cn-advanced-body .cn-label { font-size: 14px; line-height: 20px; font-weight: 500; color: var(--text-2); margin-bottom: 8px; }
#connect-modal .cn-sell { gap: 10px; }
#connect-modal .cn-sell-add { display: grid; grid-template-columns: minmax(0, 1fr) 48px; gap: 10px; align-items: stretch; }
#connect-modal .cn-sell-select { height: 48px; border: 1px solid var(--grey); border-radius: var(--r-md); background: var(--white); display: flex; }
#connect-modal .cn-sell-select .wp-select { min-height: 0; height: 100%; }
#connect-modal .cn-tok-add, #connect-modal .cn-sell-add .cn-tok-add { width: 48px; height: 48px; border: 1px solid var(--grey); border-style: solid; border-radius: var(--r-md); background: var(--white); color: var(--ink); font-size: 18px; line-height: 1; display: grid; place-items: center; }
#connect-modal .cn-tok-add:hover { background: var(--card); color: var(--ink); }
#connect-modal .cn-sell-row {
  display: grid; grid-template-columns: minmax(0, 1fr) auto 32px; grid-template-areas: "tok cap x" "held cap x";
  align-items: center; column-gap: 16px; row-gap: 2px; padding: 12px 12px 12px 16px;
  border: 1px solid var(--grey); border-radius: var(--r-md); background: var(--white);
}
#connect-modal .cn-sell-tok { grid-area: tok; gap: 2px; }
#connect-modal .cn-sell-tok strong { font-size: 14px; line-height: 20px; }
#connect-modal .cn-sell-tok .mono { font-size: 12px; line-height: 16px; color: var(--text-3); }
#connect-modal .cn-sell-held { grid-area: held; flex-basis: auto; font-size: 12px; line-height: 16px; color: var(--text-3); }
#connect-modal .cn-sell-cap { grid-area: cap; margin: 0; display: inline-flex; align-items: center; gap: 8px; }
#connect-modal .cn-sell-upto, #connect-modal .cn-sell-unit { font-size: 12px; line-height: 16px; color: var(--text-3); }
#connect-modal .cn-sell-amt { width: 96px; height: 40px; padding: 0 12px; text-align: right; font-size: 14px; line-height: 20px; border: 1px solid var(--grey); border-radius: 10px; }
#connect-modal .cn-sell-x { grid-area: x; width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center; font-size: 14px; line-height: 1; color: var(--text-3); background: transparent; border: 0; cursor: pointer; }
#connect-modal .cn-sell-x:hover { background: var(--wash); color: var(--ink); }
#connect-modal .cn-sell-note { margin-top: 0; }
#connect-modal .cn-list li.tog-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 16px; padding: 14px 0; border-top: 1px solid var(--line); border-bottom: 0; }
#connect-modal .cn-list li.tog-row > div { display: flex; flex-direction: column; gap: 2px; }
#connect-modal .cn-list li.tog-row strong { font-size: 14px; line-height: 20px; font-weight: 500; }
#connect-modal .cn-list li.tog-row .tog-sub { font-size: 14px; line-height: 20px; color: var(--text-3); margin: 0; }

/* A real reciprocal budget, revealed by "Session can trade what it receives".
   It uses the ticket's existing amount field, but names the second token authority separately:
   this is an owner→executor allowance, bounded again by what the delegation actually acquires. */
#connect-modal .cn-acq-budgets { display: grid; gap: 10px; margin-top: 10px; }
#connect-modal .cn-acq-budgets[hidden] { display: none; }
#connect-modal .cn-acq-budget {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(220px, 0.55fr);
  align-items: center; gap: 16px; padding: 14px 16px;
  border: 1px solid var(--grey); border-radius: var(--r-md); background: var(--white);
}
#connect-modal .cn-acq-copy { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
#connect-modal .cn-acq-copy strong { font-size: 14px; line-height: 20px; font-weight: 500; }
#connect-modal .cn-acq-copy em { font-size: 12px; line-height: 16px; font-style: normal; color: var(--text-3); }
#connect-modal .cn-acq-input { width: 100%; height: 48px; }
#connect-modal .cn-acq-input input { min-width: 0; }

/* =====================================================================
   BUDGET WIZARD · PASS 3 + POPUP UNIFICATION (demo-v2)
   · dropdown menus live on <body>, outside the modal's 14px root → pin them
   · inline token picker: the 52px min-height overflowed the 48px field
   · action list rows hover as white cards on the grey card
   · footnote left, "+" centred via an svg mask, Actions column right
   · permissions + create-session popups on the wizard grammar: no rules
     above/below the body, one close button, 40px pill buttons
   ===================================================================== */
.wp-select, .wp-select-menu, .wp-select-menu * { font-size: 14px; line-height: 20px; }
.wp-select-menu { font-family: inherit; }

#connect-modal .cn-inline-select .tok-pick { min-height: 0; height: 100%; padding: 0 14px; }
#connect-modal .cn-inline-select { align-items: stretch; }

#connect-modal .dlist.fn-pick .drow { padding: 14px 14px; margin: 0 -14px; width: calc(100% + 28px); border-radius: 12px; }
#connect-modal .dlist.fn-pick .drow.head { padding: 10px 14px 4px; }
#connect-modal .dlist.fn-pick button.drow:hover { background: var(--white); box-shadow: 0 1px 2px var(--shadow-1); }
#connect-modal .dlist.fn-pick button.drow:hover .cell-name { text-decoration: none; }
#connect-modal .dlist.fn-pick button.drow:hover .cell-badge { color: var(--ink); }
#connect-modal .dlist.fn-pick .drow.is-blocked:hover { background: transparent; box-shadow: none; }

#connect-modal .cn-actions .cn-foot { order: 0; flex: 1 1 auto; margin: 0 auto 0 0; text-align: left; }

#connect-modal .cn-tok-add { font-size: 0; display: grid; place-items: center; padding: 0; }
#connect-modal .cn-tok-add::before {
  content: ""; width: 14px; height: 14px; background: currentColor;   /* == .wp-select svg: 14px box, 24 viewBox, stroke 2 */
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M12 5v14M5 12h14' stroke='black' stroke-width='2' stroke-linecap='round'/></svg>") center / contain no-repeat;
          mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M12 5v14M5 12h14' stroke='black' stroke-width='2' stroke-linecap='round'/></svg>") center / contain no-repeat;
}
#connect-modal .cn-tok-add, #connect-modal .cn-sell-add .cn-tok-add { color: var(--text-3); }
#connect-modal .cn-tok-add:hover, #connect-modal .cn-sell-add .cn-tok-add:hover { color: var(--ink); }

/* waypoints table: Actions column right, waypoint cell hover */
/* :not(.is-empty) — AN EMPTY ROW'S ONLY CHILD IS ALSO ITS LAST CHILD (2026-09-02).
   This rule exists to push the Actions column to the right edge, and it was
   doing that to "No budget yet — set one." as well, which is a row with one
   cell: sole and last are the same element. The message landed 140px to the
   right of the "Budget" head it should have started under. Excluding the empty
   row here is the fix at the cause; the grid override lives at the end of the
   sheet with the other one. Same defect at :5204 for the actions/requests
   tables (235px and 204px), fixed the same way. */
#sessions .sg-dels .drow:not(.is-empty) > :last-child { justify-self: end; text-align: right; }
#sessions .sg-dels .del-actions { justify-content: flex-end; }
.del-acct[data-perms] { margin: -8px -12px; padding: 8px 12px; border-radius: 12px; transition: background 0.25s var(--ease), box-shadow 0.25s var(--ease); }
.del-acct[data-perms]:hover { background: var(--white); box-shadow: 0 1px 2px var(--shadow-1); }

/* popups: permissions + create session on the wizard grammar */
#perm-modal .modal-card, #add-agent-modal .modal-card { width: min(640px, calc(100vw - 2 * var(--bleed))); }
#perm-modal .modal-header, #add-agent-modal .modal-header { border-bottom: 0; padding: 32px 72px 6px 34px; }
#perm-modal .modal-body, #add-agent-modal .modal-body { padding: 22px 34px 34px; gap: 24px; }
#add-agent-modal .modal-body + .modal-foot, #add-agent-modal .modal-foot { border-top: 0; padding: 0 34px 30px; }
#add-agent-modal .modal-body { padding-bottom: 24px; }
.modal-x {
  top: 24px; right: 26px; width: 34px; height: 34px; border-radius: 50%;
  transition: background 0.25s var(--ease);
}
.modal-x:hover { background: var(--wash); }
.modal-x span { background: var(--text-3); }
.modal-x:hover span { background: var(--ink); }
.modal-foot .btn-pill, #add-agent-modal .btn-pill {
  height: 40px; padding: 0 18px; display: inline-flex; align-items: center; justify-content: center;
  font-size: 14px; font-weight: 500; line-height: 20px; border-radius: 999px;
}
#svc-modal #modal-budget { width: 40px; padding: 0; text-decoration: none; }
.modal-foot .wpc .wpc-pill { height: 40px; }
.modal-cat .svc-cat, .modal-cat .svc-verified { font-size: 12px; line-height: 16px; color: var(--text-3); }
.modal-cat .svc-verified { display: inline-flex; align-items: center; gap: 6px; }

#perm-modal .dlist.perm-facts .drow:first-child { border-top: 0; }
#perm-modal .dlist.perm-facts .drow:last-child { border-bottom: 0; }
#perm-modal .dlist.perm-facts .drow { padding: 12px 0; }
#perm-modal .dlist.perm-facts { background: var(--wash); border-radius: 14px; padding: 4px 20px; }
#perm-modal .perm-svc { background: var(--wash); border-radius: 14px; padding: 18px 20px; display: flex; flex-direction: column; gap: 0; }
#perm-modal .perm-svc-name { margin-bottom: 4px; }
#perm-modal .perm-fn { border-top: 1px solid var(--line); padding: 16px 0 0; margin-top: 16px; }
#perm-modal .perm-fn:last-child { padding-bottom: 0; }
#perm-modal .perm-sum-label { font-size: 12px; line-height: 16px; }
#perm-modal .perm-ro { font-size: 12px; line-height: 16px; color: var(--text-3); }

#add-agent-modal .field-label { font-size: 12px; line-height: 16px; color: var(--text-3); }
#add-agent-modal .field-hint { font-size: 12px; line-height: 16px; color: var(--text-3); }
#add-agent-modal .input { height: 48px; font-size: 14px; line-height: 20px; padding: 0 16px; border: 1px solid var(--grey); border-radius: var(--r-md); }
#add-agent-modal .cred-warn { font-size: 12px; line-height: 16px; }
#connect-modal .cn-sell-add .cn-tok-add, #connect-modal .cn-tok-add { font-size: 0; }
#add-agent-modal .btn-pill[hidden], .modal-foot .btn-pill[hidden] { display: none; }
.del-acct[data-perms]:focus { outline: none; }
.del-acct[data-perms]:focus-visible { outline: 2px solid var(--text-4); outline-offset: 0; }
#connect-modal .cn-tok-add, #connect-modal .cn-sell-add .cn-tok-add { display: flex; align-items: center; justify-content: center; padding: 0; line-height: 0; }

/* every popup's close button == the wizard's .cn-close: 34px round, 15px
   stroke-2 cross in text-3, wash on hover (the site header keeps its own) */
.modal-x { top: 24px; right: 26px; width: 34px; height: 34px; border-radius: 50%; background: transparent; display: flex; align-items: center; justify-content: center; color: var(--text-3); transition: background 0.25s var(--ease), color 0.25s var(--ease); }
.modal-x span { display: none; }
.modal-x::before {
  content: ""; width: 15px; height: 15px; background: currentColor;
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M6 6l12 12M18 6L6 18' stroke='black' stroke-width='2' stroke-linecap='round'/></svg>") center / contain no-repeat;
          mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M6 6l12 12M18 6L6 18' stroke='black' stroke-width='2' stroke-linecap='round'/></svg>") center / contain no-repeat;
}
.modal-x:hover { background: var(--wash); color: var(--ink); }
/* close buttons at the pill height (40px); icon centre stays where it was */
.modal-x, #connect-modal .cn-close { width: 40px; height: 40px; top: 21px; right: 23px; }

/* step-2 action list: square rows, dividers kept, hover fills between the two
   lines in a darker grey with a little inset; waypoint cell hover grey too */
#connect-modal .dlist.fn-pick .drow { border-radius: 0; padding: 14px 12px; margin: 0 -12px; width: calc(100% + 24px); }
#connect-modal .dlist.fn-pick .drow.head { padding: 10px 12px 4px; }
#connect-modal .dlist.fn-pick button.drow:hover { background: rgba(var(--ink-rgb), 0.045); box-shadow: none; }
#connect-modal .dlist.fn-pick .drow.is-blocked:hover { background: transparent; }
.del-acct[data-perms]:hover { background: rgba(var(--ink-rgb), 0.045); box-shadow: none; }
#connect-modal .dlist.fn-pick button.drow:focus-visible { border-radius: 0; outline-offset: -2px; }
#connect-modal .cn-advanced summary span { font-size: 14px; line-height: 20px; }
#connect-modal .cn-advanced-body { overflow: hidden; }

/* tooltips: the site's dark pill stays for ≤3-word tips ("Coming soon");
   sentences render as a compact wrapped note instead of a metre-long bar */
.tip.tip-note {
  white-space: normal; max-width: 240px; text-align: left;
  font-size: 12px; line-height: 16px; font-weight: 400; letter-spacing: 0;
  padding: 8px 10px; border-radius: 8px;
}

/* the three session tables share one first-column width (23% of the row, the
   waypoints table's current share) and the trailing time column reads right */
@media (min-width: 1001px) {
  #sessions .dlist.sg-dels .drow { grid-template-columns: 23% 0.55fr 0.55fr 1.7fr minmax(140px, auto); }
  .dlist.activity.acts .drow { grid-template-columns: 23% 1.3fr 1fr 1fr 0.9fr minmax(72px, auto); }
  #sp-req-list .drow, .dlist.props .drow[data-req] { grid-template-columns: 23% 2fr minmax(96px, auto) minmax(72px, auto); }
}
/* :not(.is-empty) for the same reason as :5118 — see the note there. */
.dlist.activity.acts .drow:not(.is-empty) > :last-child,
.dlist.props .drow[data-req]:not(.is-empty) > :last-child,
#sp-req-list .drow:not(.is-empty) > :last-child { text-align: right; justify-self: end; }

/* assets card: token + waypoint on the left, $ + amount on the right; a round
   ink "+" beside the total opens the budget wizard (same [data-connect]) */
.aum-card .stat-main { display: flex; align-items: center; gap: 12px; }
.aum-card .stat-main .bud-cap { margin-right: auto; }
.aum-add {
  margin-left: auto; width: 40px; height: 40px; flex: 0 0 auto; border: 0; border-radius: 50%;
  background: var(--ink); color: var(--white); cursor: pointer; display: flex; align-items: center; justify-content: center;
  transition: background 0.25s var(--ease);
}
.aum-add:hover { background: var(--ink-2); }
.aum-add::before {
  content: ""; width: 14px; height: 14px; background: currentColor;
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M12 5v14M5 12h14' stroke='black' stroke-width='2' stroke-linecap='round'/></svg>") center / contain no-repeat;
          mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M12 5v14M5 12h14' stroke='black' stroke-width='2' stroke-linecap='round'/></svg>") center / contain no-repeat;
}

/* drawer footer: "Your wallet" caption over the connected address; Robinhood
   with its feather on the right (logo from the landing site) */
.panel-meta { align-items: flex-end; }
.panel-wallet { display: flex; flex-direction: column; gap: 2px; }
.panel-wallet-label { font-size: 12px; line-height: 16px; font-weight: 400; color: var(--text-3); }
.panel-wallet .ca-chip { padding-left: 0; }
.panel-chain { display: inline-flex; align-items: center; gap: 8px; color: var(--ink); font-size: 14px; line-height: 20px; font-weight: 500; }
.panel-chain img { width: 16px; height: 16px; flex: 0 0 auto; }
:root[data-theme="dark"] .panel-chain img { filter: invert(1); }
/* assets "+": the close-button grammar — bare glyph, grey disc on hover — and
   it borrows no height from the total's row */
.aum-add { width: 34px; height: 34px; margin: -7px 0; background: transparent; color: var(--text-3); }
.aum-add:hover { background: var(--wash); color: var(--ink); }
/* drawer footer: both ends sit on the bottom line; feather after the name */
.pill-panel .panel-meta, .panel-meta { align-items: flex-end; }
.panel-chain { gap: 5px; line-height: 20px; }
.panel-chain img { width: 22px; height: 22px; }

/* chart direction: green when the window ends above where it began, red below */
.pf-up .pf-line { stroke: var(--ok); }
.pf-up .pf-dot, .pf-up .pf-hdot { fill: var(--ok); }
.pf-up .pf-area { fill: var(--ok-wash); }
.pf-down .pf-line { stroke: var(--bad); }
.pf-down .pf-dot, .pf-down .pf-hdot { fill: var(--bad); }
.pf-down .pf-area { fill: var(--bad-wash); }

/* balance unit dropdown beside the headline (USD · USDG · ETH) */
.pf-value-row { display: flex; align-items: baseline; gap: 6px; }
.pf-value-row .wp-select { width: auto; min-height: 0; height: 24px; padding: 0 2px 0 4px; font-size: 12px; line-height: 16px; color: var(--text-3); gap: 4px; border-radius: 6px; }
.pf-value-row .wp-select:hover { background: var(--wash); color: var(--ink); }
.pf-value-row .wp-select svg { width: 12px; height: 12px; }

/* assets card: total and "+" on one centre line; the list scrolls inside the card */
.aum-card .stat-main { align-items: center; }
.aum-add { margin: 0; }
#agg-aum .aum-list { overflow-y: auto; scrollbar-width: thin; scrollbar-color: var(--mute-fill) transparent; padding-right: 6px; margin-right: -6px; }
#agg-aum .aum-list::-webkit-scrollbar { width: 6px; }
#agg-aum .aum-list::-webkit-scrollbar-thumb { background: var(--mute-fill); border-radius: 3px; }
.aum-add { transform: translateY(-3px); }   /* the 28px figure's optical centre sits above its 34px line box */

/* assets list: keep the amounts clear of the scrollbar; count beside the label */
#agg-aum .aum-list { overscroll-behavior: contain; }
.aum-card .stat-label { display: inline-flex; align-items: center; gap: 8px; }
.aum-card .stat-label .tab-badge:empty { display: none; }
/* unit dropdown menu: never narrower than its words; above the site drawer */
.wp-select-menu { min-width: 132px; z-index: 9700; }
#aum-total { white-space: nowrap; }
#aum-total.is-long { font-size: 22px; line-height: 28px; }

/* budget wizard, trimmed (2026-09-03): no Advanced token permissions section,
   no "Cap only · spends …" line, no scope sentence in the token picker */
#connect-modal .cn-advanced { display: none; }
#connect-modal #cn-swap-note, #connect-modal .cn-swap-note { display: none; }
#connect-modal .tok-scope { display: none; }

/* ===== budget wizard, pass 4 (2026-09-03) ===== */
/* Next / Previous footer; selected venue card and action row */
#connect-modal .cn-svc[aria-selected="true"] { background: var(--grey); box-shadow: inset 0 0 0 2px var(--ink); }
#connect-modal .dlist.fn-pick button.drow.on { background: rgba(var(--ink-rgb), 0.045); box-shadow: inset 2px 0 0 var(--ink); }
#connect-modal #cn-next[disabled] { opacity: 0.35; cursor: default; }
/* expiry: slider + day field */
#connect-modal .cn-expiry { display: grid; grid-template-columns: 1fr 120px; gap: 14px; align-items: center; }
#connect-modal .cn-expiry-range { -webkit-appearance: none; appearance: none; width: 100%; height: 20px; background: transparent; margin: 0; cursor: pointer; --pct: 16%; }
#connect-modal .cn-expiry-range::-webkit-slider-runnable-track { height: 4px; border-radius: 2px; background: linear-gradient(to right, var(--ink) var(--pct), var(--line) var(--pct)); }
#connect-modal .cn-expiry-range::-moz-range-track { height: 4px; border-radius: 2px; background: var(--line); }
#connect-modal .cn-expiry-range::-moz-range-progress { height: 4px; border-radius: 2px; background: var(--ink); }
#connect-modal .cn-expiry-range::-webkit-slider-thumb { -webkit-appearance: none; width: 18px; height: 18px; margin-top: -7px; border-radius: 50%; background: var(--white); border: 2px solid var(--ink); box-shadow: 0 1px 3px var(--shadow-1); }
#connect-modal .cn-expiry-range::-moz-range-thumb { width: 14px; height: 14px; border-radius: 50%; background: var(--white); border: 2px solid var(--ink); }
#connect-modal .cn-expiry-days { display: flex; align-items: center; height: 48px; border: 1px solid var(--grey); border-radius: var(--r-md); overflow: hidden; }
#connect-modal .cn-expiry-days input { flex: 1 1 auto; min-width: 0; width: 100%; height: 100%; border: 0; outline: 0; background: transparent; padding: 0 0 0 14px; font: inherit; font-size: 14px; line-height: 20px; color: var(--ink); -moz-appearance: textfield; }
#connect-modal .cn-expiry-days input::-webkit-outer-spin-button, #connect-modal .cn-expiry-days input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
#connect-modal .cn-expiry-unit { padding: 0 14px 0 6px; font-size: 14px; line-height: 20px; color: var(--text-3); }
#connect-modal .cn-expiry-days:focus-within { border-color: var(--text-4); }
/* gas stage: docs dot-matrix on the two cards, "Optional" by the heading, buttons in the footer */
#connect-modal .cn-gas-flow > div { grid-template-columns: 40px 1fr; column-gap: 12px; }
#connect-modal .cn-gas-flow .cn-gas-dots { grid-row: 1 / 3; width: 40px; height: 40px; color: var(--ink); align-self: start; }
#connect-modal .cn-gas-flow .cn-gas-dots circle { transform-box: fill-box; transform-origin: center; }
#connect-modal .cn-gas-flow > div:hover .cn-gas-dots circle { animation: dotPop 0.42s var(--ease) both; animation-delay: calc(var(--i) * 45ms); }
#connect-modal .cn-gas-head h3 { display: flex; align-items: center; gap: 10px; }
#connect-modal .cn-opt-pill { display: inline-flex; align-items: center; height: 22px; padding: 0 9px; border-radius: 999px; background: var(--wash); color: var(--text-3); font-size: 12px; line-height: 16px; font-weight: 400; letter-spacing: 0; }
#connect-modal .cn-actions { position: relative; }
#connect-modal .cn-actions .cn-gas-stage-actions { display: contents; }
#connect-modal .cn-gas-stage .cn-gas-stage-actions { display: none; }
/* the signing sequence lives behind an info button at the footer's left */
#connect-modal .cn-seq-btn { order: -1; margin-right: auto; width: 34px; height: 34px; border: 0; border-radius: 50%; background: transparent; color: var(--text-3); display: flex; align-items: center; justify-content: center; cursor: pointer; transition: background 0.25s var(--ease), color 0.25s var(--ease); }
#connect-modal .cn-seq-btn:hover { background: var(--wash); color: var(--ink); }
#connect-modal .cn-seq-btn svg { width: 18px; height: 18px; }
#connect-modal .cn-seq-btn[hidden] { display: none; }
#connect-modal .cn-actions .cn-steps { position: absolute; left: 0; bottom: calc(100% + 8px); z-index: 3; width: min(380px, 100%); flex-basis: auto; order: 0; margin: 0; padding: 14px 16px; background: var(--white); border: 1px solid var(--line); border-radius: 12px; box-shadow: 0 10px 34px var(--shadow-2); display: none; }
#connect-modal .cn-actions .cn-steps.show { display: block; }
#connect-modal .cn-actions .cn-foot { order: 0; }

/* requests: Actions column (Approve · Decline); waypoints: Edit · Cut off */
@media (min-width: 1001px) {
  #sp-req-list .drow, .dlist.props .drow[data-req] { grid-template-columns: 23% 2fr minmax(96px, auto) minmax(72px, auto) minmax(150px, auto); }
}
#sp-req-list .drow .cell-time, .dlist.props .drow[data-req] .cell-time { text-align: right; justify-self: end; }
#sp-req-list .req-actions, .dlist.props .req-actions { display: flex; align-items: center; gap: 14px; justify-self: end; }
.sdot.bad { background: var(--bad); }

/* signing sequence as a roadmap: dots joined by a line, room between steps */
#connect-modal .cn-actions .cn-steps { gap: 0; padding: 16px 18px; }
#connect-modal .cn-actions .cn-step { position: relative; padding-bottom: 16px; gap: 12px; }
#connect-modal .cn-actions .cn-step:last-child { padding-bottom: 0; }
#connect-modal .cn-actions .cn-step .sdot { width: 8px; height: 8px; margin-top: 6px; flex: 0 0 auto; position: relative; z-index: 1; }
#connect-modal .cn-actions .cn-step::before { content: ""; position: absolute; left: 3.5px; top: 14px; bottom: -6px; width: 1px; background: var(--line); }
#connect-modal .cn-actions .cn-step.is-done::before { background: var(--ok); opacity: 0.6; }
#connect-modal .cn-actions .cn-step:last-child::before { display: none; }
#connect-modal .cn-gas-flow .cn-gas-dots { width: 36px; height: 36px; }
/* gas cards: the docs' own step glyphs at their 42px */
#connect-modal .cn-gas-flow > div { grid-template-columns: 42px 1fr; column-gap: 14px; }
#connect-modal .cn-gas-flow .cn-gas-dots { width: 42px; height: 42px; }
/* roadmap: the optional last step reads ink, reached by a dashed grey connector */
#connect-modal .cn-actions .cn-step:nth-last-child(2)::before { background: none; border-left: 1px dashed var(--text-4); width: 0; }
#connect-modal .cn-actions .cn-step:last-child .sdot { background: var(--ink); }

/* row actions as icons (2026-09-03): pen / cross / check on the close-button
   grammar — 34px round hit area, grey disc on hover, red or green where the
   action is destructive or affirmative; the label lives in the tooltip pill */
.icon-act { width: 34px; height: 34px; margin: -7px 0; border: 0; border-radius: 50%; background: transparent; color: var(--text-3); display: inline-flex; align-items: center; justify-content: center; cursor: pointer; transition: background 0.25s var(--ease), color 0.25s var(--ease); }
.icon-act svg { width: 16px; height: 16px; }
.icon-act:hover { background: var(--wash); color: var(--ink); }
.icon-act.is-bad { color: var(--bad); }
.icon-act.is-bad:hover { background: var(--bad-wash); color: var(--bad); }
.icon-act.is-ok { color: var(--ok); }
.icon-act.is-ok:hover { background: var(--ok-wash-2); color: var(--ok); }
#sessions .sg-dels .del-actions, #sp-req-list .req-actions, .dlist.props .req-actions { gap: 4px; }
/* requests: Raised reads left again; only Actions sits at the right edge */
#sp-req-list .drow .cell-time, .dlist.props .drow[data-req] .cell-time { text-align: left; justify-self: start; }

/* wizard footer: the hidden "Budget active" confirmation no longer reserves a
   second line; bottom inset == the create-session popup's 30px */
#connect-modal .cn-confirm:not(.show) { display: none; }
#connect-modal .cn-body { padding-bottom: 30px; }
/* progress count beside the info button: "4 / 5" with a state dot */
#connect-modal .cn-seq-count { order: -1; display: inline-flex; align-items: center; gap: 8px; font-size: 12px; line-height: 16px; color: var(--text-3); cursor: default; }
#connect-modal .cn-seq-count b { font-weight: 400; font-variant-numeric: tabular-nums; }
#connect-modal .cn-seq-count[hidden] { display: none; }
#connect-modal .cn-seq-btn { margin-right: 0; }
#connect-modal .cn-seq-count + .cn-seq-btn { order: -2; }
#connect-modal .cn-seq-count { margin-right: auto; }

/* ===== wallet square (2026-09-03) =====
   address + Copy in the bar beside the tile at the tile's height; Network /
   Balance as label-left value-right rows in the page face; Disconnect as a
   full-width pill; the identicon's dots pop on hover like the site's cards */
.wp-acct-bar .wp-acct-addr { flex: 1 1 auto; min-width: 0; height: 42px; padding: 0 14px; border-radius: 12px; background: var(--wash); font-family: inherit; opacity: 0; transition: opacity 0.3s var(--ease), background 0.25s var(--ease); }
.wp-acct.open .wp-acct-bar .wp-acct-addr { opacity: 1; }
.wp-acct-bar .wp-acct-addr:hover { background: var(--wash-2); }
.wp-acct-name { flex: 1 1 auto; opacity: 1; color: var(--ink); font-family: inherit; }
.wp-acct-copy-hint { font-size: 12px; line-height: 16px; letter-spacing: 0; }
.wp-acct-inner { gap: 0; padding: 6px 14px 14px; }
.wp-acct-inner .agent-kv { justify-content: space-between; align-items: center; gap: 16px; padding: 11px 0; border-bottom: 1px solid var(--line); font-family: inherit; }
.wp-acct-inner .agent-kv .k { color: var(--text-3); }
.wp-acct-inner .agent-kv .v { color: var(--ink); text-align: right; font-family: inherit; font-variant-numeric: tabular-nums; }
.wp-acct-inner .agent-kv:last-of-type { border-bottom: 0; }
.wp-acct-acts { margin-top: 10px; }
.wp-acct-acts .btn-pill { width: 100%; height: 40px; display: inline-flex; align-items: center; justify-content: center; padding: 0 18px; font-size: 14px; font-weight: 500; line-height: 20px; border-radius: 999px; }
.wp-acct-glyph svg { width: 22px; height: 22px; }
.wp-acct-glyph circle { transform-box: fill-box; transform-origin: center; }
.wp-acct-tile:hover .wp-acct-glyph circle { animation: dotPop 0.42s var(--ease) both; animation-delay: calc(var(--i) * 45ms); }
@media (prefers-reduced-motion: reduce) { .wp-acct-tile:hover .wp-acct-glyph circle { animation: none; } }

/* gas popover: one full-width field — "≈ N calls" at the left, the amount and
   ETH at the right — with Deposit · Remove under it, left-aligned */
.wpc-pop-gas { width: 320px; }
.gas-acts { flex-direction: column; align-items: stretch; gap: 12px; }
.gas-field { display: flex; align-items: center; height: 40px; padding: 0 12px 0 14px; border: 1px solid var(--grey); border-radius: var(--r-md); background: var(--white); cursor: text; transition: border-color 0.25s var(--ease); }
.gas-field:hover, .gas-field:focus-within { border-color: var(--text-4); }
.gas-field .del-gas-calls { flex: 0 0 auto; margin-right: auto; font-size: 14px; line-height: 20px; color: var(--text-3); white-space: nowrap; }
.gas-field .del-gas-calls:empty::before { content: "≈ 0 calls"; }
.gas-field .gas-amt, .gas-field .del-gas-amt { flex: 1 1 auto; width: auto; max-width: none; min-width: 0; height: 100%; border: 0; background: transparent; padding: 0 6px 0 12px; text-align: right; }
.gas-field .del-gas-unit { flex: 0 0 auto; font-size: 14px; line-height: 20px; color: var(--text-3); }
.gas-btns { display: flex; align-items: center; justify-content: flex-start; gap: 14px; }

/* ===== wizard step 2 as docs tiles (2026-09-03) — the .ov-tile grammar from
   waypoint.world/docs: two columns, grey card, kicker + title, arrow at right;
   section headings span both columns; everything but the grantable action
   answers hover with the "Coming soon" pill ===== */
#connect-modal .dlist.fn-pick { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; background: transparent; border-radius: 0; padding: 0; }
#connect-modal .dlist.fn-pick .drow.head { grid-column: 1 / -1; padding: 10px 0 0; margin: 0; width: auto; border: 0; font-size: 12px; line-height: 16px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--text-3); }
#connect-modal .dlist.fn-pick .drow.head:first-child { padding-top: 0; }
#connect-modal .dlist.fn-pick .drow:not(.head) {
  display: block; position: relative; margin: 0; width: auto; border: 0; border-radius: var(--r-md);
  padding: 22px 52px 24px 24px; background: var(--card); text-align: left; cursor: pointer;
  transition: background 0.25s var(--ease);
}
#connect-modal .dlist.fn-pick .drow:not(.head):hover { background: var(--grey); box-shadow: none; }
#connect-modal .dlist.fn-pick .drow.head + .drow, #connect-modal .dlist.fn-pick .drow:first-child { border-top: 0; }
#connect-modal .dlist.fn-pick .fn-action { display: flex; flex-direction: column-reverse; gap: 10px; }
#connect-modal .dlist.fn-pick .cell-name { font-size: 18px; font-weight: 500; letter-spacing: -0.01em; line-height: 24px; color: var(--ink); }
#connect-modal .dlist.fn-pick .cell-sub { font-size: 12px; font-weight: 500; line-height: 16px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--text-3); margin: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#connect-modal .dlist.fn-pick .cell-badge, #connect-modal .dlist.fn-pick .cn-svc-tag { display: none; }
#connect-modal .dlist.fn-pick .drow:not(.head)::after {
  content: ""; position: absolute; top: 50%; right: 22px; width: 18px; height: 18px; translate: 0 -50%;
  background: currentColor; color: rgba(var(--ink-rgb), 0.35);
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'><line x1='5' y1='12' x2='19' y2='12'/><polyline points='12 5 19 12 12 19'/></svg>") center / contain no-repeat;
          mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'><line x1='5' y1='12' x2='19' y2='12'/><polyline points='12 5 19 12 12 19'/></svg>") center / contain no-repeat;
  transition: color 0.25s var(--ease), transform 0.25s var(--ease);
}
#connect-modal .dlist.fn-pick button.drow:hover::after { color: var(--ink); transform: translateX(3px); }
/* not-yet-grantable tiles: same card, muted title, "Coming soon" kicker, no arrow */
#connect-modal .dlist.fn-pick .drow.is-nobudget, #connect-modal .dlist.fn-pick .drow.is-blocked { opacity: 1; cursor: default; }
#connect-modal .dlist.fn-pick .drow.is-nobudget .cell-name, #connect-modal .dlist.fn-pick .drow.is-blocked .cell-name { color: var(--text-3); }
#connect-modal .dlist.fn-pick .drow.is-nobudget .cell-sub, #connect-modal .dlist.fn-pick .drow.is-blocked .cell-sub { font-size: 0; }
#connect-modal .dlist.fn-pick .drow.is-nobudget .cell-sub::before, #connect-modal .dlist.fn-pick .drow.is-blocked .cell-sub::before { content: "Coming soon"; font-size: 12px; }
#connect-modal .dlist.fn-pick .drow.is-nobudget::after, #connect-modal .dlist.fn-pick .drow.is-blocked::after { opacity: 0.4; }
#connect-modal .dlist.fn-pick .fn-none { grid-column: 1 / -1; }
#connect-modal .dlist.fn-pick button.drow.on { background: var(--grey); box-shadow: inset 0 0 0 2px var(--ink); }
@media (max-width: 700px) { #connect-modal .dlist.fn-pick { grid-template-columns: 1fr; } }
#connect-modal .dlist.fn-pick .drow .cn-svc-tag, #connect-modal .dlist.fn-pick .drow .cell-badge, #connect-modal .dlist.fn-pick .drow .fn-why { display: none !important; }
#connect-modal .dlist.fn-pick .drow.is-nobudget .cell-sub.fn-why { display: block !important; }

/* step-2 tiles, pass 2: three columns, a dot-matrix mark up top that pops on
   hover, then the action name over its description at 14px — no caps, no arrow */
#connect-modal .dlist.fn-pick { grid-template-columns: repeat(3, 1fr); }
#connect-modal .dlist.fn-pick .drow:not(.head) { display: flex; flex-direction: column; gap: 22px; padding: 20px 20px 20px; }
#connect-modal .dlist.fn-pick .drow:not(.head)::after { content: none; }
#connect-modal .dlist.fn-pick .fn-dots { width: 36px; height: 36px; color: var(--ink); flex: 0 0 auto; }
#connect-modal .dlist.fn-pick .fn-dots circle, #connect-modal .dlist.fn-pick .fn-dots rect { transform-box: fill-box; transform-origin: center; }
#connect-modal .dlist.fn-pick .drow:not(.head):hover .fn-dots circle, #connect-modal .dlist.fn-pick .drow:not(.head):hover .fn-dots rect { animation: dotPop 0.42s var(--ease) both; animation-delay: calc(var(--i) * 45ms); }
@media (prefers-reduced-motion: reduce) { #connect-modal .dlist.fn-pick .drow:hover .fn-dots circle, #connect-modal .dlist.fn-pick .drow:hover .fn-dots rect { animation: none; } }
#connect-modal .dlist.fn-pick .fn-action { flex-direction: column; gap: 2px; }
#connect-modal .dlist.fn-pick .cell-name { font-size: 14px; line-height: 20px; font-weight: 500; letter-spacing: 0; }
#connect-modal .dlist.fn-pick .cell-sub { font-size: 14px; line-height: 20px; font-weight: 400; letter-spacing: 0; text-transform: none; white-space: normal; }
#connect-modal .dlist.fn-pick .drow.is-nobudget .cell-sub::before, #connect-modal .dlist.fn-pick .drow.is-blocked .cell-sub::before { font-size: 14px; }
#connect-modal .dlist.fn-pick .drow.is-nobudget .fn-dots, #connect-modal .dlist.fn-pick .drow.is-blocked .fn-dots { color: var(--text-3); }
#connect-modal .dlist.fn-pick .drow.head { letter-spacing: 0; text-transform: none; font-size: 12px; }
@media (max-width: 900px) { #connect-modal .dlist.fn-pick { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 700px) { #connect-modal .dlist.fn-pick { grid-template-columns: 1fr; } }
#connect-modal .dlist.fn-pick .drow:not(.head) { align-items: flex-start; text-align: left; }
#connect-modal .dlist.fn-pick .fn-action { align-items: flex-start; width: 100%; }

/* wizard: venue logo beside its name (step 2 heading, step 3 summary); Quote
   flows in as the sixth tile; tile inset trimmed; spend → receive with an arrow */
#connect-modal .cn-venue-logo { display: inline-block; width: 22px; height: 22px; flex: 0 0 auto; background: var(--ink); -webkit-mask: var(--logo) center / contain no-repeat; mask: var(--logo) center / contain no-repeat; }
#connect-modal #cn-fn-label { display: flex; align-items: center; gap: 8px; }
#connect-modal .cn-picked { display: flex; align-items: center; gap: 10px; }
#connect-modal .cn-picked span { font-size: 14px; line-height: 20px; }
#connect-modal .dlist.fn-pick .drow.head:not(:first-child), #connect-modal .dlist.fn-pick .fn-none { display: none; }
#connect-modal .dlist.fn-pick .drow:not(.head) { padding: 20px 20px 18px; gap: 20px; }
#connect-modal .dlist.fn-pick .fn-action { margin: 0; padding: 0; row-gap: 2px; }
#connect-modal .dlist.fn-pick .cell-sub, #connect-modal .dlist.fn-pick .cell-name { margin: 0; }
#connect-modal .cn-swap { grid-template-columns: 1fr 24px 1fr; gap: 12px; align-items: end; }
#connect-modal .cn-swap-arrow { display: flex; align-items: center; justify-content: center; height: 48px; color: var(--text-3); }
#connect-modal .cn-swap-arrow svg { width: 18px; height: 18px; }
#connect-modal .cn-swap-leg { min-width: 0; }

/* requests: the waypoint (mark + name) asks; assets: the waypoint mark on the
   sub line; step 2 loses its "Actions" heading */
#sp-req-list .drow[data-req] .cell-name .del-wp { display: inline-flex; align-items: center; gap: 8px; vertical-align: middle; }
#agg-aum .acc-cell span .del-wp { display: inline-flex; align-items: center; gap: 5px; }
#agg-aum .acc-cell span .del-wp .act-venue img, #agg-aum .acc-cell span .del-wp .act-venue svg, #agg-aum .acc-cell span .del-wp .venue-mark { width: 12px; height: 12px; }
#agg-aum .acc-cell span .del-wp .cell-name { font-size: 12px; line-height: 16px; font-weight: 400; color: var(--text-3); }
#connect-modal .dlist.fn-pick .drow.head { display: none; }
#agg-aum .acc-cell span .del-wp .act-logo { width: 12px; height: 12px; }
#sp-req-list .drow[data-req] .cell-name .del-wp .act-logo { width: 16px; height: 16px; }

/* step-2 heading breathes; requests' waypoint mark at the table's 22px, on one
   line with "asks for"; Waypoints title at 34; no monospace in the token picker */
#connect-modal #cn-fn-label { margin-bottom: 18px; }
#sp-req-list .drow[data-req] .cell-name { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
#sp-req-list .drow[data-req] .cell-name .del-wp .act-logo { width: 22px; height: 22px; }
#sp-req-list .drow[data-req] .cell-name .del-wp { gap: 8px; }
#sess-title.app-title { font-size: 34px; line-height: 41px; letter-spacing: -0.02em; }
#connect-modal .tok-panel .mono, #connect-modal .tok-row .mono, #connect-modal .tok-row-sub, #connect-modal .cn-sell-tok .mono { font-family: inherit; letter-spacing: 0; }
/* the Dashboard title sits 20px above its cards — the same gap Waypoints keeps */
#panel-overview { margin-top: 20px; }

/* waypoint ID bubble: "#3F2A" beside the action name wherever a waypoint is named */
.wp-tag { display: inline-flex; align-items: center; height: 18px; padding: 0 7px; margin-left: 6px; border-radius: 999px; background: rgba(var(--ink-rgb), 0.06); color: var(--text-3); font-size: 12px; line-height: 16px; font-weight: 400; letter-spacing: 0.01em; font-variant-numeric: tabular-nums; white-space: nowrap; vertical-align: middle; }
.del-wp .wp-tag { flex: 0 0 auto; }
#agg-aum .acc-cell span .wp-tag { height: 16px; padding: 0 6px; margin-left: 5px; }
#sp-req-list .drow[data-req] .cell-name .del-wp .wp-tag { margin-left: 0; }
.del-wp .wp-tag { margin-left: -4px; }   /* .del-wp's 12px column gap minus 4 → 8px after the name */

/* ===== directory popup (2026-09-03) ===== */
/* fixed first column in both lists so labels line up; no trailing rule
   inside the grey atom table; method names at 12px with a copy button */
.dlist.fn .drow, .atom-fns .drow { grid-template-columns: 220px 1fr; column-gap: 24px; }
.atom-fns .drow:last-child { border-bottom: 0; }
.atom-fns { margin-bottom: 6px !important; }
.atom-method-row { display: flex; align-items: center; gap: 4px; margin-bottom: 4px; }
.atom-method { display: inline; margin: 0; font-size: 12px; line-height: 16px; }
.copy-mini { width: 22px; height: 22px; border: 0; border-radius: 50%; background: transparent; color: var(--text-4); display: inline-flex; align-items: center; justify-content: center; cursor: pointer; transition: background 0.25s var(--ease), color 0.25s var(--ease); }
.copy-mini svg { width: 12px; height: 12px; }
.copy-mini:hover { background: var(--wash); color: var(--ink); }
.copy-mini.is-copied { color: var(--ok); }
/* header: the protocol's own mark, big; category and trust as pills */
.modal-symbol.svc-protocol-logo { width: 64px; height: 64px; margin-top: 0; }
.modal-header { align-items: center; }
.modal-cat .svc-cat, .modal-cat .svc-verified { display: inline-flex; align-items: center; gap: 6px; height: 22px; padding: 0 9px; border-radius: 999px; background: var(--wash); color: var(--text-3); font-size: 12px; line-height: 16px; }
.modal-cat .svc-verified .sdot { width: 6px; height: 6px; }
/* chain row: an on-disk mark (Robinhood feather) at the glyph's size */
.chain-glyph.chain-img { width: 16px; height: 16px; object-fit: contain; }
:root[data-theme="dark"] .chain-glyph.chain-img { filter: invert(1); }

/* ===== The fn-pick kicker says what the tile actually is (2026-09-02) =====
   The rule at :5424 writes "Coming soon" into every non-grantable tile's
   kicker, which is true of the LP capabilities (declared in the signed
   manifest, no encoder behind them) and false of the other two kinds:
     .is-read      a READ. Quote works today and the agent already has it. It
                   carries no budget because it spends nothing, which is a
                   different sentence from "not built yet".
     .is-included  the exit leg, compiled into the same venue arm as the action
                   above it. It is already granted.
   Both carry the class the layout needs as well, so nothing about the tile
   changes but the word. The extra class raises specificity over :5424 so this
   holds wherever it sits in the cascade. */
#connect-modal .dlist.fn-pick .drow.is-nobudget.is-read .cell-sub::before { content: "Read-only"; }
#connect-modal .dlist.fn-pick .drow.is-blocked.is-included .cell-sub::before { content: "Included"; }

/* ============================================================================
   THE EMPTY ROW SPANS THE TABLE — AFTER the per-page grids (2026-09-02).

   `.dlist .drow.is-empty { grid-template-columns: 1fr }` at :4615 was written
   to stop a one-cell message being squeezed into column one of a multi-column
   grid. Three rules added later for the #sessions page out-order it — two by
   sitting further down the sheet inside the >=1001px block (:5200-:5202) and
   two by carrying an id or a fourth class — so on the one page that matters
   the empty row kept the full five-column grid and the message rendered in a
   23% column. Measured against the real sheet: 140px off in the budgets
   table, 235px in the actions table, 204px in the requests table.

   This restates the same intent at a specificity and a position that hold:
   after every grid above, and with an id where the rule it must beat has one.
   Any NEW per-page grid for these tables belongs above this block.
   (The other half of the misalignment was `> :last-child` right-aligning a
   sole child; that is fixed at its source, :5118 and :5204.) */
#sessions .dlist .drow.is-empty,
#sessions .dlist.sg-dels .drow.is-empty,
.dlist.activity.acts .drow.is-empty,
.dlist.props .drow.is-empty,
#sp-log-list .drow.is-empty,
#sp-req-list .drow.is-empty { grid-template-columns: 1fr; }

/* …and the message starts where the first column head starts. */
#sessions .dlist .drow.is-empty > .cell-sub,
.dlist.activity.acts .drow.is-empty > .cell-sub,
.dlist.props .drow.is-empty > .cell-sub,
#sp-log-list .drow.is-empty > .cell-sub,
#sp-req-list .drow.is-empty > .cell-sub { justify-self: start; text-align: left; }


/* THE DEPOSIT TICKET'S UNITS SIZE TO THEIR OWN WORD (2026-09-03).
   `.cn-nat-unit` is fixed at 72px, which was picked for "ETH" on the native ticket. "steakUSDG"
   is nine characters and did not fit, so it sat hard against the edges of its cell and read as
   left-aligned even though the cell centres its content. These two are the only units that can
   carry a vault share ticker, so the flex basis becomes the content plus a symmetric inset —
   still centred, still the same height and border, and now actually centred to the eye because
   the box is as wide as the word inside it. */
#connect-modal .cn-dep-swap .cn-nat-unit {
  flex: 0 0 auto;
  min-width: 72px;                                  /* == the fixed basis it replaces, as a floor */
  padding: 0 14px;                                  /* == .cn-inline-select's own inset */
  text-align: center;
}

/* ============================================================================
   MOBILE USABILITY HARDENING (2026-09-03)
   One phone layout for sheets, dialogs, menus, data rows and actions. Desktop
   selectors above remain untouched; these rules apply only to narrow viewports.
   ============================================================================ */
@media (max-width: 760px) {
  html, body, .page, .app-main { max-width: 100%; overflow-x: clip; }
  .app-head, .sess-head-acts, .sp-head-pills { min-width: 0; }
  body .pill-bar, .wp-acct-bar { height: 58px; padding: 7px; }
  body .pill-logo, body .pill-toggle, .wp-acct-tile { width: 44px; height: 44px; }
  .wp-acct:not(.open) { width: 58px; }
  .sp-head-pills { width: 100%; margin-left: 0; }
  #sessions .sess-head-acts { width: 100%; }
  #sessions .sess-head-acts > *, .sp-head-pills > * { min-width: 0; }
  #sessions .sp-add { margin-left: 0; }

  /* Closed absolute popovers used to enlarge a 320px document to 460–492px.
     Header menus are viewport sheets on phones, open or closed. */
  #sp-connect-panel .wpc-pop, #sp-gas-panel .wpc-pop {
    position: fixed;
    inset: auto 12px max(12px, env(safe-area-inset-bottom));
    z-index: 9200;
    width: auto;
    max-width: none;
    max-height: min(76dvh, 560px);
    overflow-y: auto;
    overscroll-behavior: contain;
    border-radius: 18px;
    padding: 8px;
    transform-origin: bottom center;
  }
  .wpc-item { min-height: 56px; padding: 10px 12px; overflow-wrap: anywhere; }
  .wpc-item.is-error .wpc-is { color: var(--bad); }
  .wpc-pop-inner, .wpc-it, .wpc-is { min-width: 0; max-width: 100%; }

  /* All dialogs use the same bottom-sheet frame. The body is the only scrolling
     region; headers and full-width actions stay available above safe area. */
  .modal { place-items: end center; padding: 0; }
  .modal-card, #connect-modal .modal-card, #perm-modal .modal-card, #add-agent-modal .modal-card {
    width: 100%; max-width: 100%; max-height: calc(100dvh - 8px);
    border-radius: 18px 18px 0 0;
  }
  .modal-header, #perm-modal .modal-header, #add-agent-modal .modal-header {
    min-width: 0; padding: 24px 64px 12px 20px;
  }
  .modal-symbol.svc-protocol-logo { width: 48px; height: 48px; }
  .modal-title, #connect-modal .cn-title { font-size: 22px; line-height: 28px; }
  .modal-body, #perm-modal .modal-body, #add-agent-modal .modal-body {
    min-width: 0; padding: 16px 20px 24px; gap: 20px;
    overscroll-behavior: contain;
  }
  #add-agent-modal .modal-body { padding-bottom: 20px; }
  .modal-foot, #add-agent-modal .modal-foot {
    display: flex; flex-wrap: wrap; width: 100%; gap: 10px;
    padding: 12px 20px calc(16px + env(safe-area-inset-bottom));
  }
  .modal-foot .modal-confirm { flex: 1 1 100%; }
  .modal-foot .wpc { flex: 1 1 100%; width: 100%; margin: 0; }
  .modal-foot .wpc-menu, .modal-foot .wpc-pill,
  .modal-foot .btn-pill, #add-agent-modal .btn-pill { width: 100%; min-height: 44px; }
  .modal-x, #connect-modal .cn-close { width: 44px; height: 44px; top: 16px; right: 14px; }
  .modal-pair, .dlist.fn .drow, .atom-fns .drow { grid-template-columns: minmax(0, 1fr); }
  .dlist.fn .drow, .atom-fns .drow { gap: 6px; }
  .atom-head { min-height: 56px; }
  .atom-cat { max-width: 36%; text-align: right; overflow-wrap: anywhere; }

  /* The budget wizard is the same sheet, not a shrunken desktop card. */
  #connect-modal .cn-body {
    width: 100%; max-width: 100%; max-height: calc(100dvh - 8px);
    gap: 16px; padding: 20px 20px calc(16px + env(safe-area-inset-bottom));
  }
  #connect-modal .cn-head { min-width: 0; padding-right: 44px; gap: 8px 12px; }
  #connect-modal .cn-title { flex: 1 1 auto; min-width: 0; }
  #connect-modal .cn-form { min-width: 0; margin-right: -6px; padding-right: 6px; gap: 18px; }
  #connect-modal .cn-step-pane { min-width: 0; gap: 18px; }
  #connect-modal .cn-svc-list { grid-template-columns: minmax(0, 1fr); }
  #connect-modal .cn-svc {
    min-height: 88px; aspect-ratio: auto; padding: 16px 16px 16px 84px;
    justify-content: center;
  }
  #connect-modal .cn-svc-logo { inset: 0 auto 0 18px; width: 48px; height: 48px; }
  #connect-modal .dlist.fn-pick { grid-template-columns: minmax(0, 1fr); padding: 0; }
  #connect-modal .dlist.fn-pick .drow:not(.head) { min-width: 0; min-height: 96px; padding: 16px; gap: 14px; }
  #connect-modal .cn-swap, #connect-modal .cn-nat-swap, #connect-modal .cn-dep-swap {
    grid-template-columns: minmax(0, 1fr); gap: 14px;
  }
  #connect-modal .cn-swap-arrow { display: none; }
  #connect-modal .cn-inline-select { flex-basis: min(116px, 42%); }
  #connect-modal .cn-dep-swap .cn-nat-unit { max-width: 46%; overflow-wrap: anywhere; }
  #connect-modal .cn-expiry { grid-template-columns: minmax(0, 1fr) 108px; gap: 10px; }
  #connect-modal .cn-acq-budget { grid-template-columns: minmax(0, 1fr); gap: 10px; padding: 14px; }
  #connect-modal .tok-panel { left: 0; right: 0; width: auto; max-width: 100%; }
  #connect-modal .cn-actions { width: 100%; gap: 8px; padding-top: 10px; }
  #connect-modal .cn-actions .cn-approve,
  #connect-modal .cn-actions .cn-cancel {
    flex: 1 1 100%; width: 100%; min-height: 44px;
  }
  #connect-modal .cn-actions .cn-seq-btn {
    flex: 0 0 44px; width: 44px; min-height: 44px;
  }
  #connect-modal .cn-actions .cn-seq-count { flex: 1 1 auto; min-height: 44px; }
  #connect-modal .cn-actions .cn-steps {
    position: fixed; left: 12px; right: 12px;
    bottom: max(12px, env(safe-area-inset-bottom)); width: auto;
    max-height: 70dvh; overflow-y: auto;
  }
  #connect-modal .cn-gas-flow { grid-template-columns: minmax(0, 1fr); }
  #connect-modal .cn-gas-head h3 { align-items: flex-start; flex-wrap: wrap; }

  /* Data rows stop squeezing desktop tracks into 288px. */
  #sessions .dlist.sg-dels, #sessions .sp-panel .dlist { padding-inline: 16px; }
  #sessions .dlist.sg-dels .drow:not(.head):not(.is-empty) {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 14px 16px; padding: 18px 0;
  }
  #sessions .dlist.sg-dels .drow:not(.head) > :first-child,
  #sessions .dlist.sg-dels .drow:not(.head) > .cell-budget,
  #sessions .dlist.sg-dels .drow:not(.head) > .del-actions { grid-column: 1 / -1; }
  #sessions .sg-dels .cell-budget { padding-right: 0; }
  #sessions .dlist.sg-dels .drow:not(.head) > .del-leg,
  #sessions .dlist.sg-dels .drow:not(.head) > .cell-budget { min-width: 0; }
  #sessions .dlist.sg-dels .drow:not(.head) > .del-leg { display: flex; flex-direction: column; gap: 2px; }
  #sessions .dlist.sg-dels .drow:not(.head) > :nth-child(2)::before { content: "Spend"; }
  #sessions .dlist.sg-dels .drow:not(.head) > :nth-child(3)::before { content: "Receive"; }
  #sessions .dlist.sg-dels .drow:not(.head) > .del-leg::before {
    font-size: 12px; line-height: 16px; color: var(--text-3);
  }
  #sessions .sg-dels .del-actions,
  #sp-req-list .req-actions, .dlist.props .req-actions {
    justify-self: stretch; justify-content: flex-end; min-height: 44px;
  }
  .icon-act, .copy-mini, .sp-rotate, .aum-add,
  .pos-step, .pool-seed-x, #connect-modal .cn-sell-x {
    width: 44px; height: 44px; min-width: 44px; min-height: 44px; margin: 0;
  }
  #sp-req-list .drow:not(.head):not(.is-empty),
  .dlist.props .drow[data-req]:not(.head):not(.is-empty) {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 10px 16px;
  }
  #sp-req-list .drow:not(.head) > :nth-child(1),
  #sp-req-list .drow:not(.head) > :nth-child(2),
  #sp-req-list .drow:not(.head) > .req-actions { grid-column: 1 / -1; }
  .dlist.activity.acts .drow:not(.head):not(.is-empty) {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 8px 16px; padding: 18px 0;
  }
  .dlist.activity.acts .drow:not(.head) > :nth-child(even) { text-align: right; justify-self: end; }
  .dlist.activity.acts .drow:not(.head) > .cell-status { justify-self: start; text-align: left; }
  .dlist.activity.acts .drow:not(.head) > .cell-time { justify-self: end; text-align: right; }

  /* Shared 44px touch floor; long secrets wrap inside their own viewport. */
  .btn-mini, .btn-pill, .sp-cred, .wp-select, .wp-select-item,
  .pool-add-btn, .pool-panel .row-link, .pool-addtok-row .row-link,
  .pool-addtok-open, #connect-modal .cn-tok-add { min-height: 44px; }
  .sp-head-pills .btn-mini, .sp-head-pills .btn-pill { height: 44px; }
  body .app-main .car-tab, body .theme-tabs .car-tab { min-height: 44px; }
  body .pf-value-row .wp-select { height: 44px; min-height: 44px; padding-inline: 8px; }
  body .panel-wallet .ca-chip, body .wp-acct-bar .wp-acct-addr { min-height: 44px; }
  #sessions .del-acct[data-perms] { min-height: 44px; justify-content: center; }
  .cred-token, .chip-addr, .agent-kv .v, .pool-acct { overflow-wrap: anywhere; word-break: break-word; }
  .pool-panel, .pool-seed, #connect-modal .cn-sell-row { min-width: 0; }
  .pool-panel-act, .pool-panel-ctl, .pool-seed-amt { flex-wrap: wrap; }
  .pool-panel-act .btn-mini, .pool-addtok-row .btn-mini { flex: 1 1 auto; }
  .wp-select-menu {
    max-width: calc(100vw - 16px); max-height: calc(100dvh - 16px);
    overflow-y: auto; overscroll-behavior: contain;
  }
}

.wpc-item.is-error .wpc-is { color: var(--bad); }

@media (max-width: 360px) {
  #connect-modal .cn-body { padding-inline: 16px; }
  .modal-header, #perm-modal .modal-header, #add-agent-modal .modal-header { padding-left: 16px; }
  .modal-body, #perm-modal .modal-body, #add-agent-modal .modal-body,
  .modal-foot, #add-agent-modal .modal-foot { padding-left: 16px; padding-right: 16px; }
  .sess-title-row { gap: 8px; }
  #sess-title.app-title { font-size: 28px; line-height: 34px; }
  #connect-modal .cn-expiry { grid-template-columns: minmax(0, 1fr); }
}
