/* PBCTF — Point Blank skin for the CTFd core theme.
   Loaded after the built main.css so plain overrides win on load order. */

:root,
[data-bs-theme="dark"] {
  --pb-green: #37ff00;
  --pb-green-dim: #2bd400;
  --pb-dark: #0d0d0d;
  --pb-card: #141414;
  --pb-surface: #191919;
  --pb-border: #262626;
  --pb-text: #b3b3b3;
  --pb-muted: #8e8e93;

  /* glassmorphism: dark frosted panel over the animated field.
     Dark tint keeps mono text readable; the rim light + lift shadow
     read as "glass" more than the blur does on a low-contrast field. */
  --pb-glass-bg: rgba(15, 22, 17, 0.55);
  --pb-glass-bg-hover: rgba(22, 32, 24, 0.62);
  --pb-glass-border: rgba(255, 255, 255, 0.10);
  --pb-glass-blur: blur(13px) saturate(160%);
  --pb-glass-shadow: 0 8px 32px rgba(0, 0, 0, 0.45);
  --pb-glass-rim: inset 0 1px 0 rgba(255, 255, 255, 0.07);

  --bs-body-bg: var(--pb-dark);
  --bs-body-color: var(--pb-text);
  --bs-body-font-family: "Lexend", system-ui, -apple-system, "Segoe UI", sans-serif;
  --bs-heading-color: #ffffff;
  --bs-emphasis-color: #ffffff;
  --bs-secondary-color: var(--pb-muted);
  --bs-secondary-bg: var(--pb-card);
  --bs-tertiary-bg: var(--pb-surface);
  --bs-border-color: var(--pb-border);
  --bs-border-color-translucent: var(--pb-border);
  --bs-link-color: var(--pb-green);
  --bs-link-hover-color: #86ff61;
  --bs-link-color-rgb: 55, 255, 0;
  --bs-link-hover-color-rgb: 134, 255, 97;
  --bs-primary: var(--pb-green);
  --bs-primary-rgb: 55, 255, 0;
  --bs-dark: var(--pb-card);
  --bs-dark-rgb: 20, 20, 20;
  --bs-gray-dark: var(--pb-card);
  --bs-gray: #1e1e1e;
  --bs-code-color: var(--pb-green);
}

/* Reserve the scrollbar gutter on every page. Without it, navigating between a
   page that scrolls and one that doesn't changes the viewport width, which
   re-centers the navbar's .container and makes the brand appear to jump a few
   pixels sideways. */
html {
  scrollbar-gutter: stable;
}

/* Fallback for engines without scrollbar-gutter (Safari < 16): always render the
   scrollbar so its width is constant. Same goal — the brand must not move
   between a page that scrolls and one that doesn't. */
@supports not (scrollbar-gutter: stable) {
  html {
    overflow-y: scroll;
  }
}

::selection {
  background: var(--pb-green);
  color: var(--pb-dark);
}

::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}
::-webkit-scrollbar-track {
  background: var(--pb-dark);
}
::-webkit-scrollbar-thumb {
  background: var(--pb-border);
  border-radius: 5px;
}
::-webkit-scrollbar-thumb:hover {
  background: var(--pb-green-dim);
}

h1, h2, h3, h4, h5, h6 {
  color: #ffffff;
}

hr {
  border-color: var(--pb-border);
  opacity: 1;
}

code, pre, kbd, samp {
  font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
}

pre {
  background: var(--pb-surface);
  border: 1px solid var(--pb-border);
  border-radius: 4px;
  padding: 0.75rem;
}

/* Navbar — Liquid Glass navigation layer
--------------------------------------------------
   Apple's guidance is that glass belongs on the navigation layer, so this is
   where the material is pushed hardest. Built from its three parts:
     illumination — low-opacity dark tint + a top-down sheen gradient
     highlight    — 1px specular rim on the top edge (what reads as "glass")
     shadow       — outer lift + grounded bottom edge for separation
   This is the single source of truth for navbar chrome. Do not re-declare
   .navbar backgrounds in pbctf-bg.css: `.navbar.bg-dark` (0-2-0) silently
   outranks `.navbar` (0-1-0) and the two rules fight over opacity. */
.navbar.bg-dark,
.navbar.navbar-dark {
  /* Resting state is deliberately quiet; it wakes up on hover. Only the
     material and vertical padding animate — horizontal geometry is frozen so
     the brand and nav links never slide under the cursor mid-click. */
  background-color: rgba(10, 14, 12, 0.3) !important;
  -webkit-backdrop-filter: blur(20px) saturate(165%);
  backdrop-filter: blur(20px) saturate(165%);
  border: 1px solid rgba(255, 255, 255, 0.07) !important;
  border-radius: 20px;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.1),
    inset 0 -1px 0 rgba(0, 0, 0, 0.22),
    0 6px 22px rgba(0, 0, 0, 0.32);
  /* floats off the edges instead of spanning them (capsule, not a band) */
  margin: 0.6rem 0.9rem;
  --bs-navbar-padding-y: 0.22rem;
  transition:
    background-color 0.28s ease,
    backdrop-filter 0.28s ease,
    -webkit-backdrop-filter 0.28s ease,
    box-shadow 0.28s ease,
    border-color 0.28s ease,
    padding 0.28s cubic-bezier(0.32, 0.72, 0, 1);
}

/* Sheen layer: a static top-down gloss plus a specular highlight that tracks
   the cursor, which is how the real material behaves ("highlights cast and move
   across surfaces"). Lives on a pseudo-element so it can fade independently
   without interpolating gradients. */
.navbar.bg-dark::before,
.navbar.navbar-dark::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  border-radius: inherit;
  background:
    radial-gradient(
      260px circle at var(--pb-nav-mx, 50%) -20%,
      rgba(255, 255, 255, 0.1),
      transparent 70%
    ),
    linear-gradient(
      to bottom,
      rgba(255, 255, 255, 0.055) 0%,
      rgba(255, 255, 255, 0.012) 45%,
      rgba(0, 0, 0, 0.05) 100%
    );
  opacity: 0.55;
  transition: opacity 0.28s ease;
}

/* keep bar content above the sheen */
.navbar > .container {
  position: relative;
  z-index: 1;
}

/* Navigation is a landmark: its geometry never changes on hover. The only
   response is the material warming very slightly, which is feedback that the
   surface is live — not choreography. Per-item pills do the real work of
   showing what is hoverable. */
.navbar.bg-dark:hover::before,
.navbar.navbar-dark:hover::before,
.navbar.bg-dark:focus-within::before,
.navbar.navbar-dark:focus-within::before {
  opacity: 0.85;
}

/* Account menu
--------------------------------------------------
   Only four short rows, so it can be far more transparent than the language
   list (which trades glass for legibility across 25 names).

   Note: this menu is a descendant of the navbar, and the navbar's own
   backdrop-filter makes it a backdrop root — a child's blur can only sample the
   navbar's box, not the page below it. So the glass read here comes from
   translucency, rim and shadow rather than from blur. */
.pb-account .dropdown-menu {
  --bs-dropdown-bg: rgba(11, 16, 13, 0.58);
  border-color: rgba(255, 255, 255, 0.13);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.12),
    0 20px 48px rgba(0, 0, 0, 0.55);
  min-width: 11.5rem;
}

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .pb-account .dropdown-menu {
    --bs-dropdown-bg: var(--pb-card);
  }
}

.pb-account .dropdown-toggle::after {
  display: none; /* the avatar is the affordance; a caret adds noise */
}

.pb-account-name {
  color: #ffffff;
  font-weight: 600;
  font-size: 0.9rem;
  padding: 0.35rem 0.7rem 0.15rem;
}

.dropdown-menu .dropdown-item i {
  width: 1.1rem;
  margin-right: 0.5rem;
  opacity: 0.75;
  text-align: center;
}

.dropdown-divider {
  border-color: var(--pb-glass-border);
  opacity: 1;
  margin: 0.3rem 0.15rem;
}

/* Scrolled: page content now passes underneath, so the tint firms up for
   legibility. Toggled by pbctf-ui.js. */
.navbar.pb-nav-scrolled.bg-dark,
.navbar.pb-nav-scrolled.navbar-dark {
  background-color: rgba(8, 12, 10, 0.52) !important;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.1),
    inset 0 -1px 0 rgba(0, 0, 0, 0.22),
    0 8px 26px rgba(0, 0, 0, 0.44);
}

.navbar.pb-nav-scrolled.bg-dark:hover,
.navbar.pb-nav-scrolled.navbar-dark:hover {
  background-color: rgba(10, 15, 12, 0.58) !important;
}

/* the effect is decoration; never let it be the reason motion-sensitive users
   see the bar move */
@media (prefers-reduced-motion: reduce) {
  .navbar.bg-dark,
  .navbar.navbar-dark {
    transition: none;
  }
  .navbar.bg-dark:hover,
  .navbar.navbar-dark:hover,
  .navbar.bg-dark:focus-within,
  .navbar.navbar-dark:focus-within {
    --bs-navbar-padding-y: 0.22rem;
  }
}

.navbar-dark {
  --bs-navbar-color: var(--pb-text);
  --bs-navbar-hover-color: var(--pb-green);
  --bs-navbar-active-color: var(--pb-green);
  --bs-navbar-brand-color: #ffffff;
  --bs-navbar-brand-hover-color: var(--pb-green);
}

/* content clears the floating bar, including its expanded hover height */
main {
  padding-top: 5rem !important;
}

/* nav items get a soft glass pill on hover/active — tactile, not loud */
.navbar .nav-link {
  border-radius: 11px;
  padding-left: 0.7rem !important;
  padding-right: 0.7rem !important;
  transition: color 0.16s ease, background-color 0.16s ease;
}

.navbar .nav-link:hover {
  background-color: rgba(255, 255, 255, 0.055);
}

.navbar .nav-link.active {
  background-color: rgba(55, 255, 0, 0.09);
}

/* a small, confident mark reads better in a slim bar than a large one.
   Dimensions are fixed rather than auto so the mark reserves its exact box
   before the image decodes — no reflow on page load. */
.navbar-brand img {
  display: block;
  height: 17px;
  width: 90px;
}

.navbar-brand {
  padding: 0.25rem 0.55rem;
  margin-right: 0.9rem;
  opacity: 0.95;
  transition: opacity 0.16s ease;
}

.navbar-brand:hover {
  opacity: 1;
}

/* unread count sits on the bell once labels collapse to icons */
.navbar .nav-icon {
  position: relative;
  display: inline-block;
}

.navbar .nav-icon .nav-badge {
  position: absolute;
  top: -0.35em;
  right: -0.6em;
  font-size: 0.62rem;
  line-height: 1;
  padding: 0.22em 0.42em;
  box-shadow: 0 0 0 2px rgba(10, 14, 12, 0.55);
}

.navbar-toggler {
  border: none;
  border-radius: 10px;
}

/* the browser's default focus ring is blue, which reads as a foreign element in
   this palette — keep keyboard focus obvious but on-brand */
.navbar-toggler:focus,
.navbar .nav-link:focus-visible,
.navbar .dropdown-toggle:focus-visible,
.navbar-brand:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(55, 255, 0, 0.28);
}

.navbar .dropdown-toggle:focus:not(:focus-visible) {
  outline: none;
  box-shadow: none;
}

/* opaque fallback so the header never becomes unreadable */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .navbar.bg-dark,
  .navbar.navbar-dark {
    background: rgba(10, 14, 12, 0.94) !important;
  }
}

/* Landing hero — asymmetric split
--------------------------------------------------
   Deliberately not another centred stack. Identity and the action sit on a
   strong left edge; the right column is a live terminal readout. Two columns
   share the vertical space instead of stacking, which is also what keeps the
   page inside one viewport with no scroll. */
.pb-hero {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1.04fr) minmax(0, 0.96fr);
  align-items: center;
  gap: clamp(1.25rem, 4vw, 3.5rem);
  max-width: 66rem;
  margin: 0 auto;
  padding: 0 clamp(0.25rem, 2vw, 1rem);
  min-height: calc(100vh - 12rem);
}

/* soft pool of darkness rather than a card — depth without edges */
.pb-hero::before {
  content: "";
  position: absolute;
  inset: -14% -10%;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(
    62% 55% at 45% 48%,
    rgba(3, 5, 4, 0.9) 0%,
    rgba(3, 5, 4, 0.6) 48%,
    transparent 100%
  );
}

.pb-hero-panel {
  text-align: left;
}

.pb-hero-mark {
  display: block;
  width: 100%;
  max-width: 19rem;
  height: auto;
  margin: 0;
  filter: drop-shadow(0 0 26px rgba(55, 255, 0, 0.2));
}

/* hairline that anchors the left edge */
.pb-hero-rule {
  width: 3.5rem;
  height: 2px;
  margin: 1.5rem 0 1.15rem;
  background: linear-gradient(to right, var(--pb-green), rgba(55, 255, 0, 0));
}

.pb-hero-cmd {
  display: block;
  margin: 0;
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: clamp(0.75rem, 1.5vw, 0.9rem);
  line-height: 1.6;
  color: var(--pb-text);
  max-width: 32rem;
}

/* the brand is a proper noun — never let it break across lines */
.pb-hero-cmd a {
  color: var(--pb-green);
  font-weight: 600;
  white-space: nowrap;
}

.pb-hero-caret {
  display: inline-block;
  width: 0.5em;
  height: 1em;
  background: var(--pb-green);
  transform: translateY(0.1em);
  animation: pb-caret 1.1s steps(2, start) infinite;
}

@keyframes pb-caret {
  to { visibility: hidden; }
}

/* T-minus: a mission timer on one line, not a boxed countdown widget.
   Filled by pbctf-ui.js from CTFd's start/end config; removed when unset. */
.pb-tminus[hidden] { display: none; }

.pb-tminus {
  margin: 1.85rem 0 0;
  font-family: "JetBrains Mono", ui-monospace, monospace;
}

.pb-tminus-label {
  display: block;
  font-size: 0.6rem;
  letter-spacing: 2.4px;
  text-transform: uppercase;
  color: var(--pb-muted);
  margin-bottom: 0.5rem;
}

.pb-tminus-value {
  display: flex;
  align-items: baseline;
  gap: 0.1rem;
  font-size: clamp(1.45rem, 4.2vw, 2.15rem);
  font-weight: 600;
  color: #ffffff;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  text-shadow: 0 0 24px rgba(55, 255, 0, 0.2);
}

.pb-tminus-value .u {
  font-size: 0.5em;
  font-weight: 500;
  color: var(--pb-green);
  margin: 0 0.45rem 0 0.1rem;
  letter-spacing: 0.5px;
}

.pb-hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-top: 1.9rem;
}

/* squared off and monospaced — reads like a control, not a marketing pill */
.pb-hero-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 8.6rem;
  padding: 0.78rem 1.5rem;
  border-radius: 4px;
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-weight: 600;
  font-size: 0.78rem;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  text-decoration: none !important;
  border: 1px solid transparent;
  transition: background-color 0.16s ease, border-color 0.16s ease,
    transform 0.16s ease, box-shadow 0.16s ease, color 0.16s ease;
}

.pb-hero-btn-primary {
  background: var(--pb-green);
  color: var(--pb-dark) !important;
  border-color: var(--pb-green);
  box-shadow: 0 8px 24px rgba(55, 255, 0, 0.18);
}

.pb-hero-btn-primary:hover {
  background: var(--pb-green-dim);
  border-color: var(--pb-green-dim);
  transform: translateY(-2px);
  box-shadow: 0 12px 30px rgba(55, 255, 0, 0.26);
}

.pb-hero-btn-ghost {
  background: rgba(255, 255, 255, 0.055);
  color: #ffffff !important;
  border-color: var(--pb-glass-border);
}

.pb-hero-btn-ghost:hover {
  background: rgba(255, 255, 255, 0.11);
  border-color: rgba(255, 255, 255, 0.2);
  transform: translateY(-2px);
}

.pb-hero-btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(55, 255, 0, 0.35);
}

.pb-hero-terms {
  margin: 1.1rem 0 0;
  font-size: 0.76rem;
  color: var(--pb-muted);
}

.pb-hero-terms a {
  color: var(--pb-muted);
  text-decoration: underline !important;
  text-underline-offset: 2px;
}

.pb-hero-terms a:hover { color: var(--pb-green); }

/* Terminal readout — the event's live state as command output. This is the
   column that gives the page its character, and it is real data: every row
   comes from CTFd config via pbctf-ui.js. */
.pb-term {
  border: 1px solid var(--pb-glass-border);
  border-radius: 7px;
  background: rgba(6, 10, 8, 0.55);
  -webkit-backdrop-filter: blur(16px) saturate(150%);
  backdrop-filter: blur(16px) saturate(150%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.07), 0 20px 50px rgba(0, 0, 0, 0.5);
  font-family: "JetBrains Mono", ui-monospace, monospace;
  overflow: hidden;
}

.pb-term-bar {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.6rem 0.85rem;
  border-bottom: 1px solid var(--pb-glass-border);
  background: rgba(255, 255, 255, 0.025);
}

.pb-term-bar i {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.16);
  display: block;
}

.pb-term-bar i:first-child { background: rgba(55, 255, 0, 0.5); }

.pb-term-bar span {
  margin-left: 0.4rem;
  font-size: 0.66rem;
  color: var(--pb-muted);
  letter-spacing: 0.5px;
}

.pb-term-body {
  padding: 0.95rem 1rem 1.1rem;
  font-size: 0.76rem;
  line-height: 1.75;
}

.pb-term-cmd {
  color: var(--pb-text);
}

.pb-term-cmd::before {
  content: "$ ";
  color: var(--pb-green);
}

.pb-term-rows {
  margin: 0.5rem 0 0.6rem;
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.15rem 1.1rem;
}

.pb-term-rows dt {
  color: var(--pb-muted);
  font-weight: 400;
  text-transform: uppercase;
  font-size: 0.68rem;
  letter-spacing: 1px;
}

.pb-term-rows dd {
  margin: 0;
  color: #ffffff;
}

.pb-term-rows dd.is-live { color: var(--pb-green); }

.pb-term-rows dd.is-live::before {
  content: "";
  display: inline-block;
  width: 6px;
  height: 6px;
  margin-right: 0.4rem;
  border-radius: 50%;
  background: var(--pb-green);
  box-shadow: 0 0 8px var(--pb-green);
  animation: pb-pulse 1.8s ease-in-out infinite;
}

@keyframes pb-pulse {
  50% { opacity: 0.3; }
}

/* Socials as a quiet strip on the left column's baseline */
.pb-hero-social {
  margin-top: 2rem;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.pb-hero-social-label {
  margin: 0;
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 0.6rem;
  letter-spacing: 1.8px;
  text-transform: uppercase;
  color: var(--pb-muted);
}

.pb-hero-social-links {
  display: flex;
  gap: 0.15rem;
  flex-wrap: wrap;
}

.pb-hero-social-links a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border-radius: 5px;
  color: var(--pb-muted) !important;
  text-decoration: none !important;
  border: 1px solid transparent;
  transition: color 0.16s ease, background-color 0.16s ease, border-color 0.16s ease;
}

.pb-hero-social-links a:hover {
  color: var(--pb-green) !important;
  background: rgba(255, 255, 255, 0.05);
  border-color: var(--pb-glass-border);
}

.pb-hero-social-links i { font-size: 0.95rem; }

/* labels are redundant next to recognisable marks; keep them for a11y only */
.pb-hero-social-links span {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

@media (max-width: 900px) {
  .pb-hero {
    grid-template-columns: 1fr;
    gap: 2rem;
    min-height: 0;
    padding-top: 1rem;
    padding-bottom: 2rem;
  }
  .pb-term { order: 2; }
}

@media (prefers-reduced-motion: reduce) {
  .pb-hero-caret,
  .pb-term-rows dd.is-live::before {
    animation: none;
  }
}

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .pb-term { background: rgba(6, 10, 8, 0.92); }
}

/* Jumbotron
-------------------------------------------------- */
.jumbotron {
  background-color: transparent;
  color: #ffffff;
  border-bottom: 1px solid var(--pb-border);
  margin-bottom: 2rem;
}

.jumbotron h1 {
  font-weight: 600;
  letter-spacing: 1px;
}

.jumbotron h1::after {
  content: "_";
  color: var(--pb-green);
  animation: pb-blink 1.1s steps(2, start) infinite;
}

@keyframes pb-blink {
  to {
    visibility: hidden;
  }
}

/* Buttons
-------------------------------------------------- */
.btn-primary,
.btn-success,
.btn-info {
  --bs-btn-bg: var(--pb-green);
  --bs-btn-color: var(--pb-dark);
  --bs-btn-border-color: var(--pb-green);
  --bs-btn-hover-bg: var(--pb-green-dim);
  --bs-btn-hover-color: var(--pb-dark);
  --bs-btn-hover-border-color: var(--pb-green-dim);
  --bs-btn-active-bg: var(--pb-green-dim);
  --bs-btn-active-color: var(--pb-dark);
  --bs-btn-active-border-color: var(--pb-green-dim);
  --bs-btn-disabled-bg: #1d4d12;
  --bs-btn-disabled-color: #0d0d0d;
  --bs-btn-disabled-border-color: #1d4d12;
  --bs-btn-focus-shadow-rgb: 55, 255, 0;
  font-weight: 600;
}

.btn-secondary,
.btn-dark {
  --bs-btn-bg: var(--pb-card);
  --bs-btn-color: var(--pb-text);
  --bs-btn-border-color: var(--pb-border);
  --bs-btn-hover-bg: var(--pb-surface);
  --bs-btn-hover-color: #ffffff;
  --bs-btn-hover-border-color: var(--pb-green);
  --bs-btn-active-bg: var(--pb-surface);
  --bs-btn-active-color: #ffffff;
  --bs-btn-active-border-color: var(--pb-green);
}

.challenge-submit.btn-outline-secondary {
  --bs-btn-color: var(--pb-dark);
  --bs-btn-bg: var(--pb-green);
  --bs-btn-border-color: var(--pb-green);
  --bs-btn-hover-bg: var(--pb-green-dim);
  --bs-btn-hover-color: var(--pb-dark);
  --bs-btn-hover-border-color: var(--pb-green-dim);
  --bs-btn-active-bg: var(--pb-green-dim);
  --bs-btn-active-color: var(--pb-dark);
  --bs-btn-active-border-color: var(--pb-green-dim);
  font-weight: 600;
}

.btn-outline-secondary {
  --bs-btn-color: var(--pb-text);
  --bs-btn-border-color: var(--pb-border);
  --bs-btn-hover-bg: transparent;
  --bs-btn-hover-color: var(--pb-green);
  --bs-btn-hover-border-color: var(--pb-green);
  --bs-btn-active-bg: transparent;
  --bs-btn-active-color: var(--pb-green);
  --bs-btn-active-border-color: var(--pb-green);
}

/* Forms
-------------------------------------------------- */
/* inputs are glass too — a faint white wash gives them presence on a dark page
   without turning into opaque slabs */
.form-control,
.form-select,
textarea.form-control {
  background-color: rgba(255, 255, 255, 0.045);
  -webkit-backdrop-filter: blur(12px) saturate(150%);
  backdrop-filter: blur(12px) saturate(150%);
  border-color: var(--pb-glass-border);
  color: #ffffff;
  border-radius: 11px;
  box-shadow: var(--pb-glass-rim);
  transition: background-color 0.16s ease, border-color 0.16s ease, box-shadow 0.16s ease;
}

.form-control:hover:not(:focus),
.form-select:hover:not(:focus) {
  background-color: rgba(255, 255, 255, 0.065);
  border-color: rgba(255, 255, 255, 0.16);
}

.form-control:focus,
.form-select:focus {
  background-color: rgba(255, 255, 255, 0.075);
  border-color: var(--pb-green);
  color: #ffffff;
  box-shadow: 0 0 0 0.18rem rgba(55, 255, 0, 0.18), var(--pb-glass-rim);
}

.input-group-text {
  background-color: rgba(255, 255, 255, 0.045);
  border-color: var(--pb-glass-border);
  color: var(--pb-text);
}

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .form-control,
  .form-select,
  textarea.form-control {
    background-color: var(--pb-surface);
  }
}

.form-control::placeholder {
  color: var(--pb-muted);
}

.form-select {
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='%2337ff00' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e");
}

.form-check-input:checked {
  background-color: var(--pb-green);
  border-color: var(--pb-green);
}

/* Cards, modals, dropdowns
-------------------------------------------------- */
.card {
  --bs-card-bg: var(--pb-glass-bg);
  --bs-card-border-color: var(--pb-glass-border);
  --bs-card-cap-bg: rgba(255, 255, 255, 0.03);
  border-radius: 14px;
  -webkit-backdrop-filter: var(--pb-glass-blur);
  backdrop-filter: var(--pb-glass-blur);
  box-shadow: var(--pb-glass-shadow), var(--pb-glass-rim);
}

.modal-content {
  /* denser glass than the cards: it holds body text and an input, so it
     needs more surface presence to stay readable over the frosted page */
  --bs-modal-bg: transparent;
  --bs-modal-border-color: var(--pb-glass-border);
  --bs-modal-header-border-color: var(--pb-glass-border);
  --bs-modal-footer-border-color: var(--pb-glass-border);
  background-color: rgba(12, 18, 14, 0.62);
  -webkit-backdrop-filter: blur(22px) saturate(160%);
  backdrop-filter: blur(22px) saturate(160%);
  border-radius: 16px;
  box-shadow: 0 16px 48px rgba(0, 0, 0, 0.55), var(--pb-glass-rim);
}

/* soften the modal backdrop so the frosted panel has the field/page to
   blur behind it instead of a flat black scrim */
.modal-backdrop.show {
  --bs-backdrop-opacity: 0.42;
  --bs-backdrop-bg: #04070500;
  background-color: rgba(4, 7, 6, 0.42);
}

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .modal-content { background-color: var(--pb-card); }
  .modal-backdrop.show { background-color: rgba(0, 0, 0, 0.6); }
}

/* Confirm dialog (hint / solution unlock)
--------------------------------------------------
   Replaces the browser's native confirm(), which is unstyleable OS chrome.
   Driven by pbctf-ui.js; falls back to confirm() if <dialog> is unsupported. */
.pb-confirm {
  border: 1px solid var(--pb-glass-border);
  border-radius: 18px;
  padding: 0;
  max-width: min(26rem, calc(100vw - 2rem));
  color: var(--pb-text);
  background: linear-gradient(
      to bottom,
      rgba(255, 255, 255, 0.05),
      rgba(255, 255, 255, 0.012) 45%,
      rgba(0, 0, 0, 0.05)
    ),
    rgba(12, 18, 14, 0.72);
  -webkit-backdrop-filter: blur(26px) saturate(180%);
  backdrop-filter: blur(26px) saturate(180%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.14),
    0 24px 60px rgba(0, 0, 0, 0.55);
}

.pb-confirm::backdrop {
  background: rgba(4, 7, 6, 0.5);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
}

.pb-confirm-inner {
  padding: 1.5rem 1.6rem 1.25rem;
}

.pb-confirm-title {
  color: #ffffff;
  font-weight: 600;
  margin: 0 0 0.55rem;
  letter-spacing: 0.2px;
}

.pb-confirm-body {
  margin: 0;
  color: var(--pb-muted);
  font-size: 0.94rem;
}

/* the cost is the decision the player is actually making, so it leads */
.pb-confirm-cost {
  margin: 0.9rem 0 0;
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 1.45rem;
  font-weight: 600;
  color: var(--pb-green);
  line-height: 1;
}

.pb-confirm-actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.6rem;
  margin-top: 1.5rem;
}

.pb-confirm-btn {
  border: 1px solid var(--pb-glass-border);
  border-radius: 11px;
  padding: 0.5rem 1.05rem;
  font-size: 0.92rem;
  font-weight: 600;
  background: rgba(255, 255, 255, 0.06);
  color: var(--pb-text);
  cursor: pointer;
  transition: background-color 0.16s ease, color 0.16s ease, border-color 0.16s ease;
}

.pb-confirm-btn:hover {
  background: rgba(255, 255, 255, 0.1);
  color: #ffffff;
}

.pb-confirm-ok {
  background: var(--pb-green);
  border-color: var(--pb-green);
  color: var(--pb-dark);
}

.pb-confirm-ok:hover {
  background: var(--pb-green-dim);
  border-color: var(--pb-green-dim);
  color: var(--pb-dark);
}

.pb-confirm-btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(55, 255, 0, 0.3);
}

/* Toast (notifications) — plain glass panel */
.toast {
  --bs-toast-bg: rgba(12, 18, 14, 0.66);
  --bs-toast-border-color: var(--pb-glass-border);
  --bs-toast-color: var(--pb-text);
  --bs-toast-header-bg: transparent;
  --bs-toast-header-color: #ffffff;
  --bs-toast-header-border-color: var(--pb-glass-border);
  -webkit-backdrop-filter: var(--pb-glass-blur);
  backdrop-filter: var(--pb-glass-blur);
  border-radius: 12px;
  box-shadow: var(--pb-glass-shadow), var(--pb-glass-rim);
}

.toast-header strong {
  color: #ffffff;
  font-weight: 600;
}

/* Dropdown — glass panel. Kept a fairly firm tint on purpose: this menu holds
   25 language names and hangs past the navbar, so legibility wins over
   transparency. */
.dropdown-menu {
  --bs-dropdown-bg: rgba(12, 18, 14, 0.82);
  --bs-dropdown-border-color: var(--pb-glass-border);
  --bs-dropdown-color: var(--pb-text);
  --bs-dropdown-link-color: var(--pb-text);
  --bs-dropdown-link-hover-color: #ffffff;
  --bs-dropdown-link-hover-bg: rgba(255, 255, 255, 0.07);
  --bs-dropdown-link-active-color: var(--pb-green);
  --bs-dropdown-link-active-bg: rgba(55, 255, 0, 0.1);
  -webkit-backdrop-filter: blur(22px) saturate(180%);
  backdrop-filter: blur(22px) saturate(180%);
  border-radius: 16px;
  padding: 0.4rem;
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.5), var(--pb-glass-rim);
  /* a 25-item list must not run off the viewport */
  max-height: min(70vh, 30rem);
  overflow-y: auto;
  overscroll-behavior: contain;
}

.dropdown-item {
  border-radius: 10px;
  padding: 0.45rem 0.7rem;
  transition: background-color 0.14s ease, color 0.14s ease;
}

/* CTFd marks the current language with .bg-primary.text-white, which reads as a
   solid neon slab. Same subtle green pill as the active nav item instead. */
.dropdown-item.bg-primary,
.dropdown-item.bg-primary.text-white {
  background-color: rgba(55, 255, 0, 0.1) !important;
  color: var(--pb-green) !important;
  font-weight: 600;
}

.dropdown-item.bg-primary:hover,
.dropdown-item.bg-primary.text-white:hover {
  background-color: rgba(55, 255, 0, 0.16) !important;
  color: var(--pb-green) !important;
}

/* slim scrollbar so the long list doesn't get a chunky native bar */
.dropdown-menu::-webkit-scrollbar {
  width: 8px;
}
.dropdown-menu::-webkit-scrollbar-track {
  background: transparent;
}
.dropdown-menu::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.14);
  border-radius: 4px;
}
.dropdown-menu::-webkit-scrollbar-thumb:hover {
  background: rgba(55, 255, 0, 0.4);
}

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .dropdown-menu {
    --bs-dropdown-bg: var(--pb-card);
  }
}

/* Tabs (challenge modal)
-------------------------------------------------- */
.nav-tabs {
  --bs-nav-tabs-border-color: var(--pb-border);
  --bs-nav-tabs-link-active-bg: transparent;
  --bs-nav-tabs-link-active-color: var(--pb-green);
  --bs-nav-tabs-link-active-border-color: var(--pb-border) var(--pb-border) transparent;
  --bs-nav-tabs-link-hover-border-color: var(--pb-border) var(--pb-border) transparent;
  --bs-nav-link-color: var(--pb-muted);
  --bs-nav-link-hover-color: var(--pb-text);
}

/* Settings-style pill nav. A solid neon slab for the active tab shouts over the
   form it belongs to, so use the same restrained green glass pill as the navbar. */
.nav-pills {
  --bs-nav-pills-link-active-bg: rgba(55, 255, 0, 0.11);
  --bs-nav-pills-link-active-color: var(--pb-green);
  --bs-nav-pills-border-radius: 11px;
  --bs-nav-link-color: var(--pb-text);
  --bs-nav-link-hover-color: #ffffff;
}

.nav-pills .nav-link {
  border: 1px solid transparent;
  border-radius: 11px;
  transition: background-color 0.16s ease, color 0.16s ease, border-color 0.16s ease;
}

.nav-pills .nav-link:hover:not(.active) {
  background-color: rgba(255, 255, 255, 0.06);
}

.nav-pills .nav-link.active {
  border-color: rgba(55, 255, 0, 0.34);
  font-weight: 600;
  -webkit-backdrop-filter: var(--pb-glass-blur);
  backdrop-filter: var(--pb-glass-blur);
  box-shadow: var(--pb-glass-rim);
}

/* Tables
-------------------------------------------------- */
.table {
  --bs-table-bg: transparent;
  --bs-table-color: var(--pb-text);
  --bs-table-border-color: var(--pb-border);
  --bs-table-striped-bg: rgba(255, 255, 255, 0.02);
  --bs-table-striped-color: var(--pb-text);
  --bs-table-hover-bg: rgba(55, 255, 0, 0.04);
  --bs-table-hover-color: #ffffff;
}

.table thead th {
  color: #ffffff;
  border-bottom: 2px solid rgba(55, 255, 0, 0.35);
}

/* Challenge board
-------------------------------------------------- */
.category-header h3 {
  color: var(--pb-green);
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 1.15rem;
  letter-spacing: 1px;
  text-transform: uppercase;
}

.category-header h3::before {
  content: "> ";
  opacity: 0.6;
}

[data-bs-theme="dark"] .challenge-button,
.challenge-button {
  background-color: var(--pb-glass-bg) !important;
  -webkit-backdrop-filter: var(--pb-glass-blur);
  backdrop-filter: var(--pb-glass-blur);
  border: 1px solid var(--pb-glass-border);
  border-radius: 14px;
  color: #ffffff;
  box-shadow: var(--pb-glass-shadow), var(--pb-glass-rim);
  transition: border-color 0.18s ease, box-shadow 0.18s ease,
    transform 0.18s ease, background-color 0.18s ease;
}

[data-bs-theme="dark"] .challenge-button:hover,
.challenge-button:hover {
  background-color: var(--pb-glass-bg-hover) !important;
  border-color: rgba(55, 255, 0, 0.55);
  box-shadow: 0 0 20px rgba(55, 255, 0, 0.20), var(--pb-glass-shadow),
    inset 0 1px 0 rgba(255, 255, 255, 0.12);
  transform: translateY(-3px);
}

[data-bs-theme="dark"] .challenge-button.challenge-solved,
.challenge-button.challenge-solved {
  background-color: rgba(55, 255, 0, 0.10) !important;
  border-color: rgba(55, 255, 0, 0.40);
  color: var(--pb-green);
  box-shadow: var(--pb-glass-shadow), inset 0 1px 0 rgba(55, 255, 0, 0.12);
}

[data-bs-theme="dark"] .challenge-button.challenge-solved:hover,
.challenge-button.challenge-solved:hover {
  background-color: rgba(55, 255, 0, 0.16) !important;
  border-color: var(--pb-green);
  box-shadow: 0 0 20px rgba(55, 255, 0, 0.24), var(--pb-glass-shadow),
    inset 0 1px 0 rgba(55, 255, 0, 0.18);
}

/* opaque fallback where backdrop-filter is unsupported */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .challenge-button { background-color: var(--pb-card) !important; }
  .card { --bs-card-bg: var(--pb-card); }
}

.challenge-button .challenge-inner {
  font-family: "JetBrains Mono", ui-monospace, monospace;
}

/* Copy protection on challenge prose
--------------------------------------------------
   Raises friction against bulk-pasting a challenge into an LLM or a group
   chat. It is a speed bump, not a control — devtools, view-source, the API
   and OCR all still work, and nothing client-side can change that.

   Critically this is scoped to the prose only. Connection strings, commands,
   code blocks and links stay selectable, because players legitimately need to
   copy `nc host port`, file URLs and the like. Blocking those would break the
   event, not protect it. */
.challenge-desc {
  -webkit-user-select: none;
  -moz-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

/* the allowlist: anything a player has a real reason to copy */
.challenge-desc code,
.challenge-desc pre,
.challenge-desc kbd,
.challenge-desc samp,
.challenge-desc a,
.challenge-connection-info,
.challenge-connection-info * {
  -webkit-user-select: text;
  -moz-user-select: text;
  user-select: text;
  -webkit-touch-callout: default;
}

/* make it discoverable that code is the copyable part */
.challenge-desc code,
.challenge-desc pre {
  cursor: text;
}

/* Alerts, badges, pagination, misc
-------------------------------------------------- */
/* alerts are glass panels too, so notices sit on the page rather than blocking it */
.alert {
  border-radius: 14px;
  -webkit-backdrop-filter: var(--pb-glass-blur);
  backdrop-filter: var(--pb-glass-blur);
  box-shadow: var(--pb-glass-shadow), var(--pb-glass-rim);
}

.alert-success {
  --bs-alert-bg: rgba(55, 255, 0, 0.1);
  --bs-alert-border-color: rgba(55, 255, 0, 0.4);
  --bs-alert-color: var(--pb-green);
}

.alert-danger {
  --bs-alert-bg: rgba(220, 53, 69, 0.12);
  --bs-alert-border-color: rgba(220, 53, 69, 0.4);
  --bs-alert-color: #ff6b76;
}

.alert-info,
.alert-warning {
  --bs-alert-bg: var(--pb-glass-bg);
  --bs-alert-border-color: var(--pb-glass-border);
  --bs-alert-color: var(--pb-text);
}

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .alert-info,
  .alert-warning {
    --bs-alert-bg: var(--pb-surface);
  }
}

.badge.bg-info,
.badge.bg-primary,
.badge.bg-success {
  background-color: rgba(55, 255, 0, 0.15) !important;
  color: var(--pb-green);
  border: 1px solid rgba(55, 255, 0, 0.35);
}

.pagination {
  --bs-pagination-bg: var(--pb-card);
  --bs-pagination-color: var(--pb-text);
  --bs-pagination-border-color: var(--pb-border);
  --bs-pagination-hover-bg: var(--pb-surface);
  --bs-pagination-hover-color: var(--pb-green);
  --bs-pagination-hover-border-color: var(--pb-border);
  --bs-pagination-focus-bg: var(--pb-surface);
  --bs-pagination-focus-color: var(--pb-green);
  --bs-pagination-active-bg: var(--pb-green);
  --bs-pagination-active-color: var(--pb-dark);
  --bs-pagination-active-border-color: var(--pb-green);
  --bs-pagination-disabled-bg: var(--pb-dark);
  --bs-pagination-disabled-color: var(--pb-muted);
  --bs-pagination-disabled-border-color: var(--pb-border);
}

.spinner,
.fa-spin {
  color: var(--pb-green);
}

.footer {
  border-top: 1px solid var(--pb-border);
  background: var(--pb-dark);
  /* the theme pins the footer at absolute bottom with a fixed 60px height;
     keep both lines inside it or the page gets a scrollbar */
  line-height: 1.6;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.footer a,
.footer .text-muted {
  color: var(--pb-muted) !important;
}

.footer .pb-credit-name,
.footer .ctfd-credit-name {
  transition: color 0.15s ease;
}

.footer .pb-credit:hover .pb-credit-name {
  color: var(--pb-green) !important;
}

.footer .ctfd-credit:hover .ctfd-credit-name {
  color: #ffffff !important;
}
