/* One stylesheet, self-hosted, no inline style anywhere in any template — that is what lets the
   CSP ship without unsafe-inline. See SecurityHeadersFilter.

   The ground-up redesign of 2026-10-16 (HOOKS-REDESIGN-FOUNDATION-1). The visual spec is the
   vendored handoff, docs/handoff-2026-10-16-redesign/README.md: tokens, type scale, radii and copy
   come from there and are not restated here. What IS here is where this file departs from it, and
   the measured contrast of every muted, faint and opacity-over-text pairing — the workspace's
   standing rule that any reduced-contrast text carries its figure beside it.

   TOKENS SWITCH BY MEDIA QUERY, NOT light-dark(). The handoff writes every colour as
   light-dark(a, b). Inside a custom property that is unsafe: a custom property stores tokens
   without validating them, so on a browser without light-dark() (iOS Safari before 17.5) every
   var() reading it becomes invalid at computed-value time and falls back to `unset` — the page
   renders with no background, no card surfaces and no accent at all, rather than in the wrong
   theme. The same two values, chosen by prefers-color-scheme, cannot fail that way.

   FONTS ARE SELF-HOSTED (owner decision, 2026-10-16): IBM Plex Sans and Mono, latin subset, OFL,
   licence at /fonts/OFL.txt. Not Google Fonts — no new sub-processor on a privacy-led page that
   lists its sub-processors, and no CSP change, because default-src 'self' already covers font-src. */

@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 400; font-display: swap;
             src: url("/fonts/ibm-plex-sans-latin-400-normal.woff2") format("woff2"); }
@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 500; font-display: swap;
             src: url("/fonts/ibm-plex-sans-latin-500-normal.woff2") format("woff2"); }
@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 600; font-display: swap;
             src: url("/fonts/ibm-plex-sans-latin-600-normal.woff2") format("woff2"); }
@font-face { font-family: "IBM Plex Mono"; font-style: normal; font-weight: 400; font-display: swap;
             src: url("/fonts/ibm-plex-mono-latin-400-normal.woff2") format("woff2"); }
@font-face { font-family: "IBM Plex Mono"; font-style: normal; font-weight: 500; font-display: swap;
             src: url("/fonts/ibm-plex-mono-latin-500-normal.woff2") format("woff2"); }
@font-face { font-family: "IBM Plex Mono"; font-style: normal; font-weight: 600; font-display: swap;
             src: url("/fonts/ibm-plex-mono-latin-600-normal.woff2") format("woff2"); }

/* Contrast, WCAG 2.x relative luminance, measured 2026-10-16. AA is 4.5 for body text.
   muted   #5b6068 on surface #f2f3f5  5.70 · on surface-2 #fff  6.33 · on page #dcdee1  4.70
           #9aa0a8 on surface #1b1d20  6.41 · on surface-2 #26292d  5.54 · on page #121315  7.05
   faint   #9ba1a9 on #f2f3f5  2.35 · #5b6068 on #1b1d20  2.67 — BOTH FAIL, so --faint is never
           used for text here. The handoff puts it on the expired rail tile and the placeholder;
           both use --muted instead, and the expired tile keeps its dashed border as the signal.
   lead    #3d4249 on #f2f3f5  9.12 · #b9bec5 on #1b1d20  9.04
   accent  #3f6212 on #fff  7.08 · on #f2f3f5  6.37 · #bef264 on #1b1d20  12.93 · on #26292d  11.18
   accent-tint text  #365314 on #ecfccb  8.05 · #d9f99d on #2b3a12  10.48
   danger  #b91c1c on #fff  6.47 · on #fee2e2  5.30 · #fca5a5 on #26292d  7.70 · on #4a1d1d  7.45
   warn    #b45309 on #f2f3f5  4.52 (passes by 0.02 — do not put it on the page bg)
           #f5b14c on #1b1d20  9.07
   warn-tint text  #92400e on #fef3c7  6.37 · #fcd34d on #3a2a0e  9.60
   inverted card, opacity over text, composited and then measured:
           light #fff on #1a1c1f: 100% 17.08 · 85% (#dddddd) 12.57 · 70% (#babbbc) 8.88
           dark  #121315 on #ebedef: 100% 15.84 · 85% (#333436) 10.62 · 70% (#535456) 6.46
           the ✕: #fca5a5 on #1a1c1f 9.00 · #b91c1c on #ebedef 5.51 */
:root {
  color-scheme: light dark;
  --page: #dcdee1;
  --surface: #f2f3f5;
  --surface-2: #ffffff;
  --ink: #1a1c1f;
  --lead: #3d4249;
  --muted: #5b6068;
  --faint: #9ba1a9;
  --line: #e6e8eb;
  --line-soft: #eef0f2;
  --dashed: #c3c6cb;
  --accent: #a3e635;
  --accent-text: #3f6212;
  --accent-dot: #65a30d;
  --accent-tint: #ecfccb;
  --accent-tint-text: #365314;
  --danger: #b91c1c;
  --danger-tint: #fee2e2;
  --warn: #b45309;
  --warn-tint: #fef3c7;
  --warn-tint-text: #92400e;
  --inv-bg: #1a1c1f;
  --inv-text: #ffffff;
  --inv-x: #fca5a5;
  --on-ink: #ffffff;
  --focus: #1a1c1f;
}
@media (prefers-color-scheme: dark) {
  :root {
    --page: #121315;
    --surface: #1b1d20;
    --surface-2: #26292d;
    --ink: #ebedef;
    --lead: #b9bec5;
    --muted: #9aa0a8;
    --faint: #5b6068;
    --line: #33373c;
    --line-soft: #2e3136;
    --dashed: #3a3e44;
    --accent: #bef264;
    --accent-text: #bef264;
    --accent-dot: #bef264;
    --accent-tint: #2b3a12;
    --accent-tint-text: #d9f99d;
    --danger: #fca5a5;
    --danger-tint: #4a1d1d;
    --warn: #f5b14c;
    --warn-tint: #3a2a0e;
    --warn-tint-text: #fcd34d;
    --inv-bg: #ebedef;
    --inv-text: #121315;
    --inv-x: #b91c1c;
    --on-ink: #121315;
    --focus: #bef264;
  }
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
body { margin: 0; background: var(--page); color: var(--ink);
       font: 14px/1.5 "IBM Plex Sans", system-ui, -apple-system, "Helvetica Neue", sans-serif;
       isolation: isolate; }

/* The ground fills the whole window (PORTFOLIO-SITES-FILL-THE-VIEWPORT-1).
   Brave draws a raster tile holding only the ground colour as a flat
   compositor fill, outside the colour-profile transform, and a tile holding
   content colour-managed, so a page shorter than the window can show a band a
   few levels off from a tile boundary down. This fixed backdrop is one solid
   layer over the viewport, so every tile reads alike; `isolation: isolate`
   keeps it above any ground an element paints for itself. Ported from
   circle-connect's base.css with that addition, measured on readlater. No
   headless engine reproduces the band, so no test here can see it. */
body::before { content: ""; position: fixed; inset: 0; z-index: -1; background: var(--page); }
a { color: var(--accent-text); }
h1, h2, h3, h4, p { margin: 0; }
code, pre, .mono, kbd { font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace; }
/* A captured value is a stranger's unbroken string — a token, a hash, a base64 blob — and gives
   break-word no boundary to use. Found on a real handset as a capture URL pushing the page
   sideways; a desktop browser at any width shows nothing wrong. */
code { overflow-wrap: anywhere; word-break: break-all; }
pre { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; word-break: break-all; }
:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--focus); border-radius: 6px; }
[hidden] { display: none !important; }
.visually-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
                   clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.muted { color: var(--muted); }
.mono { font-family: "IBM Plex Mono", ui-monospace, monospace; }

/* --- the frame: a 56px topbar and 12px of page around the cards ---------------------------- */
.app { min-height: 100vh; min-height: 100dvh; display: flex; flex-direction: column; padding: 0 12px 12px; }
.topbar { height: 56px; flex-shrink: 0; display: flex; align-items: center; justify-content: space-between;
          gap: 12px; padding: 0 8px; }
.brand { display: inline-flex; align-items: center; gap: 10px; white-space: nowrap; color: var(--ink);
         text-decoration: none; font-weight: 600; }
.logo { width: 22px; height: 22px; border-radius: 7px; background: var(--ink); display: inline-flex;
        align-items: center; justify-content: center; flex-shrink: 0; }
.logo::after { content: ""; width: 8px; height: 8px; border-radius: 2px; background: var(--accent); }
.topnav { display: flex; gap: 18px; align-items: center; font-size: 13px; color: var(--muted); white-space: nowrap; }
.topnav a, .topnav .link { color: var(--muted); text-decoration: none; }
.topnav a:hover, .topnav .link:hover { color: var(--ink); }
.topnav form { margin: 0; display: inline; }
.avatar { width: 28px; height: 28px; border-radius: 50%; background: var(--ink); color: var(--on-ink);
          display: inline-flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 600; }
button.link { background: none; border: 0; padding: 0; font: inherit; cursor: pointer; }

.card { background: var(--surface); border-radius: 12px; }

/* --- controls ---------------------------------------------------------------------------------- */
label.field { display: flex; flex-direction: column; gap: 6px; font-size: 13px; font-weight: 500; }
input[type=email], input[type=text], input[type=password] {
  font: inherit; font-size: 14px; color: var(--ink); background: var(--surface-2); border: 0;
  border-radius: 8px; padding: 11px 12px; width: 100%; }
input::placeholder { color: var(--muted); opacity: 1; }
input:focus { outline: none; box-shadow: 0 0 0 2px var(--focus); }
.btn { font: inherit; font-size: 14px; font-weight: 600; border: 0; border-radius: 8px; padding: 11px 16px;
       cursor: pointer; text-decoration: none; display: inline-flex; align-items: center; justify-content: center;
       gap: 8px; white-space: nowrap; }
.btn-primary { background: var(--ink); color: var(--on-ink); }
.btn-secondary { background: var(--surface-2); color: var(--ink); }
.btn-block { width: 100%; }
.btn-small { font-size: 13px; padding: 8px 12px; }
.btn-lime { background: var(--accent); color: #1a1c1f; }
.text-btn { background: none; border: 0; padding: 0; font: inherit; cursor: pointer; color: var(--accent-text);
            font-weight: 600; text-decoration: none; }
.danger-text { color: var(--danger); }
.error { color: var(--danger); font-size: 13px; }

/* Plain-text notices on a surface. Warn on a tint, never --warn on the page (4.52 on surface). */
.notice { font-size: 13px; color: var(--muted); background: var(--surface-2); border-radius: 10px; padding: 10px 12px; }
.banner-warn { font-size: 13px; background: var(--warn-tint); color: var(--warn-tint-text); border-radius: 10px;
               padding: 10px 12px; }
.banner-warn strong, .banner-warn code { color: inherit; }
/* Failure simulation. Only existing pairings: the warning tint's own text colour, inherited by the
   Stop button, and the row mark drawn exactly as the session card's dropped line is. */
.fail-sim.banner-warn { display: flex; gap: 10px; align-items: baseline; justify-content: space-between; }
.fail-sim .text-btn { color: inherit; text-decoration: underline; font-size: 13px; }
details.fail-sim { font-size: 13px; }
details.fail-sim summary { cursor: pointer; color: var(--muted); }
details.fail-sim form { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 8px 0 4px; }
details.fail-sim input[type=number] { width: 4.5em; }
.req-line2 .warn-text { color: var(--warn-tint-text); background: var(--warn-tint); border-radius: 6px; padding: 0 6px; }

/* --- the trace component: landing preview and the detail Body tab ------------------------------- */
.trace { border-radius: 10px; background: var(--surface-2); overflow: hidden; }
.trace-head, .trace-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.trace-head > span { padding: 8px 14px; font-size: 12px; font-weight: 600; color: var(--muted); }
.trace-row { border-top: 1px solid var(--line-soft); }
.trace-row > :first-child { padding: 8px 14px; border-right: 1px solid var(--line); font: 13px/1.5 "IBM Plex Mono", ui-monospace, monospace;
                            overflow-wrap: anywhere; word-break: break-all; }
.trace-row > :last-child { padding: 8px 14px; font-size: 13px; }
.trace-key { color: var(--muted); }
.trace-row.signed > :last-child { color: var(--accent-text); }
.trace-row.stop > :first-child { color: var(--danger); }
.trace-row.stop > :last-child, .trace-row.unsigned > :last-child, .trace-row.meta > :last-child,
.trace-row.meta > :first-child { color: var(--muted); }
.trace-verdict { padding: 12px 14px; background: var(--inv-bg); color: var(--inv-text); font-size: 13px; }
.trace-verdict .x { color: var(--inv-x); font-weight: 600; }

/* --- landing and auth --------------------------------------------------------------------------- */
.landing.landing-auth { grid-template-columns: minmax(0, 420px); justify-content: center; align-content: center; }
.landing { flex: 1; display: grid; grid-template-columns: minmax(0, 1fr) minmax(320px, 420px); gap: 12px; }
.hero { padding: 56px 48px; display: flex; flex-direction: column; gap: 28px; }
.pill { display: inline-flex; align-self: flex-start; align-items: center; gap: 8px; font-size: 12px; font-weight: 600;
        padding: 4px 10px; border-radius: 999px; background: var(--surface-2); color: var(--muted); }
.pill::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--accent-dot); }
.hero h1 { font-size: clamp(34px, 4.5vw, 52px); line-height: 1.05; letter-spacing: -.025em; font-weight: 600;
           max-width: 14ch; text-wrap: pretty; }
.lead { font-size: 18px; line-height: 1.5; color: var(--lead); max-width: 34rem; text-wrap: pretty; }
.hero .trace { max-width: 40rem; }
.features { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 24px; max-width: 44rem;
            margin: 8px 0 0; padding: 0; list-style: none; }
.features li { display: flex; flex-direction: column; gap: 4px; }
.features strong { font-weight: 600; }
.features span { font-size: 13px; color: var(--muted); }
.provenance { font-size: 13px; color: var(--muted); max-width: 40rem; }
.provenance a { color: inherit; }
.provenance code { font-family: "IBM Plex Mono", ui-monospace, monospace; font-size: 12px; }
/* The payments set: the kits and the demo app, one line under the cards on the public pages. */
.family { display: flex; flex-wrap: wrap; gap: 6px 18px; padding: 14px 8px 2px; font-size: 13px; color: var(--muted); }
.family a { color: var(--ink); text-decoration: none; }
.family a:hover { text-decoration: underline; }
.auth-card { padding: 40px 32px; display: flex; flex-direction: column; justify-content: center; gap: 18px; }
.auth-card form { display: flex; flex-direction: column; gap: 14px; margin: 0; }
.auth-title { font-size: 22px; font-weight: 600; letter-spacing: -.01em; }
.auth-sub { font-size: 14px; color: var(--muted); }
.auth-card p { font-size: 14px; }
.auth-head { display: flex; flex-direction: column; gap: 4px; }
.info-box { background: var(--surface-2); border-radius: 10px; padding: 12px 14px; display: flex; flex-direction: column;
            gap: 2px; font-size: 13px; }
.info-box strong { font-weight: 600; }
.info-box span { color: var(--muted); }
.icon-tile { width: 36px; height: 36px; border-radius: 10px; background: var(--surface-2); display: inline-flex;
             align-items: center; justify-content: center; }
.icon-tile::after { content: ""; width: 10px; height: 10px; border-radius: 50%; background: var(--accent-dot); }
.icon-tile.warn::after { background: var(--warn); }
.remember { display: flex; align-items: center; gap: 10px; background: var(--surface-2); border-radius: 10px;
            padding: 12px 14px; font-size: 14px; cursor: pointer; }
.remember input { width: 16px; height: 16px; margin: 0; accent-color: var(--ink); }
.back-link { font-size: 13px; font-weight: 500; text-decoration: none; }

/* --- privacy ------------------------------------------------------------------------------------ */
.privacy { flex: 1; display: grid; grid-template-columns: 240px minmax(0, 1fr); gap: 12px; align-items: start; }
.privacy-nav { position: sticky; top: 12px; padding: 16px 12px; display: flex; flex-direction: column; gap: 2px; font-size: 13px; }
.privacy-nav .nav-title { font-weight: 600; padding: 6px 10px; }
.privacy-nav ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.privacy-nav ul a { display: block; padding: 6px 10px; border-radius: 6px; color: var(--muted); text-decoration: none; }
.privacy-nav ul a:hover { background: var(--surface-2); color: var(--ink); }
.privacy-nav .back-link { padding: 6px 10px; margin-top: 8px; }
.privacy-body { padding: 36px 40px 48px; display: flex; flex-direction: column; gap: 28px; }
.privacy-body h1 { font-size: 32px; line-height: 1.15; font-weight: 600; letter-spacing: -.02em; }
.facts { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; margin: 0; }
.fact { background: var(--surface-2); border-radius: 10px; padding: 14px; display: flex; flex-direction: column; gap: 2px; margin: 0; }
.fact dt { font-size: 12px; color: var(--muted); }
.fact dd { margin: 0; font-size: 22px; font-weight: 600; }
.fact dd.accent { color: var(--accent-text); }
.fact dd.note { font-size: 12px; font-weight: 400; color: var(--muted); }
.privacy-body section { display: flex; flex-direction: column; gap: 10px; scroll-margin-top: 12px; }
.privacy-body h2 { font-size: 18px; font-weight: 600; }
.privacy-body section p { font-size: 15px; line-height: 1.6; max-width: 40rem; }
.subproc { background: var(--surface-2); border-radius: 10px; border-collapse: collapse; width: 100%; max-width: 40rem;
           font-size: 14px; overflow: hidden; }
.subproc th, .subproc td { text-align: left; padding: 10px 14px; vertical-align: top; }
.subproc tr + tr th, .subproc tr + tr td { border-top: 1px solid var(--line-soft); }
.subproc th { font-weight: 600; width: 9rem; }

/* --- the workspace: rail · requests · detail ---------------------------------------------------- */
/* flex: none, NEVER flex: 1 (HOOKS-PANES-SCROLL-INDEPENDENTLY-1). .app is a column flexbox with only a
   min-height, so flex: 1's 0% basis resolves as content: the height below was ignored, the workspace
   grew to its tallest column (2602px at 1440x900 with 40 requests) and the page scrolled as one. */
.workspace { flex: none; display: grid; grid-template-columns: 56px 320px minmax(0, 1fr); grid-template-rows: minmax(0, 1fr); gap: 12px;
             height: calc(100vh - 68px); height: calc(100dvh - 68px); min-height: 480px; }
.workspace > .card { min-height: 0; overflow: hidden; display: flex; flex-direction: column; }

.rail { padding: 9px 0; align-items: center; gap: 8px; }
.rail ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; align-items: center; }
.tile { position: relative; width: 38px; height: 38px; border-radius: 10px; display: inline-flex; align-items: center;
        justify-content: center; font: 600 12px "IBM Plex Mono", ui-monospace, monospace; text-decoration: none;
        background: var(--surface-2); color: var(--muted); }
.tile[aria-current] { background: var(--ink); color: var(--on-ink); }
.tile.expired { background: transparent; border: 1px dashed var(--dashed); }
.tile .dot { position: absolute; top: -3px; right: -3px; width: 9px; height: 9px; border-radius: 50%;
             background: var(--accent-dot); box-shadow: 0 0 0 2px var(--surface); }
.tile .dot.dropped { background: var(--warn); }
.tile.add { font: 400 20px "IBM Plex Sans", sans-serif; }
/* Opacity over text, so the figure, measured 2026-10-16 by compositing the tile at .35 onto the
   surface and quantising to whole channels, as a browser paints it: the "+" against its dimmed
   tile is 1.71:1 light, 1.84:1 dark. Below
   AA ON PURPOSE — it is an inactive control (WCAG 1.4.3 exempts those), the title says why, and
   /sessions?new answers with the cap notice in full contrast. */
.tile.add.at-cap { opacity: .35; }
.rail-count { margin-top: auto; font: 10px "IBM Plex Mono", ui-monospace, monospace; color: var(--muted); }

.reqcol-top { padding: 16px; display: flex; flex-direction: column; gap: 10px; flex-shrink: 0; }
.sess-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.rename { flex: 1; min-width: 0; margin: 0; }
.rename input[type=text] { font-size: 15px; font-weight: 600; background: transparent; padding: 2px 6px; margin-left: -6px;
                           border-radius: 6px; text-overflow: ellipsis; }
.rename input[type=text]:hover { background: var(--surface-2); }
.rename button { display: none; }
.expiry { font-size: 12px; color: var(--muted); white-space: nowrap; }
.expiry.expired { color: var(--warn); }
.url-card { background: var(--surface-2); border-radius: 10px; padding: 10px 12px; display: flex; flex-direction: column; gap: 6px; }
.url-card code { font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; word-break: normal;
                 overflow-wrap: normal; display: block; }
.url-meta { display: flex; justify-content: space-between; align-items: center; gap: 8px; font-size: 12px; color: var(--muted); }
.url-meta .text-btn { font-size: 12px; }
.new-session { display: flex; flex-direction: column; gap: 8px; margin: 0; }
.new-session .actions { display: flex; gap: 8px; }
.list-head { display: flex; justify-content: space-between; align-items: center; padding: 4px 16px 8px; flex-shrink: 0; }
.list-head h2 { font-size: 14px; font-weight: 600; }
.live { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted); }
.live::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--accent-dot); }
.live.has-requests::before { animation: pulse 1.6s ease-in-out infinite; }
.live.closed::before { background: var(--muted); }
.reqcol-scroll { flex: 1; min-height: 0; overflow-y: auto; padding: 0 8px 8px; }
.req-list, .sess-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.req-row { display: flex; flex-direction: column; gap: 2px; padding: 10px 12px; border-radius: 10px; color: var(--ink);
           text-decoration: none; min-width: 0; }
.req-row:hover { background: var(--surface-2); }
/* INSET, not an outer ring. The list scrolls inside .reqcol-scroll, whose overflow clips anything
   drawn outside a row's box — so an outer 1.5px ring lost its top edge on the first row, measured on
   hooks.iamlukia.com at 2026-10-16. An inset ring is inside the row and nothing can clip it. */
.req-row[aria-current] { background: var(--surface-2); box-shadow: inset 0 0 0 1.5px var(--ink); }
.req-line1 { font: 13px "IBM Plex Mono", ui-monospace, monospace; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.req-line1 strong { font-weight: 600; }
.req-line2 { font-size: 12px; color: var(--muted); }
li.arrive { animation: arrive .25s ease-out; }
.sess-card { display: flex; flex-direction: column; gap: 4px; padding: 10px 12px; border-radius: 10px; color: var(--ink);
             text-decoration: none; }
.sess-card:hover { background: var(--surface-2); }
.sess-card strong { font-weight: 600; }
.sess-card .warn-text { color: var(--warn-tint-text); background: var(--warn-tint); border-radius: 6px; padding: 0 6px;
                        align-self: flex-start; font-size: 12px; }
.empty-card { border: 1px dashed var(--dashed); border-radius: 10px; padding: 16px; display: flex; flex-direction: column;
              gap: 8px; margin: 0 8px; }
.empty-card strong { font-weight: 600; }
.empty-card p { font-size: 13px; color: var(--muted); }
.empty-card pre { font-size: 12px; background: var(--surface-2); border-radius: 8px; padding: 10px; }
.no-sessions { padding: 24px 16px; display: flex; flex-direction: column; gap: 10px; align-items: flex-start; }
.no-sessions h2 { font-size: 18px; font-weight: 600; }
.no-sessions p { font-size: 14px; color: var(--muted); }
.reqcol-foot { flex-shrink: 0; border-top: 1px solid var(--line-soft); padding: 12px 16px; font-size: 12px;
               display: flex; justify-content: space-between; align-items: center; gap: 8px; }
.reqcol-foot form { margin: 0; display: inline; }
.reqcol-foot > .muted { white-space: nowrap; }
/* "Delete session now" asks once, with no JavaScript: a <details> opens the confirmation and the
   summary closes it again. "Keep" is a second way to close it, wired in workspace.js. */
.confirm-delete summary { list-style: none; cursor: pointer; color: var(--danger); font-weight: 500; }
.confirm-delete summary::-webkit-details-marker { display: none; }
.confirm-delete[open] summary { display: none; }
.confirm-delete .confirm { display: inline-flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.confirm-delete button { background: none; border: 0; padding: 0; font: inherit; cursor: pointer; font-weight: 600; }
.confirm-delete .yes { color: var(--danger); }
.confirm-delete .no { color: var(--muted); }
.chips { display: none; }

.detail { min-width: 0; }
.detail-scroll { flex: 1; min-height: 0; overflow-y: auto; padding: 20px 24px 24px; display: flex; flex-direction: column; gap: 14px; }
.detail-empty { flex: 1; display: flex; align-items: center; justify-content: center; padding: 24px; }
.detail-empty > div { display: flex; flex-direction: column; align-items: center; gap: 8px; text-align: center; max-width: 22rem; }
.detail-empty .icon-tile { width: 44px; height: 44px; }
.detail-empty strong { font-size: 15px; font-weight: 600; }
.detail-empty-copy { display: flex; flex-direction: column; gap: 8px; }
.detail-empty p { font-size: 13px; color: var(--muted); }
.detail-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; flex-wrap: wrap; }
.detail-title { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.detail-title h1 { font: 600 18px "IBM Plex Mono", ui-monospace, monospace; overflow-wrap: anywhere; }
.detail-meta { font-size: 12px; color: var(--muted); }
.verify-form { display: flex; gap: 8px; margin: 0; align-items: center; }
.verify-form input[type=password] { width: 200px; font-family: "IBM Plex Mono", ui-monospace, monospace; font-size: 13px; padding: 8px 10px; }
.verify-form .btn { padding: 8px 14px; font-size: 13px; }
.back-to-list { display: none; font-size: 13px; text-decoration: none; font-weight: 500; }
.tabs { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.tab { font-size: 13px; padding: 6px 10px; border-radius: 6px; color: var(--muted); text-decoration: none; }
.tab[aria-selected=true] { background: var(--surface-2); color: var(--ink); font-weight: 600; }
.tabs .download { margin-left: auto; font-size: 12px; color: var(--muted); text-decoration: none; }
.tabs .download:hover { color: var(--ink); }
.tabs .text-btn { font-size: 12px; margin-left: 10px; }
/* Copy as cURL's own disclosure, in the Raw panel. Existing pairings only: ink on the card, muted notes. */
.curl summary { font-size: 13px; cursor: pointer; }
.curl[open] summary { margin-bottom: 8px; }
.curl pre { white-space: pre-wrap; overflow-wrap: anywhere; }
/* Replay (HOOKS-REPLAY-RESIGNED-1). Existing pairings only: ink and muted on the card, the kv table. */
.replay { display: flex; flex-direction: column; gap: 8px; border-top: 1px solid var(--line); padding-top: 12px; }
.replay h2 { font-size: 14px; margin: 0; }
.replay form { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.replay form label { font-size: 13px; }
.replay input[type=url] { flex: 1 1 260px; min-width: 0; font: 13px "IBM Plex Mono", ui-monospace, monospace; padding: 8px 10px; }
.replay input[type=password] { width: 200px; font: 13px "IBM Plex Mono", ui-monospace, monospace; padding: 8px 10px; }
.replay-history { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.replay-history li { display: flex; flex-direction: column; gap: 2px; font-size: 13px; }
.replay-history code { overflow-wrap: anywhere; }
.replay-history pre { white-space: pre-wrap; overflow-wrap: anywhere; }
.panel { display: flex; flex-direction: column; gap: 12px; }
.kv { background: var(--surface-2); border-radius: 10px; border-collapse: collapse; width: 100%; table-layout: fixed;
      font: 13px "IBM Plex Mono", ui-monospace, monospace; overflow: hidden; }
.kv th, .kv td { text-align: left; vertical-align: top; padding: 8px 14px; overflow-wrap: anywhere; word-break: break-all; font-weight: 400; }
.kv th { color: var(--muted); width: 38%; border-right: 1px solid var(--line); }
.kv tr + tr th, .kv tr + tr td { border-top: 1px solid var(--line-soft); }
.raw { background: var(--surface-2); border-radius: 10px; padding: 14px; font-size: 13px; line-height: 1.6; }
.body-pre { background: var(--surface-2); border-radius: 10px; padding: 14px; font-size: 13px; line-height: 1.6; }
.note { font-size: 12px; color: var(--muted); }

/* Verdicts. The handoff draws three; the server has more (Nothing was signed, a secret that could
   not be used, warnings, the hashed string) and every one of them stays. */
.verdict { border-radius: 10px; padding: 16px 18px; display: flex; flex-direction: column; gap: 6px; }
.verdict h3 { font-size: 15px; font-weight: 600; }
.verdict-mismatch { background: var(--inv-bg); color: var(--inv-text); }
.verdict-mismatch .x { color: var(--inv-x); }
.verdict-mismatch .diag { font-size: 13px; opacity: .85; }
.verdict-mismatch .diag ul { margin: 0; padding-left: 18px; }
.verdict-mismatch .sigs { font: 12px "IBM Plex Mono", ui-monospace, monospace; opacity: .7; overflow-wrap: anywhere; word-break: break-all; }
.verdict-mismatch .verdict-row { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; flex-wrap: wrap; }
.verdict-mismatch .verdict-row > div { display: flex; flex-direction: column; gap: 6px; min-width: 0; flex: 1 1 18rem; }
.verdict-ok { background: var(--accent-tint); color: var(--accent-tint-text); }
.verdict-ok p, .verdict-nothing p, .verdict-uncomputed p { font-size: 13px; }
.verdict-nothing, .verdict-uncomputed { background: var(--warn-tint); color: var(--warn-tint-text); }
.verdict-nothing code { color: inherit; }
.verdict-hint { font-size: 13px; color: var(--muted); display: flex; flex-direction: column; gap: 2px; }
.explain-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.working { background: var(--surface-2); border-radius: 10px; padding: 0; font-size: 13px; }
.working summary { cursor: pointer; padding: 10px 14px; font-weight: 600; font-size: 12px; color: var(--muted); }
.working > div { padding: 0 14px 14px; display: flex; flex-direction: column; gap: 10px; }
.working h4 { font-size: 12px; font-weight: 600; color: var(--muted); }
.working pre { font-size: 12px; background: var(--surface); border-radius: 8px; padding: 10px; }
.working ol { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 2px; }
/* A step's <code> is a word in a sentence (StepText): break-all split `signature` as "si|gnature"
   at 412 px. overflow-wrap: anywhere, from the global rule, still breaks a token too long for a line. */
.working ol code { word-break: normal; }
.working .kv { background: var(--surface); }
.explanation { background: var(--surface-2); border-radius: 10px; padding: 16px; display: flex; flex-direction: column; gap: 8px; }
.explanation .by { font-size: 12px; font-weight: 600; color: var(--muted); }
.explanation h4 { font-size: 15px; font-weight: 600; }
.explanation p { font-size: 14px; line-height: 1.55; }
.explanation .note { font-size: 12px; }
/* htmx injects its own indicator rule as an inline <style>, which this CSP refuses, so the rule
   lives here. "Asking Claude…" shows only while the explain request is in flight. */
.htmx-indicator { display: none; }
.htmx-request .htmx-indicator, .htmx-request.htmx-indicator { display: inline; }
.htmx-request.explain-btn .label, .explain-btn.htmx-request .label { display: none; }

.toast { position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%); background: var(--inv-bg); color: var(--inv-text);
         font-size: 13px; border-radius: 10px; padding: 10px 16px; box-shadow: 0 10px 30px -10px rgba(0, 0, 0, .4); z-index: 10; }

/* --- below 900px: the rail becomes a chip row, list and detail a drill-down -------------------- */
@media (max-width: 899px) {
  .landing, .privacy { grid-template-columns: minmax(0, 1fr); }
  .hero { padding: 32px 22px; gap: 22px; }
  .auth-card { padding: 28px 22px; }
  .privacy-nav { position: static; }
  .privacy-body { padding: 24px 20px 32px; }
  .facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .workspace { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto; height: auto; min-height: 0; }
  .workspace > .card { overflow: visible; }
  .rail { display: none !important; }
  .chips { display: flex; gap: 6px; overflow-x: auto; padding: 12px 16px 0; list-style: none; margin: 0; flex-shrink: 0; }
  .chips a { display: inline-block; white-space: nowrap; font-size: 13px; padding: 6px 10px; border-radius: 999px;
             background: var(--surface-2); color: var(--muted); text-decoration: none; }
  .chips a[aria-current] { background: var(--ink); color: var(--on-ink); font-weight: 600; }
  .reqcol-scroll, .detail-scroll { overflow: visible; }
  .workspace[data-pane=detail] .reqcol { display: none; }
  .workspace[data-pane=list] .detail { display: none; }
  .back-to-list { display: inline-block; }
  .detail-scroll { padding: 16px; }
  .verify-form { width: 100%; }
  .verify-form input[type=password] { flex: 1; width: auto; min-width: 0; }
}
@media (max-width: 560px) {
  .topnav .retention { display: none; }
  .trace-head, .trace-row { grid-template-columns: minmax(0, 1fr); }
  .trace-row > :first-child { border-right: 0; padding-bottom: 2px; }
  .trace-row > :last-child { padding-top: 0; }
  .trace-head > span + span { display: none; }
  .kv th { width: 42%; }
}

@keyframes pulse { 0% { opacity: 1; } 50% { opacity: .3; } 100% { opacity: 1; } }
@keyframes arrive { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .live.has-requests::before, li.arrive { animation: none; }
}
