/* Market Products — shared styles for /private-market-products and /public-market-products.
   Stage colours (--c-<stage>) are injected per catalog by market-products-app.js. */
    :root { --bg:#000000; --panel:#161b22; --panel2:#0d1117; --line:#30363d; --line2:#21262d; --text:#e6edf3; --muted:#8b949e; --dim:#6e7681; --accent:#EA580C; --green:#3fb950; --red:#f85149; --amber:#e3b341; --blue:#58a6ff; --purple:#a371f7;
      }
    * { box-sizing:border-box; }
    body { margin:0; background:var(--bg); color:var(--text); font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif; }
    .wrap { max-width:1240px; margin:0 auto; padding:26px 18px 60px; }
    h1 { font-size:28px; margin:0 0 6px; letter-spacing:-.01em; } h1 .accent { color:var(--accent); }
    .subtitle { color:var(--muted); font-size:14px; margin:0 0 14px; line-height:1.55; max-width:860px; }
    .stats { display:flex; gap:8px; flex-wrap:wrap; margin-bottom:18px; }
    .stat { font-size:11.5px; color:var(--muted); border:1px solid var(--line); background:var(--panel); border-radius:999px; padding:4px 11px; }
    .stat b { color:#f0f6fc; font-family:ui-monospace,monospace; }
    /* A stat that maps to a filter is a button: it says so on hover and holds
       an active state, so the strip reads as a control rather than decoration. */
    button.stat { font:inherit; font-size:11.5px; cursor:pointer; transition:border-color .15s ease, background .15s ease, transform .15s ease; }
    button.stat:hover { border-color:var(--accent,#EA580C); background:#161b22; transform:translateY(-1px); }
    button.stat:focus-visible { outline:2px solid var(--accent,#EA580C); outline-offset:2px; }
    button.stat[aria-pressed="true"] { border-color:var(--accent,#EA580C); background:rgba(234,88,12,.12); color:#f0f6fc; }
    button.stat[aria-pressed="true"] b { color:var(--accent,#EA580C); }
    button.stat .x { margin-left:6px; opacity:.7; font-weight:700; }
    @media (prefers-reduced-motion: reduce) { button.stat { transition:none; } button.stat:hover { transform:none; } }

    /* ── Search core ── */
    .search { position:relative; max-width:720px; margin-bottom:12px; }
    .search input { width:100%; background:#010409; border:1px solid var(--line); color:var(--text); border-radius:12px; padding:14px 96px 14px 46px; font-size:16px; outline:none; transition:border-color .15s, box-shadow .15s; }
    .search input:focus { border-color:var(--accent); box-shadow:0 0 0 3px rgba(234,88,12,.18); }
    .search .ico { position:absolute; left:16px; top:50%; transform:translateY(-50%); color:var(--dim); font-size:16px; pointer-events:none; }
    .search .kbd { position:absolute; right:14px; top:50%; transform:translateY(-50%); display:flex; gap:6px; align-items:center; }
    .search kbd { font-family:ui-monospace,monospace; font-size:10.5px; color:var(--dim); border:1px solid var(--line); border-radius:5px; padding:1px 6px; background:var(--panel); }
    .search button.clr { display:none; background:transparent; border:0; color:var(--muted); font-size:13px; cursor:pointer; padding:2px 6px; }
    .search.has button.clr { display:inline-block; } .search.has .kbd kbd { display:none; }
    .hits { font-size:12px; color:var(--muted); min-height:16px; margin-bottom:10px; }
    .hits b { color:#f0f6fc; }

    /* ── Filter chips ── */
    .filters { display:flex; gap:6px; flex-wrap:wrap; align-items:center; margin-bottom:14px; }
    .filters .flabel { font-size:10.5px; color:var(--dim); text-transform:uppercase; letter-spacing:.5px; margin-right:2px; }
    .chip { display:inline-flex; align-items:center; gap:6px; background:var(--panel); border:1px solid var(--line); color:#c9d1d9; border-radius:999px; padding:4px 11px; font-size:11.5px; cursor:pointer; user-select:none; font-family:inherit; transition:border-color .12s, background .12s; }
    .chip .dot { width:8px; height:8px; border-radius:50%; display:inline-block; background:var(--dotc,#8b949e); }
    .chip:hover { border-color:var(--accent); }
    .chip[aria-pressed="true"] { background:rgba(234,88,12,.14); border-color:var(--accent); color:#fff; }
    .chip .n { color:var(--dim); font-family:ui-monospace,monospace; font-size:10px; }
    .sep { width:1px; height:18px; background:var(--line2); margin:0 4px; }
    .views { margin-left:auto; display:inline-flex; border:1px solid var(--line); border-radius:9px; overflow:hidden; }
    .views button { background:transparent; border:0; color:var(--muted); padding:6px 12px; font-size:11.5px; font-weight:800; letter-spacing:.03em; cursor:pointer; font-family:inherit; }
    .views button[aria-pressed="true"] { background:rgba(88,166,255,.15); color:var(--blue); }
    @media (max-width:760px){ .views { margin-left:0; width:100%; } .views button { flex:1; } }

    /* ── Constellation ── */
    .layout { display:grid; grid-template-columns:minmax(0,1fr) 300px; gap:16px; align-items:stretch; }
    @media (max-width:960px){ .layout { grid-template-columns:1fr; } }
    .stage-box { position:relative; background:radial-gradient(ellipse at center, #0b1220 0%, #000 70%); border:1px solid var(--line); border-radius:16px; overflow:hidden; }
    .stage-box svg { display:block; width:100%; height:auto; }
    .orbit { fill:none; stroke:#1c2330; stroke-width:1; }
    .orbit.dashed { stroke-dasharray:3 9; stroke:#263040; transform-origin:700px 566px; animation:spin 140s linear infinite; }
    .orbit.dashed.r { animation-direction:reverse; animation-duration:200s; }
    @media (prefers-reduced-motion: reduce) { .orbit.dashed { animation:none; } }
    .arc { fill:none; stroke-width:3; opacity:.85; stroke-linecap:round; }
    .arclbl { font-size:12.5px; font-weight:800; letter-spacing:.06em; text-transform:uppercase; fill:#c9d1d9; }
    .arclbl.dim { fill:#3d4551; }
    .spoke { stroke:#1a2230; stroke-width:1; }
    .node { cursor:pointer; transition:opacity .18s; -webkit-user-select:none; user-select:none; }
    .node circle.bg { fill:#0d1117; stroke:#30363d; stroke-width:1.25; transition:stroke .12s, r .12s; }
    .node:hover circle.bg, .node.focus circle.bg { stroke:var(--nc,#EA580C); stroke-width:2; }
    .node circle.halo { fill:var(--nc,#EA580C); opacity:0; transition:opacity .18s; }
    .node:hover circle.halo, .node.focus circle.halo { opacity:.16; }
    /* Never the browser's default focus ring on the GROUP. A node's box spans
       the icon, its leader line and its rotated label, so the ring paints a
       rectangle across a chunk of the wheel — and clicking a product called
       .focus() on it, which is why a plain click drew one. Keyboard focus
       still has to be visible, so the indicator moves onto the icon itself:
       correctly shaped, and it reads as "this node" rather than "this
       rectangle". :focus-visible is not matched after a pointer click, so a
       mouse user sees the selection styling and nothing else. */
    .node:focus { outline:none; }
    .node:focus-visible circle.bg { stroke:#fff; stroke-width:2.5; }
    .node:focus-visible circle.halo { opacity:.3; }
    .node text.em { font-size:14px; text-anchor:middle; dominant-baseline:central; pointer-events:none; }
    /* The NAME is the readable half of a node — the icon is a 34px circle in a
       ring of 67 of them, so most attempts to click a product land on its
       label. With pointer-events:none the label was not just inert: the click
       fell through to the bare <svg>, which the map reads as "clicked the
       empty sky" and UNPINS the inspector. Clicking a product's name cleared
       it. Label and leader line are now part of the node's hit area, so a
       single click on either reads it and a double-click on either opens it. */
    .node text.nm { font-size:10.5px; fill:#c9d1d9; pointer-events:auto; font-weight:600; dominant-baseline:central; transition:fill .12s; }
    .node:hover text.nm, .node.focus text.nm { fill:#fff; font-weight:800; }
    .node line.leader { stroke:#2a3340; stroke-width:1; pointer-events:auto; }
    .node:hover line.leader, .node.focus line.leader { stroke:var(--nc,#EA580C); }
    .node.tier circle.tierdot { fill:var(--tc,#3fb950); stroke:#0d1117; stroke-width:1.5; }
    /* Filtered-out nodes stay unclickable. pointer-events on the GROUP does not
       win over an explicit value on a child, so the children opted back in
       above have to be opted out again here. */
    .node.miss { opacity:.08; pointer-events:none; }
    .node.miss text.nm, .node.miss line.leader { pointer-events:none; }
    .node.hit circle.halo { opacity:.22; }
    .core text { text-anchor:middle; }
    .core .q { font-size:14px; font-weight:800; fill:#f0f6fc; }
    .core .k { font-size:10px; fill:#6e7681; text-transform:uppercase; letter-spacing:.5px; }
    .core .cnt { font-size:30px; font-weight:900; fill:var(--accent); font-family:ui-monospace,monospace; }
    .gctl { position:absolute; top:10px; right:10px; display:flex; gap:6px; z-index:3; }
    .gctl button { height:30px; padding:0 10px; border-radius:8px; border:1px solid var(--line); background:rgba(13,17,23,.85); color:#c9d1d9; font-size:11.5px; font-weight:700; cursor:pointer; font-family:inherit; }
    .gctl button:hover { border-color:var(--accent); color:#f0f6fc; }
    /* The legend used to float in the ring's bottom-left corner, which is
       where the bottom stage label sits — at 1500px "🤝 Transact" landed
       inside the legend box. In normal flow under the SVG it cannot collide
       with the constellation at any width or catalog size. */
    .legend { display:flex; gap:10px 14px; flex-wrap:wrap; font-size:10.5px; color:var(--muted); border-top:1px solid var(--line); background:rgba(13,17,23,.55); padding:9px 12px; }
    .legend .sw { display:inline-block; width:9px; height:9px; border-radius:50%; margin-right:5px; vertical-align:-1px; }

    /* inspector */
    .panel { background:var(--panel); border:1px solid var(--line); border-radius:16px; padding:16px; display:flex; flex-direction:column; min-height:0; }
    .panel .ph { font-size:10px; text-transform:uppercase; letter-spacing:.06em; color:var(--dim); font-weight:800; margin-bottom:10px; }
    .insp-empty { color:var(--dim); font-size:12.5px; line-height:1.6; }
    .insp-empty b, .insp-empty kbd { color:#c9d1d9; }
    .insp-empty kbd { font-family:ui-monospace,monospace; border:1px solid var(--line); border-radius:4px; padding:0 5px; }
    .opnhint { font-size:10.5px; color:var(--dim); margin-top:6px; text-align:center; }
    .insp .big { display:flex; align-items:center; gap:10px; margin-bottom:8px; }
    .insp .big .em { font-size:30px; width:46px; height:46px; display:flex; align-items:center; justify-content:center; background:var(--panel2); border:1px solid var(--line); border-radius:12px; }
    .insp .big h2 { margin:0; font-size:16px; line-height:1.25; color:#f0f6fc; }
    .insp .big .st { font-size:11px; font-weight:800; text-transform:uppercase; letter-spacing:.05em; color:var(--sc,#8b949e); }
    .insp p { font-size:12.5px; color:#c9d1d9; line-height:1.6; margin:6px 0 10px; }
    .tags { display:flex; flex-wrap:wrap; gap:5px; margin-bottom:12px; }
    .tag { font-size:10.5px; color:var(--muted); border:1px solid var(--line2); border-radius:999px; padding:2px 8px; }
    .aud { font-size:11px; color:var(--muted); margin-bottom:12px; }
    .aud b { color:#c9d1d9; font-weight:600; }
    .tier { display:inline-block; font-size:10px; font-weight:900; letter-spacing:.06em; text-transform:uppercase; border-radius:5px; padding:2px 7px; border:1px solid; }
    .tier-free { color:var(--green); border-color:rgba(63,185,80,.45); background:rgba(63,185,80,.08); }
    .tier-starter { color:var(--blue); border-color:rgba(88,166,255,.45); background:rgba(88,166,255,.08); }
    .tier-pro { color:var(--accent); border-color:rgba(234,88,12,.5); background:rgba(234,88,12,.08); }
    .tier-institutional { color:var(--purple); border-color:rgba(163,113,247,.5); background:rgba(163,113,247,.08); }
    .open { display:inline-block; background:var(--accent); color:#fff; border-radius:9px; padding:9px 16px; font-weight:800; font-size:13px; text-decoration:none; margin-top:auto; text-align:center; }
    .open:hover { filter:brightness(1.08); }
    .neighbors { margin-top:14px; border-top:1px dashed var(--line2); padding-top:10px; }
    .neighbors a { display:flex; align-items:center; gap:7px; font-size:12px; color:#c9d1d9; text-decoration:none; padding:4px 0; }
    .neighbors a:hover { color:var(--accent); }

    /* ── Pipeline ── */
    /* Seven stages in ONE sideways-scrolling row meant steps 5-7 sat off the
       right edge — the lifecycle is the point of this view, and you could not
       see the end of it. Wraps at four per row, so 7 reads as 4 + 3. */
    .pipe { display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:12px; align-items:start; padding-bottom:10px; }
    /* A 7-stage pipeline in a 4-column grid leaves an orphan row of three,
       which flows left and lands the tail stages under the wrong heads: step 6
       sat under step 2 and step 7 under step 3. Push that row flush right so
       each trailing stage sits beneath the one it follows — 5 under 2, 6 under
       3, 7 under 4. :nth-child(5):nth-last-child(3) matches the 5th column ONLY
       when the grid holds exactly seven, so the 8-stage public catalog (two
       full rows, no orphan) is untouched, and so is any future stage count.
       Scoped to the 4-column range; at 3 and 2 columns the rows divide
       differently and already read correctly. */
    @media (min-width:1181px){ .pipe > .col:nth-child(5):nth-last-child(3) { grid-column-start:2; } }
    @media (max-width:1180px){ .pipe { grid-template-columns:repeat(3,minmax(0,1fr)); } }
    @media (max-width:900px){ .pipe { grid-template-columns:repeat(2,minmax(0,1fr)); } }
    @media (max-width:620px){ .pipe { grid-template-columns:minmax(0,1fr); } }
    .col { background:var(--panel); border:1px solid var(--line); border-radius:14px; padding:12px; border-top:3px solid var(--sc,#8b949e); min-height:120px; }
    .col .ch { display:flex; align-items:center; gap:8px; margin-bottom:4px; }
    .col .ch .em { font-size:18px; }
    .col .ch h3 { margin:0; font-size:14px; color:#f0f6fc; }
    .col .ch .n { margin-left:auto; font-family:ui-monospace,monospace; font-size:11px; color:var(--dim); }
    .col .blurb { font-size:11.5px; color:var(--dim); line-height:1.5; margin:0 0 10px; }
    .col .step { font-size:9.5px; font-weight:900; letter-spacing:.1em; color:var(--sc,#8b949e); margin-bottom:6px; }
    /* Pipeline product card. Hover: the card lifts, its border and a soft
       outer glow take the stage colour, a faint stage-tinted wash sweeps in
       from the top-left, the icon tilts up, and an "Open →" affordance
       slides in at the bottom-right. Focus-visible gets the same treatment
       for keyboard users; reduced-motion keeps the colour, drops the motion. */
    .card { display:block; position:relative; overflow:hidden; background:var(--panel2); border:1px solid var(--line2); border-radius:10px; padding:9px 10px 9px; margin-bottom:7px; text-decoration:none; color:inherit; transition:border-color .16s ease, transform .16s ease, box-shadow .16s ease, background-color .16s ease; }
    .card::before { content:''; position:absolute; inset:0; background:linear-gradient(135deg, color-mix(in srgb, var(--sc,#EA580C) 14%, transparent) 0%, transparent 60%); opacity:0; transition:opacity .2s ease; pointer-events:none; }
    .card:hover, .card:focus-visible { border-color:var(--sc,#EA580C); transform:translateY(-2px); box-shadow:0 8px 22px rgba(0,0,0,.45), 0 0 0 1px color-mix(in srgb, var(--sc,#EA580C) 45%, transparent), 0 0 18px color-mix(in srgb, var(--sc,#EA580C) 22%, transparent); outline:none; }
    .card:hover::before, .card:focus-visible::before { opacity:1; }
    .card:active { transform:translateY(0); }
    .card .t { display:flex; align-items:center; gap:8px; position:relative; }
    .card .t .em { font-size:16px; display:inline-block; transition:transform .18s ease; }
    .card:hover .t .em, .card:focus-visible .t .em { transform:translateY(-1px) scale(1.18) rotate(-6deg); }
    .card:hover .t b, .card:focus-visible .t b { color:#fff; }
    .card .go { position:absolute; right:10px; bottom:7px; font-size:10.5px; font-weight:800; letter-spacing:.04em; color:var(--sc,#EA580C); opacity:0; transform:translateX(6px); transition:opacity .18s ease, transform .18s ease; pointer-events:none; }
    .card:hover .go, .card:focus-visible .go { opacity:1; transform:translateX(0); }
    .card:hover .d, .card:focus-visible .d { padding-right:52px; }
    @media (prefers-reduced-motion: reduce) { .card, .card::before, .card .t .em, .card .go { transition:none; } .card:hover, .card:focus-visible { transform:none; } .card:hover .t .em { transform:none; } }
    .card .t b { font-size:13px; color:#f0f6fc; flex:1; }
    .card .d { font-size:11.5px; color:var(--muted); line-height:1.5; margin-top:4px; position:relative; transition:padding-right .18s ease; }
    .card.miss { display:none; }
    .col .none { display:none; font-size:11.5px; color:var(--dim); font-style:italic; padding:6px 0; }
    .col.empty .none { display:block; }

    /* ── List ── */
    .list { display:flex; flex-direction:column; gap:2px; }
    .row { display:grid; grid-template-columns:34px minmax(0,1.3fr) 120px minmax(0,2.2fr) 110px; gap:12px; align-items:center; padding:9px 10px; border-radius:8px; text-decoration:none; color:inherit; border:1px solid transparent; }
    .row:hover { background:rgba(234,88,12,.06); border-color:var(--line2); }
    .row .em { font-size:18px; text-align:center; }
    .row b { font-size:13px; color:#f0f6fc; }
    .row .stg { font-size:11px; font-weight:800; text-transform:uppercase; letter-spacing:.04em; color:var(--sc,#8b949e); display:flex; align-items:center; gap:6px; }
    .row .stg .dot { width:8px; height:8px; border-radius:50%; background:var(--sc,#8b949e); }
    .row .d { font-size:12px; color:var(--muted); line-height:1.45; }
    .row .tier { justify-self:end; }
    .row.miss { display:none; }
    .row.head { font-size:10px; text-transform:uppercase; letter-spacing:.06em; color:var(--dim); font-weight:800; border-bottom:1px solid var(--line2); border-radius:0; }
    .row.head:hover { background:transparent; }
    @media (max-width:760px){ .row { grid-template-columns:30px 1fr 90px; } .row .stg, .row .d { display:none; } }
    mark { background:rgba(234,88,12,.3); color:inherit; border-radius:3px; padding:0 1px; }

    .view { display:none; } .view.on { display:block; }
    .empty { text-align:center; color:var(--dim); font-size:13px; padding:40px 10px; border:1px dashed var(--line); border-radius:14px; }
    .note { font-size:11.5px; color:var(--dim); line-height:1.55; margin-top:16px; }
