/* VerifyUGC design tokens — single source of truth (Improvement Backlog #6).
   Linked first on every page; per-vertical themes override only the accent trio
   + the --t1/--t2/--t3 text trio + label. Pre-existing values are preserved
   exactly so nothing shifts visually;
   the radius/spacing/semantic/motion scales below are additive for new work. */
:root,[data-theme="brand"]{ --a1:#a855f7; --a2:#3b82f6; --a3:#22d3ee; --label:"Trust & Safety";
  --t1:#bd6cff; --t2:#4d8dff; --t3:#21e8ff; --node:#3b82f6; --shield:#22d3ee; }
/* v7 vertical palettes (brand-researched): roblox "Cobalt Era" (2025 rebrand) ·
   uefn "Creator Royale" (storm purples) · minecraft "Diamond Tier" (grass→teal→diamond) */
[data-theme="roblox"]{ --a1:#1f6bff; --a2:#4f9cff; --a3:#cfe3ff; --label:"For Roblox creators";
  --t1:#2f7bff; --t2:#5cb2ff; --t3:#8fd2ff; --node:#4f8fea; --shield:#7fc0ff; }
[data-theme="uefn"]{ --a1:#8b5cf6; --a2:#4c51f7; --a3:#5fceea; --label:"For Fortnite / UEFN creators";
  --t1:#a578ff; --t2:#5d63ff; --t3:#4fdcff; --node:#7d74e8; --shield:#5fceea; }
[data-theme="minecraft"]{ --a1:#4ade80; --a2:#2dd4bf; --a3:#22d3ee; --label:"For Minecraft creators";
  --t1:#54f08c; --t2:#2ee8c4; --t3:#1fe1ff; --node:#3ecf8e; --shield:#22d3ee; }
:root{
  /* neutrals & surfaces */
  --bg:#070710; --bg2:#0c0c18; --surface:#13131f; --surface2:#171726;
  --border:rgba(255,255,255,.08); --border2:rgba(255,255,255,.14);
  --text:#edecf7; --dim:#9b9bbd; --faint:#8b8ba8;
  /* v7 additions (per vertical theme above, from the v7 design system):
     --t1/--t2/--t3 = the ELECTRIC text ramp for gradient-clipped headline words
     (brighter + more saturated than a1–a3, which read flat as text on the dark
     field); --node/--shield = the node-graph world's server + protection colors.
     HARD RULE: --node must never approach corruption red (--danger #f87171). */
  --grad-text:linear-gradient(120deg,var(--t1),var(--t2) 55%,var(--t3));
  --grad:linear-gradient(120deg,var(--a1),var(--a2));
  --maxw:1160px; --r:16px;
  /* semantic status colors (additive). --info is an independent neutral blue —
     intentionally NOT aliased to --a3 (cyan), so changing the per-vertical accent
     trio never shifts status/info indicators. */
  --success:#34d399; --danger:#f87171; --warning:#fbbf24; --info:#38bdf8;
  /* radius scale (additive) */
  --r-sm:9px; --r-md:14px; --r-lg:18px; --r-pill:999px;
  /* spacing scale (additive) */
  --s-1:6px; --s-2:10px; --s-3:14px; --s-4:20px; --s-5:28px; --s-6:40px;
  /* motion (additive) */
  --dur:.25s; --ease:cubic-bezier(.4,0,.2,1);
}

/* ===== global mobile-first guards (loaded on every page via direct link or
   page.css / article.css @import) ===== */

/* Kill horizontal scroll from full-bleed decorative orbs / blurred glows that
   sit off-canvas with negative offsets. Clipping the root inline-axis removes
   the phantom scrollbar/pan on phones without breaking sticky headers. */
html{overflow-x:hidden}
img,svg,video{max-width:100%}
/* v7 living-world background canvas — sized/positioned here so it renders on every
   page (article.css/page.css @import this; the inline-styled tool pages load it
   directly). engine.js + network.js draw into it; replaces the legacy self-injecting
   hexbg.js. network.js reads getBoundingClientRect, so this rule is required. */
#network{position:fixed;inset:0;z-index:1;width:100vw;height:100vh;pointer-events:none;opacity:.85}

/* iOS zooms the viewport when a focused input renders below 16px. Pin all
   form controls to 16px on small screens (wins over inline styles, hence
   !important) — desktop sizing is untouched above 640px. */
@media (max-width:640px){
  input,select,textarea{font-size:16px!important}
}

/* ===== reduced motion — site-wide floor for rolling / looping animations =====
   Brings every page up to the homepage's standard. The non-homepage pages run a
   lot of infinite loops with no guard of their own — skeleton-shimmer sweeps, the
   directory's 60-node float field, status pulses, spinners, drifting orbs. This
   caps animations to a single near-instant run (one-shot entrances still settle
   at their end frame) and stops every infinite loop for users who ask for less
   motion. The homepage ships its own stronger `animation:none` guard; this is the
   compatible site-wide baseline. JS-driven tickers (the hero count-ups in boot.js)
   already check this query themselves. */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.01ms!important;
    animation-iteration-count:1!important;
    transition-duration:.01ms!important;
    scroll-behavior:auto!important;
  }
}

/* ===== large-display (ultrawide / 4K) tiers — additive, min-width only =====
   The site already caps content with fixed max-width containers, so it never
   stretches unreadably wide. These tiers fix the opposite problem: on a native
   4K / ultrawide canvas the layout was a thin centered island with physically
   small rem-based text (the codebase had no min-width breakpoints at all). A
   gentle root type bump improves legibility everywhere, and a wider shell
   (--maxw, used by the homepage + opted-in grid layouts) lets dense pages use
   more of the screen. Reading-column pages (article 760px, verified 720px)
   keep their own narrower px caps for an ideal line measure, so they are
   intentionally unaffected. Breakpoints match the audited viewports. */
@media (min-width:2560px){
  :root{ font-size:17px; --maxw:1320px; }
}
@media (min-width:3440px){
  :root{ font-size:18px; --maxw:1440px; }
}

/* ===== copy-to-clipboard button (powered by /assets/clipboard.js) =====
   Self-contained, theme-aware via the accent + semantic tokens. var() fallbacks
   are included so it still looks right on the few SSR surfaces that ship their
   own scoped CSS instead of linking this file. */
.copybtn{display:inline-flex;align-items:center;justify-content:center;gap:6px;vertical-align:middle;cursor:pointer;border:1px solid var(--border2,rgba(255,255,255,.14));background:var(--bg2,#0c0c18);color:var(--dim,#9b9bbd);font-family:inherit;font-size:.8rem;font-weight:600;line-height:1;padding:7px 11px;border-radius:var(--r-sm,9px);transition:color .15s,border-color .15s,background .15s}
.copybtn:hover{color:var(--text,#edecf7);border-color:var(--a1,#a855f7)}
.copybtn.copied{color:var(--success,#34d399);border-color:color-mix(in srgb,var(--success,#34d399) 50%,transparent);background:color-mix(in srgb,var(--success,#34d399) 12%,transparent)}
.copybtn.copyfail{color:var(--warning,#fbbf24);border-color:color-mix(in srgb,var(--warning,#fbbf24) 50%,transparent)}
.copybtn:focus-visible{outline:2px solid var(--a1,#a855f7);outline-offset:2px}
/* keybox + copy button laid out on one row (revealed API keys, license keys…) */
.keyrow{display:flex;gap:8px;align-items:stretch;margin-top:10px}
.keyrow .keybox{flex:1;min-width:0;margin-top:0}
.keyrow .copybtn{flex:0 0 auto}

/* ===== inline tooltips (powered by /assets/tooltips.js) =====
   A single floating bubble positioned by JS in viewport coords (hence
   position:fixed). var() fallbacks keep it correct on the few SSR pages that
   ship their own scoped CSS instead of this file. */
.vu-tip{position:fixed;z-index:9999;left:0;top:0;max-width:250px;background:#0c0c18;color:#fff;border:1px solid var(--border2,rgba(255,255,255,.16));border-radius:10px;padding:9px 12px;font-family:Inter,system-ui,sans-serif;font-size:.8rem;font-weight:500;line-height:1.45;letter-spacing:normal;text-transform:none;white-space:normal;box-shadow:0 10px 30px rgba(0,0,0,.5);pointer-events:none;opacity:0;transform:translateY(4px);transition:opacity .15s var(--ease,ease),transform .15s var(--ease,ease)}
.vu-tip.show{opacity:1;transform:translateY(0)}
/* downward arrow when the bubble sits above the trigger; flips up when below. --ax = arrow x within the bubble. */
.vu-tip::after{content:"";position:absolute;top:100%;left:var(--ax,50%);transform:translateX(-50%);border:6px solid transparent;border-top-color:#0c0c18}
.vu-tip.below::after{top:auto;bottom:100%;border-top-color:transparent;border-bottom-color:#0c0c18}
@media (prefers-reduced-motion:reduce){.vu-tip{transition:opacity .1s}}
/* "?" help marker — the inline trigger next to a term that needs explaining */
.vu-help{display:inline-grid;place-items:center;width:15px;height:15px;margin-left:5px;border-radius:50%;border:1px solid var(--border2,rgba(255,255,255,.3));color:var(--dim,#9b9bbd);font-family:Inter,system-ui,sans-serif;font-size:.66rem;font-weight:700;line-height:1;cursor:help;vertical-align:middle;-webkit-user-select:none;user-select:none}
.vu-help:hover,.vu-help:focus-visible{border-color:var(--a1,#a855f7);color:var(--text,#edecf7)}
/* any non-marker element wired with a tooltip gets the help cursor as an affordance */
[data-tooltip]:not(.vu-help){cursor:help}
/* …except editable fields, which keep their text caret */
input[data-tooltip],textarea[data-tooltip]{cursor:auto}
/* inline-text trigger (e.g. a blacklist/watchlist tag) — dotted underline hints it's explainable */
.vu-tag{text-decoration:underline dotted;text-underline-offset:2px;text-decoration-thickness:1px}

/* ===== skip-to-content link (WCAG 2.4.1 Bypass Blocks) =====
   First focusable element on the page (injected as body's first child by nav.js
   on shared-header pages; hard-coded on the dashboard). Visually hidden until it
   receives keyboard focus, then it slides into the top-left corner above the
   sticky header (z-index beats header's 50). */
.skip-link{position:fixed;top:8px;left:8px;z-index:1000;transform:translateY(-150%);
  background:var(--surface,#13131f);color:var(--text,#edecf7);border:1px solid var(--a1,#a855f7);
  border-radius:var(--r-sm,9px);padding:10px 16px;font-family:Inter,system-ui,sans-serif;
  font-weight:600;font-size:.9rem;text-decoration:none;box-shadow:0 10px 30px rgba(0,0,0,.5);
  transition:transform .15s var(--ease,ease)}
.skip-link:focus,.skip-link:focus-visible{transform:translateY(0);outline:2px solid var(--a1,#a855f7);outline-offset:2px}
@media (prefers-reduced-motion:reduce){.skip-link{transition:none}}

/* ===== v7 glass panel system (additive, per the v7 design system) =====
   Frosted panels: white-alpha fill + blur(18px) + hairline border + a 2px
   gradient top rail (a1→a2→a3) + inset top sheen. The rail carries the theme;
   the fill stays neutral. On small screens / no backdrop-filter, blur is
   swapped for a solid dark fill so text stays legible. */
.glass{position:relative;border-radius:var(--r-lg);overflow:hidden;
  border:1px solid var(--border);
  background:rgba(255,255,255,.034);
  -webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px);
  box-shadow:0 18px 50px rgba(0,0,0,.45),inset 0 1px 0 rgba(255,255,255,.05)}
/* the 2px gradient top rail — the v7 signature cue */
.glass--rail::before{content:"";position:absolute;top:0;left:0;right:0;height:2px;pointer-events:none;
  background:linear-gradient(120deg,var(--a1),var(--a2) 55%,var(--a3));opacity:.6}
@media (max-width:720px){
  .glass{-webkit-backdrop-filter:none;backdrop-filter:none;background:rgba(15,16,28,.82)}
}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .glass{background:rgba(15,16,28,.82)}
}

/* header lockup logo (per-theme) */
.brand .brandlogo{height:30px;width:auto;display:none}
.brand .brandlogo--ugc{display:block}
html[data-theme="roblox"] .brand .brandlogo--ugc{display:none}html[data-theme="roblox"] .brand .brandlogo--roblox{display:block}
html[data-theme="uefn"] .brand .brandlogo--ugc{display:none}html[data-theme="uefn"] .brand .brandlogo--uefn{display:block}
html[data-theme="minecraft"] .brand .brandlogo--ugc{display:none}html[data-theme="minecraft"] .brand .brandlogo--minecraft{display:block}
