/* GhostNet portal — the visual identity ported from the Streamlit app (app.py)
   it replaced. Everything from ":root" to the COMPONENT LAYER below was
   extracted mechanically from app.py's own <style> blocks, with Streamlit's
   internal selectors removed. Two things that block will not survive if it is
   ever re-extracted naively: strip CSS comments FIRST (a comment in front of a
   rule joins its selector and lets @media/@supports blocks skip the filter),
   and collapse DOUBLED braces (several style blocks sit inside f-strings, so
   "{{" is an escaped "{" — left alone it silently breaks @keyframes).

   Design spec this implements: Neo-Brutalism. #ffe17c primary, #171e19
   charcoal, #b7c6c2 sage, white UI, black text. Cabinet Grotesk extrabold
   headings, Satoshi 500 body. 2px solid black borders everywhere, hard
   shadows with ZERO blur (4px standard, 8px large), buttons that translate
   into their own shadow on hover to feel physically pressed. No gradients,
   no soft shadows, no radius above 12px. */

@import url('https://api.fontshare.com/v2/css?f[]=cabinet-grotesk@800,700&f[]=satoshi@500,700&display=swap');
:root {
        --primary:  #ffe17c;
        --charcoal: #171e19;
        --sage:     #b7c6c2;
        --white:    #ffffff;
        --black:    #000000;
        --star:     #ffbc2e;
        --line:     #272727;
        --muted-card: #f4f4f5;
        --danger:   #d92d20;
        --good:     #0f7b3d;
        --font-head: 'Cabinet Grotesk', 'Arial Black', sans-serif;
        --font-body: 'Satoshi', -apple-system, BlinkMacSystemFont, sans-serif;
        --font-mono: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
        --shadow-sm: 4px 4px 0px 0px var(--black);
        --shadow-md: 8px 8px 0px 0px var(--black);
        --shadow-lg: 12px 12px 0px 0px var(--black);
    }
h1, h2, h3, h4, h5 { font-family: var(--font-head) !important; font-weight: 800 !important; letter-spacing: -0.03em !important; color: var(--black); text-transform: uppercase; }
.neo-border { border: 2px solid var(--black); }
.neo-sm { box-shadow: var(--shadow-sm); }
.neo-md { box-shadow: var(--shadow-md); }
.neo-lg { box-shadow: var(--shadow-lg); }
.outlined-text { -webkit-text-stroke: 2px var(--black); color: transparent; }
hr { border: 0; height: 2px; background: var(--black); margin: 2.5rem 0; }
.gn-nav-wordmark { display: flex; align-items: center; gap: 10px; font-family: var(--font-head); font-weight: 800; letter-spacing: -0.03em; font-size: 1.35rem; color: var(--black); white-space: nowrap; padding: 0.35rem 0; }
.gn-nav-bolt { width: 34px; height: 34px; background: var(--black); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.gn-hero { box-sizing: border-box; position: relative; overflow: hidden; text-align: center; padding: 5rem 1rem 5rem; min-height: calc(100vh - 120px); display: flex; flex-direction: column; align-items: center; justify-content: center; background: var(--primary); border-bottom: 2px solid var(--black); box-shadow: 0 0 0 100vmax var(--primary); clip-path: inset(0 -100vmax); }
.gn-hero::before { content: ""; position: absolute; inset: 0; background-image: radial-gradient(var(--black) 10%, transparent 10%); background-size: 32px 32px; opacity: 0.1; pointer-events: none; }
.gn-hero > * { position: relative; z-index: 1; }
.gn-hero-eyebrow { display: inline-flex; align-items: center; gap: 9px; background: var(--white); border: 2px solid var(--black); padding: 6px 18px; border-radius: 999px; font-size: 0.72rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; color: var(--black); margin-bottom: 1.6rem; }
.gn-hero-title { font-family: var(--font-head); font-size: clamp(3rem, 9vw, 6.5rem); font-weight: 800; letter-spacing: -0.04em; color: var(--black); line-height: 0.95; text-transform: uppercase; margin: 0; }
.gn-hero-title .outlined-text { -webkit-text-stroke: 2px var(--black); color: transparent; }
.gn-hero-sub { color: var(--black); font-size: clamp(1.05rem, 1.8vw, 1.35rem); font-weight: 500; margin: 1.5rem auto 0; max-width: 640px; line-height: 1.45; }
.gn-hero-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 2rem; margin-top: 4rem; width: 100%; max-width: 980px; }
@media (max-width: 900px) {
  .gn-hero-stats { grid-template-columns: 1fr; }
}
.gn-hero-stat { background: var(--white); border: 2px solid var(--black); box-shadow: var(--shadow-sm); padding: 1.8rem 1.2rem; text-align: center; }
.gn-hero-stat-num { font-family: var(--font-head); font-size: 3rem; font-weight: 800; color: var(--black); letter-spacing: -0.04em; line-height: 1; }
.gn-hero-stat-label { font-size: 0.76rem; letter-spacing: 0.06em; text-transform: uppercase; color: var(--line); margin-top: 0.5rem; font-weight: 700; }
.gn-hero-scrollcue { margin-top: 3.5rem; display: flex; flex-direction: column; align-items: center; gap: 10px; color: var(--black); font-size: 0.76rem; letter-spacing: 0.12em; text-transform: uppercase; font-weight: 700; }
.gn-hero-chevron { width: 14px; height: 14px; border-right: 3px solid var(--black); border-bottom: 3px solid var(--black); transform: rotate(45deg); animation: gn-chevron-bounce 1.6s ease-in-out infinite; }
.gn-live { display: inline-flex; align-items: center; gap: 8px; background: var(--primary); border: 2px solid var(--black); padding: 5px 14px; border-radius: 999px; font-size: 0.76rem; font-weight: 700; letter-spacing: 0.06em; color: var(--black); text-transform: uppercase; }
.gn-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--good); border: 1.5px solid var(--black); animation: gn-pulse 2s infinite; flex-shrink: 0; }
@keyframes gn-pulse {
        0%   { box-shadow: 0 0 0 0 rgba(15,123,61,0.5); }
        70%  { box-shadow: 0 0 0 8px rgba(15,123,61,0); }
        100% { box-shadow: 0 0 0 0 rgba(15,123,61,0); }
    }
.gn-spinner-row { display: flex; align-items: center; gap: 10px; margin-top: -10px; }
.gn-spinner { display: inline-block; width: 18px; height: 18px; border: 3px solid rgba(0,0,0,0.2); border-top-color: var(--black); border-radius: 50%; animation: gn-spin 0.7s linear infinite; flex-shrink: 0; }
.gn-spinner-text { color: var(--black); font-size: 0.95rem; font-weight: 700; }
@keyframes gn-spin { to { transform: rotate(360deg); } }
.gn-queue-pill, .gn-turn-pill, .gn-cancel-pill { display: inline-flex; align-items: center; gap: 9px; height: 34px; padding: 0 16px; border-radius: 999px; border: 2px solid var(--black); font-size: 0.8rem; font-weight: 700; white-space: nowrap; box-sizing: border-box; line-height: 1; text-transform: uppercase; }
.gn-queue-pill { background: var(--sage); color: var(--black); }
.gn-turn-pill { background: var(--primary); color: var(--black); }
.gn-cancel-pill { background: var(--white); color: var(--danger); }
.gn-queue-pill.gn-anim-in { animation: gn-queue-in 0.4s ease-out; }
@keyframes gn-queue-in {
        from { opacity: 0; transform: translateY(-6px); }
        to   { opacity: 1; transform: none; }
    }
.gn-queue-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--black); flex-shrink: 0; margin: 0; }
@keyframes gn-turn-pop {
        0%   { transform: translate(2px,2px); }
        100% { transform: none; }
    }
@keyframes gn-cancel-out {
        0%,100% { opacity: 1; }
        50%     { opacity: 0.6; }
    }
.gn-badge { display: inline-block; padding: 6px 16px; border-radius: 999px; border: 2px solid var(--black); background: var(--white); font-size: 0.8rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; }
.gn-user-chip { padding: 12px 14px; border: 2px solid var(--black); background: var(--primary); color: var(--black) !important; font-size: 0.85rem; line-height: 1.45; font-weight: 700; }
.gn-user-chip b { color: var(--black) !important; }
@keyframes gn-chevron-bounce {
        0%, 100% { transform: rotate(45deg) translate(0, 0); opacity: 0.55; }
        50%      { transform: rotate(45deg) translate(5px, 5px); opacity: 1; }
    }
.gn-page-banner { background: var(--primary); border: 2px solid var(--black); box-shadow: var(--shadow-md); padding: 2.2rem 2rem; margin: 0.5rem 0 2.5rem; }
.gn-page-banner-eyebrow { display: inline-block; background: var(--white); border: 2px solid var(--black); padding: 5px 14px; font-size: 0.68rem; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; margin-bottom: 1rem; }
.gn-page-banner h2 { font-family: var(--font-head); font-weight: 800; font-size: clamp(1.8rem, 4.5vw, 2.8rem); letter-spacing: -0.04em; line-height: 1; margin: 0 0 0.8rem; text-transform: uppercase; color: var(--black); }
.gn-page-banner p { margin: 0; font-size: 1.02rem; line-height: 1.5; color: var(--line); font-weight: 500; max-width: 60ch; }
.gn-jrny-wrap::before, .gn-cap-band::before, .gn-final-cta::before { top: 0; }
.gn-map-head { background: var(--charcoal); border: 2px solid var(--black); box-shadow: var(--shadow-md); padding: 1.6rem; margin: 0.4rem 0 1.2rem; position: relative; overflow: hidden; }
.gn-map-head::after { content: ""; position: absolute; inset: 0; pointer-events: none; background-image: radial-gradient(var(--sage) 1px, transparent 1px); background-size: 32px 32px; opacity: 0.10; }
.gn-map-head > * { position: relative; z-index: 1; }
.gn-map-head h3 { font-family: var(--font-head); font-weight: 800; color: var(--white); font-size: clamp(1.5rem, 3.6vw, 2.2rem); letter-spacing: -0.03em; line-height: 1; margin: 0.9rem 0 0.6rem; text-transform: uppercase; }
.gn-map-head p { margin: 0; color: var(--sage); font-size: 0.95rem; max-width: 62ch; font-weight: 500; line-height: 1.5; }
.gn-map-hotdot { background: var(--danger) !important; animation: gn-map-hotpulse 1.8s infinite; }
@keyframes gn-map-hotpulse {
        0%   { box-shadow: 0 0 0 0 rgba(217,45,32,0.65); }
        70%  { box-shadow: 0 0 0 9px rgba(217,45,32,0); }
        100% { box-shadow: 0 0 0 0 rgba(217,45,32,0); }
    }
.gn-map-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; margin-bottom: 1.2rem; }
.gn-map-stat { border: 2px solid var(--black); box-shadow: var(--shadow-sm); padding: 0.9rem 1rem; background: var(--white); }
.gn-map-stat-hot { background: var(--primary); }
.gn-map-stat-label { font-size: 0.6rem; font-weight: 800; letter-spacing: 0.13em; text-transform: uppercase; color: var(--line); }
.gn-map-stat-val { font-family: var(--font-head); font-weight: 800; font-size: 1.7rem; line-height: 1.05; margin-top: 6px; color: var(--black); letter-spacing: -0.02em; }
.gn-map-stat-sub { font-size: 0.72rem; font-weight: 600; color: var(--line); margin-top: 4px; }
.gn-map-legend { display: flex; flex-wrap: wrap; align-items: stretch; margin: 1.1rem 0 0; border: 2px solid var(--black); box-shadow: var(--shadow-sm); background: var(--charcoal); }
.gn-map-legend-title { display: flex; align-items: center; padding: 0 12px; border-right: 2px solid var(--black); background: var(--primary); font-size: 0.6rem; font-weight: 800; letter-spacing: 0.13em; text-transform: uppercase; color: var(--black); }
.gn-map-legend-step { display: flex; align-items: center; gap: 7px; padding: 9px 13px; }
.gn-map-legend-sw { width: 15px; height: 15px; border: 2px solid var(--black); flex-shrink: 0; }
.gn-map-legend-lbl { font-size: 0.72rem; font-weight: 700; color: var(--white); font-variant-numeric: tabular-nums; white-space: nowrap; }
.gn-map-board { border: 2px solid var(--black); box-shadow: var(--shadow-md); background: var(--white); margin-top: 1.7rem; }
.gn-map-board-head { background: var(--charcoal); color: var(--white); font-family: var(--font-head); font-weight: 800; text-transform: uppercase; font-size: 0.95rem; padding: 0.75rem 1rem; border-bottom: 2px solid var(--black); display: flex; justify-content: space-between; align-items: center; gap: 10px; }
.gn-map-board-head span { font-family: var(--font-body); font-size: 0.66rem; font-weight: 700; letter-spacing: 0.1em; color: var(--sage); }
.gn-map-row { display: grid; grid-template-columns: 30px minmax(94px, 1.1fr) 3fr 58px; align-items: center; gap: 10px; padding: 8px 1rem; border-bottom: 2px solid var(--muted-card); }
.gn-map-row:last-child { border-bottom: none; }
.gn-map-row:hover { background: var(--muted-card); }
.gn-map-rank { font-family: var(--font-head); font-weight: 800; font-size: 0.8rem; color: var(--line); font-variant-numeric: tabular-nums; }
.gn-map-name { font-size: 0.85rem; font-weight: 700; color: var(--black); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gn-map-track { height: 14px; background: var(--muted-card); border: 2px solid var(--black); overflow: hidden; }
.gn-map-fill { height: 100%; background: var(--primary); transform-origin: left center; animation: gn-map-grow 750ms cubic-bezier(.16,.84,.44,1) both; }
.gn-map-row-hot .gn-map-fill { background: var(--star); }
.gn-map-count { text-align: right; font-family: var(--font-head); font-weight: 800; font-size: 0.9rem; color: var(--black); font-variant-numeric: tabular-nums; }
@keyframes gn-map-grow { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@media (prefers-reduced-motion: reduce) {
  .gn-map-fill { animation: none; }
  .gn-map-hotdot { animation: none; }
}
@media (max-width: 640px) {
  .gn-nav-wordmark { font-size: 0 !important; gap: 0 !important; padding: 0.3rem 0.4rem 0.3rem 0; }
  .gn-nav-bolt { width: 26px; height: 26px; }
  .gn-nav-bolt svg { width: 15px; height: 15px; }
  .gn-hero { padding: 3rem 0.5rem 3.5rem; min-height: auto; }
  .gn-hero-eyebrow { font-size: 0.6rem; padding: 6px 12px; letter-spacing: 0.08em; }
  .gn-hero-sub { font-size: 1rem; margin-top: 1.1rem; }
  .gn-hero-stats { gap: 1rem; margin-top: 2.5rem; }
  .gn-hero-stat { padding: 1.2rem 1rem; }
  .gn-hero-stat-num { font-size: 2.4rem; }
  .gn-hero-scrollcue { margin-top: 2.5rem; }
  .gn-jrny-scene { height: auto !important; }
  .gn-jrny-stage { position: relative !important; height: auto !important; padding: 2.6rem 0.5rem !important; overflow: visible; }
  .gn-jrny-caption, .gn-jrny-packet, .gn-jrny-ip-label, .gn-jrny-knock, .gn-jrny-net, .gn-jrny-ghost, .gn-jrny-caught-tag, .gn-jrny-port, .gn-jrny-progress-fill { animation: none !important; opacity: 1 !important; transform: none !important; }
  .gn-jrny-door { animation: none !important; transform: rotateY(-68deg) !important; transform-origin: left center !important; }
  .gn-jrny-port-open { background: var(--primary) !important; box-shadow: 4px 4px 0 0 var(--black); }
  .gn-jrny-net { top: 0 !important; opacity: 0.8 !important; }
  .gn-jrny-packet { position: relative !important; left: auto !important; top: auto !important; }
  .gn-jrny-canvas { height: 90px !important; width: 100% !important; }
  .gn-jrny-canvas-center { height: auto !important; min-height: 150px !important; }
  .gn-jrny-caption { margin-bottom: 1.6rem !important; }
  .gn-jrny-eyebrow { font-size: 0.62rem !important; padding: 6px 12px !important; letter-spacing: 0.08em !important; }
  .gn-jrny-caption p { font-size: 0.98rem !important; }
  .gn-jrny-portgrid { grid-template-columns: repeat(6, 30px) !important; gap: 5px !important; max-width: 100% !important; }
  .gn-jrny-port { width: 30px !important; height: 30px !important; }
  .gn-jrny-knocks { width: 100% !important; }
  .gn-jrny-knock { padding: 10px 12px !important; }
  .gn-jrny-knock-left, .gn-jrny-knock-right { align-self: stretch !important; }
  .gn-jrny-doorway { width: 110px !important; height: 160px !important; }
  .gn-jrny-door { width: 110px !important; height: 160px !important; }
  .gn-jrny-progress-track { display: none !important; }
  .gn-cap-band, .gn-final-cta { padding: 3rem 0.75rem; }
  .gn-cap-heading { margin-bottom: 2rem; }
  .gn-cap-grid { gap: 1.5rem; }
  .gn-cap-card { padding: 1.5rem 1.3rem; box-shadow: var(--shadow-sm); }
  .gn-ledger-band { padding: 3rem 0.75rem; }
  .gn-chain-node { min-width: 100%; }
  .gn-page-banner { padding: 1.6rem 1.2rem; margin-bottom: 1.8rem; }
  .gn-map-head { padding: 1.2rem 1.1rem; box-shadow: var(--shadow-sm); }
  .gn-map-stats { grid-template-columns: 1fr 1fr; gap: 10px; }
  .gn-map-stat:first-child { grid-column: 1 / -1; }
  .gn-map-stat { padding: 0.75rem 0.85rem; }
  .gn-map-stat-val { font-size: 1.35rem; }
  .gn-map-legend { box-shadow: var(--shadow-sm); }
  .gn-map-legend-title { width: 100%; border-right: none; border-bottom: 2px solid var(--black); padding: 7px 12px; }
  .gn-map-legend-step { padding: 7px 10px; }
  .gn-map-board { box-shadow: var(--shadow-sm); }
  .gn-map-row { grid-template-columns: 26px 1fr 46px; gap: 8px; padding: 8px 0.8rem; }
  .gn-map-track { display: none; }
  .gn-map-name { white-space: normal; }
}
@supports (view-timeline-name: --gnj-test) {
  .gn-jrny-caption, .gn-jrny-packet, .gn-jrny-ip-label, .gn-jrny-door, .gn-jrny-port, .gn-jrny-knock, .gn-jrny-net, .gn-jrny-ghost, .gn-jrny-caught-tag { animation-fill-mode: both; animation-timing-function: ease-out; }
  .gn-jrny-knock { animation-timeline: --gnj5; }
  .gn-jrny-knock-left { animation-name: gnjKnockInLeft; }
  .gn-jrny-knock-right { animation-name: gnjKnockInRight; }
  .gn-jrny-progress-fill { animation-timeline: --gnjAll; animation-name: gnjFillProgress; animation-range: cover 0% cover 100%; animation-fill-mode: both; animation-timing-function: linear; }
  .gn-jrny-wrap { view-timeline-name: --gnjAll; view-timeline-axis: block; }
}
@media (prefers-reduced-motion: reduce) {
  .gn-jrny-caption, .gn-jrny-packet, .gn-jrny-ip-label, .gn-jrny-door, .gn-jrny-port, .gn-jrny-knock, .gn-jrny-net, .gn-jrny-ghost, .gn-jrny-caught-tag { animation: none !important; opacity: 1 !important; transform: none !important; }
  .gn-jrny-scene { height: auto !important; }
  .gn-jrny-stage { position: relative !important; height: auto !important; padding: 3rem 0; }
}
@supports not (animation-timeline: view()) {
  .gn-jrny-caption, .gn-jrny-packet, .gn-jrny-ip-label, .gn-jrny-knock, .gn-jrny-net, .gn-jrny-ghost, .gn-jrny-caught-tag { opacity: 1 !important; transform: none !important; }
  .gn-jrny-scene { height: auto !important; }
  .gn-jrny-stage { position: relative !important; height: auto !important; padding: 3.5rem 0; }
}
.gn-jrny-wrap { position: relative; background: var(--white); color: var(--black); box-shadow: 0 0 0 100vmax var(--white); clip-path: inset(0 -100vmax); border-top: 2px solid var(--black); border-bottom: 2px solid var(--black); padding: 1px 0; --accent: #171e19; --accent-soft: rgba(255, 225, 124, 0.35); --ink: #000000; --muted: #272727; --border: #000000; --surface: #f4f4f5; --danger: #d92d20; --warning: #ffe17c; --good: #b7c6c2; }
.gn-jrny-wrap h1, .gn-jrny-wrap h2, .gn-jrny-wrap h3, .gn-jrny-wrap h4, .gn-jrny-wrap p { color: var(--black); }
.gn-jrny-ghost path { fill: var(--charcoal) !important; }
.gn-jrny-ghost circle { fill: var(--primary) !important; }
.gn-jrny-skip { display: inline-block; margin: 0.4rem 0 1.2rem 0; font-size: 0.78rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; color: var(--black) !important; text-decoration: none; background: var(--primary); border: 2px solid var(--black); box-shadow: var(--shadow-sm); padding: 8px 16px; border-radius: 12px; transition: all 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275); }
.gn-jrny-skip:hover { transform: translate(4px, 4px); box-shadow: none; text-decoration: none; }
.gn-jrny-progress-track { position: fixed; top: 18%; right: 18px; width: 10px; height: 45vh; background: var(--white); border: 2px solid var(--black); z-index: 5; overflow: hidden; }
.gn-jrny-progress-fill { width: 100%; height: 0%; background: var(--primary); }
.gn-jrny-scene { position: relative; width: 100%; }
.gn-jrny-stage { position: sticky; top: 0; height: 100vh; width: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; overflow: hidden; text-align: center; padding: 0 1rem; }
.gn-jrny-caption { max-width: 860px; margin-bottom: 2.4rem; opacity: 0; transform: translateY(28px); }
.gn-jrny-eyebrow { display: inline-block; font-size: 0.78rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--black) !important; font-weight: 700; margin-bottom: 1.1rem; background: var(--primary); border: 2px solid var(--black); box-shadow: 4px 4px 0 0 var(--black); padding: 7px 16px; }
.gn-jrny-caption h3 { font-family: var(--font-head); font-size: clamp(2.1rem, 5vw, 3.8rem); font-weight: 800; margin: 0; line-height: 0.98; letter-spacing: -0.04em; text-transform: uppercase; }
.gn-jrny-caption p { margin-top: 1.2rem; color: var(--line) !important; font-size: 1.1rem; letter-spacing: 0; line-height: 1.5; font-weight: 500; }
.gn-jrny-caption-final h3 { font-size: clamp(2.4rem, 6vw, 4.4rem); }
.gn-jrny-canvas { position: relative; width: min(560px, 90%); height: 130px; }
.gn-jrny-canvas-center { display: flex; align-items: center; justify-content: center; height: 220px; }
.gn-jrny-wire { position: absolute; top: 50%; left: 0; right: 0; height: 3px; background: repeating-linear-gradient(90deg, var(--black) 0 10px, transparent 10px 20px); transform: translateY(-50%); }
.gn-jrny-node { position: absolute; top: 50%; width: 12px; height: 12px; border-radius: 0; background: var(--sage); border: 2px solid var(--black); transform: translate(-50%, -50%); }
.gn-jrny-packet { position: absolute; top: 50%; left: 0%; width: 18px; height: 18px; border-radius: 0; background: var(--primary); border: 2px solid var(--black); transform: translate(-50%, -50%); opacity: 0; }
.gn-jrny-packet-drop { top: 50%; left: 50%; }
.gn-jrny-packet-still { opacity: 1; }
.gn-jrny-pin { position: absolute; width: 26px; height: 26px; border-radius: 0; background: var(--primary); border: 2px solid var(--black); transform: rotate(45deg); }
.gn-jrny-ip-label { position: absolute; margin-top: 56px; font-family: var(--font-mono); font-size: 1.05rem; font-weight: 700; background: var(--black); color: var(--white) !important; border: 2px solid var(--black); box-shadow: 4px 4px 0 0 var(--primary); padding: 10px 20px; opacity: 0; transform: translateY(28px); }
.gn-jrny-portgrid { display: grid; grid-template-columns: repeat(10, 34px); gap: 6px; justify-content: center; }
.gn-jrny-port { width: 34px; height: 34px; border-radius: 0; background: var(--muted-card); border: 2px solid var(--black); position: relative; animation-name: gnjPortScan; animation-fill-mode: both; }
.gn-jrny-port-open { animation-name: gnjPortReveal; }
.gn-jrny-port-tag { position: absolute; top: 118%; left: 50%; transform: translateX(-50%); white-space: nowrap; font-family: var(--font-body); font-size: 0.62rem; font-weight: 700; letter-spacing: 0.08em; color: var(--black) !important; }
.gn-jrny-doorway { perspective: 700px; position: relative; width: 140px; height: 200px; }
.gn-jrny-doorway-glow { position: absolute; inset: 0; margin: auto; width: 90px; height: 170px; background: var(--charcoal); border: 2px solid var(--black); z-index: 0; }
.gn-jrny-door { position: absolute; left: 0; width: 140px; height: 200px; border-radius: 0; background: var(--sage); border: 2px solid var(--black); transform-origin: left center; transform-style: preserve-3d; z-index: 1; }
.gn-jrny-knocks { display: flex; flex-direction: column; gap: 14px; width: min(420px, 90%); }
.gn-jrny-knock { display: flex; justify-content: space-between; align-items: center; gap: 10px; padding: 14px 18px; border-radius: 0; background: var(--white); border: 2px solid var(--black); box-shadow: var(--shadow-sm); opacity: 0; }
.gn-jrny-knock-left { transform: translateX(-70px); align-self: flex-start; }
.gn-jrny-knock-right { transform: translateX(70px); align-self: flex-end; }
.gn-jrny-knock-label { font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.1em; color: var(--line) !important; font-weight: 700; }
.gn-jrny-knock-cred { font-family: var(--font-mono); color: var(--black) !important; font-size: 0.92rem; font-weight: 700; }
.gn-jrny-net { position: absolute; width: 130px; height: 130px; top: -130px; border: 2px dashed var(--black); background-image: repeating-linear-gradient(45deg, var(--black) 0 2px, transparent 2px 12px), repeating-linear-gradient(-45deg, var(--black) 0 2px, transparent 2px 12px); opacity: 0.8; transform-origin: top center; }
.gn-jrny-ghost { width: 46px; height: 46px; margin-top: 18px; opacity: 0; transform: translateY(28px); }
.gn-jrny-caught-tag { margin-top: 22px; font-family: var(--font-body); font-size: 0.72rem; letter-spacing: 0.14em; font-weight: 700; text-transform: uppercase; background: var(--black); color: var(--primary) !important; border: 2px solid var(--primary); border-radius: 999px; padding: 9px 22px; opacity: 0; transform: translateY(28px); }
@keyframes gnjKnockInLeft { from { opacity: 0; transform: translateX(-70px); } to { opacity: 1; transform: translateX(0); } }
@keyframes gnjKnockInRight { from { opacity: 0; transform: translateX(70px); } to { opacity: 1; transform: translateX(0); } }
@keyframes gnjFadeUp { from { opacity: 0; transform: translateY(28px); } to { opacity: 1; transform: translateY(0); } }
@keyframes gnjRiseAway { from { opacity: 1; transform: translateY(0); } to { opacity: 0; transform: translateY(-60px); } }
@keyframes gnjTravelRight { from { opacity: 1; left: 0%; } to { opacity: 1; left: 100%; } }
@keyframes gnjDropDown { from { opacity: 0; transform: translate(-50%, -180px); } to { opacity: 1; transform: translate(-50%, 40px); } }
@keyframes gnjDoorOpen { from { transform: rotateY(0deg); } to { transform: rotateY(-100deg); } }
@keyframes gnjPortScan { 0% { background: var(--muted-card); } 50% { background: var(--sage); } 100% { background: var(--muted-card); } }
@keyframes gnjPortReveal { 0% { background: var(--muted-card); } 50% { background: var(--primary); } 100% { background: var(--primary); box-shadow: 4px 4px 0 0 var(--black); } }
@keyframes gnjNetDrop { from { transform: translateY(0) scaleY(0); opacity: 0; } to { transform: translateY(90px) scaleY(1); opacity: 0.55; } }
@keyframes gnjFillProgress { from { height: 0%; } to { height: 100%; } }
.gn-digest-head { max-width: 900px; margin: 4.5rem auto 2rem; padding: 0 1.5rem; text-align: center; }
.gn-digest-eyebrow { display: inline-block; background: var(--charcoal); color: var(--white); font-size: 0.68rem; font-weight: 800; letter-spacing: 0.12em; text-transform: uppercase; padding: 7px 14px; border: 2px solid var(--black); }
.gn-digest-head h2 { font-family: var(--font-head); font-weight: 800; text-transform: uppercase; font-size: clamp(1.9rem, 4.6vw, 3.2rem); letter-spacing: -0.04em; line-height: 1; margin: 1.1rem 0 0.9rem; color: var(--black); }
.gn-digest-head p { color: #3d3d3d; font-size: 1.02rem; line-height: 1.55; margin: 0; max-width: 60ch; margin-inline: auto; }
.gn-digest-card { display: grid; grid-template-columns: minmax(0, 1fr) 250px; gap: 2.5rem; background: var(--white); border: 2px solid var(--black); box-shadow: var(--shadow-md); padding: 2.2rem; }
.gn-digest-date { display: block; font-size: 0.72rem; font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase; color: #6b6b6b; margin-bottom: 1.4rem; }
.gn-digest-body h3 { font-family: var(--font-head); font-size: 0.82rem; font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase; color: var(--black); margin: 1.6rem 0 0.5rem; padding-bottom: 0.4rem; border-bottom: 2px solid var(--primary); }
.gn-digest-body h3:first-child { margin-top: 0; }
.gn-digest-body p { color: #333; font-size: 0.99rem; line-height: 1.62; margin: 0; }
.gn-digest-side { border-left: 2px solid var(--black); padding-left: 2rem; }
.gn-digest-fig { margin-bottom: 1.5rem; }
.gn-digest-fig-num { font-family: var(--font-head); font-size: 2.1rem; font-weight: 800; line-height: 1; letter-spacing: -0.03em; color: var(--black); }
.gn-digest-fig-label { font-size: 0.74rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: #6b6b6b; margin-top: 0.3rem; }
.gn-digest-sev { border-top: 2px solid var(--black); padding-top: 1rem; margin-top: 1.8rem; }
.gn-digest-sev-row { display: flex; justify-content: space-between; align-items: center; font-size: 0.85rem; font-weight: 600; color: #333; padding: 0.28rem 0; }
.gn-digest-sev-num { font-weight: 800; font-variant-numeric: tabular-nums; }
@media (max-width: 900px) {
  .gn-digest-card { grid-template-columns: 1fr; gap: 1.8rem; padding: 1.5rem; }
  .gn-digest-side { border-left: none; padding-left: 0; border-top: 2px solid var(--black); padding-top: 1.4rem; display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; }
  .gn-digest-fig { margin-bottom: 0; }
  .gn-digest-sev { grid-column: 1 / -1; margin-top: 0.6rem; }
  .gn-digest-fig-num { font-size: 1.7rem; }
}
.gn-cap-band { background: var(--primary); border-top: 2px solid var(--black); border-bottom: 2px solid var(--black); box-shadow: 0 0 0 100vmax var(--primary); clip-path: inset(0 -100vmax); padding: 5rem 1.5rem; }
.gn-cap-heading { text-align: center; max-width: 820px; margin: 0 auto 3.5rem; }
.gn-cap-heading h2 { font-family: var(--font-head); font-size: clamp(2rem, 5vw, 3.6rem); font-weight: 800; margin: 0 0 1rem; letter-spacing: -0.04em; line-height: 0.98; color: var(--black); text-transform: uppercase; }
.gn-cap-heading p { color: var(--black); font-size: 1.15rem; margin: 0; font-weight: 500; line-height: 1.5; }
.gn-cap-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.8rem; max-width: 1200px; margin: 0 auto; }
@media (max-width: 900px) {
  .gn-cap-grid { grid-template-columns: 1fr; }
}
.gn-cap-card { background: var(--white); border: 2px solid var(--black); box-shadow: var(--shadow-md); padding: 2rem 1.8rem; transition: all 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275); }
.gn-cap-card:hover { transform: translate(4px, 4px); box-shadow: var(--shadow-sm); }
.gn-cap-icon { width: 48px; height: 48px; background: var(--sage); border: 2px solid var(--black); margin-bottom: 1.4rem; display: flex; align-items: center; justify-content: center; transition: background 0.2s ease; }
.gn-cap-card:hover .gn-cap-icon { background: var(--primary); }
.gn-cap-card-title { font-family: var(--font-head); font-size: 1.5rem; font-weight: 800; margin-bottom: 0.6rem; letter-spacing: -0.03em; color: var(--black); text-transform: uppercase; }
.gn-cap-card-desc { font-size: 0.98rem; line-height: 1.5; color: var(--line); font-weight: 500; }
.gn-ledger-band { background: var(--white); padding: 5rem 1.5rem; max-width: 1200px; margin: 0 auto; }
.gn-ledger-copy { margin-bottom: 3rem; }
.gn-ledger-copy h2 { font-family: var(--font-head); font-size: clamp(2rem, 5vw, 3.6rem); font-weight: 800; margin: 0 0 1.2rem; letter-spacing: -0.04em; line-height: 0.98; color: var(--black); text-transform: uppercase; }
.gn-ledger-copy p { color: var(--line); font-size: 1.15rem; line-height: 1.55; max-width: 820px; font-weight: 500; }
.gn-chain-row { display: flex; align-items: stretch; justify-content: space-between; flex-wrap: wrap; gap: 1rem; }
.gn-chain-node { background: var(--white); border: 2px solid var(--black); padding: 1.4rem 1rem; text-align: center; flex: 1; min-width: 190px; display: flex; flex-direction: column; justify-content: center; }
.gn-chain-node-current { background: var(--primary); box-shadow: var(--shadow-md); }
.gn-chain-hash { font-family: var(--font-mono); font-size: 0.78rem; color: var(--line); margin-bottom: 0.5rem; font-weight: 700; }
.gn-chain-label { font-size: 0.92rem; font-weight: 700; color: var(--black); text-transform: uppercase; letter-spacing: 0.02em; }
.gn-chain-arrow { display: flex; align-items: center; color: var(--black); font-size: 1.7rem; font-weight: 800; }
@media (max-width: 900px) {
  .gn-chain-arrow { display: none; }
}
.gn-final-cta { background: var(--primary); border-top: 2px solid var(--black); border-bottom: 2px solid var(--black); box-shadow: 0 0 0 100vmax var(--primary); clip-path: inset(0 -100vmax); padding: 5rem 1.5rem; text-align: center; }
.gn-final-cta h2 { font-family: var(--font-head); font-size: clamp(2.2rem, 6vw, 4.4rem); font-weight: 800; margin: 0; letter-spacing: -0.04em; line-height: 0.98; color: var(--black); text-transform: uppercase; }

/* ==========================================================================
   COMPONENT LAYER — real HTML equivalents of the Streamlit widgets
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }
body {
  margin: 0; background: var(--white); color: var(--black);
  font-family: var(--font-body); font-weight: 500; line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
a { color: inherit; }
.wrap { max-width: 1180px; margin: 0 auto; padding: 0 22px; }
.wrap-narrow { max-width: 620px; margin: 0 auto; padding: 0 22px; }

/* ---- nav: the wordmark + button row app.py drew with st.columns ---- */
.gn-nav {
  border-bottom: 2px solid var(--black); background: var(--white);
  position: sticky; top: 0; z-index: 40;
}
.gn-nav .wrap { display: flex; align-items: center; gap: 14px; min-height: 72px; flex-wrap: wrap; }
.gn-nav-wordmark { text-decoration: none; }
.gn-nav-links { margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap; }
.gn-nav-links a {
  text-decoration: none; border: 2px solid var(--black); border-radius: 12px;
  background: var(--white); color: var(--black);
  font-family: var(--font-body); font-weight: 700; text-transform: uppercase;
  font-size: 0.72rem; letter-spacing: 0.04em; padding: 9px 16px;
  transition: transform .08s ease, box-shadow .08s ease;
}
.gn-nav-links a:hover { box-shadow: var(--shadow-sm); transform: translate(-2px, -2px); }
.gn-nav-links a.on { background: var(--primary); box-shadow: var(--shadow-sm); }

/* ---- buttons: st.button / st.form_submit_button ---- */
.btn {
  display: inline-block; cursor: pointer; text-decoration: none;
  border: 2px solid var(--black); border-radius: 12px;
  background: var(--white); color: var(--black);
  font-family: var(--font-body); font-weight: 700; text-transform: uppercase;
  font-size: 0.8rem; letter-spacing: 0.04em; padding: 12px 22px;
  transition: transform .08s ease, box-shadow .08s ease;
}
.btn:hover { box-shadow: var(--shadow-sm); transform: translate(-2px, -2px); }
.btn-primary { background: var(--primary); }
.btn-block { display: block; width: 100%; text-align: center; }

/* ---- cards: st.container(border=True) ---- */
.card {
  border: 2px solid var(--black); border-radius: 12px; background: var(--white);
  box-shadow: var(--shadow-sm); padding: 1.6rem; margin-bottom: 1.4rem;
}
.card h2, .card h3 { margin-top: 0; }
.card-muted { background: var(--muted-card); }

/* ---- metrics: st.metric ---- */
.metrics { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 16px; }
.metric {
  background: var(--white); border: 2px solid var(--black);
  box-shadow: var(--shadow-sm); border-radius: 12px; padding: 20px 22px;
}
.metric-value {
  font-family: var(--font-head); font-weight: 800;
  letter-spacing: -0.03em; font-size: 2.4rem; line-height: 1.05;
}
.metric-label {
  color: var(--line); font-weight: 700; text-transform: uppercase;
  font-size: 0.72rem; letter-spacing: 0.05em; margin-top: 4px;
}

/* ---- forms: st.text_input / st.radio / st.form ---- */
.field { margin-bottom: 1.05rem; }
.field label, .field > .lbl {
  display: block; font-weight: 700; text-transform: uppercase;
  font-size: 0.72rem; letter-spacing: 0.05em; margin-bottom: 7px;
}
.field input[type=text], .field input[type=password], .field input[type=email],
.field input[type=number], .field select, .field textarea {
  width: 100%; padding: 12px 14px; border: 2px solid var(--black);
  border-radius: 12px; background: var(--white); color: var(--black);
  font-family: var(--font-body); font-size: 0.95rem; font-weight: 500;
}
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none; box-shadow: var(--shadow-sm);
}
.roles { display: flex; gap: 10px; flex-wrap: wrap; }
.roles label {
  display: inline-flex; align-items: center; gap: 8px; cursor: pointer;
  border: 2px solid var(--black); border-radius: 12px; padding: 10px 16px;
  font-weight: 700; text-transform: uppercase; font-size: 0.72rem;
  letter-spacing: 0.04em; margin: 0;
}
.roles input { accent-color: var(--black); }
.roles label:has(input:checked) { background: var(--primary); box-shadow: var(--shadow-sm); }

/* ---- tables: st.dataframe ---- */
.tbl-scroll { overflow-x: auto; border: 2px solid var(--black); border-radius: 12px; }
table.tbl { width: 100%; border-collapse: collapse; background: var(--white); font-size: 0.86rem; }
table.tbl th {
  text-align: left; font-family: var(--font-body); font-weight: 700;
  text-transform: uppercase; font-size: 0.68rem; letter-spacing: 0.06em;
  background: var(--primary); border-bottom: 2px solid var(--black);
  padding: 11px 13px; white-space: nowrap;
}
table.tbl td { padding: 10px 13px; border-bottom: 1px solid #e6e6e6; }
table.tbl tr:last-child td { border-bottom: 0; }
table.tbl td.mono { font-family: var(--font-mono); font-size: 0.8rem; }

/* ---- severity pills, matching the digest colour language ---- */
.sev { display: inline-block; padding: 2px 10px; border: 2px solid var(--black);
       border-radius: 999px; font-size: 0.66rem; font-weight: 700;
       text-transform: uppercase; letter-spacing: 0.05em; }
.sev-Critical { background: var(--danger); color: var(--white); }
.sev-High     { background: #f07f2d; }
.sev-Medium   { background: var(--primary); }
.sev-Low      { background: var(--good); color: var(--white); }
.sev-Unknown  { background: var(--muted-card); }

/* ---- notices: gn_error / gn_success / gn_info ---- */
.notice {
  border: 2px solid var(--black); border-radius: 12px; padding: 14px 18px;
  margin-bottom: 1.1rem; font-weight: 700; font-size: 0.88rem;
  box-shadow: var(--shadow-sm);
}
.notice-error   { background: #ffe3e1; }
.notice-success { background: #d9f5e3; }
.notice-info    { background: var(--muted-card); }

/* ---- footer ---- */
.gn-foot {
  border-top: 2px solid var(--black); margin-top: 4rem; padding: 2.2rem 0;
  font-size: 0.76rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.06em; color: var(--line);
}
.gn-foot .wrap { display: flex; gap: 18px; flex-wrap: wrap; align-items: center; }
.gn-foot a { margin-left: auto; }

@media (max-width: 720px) {
  .gn-nav .wrap { min-height: 0; padding-top: 12px; padding-bottom: 12px; }
  .gn-nav-links { margin-left: 0; width: 100%; }
  .gn-nav-links a { flex: 1 1 auto; text-align: center; }
  .card { padding: 1.15rem; }
  .metric-value { font-size: 1.9rem; }
  .gn-foot a { margin-left: 0; }
}

/* ==========================================================================
   PAGE CLASSES — the login, developer, admin, digest and docs views
   Written against the original tokens (2px black rule, 12px radius, hard
   offset shadow, Cabinet Grotesk headings) so every screen carries the same
   identity as the landing rather than a second, softer one.
   ========================================================================== */

section { padding: 2.4rem 0; }
h1, h2, h3 { letter-spacing: -0.03em; }
.sub { color: var(--line); margin: 0 0 22px; font-size: 0.94rem; font-weight: 500; }
.mono { font-family: var(--font-mono); }
.wide { max-width: 560px; }

.panel {
  background: var(--white); border: 2px solid var(--black); border-radius: 12px;
  box-shadow: var(--shadow-sm); padding: 1.6rem; margin-bottom: 1.4rem;
}
.panel h2, .panel h3 { margin-top: 0; }

/* .btn.primary is the older spelling of .btn-primary; both are the accent. */
.btn.primary { background: var(--primary); }

.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 16px; margin: 34px 0; }
.stat {
  background: var(--white); border: 2px solid var(--black); border-radius: 12px;
  box-shadow: var(--shadow-sm); padding: 20px 22px;
}
.stat .n {
  font-family: var(--font-head); font-size: 2.4rem; font-weight: 800;
  letter-spacing: -0.03em; line-height: 1.05; font-variant-numeric: tabular-nums;
}
.stat .l {
  font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--line); margin-top: 4px; font-weight: 700;
}

/* Tables: views use a bare <table> inside .tbl-scroll, so style both. */
.tbl-scroll table { width: 100%; border-collapse: collapse; background: var(--white); font-size: 0.86rem; }
.tbl-scroll th {
  text-align: left; font-weight: 700; text-transform: uppercase;
  font-size: 0.68rem; letter-spacing: 0.06em; background: var(--primary);
  border-bottom: 2px solid var(--black); padding: 11px 13px; white-space: nowrap;
}
.tbl-scroll td { padding: 10px 13px; border-bottom: 1px solid #e6e6e6; }
.tbl-scroll tr:last-child td { border-bottom: 0; }

/* Severity: pages emit `class="sev Critical"` as well as `sev-Critical`. */
.sev { display: inline-block; padding: 2px 10px; border: 2px solid var(--black);
       border-radius: 999px; font-size: 0.66rem; font-weight: 700;
       text-transform: uppercase; letter-spacing: 0.05em; }
.sev.Critical { background: var(--danger); color: var(--white); }
.sev.High     { background: #f07f2d; }
.sev.Medium   { background: var(--primary); }
.sev.Low      { background: var(--good); color: var(--white); }
.sev.Unknown  { background: var(--muted-card); }

.digest {
  background: var(--white); border: 2px solid var(--black); border-radius: 12px;
  box-shadow: var(--shadow-sm); padding: 1.5rem; margin-bottom: 18px;
}
.digest h3 { margin: 0 0 4px; font-size: 1.05rem; }
.digest .date {
  font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.1em;
  color: var(--line); font-weight: 700;
}
.digest pre { white-space: pre-wrap; font-family: var(--font-body); font-size: 0.92rem; margin: 14px 0 0; line-height: 1.75; }

/* ---- auth screens ---- */
.auth-wrap { max-width: 440px; margin: 0 auto; padding: 52px 22px; }
.auth-wrap.wide { max-width: 560px; }
.auth-wrap label {
  display: block; font-weight: 700; text-transform: uppercase;
  font-size: 0.72rem; letter-spacing: 0.05em; margin: 0 0 7px;
}
.auth-wrap input[type=text], .auth-wrap input[type=password],
.auth-wrap input[type=email], .auth-wrap input[type=number],
.auth-wrap textarea, .auth-wrap select,
.panel input[type=text], .panel input[type=password],
.panel input[type=email], .panel textarea, .panel select {
  width: 100%; padding: 12px 14px; border: 2px solid var(--black);
  border-radius: 12px; background: var(--white); color: var(--black);
  font-family: var(--font-body); font-size: 0.95rem; font-weight: 500;
  margin-bottom: 1.05rem;
}
.auth-wrap input:focus, .panel input:focus,
.auth-wrap textarea:focus, .panel textarea:focus { outline: none; box-shadow: var(--shadow-sm); }

.radio-row { display: flex; gap: 10px; margin: 6px 0 18px; flex-wrap: wrap; }
.radio-row label {
  display: inline-flex; align-items: center; gap: 8px; cursor: pointer; margin: 0;
  border: 2px solid var(--black); border-radius: 12px; padding: 10px 16px;
  font-weight: 700; text-transform: uppercase; font-size: 0.72rem; letter-spacing: 0.04em;
}
.radio-row input { accent-color: var(--black); margin: 0; }
.radio-row label:has(input:checked) { background: var(--primary); box-shadow: var(--shadow-sm); }

.error {
  background: var(--danger); color: var(--white);
  border: 2px solid var(--black); border-radius: 12px;
  box-shadow: var(--shadow-sm);
  padding: 12px 16px; font-weight: 700; font-size: 0.86rem; margin: 0 0 18px;
}
.switch { margin-top: 20px; font-size: 0.86rem; text-align: center; font-weight: 500; }
.switch a { font-weight: 700; text-decoration: underline; }
.code-input input {
  letter-spacing: 0.5em; font-size: 1.4rem; text-align: center;
  font-weight: 800; font-family: var(--font-head);
}
.qr-box { display: flex; justify-content: center; margin: 18px 0; }
.qr-box img { border: 2px solid var(--black); border-radius: 12px; box-shadow: var(--shadow-sm); }
.secret-fallback {
  font-family: var(--font-mono); font-size: 0.85rem; background: var(--muted-card);
  border: 2px solid var(--black); border-radius: 12px; padding: 10px 12px;
  word-break: break-all; margin-top: 8px;
}

.kv { display: flex; justify-content: space-between; gap: 14px; padding: 10px 0; border-top: 1.5px solid #0000001a; font-size: 0.9rem; }
.kv:first-child { border-top: none; }
.kv .k { color: var(--line); font-weight: 700; text-transform: uppercase; font-size: 0.72rem; letter-spacing: 0.05em; }
.kv .v { font-family: var(--font-mono); }

.code {
  font-family: var(--font-mono); font-size: 0.85rem; background: var(--muted-card);
  border: 2px solid var(--black); border-radius: 12px; padding: 12px 14px;
  overflow-x: auto; white-space: pre-wrap; word-break: break-word;
}

@media (max-width: 720px) {
  .auth-wrap { padding: 30px 18px; }
  .stat .n { font-size: 1.9rem; }
  .panel { padding: 1.15rem; }
  .kv { flex-direction: column; gap: 2px; }
}

/* app.py blanked the wordmark text under 640px (font-size:0, keeping only the
   bolt) because its nav was four Streamlit buttons on one non-wrapping row and
   the letters cost room it did not have. This layout wraps the links onto
   their own line instead, so the room exists and the brand should be legible.
   Restated after the ported block so it wins on order, not on specificity. */
@media (max-width: 640px) {
  .gn-nav-wordmark { font-size: 1.15rem !important; gap: 8px !important; padding: 0.3rem 0 !important; }
}

/* ==========================================================================
   SPEC SECTIONS — the parts of the brief the ported CSS had no classes for,
   because app.py rendered them through Streamlit widgets rather than markup.
   Strictly to spec: 2px black borders, zero-blur shadows, no gradients,
   no radius above 12px, only #ffe17c / #171e19 / #b7c6c2 in branded sections.
   ========================================================================== */

/* The press: a button translates INTO its own shadow, so it reads as a
   physical key going down rather than a colour change. */
.btn, .gn-nav-links a {
  box-shadow: var(--shadow-sm);
  transition: transform .2s cubic-bezier(.175,.885,.32,1.275),
              box-shadow .2s cubic-bezier(.175,.885,.32,1.275);
}
.btn:hover, .gn-nav-links a:hover {
  transform: translate(4px, 4px);
  box-shadow: 0 0 0 0 var(--black);
}
.btn-lg { padding: 1rem 2rem; font-size: 0.9rem; box-shadow: var(--shadow-md); }
.btn-lg:hover { transform: translate(4px, 4px); box-shadow: var(--shadow-sm); }
.btn-dark { background: var(--black); color: var(--white); }

/* 32px radial dot pattern at 10% opacity, on yellow grounds only. */
.dots {
  background-image: radial-gradient(circle, rgba(0,0,0,.10) 1.6px, transparent 1.6px);
  background-size: 32px 32px;
}

/* --- social proof marquee: charcoal bar, sage text, infinite linear --- */
.gn-marquee {
  background: var(--charcoal); border-top: 2px solid var(--black);
  border-bottom: 2px solid var(--black); overflow: hidden; padding: 18px 0;
}
.gn-marquee-track { display: flex; gap: 3.5rem; width: max-content; animation: gnMarquee 38s linear infinite; }
.gn-marquee span {
  font-family: var(--font-head); font-weight: 800; font-size: 1.05rem;
  letter-spacing: .04em; text-transform: uppercase;
  color: var(--sage); opacity: .5; white-space: nowrap;
}
@keyframes gnMarquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) { .gn-marquee-track { animation: none; } }

/* --- problem vs solution --- */
.gn-vs { display: grid; grid-template-columns: 1fr 1fr; gap: 26px; }
.gn-vs-card { border-radius: 12px; padding: 1.9rem; }
.gn-vs-problem { background: var(--muted-card); border: 2px dashed #9a9a9a; opacity: .72; }
.gn-vs-solution { background: var(--primary); border: 2px solid var(--black); box-shadow: var(--shadow-md); }
.gn-vs h3 { margin-top: 0; }
.gn-vs ul { list-style: none; padding: 0; margin: 1.1rem 0 0; }
.gn-vs li { display: flex; gap: 11px; align-items: flex-start; padding: 8px 0; font-weight: 700; font-size: .92rem; }
.gn-vs li::before { flex: 0 0 auto; font-family: var(--font-head); font-weight: 800; }
.gn-vs-problem li::before { content: "\2715"; color: var(--danger); }
.gn-vs-solution li::before { content: "\2713"; color: var(--good); }

/* --- how it works: dark section, connected steps --- */
.gn-how { background: var(--charcoal); border-top: 2px solid var(--black); border-bottom: 2px solid var(--black); padding: 4.5rem 0; color: var(--white); }
.gn-how h2 { color: var(--white) !important; text-align: center; margin: 0 0 3rem; }
.gn-how-flow { display: grid; grid-template-columns: repeat(3, 1fr); gap: 26px; position: relative; }
.gn-how-flow::before { content: ""; position: absolute; top: 48px; left: 12%; right: 12%; height: 2px; background: var(--line); z-index: 0; }
.gn-how-step { position: relative; z-index: 1; text-align: center; }
.gn-how-dot {
  width: 96px; height: 96px; border-radius: 50%; margin: 0 auto 1.4rem;
  background: var(--charcoal); display: grid; place-items: center;
  font-family: var(--font-head); font-weight: 800; font-size: 1.7rem; color: var(--white);
}
.gn-how-step:nth-child(1) .gn-how-dot { border: 4px solid var(--sage); }
.gn-how-step:nth-child(2) .gn-how-dot { border: 4px solid var(--primary); }
.gn-how-step:nth-child(3) .gn-how-dot { border: 4px solid var(--white); }
.gn-how-step h3 { color: var(--white) !important; font-size: 1.1rem; margin: 0 0 .5rem; }
.gn-how-step p { color: var(--sage); font-size: .9rem; margin: 0; }

/* --- bento personas: sage / yellow / dark --- */
.gn-bento { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; }
.gn-bento-card { border: 2px solid var(--black); border-radius: 12px; padding: 1.9rem; }
.gn-bento-card:nth-child(1) { background: var(--sage); }
.gn-bento-card:nth-child(2) { background: var(--primary); box-shadow: var(--shadow-md); }
.gn-bento-card:nth-child(3) { background: var(--line); color: var(--white); }
.gn-bento-card:nth-child(3) h3 { color: var(--white) !important; }
.gn-bento-pill {
  display: inline-block; background: var(--white); color: var(--black);
  border: 2px solid var(--black); border-radius: 999px; padding: 5px 14px;
  font-size: .66rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .08em; margin-bottom: 1rem;
}

/* --- browser mockup --- */
.gn-mock { background: var(--white); border: 2px solid var(--black); border-radius: 12px; box-shadow: 12px 12px 0 0 var(--black); overflow: hidden; }
.gn-mock-bar { background: var(--black); padding: 10px 14px; display: flex; gap: 7px; align-items: center; }
.gn-mock-dot { width: 11px; height: 11px; border-radius: 50%; }
.gn-mock-body { padding: 1.3rem; display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.gn-mock-tile { border: 2px solid var(--black); border-radius: 12px; padding: .9rem 1rem; }
.gn-mock-tile.sage { background: var(--sage); }
.gn-mock-tile.dark { background: var(--charcoal); color: var(--white); }
.gn-mock-tile.wide { grid-column: 1 / -1; }
.gn-mock-num { font-family: var(--font-head); font-weight: 800; font-size: 1.75rem; line-height: 1.1; }
.gn-mock-lbl { font-size: .62rem; font-weight: 700; text-transform: uppercase; letter-spacing: .07em; }
.gn-bars { display: flex; align-items: flex-end; gap: 6px; height: 62px; margin-top: .6rem; }
.gn-bars i { flex: 1; background: var(--primary); border: 2px solid var(--black); border-radius: 3px 3px 0 0; }

@media (max-width: 900px) {
  .gn-vs, .gn-how-flow, .gn-bento { grid-template-columns: 1fr; }
  .gn-how-flow::before { display: none; }
}
@media (max-width: 720px) {
  .gn-mock-body { grid-template-columns: 1fr; }
  .btn-lg { padding: .85rem 1.4rem; }
}

/* ---- the story: per-element values, lifted out of inline style attributes.
   They are static, so they belong in the stylesheet — and they HAVE to be
   here: this CSP sets no 'unsafe-inline' and no style-src-attr, so an inline
   style attribute is dropped by the browser. Left inline, every scene lost
   its scroll range and the whole journey rendered dead. Same trap as the
   Sonava progress bars. ---- */
.gnj-s000 { height:160vh; view-timeline-name: --gnj1; }
.gnj-s001 { animation-timeline:--gnj1; animation-name:gnjFadeUp; animation-range: entry 0% entry 85%; }
.gnj-s002 { left:10%; }
.gnj-s003 { left:40%; }
.gnj-s004 { left:70%; }
.gnj-s005 { animation-timeline:--gnj1; animation-name:gnjTravelRight; animation-range: entry 0% entry 100%; }
.gnj-s006 { height:150vh; view-timeline-name: --gnj2; }
.gnj-s007 { animation-timeline:--gnj2; animation-name:gnjFadeUp; animation-range: entry 0% entry 85%; }
.gnj-s008 { animation-timeline:--gnj2; animation-name:gnjFadeUp; animation-range: entry 30% entry 90%; }
.gnj-s009 { animation-timeline:--gnj2; animation-name:gnjDropDown; animation-range: entry 0% entry 90%; }
.gnj-s010 { height:210vh; view-timeline-name: --gnj3; }
.gnj-s011 { animation-timeline:--gnj3; animation-name:gnjFadeUp; animation-range: entry 0% entry 60%; }
.gnj-s012 { animation-range: entry 0.0% entry 14.0%; }
.gnj-s013 { animation-range: entry 1.37% entry 15.37%; }
.gnj-s014 { animation-range: entry 2.73% entry 16.73%; }
.gnj-s015 { animation-range: entry 4.1% entry 18.1%; }
.gnj-s016 { animation-range: entry 5.47% entry 19.47%; }
.gnj-s017 { animation-range: entry 6.83% entry 20.83%; }
.gnj-s018 { animation-range: entry 8.2% entry 22.2%; }
.gnj-s019 { animation-range: entry 9.57% entry 23.57%; }
.gnj-s020 { animation-range: entry 10.93% entry 24.93%; }
.gnj-s021 { animation-range: entry 12.3% entry 26.3%; }
.gnj-s022 { animation-range: entry 13.67% entry 27.67%; }
.gnj-s023 { animation-range: entry 15.03% entry 29.03%; }
.gnj-s024 { animation-range: entry 16.4% entry 30.4%; }
.gnj-s025 { animation-range: entry 17.77% entry 31.77%; }
.gnj-s026 { animation-range: entry 19.13% entry 33.13%; }
.gnj-s027 { animation-range: entry 20.5% entry 34.5%; }
.gnj-s028 { animation-range: entry 21.87% entry 35.87%; }
.gnj-s029 { animation-range: entry 23.23% entry 37.23%; }
.gnj-s030 { animation-range: entry 24.6% entry 38.6%; }
.gnj-s031 { animation-range: entry 25.97% entry 39.97%; }
.gnj-s032 { animation-range: entry 27.33% entry 41.33%; }
.gnj-s033 { animation-range: entry 28.7% entry 42.7%; }
.gnj-s034 { animation-range: entry 30.07% entry 44.07%; }
.gnj-s035 { animation-range: entry 31.43% entry 45.43%; }
.gnj-s036 { animation-range: entry 32.8% entry 46.8%; }
.gnj-s037 { animation-range: entry 34.17% entry 48.17%; }
.gnj-s038 { animation-range: entry 35.53% entry 49.53%; }
.gnj-s039 { animation-range: entry 36.9% entry 50.9%; }
.gnj-s040 { animation-range: entry 38.27% entry 52.27%; }
.gnj-s041 { animation-range: entry 39.63% entry 53.63%; }
.gnj-s042 { animation-range: entry 41.0% entry 55.0%; }
.gnj-s043 { animation-range: entry 42.37% entry 56.37%; }
.gnj-s044 { animation-range: entry 43.73% entry 57.73%; }
.gnj-s045 { animation-range: entry 45.1% entry 59.1%; }
.gnj-s046 { animation-range: entry 46.47% entry 60.47%; }
.gnj-s047 { animation-range: entry 47.83% entry 61.83%; }
.gnj-s048 { animation-range: entry 49.2% entry 63.2%; }
.gnj-s049 { animation-range: entry 50.57% entry 64.57%; }
.gnj-s050 { animation-range: entry 51.93% entry 65.93%; }
.gnj-s051 { animation-range: entry 53.3% entry 67.3%; }
.gnj-s052 { animation-range: entry 54.67% entry 68.67%; }
.gnj-s053 { animation-range: entry 56.03% entry 70.03%; }
.gnj-s054 { animation-range: entry 57.4% entry 71.4%; }
.gnj-s055 { animation-range: entry 58.77% entry 72.77%; }
.gnj-s056 { animation-range: entry 60.13% entry 74.13%; }
.gnj-s057 { animation-range: entry 61.5% entry 75.5%; }
.gnj-s058 { animation-range: entry 62.87% entry 76.87%; }
.gnj-s059 { animation-range: entry 64.23% entry 78.23%; }
.gnj-s060 { animation-range: entry 65.6% entry 79.6%; }
.gnj-s061 { animation-range: entry 66.97% entry 80.97%; }
.gnj-s062 { animation-range: entry 68.33% entry 82.33%; }
.gnj-s063 { animation-range: entry 69.7% entry 83.7%; }
.gnj-s064 { animation-range: entry 71.07% entry 85.07%; }
.gnj-s065 { animation-range: entry 72.43% entry 86.43%; }
.gnj-s066 { animation-range: entry 73.8% entry 87.8%; }
.gnj-s067 { animation-range: entry 75.17% entry 89.17%; }
.gnj-s068 { animation-range: entry 76.53% entry 90.53%; }
.gnj-s069 { animation-range: entry 77.9% entry 91.9%; }
.gnj-s070 { animation-range: entry 79.27% entry 93.27%; }
.gnj-s071 { animation-range: entry 80.63% entry 94.63%; }
.gnj-s072 { height:150vh; view-timeline-name: --gnj4; }
.gnj-s073 { animation-timeline:--gnj4; animation-name:gnjFadeUp; animation-range: entry 0% entry 85%; }
.gnj-s074 { animation-timeline:--gnj4; animation-name:gnjDoorOpen; animation-range: entry 10% entry 90%; }
.gnj-s075 { height:200vh; view-timeline-name: --gnj5; }
.gnj-s076 { animation-timeline:--gnj5; animation-name:gnjFadeUp; animation-range: entry 0% entry 50%; }
.gnj-s077 { animation-range: entry 0% entry 18%; }
.gnj-s078 { animation-range: entry 14% entry 32%; }
.gnj-s079 { animation-range: entry 28% entry 46%; }
.gnj-s080 { animation-range: entry 42% entry 60%; }
.gnj-s081 { animation-range: entry 56% entry 74%; }
.gnj-s082 { animation-range: entry 70% entry 88%; }
.gnj-s083 { height:170vh; view-timeline-name: --gnj6; }
.gnj-s084 { animation-name: gnjFadeUp, gnjRiseAway; animation-timeline: --gnj6, --gnj6; animation-range: entry 0% entry 60%, exit 0% exit 90%; }
.gnj-s085 { animation-timeline:--gnj6; animation-name:gnjNetDrop; animation-range: entry 0% entry 55%; }
.gnj-s086 { animation-timeline:--gnj6; animation-name:gnjFadeUp; animation-range: entry 35% entry 80%; }
.gnj-s087 { animation-timeline:--gnj6; animation-name:gnjFadeUp; animation-range: entry 45% entry 90%; }
.gnj-s088 { height:110vh; view-timeline-name: --gnj7; }
.gnj-s089 { animation-timeline:--gnj7; animation-name:gnjFadeUp; animation-range: entry 0% entry 80%; }

/* ---- landing: values lifted out of inline style attributes, for the same
   CSP reason as the story block above. ---- */
.cta { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 2.2rem; }
.m0 { margin-bottom: 0; }
.mt-lg { margin-top: 1.8rem; }
.dot-red { background: #ff5f57; }
.dot-amber { background: #febc2e; }
.dot-green { background: #28c840; }

/* Severity-bar heights in 5% buckets. A CSP with no 'unsafe-inline' drops
   style="height:N%" outright, which renders every bar at its default and
   quietly turns a real chart into a decorative one. */
.gn-bars i.h5 { height: 5%; }
.gn-bars i.h10 { height: 10%; }
.gn-bars i.h15 { height: 15%; }
.gn-bars i.h20 { height: 20%; }
.gn-bars i.h25 { height: 25%; }
.gn-bars i.h30 { height: 30%; }
.gn-bars i.h35 { height: 35%; }
.gn-bars i.h40 { height: 40%; }
.gn-bars i.h45 { height: 45%; }
.gn-bars i.h50 { height: 50%; }
.gn-bars i.h55 { height: 55%; }
.gn-bars i.h60 { height: 60%; }
.gn-bars i.h65 { height: 65%; }
.gn-bars i.h70 { height: 70%; }
.gn-bars i.h75 { height: 75%; }
.gn-bars i.h80 { height: 80%; }
.gn-bars i.h85 { height: 85%; }
.gn-bars i.h90 { height: 90%; }
.gn-bars i.h95 { height: 95%; }
.gn-bars i.h100 { height: 100%; }

/* ---- utility classes replacing inline style attributes across the views.
   Under this CSP (no 'unsafe-inline', no style-src-attr) a style attribute is
   dropped by the browser, so anything positional or dimensional written inline
   silently does nothing. ---- */
.mt-36 { margin-top: 36px; }
.mt-34 { margin-top: 34px; }
.mt-22 { margin-top: 22px; }
.mt-14r { margin-top: 1.4rem; }
.mt-30-lg { margin-top: 30px; font-size: 1.15rem; }
.mt-20-ib { margin-top: 20px; display: inline-block; }
.mb-26 { margin-bottom: 26px; }
.mb-22 { margin-bottom: 22px; }
.mb-12 { margin: 0 0 12px; }
.m0-all { margin: 0; }
.m0-muted { margin: 0; color: var(--line); }
.m-tabs { margin: 1.6rem 0 0; }
.d-inline { display: inline; }
.tc { text-align: center; }
.tc-m0 { text-align: center; margin-bottom: 0; }
.lg { font-size: 1.15rem; }
.lg-mt-26 { font-size: 1.15rem; margin-top: 26px; }
.w170 { width: 170px; font-weight: 600; }
.pill-sm { padding: 3px 10px; font-size: .78rem; }
.scroll-420 { max-height: 420px; overflow-y: auto; }
.scroll-520 { max-height: 520px; overflow-y: auto; }
.row-12 { display: flex; align-items: center; gap: 12px; margin: 7px 0; }
.badge-armed { background: #ffe3e1; color: var(--danger); }
.badge-disarmed { background: #d9f5e3; color: var(--good); }

/* Origin-bar widths in 5% buckets — the same CSP constraint as the severity
   bars. Without these every bar renders at its default width, which reads as
   'every country is equally busy'. */
.gn-map-fill.w5 { width: 5%; }
.gn-map-fill.w10 { width: 10%; }
.gn-map-fill.w15 { width: 15%; }
.gn-map-fill.w20 { width: 20%; }
.gn-map-fill.w25 { width: 25%; }
.gn-map-fill.w30 { width: 30%; }
.gn-map-fill.w35 { width: 35%; }
.gn-map-fill.w40 { width: 40%; }
.gn-map-fill.w45 { width: 45%; }
.gn-map-fill.w50 { width: 50%; }
.gn-map-fill.w55 { width: 55%; }
.gn-map-fill.w60 { width: 60%; }
.gn-map-fill.w65 { width: 65%; }
.gn-map-fill.w70 { width: 70%; }
.gn-map-fill.w75 { width: 75%; }
.gn-map-fill.w80 { width: 80%; }
.gn-map-fill.w85 { width: 85%; }
.gn-map-fill.w90 { width: 90%; }
.gn-map-fill.w95 { width: 95%; }
.gn-map-fill.w100 { width: 100%; }

/* ---- origin heat map ---------------------------------------------------
   The choropleth is a plain inline SVG: geometry is pre-projected, so the only
   thing that varies per request is which band class a country carries. Fills
   MUST be classes — a style attribute is dropped by this CSP, which would
   flatten every country to one colour and silently turn the map into a
   decoration that looks identical whatever the data says. ---- */
.gn-map-panel { background: #171e19; border: 2px solid var(--black); border-radius: 12px; box-shadow: var(--shadow-sm); padding: 6px; margin-bottom: 1.2rem; overflow: hidden; }
.gn-map-svg { display: block; width: 100%; height: auto; }
.gn-c { fill: #232b28; stroke: #3a4541; stroke-width: .7; vector-effect: non-scaling-stroke; }
.gn-c.b-1 { fill: #232b28; }
.gn-c.b0 { fill: #61522a; }
.gn-c.b1 { fill: #836d2c; }
.gn-c.b2 { fill: #a68a30; }
.gn-c.b3 { fill: #c9aa3b; }
.gn-c.b4 { fill: #e7ca55; }
.gn-c.b5 { fill: #ffe17c; }
/* Hover lifts a country to the accent, so the tooltip has something to point at. */
.gn-c:hover { fill: var(--primary); stroke: var(--black); stroke-width: 1.2; }
.gn-map-legend-sw.sw-none { background: #232b28; }
.gn-map-legend-sw.sw-b0 { background: #61522a; }
.gn-map-legend-sw.sw-b1 { background: #836d2c; }
.gn-map-legend-sw.sw-b2 { background: #a68a30; }
.gn-map-legend-sw.sw-b3 { background: #c9aa3b; }
.gn-map-legend-sw.sw-b4 { background: #e7ca55; }
.gn-map-legend-sw.sw-b5 { background: #ffe17c; }
.gn-map-note { margin: 0 0 1.2rem; font-size: .8rem; }

/* ---- Ask Ghost -----------------------------------------------------------
   Yellow accents so the page isn't a wall of white, and the two sides of the
   conversation stay visually distinct: Ghost's replies get the accent bubble,
   the visitor's own messages stay white. Straight from app.py's Ask Ghost
   block, translated off the Streamlit widget selectors. ---- */
.ghost-wrap { max-width: 760px; margin: 0 auto; }
.ghost-head { background: var(--primary); box-shadow: var(--shadow-md); }
.ghost-head h2 { margin-top: 0; }
.ghost-head .sub { color: var(--line); }

.ghost-unlock {
  border: 2px solid var(--black); border-radius: 12px; box-shadow: var(--shadow-sm);
  overflow: hidden; margin-bottom: 1.4rem; background: var(--white);
}
.ghost-unlock > summary {
  cursor: pointer; padding: 14px 18px; font-weight: 700; text-transform: uppercase;
  font-size: .74rem; letter-spacing: .05em; background: var(--muted-card);
  border-bottom: 2px solid transparent;
}
.ghost-unlock[open] > summary { border-bottom-color: var(--black); }
.ghost-unlock > .panel { border: 0; border-radius: 0; box-shadow: none; margin: 0; }

.chat-log {
  max-height: 60vh; overflow-y: auto; padding: 4px;
  display: flex; flex-direction: column; margin-bottom: 1.1rem;
}
.chat-log .msg {
  border: 2px solid var(--black); border-radius: 12px; background: var(--white);
  box-shadow: var(--shadow-sm); padding: 12px 16px; margin-bottom: 1rem;
  font-size: .94rem; line-height: 1.65; white-space: pre-wrap; word-break: break-word;
  max-width: 88%;
}
.chat-log .msg.ghost { background: var(--primary); align-self: flex-start; }
.chat-log .msg.user { align-self: flex-end; }

.chat-form { display: flex; gap: 12px; align-items: flex-end; }
.chat-form textarea {
  flex: 1; resize: vertical; min-height: 52px; padding: 12px 14px;
  border: 2px solid var(--black); border-radius: 12px; background: var(--white);
  font-family: var(--font-body); font-size: .95rem; font-weight: 500; margin: 0;
}
.chat-form textarea:focus { outline: none; box-shadow: var(--shadow-sm); }
.chat-reset { margin-top: .9rem; text-align: right; }
.btn-sm { padding: 7px 13px; font-size: .68rem; }

@media (max-width: 720px) {
  .chat-log .msg { max-width: 100%; }
  .chat-form { flex-direction: column; align-items: stretch; }
}

/* ==========================================================================
   DEVELOPER CONSOLE — the authenticated API dashboard and the auth screens
   around it. The marketing landing was fully designed; the signed-in area was
   a bare .panel of key/value rows with the API key printed in the clear. This
   layer rebuilds it as a real developer console in the SAME neo-brutalist
   tokens (2px black rule, zero-blur offset shadow, Cabinet Grotesk heads,
   yellow #ffe17c / charcoal #171e19 / sage #b7c6c2) so the inside of the
   product reads as the same product as the front door.

   CSP note: this app sets no 'unsafe-inline' and no style-src-attr, so a
   style="" attribute is DROPPED by the browser. Every width/fill below is a
   bucket class, never an inline style — same rule as the story and map bars. */

/* Generic 5%-step width buckets, reusable by any neo meter/bar fill. */
.fillw-0{width:0}.fillw-5{width:5%}.fillw-10{width:10%}.fillw-15{width:15%}
.fillw-20{width:20%}.fillw-25{width:25%}.fillw-30{width:30%}.fillw-35{width:35%}
.fillw-40{width:40%}.fillw-45{width:45%}.fillw-50{width:50%}.fillw-55{width:55%}
.fillw-60{width:60%}.fillw-65{width:65%}.fillw-70{width:70%}.fillw-75{width:75%}
.fillw-80{width:80%}.fillw-85{width:85%}.fillw-90{width:90%}.fillw-95{width:95%}
.fillw-100{width:100%}

/* ---- console header: a dark "you are inside the system" band, echoing the
   charcoal bands on the landing so it belongs to the same identity. ---- */
.gn-con-head {
  position: relative; overflow: hidden;
  background: var(--charcoal); border: 2px solid var(--black);
  box-shadow: var(--shadow-md); padding: 2rem 2.1rem;
  margin: 0.4rem 0 1.8rem; display: flex; flex-wrap: wrap;
  align-items: center; gap: 1.2rem 1.4rem;
}
.gn-con-head::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background-image: radial-gradient(var(--sage) 1px, transparent 1px);
  background-size: 30px 30px; opacity: 0.09;
}
.gn-con-head > * { position: relative; z-index: 1; }
.gn-con-headmain { flex: 1 1 300px; min-width: 0; }
.gn-con-eyebrow {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--primary); color: var(--black); border: 2px solid var(--black);
  padding: 4px 12px; font-size: 0.62rem; font-weight: 800;
  letter-spacing: 0.14em; text-transform: uppercase; margin-bottom: 0.9rem;
}
.gn-con-title {
  font-family: var(--font-head); font-weight: 800; text-transform: uppercase;
  letter-spacing: -0.03em; color: var(--white); line-height: 1;
  font-size: clamp(1.7rem, 4vw, 2.4rem); margin: 0 0 0.75rem;
}
.gn-con-meta { display: flex; align-items: center; gap: 10px 14px; flex-wrap: wrap; }
.gn-con-email {
  font-family: var(--font-mono); color: var(--sage);
  font-size: 0.9rem; font-weight: 600; word-break: break-all;
}
.gn-con-tier {
  display: inline-block; background: rgba(255,255,255,0.06);
  border: 2px solid var(--sage); color: var(--sage);
  font-size: 0.6rem; font-weight: 800; letter-spacing: 0.1em;
  text-transform: uppercase; padding: 3px 10px;
}
.gn-con-live {
  display: inline-flex; align-items: center; gap: 8px;
  background: rgba(255,255,255,0.06); border: 2px solid var(--good);
  color: #d9f5e3; font-size: 0.62rem; font-weight: 800;
  letter-spacing: 0.08em; text-transform: uppercase; padding: 5px 12px;
}
.gn-con-actions { margin-left: auto; display: flex; gap: 10px; align-items: center; }
.gn-con-actions .btn { background: var(--white); }

/* ---- the two-column console layout ---- */
.gn-con-grid { display: grid; grid-template-columns: minmax(0,1fr) 330px; gap: 1.6rem; align-items: start; }
.gn-side { display: flex; flex-direction: column; gap: 1.4rem; }
.gn-side .panel { margin-bottom: 0; }
@media (max-width: 900px) { .gn-con-grid { grid-template-columns: 1fr; } }

.gn-card-eyebrow {
  font-size: 0.64rem; font-weight: 800; letter-spacing: 0.13em;
  text-transform: uppercase; color: var(--line); margin: 0 0 1rem;
  padding-bottom: 0.6rem; border-bottom: 2px solid var(--primary);
}

/* ---- the API key vault: the one thing a developer opens this page for.
   Charcoal card with a yellow spine; the key is blurred until hovered,
   focused or revealed, so it survives a shoulder-surf but never depends on
   JS to be readable (hover/focus unblur are pure CSS). ---- */
.gn-vault {
  background: var(--charcoal); border: 2px solid var(--black);
  border-left: 7px solid var(--primary); box-shadow: var(--shadow-md);
  padding: 1.6rem 1.8rem; margin-bottom: 1.4rem;
}
.gn-vault-top {
  display: flex; align-items: center; justify-content: space-between;
  gap: 0.8rem 1rem; margin-bottom: 1rem; flex-wrap: wrap;
}
.gn-vault-label {
  display: flex; align-items: center; gap: 8px; margin: 0;
  font-size: 0.66rem; font-weight: 800; letter-spacing: 0.13em;
  text-transform: uppercase; color: var(--sage);
}
.gn-vault-label svg { width: 15px; height: 15px; }
.gn-vault-keyrow { display: flex; align-items: stretch; gap: 10px; flex-wrap: wrap; }
.gn-vault-key {
  flex: 1 1 240px; min-width: 0; font-family: var(--font-mono);
  font-size: 1rem; font-weight: 700; letter-spacing: 0.02em;
  color: var(--white); background: #0e1411; border: 2px solid var(--black);
  padding: 13px 15px; overflow-x: auto; white-space: nowrap;
  filter: blur(5px); transition: filter 0.15s ease; cursor: pointer;
}
.gn-vault-key:hover, .gn-vault-key:focus, .gn-vault-key.is-shown { filter: blur(0); outline: none; }
.gn-vault-btns { display: flex; gap: 10px; flex-wrap: wrap; }
.gn-vault-hint { font-size: 0.74rem; color: var(--sage); margin: 0.85rem 0 0; font-weight: 600; }
.gn-vault-hint b { color: var(--primary); }

/* ---- dark-surface mini buttons (reveal / copy) ---- */
.gn-mini {
  display: inline-flex; align-items: center; gap: 7px; cursor: pointer;
  border: 2px solid var(--black); background: var(--primary); color: var(--black);
  font-family: var(--font-body); font-weight: 800; text-transform: uppercase;
  font-size: 0.68rem; letter-spacing: 0.06em; padding: 9px 15px;
  box-shadow: var(--shadow-sm); text-decoration: none;
  transition: transform 0.12s, box-shadow 0.12s, background 0.12s;
}
.gn-mini:hover { transform: translate(3px,3px); box-shadow: 0 0 0 0 var(--black); }
.gn-mini svg { width: 14px; height: 14px; }
.gn-mini-ghost { background: transparent; color: var(--sage); border-color: var(--sage); box-shadow: none; }
.gn-mini-ghost:hover { background: rgba(255,255,255,0.08); transform: none; box-shadow: none; }
.gn-mini.copied { background: var(--good); color: var(--white); border-color: var(--black); }

/* ---- quota gauge ---- */
.gn-meter-head { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; margin-bottom: 0.7rem; }
.gn-meter-num { font-family: var(--font-head); font-weight: 800; font-size: 1.55rem; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.gn-meter-num small { font-size: 0.9rem; color: var(--line); font-weight: 800; }
.gn-meter-pct { font-weight: 800; font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--line); }
.gn-meter { height: 20px; background: var(--muted-card); border: 2px solid var(--black); overflow: hidden; }
.gn-meter-fill { height: 100%; background: var(--primary); transform-origin: left center; animation: gn-map-grow 700ms cubic-bezier(.16,.84,.44,1) both; }
.gn-meter-fill.warn { background: var(--star); }
.gn-meter-fill.crit { background: var(--danger); }
.gn-meter-foot { display: flex; justify-content: space-between; gap: 1rem; font-size: 0.72rem; font-weight: 700; color: var(--line); text-transform: uppercase; letter-spacing: 0.04em; margin-top: 0.6rem; }
@media (prefers-reduced-motion: reduce) { .gn-meter-fill { animation: none; } }

/* ---- used / remaining stat pair ---- */
.gn-con-stats { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-top: 1.3rem; }
.gn-con-stat { border: 2px solid var(--black); box-shadow: var(--shadow-sm); padding: 14px 16px; background: var(--white); }
.gn-con-stat.hot { background: var(--primary); }
.gn-con-stat .n { font-family: var(--font-head); font-weight: 800; font-size: 1.7rem; line-height: 1; letter-spacing: -0.03em; font-variant-numeric: tabular-nums; }
.gn-con-stat .l { font-size: 0.64rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: var(--line); margin-top: 5px; }

/* ---- quick-start code block with an absolute copy button ---- */
.gn-quick { position: relative; }
.gn-quick .code { margin: 0; padding-right: 96px; }
.gn-quick .gn-mini { position: absolute; top: 10px; right: 10px; }

/* ---- endpoint reference cards (real endpoints, from the docs page) ---- */
.gn-eps { display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px; }
@media (max-width: 560px) { .gn-eps { grid-template-columns: 1fr; } }
.gn-ep { display: block; text-decoration: none; border: 2px solid var(--black); background: var(--white); box-shadow: var(--shadow-sm); padding: 1rem 1.1rem; transition: transform 0.14s, box-shadow 0.14s; }
.gn-ep:hover { transform: translate(3px,3px); box-shadow: 0 0 0 0 var(--black); }
.gn-ep-top { display: flex; align-items: center; gap: 9px; margin-bottom: 0.55rem; }
.gn-ep-method { font-weight: 800; font-size: 0.58rem; letter-spacing: 0.08em; text-transform: uppercase; background: var(--charcoal); color: var(--primary); border: 2px solid var(--black); padding: 2px 8px; }
.gn-ep-method.pub { background: var(--good); color: var(--white); }
.gn-ep-path { font-family: var(--font-mono); font-weight: 700; font-size: 0.8rem; color: var(--black); overflow-x: auto; white-space: nowrap; }
.gn-ep-desc { font-size: 0.8rem; color: var(--line); font-weight: 500; margin: 0; line-height: 1.45; }
.gn-ep-need { display: inline-block; margin-top: 0.6rem; font-size: 0.58rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: var(--line); }

/* ---- side cards: security + account meta ---- */
.gn-pill { display: inline-flex; align-items: center; gap: 7px; border: 2px solid var(--black); border-radius: 999px; padding: 4px 12px; font-size: 0.64rem; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; }
.gn-pill-ok { background: #d9f5e3; color: var(--good); }
.gn-pill-warn { background: #ffe3e1; color: var(--danger); }
.gn-pill-dot { width: 8px; height: 8px; border-radius: 50%; background: currentColor; flex-shrink: 0; }
.gn-side-note { font-size: 0.82rem; color: var(--line); font-weight: 500; line-height: 1.5; margin: 0.9rem 0 0; }

/* ---- one-time key reveal (register_done) — was class-less, so unstyled ---- */
.apikey-box {
  font-family: var(--font-mono); font-size: 1.02rem; font-weight: 700;
  color: var(--white); background: var(--charcoal);
  border: 2px solid var(--black); border-left: 7px solid var(--primary);
  box-shadow: var(--shadow-sm); padding: 16px 18px; margin: 0 0 1.2rem;
  overflow-x: auto; word-break: break-all;
}

/* ---- shared lift for every auth screen: a branded eyebrow above the form,
   and a livelier yellow focus ring on inputs. Additive, so the ported admin
   pages keep working. ---- */
.gn-auth-eyebrow {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--primary); border: 2px solid var(--black);
  box-shadow: var(--shadow-sm); color: var(--black);
  font-size: 0.62rem; font-weight: 800; letter-spacing: 0.13em;
  text-transform: uppercase; padding: 5px 13px; margin-bottom: 1rem;
}
.gn-auth-eyebrow svg { width: 14px; height: 14px; }
.auth-wrap input:focus, .panel input:focus,
.auth-wrap textarea:focus, .panel textarea:focus,
.field input:focus, .field select:focus, .field textarea:focus {
  border-color: var(--black); box-shadow: 3px 3px 0 0 var(--primary);
}

@media (max-width: 720px) {
  .gn-con-head { padding: 1.4rem 1.3rem; }
  .gn-con-actions { margin-left: 0; width: 100%; }
  .gn-con-actions .btn { flex: 1 1 auto; text-align: center; }
  .gn-vault { padding: 1.2rem 1.2rem; }
  .gn-con-stats { grid-template-columns: 1fr; }
}

/* ==========================================================================
   API DOCS — the /docs usage guide the console links to. Reuses the console
   header band and endpoint cards; adds a language-labelled code block with a
   copy button and a three-step proof-of-work flow. CSP-safe: no inline styles.
   ========================================================================== */
.gn-doc-sub { color: var(--line); font-weight: 500; font-size: 1rem; line-height: 1.55; max-width: 68ch; margin: 0 0 1.6rem; }
.gn-doc-sub code, .gn-inline-code {
  font-family: var(--font-mono); font-size: 0.86em; font-weight: 700;
  background: var(--muted-card); border: 2px solid var(--black);
  padding: 1px 7px; border-radius: 6px; white-space: nowrap;
}

/* language-labelled, copyable code block */
.gn-codeblock { position: relative; margin: 0 0 1.4rem; }
.gn-codeblock .code { margin: 0; padding-top: 2.6rem; }
.gn-code-lang {
  position: absolute; top: 0; left: 0; z-index: 1;
  background: var(--charcoal); color: var(--primary);
  border: 2px solid var(--black); border-bottom: 0;
  font-family: var(--font-body); font-weight: 800; font-size: 0.6rem;
  letter-spacing: 0.1em; text-transform: uppercase; padding: 6px 13px;
}
.gn-codeblock .gn-mini { position: absolute; top: 8px; right: 8px; z-index: 1; }

/* proof-of-work three-step flow */
.gn-flow { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin: 1.2rem 0 0.4rem; }
@media (max-width: 760px) { .gn-flow { grid-template-columns: 1fr; } }
.gn-flow-step { border: 2px solid var(--black); box-shadow: var(--shadow-sm); background: var(--white); padding: 1.2rem 1.3rem; position: relative; }
.gn-flow-num {
  width: 34px; height: 34px; display: grid; place-items: center;
  background: var(--primary); border: 2px solid var(--black);
  font-family: var(--font-head); font-weight: 800; font-size: 1rem;
  margin-bottom: 0.8rem;
}
.gn-flow-step h4 { font-family: var(--font-head); font-weight: 800; text-transform: uppercase; letter-spacing: -0.02em; font-size: 1rem; margin: 0 0 0.4rem; }
.gn-flow-step p { margin: 0; font-size: 0.86rem; color: var(--line); font-weight: 500; line-height: 1.5; }
.gn-flow-step p code { font-family: var(--font-mono); font-weight: 700; color: var(--black); }

/* a compact params/headers table wrapper reusing .tbl-scroll */
.gn-doc-note { border-left: 7px solid var(--primary); background: var(--muted-card); border: 2px solid var(--black); box-shadow: var(--shadow-sm); padding: 1rem 1.2rem; margin: 0 0 1.4rem; font-size: 0.9rem; font-weight: 500; line-height: 1.55; }
.gn-doc-note strong { font-weight: 800; }
