/* ══ TOKENS ═══════════════════════════════════════════════════════
   Lines 1-60 of the marketing site's assets/site.css, verbatim, plus
   the four tokens the portal needs on top: the semantic ramp, the
   rail width and the two chart inks. Same accent, same six surfaces,
   same 6px cards, same uppercase mono labels.

   The semantic colours are the application's deliberately cooled
   #30a06a / #e8a87c / #c24a56, not the stock Tailwind tones the demo
   shipped. They are stated per theme for the same reason the accent
   is: #e8a87c is a 1.9:1 contrast on white and unreadable as text, so
   light gets the same hues taken down in value. The raw app value is
   the dark one, where it was designed to sit.                       */
:root{
  color-scheme: light dark;
  --accent:     #2563eb;
  --accent-dim: #1d4ed8;
  --accent-hi:  #2563eb;

  /* LIGHT */
  --bg:        #ffffff;
  --surface:   #f7f8fa;
  --surface-2: #f0f2f5;
  --border:    #e2e5ea;
  --text:      #0d0f12;
  --muted:     #64748b;
  --faint:     #8a94a3;
  --chip-bg:   #eff5ff;
  --chip-bd:   #c7dbfe;
  --chip-tx:   #1d4ed8;
  --grid-line: #edeff3;
  --nav-bg:    rgba(255,255,255,.84);
  --shadow:    0 1px 2px rgba(13,15,18,.05), 0 12px 30px rgba(13,15,18,.07);
  --hover:     rgba(13,15,18,.025);

  --sans:'IBM Plex Sans',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
  --mono:'IBM Plex Mono',ui-monospace,SFMono-Regular,Menlo,monospace;
  --logo-sh:#0d0f18; --logo-sh1:.10; --logo-sh2:.14;
  --logo-warm:#a06c44; --logo-mid:#1c38a8; --logo-cool:#685aa0;
  --logo-b1:#2563eb;   --logo-b2:#685aa0; --logo-core:#1c38a8; --logo-glow:#4c68b0;
  --nav-h:64px;
  --maxw:1120px;

  /* portal additions — light */
  --rail-w:244px;
  --ok:#227a51;   --ok-bg:#eaf6f0;   --ok-bd:#bfe3d1;
  --warn:#9c6127; --warn-bg:#fdf3e9; --warn-bd:#f0d8bd;
  --bad:#a5333f;  --bad-bg:#fdeced;  --bad-bd:#f2c8cc;
  --plot:#2563eb; --plot-2:#a06c44;
}
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    --accent:#3b82f6; --accent-dim:#1d4ed8; --accent-hi:#60a5fa;
    --bg:#0d0f12; --surface:#13161b; --surface-2:#0f1218; --border:#1e2229;
    --text:#e2e8f0; --muted:#64748b; --faint:#7c8798;
    --chip-bg:#0f1525; --chip-bd:#1a3050; --chip-tx:#60a5fa;
    --grid-line:#161a20; --nav-bg:rgba(13,15,18,.85);
    --shadow:0 1px 2px rgba(0,0,0,.4), 0 16px 44px rgba(0,0,0,.4);
    --hover:rgba(255,255,255,.02);
    --logo-sh:#000000; --logo-sh1:.24; --logo-sh2:.30;
    --logo-warm:#e8a87c; --logo-mid:#eaf1ff; --logo-cool:#a898e8;
    --logo-b1:#3b82f6;   --logo-b2:#a898e8; --logo-core:#e8ecff; --logo-glow:#6888e8;
    --ok:#30a06a;   --ok-bg:#0e1b16;   --ok-bd:#1c3a2c;
    --warn:#e8a87c; --warn-bg:#1d1611; --warn-bd:#3d2f22;
    --bad:#c24a56;  --bad-bg:#1d1215;  --bad-bd:#3d2229;
    --plot:#3b82f6; --plot-2:#e8a87c;
  }
}
:root[data-theme="dark"]{
  --accent:#3b82f6; --accent-dim:#1d4ed8; --accent-hi:#60a5fa;
  --bg:#0d0f12; --surface:#13161b; --surface-2:#0f1218; --border:#1e2229;
  --text:#e2e8f0; --muted:#64748b; --faint:#7c8798;
  --chip-bg:#0f1525; --chip-bd:#1a3050; --chip-tx:#60a5fa;
  --grid-line:#161a20; --nav-bg:rgba(13,15,18,.85);
  --shadow:0 1px 2px rgba(0,0,0,.4), 0 16px 44px rgba(0,0,0,.4);
  --hover:rgba(255,255,255,.02);
  --logo-sh:#000000; --logo-sh1:.24; --logo-sh2:.30;
  --logo-warm:#e8a87c; --logo-mid:#eaf1ff; --logo-cool:#a898e8;
  --logo-b1:#3b82f6;   --logo-b2:#a898e8; --logo-core:#e8ecff; --logo-glow:#6888e8;
  --ok:#30a06a;   --ok-bg:#0e1b16;   --ok-bd:#1c3a2c;
  --warn:#e8a87c; --warn-bg:#1d1611; --warn-bd:#3d2f22;
  --bad:#c24a56;  --bad-bg:#1d1215;  --bad-bd:#3d2229;
  --plot:#3b82f6; --plot-2:#e8a87c;
}

*,*::before,*::after{margin:0;padding:0;box-sizing:border-box}

/* ── boot ──
   Shown until getSession() answers. It carries a line of text so a stall is
   distinguishable from a blank stare, and the text goes red if boot fails. */
#boot{min-height:100vh;display:grid;place-items:center;align-content:center;gap:1.1rem;
  padding:2rem;text-align:center}
#boot-msg{font-family:var(--mono);font-size:.76rem;letter-spacing:.1em;text-transform:uppercase;
  color:var(--faint);max-width:46ch;line-height:1.7;text-transform:none;letter-spacing:.02em}
#boot-msg.bad{color:var(--bad);text-transform:none;letter-spacing:0;font-family:var(--sans);
  font-size:.9rem}
#boot-msg a{color:var(--accent-hi);text-decoration:underline;text-underline-offset:2px}
#boot svg{animation:pulse 1.5s ease-in-out infinite}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.45}}
body{background:var(--bg);color:var(--text);font-family:var(--sans);font-size:15px;
  line-height:1.65;-webkit-font-smoothing:antialiased;
  transition:background .2s ease,color .2s ease}
a{color:inherit;text-decoration:none}
svg,img{display:block;max-width:100%}
::selection{background:var(--chip-bd);color:var(--text)}
h1,h2,h3{font-weight:500;letter-spacing:-.02em;line-height:1.15}
input,select,textarea,button{font:inherit;color:inherit}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:3px}
/* Except the route container. It is focused after every navigation so that a
   screen reader announces the new page and Tab restarts inside it — but it is
   tabindex="-1" and can never be reached by Tab, so its ring is not telling
   anybody where they can go next. Before the first pointer event a browser
   treats that programmatic focus as focus-visible, which is why a rectangle
   was drawn around the whole page on load and never again after the first
   click. The focus move stays; only the box goes. */
#route:focus,#route:focus-visible{outline:none}
[hidden]{display:none!important}
.mono{font-family:var(--mono)}
.tabnum{font-variant-numeric:tabular-nums}

/* the uppercase mono label — the identity's only shouting */
.lbl{font-family:var(--mono);font-size:.66rem;letter-spacing:.12em;text-transform:uppercase;
  color:var(--muted)}

/* ══ BUTTONS ══════════════════════════════════════════════════════ */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;
  font-family:var(--sans);font-size:.85rem;font-weight:500;letter-spacing:.04em;
  padding:.68rem 1.4rem;border-radius:4px;border:1px solid transparent;cursor:pointer;
  transition:background .2s,border-color .2s,color .2s,opacity .2s;white-space:nowrap}
.btn-primary{background:var(--accent);color:#fff}
.btn-primary:hover{background:var(--accent-dim);color:#fff}
.btn-ghost{background:var(--surface);border-color:var(--border);color:var(--text)}
.btn-ghost:hover{border-color:var(--accent)}
.btn-quiet{background:transparent;border-color:transparent;color:var(--muted);padding:.4rem .6rem}
.btn-quiet:hover{color:var(--text);background:var(--hover)}
.btn-danger{background:transparent;border-color:var(--bad-bd);color:var(--bad)}
.btn-danger:hover{background:var(--bad-bg);border-color:var(--bad)}
.btn-sm{padding:.44rem 1rem;font-size:.8rem}
.btn-xs{padding:.3rem .7rem;font-size:.74rem;letter-spacing:.03em}
.btn[disabled],.btn[aria-busy="true"]{opacity:.5;pointer-events:none}
.btn-block{width:100%}
.icon-btn{width:34px;height:34px;padding:0;display:grid;place-items:center;border-radius:4px;
  background:var(--surface);border:1px solid var(--border);color:var(--muted);cursor:pointer;
  transition:border-color .2s,color .2s;flex:0 0 34px}
.icon-btn:hover{border-color:var(--accent);color:var(--text)}
.theme-btn .sun{display:none}.theme-btn .moon{display:block}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]) .theme-btn .sun{display:block}
  :root:not([data-theme="light"]) .theme-btn .moon{display:none}}
:root[data-theme="dark"] .theme-btn .sun{display:block}
:root[data-theme="dark"] .theme-btn .moon{display:none}
:root[data-theme="light"] .theme-btn .sun{display:none}
:root[data-theme="light"] .theme-btn .moon{display:block}

/* ══ TOP BAR ══════════════════════════════════════════════════════ */
.topbar{position:fixed;inset:0 0 auto 0;z-index:100;height:var(--nav-h);
  display:flex;align-items:center;gap:12px;padding:0 clamp(16px,3vw,28px);
  background:var(--nav-bg);backdrop-filter:blur(12px);
  border-bottom:1px solid var(--border);transition:background .2s,border-color .2s}
.brand{display:flex;align-items:center;gap:11px;margin-right:auto;min-width:0}
.brand-txt{display:flex;flex-direction:column;justify-content:center;min-width:0}
.brand-txt .name{font-family:var(--mono);font-size:1rem;color:var(--accent);letter-spacing:.04em;
  line-height:1.15;white-space:nowrap}
.brand-txt .sub2{font-size:.66rem;color:var(--muted);letter-spacing:.12em;text-transform:uppercase;
  margin-top:1px;white-space:nowrap}
.top-link{font-size:.85rem;color:var(--muted);transition:color .2s;white-space:nowrap}
.top-link:hover{color:var(--text)}
@media(max-width:700px){.top-link{display:none}.brand-txt .sub2{display:none}}

/* the account button and its menu */
.acct{position:relative}
.acct-btn{display:flex;align-items:center;gap:8px;background:var(--surface);
  border:1px solid var(--border);border-radius:4px;padding:.3rem .55rem .3rem .35rem;
  cursor:pointer;transition:border-color .2s;max-width:210px}
.acct-btn:hover{border-color:var(--accent)}
.avatar{width:26px;height:26px;border-radius:3px;display:grid;place-items:center;flex:0 0 26px;
  background:var(--chip-bg);border:1px solid var(--chip-bd);color:var(--chip-tx);
  font-family:var(--mono);font-size:.7rem;letter-spacing:.02em;text-transform:uppercase}
.acct-btn .who{font-size:.8rem;color:var(--text);overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
@media(max-width:560px){.acct-btn .who{display:none}}
.acct-menu{position:absolute;right:0;top:calc(100% + 10px);width:270px;z-index:120;
  background:var(--surface);border:1px solid var(--border);border-radius:6px;
  box-shadow:var(--shadow);padding:6px;opacity:0;visibility:hidden;transform:translateY(-6px);
  transition:opacity .16s,transform .16s,visibility .16s}
.acct[open] .acct-menu{opacity:1;visibility:visible;transform:none}
.acct-menu .head{padding:.6rem .7rem .7rem;border-bottom:1px solid var(--border);margin-bottom:6px}
.acct-menu .head .em{font-size:.82rem;color:var(--text);word-break:break-all;line-height:1.4}
.acct-menu .head .lbl{margin-bottom:.3rem}
.acct-menu button,.acct-menu a{display:block;width:100%;text-align:left;padding:.5rem .7rem;
  border:0;background:none;border-radius:4px;font-size:.84rem;color:var(--text);cursor:pointer;
  transition:background .15s}
.acct-menu button:hover,.acct-menu a:hover{background:var(--surface-2)}

/* ══ SHELL ════════════════════════════════════════════════════════ */
.shell{display:flex;min-height:100vh;padding-top:var(--nav-h)}
.rail{position:fixed;top:var(--nav-h);bottom:0;left:0;width:var(--rail-w);z-index:90;
  border-right:1px solid var(--border);background:var(--bg);
  display:flex;flex-direction:column;padding:18px 12px;gap:2px;overflow-y:auto}
.rail .lbl{padding:0 .7rem;margin:14px 0 6px}
.rail .lbl:first-child{margin-top:0}
.rail-item{display:flex;align-items:center;gap:10px;padding:.55rem .7rem;border-radius:4px;
  font-size:.87rem;color:var(--muted);cursor:pointer;border:0;background:none;width:100%;
  text-align:left;transition:background .15s,color .15s}
.rail-item svg{width:16px;height:16px;flex:0 0 16px;stroke-width:1.6}
.rail-item:hover{background:var(--hover);color:var(--text)}
.rail-item[aria-current="page"]{background:var(--chip-bg);color:var(--chip-tx)}
.rail-item .count{margin-left:auto;font-family:var(--mono);font-size:.68rem;color:var(--faint)}
.rail-item[aria-current="page"] .count{color:var(--chip-tx)}
.rail-foot{margin-top:auto;padding-top:14px;border-top:1px solid var(--border)}
.rail-foot a{display:block;font-size:.78rem;color:var(--faint);padding:.3rem .7rem;
  transition:color .2s}
.rail-foot a:hover{color:var(--accent-hi)}

.main{flex:1;min-width:0;margin-left:var(--rail-w);padding:clamp(24px,3.2vw,40px) clamp(16px,3vw,40px) 72px}
.main-in{max-width:1080px;margin:0 auto}

@media(max-width:900px){
  .rail{position:static;width:auto;height:auto;border-right:0;border-bottom:1px solid var(--border);
    flex-direction:row;overflow-x:auto;padding:8px clamp(16px,3vw,28px);gap:4px;
    scrollbar-width:none}
  .rail::-webkit-scrollbar{display:none}
  .rail .lbl,.rail-foot{display:none}
  .rail-item{width:auto;white-space:nowrap;padding:.45rem .75rem}
  .rail-item .count{margin-left:6px}
  .shell{flex-direction:column}
  .main{margin-left:0}
}

/* ══ PAGE HEADS ═══════════════════════════════════════════════════ */
.page-head{margin-bottom:1.8rem}
.page-head h1{font-size:clamp(1.5rem,2.6vw,1.95rem);letter-spacing:-.025em}
.page-head .sub{font-size:.94rem;color:var(--muted);max-width:640px;margin-top:.4rem;
  line-height:1.65}
.page-head .row{display:flex;align-items:flex-start;gap:1rem;flex-wrap:wrap}
.page-head .row .acts{margin-left:auto;display:flex;gap:8px;flex-wrap:wrap}

/* ══ PANELS ═══════════════════════════════════════════════════════ */
.panel{background:var(--surface);border:1px solid var(--border);border-radius:6px;
  overflow:hidden;margin-bottom:14px}
.panel-head{display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  padding:.9rem 1.15rem;border-bottom:1px solid var(--border)}
.panel-head h2{font-size:.95rem;letter-spacing:-.01em}
.panel-head .lbl{margin-left:auto}
.panel-head .acts{margin-left:auto;display:flex;gap:8px;align-items:center}
.panel-head + .panel-head{border-top:0}
.panel-body{padding:1.15rem}
.panel-body > p{font-size:.88rem;color:var(--muted);line-height:1.66}
.panel-note{padding:.8rem 1.15rem;border-top:1px solid var(--border);font-size:.82rem;
  color:var(--muted);line-height:1.6}
.panel-note b{color:var(--text);font-weight:500}
.panel-note code{font-family:var(--mono);font-size:.78rem;color:var(--text)}

/* ══ STATS ════════════════════════════════════════════════════════ */
.stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:14px;
  margin-bottom:14px}
.stat{background:var(--surface);border:1px solid var(--border);border-radius:6px;
  padding:1.15rem 1.25rem}
.stat .l{font-family:var(--mono);font-size:.66rem;letter-spacing:.12em;text-transform:uppercase;
  color:var(--muted);margin-bottom:.6rem}
.stat .v{font-family:var(--mono);font-size:1.5rem;line-height:1.1;color:var(--text);
  font-variant-numeric:tabular-nums;word-break:break-word}
.stat .v.ok{color:var(--ok)}.stat .v.warn{color:var(--warn)}.stat .v.bad{color:var(--bad)}
.stat .v.hi{color:var(--accent-hi)}
.stat .s{font-size:.78rem;color:var(--muted);margin-top:.45rem;line-height:1.5}
.stat .s b{color:var(--text);font-weight:500}

/* ══ KEY / VALUE ROWS ═════════════════════════════════════════════ */
.kv{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));
  background:var(--surface);margin:0 -1px -1px 0}
.kv > div{background:var(--surface);padding:.95rem 1.15rem;
  border-right:1px solid var(--border);border-bottom:1px solid var(--border)}
.kv + .panel-note{border-top:0}
.kv .l{font-family:var(--mono);font-size:.66rem;letter-spacing:.12em;text-transform:uppercase;
  color:var(--muted);margin-bottom:.4rem}
.kv .v{font-size:.9rem;color:var(--text);line-height:1.5;word-break:break-word}
.kv .v.mono{font-family:var(--mono);font-size:.84rem}
.kv .v .muted{color:var(--muted)}

/* ══ BADGES AND CHIPS ═════════════════════════════════════════════ */
.badge{display:inline-flex;align-items:center;gap:5px;font-family:var(--mono);font-size:.68rem;
  padding:.2rem .5rem;border-radius:3px;letter-spacing:.04em;text-transform:uppercase;
  background:var(--chip-bg);border:1px solid var(--chip-bd);color:var(--chip-tx);
  white-space:nowrap}
.badge.ok{background:var(--ok-bg);border-color:var(--ok-bd);color:var(--ok)}
.badge.warn{background:var(--warn-bg);border-color:var(--warn-bd);color:var(--warn)}
.badge.bad{background:var(--bad-bg);border-color:var(--bad-bd);color:var(--bad)}
.badge.mute{background:var(--surface-2);border-color:var(--border);color:var(--muted)}
.badge .dot{width:5px;height:5px;border-radius:50%;background:currentColor;flex:0 0 5px}
.chips{display:flex;flex-wrap:wrap;gap:6px}
.chip{font-family:var(--mono);font-size:.7rem;padding:.18rem .45rem;border-radius:3px;
  background:var(--surface-2);border:1px solid var(--border);color:var(--muted)}
.chip.on{background:var(--chip-bg);border-color:var(--chip-bd);color:var(--chip-tx)}

/* ══ TABLES ═══════════════════════════════════════════════════════ */
.tblwrap{overflow-x:auto}
table{width:100%;border-collapse:collapse}
th{text-align:left;font-family:var(--mono);font-size:.66rem;color:var(--muted);
  text-transform:uppercase;letter-spacing:.12em;padding:.7rem 1.15rem;font-weight:400;
  border-bottom:1px solid var(--border);white-space:nowrap}
td{padding:.75rem 1.15rem;border-bottom:1px solid var(--border);font-size:.86rem;
  color:var(--muted);vertical-align:middle}
tr:last-child td{border-bottom:none}
tbody tr:hover td{background:var(--hover)}
td.first{font-family:var(--mono);color:var(--text);white-space:nowrap}
td.num{font-family:var(--mono);font-variant-numeric:tabular-nums;color:var(--text);
  white-space:nowrap}
td.act{text-align:right;white-space:nowrap}
td code,code{font-family:var(--mono);font-size:.8rem;color:var(--text)}

/* ══ EMPTY / LOADING ══════════════════════════════════════════════ */
.empty{padding:2.6rem 1.15rem;text-align:center}
.empty .ico{width:38px;height:38px;margin:0 auto .9rem;border-radius:4px;display:grid;
  place-items:center;background:var(--chip-bg);border:1px solid var(--chip-bd);
  color:var(--accent-hi)}
.empty h3{font-size:.95rem;margin-bottom:.35rem}
.empty p{font-size:.86rem;color:var(--muted);max-width:44ch;margin:0 auto;line-height:1.6}
.empty .btn{margin-top:1.1rem}
/* Three claim buttons on one row, wrapping to their own lines on a narrow
   screen rather than shrinking. The margin moves to the row so the buttons
   do not stack their own top margins when they wrap. */
.empty-acts{display:flex;flex-wrap:wrap;justify-content:center;gap:.5rem;margin-top:1.1rem}
.empty-acts .btn{margin-top:0}

.skel{background:linear-gradient(90deg,var(--surface-2) 25%,var(--border) 50%,var(--surface-2) 75%);
  background-size:200% 100%;animation:shimmer 1.3s linear infinite;border-radius:3px;
  height:.85rem;display:block}
@keyframes shimmer{to{background-position:-200% 0}}

/* ══ NOTES ════════════════════════════════════════════════════════ */
.note{display:flex;gap:10px;padding:.85rem 1rem;border-radius:6px;font-size:.85rem;
  line-height:1.6;border:1px solid var(--chip-bd);background:var(--chip-bg);color:var(--text);
  margin-bottom:14px}
.note svg{width:15px;height:15px;flex:0 0 15px;margin-top:.24rem;color:var(--chip-tx)}
.note.ok{border-color:var(--ok-bd);background:var(--ok-bg)}.note.ok svg{color:var(--ok)}
.note.warn{border-color:var(--warn-bd);background:var(--warn-bg)}.note.warn svg{color:var(--warn)}
.note.bad{border-color:var(--bad-bd);background:var(--bad-bg)}.note.bad svg{color:var(--bad)}
.note b{font-weight:500}
.note a{color:var(--accent-hi);text-decoration:underline;text-underline-offset:2px}
.note code{font-family:var(--mono);font-size:.79rem}

/* ══ FORMS ════════════════════════════════════════════════════════ */
.field{margin-bottom:1rem}
.field label{display:block;font-family:var(--mono);font-size:.66rem;letter-spacing:.12em;
  text-transform:uppercase;color:var(--muted);margin-bottom:.4rem}
.field .hint{font-size:.78rem;color:var(--faint);margin-top:.35rem;line-height:1.5}
input[type=text],input[type=email],input[type=password],select,textarea{
  width:100%;background:var(--bg);border:1px solid var(--border);border-radius:4px;
  padding:.6rem .75rem;font-size:.88rem;color:var(--text);
  transition:border-color .2s,background .2s}
textarea{resize:vertical;min-height:80px;line-height:1.6}
input:focus,select:focus,textarea:focus{outline:none;border-color:var(--accent)}
input:disabled,select:disabled{color:var(--muted);background:var(--surface-2);cursor:not-allowed}
input::placeholder,textarea::placeholder{color:var(--faint)}
select{appearance:none;cursor:pointer;
  background-image:linear-gradient(45deg,transparent 50%,var(--muted) 50%),
                   linear-gradient(135deg,var(--muted) 50%,transparent 50%);
  background-position:calc(100% - 16px) 52%,calc(100% - 11px) 52%;
  background-size:5px 5px,5px 5px;background-repeat:no-repeat;padding-right:2rem}
.field-row{display:grid;grid-template-columns:1fr 1fr;gap:1rem}
@media(max-width:560px){.field-row{grid-template-columns:1fr}}
.check{display:flex;gap:10px;align-items:flex-start;padding:.7rem 0;cursor:pointer}
.check input{width:16px;height:16px;flex:0 0 16px;margin-top:.2rem;accent-color:var(--accent);
  cursor:pointer}
.check .t{font-size:.87rem;line-height:1.5}
.check .t .d{display:block;font-size:.79rem;color:var(--muted);margin-top:.2rem;line-height:1.5}
.form-msg{font-size:.83rem;line-height:1.55;margin-top:.9rem;padding:.6rem .75rem;
  border-radius:4px;display:none}
.form-msg.show{display:block}
.form-msg.err{background:var(--bad-bg);border:1px solid var(--bad-bd);color:var(--bad)}
.form-msg.ok{background:var(--ok-bg);border:1px solid var(--ok-bd);color:var(--ok)}
.form-msg.info{background:var(--chip-bg);border:1px solid var(--chip-bd);color:var(--chip-tx)}

/* ══ LICENSE KEY ══════════════════════════════════════════════════ */
.keyline{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.keybox{font-family:var(--mono);font-size:.92rem;letter-spacing:.06em;color:var(--text);
  background:var(--bg);border:1px solid var(--border);border-radius:4px;padding:.5rem .7rem;
  user-select:all;white-space:nowrap;overflow-x:auto;max-width:100%}
.keybox.masked{color:var(--muted);letter-spacing:.1em}

/* ══ AUTH SCREEN ══════════════════════════════════════════════════ */
.auth{min-height:100vh;display:grid;grid-template-columns:1fr 1fr;position:relative}
@media(max-width:940px){.auth{grid-template-columns:1fr}.auth-aside{display:none}}
.auth-aside{position:relative;overflow:hidden;border-right:1px solid var(--border);
  background:var(--surface);padding:clamp(40px,5vw,64px);display:flex;flex-direction:column;
  justify-content:center}
.grid-bg{position:absolute;inset:0;z-index:0;
  background-image:linear-gradient(var(--grid-line) 1px,transparent 1px),
                   linear-gradient(90deg,var(--grid-line) 1px,transparent 1px);
  background-size:44px 44px;
  -webkit-mask-image:radial-gradient(ellipse 74% 62% at 40% 42%,#000 30%,transparent 100%);
  mask-image:radial-gradient(ellipse 74% 62% at 40% 42%,#000 30%,transparent 100%)}
.glow{position:absolute;top:16%;left:34%;width:520px;height:520px;border-radius:50%;z-index:0;
  pointer-events:none;
  background:radial-gradient(circle,color-mix(in srgb,var(--accent) 13%,transparent) 0%,transparent 70%)}
.auth-aside .in{position:relative;z-index:1;max-width:440px}
.auth-aside h2{font-size:clamp(1.5rem,2.6vw,2rem);letter-spacing:-.03em;margin:1rem 0 .8rem}
.auth-aside h2 span{color:var(--accent-hi)}
.auth-aside p{font-size:.95rem;color:var(--muted);line-height:1.7}
.auth-pts{list-style:none;margin-top:2rem;border-top:1px solid var(--border)}
.auth-pts li{display:grid;grid-template-columns:118px 1fr;gap:1rem;padding:.85rem 0;
  border-bottom:1px solid var(--border);align-items:baseline}
.auth-pts .k{font-family:var(--mono);font-size:.72rem;color:var(--accent-hi);letter-spacing:.04em}
.auth-pts .v{font-size:.86rem;color:var(--muted);line-height:1.6}
@media(max-width:1100px){.auth-pts li{grid-template-columns:1fr;gap:.2rem}}

.auth-main{display:flex;flex-direction:column;padding:clamp(24px,4vw,48px);position:relative}
.auth-top{display:flex;align-items:center;gap:12px;margin-bottom:auto}
.auth-top .brand{margin-right:auto}
.auth-card{width:100%;max-width:400px;margin:2.5rem auto;padding:0}
.auth-card h1{font-size:1.45rem;letter-spacing:-.025em;margin-bottom:.4rem}
.auth-card .sub{font-size:.89rem;color:var(--muted);margin-bottom:1.7rem;line-height:1.6}
.auth-tabs{display:flex;gap:2px;padding:3px;background:var(--surface-2);border:1px solid var(--border);
  border-radius:5px;margin-bottom:1.6rem}
.auth-tabs button{flex:1;padding:.5rem;border:0;background:none;border-radius:3px;
  font-size:.83rem;font-weight:500;letter-spacing:.03em;color:var(--muted);cursor:pointer;
  transition:background .18s,color .18s}
.auth-tabs button[aria-selected=true]{background:var(--bg);color:var(--text);
  box-shadow:0 1px 2px rgba(13,15,18,.06)}
.auth-alt{margin-top:1.4rem;font-size:.83rem;color:var(--muted);text-align:center}
.auth-alt button{background:none;border:0;color:var(--accent-hi);cursor:pointer;font-size:.83rem;
  padding:0}
.auth-alt button:hover{text-decoration:underline;text-underline-offset:2px}
.auth-foot{margin-top:auto;padding-top:2rem;font-size:.76rem;color:var(--faint);
  display:flex;gap:1.2rem;flex-wrap:wrap}
.auth-foot a:hover{color:var(--accent-hi)}

/* ══ CHART ════════════════════════════════════════════════════════ */
.chart{width:100%;height:auto;display:block;overflow:visible}
.chart .ax{stroke:var(--border);stroke-width:1}
.chart .gl{stroke:var(--grid-line);stroke-width:1}
.chart .bar{fill:var(--plot);transition:fill .15s}
.chart .bar:hover{fill:var(--accent-hi)}
.chart .tick{font-family:var(--mono);font-size:9px;fill:var(--faint)}
.legend{display:flex;gap:1.1rem;flex-wrap:wrap;margin-top:.9rem;font-size:.76rem;color:var(--muted)}
.legend i{display:inline-block;width:9px;height:9px;border-radius:2px;margin-right:6px;
  vertical-align:-1px}

/* ══ TIMELINE ═════════════════════════════════════════════════════ */
.tl{list-style:none}
.tl li{display:grid;grid-template-columns:104px 1fr;gap:1rem;padding:.7rem 1.15rem;
  border-bottom:1px solid var(--border);align-items:baseline}
.tl li:last-child{border-bottom:0}
.tl .when{font-family:var(--mono);font-size:.72rem;color:var(--faint);white-space:nowrap}
.tl .what{font-size:.86rem;color:var(--muted);line-height:1.55}
.tl .what b{color:var(--text);font-weight:500;font-family:var(--mono);font-size:.8rem}
@media(max-width:520px){.tl li{grid-template-columns:1fr;gap:.2rem}}

/* ══ PLAN CARDS ═══════════════════════════════════════════════════ */
/* The plans page is the one route whose content is a comparison rather than
   prose, so it gets a wider column than the 1080px reading measure. At 1080
   six SKUs landed as 4 + 2 -- two rows of different card widths -- and the
   cards were narrow enough that nearly every bullet wrapped to two lines,
   which is what made them hard to read. The prose on the page keeps the
   reading width; only the grid takes the extra. */
#route[data-route="plans"]{max-width:1300px}
#route[data-route="plans"] .route > .note,
#route[data-route="plans"] .route > .panel{max-width:880px}

/* Three columns, then two, then one -- and never four, which is what the
   cards were before and what made them narrow. The count is a container
   query rather than a viewport one because the width that decides it is the
   route column, which the rail and the page padding both eat into; a
   viewport breakpoint would have to restate both and drift when either
   changes. The wrapper exists only to be the container -- an element cannot
   query itself. The thresholds are three and two times the ~330px at which
   the longest bullet stops wrapping, plus the gaps. */
.plans-wrap{container-type:inline-size}
.plans{display:grid;grid-template-columns:1fr;gap:16px}
@container (min-width:1020px){.plans{grid-template-columns:repeat(3,1fr)}}
@container (min-width:680px) and (max-width:1019.98px){.plans{grid-template-columns:repeat(2,1fr)}}
.plan{background:var(--surface);border:1px solid var(--border);border-radius:6px;padding:1.4rem;
  display:flex;flex-direction:column;transition:border-color .2s,transform .2s}
.plan:hover{border-color:var(--accent);transform:translateY(-2px)}
.plan.current{border-color:var(--accent)}
.plan .pn{font-size:1rem;margin-bottom:.3rem}
.plan .pt{font-size:.83rem;color:var(--muted);line-height:1.55;margin-bottom:.85rem;min-height:2.6em}
.plan .pp{font-family:var(--mono);font-size:1.45rem;color:var(--text);line-height:1;
  margin-bottom:.3rem;font-variant-numeric:tabular-nums}
.plan .pp small{font-size:.74rem;color:var(--muted);letter-spacing:.04em}
/* The undiscounted price, struck through. Smaller and dimmed so the price
   that is actually charged stays the one the eye lands on -- a strike-through
   at the same weight reads as two prices rather than as an offer. `s` rather
   than a styled span so it is still struck for a screen reader. */
.plan .pp .was{font-size:.92rem;color:var(--faint);opacity:.8;margin-right:.4rem;
  text-decoration:line-through;text-decoration-thickness:1px}
/* The recurring half of a two-part price. Smaller than .pp and above .pmeta,
   so it reads as a continuation of the price rather than as a second one. */
.plan .pren{font-family:var(--mono);font-size:.86rem;color:var(--muted);
  margin:-.35rem 0 .5rem;line-height:1.3}
.plan .pren s{color:var(--faint);opacity:.8;text-decoration:line-through;
  text-decoration-thickness:1px;margin-right:.25rem}
.plan .pren small{font-size:.72rem;color:var(--faint);letter-spacing:.04em}
.plan .pmeta{font-size:.78rem;color:var(--faint);margin-bottom:.9rem}
/* THE INTEGRATION HOURS. The one thing on a team card that is not software,
   so it does not look like the software: a tinted block in the accent chip
   colours, sitting between the price and the bullets. The hour count is set
   in mono at price weight because it is the second number on the card the
   customer is comparing between SKUs -- the first being the price. */
.plan .pint{background:var(--chip-bg);border:1px solid var(--chip-bd);border-radius:5px;
  padding:.7rem .8rem;margin-bottom:.9rem}
.plan .pint .ph{font-family:var(--mono);font-size:1.05rem;color:var(--chip-tx);line-height:1.1;
  font-variant-numeric:tabular-nums}
/* The recurring top-up, set smaller and beside the base so the pair reads as
   one promise rather than as two competing numbers. */
.plan .pint .ph .plus{font-size:.78rem;opacity:.85;letter-spacing:.02em}
.plan .pint .pl{font-family:var(--mono);font-size:.66rem;letter-spacing:.09em;
  text-transform:uppercase;color:var(--chip-tx);opacity:.75;margin-top:.28rem}
.plan .pint p{font-size:.79rem;color:var(--muted);line-height:1.5;margin-top:.5rem}
/* Tighter than it was: with the wider card a bullet is one line, and the
   padding that kept two wrapped lines apart now only pads empty space. */
.plan ul{list-style:none;margin-bottom:1rem;flex:1}
.plan li{font-size:.83rem;color:var(--muted);padding:.22rem 0 .22rem 1.1rem;position:relative;
  line-height:1.5}
.plan li::before{content:"";position:absolute;left:0;top:.68rem;width:4px;height:4px;
  border-radius:50%;background:var(--accent-hi)}
/* THE REDISTRIBUTION RIGHT. On a team SKU this is the line the customer is
   scanning for -- the right to ship the SDK inside their own product is what
   separates these from every other plan -- so it is lifted out of the list
   rather than set like the five bullets around it. Same chip colours as the
   integration-hours block, because it is the same kind of claim: a term of
   the licence, not a feature of the software. */
.plan li.hi{color:var(--chip-tx);font-weight:500;background:var(--chip-bg);
  border:1px solid var(--chip-bd);border-radius:5px;
  padding:.4rem .6rem .4rem 1.35rem;margin:.3rem 0}
.plan li.hi::before{left:.6rem;top:.95rem;width:5px;height:5px;background:var(--chip-tx)}
/* Why a claim button is disabled, or what pressing it will actually do.
   It sits under the action rather than in the bullets because it is about
   this account, not about the SKU. */
.plan .why{font-size:.78rem;color:var(--faint);line-height:1.5;margin-top:.6rem}

/* ══ TOAST ════════════════════════════════════════════════════════ */
#toast{position:fixed;right:20px;bottom:20px;z-index:300;display:flex;flex-direction:column;
  gap:8px;align-items:flex-end;pointer-events:none}
.toast{background:var(--surface);border:1px solid var(--border);border-left-width:2px;
  border-radius:5px;box-shadow:var(--shadow);padding:.7rem 1rem;font-size:.85rem;
  max-width:340px;line-height:1.5;animation:slide .22s cubic-bezier(.2,.7,.3,1) both}
.toast.ok{border-left-color:var(--ok)}
.toast.err{border-left-color:var(--bad)}
.toast.info{border-left-color:var(--accent)}
@keyframes slide{from{opacity:0;transform:translateX(14px)}to{opacity:1;transform:none}}

/* ══ MODAL ════════════════════════════════════════════════════════ */
.modal{position:fixed;inset:0;z-index:400;display:grid;place-items:center;padding:20px;
  background:rgba(13,15,18,.55);backdrop-filter:blur(3px)}
.modal-box{width:100%;max-width:420px;background:var(--bg);border:1px solid var(--border);
  border-radius:6px;box-shadow:var(--shadow);overflow:hidden;
  animation:pop .18s cubic-bezier(.2,.7,.3,1) both}
@keyframes pop{from{opacity:0;transform:scale(.97)}to{opacity:1;transform:none}}
.modal-box h2{font-size:1rem;padding:1.1rem 1.25rem .2rem}
.modal-box .bd{padding:.4rem 1.25rem 1.1rem;font-size:.87rem;color:var(--muted);line-height:1.6}
.modal-box .bd b{color:var(--text);font-weight:500}
.modal-box .ft{display:flex;gap:8px;justify-content:flex-end;padding:.9rem 1.25rem;
  border-top:1px solid var(--border);background:var(--surface)}

/* ══ MISC ═════════════════════════════════════════════════════════ */
.grid-2{display:grid;grid-template-columns:1fr 1fr;gap:14px;align-items:start}
@media(max-width:860px){.grid-2{grid-template-columns:1fr}}
.route{animation:up .32s ease both}
@keyframes up{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
.sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0,0,0,0);white-space:nowrap;border:0}

@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;
    transition-duration:.01ms!important}
}
