/* ─────────────────────────────────────────────────────────────────────────
   Account redesign — Home crawl cards + Crawl hub.
   Component styles for the new /account/ home and /account/crawl/ pages.
   Scoped with an `rl-` prefix so nothing here collides with account.css; all
   tokens use var(--x, #fallback) so it renders even where a token is unset.
   Reuses .badge / .btn / .brand-avatar from account.css.
   ───────────────────────────────────────────────────────────────────────── */

:root { --rl-accent:#c8ff00; --rl-amber:var(--amber-bright); --rl-blue:var(--sky-ink); --rl-red:var(--red-ink); }

/* ── Crawls page (/account/audits/) — signal cards over the existing data ── */
.dash--audits .series-grid { display: grid; grid-template-columns: 1fr; gap: 16px; }
.dash--audits .account-subtabs { top: 64px; }
.rl-signal__idwrap { flex: 1; min-width: 0; }
.rl-signal__head .brand-avatar { width: 54px; height: 54px; border-radius: 14px; flex: none; }
.rl-signal__head .brand-avatar__mono { font-size: 1.4rem; }
.rl-signal__head .brand-avatar__img { border-radius: 14px; }
.rl-signal__head .row-menu { margin-left: 4px; }
.rl-signal .attn-vis { justify-content: flex-end; }
.rl-signal .series__nextrun { margin-top: 14px; }
.rl-signal .series-card__cycles, .rl-signal .audit-rows.cyc-timeline { margin-top: 14px; }
.rl-signal .series-team { margin-top: 14px; }
.rl-signal__nowrow { margin-top: 14px; }
.rl-signal__nowrow .rl-now { color: var(--text-secondary); font-size: .9rem; }
.rl-signal__foot .series-access { flex: 1; margin: 0; min-width: 0; }
.rl-signal__foot .series-access--empty { flex: 0 0 auto; }
/* A shared card's footer carries the CTA alone — there is no access manager on a
   crawl you don't own — so it sits at the end rather than floating mid-row where
   space-between would leave it. */
.rl-signal__foot--shared { justify-content: flex-end; }
/* clickable status line (single-cycle) */
.rl-nowrow { display: flex; align-items: center; gap: 10px; text-decoration: none; margin-top: 14px;
  padding: 12px 14px; border: 1px solid var(--border); border-radius: 11px; background: var(--bg-card); transition: .15s; }
.rl-nowrow:hover { border-color: var(--accent); }
.rl-nowrow .rl-now { flex: 1; color: var(--text-secondary); font-size: .9rem; }
.rl-nowrow__go { color: var(--text-muted); transition: .15s; }
.rl-nowrow:hover .rl-nowrow__go { color: var(--accent); transform: translateX(2px); }
/* collapsed "Shared with" (avatars + Manage) */
.series-access--collapsed { margin: 0; }
.series-access__summary { display: inline-flex; align-items: center; gap: 10px; background: none; border: none; cursor: pointer; padding: 4px 0; color: var(--text-muted); font: inherit; }
.series-access__summary:hover .series-access__chev { color: var(--accent); }
.series-access__summary .rl-avstack .rl-av { width: 26px; height: 26px; font-size: .6rem; border-color: var(--bg-card); }
.series-access__chev { font-family: var(--mono, monospace); font-size: .64rem; text-transform: uppercase; letter-spacing: .06em; color: var(--text-faint); }
.series-access__panel { margin-top: 12px; }


/* ── Single-bar account nav (artifact style) ──────────────────────────────
   The account links live INSIDE the top logo bar instead of a separate row
   below it, reclaiming ~48px of vertical space. .site-nav__inner is already a
   flex row with space-between (main.css), so the subnav simply lands on the
   right. Desktop only — on ≤640px account.css hides .account-subnav and
   account-nav.js takes over with the hamburger + bottom tab bar. */
@media (min-width: 641px) {
  .rl-topbar .account-subnav {
    position: static; top: auto; z-index: auto;
    border: none; background: none; margin: 0; padding: 0; flex: 0 0 auto;
    display: flex; align-items: center; gap: 10px;
  }
  .rl-topbar .account-subnav__links { gap: 0.05rem; }
  .rl-topbar .account-subnav__link { font-size: 0.84rem; padding: 0.5rem 0.66rem; }
  /* Sign out moved into the profile dropdown; the inline button stays in the DOM
     (each page wires #signout) but is hidden here. */
  .rl-topbar .account-subnav__signout { display: none; }
}
/* Hidden until auth resolves (the nav lives outside #dash now). */
.rl-topbar .account-subnav[hidden] { display: none; }

/* ── Profile dropdown (desktop) ────────────────────────────────────────────
   Avatar button pinned to the right of the top bar; opens a small menu of the
   secondary destinations + Sign out. Hidden on mobile with the rest of
   .account-subnav (the hamburger covers those links there). */
.rl-profile { position: relative; flex: 0 0 auto; }
.rl-profile__btn {
  display: grid; place-items: center; padding: 0; border: none; background: none; cursor: pointer;
  border-radius: 999px; line-height: 0;
}
.rl-profile__avatar {
  position: relative; width: 34px; height: 34px; border-radius: 999px; display: grid; place-items: center;
  color: var(--text-muted); background: var(--bg-card);
  border: 1px solid var(--border-light); transition: .15s;
}
.rl-profile__avatar svg { width: 19px; height: 19px; }
.rl-profile__avatar--mono {
  color: var(--accent-ink); font-weight: 700; font-size: .95rem; border-color: transparent;
  background: linear-gradient(135deg, #eaffa0, var(--accent, #c8ff00));
}
.rl-profile__btn:hover .rl-profile__avatar { border-color: var(--accent); }
.rl-profile__btn.is-active .rl-profile__avatar,
.rl-profile__btn[aria-expanded="true"] .rl-profile__avatar {
  box-shadow: 0 0 0 2px var(--bg, #09090b), 0 0 0 4px rgba(var(--accent-rgb), .55);
}
.rl-profile__menu {
  position: absolute; right: 0; top: calc(100% + 10px); z-index: 62; min-width: 210px;
  background: var(--bg-secondary); border: 1px solid var(--border-light);
  border-radius: 14px; box-shadow: 0 24px 60px -20px rgba(0,0,0,.9); padding: 7px; display: flex; flex-direction: column;
}
.rl-profile__menu[hidden] { display: none; }
.rl-profile__link, .rl-profile__signout {
  display: block; width: 100%; text-align: left; font: inherit; font-size: .88rem; color: var(--text);
  background: none; border: none; padding: 9px 12px; border-radius: 9px; cursor: pointer; text-decoration: none;
}
.rl-profile__link:hover, .rl-profile__signout:hover { background: var(--bg-card); }
.rl-profile__link[aria-current="page"] { color: var(--accent); }
.rl-profile__signout { color: var(--text-muted); }
.rl-profile__sep { height: 1px; background: var(--border); margin: 6px 4px; }

/* Activity unread badge — reuses .acct-badge (account.css). On desktop it rides
   the avatar (corner dot) and the Activity row inside the dropdown; on mobile it
   rides the hamburger button (the "more" surface Activity now lives behind). */
.rl-profile__btn { position: relative; }
.rl-profile__btn .acct-badge { position: absolute; top: -3px; right: -3px; }
.rl-profile__link.has-badge { display: flex; align-items: center; justify-content: space-between; gap: .5rem; }
.acct-burger { position: relative; }
.acct-burger .acct-badge { position: absolute; top: 3px; right: 1px; }

.rl-mono { font-family: var(--mono, 'JetBrains Mono', ui-monospace, monospace); }
.rl-tnum { font-variant-numeric: tabular-nums; }
.rl-eyebrow { font-family: var(--mono, 'JetBrains Mono', monospace); text-transform:uppercase;
  letter-spacing:.14em; font-size:.66rem; color:var(--text-muted,var(--text-muted)); font-weight:500; }
.rl-idcode { font-family: var(--mono, 'JetBrains Mono', monospace); font-size:.64rem; color:var(--text-muted,var(--text-muted));
  background:var(--bg-card,var(--bg-card)); border:1px solid var(--border,var(--border)); padding:2px 7px; border-radius:6px; letter-spacing:.02em; }
.rl-delta { font-family: var(--mono, 'JetBrains Mono', monospace); font-size:.78rem; font-weight:600; }
.rl-delta.up { color:var(--accent,var(--accent)); } .rl-delta.down { color:var(--rl-red); } .rl-delta.flat { color:var(--text-muted,var(--text-muted)); }

/* ── home header + toolbar ─────────────────────────────────────────────── */
.rl-homehead { display:flex; align-items:flex-end; justify-content:space-between; gap:20px; flex-wrap:wrap; margin:6px 0 24px; }
.rl-homehead h1 { font-size:1.9rem; margin:9px 0 0; letter-spacing:-.02em; }
.rl-homehead p { color:var(--text-muted,var(--text-muted)); margin:8px 0 0; max-width:48ch; font-size:.97rem; }
.rl-homehead__r { display:flex; flex-direction:column; align-items:flex-end; gap:12px; }
/* The crawl count, sitting with the view toggle it describes. /account/audits/
   used to carry this in its own .view-bar strip below a second page header;
   folding it into the shared head is what let that whole strip go. */
.rl-headcount { font-family:var(--mono,monospace); font-size:.68rem; letter-spacing:.08em;
  text-transform:uppercase; color:var(--text-muted,var(--text-muted)); }
.rl-seg { display:inline-flex; background:var(--bg-card,var(--bg-card)); border:1px solid var(--border,var(--border)); border-radius:10px; padding:3px; }
.rl-seg button { font-family:var(--mono,monospace); font-size:.68rem; text-transform:uppercase; letter-spacing:.08em;
  color:var(--text-muted,var(--text-muted)); border:none; background:none; padding:7px 13px; border-radius:7px; transition:.15s; display:flex; align-items:center; gap:6px; cursor:pointer; }
.rl-seg button.on { background:var(--bg-card-hover,var(--tone-900)); color:var(--text,var(--text)); }
.rl-seg svg { width:13px; height:13px; }

.rl-cards { display:grid; gap:22px; }
.rl-list { display:grid; gap:10px; }
/* Grouping. Only the group a customer can act on takes the accent — the others
   are stated in the muted ink, so "needs attention" is the one thing that
   colours on a page of crawls. */
.rl-group { display:grid; gap:12px; }
.rl-groupk { display:flex; align-items:baseline; gap:10px; flex-wrap:wrap; padding:2px 2px 0; }
.rl-groupk b { font-family:var(--mono,monospace); font-size:.62rem; text-transform:uppercase; letter-spacing:.13em;
  color:var(--text-muted,var(--text-muted)); }
.rl-groupk[data-t="you"] b { color:var(--accent,var(--accent)); }
.rl-groupk span { font-size:.82rem; color:var(--text-faint,var(--text-faint)); }
.rl-cards .rl-group__in { display:grid; gap:22px; }
.rl-list .rl-group__in { display:grid; gap:10px; }
.rl-home[data-view="list"] .rl-cards { display:none; }
.rl-home:not([data-view="list"]) .rl-list { display:none; }

/* ── monogram tile (falls back to brand-avatar from account.css when used) ─ */
.rl-mono-tile { width:46px; height:46px; border-radius:12px; flex:none; display:grid; place-items:center;
  font-weight:700; font-size:1.15rem; color:var(--accent-ink); background:linear-gradient(135deg,#eaffa0,var(--accent,#c8ff00)); }
.rl-mono-tile--alt { background:linear-gradient(135deg,var(--border-light),var(--border)); color:var(--text-secondary); }
.rl-mono-tile--lg { width:58px; height:58px; border-radius:15px; font-size:1.5rem; }
.rl-url { font-family:var(--mono,monospace); font-size:.74rem; color:var(--text-faint,var(--text-faint)); }
.rl-chip-mini { display:inline-flex; align-items:center; gap:6px; font-family:var(--mono,monospace); font-size:.62rem;
  color:var(--text-muted,var(--text-muted)); border:1px solid var(--border,var(--border)); border-radius:999px; padding:3px 10px; }

/* ── signal card ───────────────────────────────────────────────────────── */
/* THE CARD IS A SURFACE, NOT A BUTTON. It carried cursor:pointer and a
   3px lift on hover, but nothing happens when its body is clicked: only the
   stage nodes and the buttons inside have handlers. So hovering any part of it
   made the card jump, which competed with the one control that is pressable.
   The lift now lives on the button. */
.rl-signal { position:relative; overflow:hidden; text-align:left; width:100%; display:block;
  background:linear-gradient(158deg,#191a1d 0%,var(--bg-card,var(--bg-card)) 46%,#101012 100%);
  border:1px solid var(--border-light,var(--border-light)); border-radius:22px; padding:24px 26px 20px; transition:.2s; color:inherit; }
.rl-signal::after { content:""; position:absolute; left:0; right:0; top:0; height:1px;
  background:linear-gradient(90deg,transparent,rgba(var(--accent-rgb), .5),transparent); }
.rl-signal__rings { position:absolute; top:-90px; right:-70px; width:340px; height:340px; pointer-events:none; opacity:.5; }
.rl-signal__head { display:flex; align-items:flex-start; gap:14px; position:relative; }
.rl-signal__idname { display:flex; align-items:center; gap:9px; font-size:1.22rem; font-weight:600; }
.rl-signal__meta { margin-left:auto; text-align:right; display:flex; flex-direction:column; gap:6px; align-items:flex-end; }


.rl-signal--sec { background:linear-gradient(158deg,#151517,var(--bg-card,var(--bg-card))); border-color:var(--border,var(--border)); }
.rl-signal--sec .rl-readout__val { font-size:2.5rem; }
.rl-signal--sec .rl-signal__rings { display:none; }

/* ── live "we're working on this" state ────────────────────────────────────
   A crawl mid-build must LOOK alive: soft blue breathing glow on the card, a
   pulsing dot inside its "In progress" badge, and a slow current running along
   the track fill. Blue on purpose — it's the established "working" color on
   the stage nodes (vs amber = your move, lime = done). */
.rl-signal--working { border-color:rgba(var(--sky-rgb), .5); animation:rl-workglow 2.6s ease-in-out infinite; }
.rl-signal--working::after { background:linear-gradient(90deg,transparent,rgba(var(--sky-rgb), .85),transparent); }
@keyframes rl-workglow {
  0%,100% { box-shadow:0 0 0 1px rgba(var(--sky-rgb), .14), 0 0 36px -12px rgba(var(--sky-rgb), .3); }
  50%     { box-shadow:0 0 0 2px rgba(var(--sky-rgb), .5), 0 0 64px -6px rgba(var(--sky-rgb), .65); }
}
.rl-signal--working .badge--progress { display:inline-flex; align-items:center; gap:6px; }
.rl-signal--working .badge--progress::before { content:""; width:8px; height:8px; border-radius:50%; flex:none;
  background:var(--rl-blue,var(--sky-ink)); animation:rl-livedot 1.6s ease-in-out infinite; }
/* The dot pulses AND pings: the scale/opacity beat plus an expanding ring,
   so "in progress" reads from across the room, not on inspection. */
@keyframes rl-livedot {
  0%   { opacity:1; transform:scale(1); box-shadow:0 0 0 0 rgba(var(--sky-rgb), .5); }
  50%  { opacity:.5; transform:scale(.75); box-shadow:0 0 0 6px rgba(var(--sky-rgb), 0); }
  100% { opacity:1; transform:scale(1); box-shadow:0 0 0 0 rgba(var(--sky-rgb), 0); }
}
.rl-signal--working .rl-track__fill { background:linear-gradient(90deg,var(--accent,#c8ff00),var(--sky-ink),var(--accent,#c8ff00));
  background-size:200% 100%; animation:rl-railflow 2.4s linear infinite; }
@keyframes rl-railflow { to { background-position:-200% 0; } }

/* Arrival glow for a just-kicked-off foundation (?started= spotlight): one
   bright lime pulse that hands off to the working glow. */
.rl-signal--hello { animation:rl-hello 2.4s ease-out 1; }
.rl-signal--hello.rl-signal--working { animation:rl-hello 2.4s ease-out 1, rl-workglow 3.2s ease-in-out 2.4s infinite; }
@keyframes rl-hello {
  0%   { box-shadow:0 0 0 3px rgba(var(--accent-rgb), .6), 0 0 70px -8px rgba(var(--accent-rgb), .5); }
  100% { box-shadow:0 0 0 1px rgba(var(--accent-rgb), 0), 0 0 0 0 rgba(var(--accent-rgb), 0); }
}
@media (prefers-reduced-motion: reduce) {
  .rl-signal--working, .rl-signal--hello, .rl-signal--working .rl-track__fill,
  .rl-signal--working .badge--progress::before,
  .rl-quick__st--working .rl-quick__dot,
  .hub-sec.is-working, .hub-sec.is-working .hub-badge--run::before,
  .hub-ask__k i { animation:none; }
}

.rl-readout { display:flex; align-items:center; gap:22px; margin:20px 0 6px; position:relative; }
/* The status column takes the card's width. It was flex:none under a 34ch cap,
   so a one-line status ("Writing the buyer questions you'll be measured on.")
   wrapped its last word onto a second line with half the card empty beside it. */
.rl-readout__num { flex:1 1 auto; min-width:0; }
.rl-readout__val { font-size:3.3rem; font-weight:700; letter-spacing:-.04em; line-height:.92; margin-top:6px;
  display:flex; align-items:baseline; gap:10px; text-shadow:0 0 44px rgba(var(--accent-rgb), .10); }
.rl-readout__val .pct { font-size:1.3rem; color:var(--text-muted,var(--text-muted)); font-weight:600; }
.rl-readout__val.muted { color:var(--text-faint,var(--text-faint)); text-shadow:none; }
/* The readout when there is no figure yet: the crawl's state, in the accent
   system rather than a lone blue. .is-you is accent-lined with a dot, not
   filled: the fill belongs to the card's one button, and a lime badge above a
   lime button read as two things to press. */
.rl-readout__state { display:inline-flex; align-items:center; gap:7px; align-self:center; font-family:var(--mono,monospace); font-size:.66rem;
  text-transform:uppercase; letter-spacing:.1em; padding:.34rem .66rem; border-radius:7px;
  color:var(--text-muted,var(--text-muted)); border:1px solid var(--border-light,var(--border-light)); }
.rl-readout__state.is-you { color:var(--accent,var(--accent)); border-color:rgba(var(--accent-rgb), .55); background:rgba(var(--accent-rgb), .06); font-weight:600; }
.rl-readout__state.is-you::before { content:""; width:7px; height:7px; border-radius:50%; flex:none; background:var(--accent-fill,var(--accent)); }
.rl-readout__cap { font-size:.86rem; color:var(--text-muted,var(--text-muted)); margin-top:10px; max-width:62ch; }
.rl-readout__wave { flex:1 1 180px; min-width:0; }
.rl-readout__wave svg { width:100%; height:auto; display:block; }

/* ── journey track + pin ───────────────────────────────────────────────── */
.rl-track { position:relative; margin:20px 0 4px; }
/* Five stages: Foundations · Questions · Crawl · Visibility · Actions. Node
   centers land at (i+0.5)/5 → 10%…90%, so the rail runs 10% in from each edge
   (trackHTML computes the fill's left/width to match). */
.rl-track__nodes { position:relative; display:grid; grid-template-columns:repeat(5,1fr); padding-top:26px; }
.rl-track__nodes::before { content:""; position:absolute; top:calc(26px + 13px); left:10%; right:10%; height:2px;
  background:var(--border,var(--border)); border-radius:2px; }
.rl-track__fill { position:absolute; top:calc(26px + 13px); height:2px; background:var(--accent,#c8ff00); border-radius:2px;
  box-shadow:0 0 8px rgba(var(--accent-rgb), .5); z-index:1; }
.rl-stop { position:relative; display:flex; flex-direction:column; align-items:center; gap:9px; }
.rl-node { width:26px; height:26px; border-radius:50%; display:grid; place-items:center; position:relative; z-index:2;
  font-family:var(--mono,monospace); font-size:.72rem; font-weight:600; background:var(--bg-card-hover,var(--tone-900));
  border:2px solid var(--border-light,var(--border-light)); color:var(--text-faint,var(--text-faint)); }
.rl-stop.done .rl-node { background:var(--accent-fill); border-color:var(--accent,var(--accent)); color:var(--accent-ink); }
.rl-stop.is-active.you .rl-node { border-color:var(--rl-amber); color:var(--rl-amber); background:rgba(var(--amber-rgb), .08); }
.rl-stop.is-active.working .rl-node { border-color:var(--rl-blue); color:var(--rl-blue); background:rgba(var(--sky-rgb), .08); }
.rl-stop.is-active .rl-node { box-shadow:0 0 0 4px rgba(var(--accent-rgb), .10); }
a.rl-stop { text-decoration:none; color:inherit; }
.rl-stop.is-link { cursor:pointer; }
.rl-stop.is-link:hover .rl-node { border-color:var(--accent,var(--accent)); color:var(--accent,var(--accent)); box-shadow:0 0 0 4px rgba(var(--accent-rgb), .12); }
.rl-stop.done.is-link:hover .rl-node { filter:brightness(1.12); box-shadow:0 0 0 4px rgba(var(--accent-rgb), .18); }
.rl-stop.is-link:hover .rl-stop__lbl { color:var(--text,var(--text)); }
.rl-stop__lbl { font-family:var(--mono,monospace); font-size:.62rem; text-transform:uppercase; letter-spacing:.07em; color:var(--text-faint,var(--text-faint)); }
.rl-stop.done .rl-stop__lbl, .rl-stop.is-active .rl-stop__lbl { color:var(--text-secondary,var(--text-secondary)); }
.rl-pin { position:absolute; top:-2px; left:50%; transform:translateX(-50%); z-index:4; line-height:0; filter:drop-shadow(0 3px 6px rgba(0,0,0,.6)); }
.rl-pin svg { display:block; }
@keyframes rl-pinbob { 0%,100%{transform:translateX(-50%) translateY(0)} 50%{transform:translateX(-50%) translateY(-3px)} }
.rl-pin { animation:rl-pinbob 2.4s ease-in-out infinite; }
@keyframes rl-ringpulse { 0%{box-shadow:0 0 0 0 rgba(var(--accent-rgb), .22)} 70%{box-shadow:0 0 0 9px rgba(var(--accent-rgb), 0)} 100%{box-shadow:0 0 0 0 rgba(var(--accent-rgb), 0)} }
.rl-stop.is-active .rl-node { animation:rl-ringpulse 2.4s ease-out infinite; }
@media (prefers-reduced-motion: reduce) { .rl-pin, .rl-stop.is-active .rl-node { animation:none; } }

/* Peek-ahead: a greyed stage on a card is tappable to reveal what it will hold.
   A dotted underline on the label hints there's more without a hover (works on
   touch too); the node lights lime while its panel is open. */
.rl-signal .rl-stop.locked { cursor:pointer; }
.rl-signal .rl-stop.locked .rl-stop__lbl { text-decoration:underline dotted; text-underline-offset:3px; text-decoration-color:rgba(var(--ink-rgb), .2); }
.rl-signal .rl-stop.locked:hover .rl-node { border-color:var(--text-muted,var(--text-muted)); color:var(--text-secondary,var(--text-secondary)); }
.rl-signal .rl-stop.locked:hover .rl-stop__lbl { color:var(--text-secondary,var(--text-secondary)); }
.rl-stop.is-peek .rl-node { border-color:var(--accent,var(--accent)); color:var(--accent,var(--accent)); box-shadow:0 0 0 4px rgba(var(--accent-rgb), .10); }
.rl-stop.is-peek .rl-stop__lbl { color:var(--text,var(--text)); }

/* The "what's coming" panel — a dashed, softly-lit placeholder (the universal
   "nothing here yet") that says what the stage will fill with. */
.rl-stagedesc {
  margin:14px 0 2px; padding:16px 18px; border-radius:14px;
  border:1px dashed var(--border-light,var(--border-light)); background:rgba(var(--accent-rgb), .03);
  animation:rl-stagedesc-in .18s ease;
}
.rl-stagedesc__hd { display:flex; align-items:center; gap:8px; font-size:1rem; color:var(--text,var(--text)); }
.rl-stagedesc__hd svg { width:16px; height:16px; flex:none; color:var(--text-muted,var(--text-muted)); }
.rl-stagedesc__tag {
  margin-left:6px; font-family:var(--mono,monospace); font-size:.6rem; text-transform:uppercase; letter-spacing:.1em;
  color:var(--text-faint,var(--text-faint)); border:1px solid var(--border,var(--border)); border-radius:999px; padding:2px 8px;
}
.rl-stagedesc__msg { margin:9px 0 0; font-size:.9rem; line-height:1.55; color:var(--text-secondary,var(--text-secondary)); max-width:70ch; }
.rl-stagedesc__x { margin-top:12px; font:inherit; font-size:.8rem; font-weight:600; color:var(--accent,var(--accent)); background:none; border:0; padding:0; cursor:pointer; }
.rl-stagedesc__x:hover { text-decoration:underline; }
@keyframes rl-stagedesc-in { from{opacity:0; transform:translateY(-4px)} to{opacity:1; transform:none} }

/* ── quick access strip: Foundation + Query Explorer on the card face ──── */
/* Sits between the stage track and the footer. Chips with an href are real
   anchors (the card is a <div>, so no nested-link hazard); tone classes reuse
   the track's state vocabulary — done / you / working / locked. */
/* ── the two doors ─────────────────────────────────────────────────────────
   Foundation and Questions, stacked full width under a "Your documents"
   heading. They are the second level on the card, below its one button, so
   they read as rows in a list: quiet outline, the state in large type, the
   verb as plain accent text with an arrow rather than another pill. The door
   whose move it is takes an accent line (not a fill, which is the button's);
   a locked one goes dashed with a padlock and no verb, because there is
   nothing behind it to press yet. */
.rl-quick { display:grid; grid-template-columns:1fr; gap:8px; margin:22px 0 2px; position:relative; }
.rl-quick__head { font-family:var(--mono,monospace); font-size:.62rem; letter-spacing:.11em; text-transform:uppercase;
  color:var(--text-faint,var(--text-faint)); margin-bottom:2px; }
.rl-quick__chip { display:flex; flex-direction:row; align-items:center; gap:16px; min-width:0; min-height:68px;
  text-decoration:none; color:inherit; background:transparent;
  border:1px solid var(--border,var(--border)); border-radius:14px; padding:14px 18px 14px 20px; box-sizing:border-box; }
.rl-quick__txt { flex:1 1 0; min-width:0; display:flex; flex-direction:column; align-items:flex-start; gap:4px; }
a.rl-quick__chip { transition:.15s; }
a.rl-quick__chip:hover { border-color:rgba(var(--accent-rgb), .55); background:rgba(var(--accent-rgb), .05); transform:translateY(-1px); }
a.rl-quick__chip:focus-visible { outline:2px solid var(--accent,#c8ff00); outline-offset:2px; }
.rl-quick__lbl { display:flex; align-items:center; gap:8px;
  font-family:var(--mono,monospace); font-size:.62rem; letter-spacing:.11em; text-transform:uppercase;
  color:var(--text-muted,var(--text-muted)); }
.rl-quick__dot { width:7px; height:7px; border-radius:50%; flex:none;
  background:var(--text-faint,var(--text-faint)); }
.rl-quick__lock { flex:none; color:var(--text-faint,var(--text-faint)); }
.rl-quick__st { font-size:1.06rem; font-weight:600; line-height:1.3; color:var(--text,var(--text)); }
.rl-quick__about { font-size:.8rem; line-height:1.45; color:var(--text-muted,var(--text-muted)); }
.rl-quick__go { flex:none; display:inline-flex; align-items:center; gap:6px; white-space:nowrap;
  font-style:normal; font-size:.9rem; font-weight:600; color:var(--accent,var(--accent)); transition:.15s; }
.rl-quick__go span { display:inline-block; transition:transform .15s; }
a.rl-quick__chip:hover .rl-quick__go span { transform:translateX(3px); }

.rl-quick__chip[data-t="done"] .rl-quick__dot { background:var(--accent,#c8ff00); box-shadow:0 0 6px rgba(var(--accent-rgb), .5); }
.rl-quick__chip[data-t="you"] { border-color:rgba(var(--accent-rgb), .55); background:rgba(var(--accent-rgb), .04); }
.rl-quick__chip[data-t="you"] .rl-quick__lbl { color:var(--accent,var(--accent)); }
.rl-quick__chip[data-t="you"] .rl-quick__dot { background:var(--accent-fill); }
.rl-quick__chip[data-t="working"] .rl-quick__st { color:var(--rl-blue,var(--sky-ink)); }
.rl-quick__chip[data-t="working"] .rl-quick__dot { background:var(--rl-blue,var(--sky-ink)); animation:rl-livedot 1.6s ease-in-out infinite; }
.rl-quick__chip[data-t="locked"] { border-style:dashed; background:none; }
.rl-quick__chip[data-t="locked"] .rl-quick__st { color:var(--text-muted,var(--text-muted)); }
.rl-quick__chip[data-t="locked"] .rl-quick__about { color:var(--text-faint,var(--text-faint)); }
@media (max-width:560px) { .rl-quick__chip { padding:14px 16px; gap:12px; } .rl-quick__go { font-size:.85rem; } }

/* ── the step running now (from /api/crawl-status) ─────────────────────── */
.rl-liveline { display:flex; align-items:center; gap:8px; margin-top:10px; font-size:.82rem; color:var(--rl-blue,var(--sky-ink)); min-width:0; }
.rl-liveline > span:last-child { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.rl-liveline b { font-weight:500; color:var(--text-muted,var(--text-muted)); }
.rl-liveline__spin { width:12px; height:12px; flex:none; border-radius:50%; border:1.5px solid var(--border-light,var(--border-light));
  border-top-color:var(--rl-blue,var(--sky-ink)); animation:rl-spin 1s linear infinite; }
@keyframes rl-spin { to { transform:rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .rl-liveline__spin { animation:none; } }

/* ── the chain: what the crawl does, before the sign-off ───────────────── */
.rl-chain { border-top:1px solid var(--border,var(--border)); padding-top:13px; margin-top:16px; }
.rl-chain__k { font-family:var(--mono,monospace); font-size:.58rem; text-transform:uppercase; letter-spacing:.12em; color:var(--text-faint,var(--text-faint)); }
.rl-chain__row { display:flex; flex-wrap:wrap; align-items:center; gap:7px; margin-top:9px; }
.rl-chain__s { font-size:.78rem; color:var(--text-muted,var(--text-muted)); line-height:1.4; background:rgba(var(--ink-rgb), .03);
  border:1px solid var(--border,var(--border)); border-radius:8px; padding:.36rem .6rem; }
.rl-chain__s b { color:var(--text,var(--text)); font-weight:600; }
.rl-chain__a { color:var(--text-faint,var(--text-faint)); font-size:.72rem; flex:none; }
/* The lede replaces the one-line status on the large card: a full sentence
   with a real measure, and its own emphasis. */
.rl-readout__cap--lede { max-width:56ch; font-size:.9rem; line-height:1.6; }
.rl-readout__cap--lede b { color:var(--text,var(--text)); font-weight:600; }

/* ── DENSITY FOLLOWS THE ACCOUNT ────────────────────────────────────────────
   One or two crawls: the card is already the width of the column and grows
   with the lede and the chain above. Three or more: the compact card — no
   rings, no sparkline, no line under each door, tighter type — and a two-up
   grid once the window is wide enough for each card to keep a real column.
   The home column is 720px (account.css .dash); it widens to 1040px only in
   the many case, so a one-crawl page keeps its measure. */
.rl-home[data-d="many"] .rl-signal { padding:22px 24px 20px; border-radius:18px; }
.rl-home[data-d="many"] .rl-signal__rings, .rl-home[data-d="many"] .rl-readout__wave,
.rl-home[data-d="many"] .rl-quick__about { display:none; }
.rl-home[data-d="many"] .rl-signal__idname { font-size:1.08rem; }
.rl-home[data-d="many"] .rl-mono-tile--lg { width:46px; height:46px; border-radius:12px; font-size:1.2rem; }
.rl-home[data-d="many"] .rl-readout { margin:14px 0 2px; gap:14px; }
.rl-home[data-d="many"] .rl-readout__val { font-size:2.3rem; }
.rl-home[data-d="many"] .rl-readout__cap { font-size:.82rem; margin-top:8px; }
.rl-home[data-d="many"] .rl-quick { margin-top:12px; gap:8px; }
.rl-home[data-d="many"] .rl-quick__chip { padding:12px 16px 12px 18px; min-height:60px; }
.rl-home[data-d="many"] .rl-signal__foot { margin-top:14px; padding-top:12px; }
@media (min-width:900px) {
  .dash--wide { max-width:1040px; }
  .rl-home[data-d="many"] .rl-cards .rl-group__in { grid-template-columns:repeat(2,minmax(0,1fr)); }
  .rl-home[data-d="many"] .rl-cards > .rl-newtile { grid-column:1 / -1; }
}

/* ── card footer: collaborators + cta ──────────────────────────────────── */
.rl-signal__foot { display:flex; align-items:center; justify-content:space-between; gap:16px; flex-wrap:wrap;
  margin-top:18px; padding-top:16px; border-top:1px solid var(--border,var(--border)); }
.rl-collab { display:flex; align-items:center; gap:11px; }
/* Same cluster, now the way into the share sheet. Styled to stay a label, not
   become a second button competing with the CTA beside it. */
.rl-collab--btn { background:none; border:0; padding:0; font:inherit; cursor:pointer; text-align:left; }
.rl-collab--btn:hover .rl-collab__lbl { color:var(--text,var(--text)); }
.rl-collab--btn:focus-visible { outline:2px solid var(--accent,#c8ff00); outline-offset:3px; border-radius:6px; }
.rl-collab__lbl { font-family:var(--mono,monospace); font-size:.6rem; text-transform:uppercase; letter-spacing:.1em; color:var(--text-muted,var(--text-muted)); }
/* Shared-with-you variant: avatar first, then who shared it. Lowercase and
   allowed to wrap, because an owner's email is far longer than the "Shared with"
   label this replaces and must not push the card sideways on a phone. */
.rl-collab--shared { min-width:0; }
.rl-collab--shared .rl-collab__lbl { text-transform:none; letter-spacing:.02em; font-size:.68rem;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0; }
.rl-avstack { display:flex; }
.rl-av { width:29px; height:29px; border-radius:50%; display:grid; place-items:center; font-size:.64rem; font-weight:700;
  color:var(--accent-ink); border:2px solid var(--bg-card,var(--bg-card)); margin-left:-8px; font-family:var(--mono,monospace); }
.rl-av:first-child { margin-left:0; }
.rl-av--more { background:var(--bg-card-hover,var(--tone-900)); color:var(--text-muted,var(--text-muted)); }
.rl-av--you { box-shadow:0 0 0 2px var(--accent,#c8ff00); }
/* A real <a> to the hub's share panel. min-height keeps it a 44px touch target —
   at the old 6px/.78rem padding it measured 34px, under the thumb-size floor.
   The 44px is hit area, not paint: drawn as a dashed pill it was the largest
   control at the top of the card, beside a name, for a ten-second utility.
   It is a quiet mono link now, with the outline appearing on hover, so the
   card's one button stays the one thing that looks pressable. */
.rl-sharebtn { display:inline-flex; align-items:center; gap:6px; font-family:var(--mono,monospace); font-size:.68rem; font-weight:500;
  letter-spacing:.06em; text-transform:uppercase; color:var(--text-muted,var(--text-muted));
  background:none; border:1px solid transparent; border-radius:999px; padding:6px 10px; margin-right:-10px; transition:.15s; cursor:pointer;
  min-height:44px; box-sizing:border-box; text-decoration:none; }
.rl-sharebtn:hover { border-color:var(--border-light,var(--border-light)); color:var(--text,var(--text)); }
.rl-sharebtn:focus-visible { outline:2px solid var(--accent,#c8ff00); outline-offset:2px; }
.rl-sharebtn svg { width:13px; height:13px; }
.rl-ctaline { display:flex; align-items:center; gap:14px; flex-wrap:wrap; }
.rl-now { font-size:.9rem; color:var(--text-secondary,var(--text-secondary)); } .rl-now b { color:var(--text,var(--text)); font-weight:600; }
.rl-cta { display:inline-flex; align-items:center; gap:7px; background:var(--btn-fill, #3f5c0b); color:var(--btn-ink, #f4ffe0); font-weight:600;
  font-size:.9rem; padding:10px 17px; border-radius:11px; border:none; transition:.15s; }
.rl-cta--ghost { background:var(--bg-card,var(--bg-card)); color:var(--text,var(--text)); border:1px solid var(--border-light,var(--border-light)); }
.rl-cta:hover { gap:10px; }

/* ── start-new tile ────────────────────────────────────────────────────── */
.rl-newtile { display:flex; align-items:center; gap:14px; width:100%; text-align:left; cursor:pointer;
  border:1px dashed var(--border-light,var(--border-light)); border-radius:18px; padding:18px 22px; background:none; color:inherit; transition:.15s; }
.rl-newtile:hover { border-color:var(--accent,var(--accent)); background:rgba(var(--accent-rgb), .03); }
.rl-newtile .rl-mono-tile { background:var(--bg-card-hover,var(--tone-900)); color:var(--accent,var(--accent)); border:1px dashed var(--border-light,var(--border-light)); }
.rl-newtile__t { font-size:1.02rem; font-weight:600; }

/* ── list rows ─────────────────────────────────────────────────────────── */
.rl-row { display:grid; grid-template-columns:auto 1.5fr 1.6fr auto auto; align-items:center; gap:16px; width:100%; text-align:left;
  background:var(--bg-card,var(--bg-card)); border:1px solid var(--border,var(--border)); border-radius:14px; padding:15px 18px; transition:.15s; cursor:pointer; color:inherit; }
.rl-row:hover { border-color:var(--border-light,var(--border-light)); background:var(--bg-card-hover,var(--tone-900)); }
.rl-row__id { display:flex; align-items:center; gap:12px; min-width:0; }
.rl-row__name { font-weight:600; font-size:.98rem; display:flex; align-items:center; gap:8px; }
.rl-row .rl-track { margin:0; }
.rl-track--sm .rl-track__nodes { padding-top:20px; }
.rl-track--sm .rl-node { width:20px; height:20px; font-size:.6rem; border-width:2px; }
.rl-track--sm .rl-track__nodes::before, .rl-track--sm .rl-track__fill { top:calc(20px + 10px); }
.rl-track--sm .rl-stop__lbl { display:none; }
.rl-track--sm .rl-pin svg { width:15px; height:15px; }
/* The next move, in the track that used to hold a bare <span></span>. .rl-row
   is a five-column grid whose widest track is 1.6fr, so that empty element was
   the dead middle of every row; the status line the card already carries fills
   it, and the row finally says what to do rather than only where it is. */
.rl-row__next { font-size:.83rem; color:var(--text-muted,var(--text-muted)); min-width:0;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* Whose move it is, in the slot the figure takes once there is one. */
.rl-rowpill { display:inline-block; font-family:var(--mono,monospace); font-size:.58rem; text-transform:uppercase;
  letter-spacing:.09em; padding:.22rem .5rem; border-radius:5px; white-space:nowrap;
  color:var(--text-muted,var(--text-muted)); border:1px solid var(--border-light,var(--border-light)); }
.rl-rowpill.is-you { color:var(--accent-ink); background:var(--accent-fill); border-color:var(--accent-fill); font-weight:600; }
.rl-row__vis { text-align:right; }
.rl-row__vis .n { font-size:1.4rem; font-weight:700; letter-spacing:-.03em; }
.rl-row__vis .l { font-family:var(--mono,monospace); font-size:.55rem; text-transform:uppercase; letter-spacing:.1em; color:var(--text-muted,var(--text-muted)); }
.rl-row__go { width:34px; height:34px; border-radius:9px; border:1px solid var(--border-light,var(--border-light)); background:var(--bg-card,var(--bg-card));
  display:grid; place-items:center; color:var(--text-secondary,var(--text-secondary)); transition:.15s; }
.rl-row:hover .rl-row__go { border-color:var(--accent,var(--accent)); color:var(--accent,var(--accent)); }

/* ── empty state ───────────────────────────────────────────────────────── */
.rl-empty { position:relative; border:1px solid var(--border-light,var(--border-light)); border-radius:24px; overflow:hidden;
  background:linear-gradient(180deg,#17181a,var(--bg-secondary,var(--bg-secondary))); padding:56px 40px; }
.rl-empty__rings { position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); width:640px; height:640px; opacity:.4; pointer-events:none; }
.rl-empty__in { position:relative; max-width:54ch; margin:0 auto; text-align:center; }
.rl-empty h1 { font-size:2.9rem; margin:16px 0 0; letter-spacing:-.04em; }
.rl-empty h1 em { font-style:normal; color:var(--accent,var(--accent)); text-shadow:0 0 34px rgba(var(--accent-rgb), .10); }
.rl-empty p { color:var(--text-muted,var(--text-muted)); margin:16px auto 0; font-size:1.02rem; }
.rl-empty__engines { display:flex; gap:10px; justify-content:center; flex-wrap:wrap; margin-top:22px; }
.rl-chip { font-family:var(--mono,monospace); font-size:.72rem; color:var(--text-secondary,var(--text-secondary)); border:1px solid var(--border-light,var(--border-light));
  border-radius:999px; padding:6px 13px; background:rgba(var(--ink-rgb), .02); }
.rl-empty__cta { display:inline-flex; align-items:center; gap:9px; margin-top:30px; background:var(--accent-fill); color:var(--accent-ink);
  font-weight:600; font-size:1rem; padding:13px 24px; border-radius:12px; border:none; transition:.15s; }
.rl-empty__cta:hover { transform:translateY(-2px); box-shadow:0 16px 34px -16px var(--accent,#c8ff00); }
.rl-empty__sub { margin-top:16px; font-size:.82rem; color:var(--text-faint,var(--text-faint)); }
.rl-empty__sub a { color:var(--text-muted,var(--text-muted)); text-decoration:underline; text-underline-offset:3px; }

/* ── CRAWL HUB ─────────────────────────────────────────────────────────── */
.rl-back { display:inline-flex; align-items:center; gap:7px; font-family:var(--mono,monospace); font-size:.72rem; text-transform:uppercase;
  letter-spacing:.1em; color:var(--text-muted,var(--text-muted)); margin-bottom:18px; background:none; border:none; cursor:pointer; }
.rl-back:hover { color:var(--text,var(--text)); }
/* ── F1 · the crawl hub has NO operator chrome ─────────────────────────────
   There was an `.rl-opbar` here, and four `.hub-op` controls inlined into the
   hub's own sections. Both are gone: the hub renders identically for an
   operator and for the customer. Operator work lives on the ops board, and
   acting as the customer goes through "View as client" on the global operator
   bar (`.rl-opbar-g`, in account.css) — which is injected above every account
   page, so operator context is solved once instead of per page.
   Adding an operator-only rule scoped to this page is the regression. */
/* The hub's own layout lives in the `hub-*` block at the foot of this file —
   see "CRAWL HUB — ported design". What stays here is what the hub shares with
   the rest of the account: the back link, the operator bar, the series strip,
   the embedded viewers, the share-of-voice bars and the actions reader. */

/* Inline-embedded viewer (iframe + its ?embed=1 chrome-hiding). Currently
   unused: the ported hub summarises each deliverable natively and links out to
   its viewer, as the approved design does. Kept because restoring the embed is
   a markup change, not a restyle. */
.rl-embed-wrap { margin-top:16px; border:1px solid var(--border,var(--border)); border-radius:12px; overflow:hidden; background:var(--bg,#09090b); }
.rl-embed-frame { width:100%; height:72vh; border:none; display:block; background:var(--bg,#09090b); }
.rl-embed-loading { padding:44px; text-align:center; color:var(--text-muted,var(--text-muted)); font-family:var(--mono,monospace); font-size:.78rem; letter-spacing:.04em; }
/* earlier cycles directory (series) */
.rl-earlier { margin-top:24px; }
.rl-cyrows { display:grid; gap:8px; }
.rl-cyrow { display:flex; align-items:center; gap:12px; text-decoration:none; color:inherit; background:var(--bg-card,var(--bg-card));
  border:1px solid var(--border,var(--border)); border-radius:11px; padding:12px 15px; transition:.15s; }
.rl-cyrow:hover { border-color:var(--border-light,var(--border-light)); transform:translateY(-1px); }
.rl-cyrow__dot { width:7px; height:7px; border-radius:50%; background:var(--accent,#c8ff00); flex:none; }
.rl-cyrow__main { flex:1; font-size:.9rem; color:var(--text-muted,var(--text-muted)); } .rl-cyrow__main b { color:var(--text,var(--text)); font-weight:600; }
.rl-cyrow__vis { font-family:var(--mono,monospace); color:var(--accent,var(--accent)); font-size:.82rem; }
.rl-cyrow__go { color:var(--text-muted,var(--text-muted)); } .rl-cyrow:hover .rl-cyrow__go { color:var(--accent,var(--accent)); }
.rl-serieswrap { display:flex; align-items:center; flex-wrap:wrap; gap:8px; margin:16px 0 0; padding:14px 0 0; border-top:1px dashed var(--border,var(--border)); }
.rl-series { display:flex; align-items:center; flex-wrap:wrap; }
.rl-series__lbl { font-family:var(--mono,monospace); font-size:.6rem; text-transform:uppercase; letter-spacing:.1em; color:var(--text-muted,var(--text-muted)); margin-right:12px; }
.rl-scy { display:flex; flex-direction:column; align-items:center; gap:6px; padding:0; background:none; border:none; text-decoration:none; cursor:pointer; }
.rl-scy__node { padding:7px 13px; border-radius:10px; border:1px solid var(--border-light,var(--border-light)); background:var(--bg-card,var(--bg-card));
  font-family:var(--mono,monospace); font-size:.72rem; color:var(--text-secondary,var(--text-secondary)); display:flex; align-items:center; gap:8px; transition:.15s; white-space:nowrap; }
.rl-scy:hover .rl-scy__node { border-color:var(--accent,var(--accent)); color:var(--text,var(--text)); transform:translateY(-1px); }
.rl-scy.is-current .rl-scy__node { border-color:var(--accent,var(--accent)); background:rgba(var(--accent-rgb), .12); color:var(--accent,var(--accent)); }
.rl-scy__vis { font-weight:700; }
.rl-scy__lbl { font-family:var(--mono,monospace); font-size:.54rem; text-transform:uppercase; letter-spacing:.08em; color:var(--text-faint,var(--text-faint)); }
.rl-scy.is-current .rl-scy__lbl { color:var(--accent,var(--accent)); }
.rl-sconn { width:24px; height:2px; background:var(--border-light,var(--border-light)); flex:none; margin-top:-15px; }
.rl-scy--new .rl-scy__node { border-style:dashed; color:var(--accent,var(--accent)); }
/* `.rl-opnote` is gone with the rest of the operator chrome (F1) — it was two
   amber "◂ operator: …" hints shipped inside the customer's series strip and
   hidden by CSS, which is still operator copy sitting in her page. */
.rl-plabel { font-family:var(--mono,monospace); font-size:.62rem; text-transform:uppercase; letter-spacing:.1em; color:var(--text-muted,var(--text-muted)); margin-bottom:13px; }
.rl-hbars { display:grid; gap:9px; }
.rl-hbar { display:grid; grid-template-columns:118px 1fr 40px; align-items:center; gap:10px; font-size:.82rem; }
.rl-hbar__name { color:var(--text-secondary,var(--text-secondary)); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.rl-hbar__name.focal { color:var(--accent,var(--accent)); font-weight:600; }
.rl-hbar__track { height:10px; background:var(--border,var(--border)); border-radius:5px; overflow:hidden; }
/* display:block is load-bearing — these are <span>s, and an inline box ignores
   width/height, so every share-of-voice bar rendered as an empty track. */
.rl-hbar__fill { display:block; height:100%; border-radius:5px; background:var(--border-light,var(--border-light)); }
.rl-hbar__fill.focal { background:var(--accent,#c8ff00); }
.rl-hbar__val { font-family:var(--mono,monospace); text-align:right; color:var(--text-muted,var(--text-muted)); font-size:.78rem; }
.rl-hbar__val.focal { color:var(--accent,var(--accent)); }
.rl-trend svg { width:100%; height:auto; display:block; }
.rl-progline { display:flex; align-items:center; gap:12px; margin-bottom:14px; }
.rl-progline__bar { flex:1; height:8px; background:var(--border,var(--border)); border-radius:4px; overflow:hidden; }
.rl-progline__fill { display:block; height:100%; background:var(--accent,#c8ff00); border-radius:4px; }
.rl-progline__lbl { font-family:var(--mono,monospace); font-size:.76rem; color:var(--text-secondary,var(--text-secondary)); white-space:nowrap; }
@media (max-width:720px) {
  .rl-readout { flex-wrap:wrap; gap:12px; } .rl-readout__wave { width:100%; flex:1 0 100%; } .rl-readout__val { font-size:2.7rem; }
  .rl-signal__foot { flex-direction:column; align-items:stretch; }
  .rl-empty h1 { font-size:2.1rem; }
  /* TWO LINES, NOT ONE. The row used to hide its track and its next-move
     line below 720px and keep only name + pill, so a phone list said where
     each crawl was and nothing about what to do. Line one is the name and
     whose move it is; line two is the stage rail and the next move, with the
     arrow spanning both. */
  .rl-row { grid-template-columns:auto minmax(0,1fr) auto auto; grid-template-rows:auto auto; gap:6px 12px; align-items:center; }
  .rl-row__id { grid-column:1 / 3; grid-row:1; }
  .rl-row__vis { grid-column:3; grid-row:1; }
  .rl-row__go { grid-column:4; grid-row:1 / 3; align-self:center; }
  .rl-row .rl-track { grid-column:1 / 2; grid-row:2; width:150px; }
  .rl-row .rl-track--sm .rl-track__nodes { padding-top:14px; }
  .rl-row .rl-track--sm .rl-node { width:16px; height:16px; font-size:.52rem; }
  .rl-row .rl-track--sm .rl-track__nodes::before, .rl-row .rl-track--sm .rl-track__fill { top:calc(14px + 8px); }
  .rl-row .rl-track--sm .rl-pin { display:none; }
  .rl-row__next { display:block; grid-column:2 / 4; grid-row:2; white-space:normal; font-size:.78rem; line-height:1.4; }
  .rl-row .rl-avstack { display:none; }
  .rl-hbar { grid-template-columns:90px 1fr 36px; }
}

/* ── Native Actions reader (crawl hub) ───────────────────────────────────────
   The action plan renders inline from action_items — a working to-do list the
   customer checks off (DB-backed), filters by layer, and copies out. */
.rl-actwrap { display:grid; gap:14px; }
.rl-acthd { display:flex; flex-direction:column; gap:12px; }
.rl-actbar { display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
.rl-actfilters { display:flex; gap:6px; flex-wrap:wrap; }
.rl-actf { font-family:var(--mono,monospace); font-size:.68rem; letter-spacing:.04em; padding:6px 11px; border-radius:8px; cursor:pointer; border:1px solid var(--border-light,var(--border-light)); background:transparent; color:var(--text-muted,var(--text-muted)); }
.rl-actf.on { background:var(--bg-card-hover,var(--tone-900)); color:var(--text,var(--text)); border-color:var(--text-muted,var(--text-muted)); }
.rl-actf:hover { color:var(--text,var(--text)); }
.rl-actcopy { margin-left:auto; display:inline-flex; align-items:center; gap:7px; font-size:.8rem; font-weight:600; padding:8px 14px; border-radius:9px; cursor:pointer; border:1px solid var(--accent,var(--accent)); background:var(--accent-fill); color:var(--accent-ink); }
.rl-actcopy svg { width:14px; height:14px; }
.rl-actlist { display:flex; flex-direction:column; gap:9px; }
.rl-act { display:grid; grid-template-columns:auto 24px 1fr auto; gap:13px; align-items:start; background:var(--bg-card,var(--bg-card)); border:1px solid var(--border,var(--border)); border-radius:12px; padding:14px 16px; }
.rl-act:hover { border-color:var(--border-light,var(--border-light)); }
.rl-act.is-done { opacity:.55; }
.rl-act.is-done .rl-act__title { text-decoration:line-through; }
.rl-act__chk { width:20px; height:20px; border-radius:6px; border:1.5px solid var(--border-light,var(--border-light)); background:transparent; cursor:pointer; margin-top:1px; display:grid; place-items:center; flex:none; padding:0; }
.rl-act__chk.on { background:var(--accent,#c8ff00); border-color:var(--accent,var(--accent)); }
.rl-act__chk svg { width:12px; height:12px; opacity:0; }
.rl-act__chk.on svg { opacity:1; }
.rl-act__rank { font-family:var(--mono,monospace); font-size:.95rem; color:var(--text-faint,var(--text-faint)); text-align:center; margin-top:1px; }
.rl-act__title { font-weight:600; font-size:.93rem; letter-spacing:-.01em; }
.rl-act__why { font-size:.82rem; color:var(--text-muted,var(--text-muted)); margin-top:4px; line-height:1.5; }
.rl-act__tags { display:flex; gap:7px; margin-top:9px; flex-wrap:wrap; }
.rl-act__tag { font-family:var(--mono,monospace); font-size:.6rem; letter-spacing:.04em; padding:3px 8px; border-radius:6px; border:1px solid var(--border-light,var(--border-light)); color:var(--text-muted,var(--text-muted)); text-transform:uppercase; }
.rl-act__tag--l { color:var(--accent,var(--accent)); border-color:rgba(var(--accent-rgb), .3); background:rgba(var(--accent-rgb), .1); }
.rl-act__open { color:var(--text-muted,var(--text-muted)); text-decoration:none; font-size:1.15rem; padding:2px 6px; align-self:center; }
.rl-act__open:hover { color:var(--accent,var(--accent)); }
.rl-toast { position:fixed; bottom:24px; left:50%; transform:translateX(-50%) translateY(16px); background:var(--accent-fill); color:var(--accent-ink); font-weight:600; font-size:.85rem; padding:11px 20px; border-radius:11px; opacity:0; transition:.22s; pointer-events:none; z-index:120; box-shadow:0 10px 40px -10px rgba(var(--accent-rgb), .55); }
.rl-toast.show { opacity:1; transform:translateX(-50%) translateY(0); }

/* ═══════════════════════════════════════════════════════════════════════════
   CRAWL HUB — ported design
   ──────────────────────────────────────────────────────────────────────────
   The approved crawl-hub mockup, ported verbatim. Everything here is prefixed
   `hub-` and scoped under `.rl-hub`: the mockup's own class names (.hero,
   .panel, .stat, .badge, .chip, .track, .find, .open, .btn, .team …) collide
   head-on with main.css and account.css, and a bare `.stat` rule would repaint
   half the account. The prefix is the only change made to the design.

   Design tokens map onto the live system's variables, with the mockup's
   literals as fallbacks, so the hub inherits any future palette move.
   ══════════════════════════════════════════════════════════════════════════ */
.rl-hub {
  --hub-card:   var(--bg-card);
  --hub-card-2: var(--bg-card-hover, var(--tone-900));
  --hub-card-3: var(--tone-850);
  --hub-bd:     var(--border);
  --hub-bd-lt:  var(--border-light);
  --hub-text:   var(--text);
  --hub-text-2: var(--text-secondary);
  --hub-muted:  var(--text-muted);
  --hub-faint:  var(--text-faint);
  --hub-accent: var(--accent, #c8ff00);
  --hub-accent-dim: rgba(var(--accent-rgb), .14);

  /* Severity ramp — deliberately not the accent, so "needs attention" never
     renders in the same colour as "done". */
  --hub-sev-high:var(--high-ink); --hub-sev-med:var(--amber-ink); --hub-sev-low:var(--text-faint);
  --hub-info:var(--info); --hub-info-dim:rgba(125,211,252,.12);

  /* Track geometry as tokens so the rail's vertical position always follows
     the dot size — changing one on mobile can't desync the other. */
  --hub-dot:28px; --hub-track-pt:1.85rem;

  --hub-r:14px; --hub-r-sm:9px;
}
.rl-hub .hub-num { font-variant-numeric: tabular-nums; }

@media (prefers-reduced-motion: reduce) {
  .rl-hub *, .rl-hub *::before, .rl-hub *::after { animation:none !important; transition:none !important; }
}

/* ── the ask ─────────────────────────────────────────────────────────────
   ONE ASK PER SCREEN. The needs band, the hero's live readout, the stage
   explainer under the track and the first-wait strip each said where the
   crawl was, in their own words, on the same screen. This is the one place:
   an eyebrow, a headline, a sentence, one verb — and the commerce or the
   processing panel in the right-hand column. Tones: act (the customer's
   move, and the page's one lime fill), wait (ours), clear, bad (money). */
.hub-ask { margin-top:1rem; border-radius:var(--hub-r); border:1px solid var(--hub-bd); background:var(--hub-card); padding:1.4rem 1.5rem;
  display:grid; gap:1.1rem 1.6rem; grid-template-columns:minmax(0,1fr) minmax(0,300px); align-items:center;
  container-type:inline-size; }
.hub-ask[data-side="wide"] { grid-template-columns:minmax(0,1fr) minmax(0,392px); align-items:start; }
.hub-ask[data-tone="act"] { border-color:rgba(var(--accent-rgb), .4); background:linear-gradient(100deg, rgba(var(--accent-rgb), .09), transparent 46%), var(--hub-card); }
.hub-ask[data-tone="wait"] { border-color:rgba(var(--sky-rgb), .35); background:linear-gradient(100deg, var(--hub-info-dim), transparent 62%), var(--hub-card); }
.hub-ask[data-tone="clear"] { border-style:dashed; }
.hub-ask[data-tone="bad"] { border-color:rgba(var(--red-rgb), .45); background:linear-gradient(100deg, rgba(var(--red-rgb), .09), transparent 62%), var(--hub-card); }
.hub-ask__l { min-width:0; }
.hub-ask__k { font-family:var(--mono,monospace); font-size:.6rem; text-transform:uppercase; letter-spacing:.14em; color:var(--hub-faint);
  display:inline-flex; align-items:center; gap:8px; }
.hub-ask[data-tone="act"] .hub-ask__k { color:var(--hub-accent); }
.hub-ask[data-tone="wait"] .hub-ask__k { color:var(--hub-info); }
.hub-ask[data-tone="bad"] .hub-ask__k { color:var(--red-ink); }
.hub-ask__k i { width:7px; height:7px; border-radius:50%; background:currentColor; display:block; flex:none; }
.hub-ask[data-tone="wait"] .hub-ask__k i { animation:rl-livedot 1.6s ease-in-out infinite; }
.rl-hub .hub-ask h2 { margin:.36rem 0 0; font-size:1.3rem; font-weight:600; letter-spacing:-.022em; line-height:1.24; text-wrap:balance; }
.rl-hub .hub-ask p { margin:.5rem 0 0; font-size:.88rem; color:var(--hub-muted); line-height:1.6; max-width:54ch; }
.hub-ask p b { color:var(--hub-text); font-weight:600; }
.rl-hub .hub-ask__foot { margin-top:.7rem; font-size:.79rem; color:var(--hub-faint); }
.hub-inlink { color:var(--hub-accent); font-weight:600; text-decoration:underline; text-underline-offset:2px; }
.hub-ask__r { display:flex; flex-direction:column; gap:.6rem; min-width:0; }
.hub-ask__r .paygate { margin:0; }
.hub-ask__r .hub-fig { margin-bottom:.2rem; }

.hub-fig__k { font-family:var(--mono,monospace); font-size:.58rem; text-transform:uppercase; letter-spacing:.13em; color:var(--hub-faint); }
.hub-fig__v { font-size:2.85rem; font-weight:600; letter-spacing:-.05em; line-height:1.05; margin-top:.1rem; }
.hub-fig__v span { font-size:1.35rem; color:var(--hub-muted); }
.hub-fig__d { font-family:var(--mono,monospace); font-size:.73rem; font-weight:600; color:var(--hub-accent); margin-top:.16rem; }

/* the three steps between here and the report */
.hub-sublab { display:block; font-family:var(--mono,monospace); font-size:.56rem; text-transform:uppercase; letter-spacing:.12em; color:var(--hub-faint); margin-top:16px; }
.rl-hub .hub-steps { margin:15px 0 0; padding:0; list-style:none; }
.hub-steps li { display:grid; grid-template-columns:26px minmax(0,1fr); gap:12px; padding:0 0 12px; position:relative; }
.hub-steps li:last-child { padding-bottom:0; }
.hub-steps li::before { content:""; position:absolute; left:12px; top:28px; bottom:1px; width:1.5px; background:var(--hub-bd); }
.hub-steps li:last-child::before { display:none; }
.hub-steps__n { width:26px; height:26px; border-radius:50%; display:grid; place-items:center; font-family:var(--mono,monospace);
  font-size:.67rem; font-weight:600; background:var(--hub-card); border:1.5px solid rgba(var(--accent-rgb), .3); color:var(--hub-accent); z-index:1; }
.hub-steps b { display:block; font-size:.85rem; font-weight:600; color:var(--hub-text); }
.rl-hub .hub-steps p { margin:.2rem 0 0; font-size:.79rem; color:var(--hub-muted); line-height:1.52; max-width:48ch; }
.hub-askcta { margin-top:15px; display:flex; flex-direction:column; align-items:flex-start; }
.rl-hub .hub-ctasub { margin:.55rem 0 0; font-size:.78rem; color:var(--hub-muted); }

/* the one button */
.hub-cta { display:inline-flex; align-items:center; justify-content:center; gap:10px; background:var(--btn-fill, #3f5c0b); color:var(--btn-ink, #f4ffe0);
  font-size:.9rem; font-weight:700; border:0; border-radius:10px; padding:.8rem 1.25rem; min-height:48px; text-decoration:none;
  transition:transform .14s, box-shadow .14s; }
.hub-cta:hover { transform:translateY(-1px); box-shadow:0 12px 26px -14px var(--hub-accent); }
.hub-cta__p { font-family:var(--mono,monospace); font-weight:600; }
.hub-cta__p::before { content:"·"; margin-right:10px; opacity:.45; }
.hub-cta--quiet { background:none; color:var(--hub-text); border:1px solid var(--hub-bd-lt); font-weight:600; }
.hub-cta--quiet:hover { border-color:var(--hub-accent); color:var(--hub-accent); box-shadow:none; }
.hub-cta--bad { background:var(--red-ink); color:#fff; }
.hub-ask__r .hub-cta { align-self:stretch; }
.hub-alt { font-size:.79rem; font-weight:500; color:var(--hub-muted); text-align:center; text-decoration:none; padding:.2rem; }
.hub-alt:hover { color:var(--hub-accent); }

/* ── the standing offer ────────────────────────────────────────────────────
   Below everything, after the documents — findable by anyone who wants it,
   invisible to anyone who doesn't. Card ground and a plain border, not the
   accent wash: this is a shelf, not a pitch. */
.hub-standing { margin-top:1.4rem; border:1px solid var(--hub-bd); border-radius:var(--hub-r); background:var(--hub-card); padding:1.3rem 1.4rem; }
.hub-standing__k { font-family:var(--mono,monospace); font-size:.56rem; text-transform:uppercase; letter-spacing:.13em; color:var(--hub-faint); display:block; }
.rl-hub .hub-standing h3 { margin:.42rem 0 0; font-size:1.06rem; font-weight:600; letter-spacing:-.018em; }
.rl-hub .hub-standing > p { margin:.45rem 0 0; font-size:.83rem; color:var(--hub-muted); line-height:1.6; max-width:64ch; }
.hub-standing > p b { color:var(--hub-text); font-weight:600; }
.hub-cmp { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:9px; margin-top:14px; }
.hub-cmp__c { border:1px solid var(--hub-bd); border-radius:8px; padding:.65rem .75rem; background:var(--hub-card-2); }
.hub-cmp__c--on { border-color:rgba(var(--accent-rgb), .3); background:rgba(var(--accent-rgb), .05); }
.hub-cmp__k { font-family:var(--mono,monospace); font-size:.52rem; text-transform:uppercase; letter-spacing:.11em; color:var(--hub-faint); display:block; margin-bottom:.5rem; }
.hub-cmp__c--on .hub-cmp__k { color:var(--hub-accent); }
.hub-cmp ul { margin:0; padding:0; list-style:none; }
.hub-cmp li { font-size:.76rem; color:var(--hub-muted); line-height:1.45; display:flex; gap:7px; }
.hub-cmp li + li { margin-top:.35rem; }
.hub-cmp li i { font-style:normal; flex:none; color:var(--hub-accent); font-size:.7rem; line-height:1.6; }
.hub-cmp__c:not(.hub-cmp__c--on) li i { color:var(--hub-faint); }
.hub-standing__go { display:flex; align-items:center; gap:11px; flex-wrap:wrap; margin-top:13px; }
.hub-open--offer { display:inline-flex; align-items:center; gap:8px; min-height:40px; font:inherit; font-size:.83rem; font-weight:600;
  background:var(--hub-card); cursor:pointer; }
.hub-open--offer:hover { background:var(--hub-accent-dim); }
.hub-open--offer[disabled] { opacity:.6; cursor:wait; }
.hub-ctanote { font-size:.73rem; color:var(--hub-faint); flex:1 1 240px; }
.rl-hub .hub-standing__err { margin:.6rem 0 0; }
@media (max-width:620px) { .hub-cmp { grid-template-columns:minmax(0,1fr); } }

/* ── the processing panel ──────────────────────────────────────────────────
   Itemised, in the pipeline's own phrases: done / now / next, each with the
   time the pipeline reported, and per-engine bars for the crawl. */
.hub-proc { border:1px solid rgba(var(--sky-rgb), .3); border-radius:var(--hub-r-sm); background:var(--hub-card-2); padding:15px 16px;
  display:flex; flex-direction:column; gap:13px; }
.hub-proc__k { display:flex; align-items:center; gap:8px; font-family:var(--mono,monospace); font-size:.58rem; text-transform:uppercase;
  letter-spacing:.13em; color:var(--hub-info); }
.hub-proc__k b { margin-left:auto; font-weight:400; color:var(--hub-faint); letter-spacing:.06em; text-transform:none; }
.hub-proc__k i { width:7px; height:7px; border-radius:50%; background:var(--hub-info); flex:none; animation:rl-livedot 1.7s ease-in-out infinite; }
.hub-proc__now { font-size:.98rem; font-weight:600; letter-spacing:-.015em; line-height:1.3; color:var(--hub-text); }
.hub-pbar { height:6px; border-radius:3px; background:var(--hub-card-3); overflow:hidden; }
.hub-pbar i { display:block; height:100%; border-radius:3px; background:var(--hub-info); transition:width .6s cubic-bezier(.4,0,.2,1); }
.hub-pbar--sweep { margin-top:10px; }
.hub-pbar--sweep i { width:40%; animation:hub-sweep-x 2.4s ease-in-out infinite; }
@keyframes hub-sweep-x { 0% { transform:translateX(-100%); } 100% { transform:translateX(280%); } }
.hub-pcount { display:flex; justify-content:space-between; gap:10px; font-family:var(--mono,monospace); font-size:.66rem; color:var(--hub-muted); margin:6px 0; }
.hub-psteps { display:flex; flex-direction:column; border-top:1px solid var(--hub-bd); padding-top:12px; }
.hub-pstep { display:grid; grid-template-columns:16px minmax(0,1fr) auto; align-items:center; gap:10px; padding:.3rem 0; font-size:.79rem; color:var(--hub-faint); }
.hub-pstep[data-t="done"] { color:var(--hub-muted); }
.hub-pstep[data-t="now"] { color:var(--hub-text); font-weight:600; }
.hub-pstep[data-t="bad"] { color:var(--hub-sev-high); }
.hub-pstep__i { display:grid; place-items:center; font-size:.7rem; }
.hub-pstep[data-t="done"] .hub-pstep__i { color:var(--hub-accent); }
.hub-pstep__n { font-family:var(--mono,monospace); font-size:.64rem; color:var(--hub-faint); font-weight:400; }
.hub-pdot { width:7px; height:7px; border-radius:50%; border:1.5px solid var(--hub-bd-lt); }
.hub-peng { display:flex; flex-direction:column; gap:8px; }
.hub-pengrow { display:grid; grid-template-columns:80px minmax(0,1fr) 66px; align-items:center; gap:10px; font-size:.76rem; }
.hub-pengrow__l { display:flex; align-items:center; gap:7px; color:var(--hub-muted); }
.hub-pengrow__l i { width:8px; height:8px; border-radius:2px; flex:none; background:var(--hub-info); }
.hub-pengrow[data-engine="chatgpt"] i, .hub-pengrow[data-engine="chatgpt"] .hub-pbar i { background:#12a674; }
.hub-pengrow[data-engine="gemini"] i, .hub-pengrow[data-engine="gemini"] .hub-pbar i { background:#5b82f0; }
.hub-pengrow[data-engine="claude"] i, .hub-pengrow[data-engine="claude"] .hub-pbar i { background:#d1742b; }
.hub-pengrow[data-engine="perplexity"] i, .hub-pengrow[data-engine="perplexity"] .hub-pbar i { background:#109fb8; }
.hub-pengrow__v { font-family:var(--mono,monospace); font-size:.68rem; text-align:right; color:var(--hub-muted); }
.hub-pengrow[data-done="1"] .hub-pengrow__v { color:var(--hub-accent); }
.rl-hub .hub-proc__eta { font-size:.78rem; color:var(--hub-muted); line-height:1.55; margin:0; }
.hub-proc__eta b { color:var(--hub-text); font-weight:600; }

/* the picker (pay-crawl.js variant "pick") inside the ask */
.paygate--pick { display:flex; flex-direction:column; gap:12px; }
.paygate__k { font-family:var(--mono,monospace); font-size:.58rem; text-transform:uppercase; letter-spacing:.13em; color:var(--hub-faint); }
.paygate--pick .paygate__plans, .paygate--pick .paygate__tiers { margin:0; }
.paygate__total { display:flex; align-items:baseline; justify-content:space-between; gap:10px; padding-top:10px; border-top:1px solid var(--hub-bd); }
.paygate__total span { font-size:.78rem; color:var(--hub-muted); }
.paygate__total b { font-family:var(--mono,monospace); font-size:1.18rem; font-weight:600; letter-spacing:-.02em; color:var(--hub-text); }
.paygate__foot { font-size:.73rem; color:var(--hub-muted); line-height:1.55; margin:0; }
.paygate__foot b { color:var(--hub-text); font-weight:600; }
.paygate__credit { border:1px solid rgba(var(--accent-rgb), .3); background:var(--hub-accent-dim); border-radius:8px; padding:.7rem .8rem; font-size:.78rem; color:var(--hub-muted); line-height:1.5; }
.paygate__credit b { color:var(--hub-text); }

@container (max-width:720px) {
  .hub-ask, .hub-ask[data-side="wide"] { grid-template-columns:minmax(0,1fr); }
}
@media (max-width:760px) {
  .hub-ask, .hub-ask[data-side="wide"] { grid-template-columns:minmax(0,1fr); padding:1.1rem 1.1rem; }
  .rl-hub .hub-ask h2 { font-size:1.1rem; }
  .hub-fig__v { font-size:2.2rem; }
  .hub-askcta { align-self:stretch; }
  .hub-askcta .hub-cta { align-self:stretch; }
}

/* ── dateline ──────────────────────────────────────────────────────────── */
.hub-dates { display:flex; flex-wrap:wrap; gap:.35rem .5rem; align-items:center;
  font-family:var(--mono,monospace); font-size:.68rem; color:var(--hub-faint); padding:.85rem .2rem 0; }
.hub-dates__i { display:flex; align-items:center; gap:.35rem; white-space:nowrap; }
.hub-dates__d { width:5px; height:5px; border-radius:50%; background:var(--hub-accent); flex:none; }
.hub-dates__i--now .hub-dates__d { background:var(--hub-info); }
.hub-dates__i--wait .hub-dates__d { background:var(--hub-bd-lt); }
.hub-dates__i b { color:var(--hub-text-2); font-weight:500; }
.hub-dates__i--wait b { color:var(--hub-faint); }
.hub-dates__arw { color:var(--hub-bd-lt); }

/* ── sticky mini-bar ─────────────────────────────────────────────────────
   Appears once the hero scrolls away. The page is long, so the track — already
   the page's navigation metaphor — comes with you. Its dots reflect the
   section you're scrolled into (scroll-spy), a different job from the hero
   explainer: that one shows what you deliberately picked. */
/* Parks directly under whatever chrome is pinned above it. That is NOT a
   constant: .site-nav is 64px and sticky at z-index 100, but for an operator
   the .rl-opbar-g strip sits above it and initOperatorBar() pushes the nav
   down by its height. Hardcoding 64px put the mini-bar *behind* the nav for
   every operator — present in the DOM, invisible on screen. The hub measures
   the nav's bottom edge into --hub-sticky-top instead. */
/* FIXED, not sticky. As a sticky element it stayed in flow and reserved its own
   39px at the top of the page even while translated out of sight — so an
   invisible bar was pushing the crawl itself down on every load. It only ever
   appears over the content on scroll, which is what fixed is for. left/right
   pin it across the viewport, so the inner row re-centres to the hub's width. */
.hub-mini { position:fixed; top:var(--hub-sticky-top, 64px); left:0; right:0; z-index:39;
  background:rgba(var(--bg-rgb), .92); backdrop-filter:blur(10px);
  border-bottom:1px solid var(--hub-bd); transform:translateY(-100%); opacity:0; pointer-events:none;
  transition:transform .22s ease, opacity .22s ease; }
/* Reading progress along the bar's foot — how far through the deliverables you
   are, on a page whose length depends on how much has been delivered. */
.hub-mini__prog { position:absolute; left:0; bottom:-1px; height:2px; width:0;
  background:var(--hub-accent); transition:width .1s linear; }
.hub-mini.is-on { transform:none; opacity:1; pointer-events:auto; }
/* Re-centres to the hub's column now that .hub-mini spans the viewport (fixed).
   The horizontal padding lives here, not on an earlier rule — this one is later
   in the file and its `padding` shorthand would reset it. */
.hub-mini__in { display:flex; align-items:center; gap:1rem;
  max-width:920px; margin:0 auto; padding:.6rem 1.5rem; }
@media (max-width:640px) { .hub-mini__in { padding:.6rem 1.1rem; } }
.hub-mini__id { display:flex; align-items:center; gap:.5rem; font-size:.85rem; font-weight:600; white-space:nowrap; }
.hub-mini__tile { width:22px; height:22px; border-radius:5px; background:var(--hub-accent); color:var(--accent-ink);
  display:grid; place-items:center; font-size:.7rem; font-weight:700; }
.hub-mini__cyc { font-family:var(--mono,monospace); font-size:.62rem; color:var(--hub-faint); font-weight:400; }
.hub-mini__nav { display:flex; align-items:center; gap:.15rem; margin:0 auto; }
.hub-mdot { background:none; border:0; cursor:pointer; font:inherit; color:var(--hub-faint); font-size:.76rem;
  padding:.28rem .6rem; border-radius:6px; white-space:nowrap; display:flex; align-items:center; gap:.4rem; }
.hub-mdot:hover { color:var(--hub-text); background:var(--hub-card-2); }
.hub-mdot__d { width:7px; height:7px; border-radius:50%; background:var(--hub-bd-lt); flex:none; }
.hub-mdot.done .hub-mdot__d { background:var(--hub-accent); }
.hub-mdot.now .hub-mdot__d { background:var(--hub-info); }
.hub-mdot.you .hub-mdot__d { background:var(--hub-accent); box-shadow:0 0 0 3px var(--hub-accent-dim); }
.hub-mdot.is-view { color:var(--hub-text); background:var(--hub-card-2); }
.hub-mdot.is-view .hub-mdot__d { box-shadow:0 0 0 3px rgba(var(--ink-rgb), .09); }
/* Each stop carries its own headline figure, so the bar is a summary of the
   page and not just a set of labels. */
.hub-mdot__n { font-family:var(--mono,monospace); font-size:.66rem; color:var(--hub-faint); }
.hub-mdot.is-view .hub-mdot__n, .hub-mdot:hover .hub-mdot__n { color:var(--hub-accent); }
.hub-mini__r { display:flex; align-items:center; gap:.7rem; white-space:nowrap; }
.hub-mini__stat { font-family:var(--mono,monospace); font-size:.7rem; color:var(--hub-muted); }
@media (max-width:820px) {
  .rl-hub .hub-mini__nav .hub-mdot span:not(.hub-mdot__d) { display:none; }
  .hub-mdot { padding:.3rem .4rem; }
  /* …except the one you're looking at. Five anonymous dots tell you there are
     five places to go and nothing else; keeping the active label turns the row
     into a "you are here" as well as a jump list, for the width of one word.
     The figure (.hub-mdot__n) stays hidden — it's the label that navigates. */
  .rl-hub .hub-mini__nav .hub-mdot.is-view span:not(.hub-mdot__d):not(.hub-mdot__n) { display:inline; }
  .hub-mdot.is-view { padding:.3rem .55rem; }
}
@media (max-width:640px) { .hub-mini__stat, .hub-mini__cyc { display:none; } }

/* ── section deep-link + bulk expand ───────────────────────────────────── */
.hub-lnk { background:none; border:1px solid transparent; color:var(--hub-faint); width:24px; height:24px;
  border-radius:6px; cursor:pointer; display:grid; place-items:center; opacity:0; transition:opacity .15s ease; padding:0; }
.hub-sec__head:hover .hub-lnk, .hub-lnk:focus-visible { opacity:1; }
.hub-lnk:hover { color:var(--hub-accent); border-color:var(--hub-bd-lt); }
.hub-lnk.copied { opacity:1; color:var(--hub-accent); border-color:var(--hub-accent); }

/* ── hero ──────────────────────────────────────────────────────────────── */
.hub-hero { background:var(--hub-card); border:1px solid var(--hub-bd); border-radius:var(--hub-r); margin-top:.9rem; overflow:hidden;
  /* The hero stacks on ITS OWN width, not the window's. .hub-hero__acts asks
     for ~400px (.hub-live's 250 plus the Share button) and .hub-ident carries
     min-width:0, so column 1 collapses rather than widening the layout. Under
     roughly 700px of CARD width the ident track gets narrower than the single
     unbreakable token in a domain name and the h1 painted straight over the
     status band. The viewport was 1200px+ the whole time, so the max-width:760
     rule below never fired: a container problem policed by a window query. */
  container-type: inline-size; }
/* THE SECOND TRACK HAS A CEILING, WHICH IS WHAT THE CONTAINER QUERY BELOW
   CANNOT DO ON ITS OWN. `auto` sizes to the column's max-content, and the
   widest thing in it is .hub-live__sub — a full sentence. So on a wide card
   column 2 took ~800px, column 1 collapsed to a fraction of the h1, and the
   @container rule never fired because the CARD was 1400px, not 700. Bounding
   the track fixes the cause; the container query stays for the genuinely
   narrow case, and the window query behind it for browsers without support. */
.hub-hero__top { display:grid; grid-template-columns:minmax(0,1fr) minmax(0,220px); gap:1.5rem 2rem; align-items:center; padding:1.5rem 1.5rem 1.3rem; }
@container (max-width:700px) { .hub-hero__top { grid-template-columns:minmax(0,1fr); } }
@media (max-width:760px) { .hub-hero__top { grid-template-columns:minmax(0,1fr); } }

/* min-width:0 on BOTH: a grid/flex item defaults to min-width:auto and refuses
   to shrink below its content, so a long crawl name (or the shared-with-you
   chip's owner email) pushed .hub-ident past its grid track and .hub-hero's
   overflow:hidden silently clipped it on a phone. */
.hub-ident { display:flex; gap:1rem; align-items:center; min-width:0; }
.hub-ident > div { min-width:0; }
.hub-tile { width:56px; height:56px; flex:none; border-radius:var(--hub-r-sm);
  background:linear-gradient(145deg,var(--hub-accent),#a3d100); color:var(--accent-ink); display:grid; place-items:center;
  font-weight:700; font-size:1.45rem; letter-spacing:-.03em; }
/* A company name is one long token far more often than not, and a token wider
   than its track overflows instead of wrapping. Same fix already applied to
   .hub-cover__client in account.css. Belt and braces behind the container
   query: even if the track is squeezed, the name breaks rather than escaping. */
.rl-hub .hub-ident h1 { margin:0; font-size:clamp(1.45rem,3.2vw,1.95rem); letter-spacing:-.025em; line-height:1.1;
  overflow-wrap:anywhere; }
.hub-ident__row { display:flex; align-items:center; gap:.6rem; flex-wrap:wrap; margin-top:.35rem; }
.hub-host { color:var(--hub-muted); font-size:.85rem; }
.hub-idcode { font-family:var(--mono,monospace); font-size:.67rem; color:var(--hub-faint); background:var(--hub-card-2);
  border:1px solid var(--hub-bd); padding:.16rem .45rem; border-radius:5px; }
.hub-cycle { font-family:var(--mono,monospace); font-size:.62rem; letter-spacing:.09em; text-transform:uppercase;
  color:var(--hub-accent); background:var(--hub-accent-dim); border:1px solid rgba(var(--accent-rgb), .3); padding:.2rem .5rem; border-radius:5px; }

/* "Shared with you by <owner> · read-only". A viewer whose only crawl is a
   shared one is redirected here from Home, so this page has to answer "whose
   crawl am I looking at?" without a hover. Cool blue, deliberately NOT the lime
   accent — accent means "yours" everywhere else in the account. min-width:0 lets
   a long owner email ellipsize instead of widening the header on mobile. */
.hub-shared { display:flex; align-items:center; gap:.4rem; margin-top:.5rem; max-width:100%; min-width:0; width:fit-content;
  font-size:.75rem; color:var(--info-soft); background:rgba(125,211,252,.1); border:1px solid rgba(125,211,252,.28);
  padding:.24rem .55rem; border-radius:6px; }
/* The owner's email is the only unbounded part, so it's the only part allowed to
   ellipsize — "Shared with you by" and "· read-only" always stay legible. */
.hub-shared b { font-weight:600; color:#e0f2fe; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0; flex:0 1 auto; }
.hub-shared__k, .hub-shared__ro { white-space:nowrap; flex:none; }
/* A tag, not a trailing "· read-only" clause: when the chip wraps on a phone
   this lands on its own line, and a lone leading "·" reads like a typo where a
   small caps tag reads like a label. */
.hub-shared__ro { font-family:var(--mono,monospace); font-size:.58rem; letter-spacing:.09em; text-transform:uppercase;
  color:var(--info); border:1px solid rgba(125,211,252,.35); border-radius:4px; padding:.1rem .3rem; }
/* On a phone all four parts on one line squeezed the email down to "koli…" —
   the one part a reader actually needs. Wrapping gives it a full line. */
@media (max-width:760px) { .hub-shared { flex-wrap:wrap; row-gap:.22rem; } }
.hub-shared svg { flex:none; opacity:.85; }
@media print { .hub-shared { display:none; } }

/* ── stage track ─────────────────────────────────────────────────────────
   One continuous rail with the dots sitting on it. The rail is a single
   element spanning first-dot-centre to last-dot-centre, NOT a pseudo-element
   per stop — per-item segments get clipped by anything painted over a stop.
   Nothing draws a background across the rail: the hover/active affordance
   lives on the label, below it. */
.hub-track { position:relative; display:grid; grid-template-columns:repeat(5,1fr);
  padding:var(--hub-track-pt) 1.5rem 1.5rem; }   /* top pad reserves the pin row */
.hub-rail, .hub-rail__fill, .hub-rail__now {
  position:absolute; top:calc(var(--hub-track-pt) + (var(--hub-dot) / 2));   /* dot centre */
  height:2px; border-radius:2px; }
.hub-rail { left:10%; right:10%; background:var(--hub-bd-lt); }
.hub-rail__fill { left:10%; background:var(--hub-accent); }
.hub-rail__now { background:linear-gradient(90deg,var(--hub-accent),var(--hub-info)); animation:hub-flow 2.4s ease-in-out infinite; }
@keyframes hub-flow { 0%,100% { opacity:.45 } 50% { opacity:1 } }

.hub-stop { position:relative; z-index:1; display:grid; grid-template-rows:var(--hub-dot) auto; justify-items:center;
  gap:.55rem; background:none; border:0; padding:0; cursor:pointer; font:inherit; color:inherit; }
.hub-dot { width:var(--hub-dot); height:var(--hub-dot); border-radius:50%; display:grid; place-items:center;
  font-family:var(--mono,monospace); font-size:.7rem; font-weight:500; border:1.5px solid var(--hub-bd-lt);
  background:var(--hub-card); color:var(--hub-faint); box-shadow:0 0 0 4px var(--hub-card);  /* mask the rail behind the dot */
  transition:transform .18s ease, border-color .18s ease; }
.hub-stop:hover .hub-dot { transform:translateY(-2px); border-color:var(--hub-muted); }
.hub-stop.done .hub-dot { background:var(--hub-accent); border-color:var(--hub-accent); color:#0a0a0a; }
.hub-stop.now .hub-dot { border-color:var(--hub-info); color:var(--hub-info); background:var(--hub-card);
  box-shadow:0 0 0 4px var(--hub-card), 0 0 0 7px var(--hub-info-dim); }
.hub-stop.you .hub-dot { border-color:var(--hub-accent); color:var(--hub-accent);
  box-shadow:0 0 0 4px var(--hub-card), 0 0 0 7px var(--hub-accent-dim); }
.hub-stop__l { font-size:.76rem; color:var(--hub-faint); text-align:center; line-height:1.25; padding:.22rem .6rem;
  border-radius:6px; border:1px solid transparent; transition:color .15s ease, background .15s ease, border-color .15s ease; }
.hub-stop.done .hub-stop__l { color:var(--hub-text-2); }
.hub-stop.now .hub-stop__l, .hub-stop.you .hub-stop__l { color:var(--hub-text); font-weight:600; }
.hub-stop:hover .hub-stop__l { background:var(--hub-card-2); color:var(--hub-text); }
.hub-stop[aria-expanded="true"] .hub-stop__l { background:var(--hub-card-2); border-color:var(--hub-bd-lt); color:var(--hub-text); }
.hub-stop:focus-visible { outline:none; }
.hub-stop:focus-visible .hub-stop__l { outline:2px solid var(--hub-accent); outline-offset:2px; }

/* Pin sits in the track's reserved top padding, above the dot row, so it can
   never touch the dot, the rail, or the label. */
.hub-pin { position:absolute; top:-22px; left:50%; transform:translateX(-50%); display:flex; flex-direction:column;
  align-items:center; gap:2px; font-size:.54rem; letter-spacing:.1em; font-family:var(--mono,monospace);
  color:var(--hub-info); text-transform:uppercase; white-space:nowrap; }
.hub-pin::after { content:""; width:0; height:0; border-left:4px solid transparent; border-right:4px solid transparent;
  border-top:5px solid var(--hub-info); }
.hub-stop.you .hub-pin { color:var(--hub-accent); }
.hub-stop.you .hub-pin::after { border-top-color:var(--hub-accent); }

/* ── the explainer panel — the point of the hero ───────────────────────── */
.hub-peek { border-top:1px solid var(--hub-bd); background:var(--hub-card-2); padding:1.25rem 1.5rem 1.35rem;
  display:grid; grid-template-columns:1fr auto; gap:1.25rem 2rem; align-items:center; }
@media (max-width:760px) { .hub-peek { grid-template-columns:1fr; } }
.hub-peek__k { font-family:var(--mono,monospace); font-size:.61rem; letter-spacing:.12em; text-transform:uppercase;
  display:flex; align-items:center; gap:.45rem; }
.hub-peek__k.is-done { color:var(--hub-accent); }
.hub-peek__k.is-now { color:var(--hub-info); }
.hub-peek__k.is-next { color:var(--hub-faint); }
.rl-hub .hub-peek h2 { margin:.4rem 0 .35rem; font-size:1.12rem; letter-spacing:-.015em; font-weight:600; }
.rl-hub .hub-peek p { margin:0; color:var(--hub-muted); font-size:.88rem; max-width:64ch; }
.hub-peek__got { margin-top:.7rem; display:flex; flex-wrap:wrap; gap:.4rem; }
.hub-peek__cta { display:flex; flex-direction:column; gap:.5rem; align-items:flex-start; }

.hub-kv { font-family:var(--mono,monospace); font-size:.7rem; color:var(--hub-text-2); background:var(--hub-card-3);
  border:1px solid var(--hub-bd-lt); padding:.25rem .55rem; border-radius:5px; }
.hub-kv b { color:var(--hub-accent); font-weight:600; }
.hub-kv.dim b { color:var(--hub-faint); }

.hub-btn { font-size:.84rem; text-decoration:none; white-space:nowrap; border-radius:8px; padding:.5rem .9rem;
  border:1px solid var(--hub-bd-lt); background:var(--hub-card-3); color:var(--hub-text-2); }
.hub-btn:hover { border-color:var(--hub-accent); color:var(--hub-accent); }
.hub-btn--go { background:var(--hub-accent); color:#0a0a0a; border-color:var(--hub-accent); font-weight:600; }
.hub-btn--go:hover { background:#d9ff3d; color:#0a0a0a; }
.hub-eta { font-family:var(--mono,monospace); font-size:.7rem; color:var(--hub-faint); }

.hub-meta { display:flex; gap:1.1rem; flex-wrap:wrap; align-items:center; color:var(--hub-faint); font-size:.78rem; padding:1rem .2rem 0; }
.hub-meta .sep { width:3px; height:3px; border-radius:50%; background:var(--hub-bd-lt); }
.hub-meta__r { margin-left:auto; display:flex; align-items:center; gap:.7rem; }

/* ── team ──────────────────────────────────────────────────────────────── */
.hub-team { display:flex; align-items:center; gap:.5rem; }
/* The whole cluster is the target now — avatars included. Button reset, so it
   still reads as the meta row it lives in. */
.hub-team--btn { background:none; border:0; padding:0; font:inherit; cursor:pointer; }
.hub-team--btn:hover .hub-share--ro { border-color:rgba(125,211,252,.5); color:#bae6fd; }
.hub-team--btn:focus-visible { outline:2px solid var(--hub-accent); outline-offset:3px; border-radius:8px; }
.hub-avs { display:flex; }
.hub-av { width:25px; height:25px; border-radius:50%; display:grid; place-items:center; font-size:.66rem; font-weight:600;
  color:#0a0a0a; border:2px solid var(--bg,#09090b); margin-left:-7px; }
.hub-av:first-child { margin-left:0; }
.hub-av--wait { background:var(--hub-card-3); color:var(--hub-muted); border-color:var(--bg,#09090b); font-weight:500; }
.hub-share { display:inline-flex; align-items:center; gap:.35rem; font-size:.78rem; color:var(--hub-text-2);
  background:var(--hub-card-2); border:1px solid var(--hub-bd-lt); border-radius:7px; padding:.3rem .65rem;
  cursor:pointer; font-family:inherit; }
.hub-share:hover { border-color:var(--hub-accent); color:var(--hub-accent); }
/* A viewer's version reveals the roster instead of an invite form, so it hovers
   blue (informational) rather than lime (an action that changes something). */
.hub-share--ro:hover { border-color:rgba(125,211,252,.5); color:#bae6fd; }
/* The hero's copy — the primary Share affordance, sitting beside the crawl's
   name where the decision to share is actually made. Sized as a real touch
   target; the meta-row twin below it stays a small secondary link. */
.hub-share--top { font-size:.85rem; font-weight:500; padding:.55rem .9rem; border-radius:9px;
  min-height:44px; color:var(--hub-text); border-color:var(--hub-bd-lt); }
.hub-share--top svg { width:14px; height:14px; }
.hub-hero__acts { display:flex; align-items:center; gap:.7rem; flex-wrap:wrap; justify-content:flex-end; }
@media (max-width:760px) {
  /* The hero stacks here, so without an explicit order Share fell BELOW the
     whole live-status block — title, stage, progress bar, caption — which is
     most of a phone screen and the opposite of "toward the top". */
  .hub-hero__acts { justify-content:flex-start; flex-direction:column; align-items:stretch; gap:.85rem; }
  .hub-share--top { order:-1; width:100%; justify-content:center; }
}

/* Share panel — /api/shares is complete (list / create / revoke); this is its UI. */
.hub-sharebox { margin:.8rem 0 0; background:var(--hub-card); border:1px solid var(--hub-bd-lt); border-radius:var(--hub-r-sm); padding:1rem; }
.hub-sharebox[hidden] { display:none; }
.hub-sharebox__k { font-family:var(--mono,monospace); font-size:.62rem; letter-spacing:.1em; text-transform:uppercase;
  color:var(--hub-faint); margin-bottom:.7rem; }
.hub-sharerow { display:flex; align-items:center; gap:.6rem; padding:.4rem 0; font-size:.84rem; color:var(--hub-text-2);
  border-top:1px solid var(--hub-bd); }
.hub-sharerow:first-of-type { border-top:none; }
.hub-sharerow__tag { font-family:var(--mono,monospace); font-size:.6rem; letter-spacing:.08em; text-transform:uppercase;
  color:var(--hub-faint); background:var(--hub-card-2); border-radius:4px; padding:.14rem .4rem; }
.hub-sharerow__x { margin-left:auto; background:none; border:1px solid var(--hub-bd-lt); color:var(--hub-muted);
  font:inherit; font-size:.72rem; border-radius:6px; padding:.2rem .55rem; cursor:pointer; }
.hub-sharerow__x:hover { color:var(--red-ink); border-color:var(--red-ink); }
.hub-shareform { display:flex; gap:.5rem; margin-top:.8rem; flex-wrap:wrap; }
.hub-shareform input { flex:1; min-width:200px; background:var(--hub-card-2); border:1px solid var(--hub-bd-lt);
  color:var(--hub-text); border-radius:7px; padding:.45rem .7rem; font:inherit; font-size:.84rem; }
.hub-shareform button { background:var(--hub-accent); color:var(--accent-ink); border:none; border-radius:7px; padding:.45rem .9rem;
  font:inherit; font-size:.82rem; font-weight:600; cursor:pointer; }
.hub-sharemsg { font-size:.78rem; margin-top:.6rem; color:var(--hub-muted); }
.hub-sharemsg.err { color:var(--red-ink); }

/* ── feedback guidance ─────────────────────────────────────────────────── */
.hub-fb { display:grid; grid-template-columns:auto 1fr auto; gap:.8rem; align-items:center;
  background:rgba(var(--accent-rgb), .05); border:1px solid rgba(var(--accent-rgb), .22); border-radius:var(--hub-r-sm); padding:.7rem .9rem; }
.hub-fb__i { width:26px; height:26px; border-radius:6px; display:grid; place-items:center;
  background:var(--hub-accent-dim); color:var(--hub-accent); font-size:.85rem; }
.hub-fb__t { font-size:.83rem; color:var(--hub-text-2); }
.hub-fb__t b { color:var(--hub-text); font-weight:600; }
/* Outlined, never filled: the one lime button on the page is the ask's. */
.hub-fb__go { font-size:.78rem; text-decoration:none; white-space:nowrap; color:var(--hub-accent); background:rgba(var(--accent-rgb), .06);
  border:1px solid rgba(var(--accent-rgb), .3); border-radius:7px; padding:.34rem .7rem; font-weight:600; }
.hub-fb__go:hover { border-color:var(--hub-accent); background:var(--hub-accent-dim); }
@media (max-width:620px) { .hub-fb { grid-template-columns:auto 1fr; } .hub-fb__go { grid-column:2; justify-self:start; } }

/* in-viewer coach mark */
.hub-coach { background:var(--hub-card-2); border:1px solid var(--hub-bd); border-radius:var(--hub-r-sm);
  padding:.9rem 1rem; display:flex; flex-direction:column; gap:.6rem; }
.hub-coach__q { display:flex; align-items:flex-start; gap:.6rem; font-size:.85rem; color:var(--hub-text-2);
  background:var(--hub-card); border:1px solid var(--hub-bd-lt); border-radius:7px; padding:.6rem .7rem; position:relative; }
.hub-coach__pen { width:21px; height:21px; flex:none; border-radius:5px; display:grid; place-items:center;
  background:var(--hub-accent); color:var(--accent-ink); font-size:.72rem; }
.hub-coach__bub { align-self:flex-start; margin-left:2.2rem; position:relative; background:var(--hub-card-3);
  border:1px solid var(--hub-accent); border-radius:8px; padding:.55rem .75rem; font-size:.79rem; color:var(--hub-text-2); max-width:44ch; }
.hub-coach__bub::before { content:""; position:absolute; top:-6px; left:16px; width:9px; height:9px;
  background:var(--hub-card-3); border-left:1px solid var(--hub-accent); border-top:1px solid var(--hub-accent); transform:rotate(45deg); }

/* ── export ────────────────────────────────────────────────────────────── */
/* Three columns: the cover, what's in it, and what you can do with it.

   `auto 1fr auto` looked reasonable and collapsed in practice. An `auto` track
   sizes to its content's MAX-CONTENT width, and the third column ends with a
   full sentence ("The report is the whole crawl; the answers are every question
   you're missing from"). That sentence set the column's width, the actions
   column ballooned past 400px, and the middle `1fr` took whatever was left —
   about fifteen characters, so the description wrapped into a ragged ribbon two
   or three words wide.

   Fixed here rather than by shortening the sentence: the copy is right, the
   track sizing was wrong. The actions column is now bounded on both sides so no
   string inside it can set the layout, and the middle track is `minmax(0,1fr)`
   — a bare `1fr` has an automatic minimum of min-content and refuses to shrink
   below its longest word, which is what turns a grid like this rigid. */
/* `1fr auto` on the rows, not `auto auto`: the cover spans both, and any slack
   between its 383px and the content's ~350px has to go somewhere. Given to the
   first row it becomes breathing space above the actions, which then sit level
   with the foot of the cover. Left to distribute evenly it opened a ragged gap
   in the middle of the column instead. */
.hub-exp { display:grid; grid-template-columns:auto minmax(0,1fr); grid-template-rows:1fr auto;
  gap:1.4rem 2rem; align-items:start; }
/* Prose wants a measure. The column is ~750px here and the description ran to
   ~100 characters a line, which is past the point where the eye loses its place
   returning to the left edge. The contents list is deliberately NOT capped — its
   rows are a two-column manifest and want the full width. */
.hub-exp .hub-lede { max-width:64ch; }
/* The actions sit UNDER the copy, not in a third column.
   Three columns was the original shape and it failed twice over. The copy got
   ~15 characters of measure and wrapped into a ribbon, because the third track
   was `auto` and a full sentence inside it set the width. Fixing the track
   sizing bought a readable measure but left the next problem: the cover is a
   fixed 250px card, 383px tall with its caption, while the copy beside it is
   ~230px and the buttons ~200px — so two of three columns ended a third of the
   way down and the panel had a void through its lower right.
   Stacking copy over actions in one column puts ~330px against the cover's 383
   and closes it, and it lets the two downloads sit side by side, which reads
   better than a vertical stack of look-alike buttons anyway. */
.hub-exp__cta { grid-column:2; grid-row:2; }
/* The cover spans both rows or it defeats the point: left in row 1 only, the
   actions land UNDERNEATH it and the panel gets taller than the three-column
   version it was meant to tighten (507px vs 383px). Spanning puts copy and
   actions against the full height of the card. */
.hub-cover__wrap { grid-row:1 / span 2; }
@media (max-width:900px) { .hub-exp { grid-template-columns:1fr; justify-items:start; }
  .hub-exp__cta { grid-column:1; grid-row:auto; } .hub-cover__wrap { grid-row:auto; } }
/* The contents list carries the other half of this panel's job — the copy says
   what the document is, these rows say what's in it. Given room to breathe
   rather than packed at .35rem: it reads as a manifest, and the extra height
   helps the middle column meet the cover instead of stopping a third of the way
   down it. Rules between rows, not around them, so it stays a list. */
.hub-exp__list { display:flex; flex-direction:column; margin-top:1.05rem;
  border-top:1px solid var(--hub-bd-lt); }
.hub-exp__row { display:grid; grid-template-columns:auto 1fr auto; gap:.75rem; align-items:center;
  font-size:.84rem; color:var(--hub-text-2); padding:.52rem .1rem;
  border-bottom:1px solid var(--hub-bd-lt); }
.hub-tick { width:16px; height:16px; border-radius:4px; display:grid; place-items:center; font-size:.65rem;
  background:var(--hub-accent-dim); color:var(--hub-accent); border:1px solid rgba(var(--accent-rgb), .3); }
.hub-tick--wait { background:var(--hub-card-3); color:var(--hub-faint); border-color:var(--hub-bd-lt); }
.hub-exp__note { font-family:var(--mono,monospace); font-size:.66rem; line-height:1.6; color:var(--hub-faint); }
/* Downloads on one row, "read it here" beneath. The two buttons share the width
   evenly (flex:1 on each) so neither reads as the senior one — a customer wants
   the report or the answers depending on who they're forwarding it to. */
.hub-exp__cta { display:flex; flex-direction:column; gap:.7rem; align-items:stretch; margin-top:.25rem; }
/* Bounded on both sides. Unbounded, two buttons became 370px each and a single
   one stretched the full 754px — a download control the width of a paragraph
   reads as a banner, not a button. `flex:1 1 0` keeps the pair equal (neither
   document is the senior one) and the max-width stops either from sprawling
   when it's alone. */
.hub-exp__dls { display:flex; gap:.6rem; flex-wrap:wrap; }
.hub-exp__dls .hub-dl { flex:1 1 0; min-width:200px; max-width:288px; }
.hub-dl { display:flex; align-items:center; justify-content:center; gap:.45rem; font-size:.86rem; font-weight:600;
  text-decoration:none; background:var(--btn-fill, #3f5c0b); color:var(--btn-ink, #f4ffe0); border-radius:8px; padding:.7rem 1rem;
  white-space:nowrap; }
.hub-dl:hover { background:color-mix(in srgb, var(--btn-fill, #3f5c0b) 88%, #fff); }
/* The second document. Both downloads are primary — a customer wants the report
   OR the answers depending on who they're forwarding it to, and neither is the
   lesser errand — so this reads as the same class of control, distinguished by
   weight rather than demoted to a ghost. A ghost button here put the answers in
   the same visual bracket as "open" and "email", which is where it got lost. */
.hub-dl--second { background:var(--hub-accent-dim); color:var(--hub-accent);
  border:1px solid rgba(var(--accent-rgb), .42); }
.hub-dl--second:hover { background:rgba(var(--accent-rgb), .16); border-color:var(--hub-accent); }
.hub-dl--ghost { background:var(--hub-card-2); color:var(--hub-text-2); border:1px solid var(--hub-bd-lt); font-weight:500; }
.hub-dl--ghost:hover { border-color:var(--hub-accent); color:var(--hub-accent); background:var(--hub-card-2); }

/* Reading it here instead of taking it away. Deliberately NOT buttons: these are
   the alternative to the two above, and a third and fourth button of the same
   shape is what made the original stack read as four equal errands. A rule and a
   label separate the two intents; the links themselves are text. */
.hub-exp__open { display:flex; align-items:baseline; flex-wrap:wrap; gap:.3rem 1rem; }
.hub-exp__openlbl { font-family:var(--mono,monospace); font-size:.62rem;
  letter-spacing:.09em; text-transform:uppercase; color:var(--hub-faint); }
.hub-openlink { font-size:.82rem; font-weight:500; color:var(--hub-text-2); text-decoration:none;
  border-bottom:1px solid transparent; padding-bottom:1px; }
.hub-openlink:hover { color:var(--hub-accent); border-bottom-color:currentColor; }
.hub-openlink span { font-size:.72em; opacity:.7; }

/* ── report cover ────────────────────────────────────────────────────────
   The PDF is light while the account is dark: it's printed, forwarded and read
   outside the product. Shown here at ~40% of a US Letter page. */
/* 250px, and it must stay 250px: every size inside this card is absolute px
   tuned to that width (client 25px, figure 31px, footer 5.8px). Narrowing the
   container does not scale them, it collides them — at 208px the footer's two
   halves ran together. If this ever needs to be resizable, the inner sizes have
   to become `em` off the card's own font-size first. */
.hub-cover { width:250px; aspect-ratio:8.5 / 11; flex:none; background:#faf9f6; color:var(--tone-950); border-radius:4px;
  border:1px solid var(--hub-bd-lt); box-shadow:0 10px 34px rgba(0,0,0,.5), 0 2px 6px rgba(0,0,0,.4);
  padding:20px 19px 17px; display:flex; flex-direction:column; font-size:7px; line-height:1.5; }
.hub-cover__brand { display:flex; align-items:center; gap:4px; font-size:7.5px; font-weight:700; letter-spacing:-.01em; color:var(--tone-950); }
/* The real lockup at facsimile scale: 245/1200 of 56px keeps the artwork's ratio. */
.hub-cover__brand svg { display:block; width:56px; height:11.4px; color:#18181b; }
.hub-cover__rule { height:2px; background:var(--accent-fill); margin:11px 0 0; border-radius:2px; }
.hub-cover__eyebrow { font-family:var(--mono,monospace); font-size:5.6px; letter-spacing:.16em; text-transform:uppercase; color:#7a7a85; margin-top:13px; }
.hub-cover__client { font-size:25px; font-weight:700; letter-spacing:-.035em; line-height:1.02; margin-top:5px; color:#0d0d0f; }
.hub-cover__sub { font-size:8px; color:var(--tone-600); margin-top:4px; letter-spacing:-.01em; }
.hub-cover__mid { margin-top:auto; }
.hub-cover__num { display:flex; align-items:baseline; gap:4px; }
.hub-cover__num b { font-size:31px; font-weight:700; letter-spacing:-.045em; color:#0d0d0f; font-variant-numeric:tabular-nums; }
.hub-cover__num span { font-size:6.5px; color:#7a7a85; font-family:var(--mono,monospace); letter-spacing:.1em; text-transform:uppercase; }
/* The foundation edition's cover carries a claim where the report carries the
   visibility figure. At facsimile scale it is unreadable as prose either way,
   so it is set to occupy the numeral's optical weight — the card is a picture of
   the document, and the picture has to have the right shape. */
.hub-cover__claim { font-size:9px; line-height:1.3; font-weight:600; color:#0d0d0f;
  letter-spacing:-.01em; border-left:1.5px solid #c8ff00; padding-left:5px; max-width:105px; }
.hub-cover__toc { margin-top:12px; padding-top:9px; border-top:1px solid #e2e1dc; display:flex; flex-direction:column; gap:3.5px; }
.hub-cover__toc div { display:flex; justify-content:space-between; color:var(--border-light); font-size:6.4px; }
.hub-cover__toc .p { color:var(--text-muted); font-family:var(--mono,monospace); }
.hub-cover__foot { margin-top:11px; padding-top:8px; border-top:1px solid #e2e1dc; display:flex; justify-content:space-between;
  color:#8a8a93; font-size:5.8px; font-family:var(--mono,monospace); letter-spacing:.05em; }
.hub-cover__wrap { display:flex; flex-direction:column; align-items:center; gap:.55rem; }
.hub-cover__cap { font-family:var(--mono,monospace); font-size:.63rem; color:var(--hub-faint); letter-spacing:.06em; }

/* The shared readers (deliverable.css) take their palette from the host page.
   Mapping the hub's tokens here is the ONLY styling the hub does to them — the
   components themselves are identical to the ones the report mounts. */
.rl-hub .dv {
  --dvx-panel:var(--hub-card); --dvx-panel-2:var(--hub-card-2); --dvx-rule:var(--hub-bd);
  --dvx-rule-2:var(--hub-bd-lt); --dvx-text:var(--hub-text); --dvx-text-2:var(--hub-text-2);
  --dvx-muted:var(--hub-muted); --dvx-faint:var(--hub-faint); --dvx-accent:var(--hub-accent);
  --dvx-accent-dim:var(--hub-accent-dim); --dvx-high:var(--hub-sev-high);
  --dvx-med:var(--hub-sev-med); --dvx-low:var(--hub-sev-low);
}

/* ── deliverable sections ──────────────────────────────────────────────── */
/* ── the spine ─────────────────────────────────────────────────────────────
   Sections are the stages: numbered plates on a rail that fills to the last
   delivered one, so the list reads as the same sequence as the track. The
   gutter is the plate plus its gap; on a phone both shrink (below). */
.hub-dir { display:flex; flex-direction:column; gap:1rem; margin-top:1.5rem; position:relative; padding-left:48px; }
.hub-spine { position:absolute; left:15px; top:22px; bottom:22px; width:2px; background:var(--hub-bd); border-radius:2px; }
.hub-spine i { position:absolute; left:0; top:0; display:block; width:100%; height:0; background:var(--hub-accent); border-radius:2px; transition:height .4s ease; }
.hub-plate { position:absolute; left:-48px; top:13px; width:32px; height:32px; border-radius:9px; display:grid; place-items:center; z-index:2;
  font-family:var(--mono,monospace); font-size:.66rem; font-weight:600; background:var(--bg-primary, var(--bg)); border:1.5px solid var(--hub-bd); color:var(--hub-faint); }
.hub-sec[data-t="done"] .hub-plate { background:var(--hub-accent); border-color:var(--hub-accent); color:var(--accent-ink); }
.hub-sec[data-t="you"] .hub-plate { border-color:var(--hub-accent); color:var(--hub-accent); box-shadow:0 0 0 4px var(--hub-accent-dim); }
.hub-sec[data-t="now"] .hub-plate { border-color:var(--hub-info); color:var(--hub-info); box-shadow:0 0 0 4px var(--hub-info-dim); }
.hub-sec[data-t="next"] { border-style:dashed; }
.hub-sec[data-t="you"] { border-color:rgba(var(--accent-rgb), .4); box-shadow:0 0 0 3px var(--hub-accent-dim); }
/* Sections are jumped to (mini-bar dots, #sec- links, a hash on load) and every
   one of those lands via scrollIntoView({block:"start"}) — which parks the head
   underneath the fixed top nav plus the sticky mini-bar, so you arrive mid-card
   with no sign you moved. --hub-sticky-top is the nav's measured bottom edge
   (set in crawl/index.html); +52px clears the mini-bar. Same formula the
   booklet and deliverable readers use. */
/* overflow:visible, not hidden: the plate sits outside the card on the
   spine. The body is display:none when collapsed, so nothing needed clipping. */
.hub-sec { background:var(--hub-card); border:1px solid var(--hub-bd); border-radius:var(--hub-r); overflow:visible; position:relative;
  scroll-margin-top:calc(var(--hub-sticky-top, 64px) + 52px); }
.hub-sec.is-now { border-color:rgba(125,211,252,.4); box-shadow:0 0 0 1px rgba(125,211,252,.12); }
/* A section we are actively working (state "progress") breathes exactly like
   the home wall's rl-signal--working — same blue, same cadence — so the crawl
   page carries the "we're on it" cue instead of only Home having it. Amber
   your-move sections stay deliberately still: the glow means US working. */
.hub-sec.is-working { border-color:rgba(var(--sky-rgb), .45); animation:rl-workglow 2.6s ease-in-out infinite; }
.hub-sec.is-working .hub-badge--run { display:inline-flex; align-items:center; gap:6px; }
.hub-sec.is-working .hub-badge--run::before { content:""; width:7px; height:7px; border-radius:50%; flex:none;
  background:var(--hub-info,var(--info)); animation:rl-livedot 1.6s ease-in-out infinite; }
/* The header readout gets the same live dot while anything is in motion. */
.hub-live--motion .hub-live__k { display:inline-flex; align-items:center; gap:7px; }
.hub-live--motion .hub-live__k::before { content:""; width:8px; height:8px; border-radius:50%; flex:none;
  background:var(--hub-info,var(--info)); animation:rl-livedot 1.6s ease-in-out infinite; }
.hub-sec__head { display:grid; grid-template-columns:1fr auto; gap:1rem; align-items:center; padding:1.15rem 1.3rem; cursor:pointer; }
.hub-sec__t { display:flex; flex-direction:column; gap:.15rem; min-width:0; }
.hub-sec__eyebrow { font-family:var(--mono,monospace); font-size:.61rem; letter-spacing:.11em; text-transform:uppercase; color:var(--hub-faint); }
.rl-hub .hub-sec__t h2 { margin:0; font-size:1.05rem; letter-spacing:-.015em; font-weight:600; }
.hub-sec__r { display:flex; align-items:center; gap:.7rem; flex-wrap:wrap; justify-content:flex-end; }

/* ── collapse ────────────────────────────────────────────────────────────
   Only the current stage is open on a first visit; the rest collapse to a
   header that still carries its badge and a one-line summary, so collapsing
   hides bulk without hiding value. Open state persists per crawl. */
.hub-sec__toggle { background:var(--hub-card-2); border:1px solid var(--hub-bd-lt); color:var(--hub-muted);
  width:26px; height:26px; border-radius:6px; cursor:pointer; flex:none; display:grid; place-items:center;
  font-size:.7rem; line-height:1; padding:0; transition:transform .2s ease, color .15s ease, border-color .15s ease; }
.hub-sec__toggle:hover { color:var(--hub-accent); border-color:var(--hub-accent); }
.hub-sec.is-open .hub-sec__toggle { transform:rotate(180deg); }
.hub-sec__head:hover .hub-sec__toggle { color:var(--hub-accent); }

/* summary line, shown only while collapsed. Pinned to row 2 / col 2 explicitly:
   auto-placement alone would push the badge+toggle group down a row, because
   the summary precedes it in the DOM. */
.hub-sec__sum { grid-column:1 / 2; grid-row:2; font-size:.79rem; color:var(--hub-faint);
  display:flex; flex-wrap:wrap; gap:.5rem; align-items:center; margin-top:.15rem; }
.hub-sec.is-open .hub-sec__sum { display:none !important; }
.hub-sec__sum .sep { width:3px; height:3px; border-radius:50%; background:var(--hub-bd-lt); }
.hub-sec__sum .hot { color:var(--hub-sev-high); }

/* Collapse is expressed as :not(.is-open) — specificity (0,2,0) beats the bare
   `.hub-sec__body { display:flex }` rule below (0,1,0), so this can't be
   silently undone by source order. Writing it as `.hub-sec__body{display:none}`
   here did exactly that: the later rule won and nothing ever collapsed. */
.hub-sec:not(.is-open) .hub-sec__body { display:none; }
.hub-sec__body { padding:0 1.3rem 1.3rem; display:flex; flex-direction:column; gap:1rem; }

.hub-badge { font-family:var(--mono,monospace); font-size:.65rem; letter-spacing:.05em; padding:.24rem .55rem;
  border-radius:5px; white-space:nowrap; }
.hub-badge--done { background:var(--hub-accent-dim); color:var(--hub-accent); border:1px solid rgba(var(--accent-rgb), .3); }
.hub-badge--run { background:var(--hub-info-dim); color:var(--hub-info); border:1px solid rgba(125,211,252,.28); }
.hub-badge--wait { background:var(--hub-card-2); color:var(--hub-faint); border:1px solid var(--hub-bd-lt); }
.hub-badge--you { background:rgba(var(--med-rgb), .12); color:var(--hub-sev-med); border:1px solid rgba(var(--med-rgb), .32); }

.hub-open { font-size:.82rem; color:var(--hub-text-2); text-decoration:none; border:1px solid var(--hub-bd-lt);
  border-radius:7px; padding:.36rem .75rem; white-space:nowrap; background:var(--hub-card-2); }
.hub-open:hover { border-color:var(--hub-accent); color:var(--hub-accent); }
.hub-open[aria-disabled="true"] { opacity:.4; pointer-events:none; }
/* `.hub-op` is gone: operator controls no longer live in the customer's
   sections at all. See the operator rail (.rl-oprail) near the top of this
   file — putting one back here is the regression that comment describes. */

.rl-hub .hub-lede { font-size:.9rem; color:var(--hub-text-2); margin:0 0 .1rem; border-left:2px solid var(--hub-bd-lt);
  padding-left:.85rem; max-width:70ch; }
.rl-hub .hub-lede b { color:var(--hub-text); font-weight:600; }

/* The Voice-of-Customer line is a link, not a paragraph. It reads as body text on
   purpose — it belongs to the Foundations card rather than competing with the card's
   own CTA — so the accent border and the trailing "Read what buyers said →" are what
   say it is clickable. Both strengthen on hover; neither shouts when idle. */
.rl-hub a.hub-lede--link { display:block; text-decoration:none; transition:border-color .15s, background .15s; }
.rl-hub a.hub-lede--link:hover, .rl-hub a.hub-lede--link:focus-visible {
  border-left-color:var(--rl-accent,var(--accent)); background:rgba(var(--accent-rgb), .045); }
.rl-hub a.hub-lede--link:focus-visible { outline:2px solid var(--rl-accent,#c8ff00); outline-offset:3px; }
.hub-lede__go { display:inline-block; margin-left:.4rem; white-space:nowrap;
  color:var(--rl-accent,var(--accent)); font-weight:600; }
.rl-hub a.hub-lede--link:hover .hub-lede__go { text-decoration:underline; }

/* ── Section 01's doors (F3) ────────────────────────────────────────────────
   A count that opens. These replaced `.hub-stat` tiles, which were <div>s that
   looked exactly like this and did nothing — so the whole job of this block is
   to make "looks like a control" and "is a control" the same set. Hence a real
   <button>, a hover state, a caret that turns, and an open state that reads as
   connected to the panel it opened. */
.hub-doors { display:flex; flex-direction:column; gap:.6rem; }
.hub-doors__tiles { display:grid; grid-template-columns:repeat(auto-fit,minmax(118px,1fr)); gap:.6rem; }
.hub-door { display:flex; flex-direction:column; gap:.1rem; text-align:left; width:100%; cursor:pointer;
  background:var(--hub-card-2); border:1px solid var(--hub-bd-lt); border-radius:var(--hub-r-sm);
  padding:.7rem .8rem; color:inherit; font:inherit; transition:background .13s ease, border-color .13s ease; }
.hub-door:hover { background:var(--hub-card-3,var(--hub-card-2)); border-color:var(--hub-bd); }
.hub-door__k { font-family:var(--mono,monospace); font-size:.6rem; letter-spacing:.1em; text-transform:uppercase; color:var(--hub-faint); }
.hub-door__k::after { content:" ▾"; color:var(--hub-faint); }
.hub-door[aria-expanded="true"] { background:var(--hub-accent-dim); border-color:var(--hub-accent); }
.hub-door[aria-expanded="true"] .hub-door__k::after { content:" ▴"; color:var(--hub-accent); }
.hub-door[aria-expanded="true"] .hub-door__v { color:var(--hub-accent); }
.hub-door__v { font-size:1.5rem; font-weight:600; letter-spacing:-.03em; margin-top:.15rem; color:var(--hub-text); }
.hub-door__s { font-size:.72rem; color:var(--hub-faint); }

.hub-dpanel { border:1px solid var(--hub-accent); border-radius:var(--hub-r-sm);
  background:var(--hub-card-2); overflow:hidden; }
.hub-dpanel[hidden] { display:none; }
.hub-dpanel:focus-visible { outline:2px solid var(--hub-accent); outline-offset:2px; }
.hub-dpanel__h { display:flex; flex-wrap:wrap; gap:.5rem 1rem; align-items:baseline; justify-content:space-between;
  padding:.7rem .95rem; border-bottom:1px solid var(--hub-bd-lt); background:var(--hub-card); }
.hub-dpanel__all { font-size:.8rem; font-weight:600; color:var(--hub-accent); text-decoration:none; white-space:nowrap; }
.hub-dpanel__all:hover { text-decoration:underline; }
.hub-prows { display:flex; flex-direction:column; }
.hub-prow { display:grid; grid-template-columns:1fr auto; gap:.2rem .7rem; align-items:baseline;
  padding:.65rem .95rem; border-bottom:1px solid var(--hub-bd-lt); }
.hub-prow:last-child { border-bottom:none; }
.hub-prow__t { font-size:.9rem; color:var(--hub-text); font-weight:550; }
.hub-prow__s { grid-column:1/-1; font-size:.78rem; color:var(--hub-faint); line-height:1.45; }
.hub-pill { font-family:var(--mono,monospace); font-size:.6rem; letter-spacing:.09em; text-transform:uppercase;
  padding:.12rem .42rem; border-radius:4px; white-space:nowrap; border:1px solid var(--hub-bd-lt); color:var(--hub-text-2); }
.hub-pill--flag { color:var(--hub-sev-high); border-color:rgba(var(--red-rgb), .4); }
.hub-pill--mid { color:var(--hub-sev-med); border-color:rgba(var(--med-rgb), .36); }
.hub-pill--ok { color:var(--hub-accent); border-color:rgba(var(--accent-rgb), .32); }
@media (max-width:620px) { .hub-doors__tiles { grid-template-columns:repeat(2,1fr); } }

.hub-stats { display:grid; grid-template-columns:repeat(auto-fit,minmax(118px,1fr)); gap:.6rem; }
.hub-stat { background:var(--hub-card-2); border:1px solid var(--hub-bd); border-radius:var(--hub-r-sm); padding:.7rem .8rem; }
.hub-stat__k { font-family:var(--mono,monospace); font-size:.6rem; letter-spacing:.1em; text-transform:uppercase; color:var(--hub-faint); }
.hub-stat__v { font-size:1.5rem; font-weight:600; letter-spacing:-.03em; margin-top:.15rem; }
.hub-stat--hero .hub-stat__v { color:var(--hub-accent); }
.hub-stat__s { font-size:.72rem; color:var(--hub-faint); }

/* The one stat tile that goes somewhere. Section 02's "600 answers captured"
   was the largest number on the page and led nowhere — the same complaint F3
   made about the old `.hub-stat` tiles, which is why the rule here is the
   same one: if it looks like a control it has to BE one. So this tile is a
   real link, and it says so on hover and on focus rather than only under the
   cursor. Everything else in the row stays an inert <div>, which is what makes
   this one legible as different. */
a.hub-stat-link { display:block; text-decoration:none; color:inherit; border-radius:var(--hub-r-sm); }
a.hub-stat-link .hub-stat { transition:background .13s ease, border-color .13s ease; height:100%; }
a.hub-stat-link:hover .hub-stat,
a.hub-stat-link:focus-visible .hub-stat { border-color:var(--hub-accent); background:var(--hub-card-3,var(--hub-card-2)); }
a.hub-stat-link:hover .hub-stat__v { color:var(--hub-accent); }
a.hub-stat-link .hub-stat__s { color:var(--hub-accent); }

.hub-panel { background:var(--hub-card-2); border:1px solid var(--hub-bd); border-radius:var(--hub-r-sm); padding:.95rem 1rem; }
.hub-panel__k { font-family:var(--mono,monospace); font-size:.62rem; letter-spacing:.1em; text-transform:uppercase;
  color:var(--hub-faint); margin-bottom:.75rem; }
.hub-grid2 { display:grid; grid-template-columns:1fr 1fr; gap:.6rem; }
@media (max-width:760px) { .hub-grid2 { grid-template-columns:1fr; } }

/* gauges carry a plain-language read */
.hub-gauges { display:grid; grid-template-columns:repeat(auto-fit,minmax(238px,1fr)); gap:1rem 1.6rem; }
.hub-g__top { display:flex; justify-content:space-between; align-items:baseline; gap:.5rem; font-size:.82rem; }
.hub-g__v { font-family:var(--mono,monospace); font-size:.76rem; color:var(--hub-text-2); }
.hub-g__track { height:5px; border-radius:3px; background:var(--hub-card-3); margin-top:.4rem; overflow:hidden; }
.hub-g__fill { height:100%; border-radius:3px; }
.hub-g__read { font-size:.77rem; color:var(--hub-faint); margin-top:.35rem; line-height:1.4; }

.hub-finds { display:flex; flex-direction:column; gap:.4rem; }
.hub-find { display:grid; grid-template-columns:3px auto 1fr auto; gap:.8rem; align-items:center;
  background:var(--hub-card-2); border:1px solid var(--hub-bd); border-radius:var(--hub-r-sm); padding:.6rem .8rem .6rem 0; overflow:hidden; }
.hub-find__stripe { align-self:stretch; border-radius:3px 0 0 3px; }
.hub-find__sev { font-family:var(--mono,monospace); font-size:.57rem; letter-spacing:.1em; text-transform:uppercase;
  padding:.16rem .4rem; border-radius:4px; white-space:nowrap; }
.hub-find__t { font-size:.85rem; color:var(--hub-text-2); min-width:0; }
.hub-find__m { font-family:var(--mono,monospace); font-size:.66rem; color:var(--hub-faint); display:flex; gap:.55rem; white-space:nowrap; }
@media (max-width:640px) { .hub-find { grid-template-columns:3px auto 1fr; } .hub-find__m { display:none; } }
.hub-sev-critical, .hub-sev-high { color:var(--hub-sev-high); background:rgba(var(--high-rgb), .13); }
.hub-sev-medium { color:var(--hub-sev-med); background:rgba(var(--med-rgb), .12); }
.hub-sev-low { color:var(--hub-sev-low); background:rgba(113,113,122,.16); }
.hub-bg-critical, .hub-bg-high { background:var(--hub-sev-high); }
.hub-bg-medium { background:var(--hub-sev-med); }
.hub-bg-low { background:var(--hub-sev-low); }

.hub-chips { display:flex; flex-wrap:wrap; gap:.4rem; }
.hub-chip { font-size:.75rem; color:var(--hub-text-2); background:var(--hub-card-3); border:1px solid var(--hub-bd-lt);
  border-radius:20px; padding:.24rem .65rem; }
.hub-chip .n { font-family:var(--mono,monospace); font-size:.68rem; color:var(--hub-faint); margin-left:.3rem; }
/* A chip that is a link INTO the report — the cross-links (a feature an action
   moves, the action that answers a question) read as destinations, not labels. */
.hub-chip--go { text-decoration:none; white-space:nowrap; }
.hub-chip--go:hover { border-color:var(--hub-accent); color:var(--hub-accent); }
.hub-q__a { font-size:.68rem; padding:.14rem .5rem; }
.hub-chip--warn { border-color:rgba(var(--high-rgb), .5); }

.hub-crawlers { display:flex; flex-wrap:wrap; gap:.35rem; }
.hub-cr { font-family:var(--mono,monospace); font-size:.68rem; padding:.2rem .5rem; border-radius:5px;
  background:var(--hub-accent-dim); color:var(--hub-accent); border:1px solid rgba(var(--accent-rgb), .25); }
.hub-cr--no { background:rgba(var(--red-rgb), .12); color:var(--red-ink); border-color:rgba(var(--red-rgb), .3); }

.hub-empty { display:flex; align-items:center; gap:.7rem; color:var(--hub-muted); font-size:.86rem;
  background:var(--hub-card-2); border:1px dashed var(--hub-bd-lt); border-radius:var(--hub-r-sm); padding:.9rem 1rem; }
.hub-empty b { color:var(--hub-text); font-weight:600; }
/* A gate that names her move carries the way to make it (see gateHTML). It
   wraps under the sentence on a phone rather than squeezing it to nothing. */
.hub-empty .hub-open { margin-left:auto; flex:none; }
@media (max-width:620px) { .hub-empty { flex-wrap:wrap; } .hub-empty .hub-open { margin-left:0; } }
.hub-spin { width:13px; height:13px; flex:none; border-radius:50%; border:1.5px solid var(--hub-bd-lt);
  border-top-color:var(--hub-info); animation:hub-sp 1s linear infinite; }
@keyframes hub-sp { to { transform:rotate(360deg); } }

/* Actions "shape" preview — what the row will hold once the plan lands. */
.hub-acts { display:flex; flex-direction:column; gap:.4rem; }
.hub-act { display:grid; grid-template-columns:auto auto 1fr auto; gap:.8rem; align-items:center;
  background:var(--hub-card-2); border:1px solid var(--hub-bd); border-radius:var(--hub-r-sm); padding:.65rem .85rem; }
.hub-box { width:17px; height:17px; border-radius:5px; border:1.5px solid var(--hub-bd-lt); }
.hub-rank { font-family:var(--mono,monospace); font-size:.72rem; color:var(--hub-faint); }
.hub-act__t { font-size:.85rem; color:var(--hub-text-2); }
.hub-lyr { font-family:var(--mono,monospace); font-size:.6rem; letter-spacing:.07em; padding:.16rem .42rem; border-radius:4px;
  background:var(--hub-card-3); color:var(--hub-muted); border:1px solid var(--hub-bd-lt); }

/* ─────────────────────────────────────────────────────────────────────────
   MOBILE
   The track is the piece that genuinely breaks: five columns of labels at
   375px leaves ~66px each. Rather than hide the labels (which would make the
   dots unidentifiable) the whole track scales down via the --hub-dot /
   --hub-track-pt tokens, so the rail follows automatically.
   ───────────────────────────────────────────────────────────────────────── */
@media (max-width:680px) {
  .rl-hub { --hub-dot:24px; --hub-track-pt:1.6rem; }
  .hub-track { padding-left:.35rem; padding-right:.35rem; }
  .hub-stop__l { font-size:.66rem; padding:.2rem .3rem; line-height:1.2; hyphens:auto; }
  .hub-stop { gap:.4rem; }
  .hub-pin { font-size:.5rem; top:-19px; }
  .hub-dot { font-size:.64rem; }

  .hub-hero__top { padding:1.15rem 1.1rem 1rem; gap:1.15rem; }
  .hub-peek { padding:1.05rem 1.1rem 1.15rem; }
  .hub-tile { width:46px; height:46px; font-size:1.2rem; }

  .hub-sec__head { padding:.95rem 1rem; gap:.7rem; column-gap:.7rem; }
  .hub-sec__body { padding:0 1rem 1.1rem; }
  .hub-dir { padding-left:36px; }
  .hub-spine { left:11px; }
  .hub-plate { left:-36px; width:24px; height:24px; border-radius:7px; font-size:.58rem; top:14px; }
  .hub-sec__sum { grid-column:1 / -1; grid-row:2; }
  .rl-hub .hub-sec__t h2 { font-size:1rem; }

  /* The header's right-hand group wraps under the title instead of squeezing
     the title to nothing. */
  .hub-sec__r { grid-column:1 / -1; grid-row:3; justify-content:flex-start; gap:.5rem; }
  .hub-sec.is-open .hub-sec__r { grid-row:2; }
  .hub-lnk { opacity:1; }                       /* no hover on touch */

  .hub-stats { grid-template-columns:repeat(2,1fr); }
  .hub-gauges { grid-template-columns:1fr; }
  .hub-meta { gap:.55rem .9rem; }
  .hub-meta__r { margin-left:0; width:100%; padding-top:.5rem; }
  .hub-dates { font-size:.64rem; }
  .hub-dates__arw { display:none; }

  .hub-exp { gap:1.1rem; }
  .hub-cover { width:min(230px, 72vw); }
  /* Single column here, so the actions span it and the cover centres above
     them rather than sitting in a half-width track. */
  .hub-exp__cta { width:100%; grid-column:auto; }
  .hub-cover__wrap { align-self:center; width:100%; }

}

/* Mini-bar: let the section jumper scroll rather than overflow the page. */
@media (max-width:820px) {
  /* Keeps the horizontal padding: .hub-mini is fixed and full-bleed now, so a
     0 here put the bar's contents hard against the screen edge. */
  .hub-mini__in { gap:.6rem; padding:.5rem 1.1rem; }
  .hub-mini__nav { margin:0 0 0 auto; overflow-x:auto; scrollbar-width:none; -webkit-overflow-scrolling:touch; }
  .hub-mini__nav::-webkit-scrollbar { display:none; }
}

/* ─────────────────────────────────────────────────────────────────────────
   VIEWER OVERLAY  (viewer-overlay.js)
   Deliverables open ON TOP of the crawl hub instead of navigating away, so
   closing one puts the reader back exactly where they were — same scroll,
   same expanded sections. Lives on <body>, outside .rl-hub, so it styles off
   the account-wide tokens rather than the hub's.
   ───────────────────────────────────────────────────────────────────────── */
.rlv { position:fixed; inset:0; z-index:150;   /* above .site-nav (100) and the account modals */ display:flex; align-items:center; justify-content:center;
  padding:clamp(0px, 3vh, 34px) clamp(0px, 3vw, 34px); }
.rlv[hidden] { display:none; }
.rlv__scrim { position:absolute; inset:0; background:rgba(4,4,6,.72); backdrop-filter:blur(3px);
  opacity:0; transition:opacity .18s ease; border:0; padding:0; cursor:pointer; }
.rlv.is-on .rlv__scrim { opacity:1; }
.rlv__panel { position:relative; display:flex; flex-direction:column; width:min(1180px, 100%); height:100%;
  background:var(--bg,#09090b); border:1px solid var(--border-light,var(--border-light)); border-radius:16px; overflow:hidden;
  box-shadow:0 24px 70px rgba(0,0,0,.6); opacity:0; transform:translateY(10px) scale(.995);
  transition:opacity .18s ease, transform .18s ease; }
.rlv.is-on .rlv__panel { opacity:1; transform:none; }

.rlv__bar { display:flex; align-items:center; gap:.9rem; padding:.7rem .95rem; flex:none;
  background:var(--bg-card,var(--bg-card)); border-bottom:1px solid var(--border,var(--border)); }
.rlv__grip { display:none; }
.rlv__id { display:flex; flex-direction:column; min-width:0; }
.rlv__eyebrow { font-family:var(--mono,monospace); font-size:.58rem; letter-spacing:.11em; text-transform:uppercase;
  color:var(--text-faint,var(--text-faint)); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.rlv__title { font-size:.95rem; font-weight:600; color:var(--text,var(--text)); letter-spacing:-.015em;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.rlv__acts { margin-left:auto; display:flex; align-items:center; gap:.5rem; flex:none; }
.rlv__act { display:inline-flex; align-items:center; justify-content:center; gap:.45rem; height:36px; padding:0 .8rem;
  border-radius:9px; border:1px solid var(--border-light,var(--border-light)); background:var(--bg,#09090b);
  color:var(--text-secondary,var(--text-secondary)); font-size:.82rem; font-weight:600; text-decoration:none; cursor:pointer; }
.rlv__act:hover { border-color:var(--accent,var(--accent)); color:var(--accent,var(--accent)); }
.rlv__act svg { width:15px; height:15px; flex:none; }
.rlv__act--x { width:36px; padding:0; }

.rlv__stage { position:relative; flex:1; min-height:0; background:var(--bg,#09090b); }
.rlv__frame { width:100%; height:100%; border:0; display:block; background:var(--bg,#09090b); opacity:0;
  transition:opacity .2s ease; }
.rlv.is-loaded .rlv__frame { opacity:1; }
.rlv__load { position:absolute; inset:0; display:flex; align-items:center; justify-content:center; gap:.6rem;
  color:var(--text-muted,var(--text-muted)); font-family:var(--mono,monospace); font-size:.76rem; letter-spacing:.06em; }
.rlv.is-loaded .rlv__load { display:none; }
.rlv__spin { width:14px; height:14px; border-radius:50%; border:1.6px solid var(--border-light,var(--border-light));
  border-top-color:var(--accent,var(--accent)); animation:hub-sp .9s linear infinite; }

/* Phone: a full-bleed sheet. There is no room for a 34px gutter, and a
   part-height modal on a 375px screen wastes the only asset it has. dvh (not
   vh) so the browser chrome collapsing doesn't crop the viewer's own footer. */
@media (max-width:760px) {
  .rlv { padding:0; align-items:flex-end; }
  .rlv__panel { width:100%; height:100dvh; max-height:100dvh; border-radius:0; border:0; transform:translateY(2%); }
  .rlv__bar { padding:.55rem .7rem; padding-top:max(.55rem, env(safe-area-inset-top)); gap:.6rem; }
  .rlv__title { font-size:.88rem; }
  .rlv__act { height:40px; }                 /* thumb-sized, not pointer-sized */
  .rlv__act__l { display:none; }
  .rlv__act:not(.rlv__act--x) { width:40px; padding:0; }
}
@media (prefers-reduced-motion: reduce) {
  .rlv__scrim, .rlv__panel, .rlv__frame { transition:none; }
}

/* ─────────────────────────────────────────────────────────────────────────
   INLINE READERS  (findings · questions · actions)
   The hub used to summarise each deliverable and send you elsewhere for the
   detail. These are the detail, on the page: expandable rows, a filter, a
   search, and a link INTO the viewer for anyone who wants the whole document.
   ───────────────────────────────────────────────────────────────────────── */
.hub-panel--reader { padding-bottom:.7rem; }
.hub-panel__hd { display:flex; align-items:center; gap:.7rem; margin-bottom:.7rem; }
.hub-panel__hd .hub-panel__k { margin:0; flex:1; min-width:0; }
.hub-panel__note { font-size:.76rem; color:var(--hub-faint); margin:.6rem 0 0; }
.hub-mini-b { font-family:var(--mono,monospace); font-size:.63rem; letter-spacing:.05em; text-transform:uppercase;
  padding:.34rem .6rem; border-radius:7px; cursor:pointer; flex:none;
  border:1px solid var(--hub-bd-lt); background:transparent; color:var(--hub-muted); }
.hub-mini-b:hover { color:var(--hub-accent); border-color:var(--hub-accent); }

.hub-filters { display:flex; flex-wrap:wrap; gap:.35rem; margin-bottom:.7rem; }
.hub-fchip { display:inline-flex; align-items:center; gap:.4rem; font-family:var(--mono,monospace); font-size:.64rem;
  letter-spacing:.04em; text-transform:uppercase; padding:.32rem .6rem; border-radius:7px; cursor:pointer;
  border:1px solid var(--hub-bd-lt); background:transparent; color:var(--hub-muted); }
.hub-fchip:hover { color:var(--hub-text); }
.hub-fchip.on { background:var(--hub-card-3); color:var(--hub-text); border-color:var(--hub-muted); }
.hub-fdot { width:6px; height:6px; border-radius:50%; flex:none; }

/* A finding: severity row you already knew, with the write-up under it. */
.hub-find2 { background:var(--hub-card-2); border:1px solid var(--hub-bd); border-radius:var(--hub-r-sm);
  overflow:hidden; transition:border-color .15s ease; }
.hub-find2:hover { border-color:var(--hub-bd-lt); }
.hub-find2.is-open { border-color:var(--hub-bd-lt); background:var(--hub-card-3); }
.hub-find2__hd { display:grid; grid-template-columns:3px auto 1fr auto auto; gap:.8rem; align-items:center; width:100%;
  padding:.6rem .8rem .6rem 0; background:none; border:0; cursor:pointer; text-align:left; font:inherit; color:inherit; }
.hub-find2__hd .hub-find__stripe { align-self:stretch; border-radius:3px 0 0 3px; }
.hub-find2__body { display:none; padding:0 .9rem 1rem 1.1rem; }
.hub-find2.is-open .hub-find2__body { display:block; }
.hub-chev { color:var(--hub-faint); font-size:.7rem; transition:transform .18s ease; flex:none; }
.hub-find2.is-open .hub-chev, .rl-act.is-open .hub-chev { transform:rotate(180deg); color:var(--hub-accent); }

.hub-block { margin-top:.75rem; }
.hub-block:first-child { margin-top:.2rem; }
.hub-block__k { font-family:var(--mono,monospace); font-size:.58rem; letter-spacing:.1em; text-transform:uppercase;
  color:var(--hub-faint); margin-bottom:.25rem; }
.rl-hub .hub-block p { margin:0; font-size:.85rem; line-height:1.55; color:var(--hub-text-2); max-width:72ch; }
.rl-hub .hub-block__none { margin:.4rem 0 0; font-size:.82rem; color:var(--hub-faint); }
.hub-bullets { margin:.2rem 0 0; padding-left:1.05rem; display:flex; flex-direction:column; gap:.3rem; }
.rl-hub .hub-bullets li { font-size:.85rem; line-height:1.5; color:var(--hub-text-2); }
.hub-urls { display:flex; flex-wrap:wrap; gap:.35rem; }
.hub-url { font-family:var(--mono,monospace); font-size:.68rem; color:var(--hub-muted); background:var(--hub-card);
  border:1px solid var(--hub-bd); border-radius:6px; padding:.2rem .45rem; word-break:break-all; }
.rl-hub .hub-scope { margin:.7rem 0 0; font-size:.76rem; color:var(--hub-faint); }
.hub-rowacts { margin-top:.9rem; display:flex; gap:.5rem; flex-wrap:wrap; }
.hub-open--sm { font-size:.74rem; padding:.3rem .6rem; }

.hub-readfoot { display:flex; align-items:center; gap:.6rem; flex-wrap:wrap; margin-top:.75rem; }
.hub-readfoot__c { font-family:var(--mono,monospace); font-size:.66rem; color:var(--hub-faint); margin-right:auto; }
.hub-more { font-size:.78rem; font-weight:600; padding:.4rem .8rem; border-radius:8px; cursor:pointer;
  border:1px dashed var(--hub-bd-lt); background:transparent; color:var(--hub-text-2); }
.hub-more:hover { border-style:solid; border-color:var(--hub-accent); color:var(--hub-accent); }

/* Questions: the persona chips are the filter, the list is the answer. */
.hub-chip--b { cursor:pointer; font:inherit; font-size:.75rem; }
.hub-chip--b:hover { border-color:var(--hub-muted); color:var(--hub-text); }
.hub-chip--b.on { background:var(--hub-accent-dim); border-color:rgba(var(--accent-rgb), .45); color:var(--hub-accent); }
.hub-chip--b.on .n { color:var(--hub-accent); }
.hub-search { display:flex; align-items:center; gap:.5rem; margin:.7rem 0 .6rem; padding:0 .7rem;
  background:var(--hub-card); border:1px solid var(--hub-bd); border-radius:var(--hub-r-sm); }
.hub-search__i { color:var(--hub-faint); font-size:.95rem; }
.hub-search input { flex:1; min-width:0; background:none; border:0; outline:none; color:var(--hub-text);
  font:inherit; font-size:.85rem; padding:.55rem 0; }
.hub-search input::placeholder { color:var(--hub-faint); }
.hub-qlist { display:flex; flex-direction:column; gap:.3rem; }
.hub-q { display:grid; grid-template-columns:1.6rem 1fr auto auto; gap:.7rem; align-items:baseline;
  background:var(--hub-card); border:1px solid var(--hub-bd); border-radius:var(--hub-r-sm); padding:.5rem .7rem; }
.hub-q__n { font-family:var(--mono,monospace); font-size:.66rem; color:var(--hub-faint); }
.hub-q__t { font-size:.85rem; color:var(--hub-text-2); line-height:1.45; }
.hub-q__p { font-family:var(--mono,monospace); font-size:.6rem; letter-spacing:.04em; text-transform:uppercase;
  color:var(--hub-faint); white-space:nowrap; }

/* Report section jumper — each opens the report overlay already scrolled. */
.hub-jumps { display:grid; grid-template-columns:repeat(auto-fit,minmax(196px,1fr)); gap:.5rem; }
.hub-jump { display:grid; grid-template-columns:1fr auto; align-items:center; gap:.3rem .6rem; text-decoration:none;
  background:var(--hub-card); border:1px solid var(--hub-bd); border-radius:var(--hub-r-sm); padding:.6rem .75rem; }
.hub-jump:hover { border-color:var(--hub-accent); }
.hub-jump__l { font-size:.85rem; font-weight:600; color:var(--hub-text); }
.hub-jump__s { grid-column:1; font-size:.72rem; color:var(--hub-faint); }
.hub-jump__go { grid-column:2; grid-row:1 / span 2; color:var(--hub-faint); }
.hub-jump:hover .hub-jump__go { color:var(--hub-accent); }

/* Actions: the row body opens in place rather than only in the plan. */
.rl-act__main { text-align:left; background:none; border:0; padding:0; font:inherit; color:inherit; cursor:pointer;
  min-width:0; }
.rl-act__main:focus-visible { outline:2px solid var(--accent,#c8ff00); outline-offset:3px; border-radius:6px; }
.rl-act__more { display:none; margin-top:.85rem; }
.rl-act.is-open { border-color:var(--border-light,var(--border-light)); }
.rl-act.is-open .rl-act__more { display:block; }
.rl-act__side { display:flex; align-items:center; gap:.5rem; }
.rl-act__side .hub-chev { display:grid; place-items:center; width:26px; height:26px; border-radius:7px;
  border:1px solid var(--border,var(--border)); background:var(--bg-card-hover,var(--tone-900)); color:var(--text-muted,var(--text-muted));
  font-size:.68rem; }
.rl-act:hover .rl-act__side .hub-chev { border-color:var(--border-light,var(--border-light)); color:var(--text,var(--text)); }
.rl-act .hub-open--sm { white-space:nowrap; }

@media (max-width:680px) {
  .hub-find2__hd { grid-template-columns:3px auto 1fr auto; gap:.6rem; padding-right:.6rem; }
  .hub-find2__hd .hub-find__m { display:none; }
  .hub-find2__body { padding:0 .8rem .9rem .8rem; }
  .hub-panel--reader { padding-left:.8rem; padding-right:.8rem; }
  .hub-jumps { grid-template-columns:1fr; }
  .hub-q { grid-template-columns:1.4rem 1fr; }
  .hub-q__p, .hub-q__a { grid-column:2; justify-self:start; }
  /* Footer controls stack: side-by-side, "Show 3 more findings" wraps to three
     lines inside a 150px box and stops reading as a button. */
  .hub-readfoot { flex-direction:column; align-items:stretch; gap:.45rem; }
  .hub-readfoot__c { order:3; margin-right:0; text-align:center; }
  .hub-more, .hub-readfoot .hub-open { text-align:center; justify-content:center; }
  /* Filters scroll sideways rather than stacking four rows deep. */
  .hub-filters, .hub-chips { flex-wrap:nowrap; overflow-x:auto; scrollbar-width:none; padding-bottom:.2rem; }
  .hub-filters::-webkit-scrollbar, .hub-chips::-webkit-scrollbar { display:none; }
  .hub-fchip, .hub-chip { flex:none; }
  /* Tap targets: 38px minimum on anything you're expected to hit with a thumb. */
  .hub-mini-b, .hub-more, .hub-open, .rl-actf { min-height:38px; display:inline-flex; align-items:center; }
  .rl-act { grid-template-columns:auto 1fr auto; gap:.7rem .8rem; padding:12px 13px; }
  .rl-act__rank { display:none; }
  /* The row is ~300px wide on a phone — every pixel the side column takes is a
     pixel of action title. Label off, arrow only. */
  .hub-lbl-sm { display:none; }
  .rl-act__side { flex-direction:column; align-items:flex-end; gap:.4rem; }
  .rl-act .hub-open--sm { padding:.3rem .45rem; }
  .rl-actcopy__l { display:none; }
  .rl-actcopy { margin-left:0; }
  .rl-actbar { gap:.5rem; }
  .rl-actfilters { flex:1; overflow-x:auto; scrollbar-width:none; flex-wrap:nowrap; }
  .rl-actfilters::-webkit-scrollbar { display:none; }
  .rl-actf { flex:none; }
}

/* ── Boot guard ─────────────────────────────────────────────────────────────
   The "we're loading / we couldn't load" panel that boot-guard.js paints. It has
   to be styled here rather than inline because the guard runs before any module
   does, and its whole job is to be legible when the app is not working. */
.bootg { max-width: 30rem; margin: 4rem auto; padding: 2rem 1.75rem; text-align: center;
  background: var(--bg-card); border: 1px solid var(--border); border-radius: 16px; }
.bootg[hidden] { display: none; }   /* author display would defeat the attribute */
.bootg__spin { width: 26px; height: 26px; margin: 0 auto 1rem; border-radius: 50%;
  border: 2px solid var(--border-light); border-top-color: var(--accent);
  animation: bootg-spin 0.7s linear infinite; }
@keyframes bootg-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .bootg__spin { animation-duration: 2.4s; } }
.bootg__msg { margin: 0; color: var(--text-secondary); font-size: 0.95rem; line-height: 1.5; }
.bootg__msg strong { color: var(--text); }
.bootg__sub { margin: 0.5rem 0 0; color: var(--text-muted); font-size: 0.85rem; line-height: 1.5; }
.bootg__acts { display: flex; gap: 0.75rem; justify-content: center; align-items: center;
  flex-wrap: wrap; margin: 1.25rem 0 0; }
.bootg__btn { font: inherit; font-size: 0.88rem; font-weight: 600; cursor: pointer;
  padding: 0.6rem 1.1rem; border-radius: 10px; border: 0;
  background: var(--accent-fill); color: var(--accent-ink); }
.bootg__link { font-size: 0.88rem; color: var(--text-muted); }
.bootg.is-stuck { border-color: rgba(var(--amber-rgb), 0.4); }

/* ── "New Foundation" — the free-tier entry point in the account nav ── */
.account-subnav__link--cta {
  color: var(--btn-ink, #f4ffe0); background: var(--btn-fill, #3f5c0b);
  border-radius: 999px; padding: .3rem .85rem; font-weight: 600;
}
.account-subnav__link--cta:hover { background: color-mix(in srgb, var(--btn-fill, #3f5c0b) 88%, #fff); color: var(--btn-ink, #f4ffe0); }
.account-subnav__link--cta[aria-current="page"] { outline: none; }
.acct-menu__link--cta { color: var(--rl-accent, var(--accent)); font-weight: 600; }

/* ── The first wait (crawl hub, foundation building) ──────────────────────
   The stretch where a first-cycle customer is watching us work is the page's
   one guaranteed audience, so it gets motion and a map instead of a price
   card: the build readout's phrase rotates (data-build-ticker), the fill bar
   sweeps, and the hub-wait strip explains the coming stages in their terms.
   All motion is decorative — reduced-motion turns it off wholesale. */
.hub-live--motion .hub-live__fill {
  background: linear-gradient(90deg, var(--hub-info), var(--sky-ink) 35%, rgba(var(--accent-rgb), .75) 50%, var(--sky-ink) 65%, var(--hub-info));
  background-size: 220% 100%;
  animation: hub-sweep 2.8s linear infinite;
}
@keyframes hub-sweep { from { background-position: 200% 0 } to { background-position: -20% 0 } }
[data-build-ticker] { display: inline-block; transition: opacity .26s ease, transform .26s ease; }
[data-build-ticker].is-swapping { opacity: 0; transform: translateY(3px); }

.hub-wait { margin: 1.2rem 0 1.4rem; }
.hub-wait__k {
  font: 600 .68rem/1 var(--mono, ui-monospace, monospace);
  letter-spacing: .09em; text-transform: uppercase;
  color: var(--rl-accent, var(--accent)); margin-bottom: .7rem;
}
.hub-wait__grid {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: .7rem;
}
@media (max-width: 900px) { .hub-wait__grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { .hub-wait__grid { grid-template-columns: 1fr; } }
.hub-wait__card {
  position: relative; border-radius: 16px; padding: .9rem 1rem 1rem;
  border: 1px solid var(--border);
  background: linear-gradient(158deg, #17181b 0%, #121214 55%, #0e0e10 100%);
  animation: hub-wait-in .55s ease both;
  animation-delay: calc(var(--i, 0) * 120ms);
  transition: transform .18s ease, border-color .18s ease;
}
.hub-wait__card:hover { transform: translateY(-2px); border-color: var(--border-light); }
.hub-wait__card::before {
  content: ""; position: absolute; top: 0; left: 16px; right: 16px; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(var(--accent-rgb), .3), transparent);
}
.hub-wait__n {
  font: 600 .66rem/1 var(--mono, ui-monospace, monospace);
  color: var(--text-muted); letter-spacing: .08em;
}
.hub-wait__card b { display: block; margin: .35rem 0 .3rem; font-size: .92rem; color: var(--text); }
.hub-wait__card p { margin: 0; font-size: .8rem; line-height: 1.5; color: var(--text-muted); }
.hub-wait__sub { margin: .75rem 0 0; font-size: .8rem; color: var(--text-muted); max-width: 62ch; }
@keyframes hub-wait-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .hub-live--motion .hub-live__fill { animation: none; }
  .hub-wait__card { animation: none; }
  [data-build-ticker] { transition: none; }
}

/* ── themes: the signal-card family is art-directed per theme ─────────────
   These four surfaces are deliberate dark-object gradients (premium card
   look), so each theme gets its own explicit art direction instead of
   token math. Dark (no data-theme) keeps the original values above. ── */
/* THE CARD HAS TO READ AS A CARD ON THE PAPER. The first light pass gave the
   card a paper-to-paper gradient (#fdfcf8 to #efece2) and the secondary card
   an even closer one (#fbfaf5 to #f4f1e9), both under a 1px hairline within
   two or three shades of the #faf9f6 page. Against that ground the edge did
   not resolve at all: the only outlines on the page were the door rows INSIDE
   the card, so the doors read as the cards and the cards read as the page.
   Now every card is plain white, lifted off the cardstock by a rule one step
   darker than --border-light and a soft drop shadow, on both the primary and
   the secondary card. */
[data-theme="light"] .rl-signal, [data-theme="light"] .rl-signal--sec {
  background: #ffffff;
  border-color: #b9b4a5;
  box-shadow: 0 1px 3px rgba(28, 28, 24, .10), 0 18px 40px -22px rgba(28, 28, 24, .38);
}
/* The footer rule and the door rows were drawn in --border (#e5e2d9), which
   on the white card is as faint as the card edge was on the page. */
[data-theme="light"] .rl-signal__foot { border-top-color: var(--border-light); }
[data-theme="light"] .rl-quick__chip { border-color: var(--border-light); background: #fbfaf7; }
[data-theme="light"] .rl-empty { background: linear-gradient(180deg, #f6f4ee, var(--bg-secondary)); }
[data-theme="light"] .hub-wait__card { background: linear-gradient(158deg, #fdfcf8 0%, #f7f5ee 55%, #f0ede4 100%); }
[data-theme="terminal"] .rl-signal { background: linear-gradient(158deg, #0e1a0e 0%, #0a140a 46%, #060f06 100%); }
[data-theme="terminal"] .rl-signal--sec { background: linear-gradient(158deg, #0c160c, #0a140a); }
[data-theme="terminal"] .rl-empty { background: linear-gradient(180deg, #0c160c, var(--bg-secondary)); }
[data-theme="terminal"] .hub-wait__card { background: linear-gradient(158deg, #0e1a0e 0%, #0a140a 55%, #071007 100%); }

/* ── the crawl card on a phone ─────────────────────────────────────────────
   .rl-signal__head is one non-wrapping row — brand tile, name, cycle pill, and
   a meta column pushed right by margin-left:auto — and it had no phone rules at
   all. At 320px it measured 237px of space holding 337px of content, so the
   Share control sat ~277px past the right edge. An ancestor clips rather than
   scrolls, so nothing looked broken: the control was simply not there, which is
   the worst way for a feature to be missing. Reported from a phone 2026-08-29.

   Wrapping is the whole fix. Identity on the first row, the meta row beneath it
   at full width and left-aligned, because a right-aligned column of one item on
   a 320px screen is just an indent. */
@media (max-width: 700px) {
  .rl-signal__head { flex-wrap: wrap; gap: 10px; }
  .rl-signal__head .brand-avatar { width: 44px; height: 44px; border-radius: 12px; }
  .rl-signal__head .brand-avatar__mono { font-size: 1.1rem; }
  .rl-signal__idname { flex: 1 1 auto; min-width: 0; font-size: 1.06rem; gap: 7px; flex-wrap: wrap; }
  .rl-signal__idname > * { min-width: 0; }
  .rl-signal__meta {
    margin-left: 0; flex: 1 0 100%;
    flex-direction: row; align-items: center; justify-content: flex-start;
    text-align: left; gap: 10px; flex-wrap: wrap;
  }
  /* The share control is a real action, not a caption. */
  .rl-sharebtn { min-height: 44px; padding-inline: 0.7rem; }

  /* .rl-readout__num is flex:none, so the column holding the headline number
     AND the status line could not shrink, and the caption carried a 34ch
     max-width that outruns a 320px card. The status line is the sentence
     telling the customer what to do next — the one string on this card that
     must never be the one clipped. */
  .rl-readout { gap: 12px; }
  .rl-readout__num { flex: 1 1 auto; min-width: 0; }
  .rl-readout__cap { max-width: none; }

  /* The remaining rows on the card are the same shape: a flex row that cannot
     wrap, holding a label and a value that together outrun 320px. .rl-ctaline
     already wraps and only needed its children allowed to shrink. */
  .rl-collab { flex-wrap: wrap; min-width: 0; }
  .rl-collab__lbl { min-width: 0; overflow-wrap: anywhere; }
  .rl-ctaline { min-width: 0; }
  .rl-ctaline > * { min-width: 0; max-width: 100%; }

  /* Five equal grid columns are ~54px on a 320px card, and "FOUNDATIONS" at
     10px mono is wider than that — so the stepper's outer labels ran past their
     cells and into each other (visible in the report: the last two labels
     collided and their dotted "locked" underline ran on as one line). Smaller
     and tighter, centred in the cell, and never broken mid-word: a label that
     hyphenates is worse than one that is small. */
  .rl-track__nodes { padding-top: 22px; }
  .rl-stop__lbl {
    font-size: .52rem; letter-spacing: .02em; line-height: 1.2;
    text-align: center; word-break: keep-all; hyphens: none;
    max-width: 100%; overflow: hidden; text-overflow: ellipsis;
  }
}

/* ── the hub as a directory (2026-09-06) ──────────────────────────────────── */
.hub-stats--vis .hub-stat--hero .hub-stat__v { color: var(--hub-accent, var(--accent)); }
.hub-engs { margin-top: .9rem; display: grid; gap: .35rem; }
.hub-eng { display: grid; grid-template-columns: 92px minmax(0, 1fr) 44px; gap: .6rem; align-items: center; text-decoration: none; color: inherit; font-size: .84rem; min-height: 36px; }
.hub-eng__n { font-family: var(--mono); font-size: .66rem; letter-spacing: .06em; text-transform: uppercase; color: var(--text-secondary); }
.hub-eng__t { display: block; height: 8px; background: var(--border); border-radius: 4px; overflow: hidden; }
.hub-eng__t i { display: block; height: 100%; border-radius: 4px; background: var(--rl-blue, #7aa6f5); }
.hub-eng--chatgpt .hub-eng__t i { background: #3fbf86; } .hub-eng--claude .hub-eng__t i { background: #e8965a; } .hub-eng--gemini .hub-eng__t i { background: #7aa6f5; } .hub-eng--perplexity .hub-eng__t i { background: #5ed3c8; }
.hub-eng__v { font-family: var(--mono); font-size: .76rem; text-align: right; color: var(--text-muted); }
.hub-trend { margin-top: .9rem; max-width: 340px; }
.hub-lede--tension { margin-top: .9rem; }
.hub-lede--tension b { color: var(--text); }
.hub-plan__prog { display: flex; align-items: center; gap: .8rem; }
.hub-plan__bar { flex: 1; height: 8px; background: var(--border); border-radius: 4px; overflow: hidden; }
.hub-plan__bar i { display: block; height: 100%; background: var(--hub-accent, var(--accent)); }
.hub-act--link { grid-template-columns: auto minmax(0, 1fr) auto auto; text-decoration: none; color: inherit; min-height: 44px; }
.hub-act--link:hover .hub-act__t { color: var(--hub-accent, var(--accent)); }
.hub-pri { font-family: var(--mono); font-size: .6rem; letter-spacing: .08em; text-transform: uppercase; padding: .15rem .4rem; border-radius: 4px; background: var(--bg-card-hover); color: var(--text-muted); }
.hub-pri--critical { background: rgba(239,68,68,.15); color: #f8a5a0; } .hub-pri--high { background: rgba(245,158,11,.15); color: #f9c77a; }
[data-theme="light"] .hub-pri--critical { color: #b91c1c; } [data-theme="light"] .hub-pri--high { color: #a16207; }
/* On a phone the account's tab bar is the navigation; the hub's own floating
   name bar was a third fixed strip on top of the operator bar and the nav. */
@media (max-width: 700px) { .hub-mini { display: none !important; } }

/* ── the track's linked stops read as buttons (2026-09-06) ─────────────────── */
.rl-track:not(.rl-track--sm) .rl-node { width: 36px; height: 36px; font-size: .82rem; }
.rl-track:not(.rl-track--sm) .rl-track__nodes::before, .rl-track:not(.rl-track--sm) .rl-track__fill { top: calc(26px + 18px); }
.rl-track:not(.rl-track--sm) .rl-stop { gap: 8px; }
.rl-stop.is-link .rl-node { box-shadow: 0 0 0 3px rgba(var(--accent-rgb), .14), 0 2px 8px rgba(0,0,0,.25); }
.rl-stop.is-link .rl-stop__lbl { color: var(--text-secondary); }
.rl-stop__go { font-family: var(--mono); font-size: .6rem; letter-spacing: .06em; text-transform: uppercase; color: var(--accent); margin-top: -4px; opacity: .9; }
.rl-stop.is-link:hover .rl-stop__go, .rl-stop.is-link:focus-visible .rl-stop__go { text-decoration: underline; text-underline-offset: 3px; opacity: 1; }
.rl-stop.is-link:hover .rl-node { transform: translateY(-1px); }
@media (max-width: 640px) { .rl-stop__go { font-size: .55rem; } .rl-track:not(.rl-track--sm) .rl-node { width: 32px; height: 32px; } .rl-track:not(.rl-track--sm) .rl-track__nodes::before, .rl-track:not(.rl-track--sm) .rl-track__fill { top: calc(26px + 16px); } }

/* the card or section a viewer's Back landed on */
.is-return { animation: rl-return 1.6s ease-out; }
@keyframes rl-return { 0% { box-shadow: 0 0 0 3px rgba(var(--accent-rgb), .55); } 100% { box-shadow: 0 0 0 3px rgba(var(--accent-rgb), 0); } }
@media (prefers-reduced-motion: reduce) { .is-return { animation: none; } }

/* the card's foot: the crawl page and the report file, beside Share access */
.rl-signal__links { display: inline-flex; gap: .35rem; flex-wrap: wrap; align-items: center; margin-right: auto; }
.rl-signal__link { display: inline-flex; align-items: center; gap: .35rem; padding: .4rem .7rem; border-radius: 10px; border: 1px solid var(--border-light); color: var(--text-secondary); font-size: .82rem; text-decoration: none; min-height: 36px; }
.rl-signal__link:hover { border-color: rgba(var(--accent-rgb), .45); color: var(--text); }
@media (max-width: 640px) { .rl-signal__links { width: 100%; } .rl-signal__link { flex: 1; justify-content: center; } }

/* find a crawl: only drawn past three crawls */
.rl-search { display: inline-flex; align-items: center; gap: .45rem; padding: 0 .7rem; min-height: 38px; border: 1px solid var(--border-light); border-radius: 10px; background: var(--bg-card); color: var(--text-muted); }
.rl-search svg { width: 15px; height: 15px; stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; flex: none; }
.rl-search input { background: transparent; border: 0; outline: 0; color: var(--text); font: inherit; font-size: .9rem; width: 12rem; min-width: 0; }
.rl-search input::placeholder { color: var(--text-faint); }
.rl-search:focus-within { border-color: rgba(var(--accent-rgb), .5); }
.rl-search__none { color: var(--text-muted); font-size: .92rem; padding: 1.2rem 0; }
.rl-search-hide { display: none !important; }
@media (max-width: 640px) { .rl-search { width: 100%; } .rl-search input { width: 100%; } }

/* ── section heads as doors (2026-09-06) ─────────────────────────────────── */
.hub-ico { width: 18px; height: 18px; stroke: var(--hub-accent, var(--accent)); fill: none; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; vertical-align: -3px; margin-right: .45rem; flex: none; }
.hub-ico--btn { width: 15px; height: 15px; stroke: currentColor; margin-right: .35rem; vertical-align: -2px; }
.rl-hub .hub-sec__t h2 { display: flex; align-items: center; }
.hub-open--door { display: inline-flex; align-items: center; background: var(--accent-dim, rgba(200,255,0,.12)); border-color: rgba(var(--accent-rgb), .5); color: var(--text); font-weight: 600; padding: .45rem .85rem; min-height: 38px; }
.hub-open--door:hover { background: var(--accent-fill, var(--accent)); color: var(--accent-ink, #09090b); border-color: var(--accent-fill, var(--accent)); }
.hub-open--door:hover .hub-ico--btn { stroke: currentColor; }
@media (max-width: 640px) { .hub-open--door { width: 100%; justify-content: center; min-height: 44px; } }

/* the primary action row under the score
   The one thing to press on the card, so it is drawn as a full-width bar and
   it is the only filled control on the card. "View details" lives in the
   footer as a plain link (and only when it goes somewhere the bar does not). */
.rl-signal__cta { display: flex; align-items: stretch; gap: 10px; flex-wrap: wrap; margin: 16px 0 8px; }
.rl-signal__cta .rl-cta { flex: 1 1 260px; justify-content: center; min-height: 54px; padding: 0 24px; border-radius: 14px; font-size: 1.02rem; font-weight: 700;
  background: var(--accent-fill, var(--accent)); color: var(--accent-ink, #09090b); border-color: var(--accent-fill, var(--accent));
  box-shadow: 0 10px 22px -14px rgba(0,0,0,.45); }
.rl-signal__cta .rl-cta:hover { filter: brightness(1.04); transform: translateY(-1px); box-shadow: 0 10px 24px -12px rgba(0, 0, 0, .45); }
.rl-signal__vd { display: inline-flex; align-items: center; min-height: 36px; color: var(--text-secondary); font-size: .85rem; font-weight: 500;
  text-decoration: underline; text-underline-offset: 3px; text-decoration-color: rgba(var(--ink-rgb), .3); }
.rl-signal__vd:hover { color: var(--text); text-decoration-color: currentColor; }

/* ── the client's mark on the card, the crawl page and the reader ─────────── */
.rl-brandlink { display: inline-flex; text-decoration: none; flex: none; }
.brand-avatar--card { width: 54px; height: 54px; border-radius: 14px; background: #fff; box-shadow: 0 2px 10px rgba(0,0,0,.35), 0 0 0 1px rgba(255,255,255,.06); }
.brand-avatar--card .brand-avatar__mono { font-size: 1.35rem; color: #111; }
.brand-avatar--card .brand-avatar__img { padding: 8px; }
.brand-avatar--row { width: 34px; height: 34px; border-radius: 9px; background: #fff; }
.brand-avatar--row .brand-avatar__mono { font-size: .95rem; color: #111; }
.brand-avatar--row .brand-avatar__img { padding: 5px; }
.brand-avatar--hub { width: 56px; height: 56px; border-radius: var(--hub-r-sm, 14px); background: #fff; box-shadow: 0 2px 12px rgba(0,0,0,.4); }
.brand-avatar--hub .brand-avatar__mono { font-size: 1.4rem; color: #111; }
.brand-avatar--hub .brand-avatar__img { padding: 8px; }
@media (max-width: 640px) { .brand-avatar--card, .brand-avatar--hub { width: 46px; height: 46px; } .brand-avatar--card .brand-avatar__mono, .brand-avatar--hub .brand-avatar__mono { font-size: 1.15rem; } }

.brand-avatar--mini { width: 22px; height: 22px; border-radius: 5px; background: #fff; flex: none; box-shadow: 0 1px 4px rgba(0,0,0,.35); }
.brand-avatar--mini .brand-avatar__mono { font-size: .72rem; color: #111; }
.brand-avatar--mini .brand-avatar__img { padding: 2px; }

/* ── Price under the lock-in CTA ───────────────────────────────────────────── */
.rl-cta__sub { order: 3; flex-basis: 100%; margin-top: -6px; font-size: .78rem; color: var(--muted); letter-spacing: .01em; }

/* ── "How this works" strip on Home (first-time, until the first report) ──── */
.rl-how { border: 1px solid var(--line); border-radius: 14px; padding: 16px 18px 14px; margin: 0 0 18px; background: var(--bg-2, var(--surface, transparent)); }
.rl-how__head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 10px; }
.rl-how__x { appearance: none; background: none; border: 1px solid var(--line); border-radius: 999px; color: var(--text); font: inherit; font-size: .8rem; padding: 4px 12px; cursor: pointer; }
.rl-how__x:hover { border-color: var(--text); }
.rl-how__steps { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px 18px; }
.rl-how__steps li { display: flex; gap: 10px; align-items: flex-start; min-width: 0; }
.rl-how__steps b { display: block; font-size: .92rem; margin-bottom: 2px; }
.rl-how__steps li > div > span { display: block; font-size: .82rem; line-height: 1.45; color: var(--muted); }
.rl-how__n { flex: none; width: 22px; height: 22px; border-radius: 50%; display: grid; place-items: center; font-size: .72rem; font-weight: 700; background: var(--accent-fill, var(--accent)); color: var(--accent-ink, #09090b); }
.rl-how__foot { margin: 12px 0 0; font-size: .82rem; color: var(--muted); }
@media (max-width: 860px) { .rl-how__steps { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 480px) { .rl-how__steps { grid-template-columns: 1fr; } .rl-how { padding: 14px; } }

/* The Voice of Customer jump sits alone under the evidence panel, not in the jumper grid. */
.hub-jump--voc { margin-top:.6rem; }

/* ── The buyer's voice has its own hue (2026-09-06) ────────────────────────
   Violet, the one hue the account had not spent: wherever it appears, a buyer
   said it. Used for the calls link on the cards, the crawl page's calls door
   and jump, and the reader's door. */
:root { --rl-voice:#b9a5ff; --rl-voice-soft:rgba(185,165,255,.14); --rl-voice-line:rgba(185,165,255,.45); }
[data-theme="light"] { --rl-voice:#5b3fc4; --rl-voice-soft:rgba(91,63,196,.1); --rl-voice-line:rgba(91,63,196,.4); }
.rl-signal__link--voc, .rl-signal__link--calls { color:var(--rl-voice); }
/* Same step-down as the Share control: the dashed pill made this the loudest
   thing in the footer. Plain voice-colored text; the outline arrives on hover. */
.rl-signal__link--calls { border:1px solid transparent; border-radius:999px; padding:.18rem .6rem; }
.rl-signal__link--voc:hover, .rl-signal__link--calls:hover { color:var(--text,#f4f4f5); border-color:var(--rl-voice); }
.rl-hub a.hub-lede--calls { border-style:dashed; border-color:var(--rl-voice-line); }
.rl-hub a.hub-lede--calls .hub-lede__go, .hub-jump--calls .hub-jump__go, .hub-jump--voc .hub-jump__l { color:var(--rl-voice); }
.hub-jump--calls { border-style:dashed; border-color:var(--rl-voice-line); }
