/* Fonts are NOT imported here. The @import that used to sit on this line hid the
   font stylesheet from the preload scanner, serialising two round trips; it now
   loads from a <link> in base.tmpl's head. Do not reintroduce it. */
/* Shared: design tokens, light-theme overrides, typography, polish, footer, controls, copy. */
/* Canonical dark design tokens (single source of truth for every page). */
/* The brand accent was defined TWICE with different values: this file used
   #3fdc7a (grass) while index.tmpl used #2fe0ad (mint), so the same "Start free"
   button was a visibly different green on the landing page than in the docs.
   Aligned to the landing's palette, which is the current brand. */
:root {
  --bg:#070a0f; --panel:#10151e; --panel-2:#151c27; --border:#1f2937; --border-hi:#2b3a4d;
  --fg:#e9eef5; --muted:#8a97a8; --accent:#2fe0ad; --accent2:#3cc6f0; --accent-ink:#04120d; --bad:#f85149; --warn:#e3b341;
  --input-bg:#05080d;
  --font-display:'Space Grotesk','Inter',ui-sans-serif,system-ui,sans-serif;
  --font-mono:'JetBrains Mono',ui-monospace,Menlo,Consolas,monospace;
  --grad:linear-gradient(100deg,#3fdc7a,#54a8ff);
  --glow:0 0 0 1px rgba(63,220,122,.0), 0 18px 50px -24px rgba(0,0,0,.75);
  color-scheme: dark;
}
html[data-theme="light"] {
  /* The light theme's two accents carry text and they were both below AA:
     --accent was 3.49:1 (as a link colour on white, and as the fill under the
     white text of every primary CTA) and --accent2 was 3.44:1 on --bg, against a
     4.5:1 requirement for normal text. Nothing was wrong with the DARK values —
     these tokens are already theme-specific precisely so each can be legible on
     its own background; the light pair simply was not taken far enough.
     Darkened along the same hue to 5.77:1 and 6.02:1 on white — with headroom,
     because these tints get used as backgrounds UNDER their own colour (the docs
     method badges) and a 5.1 token leaves nothing left once the fill lifts it. --fg (17.79:1) and --muted
     (5.79:1) always passed, so body copy never changed.
     TestLightThemeAccentsMeetContrast pins all four. */
  --bg:#f6f8fb; --panel:#ffffff; --panel-2:#f1f4f9; --border:#e3e8ef; --border-hi:#cfd8e3;
  --fg:#0d1117; --muted:#586273; --accent:#087454; --accent2:#0a6a92; --accent-ink:#ffffff; --bad:#cf222e; --warn:#8f6300;
  --input-bg:#eef2f7;
  color-scheme: light;
}
/* Distinctive display type + monospaced code, applied site-wide. */
h1, h2, h3, .display { font-family: var(--font-display); letter-spacing: -.02em; }
code, pre, kbd, samp { font-family: var(--font-mono); }
/* In light mode the accent green is dark, so accent-filled controls need light
   text (avoids dark-text-on-dark-button). */
html[data-theme="light"] .btn.primary,
html[data-theme="light"] button.submit,
html[data-theme="light"] .plan-badge,
html[data-theme="light"] .plan .badge,
html[data-theme="light"] .pb-skip { color:#fff; }
html[data-theme="light"] ::selection { background: var(--accent); color:#fff; }
body {
  /* The browser's default 8px body margin was never reset here, only in
     index.tmpl. Every page except the landing therefore inset the sticky header
     8px from the top and both edges, so the same bar sat lower and narrower on
     /docs than on / — the last of the "why does the nav look different" set. */
  margin: 0;
  /* STATE the canvas colours. They were never declared anywhere: :root only set
     `color-scheme: dark`, so the dark page you see was painted by user-agent
     convention, not by this stylesheet. Nothing in the document declared a
     background at all — walking a flagged element's ancestors returned an empty
     list and documentElement computed rgba(0,0,0,0).
     That made /docs *look* right while being wrong: every contrast tool resolves
     an undeclared background to white and scored the whole page at 1.16:1 (184
     axe nodes), and forced-colors mode, a UA that reads color-scheme differently,
     or any embedding context would have rendered black-on-white for real.
     The transition below has referenced `background` since it was written — this
     rule finally gives it something to transition. */
  background: var(--bg);
  color: var(--fg);
  font-family: 'Inter', ui-sans-serif, system-ui, 'Segoe UI', Roboto, sans-serif;
  -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility;
  transition: background .2s ease, color .2s ease;
}
/* Mobile: keep the layout at viewport width so browsers don't shrink-to-fit the
   whole page ("zoomed out"). overflow-x: clip — NOT hidden — because hidden makes
   a scroll container that breaks the sticky nav/topbar/sidebars; clip just trims
   the stray horizontal overflow. Genuinely wide content (tables, code samples)
   already scrolls inside its own overflow-x:auto box, so nothing becomes
   unreachable. The img rule stops an oversized image from forcing the same. */
html, body { overflow-x: clip; }
img { max-width: 100%; height: auto; }
::selection { background: var(--accent); color: #06210f; }

/* nicer scrollbars */
* { scrollbar-width: thin; scrollbar-color: var(--border) transparent; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 6px; }
::-webkit-scrollbar-thumb:hover { background: var(--muted); }

/* micro-interactions (reduced-motion users are exempted below) */
.btn, .plan, .card, .pb-theme { transition: transform .15s ease, border-color .15s ease, box-shadow .15s ease, filter .15s ease; }
.btn:hover { transform: translateY(-1px); }
.card:hover { transform: translateY(-3px); border-color: var(--accent2); box-shadow: 0 10px 30px -16px rgba(0,0,0,.6); }
.plan:hover { transform: translateY(-4px); box-shadow: 0 16px 40px -20px rgba(0,0,0,.7); }

/* "most popular" badge */
.plan { position: relative; }
.plan .badge {
  position: absolute; top: -12px; left: 50%; transform: translateX(-50%);
  background: var(--grad); color: #06210f;
  font-size: 11px; font-weight: 800; letter-spacing: .5px; text-transform: uppercase;
  padding: 4px 12px; border-radius: 20px; white-space: nowrap;
}

/* hero code tabs */
.codetabs { max-width: 760px; margin: 8px auto 0; text-align: left; }
.codetabs .tabs { display: flex; gap: 4px; }
.codetabs .tab {
  background: transparent; border: 1px solid var(--border); border-bottom: none;
  color: var(--muted); padding: 7px 16px; border-radius: 8px 8px 0 0; cursor: pointer;
  font: 600 13px/1 'Inter', sans-serif;
}
/* the active tab joins the always-dark code block, so its text stays light in both themes */
.codetabs .tab.active { background: #05080d; color: #e6edf3; border-color: var(--border); }
.codetabs pre { margin-top: -1px; border-top-left-radius: 0; }

/* trust pills row */
.trust { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; margin: 22px 0 4px; }
.trust .t {
  font-size: 13px; color: var(--muted); border: 1px solid var(--border);
  background: var(--panel); padding: 5px 12px; border-radius: 20px;
}

/* mobile nav drawer */
.nav-toggle{display:none;background:transparent;border:1px solid var(--border);border-radius:8px;color:var(--fg);font-size:18px;line-height:1;padding:6px 11px;cursor:pointer}
@media (max-width:760px){
  nav{position:relative}
  /* glass dropdown card anchored under the bar */
  nav .nav-links{position:absolute;left:0;right:0;top:calc(100% + 10px);
    background:rgba(12,16,24,.97);backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);
    border:1px solid var(--border);border-radius:16px;
    flex-direction:column;align-items:stretch;gap:2px;padding:10px;display:none;z-index:60;
    box-shadow:0 28px 60px -28px rgba(0,0,0,.85)}
  nav .nav-links.open{display:flex;animation:navdrop .16s ease}
  @keyframes navdrop{from{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:none}}
  nav .nav-links > a{padding:13px 14px;border-radius:11px;font-size:15px;font-weight:500;color:var(--fg)}
  nav .nav-links > a:not(.btn):hover{background:var(--panel-2);text-decoration:none}
  nav .nav-links > a.btn{margin-top:6px;justify-content:center}
  nav .nav-links > a.btn.primary{box-shadow:0 8px 24px -10px rgba(63,220,122,.5)}
  nav .nav-links .pb-controls{margin-top:8px;padding:10px 6px 4px;justify-content:flex-start;border-top:1px solid var(--border)}
  nav .nav-links .pb-lang{width:auto}
  .nav-toggle{display:inline-flex}
}
@media (min-width:761px){
  nav .nav-links{display:flex;align-items:center;gap:4px}
  /* text links read as nav items (muted, pill hover), not generic blue links */
  nav .nav-links > a:not(.btn){color:var(--muted);font-weight:500;font-size:14.5px;padding:9px 12px;border-radius:9px;
    transition:color .15s ease, background .15s ease}
  nav .nav-links > a:not(.btn):hover{color:var(--fg);background:var(--panel);text-decoration:none}
  nav .nav-links > .btn{padding:9px 16px;font-size:14.5px;margin-left:4px}
  /* divider between the actions and the utility controls (lang/theme) */
  nav .nav-links .pb-controls{margin-left:10px;padding-left:12px;border-left:1px solid var(--border)}
}

/* comparison table */
.compare{max-width:900px;margin:0 auto;overflow-x:auto}
.compare table{width:100%;border-collapse:collapse;background:var(--panel);border:1px solid var(--border);border-radius:14px;overflow:hidden;min-width:560px}
.compare th,.compare td{padding:13px 16px;text-align:left;border-bottom:1px solid var(--border);font-size:14px}
.compare thead th{font-size:13px;color:var(--muted);text-transform:uppercase;letter-spacing:.5px}
.compare td.us,.compare th.us{background:rgba(63,185,80,.08)}
.compare th.us{color:var(--accent)}
.compare td.good{color:var(--accent)}.compare td.bad{color:var(--muted)}
.compare tr td:first-child{color:var(--muted)}

/* cost calculator */
.calc{max-width:760px;margin:0 auto;background:linear-gradient(180deg,var(--panel),var(--panel-2));border:1px solid var(--border);border-radius:18px;padding:28px}
.calc label{display:flex;align-items:baseline;justify-content:space-between;gap:10px;color:var(--muted);font-size:13.5px;margin-bottom:16px}
.calc .reqval{font-size:27px;font-weight:800;font-family:var(--font-display);background:var(--grad);-webkit-background-clip:text;background-clip:text;color:transparent;letter-spacing:-.01em}
/* custom range slider: thin gradient-filled track + clean ring thumb */
.calc input[type=range]{-webkit-appearance:none;appearance:none;width:100%;height:8px;border-radius:999px;cursor:pointer;outline:none;margin:6px 0 2px;
  background:var(--border);background-image:var(--grad);background-repeat:no-repeat;background-size:var(--fill,2%) 100%}
.calc input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:22px;height:22px;border-radius:50%;
  background:#fff;border:4px solid var(--accent);box-shadow:0 3px 10px -2px rgba(0,0,0,.6);transition:transform .12s ease}
.calc input[type=range]:hover::-webkit-slider-thumb{transform:scale(1.12)}
.calc input[type=range]:active::-webkit-slider-thumb{transform:scale(1.04);cursor:grabbing}
.calc input[type=range]:focus-visible::-webkit-slider-thumb{box-shadow:0 0 0 4px rgba(63,220,122,.3)}
.calc input[type=range]::-moz-range-thumb{width:18px;height:18px;border-radius:50%;background:#fff;border:4px solid var(--accent);box-shadow:0 3px 10px -2px rgba(0,0,0,.6)}
.calc input[type=range]::-moz-range-track{height:8px;border-radius:999px;background:var(--border)}
.calc input[type=range]::-moz-range-progress{height:8px;border-radius:999px;background:var(--accent)}
.calc .ticks{display:flex;justify-content:space-between;color:var(--muted);font-size:11.5px;margin:8px 2px 0;font-family:var(--font-mono)}
.calc .grid{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-top:24px}
@media(max-width:560px){.calc .grid{grid-template-columns:1fr}}
.calc .q{border:1px solid var(--border);border-radius:14px;padding:18px 16px;text-align:center;background:var(--bg);transition:border-color .15s ease,transform .15s ease}
.calc .q.us{border-color:rgba(63,220,122,.5);background:rgba(63,220,122,.07);box-shadow:0 0 0 1px rgba(63,220,122,.12)}
.calc .q .name{font-size:12px;text-transform:uppercase;letter-spacing:.6px;color:var(--muted)}
.calc .q .price{font-size:25px;font-weight:800;font-family:var(--font-display);margin-top:7px}
.calc .q.us .price{background:var(--grad);-webkit-background-clip:text;background-clip:text;color:transparent}
.calc .save{text-align:center;margin-top:22px;font-size:15px;color:var(--muted)}
.calc .save b{color:var(--accent);font-size:18px}

/* toast notifications */
#pb-toasts{position:fixed;bottom:18px;right:18px;display:flex;flex-direction:column;gap:8px;z-index:200;max-width:min(360px,90vw)}
.pb-toast{background:var(--panel);border:1px solid var(--border);border-left:3px solid var(--accent);border-radius:9px;
  padding:11px 14px;color:var(--fg);font-size:14px;box-shadow:0 12px 32px -14px rgba(0,0,0,.65);animation:pbtoast .2s ease;
  display:flex;align-items:flex-start;gap:12px}
.pb-toast.err{border-left-color:var(--bad)}
/* WCAG 2.2.1: the dismiss control. Not decoration — a message that removes itself
   after 2.6s has to be pausable, extendable OR dismissible, and this is the one of
   the three a keyboard user can actually reach. */
.pb-toast-x{flex:none;margin-left:auto;background:none;border:0;padding:0 1px;cursor:pointer;
  color:var(--muted);font:inherit;font-size:17px;line-height:1.2}
.pb-toast-x:hover{color:var(--fg)}
@keyframes pbtoast{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}

/* in-app modal dialog (pbConfirm / pbAlert) */
.pb-modal-ov{position:fixed;inset:0;z-index:300;display:grid;place-items:center;padding:20px;overflow:auto;
  background:rgba(3,6,11,.72);opacity:0;transition:opacity .16s ease}
.pb-modal-ov.open{opacity:1}
.pb-modal{position:relative;z-index:1;width:100%;max-width:440px;background:var(--panel);border:1px solid var(--border-hi);border-radius:16px;
  padding:24px;box-shadow:0 40px 90px -40px rgba(0,0,0,.9)}
.pb-modal-title{font-family:var(--font-display);font-size:19px;font-weight:700;margin:0 0 8px;letter-spacing:-.01em}
.pb-modal-msg{color:var(--muted);font-size:14.5px;line-height:1.6;margin:0 0 22px}
.pb-modal-actions{display:flex;gap:10px;justify-content:flex-end;flex-wrap:wrap}
.pb-modal-actions .btn{padding:9px 18px;border-radius:9px;border:1px solid var(--border);background:var(--panel);color:var(--fg);font-weight:600;cursor:pointer;font:inherit;font-size:14px}
.pb-modal-actions .btn:hover{border-color:var(--border-hi)}
.pb-modal-actions .btn.primary{background:var(--accent);color:#04220f;border-color:transparent}
.pb-modal-actions .btn.pb-modal-danger{background:var(--bad);color:#fff;border-color:transparent}
.pb-modal-actions .btn.pb-modal-danger:hover{filter:brightness(1.08)}
@media (max-width:520px){
  .pb-modal-actions{flex-direction:column-reverse;flex-wrap:nowrap}
  .pb-modal-actions .btn{width:100%}
}

/* usage progress bar (dashboard) */
.progress { height: 8px; border-radius: 6px; background: var(--border); overflow: hidden; margin-top: 8px; }
.progress > span { display: block; height: 100%; background: var(--grad); border-radius: 6px; }

/* accessibility */
.pb-skip {
  position:absolute; left:-9999px; top:8px; z-index:1000;
  background:var(--accent); color:#06210f; padding:10px 16px; border-radius:8px; font-weight:700;
}
.pb-skip:focus { left:8px; }
/* Text for screen readers only. Not `display:none` and not `visibility:hidden` —
   both remove the element from the accessibility tree, which is the opposite of
   the point. This is the standard clip-rect recipe: laid out, painted, and
   read aloud, but occupying no visible space. */
.pb-sr {
  position:absolute !important; width:1px; height:1px; overflow:hidden;
  clip:rect(0 0 0 0); clip-path:inset(50%); white-space:nowrap; border:0; padding:0; margin:-1px;
}
a:focus-visible, button:focus-visible, select:focus-visible, input:focus-visible,
textarea:focus-visible, [tabindex]:focus-visible, summary:focus-visible {
  outline:2px solid var(--accent2); outline-offset:2px; border-radius:4px;
}
/* The skip link's target. <main> is not focusable, so a fragment jump moves the
   scroll position but leaves focus on <body> — the next Tab then lands back at
   the top of the nav and the skip link has skipped nothing. tabindex="-1" in the
   markup makes it a focus target; this suppresses the ring it would otherwise
   draw around the entire page. */
main:focus { outline:none; }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition:none !important; animation:none !important; scroll-behavior:auto !important; }
}

/* polished native <select> (daisyUI-style): custom chevron, token colours, focus
   ring. Excludes .pb-lang, which is upgraded to the .pb-dd component by JS. */
select:not(.pb-lang) {
  -webkit-appearance:none; -moz-appearance:none; appearance:none;
  background-color:var(--panel); color:var(--fg);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%238a97a8' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right 11px center;
  border:1px solid var(--border); border-radius:9px;
  padding:9px 34px 9px 12px; font:inherit; font-size:14px; line-height:1.2; cursor:pointer;
}
select:not(.pb-lang):hover { border-color:var(--border-hi); }
select:not(.pb-lang):focus { outline:none; border-color:var(--accent2); box-shadow:0 0 0 3px rgba(84,168,255,.15); }
select:not(.pb-lang) option { background:var(--panel); color:var(--fg); }

/* nav controls — sized to align with the nav buttons (consistent 38px height) */
.pb-controls { display:inline-flex; gap:8px; align-items:center; }
.pb-theme {
  background:transparent; border:1px solid var(--border); color:var(--muted);
  border-radius:9px; width:38px; height:38px; display:inline-grid; place-items:center;
  cursor:pointer; line-height:1;
}
.pb-theme:hover { border-color:var(--border-hi); color:var(--fg); }
.pb-theme .i { width:16px; height:16px; display:block; }
.pb-lang {
  background:var(--panel); border:1px solid var(--border); color:var(--fg);
  border-radius:9px; padding:0 10px; height:38px; font:inherit; font-size:13px; cursor:pointer;
}

/* copy button on code blocks */
.pb-copy {
  position:absolute; top:8px; right:8px; background:rgba(20,26,34,.85);
  border:1px solid var(--border); color:#c7d0db; border-radius:7px;
  padding:5px; line-height:0; cursor:pointer; opacity:.8; transition:.15s; display:inline-grid; place-items:center;
}
.pb-copy svg { width:15px; height:15px; display:block; }
/* 27x27 is too small to hit with a thumb, and the code block clips overflow so a
   transparent ::after overlay gets cut off before it reaches 44px. Grow the
   button itself, only on touch/narrow viewports — the desktop look is untouched. */
@media (hover:none),(max-width:760px){ .pb-copy { padding:14px; } }
.pb-copy:hover { opacity:1; border-color:var(--accent2); color:#fff; }
.pb-copy.ok { opacity:1; color:var(--accent); border-color:var(--accent); }

/* footer */
.pb-footer { border-top:1px solid var(--border); margin-top:80px; background:var(--panel); }
.pb-footer .cols {
  max-width:1080px; margin:0 auto; padding:48px 24px 24px;
  display:grid; grid-template-columns:2fr 1fr 1fr 1fr; gap:32px;
}
.pb-footer .brand .logo { font-weight:800; font-size:18px; }
.pb-footer .brand .logo .b { color:var(--accent); }
/* the S mark next to the wordmark, sized in em so it scales with the logo */
.logo-mark { width:1.2em; height:1.2em; vertical-align:-.22em; margin-right:.42em; }
.logo { display:inline-flex; align-items:center; }
.pb-footer .brand p { color:var(--muted); font-size:14px; max-width:260px; }
/* h2, not h3: these are the footer's own top-level column headings, and on a page
   whose body stops at <h1> (the dashboard's Projects view) an <h3> here skipped a
   level — axe flagged heading-order on the footer of a page whose footer had not
   changed. Going back UP a level after a page's own h2/h3 sections is always valid;
   skipping DOWN one is not. */
.pb-footer h2 { font-size:12px; text-transform:uppercase; letter-spacing:1px; color:var(--muted); margin:0 0 12px; }
.pb-footer a { display:block; color:var(--fg); opacity:.8; text-decoration:none; padding:4px 0; font-size:14px; }
.pb-footer a:hover { opacity:1; color:var(--accent2); }
.pb-footer .bar {
  border-top:1px solid var(--border); max-width:1080px; margin:0 auto;
  padding:18px 24px; display:flex; gap:16px; align-items:center; color:var(--muted); font-size:13px;
}
.pb-footer .bar .sp { flex:1; }
@media (max-width:760px) { .pb-footer .cols { grid-template-columns:1fr 1fr; } }

/* language dropdown (daisyUI-style, replaces the native .pb-lang select) */
.pb-dd { position:relative; display:inline-block; }
.pb-dd-btn {
  display:inline-flex; align-items:center; gap:6px; cursor:pointer; height:38px;
  background:var(--panel); border:1px solid var(--border); color:var(--fg);
  border-radius:9px; padding:0 12px; font:600 13px/1 'Inter', sans-serif;
}
.pb-dd-btn::after { content:"▾"; font-size:10px; color:var(--muted); margin-left:2px; }
.pb-dd-btn:hover { border-color:var(--border-hi); }
.pb-dd-menu {
  position:absolute; right:0; top:calc(100% + 6px); z-index:120; min-width:160px;
  list-style:none; margin:0; padding:6px;
  background:var(--panel); border:1px solid var(--border); border-radius:10px;
  box-shadow:0 18px 40px -20px rgba(0,0,0,.7);
  opacity:0; transform:translateY(-6px); pointer-events:none; transition:opacity .14s ease, transform .14s ease;
}
.pb-dd.open .pb-dd-menu { opacity:1; transform:none; pointer-events:auto; }
.pb-dd-menu li {
  padding:8px 11px; border-radius:7px; font-size:14px; color:var(--fg); cursor:pointer;
  display:flex; align-items:center; justify-content:space-between; gap:10px; outline:none;
}
.pb-dd-menu li:hover, .pb-dd-menu li:focus { background:rgba(88,166,255,.12); }
.pb-dd-menu li[aria-selected="true"] { color:var(--accent); font-weight:700; }
.pb-dd-menu li[aria-selected="true"]::after { content:"✓"; color:var(--accent); }
/* searchable dropdown */
.pb-dd-list { list-style:none; margin:0; padding:0; }
.pb-dd-search { padding:2px 2px 8px; }
.pb-dd-search input {
  width:100%; box-sizing:border-box; background:var(--bg); border:1px solid var(--border);
  color:var(--fg); border-radius:7px; padding:7px 9px; font:500 13px/1 'Inter', sans-serif; outline:none;
}
.pb-dd-search input:focus { border-color:var(--accent); }
.pb-dd-empty { padding:8px 11px; color:var(--muted); text-align:center; font-size:13px; }

/* per-key budget usage bar (dashboard keys table) */
.kbudget { display:flex; flex-direction:column; gap:4px; min-width:120px; }
.kbar { height:6px; border-radius:99px; background:var(--border); overflow:hidden; }
.kbar-fill { height:100%; border-radius:99px; background:var(--accent); transition:width .2s ease; }
.kbar-fill.warn { background:#e3b341; }
.kbar-fill.bad { background:var(--bad); }

/* pay-as-you-go top-up block (dashboard billing panel) */
.topup { margin-top:16px; padding-top:14px; border-top:1px solid var(--border); }

/* ---- account avatar + dropdown (public nav, logged-in) ---- */
.pb-user{position:relative;display:inline-flex}
.pb-user-btn{background:none;border:0;padding:0;cursor:pointer;border-radius:50%;line-height:0}
.pb-user-btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.pb-avatar{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;border-radius:50%;
  color:#fff;font-weight:700;font-size:14px;background:#3a4658;box-shadow:inset 0 0 0 1px rgba(255,255,255,.14);
  text-transform:uppercase;user-select:none}
.pb-avatar-lg{width:40px;height:40px;font-size:17px}
.pb-user-btn .pb-avatar{transition:transform .12s,box-shadow .12s}
.pb-user-btn:hover .pb-avatar{transform:translateY(-1px);box-shadow:inset 0 0 0 1px rgba(255,255,255,.24),0 5px 16px -5px rgba(0,0,0,.6)}
.pb-user.open .pb-user-btn .pb-avatar{box-shadow:inset 0 0 0 1px rgba(255,255,255,.24),0 0 0 3px color-mix(in srgb,var(--accent) 32%,transparent)}
.pb-user-menu{position:absolute;top:calc(100% + 10px);right:0;min-width:232px;background:var(--panel);
  border:1px solid var(--border);border-radius:14px;box-shadow:0 24px 60px -18px rgba(0,0,0,.7);padding:6px;z-index:70;
  opacity:0;visibility:hidden;transform:translateY(-6px);transition:opacity .14s,transform .14s,visibility .14s}
.pb-user.open .pb-user-menu{opacity:1;visibility:visible;transform:none}
.pb-user-head{display:flex;align-items:center;gap:11px;padding:10px 12px 12px;border-bottom:1px solid var(--border);margin-bottom:6px}
.pb-user-email{font-size:13px;color:var(--fg);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:172px}
.pb-user-menu a{display:flex;align-items:center;gap:10px;padding:9px 12px;border-radius:9px;color:var(--fg);font-size:14px;text-decoration:none}
.pb-user-menu a:hover{background:var(--panel-2);text-decoration:none}
.pb-user-menu .js-logout{color:var(--muted)}
.pb-user-menu .js-logout:hover{color:var(--bad)}
.pb-user-sep{height:1px;background:var(--border);margin:6px 4px}
.pb-user-row{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:6px 12px;font-size:14px;color:var(--fg)}
.pb-user-row select{background:var(--input-bg);border:1px solid var(--border);color:var(--fg);border-radius:8px;padding:5px 8px;font:inherit;cursor:pointer}
.pb-user-row select:focus{outline:none;border-color:var(--accent)}
.pb-user-row .pb-dd{margin:0}
/* theme toggle switch (dark = on): the knob carries a sun (light) / moon (dark) icon */
.pb-toggle{position:relative;width:52px;height:26px;flex:none;border-radius:999px;border:1px solid var(--border);background:var(--panel-2);cursor:pointer;padding:0;transition:background .15s,border-color .15s}
.pb-toggle.on{background:color-mix(in srgb,var(--accent) 26%,transparent);border-color:var(--accent)}
.pb-toggle .pb-toggle-knob{position:absolute;top:2px;left:2px;width:20px;height:20px;border-radius:50%;background:#f3f6fa;color:#0c141d;display:flex;align-items:center;justify-content:center;transition:transform .16s}
.pb-toggle.on .pb-toggle-knob{transform:translateX(26px)}
.pb-toggle .pb-toggle-knob svg{width:12px;height:12px}
.pb-tg-moon{display:none}
.pb-toggle.on .pb-tg-sun{display:none}
.pb-toggle.on .pb-tg-moon{display:block}

/* ---- monthly <-> annual price switch (see "billingtoggle" in base.tmpl) ----
   Both prices are RENDERED and one is hidden, rather than one being computed and
   written in by script. Three reasons, and they are all the same reason: the numbers
   are already translated strings ($2,490 / $2.490 / $2.490 and $0.130 / $0,130), so
   computing them in JS would mean re-implementing per-locale currency formatting for
   a set of seven constants; a display:none price is not read by a screen reader, so
   nothing is announced twice; and with no script at all the page still shows a
   complete, correct monthly price list. */
.bsw{display:flex;align-items:center;justify-content:center;gap:10px;flex-wrap:wrap;margin:0 0 26px}
.bsw-lbl{font-size:14px;font-weight:600;color:var(--muted);transition:color .18s}
html:not([data-billing="year"]) .bsw-m,html[data-billing="year"] .bsw-y{color:var(--fg)}
.bsw-sw{position:relative;width:52px;height:26px;flex:none;border-radius:999px;border:1px solid var(--border);background:var(--panel-2);cursor:pointer;padding:0;transition:background .15s,border-color .15s}
html[data-billing="year"] .bsw-sw{background:color-mix(in srgb,var(--accent) 26%,transparent);border-color:var(--accent)}
.bsw-knob{position:absolute;top:2px;left:2px;width:20px;height:20px;border-radius:50%;background:#f3f6fa;transition:transform .16s}
html[data-billing="year"] .bsw-knob{transform:translateX(26px)}
/* The saving is a badge, not a sentence: it has to survive being read at 320px next
   to three other words, so it wraps onto its own line rather than squeezing them.
   Its fill is --panel and NOT a tint of --accent: accent-on-its-own-14%-tint measures
   4.47:1 in the light theme, which axe flagged and which is the exact trap
   TestLightThemeAccentsMeetContrast already documents for --warn. accent-on-panel is
   one of the pairs that test pins (5.77:1 light, 10.79:1 dark), so this fill is
   guarded rather than merely checked once. The accent survives in the border, which
   carries no text. */
.bsw-save{font-size:12px;font-weight:700;letter-spacing:.02em;padding:3px 9px;border-radius:999px;
  color:var(--accent);background:var(--panel);
  border:1px solid color-mix(in srgb,var(--accent) 40%,transparent)}
/* The swap itself. `.pr-y` carries the annual value; a tier with no annual price
   simply has no `.pr-y`, so it keeps showing its monthly one in both modes instead
   of going blank — which is what Free does. */
.pr-y{display:none}
html[data-billing="year"] .pr-m{display:none}
html[data-billing="year"] .pr-y{display:inline}
/* The animation is on the value that just appeared, keyed off the attribute, so it
   runs on a real change and not on every repaint. The global prefers-reduced-motion
   rule above already sets `animation:none !important` on everything, so a reader who
   asked for stillness gets the same numbers with no movement at all. */
@keyframes pb-price-swap{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}
html[data-billing] .pr-m,html[data-billing] .pr-y{animation:pb-price-swap .22s ease-out}

/* ============================================================================
   Shared top navigation — ONE definition for every page.
   There were three: the landing's, a separate one in docs.tmpl, and a third in
   base.tmpl for login/register/legal, so the header visibly changed as you moved
   around the site. This is the single source of truth.

   Colours use a fallback chain because the landing page layers its own token set
   (--ground/--surface/--text) over the global one in this file (--bg/--panel/--fg).
   Each var resolves to the page's own palette where it exists and the global one
   everywhere else, so the bar looks identical without reconciling both systems.
   ========================================================================== */
header.nav,.mnav{
  /* Typography is DECLARED, not inherited. Each page sets its own body font and
     line-height — docs pulls Inter as a webfont, the landing and legal pages use
     the system stack — so the same shared bar rendered in two different faces and
     the same CTA came out 43px tall on docs and 48px on the landing. Pinning it
     to the landing's stack keeps the flagship page unchanged and avoids making
     every other page wait on a webfont just to draw its header. */
  font-family:var(--sans,system-ui,-apple-system,"Segoe UI",Roboto,Helvetica,Arial,sans-serif);
  line-height:1.5}
header.nav{position:sticky;top:0;z-index:50;backdrop-filter:blur(12px);
  background:color-mix(in srgb,var(--ground,var(--bg)) 82%,transparent);
  border-bottom:1px solid var(--border)}
header.nav>.nav-in{max-width:none;padding:0 30px;margin:0 auto}
.nav-in{display:flex;align-items:center;gap:20px;height:64px}
.lbrand{display:inline-flex;align-items:center;gap:10px;color:var(--text,var(--fg));
  text-decoration:none;font-weight:800;font-size:1.06rem;padding:6px 2px}
.lbrand .llogo,.lbrand .logo-mark{width:30px;height:30px;flex:0 0 auto}
.lnavlinks{display:flex;gap:26px;margin-left:14px}
.lnavlinks a{color:var(--muted);font-size:.93rem;font-weight:520;text-decoration:none}
.lnavlinks a:hover,.lnavlinks a[aria-current="page"]{color:var(--text,var(--fg))}
.nav-right{margin-left:auto;display:flex;align-items:center;gap:10px}
.icon-btn{width:38px;height:38px;display:grid;place-items:center;border-radius:9px;
  border:1px solid var(--border);background:var(--surface,var(--panel));color:var(--muted);cursor:pointer}
.icon-btn:hover{color:var(--accent);border-color:var(--accent)}
.burger{display:none}
.mnav{display:none}

/* Element+class, not bare class: docs.tmpl carries legacy nav[aria-label="Primary"]
   rules that otherwise win on specificity and keep the links visible on a phone. */
@media(max-width:860px){header.nav nav.lnavlinks{display:none}}
@media(max-width:780px){
  header.nav>.nav-in{padding:0 16px}
  .nav-in{gap:10px;height:58px}
  header.nav .burger{display:grid}
  .nav-right{gap:8px}
  header.nav .pb-lang,header.nav .pb-dd,header.nav #theme,header.nav .nav-signin{display:none}
  .nav-cta{padding:.6em .9em;font-size:.86rem}
  .mnav{display:block;position:fixed;inset:58px 0 auto 0;z-index:49;
    background:color-mix(in srgb,var(--ground,var(--bg)) 97%,transparent);backdrop-filter:blur(14px);
    border-bottom:1px solid var(--border);padding:10px 16px 18px;
    max-height:calc(100dvh - 58px);overflow-y:auto}
  .mnav[hidden]{display:none}
  .mnav-links{display:flex;flex-direction:column}
  /* 48px rows: the audit measured 23-30px targets, under every touch guideline. */
  .mnav-links a{padding:14px 4px;min-height:48px;display:flex;align-items:center;
    font-size:1.02rem;font-weight:560;color:var(--text,var(--fg));text-decoration:none;
    border-bottom:1px solid var(--border)}
  .mnav-foot{display:flex;flex-direction:column;gap:10px;margin-top:16px}
  .mnav-foot .lbtn{justify-content:center;padding:.9em 1em;font-size:1rem}
  .mnav-tools{display:flex;align-items:center;gap:10px;margin-top:6px;
    padding-top:14px;border-top:1px solid var(--border)}
  .mnav-tools .pb-dd{flex:1}
  .mnav-tools .pb-dd-btn{width:100%;justify-content:space-between}
  .mnav-tools .icon-btn{width:44px;height:44px;flex:0 0 auto}
}

/* Shared button + brand styling for the site-wide nav.
   These lived only in index.tmpl, so once the nav became shared every OTHER page
   rendered its "Get started" as a bare blue underlined link — the docs header
   looked nothing like the landing one. Same fallback chain as the nav above:
   the landing's own tokens where they exist, the global ones everywhere else. */
.lbrand{display:flex;align-items:center;gap:11px;font-weight:680;letter-spacing:-.02em;
  font-size:1.1rem;color:var(--text,var(--fg));text-decoration:none}
.lbrand:hover{text-decoration:none}
.wordmark .dot{color:var(--accent)}
.wordmark .tld{color:var(--muted)}
.lbtn{display:inline-flex;align-items:center;gap:.5em;font-weight:620;font-size:.95rem;line-height:1.5;
  font-family:var(--sans,system-ui,-apple-system,"Segoe UI",Roboto,Helvetica,Arial,sans-serif);
  padding:.72em 1.25em;border-radius:9px;border:1px solid transparent;cursor:pointer;
  text-decoration:none;white-space:nowrap;
  transition:transform .12s ease,background .15s ease,border-color .15s ease}
.lbtn:hover{text-decoration:none}
.lbtn:active{transform:translateY(1px)}
/* --accent-ink is the landing's "readable text on an accent fill". Other pages
   don't define it, hence the literal fallback rather than inheriting --fg, which
   would be near-invisible on green. */
.lbtn-primary{background:var(--accent);color:var(--accent-ink,#06210f);border-color:var(--accent)}
.lbtn-primary:hover{filter:brightness(1.06)}
.lbtn-ghost{background:transparent;color:var(--text,var(--fg));
  border-color:var(--border-strong,var(--border-hi,var(--border)))}
.lbtn-ghost:hover{border-color:var(--accent);color:var(--accent)}
.lbtn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* Language-suggestion bar and the language-swap fade.
   The bar is built by app.js only for a visitor whose browser asks for a language
   we serve, on the English URLs, who has not already chosen or dismissed. It is a
   suggestion and never a redirect: anything that changed what a URL serves based
   on the visitor's language would mean Googlebot (US, Accept-Language: en) only
   ever sees English and /ro/ never gets indexed. */
.pb-locbar {
  position: fixed; left: 50%; bottom: 18px; transform: translate(-50%, 12px);
  z-index: 90; display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  max-width: calc(100vw - 24px); padding: 11px 14px;
  background: var(--panel); color: var(--fg);
  border: 1px solid var(--border-hi); border-radius: 12px;
  box-shadow: 0 18px 50px -22px rgba(0,0,0,.7); font-size: 14px;
  opacity: 0; transition: opacity .22s ease, transform .22s ease;
}
.pb-locbar.in { opacity: 1; transform: translate(-50%, 0); }
.pb-locbar .lbtn { padding: 7px 14px; font-size: 13.5px; }
.pb-locbar-no {
  background: none; border: 0; color: var(--muted); cursor: pointer;
  font: inherit; padding: 6px 4px; text-decoration: underline;
}
.pb-locbar-no:hover { color: var(--fg); }

/* Every string changes at once on a language switch; without this it is a hard
   flicker. app.js removes the class on the next frame, so this is the "back to
   normal" half of the transition and the page can never be stranded faded. */
html.pb-langswap body { opacity: .55; }
body { transition: opacity .18s ease; }

@media (prefers-reduced-motion: reduce) {
  .pb-locbar { transition: none; }
  html.pb-langswap body, body { opacity: 1; transition: none; }
}
