/* ============ THEME TOKENS ============ */
:root {
  /* Default = DARK page; codeblock background is LIGHT (inv-bg). */
  --paper:    14  14  14;
  --ink:      237 237 237;
  --muted:    176 176 176;      /* WCAG AA: 8.9:1 on paper (was 154 → 6.9:1) */
  --chip:     26  26  26;
  --inv-bg:   244 241 234;
  --inv-text: 17  17  17;
  /* Syntax tokens — tuned to read on the LIGHT codeblock bg in dark mode */
  --syn-prompt:   96  96  96;   /* AA: 5.6:1 (was 120 → 3.9:1, failed) */
  --syn-cmd:      22 101  52;   /* forest green */
  --syn-flag:    154  85   0;   /* amber */
  --syn-url:      29  78 216;   /* deep blue */
  --syn-op:       96  96  96;   /* AA: 5.6:1 (was 120 → 3.9:1, failed) */
  --syn-arg:      71  85 105;   /* slate */
  color-scheme: dark;
}
:root.light {
  --paper:    244 241 234;
  --ink:      17  17  17;
  --muted:    74  74  74;       /* WCAG AA: 7.9:1 on paper (was 90 → 6.1:1) */
  --chip:     234 230 220;
  --inv-bg:   17  17  17;
  --inv-text: 244 241 234;
  /* Codeblock bg is DARK in light mode → use BRIGHT syntax colors */
  --syn-prompt:  148 163 184;
  --syn-cmd:      74 222 128;   /* bright green */
  --syn-flag:    251 191  36;   /* bright amber */
  --syn-url:     125 211 252;   /* sky-blue */
  --syn-op:      148 163 184;
  --syn-arg:     203 213 225;
  color-scheme: light;
}

html { scroll-behavior: smooth; scroll-padding-top: 56px; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
html, body { background: rgb(var(--paper)); color: rgb(var(--ink)); }
body {
  /* Subtle DOT field — no edges to misalign against UI boxes. */
  background-image: radial-gradient(rgb(var(--ink) / 0.10) 1px, transparent 1.5px);
  background-size: 28px 28px;
  background-position: 0 0;
  background-attachment: scroll;
}

/* ============ Square scrollbar (custom, boxy — replaces native) ============ */
/* WebKit / Blink (Chrome, Edge, Safari). Bordered track + solid square thumb
   block (inset via a paper-colored border), accent on hover. No round corners,
   no native arrow buttons → reads as part of the brutalist box grid. */
::-webkit-scrollbar { width: 14px; height: 14px; }
::-webkit-scrollbar-track {
  background: rgb(var(--paper));
  border: 1px solid rgb(var(--ink));
}
::-webkit-scrollbar-thumb {
  background: rgb(var(--ink));
  border: 3px solid rgb(var(--paper));   /* inset gap → distinct square block */
  border-radius: 0;
}
::-webkit-scrollbar-thumb:hover  { background: color-mix(in srgb, rgb(var(--ink)) 65%, black); }  /* just darker */
::-webkit-scrollbar-thumb:active { background: color-mix(in srgb, rgb(var(--ink)) 50%, black); }  /* darker still */
::-webkit-scrollbar-corner { background: rgb(var(--paper)); }
::-webkit-scrollbar-button { display: none; width: 0; height: 0; }  /* kill default arrows */

/* Firefox — themed (not the native grey). `auto` keeps it chunky & visible.
   CRITICAL: gated behind `@supports not selector(::-webkit-scrollbar)`.
   Since Chrome 121 the standard scrollbar-color/scrollbar-width properties
   OVERRIDE the ::-webkit-scrollbar pseudo-elements, forcing the rounded
   (pill/oval) native thumb and discarding our square border-radius:0 styling.
   The @supports guard applies these only on engines WITHOUT ::-webkit-scrollbar
   (Firefox), so Blink keeps the boxy ::-webkit-scrollbar look. */
@supports not selector(::-webkit-scrollbar) {
  html { scrollbar-color: rgb(var(--ink)) rgb(var(--paper)); scrollbar-width: auto; }
}

/* Inverted regions (light codeblocks in dark mode, etc.) */
.inv ::-webkit-scrollbar-track { background: rgb(var(--inv-bg)); border-color: rgb(var(--inv-text)); }
.inv ::-webkit-scrollbar-thumb { background: rgb(var(--inv-text)); border-color: rgb(var(--inv-bg)); }
.inv ::-webkit-scrollbar-thumb:hover { background: color-mix(in srgb, rgb(var(--inv-text)) 65%, black); }

/* ============ Features grid — keep the 8 cells tidy ============ */
/* Each cell stacks: num → heading → list. Headings vary in length and wrap to
   one or two lines at narrow column widths, which pushed each cell's <ul> to a
   different vertical start and made the row look ragged. Reserve a uniform
   two-line heading height (only when the grid is multi-column) so every list
   begins on the same line across a row, and let the list grow to fill so cell
   bottoms stay aligned. */
@media (min-width: 640px) {
  #features .grid-cell { display: flex; flex-direction: column; }
  #features .grid-cell .cell-sum { flex: 1 1 auto; }
}
/* Compact: tighten the title→summary gap (overrides the mt-3 utility). */
#features .grid-cell .cell-sum { margin-top: 0.375rem; }
/* Summary line is muted, but must stay readable on the inverted hover bg. */
.grid-cell:hover .cell-sum { color: rgb(var(--paper) / 0.85); }

/* ============ Pixel marquee (LED dot-matrix vibe) ============ */
.pixel-marquee {
  font-family: "VT323", ui-monospace, monospace;
  font-size: clamp(1rem, 2.2vw, 1.5rem);
  letter-spacing: 0.05em;
  line-height: 1;
}
.pixel-marquee .dot { display: inline-block; vertical-align: middle; }
@keyframes pixel-scroll { from { transform: translateX(0); } to { transform: translateX(-50%); } }
.pixel-track {
  animation: pixel-scroll 60s linear infinite;
  will-change: transform;
}
@media (prefers-reduced-motion: reduce) { .pixel-track { animation: none; } }

/* ============ Code block visuals (color tokens + variants) ============ */
.codeblock-head {
  background: rgb(var(--paper));
}
.codeblock-body {
  background: rgb(var(--inv-bg));
  color: rgb(var(--inv-text));
  border-radius: 0;
  tab-size: 2;
}
.codeblock-body .prompt { color: rgb(var(--syn-prompt)); user-select: none; }
.codeblock-body .cmd    { color: rgb(var(--syn-cmd));    font-weight: 700; }
.codeblock-body .flag   { color: rgb(var(--syn-flag));   font-weight: 500; }
.codeblock-body .url    { color: rgb(var(--syn-url));    text-decoration: underline; text-underline-offset: 3px; text-decoration-style: dotted; }
.codeblock-body .op     { color: rgb(var(--syn-op)); }
.codeblock-body .arg    { color: rgb(var(--syn-arg)); }
.copy-btn[data-state="copied"] { background: rgb(var(--ink)); color: rgb(var(--paper)); }

/* Format-chip variants — same size as .copy-btn, color-coded per package format. */
.chip-fmt-deb { background: #b91c1c; color: #ffffff; border-color: #b91c1c; }   /* Debian red */
.chip-fmt-rpm { background: #1d4ed8; color: #ffffff; border-color: #1d4ed8; }   /* Fedora blue */
.chip-fmt-app { background: #15803d; color: #ffffff; border-color: #15803d; }   /* AppImage green */

/* ============ Download dropdown (<details>/<summary> based) ============ */
.dl-dropdown {
  position: relative;
  border: 1px solid rgb(var(--ink));
  background: rgb(var(--ink));
}
.dl-dropdown[open] { z-index: 30; }
.dl-dropdown > summary {
  list-style: none;
  cursor: pointer;
  padding: 0.5rem 1rem;
  background: rgb(var(--ink));
  color: rgb(var(--paper));
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 14px;
  font-weight: 600;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem;
  transition: background-color 150ms, color 150ms;
  user-select: none;
}
.dl-dropdown > summary::-webkit-details-marker { display: none; }
.dl-dropdown > summary::marker { content: ''; }
.dl-dropdown:not([open]) > summary:hover {
  background: rgb(var(--paper));
  color: rgb(var(--ink));
}
.dl-dropdown .arrow {
  display: inline-block;
  transition: transform 200ms ease;
  font-size: 11px;
  line-height: 1;
}
.dl-dropdown[open] .arrow { transform: rotate(180deg); }
/* Menu floats absolutely below summary so opening doesn't push other cells */
.dl-menu {
  position: absolute;
  top: 100%;
  left: -1px;
  right: -1px;
  z-index: 30;
  background: rgb(var(--paper));
  border: 1px solid rgb(var(--ink));
  border-top: 0;
  display: flex;
  flex-direction: column;
  box-shadow: 0 4px 0 rgb(0 0 0 / 0.15);
}
.dl-menu > a {
  padding: 0.5rem 1rem;
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 12.5px;
  color: rgb(var(--ink));
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem;
  transition: background-color 150ms, color 150ms;
}
.dl-menu > a + a { border-top: 1px solid rgb(var(--ink)); }
.dl-menu > a:hover {
  background: rgb(var(--ink));
  color: rgb(var(--paper));
}
.dl-menu > a .meta { opacity: 0.75; font-size: 11px; }

/* ============ CTA buttons (inside .inv section) ============ */
.cta-btn-primary {
  background: rgb(var(--inv-text));
  color: rgb(var(--inv-bg));
  border-color: rgb(var(--inv-text));
}
.cta-btn-primary:hover {
  background: rgb(var(--inv-bg));
  color: rgb(var(--inv-text));
  border-color: rgb(var(--inv-text));
}
.cta-btn-ghost {
  background: transparent;
  color: inherit;
  border-color: currentColor;
}
.cta-btn-ghost:hover {
  background: rgb(var(--inv-text));
  color: rgb(var(--inv-bg));
  border-color: rgb(var(--inv-text));
}

/* ============ Stripe accent ============ */
.stripes {
  background-image: repeating-linear-gradient(45deg, rgb(var(--ink)) 0 1px, transparent 1px 8px);
}

/* ============ Image modal (native <dialog>) ============ */
.image-modal {
  padding: 0;
  border: 1px solid rgb(var(--ink));
  background: rgb(var(--paper));
  color: rgb(var(--ink));
  max-width: min(95vw, 1920px);
  max-height: 95vh;
  width: auto;
  border-radius: 0;
  overflow: visible;
}
.image-modal::backdrop { background: rgb(0 0 0 / 0.80); }
.image-modal img {
  display: block;
  max-width: 100%;
  max-height: calc(95vh - 2px);
  height: auto;
  width: auto;
}
.modal-close {
  position: absolute;
  top: -1px;
  right: -1px;
  width: 36px;
  height: 36px;
  background: rgb(var(--paper));
  color: rgb(var(--ink));
  border: 1px solid rgb(var(--ink));
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background-color 150ms, color 150ms;
  border-radius: 0;
}
.modal-close:hover { background: rgb(var(--ink)); color: rgb(var(--paper)); }
.modal-trigger { cursor: zoom-in; }

/* ============ Hero video (click to play inline; YouTube fallback) ============ */
.hero-video {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: rgb(var(--ink));
  overflow: hidden;
}
.hero-video-btn {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  padding: 0;
  margin: 0;
  background: transparent;
  border: 0;
  cursor: pointer;
  overflow: hidden;
}
.hero-video-btn img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.hero-video-play {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}
.hero-video-play svg {
  width: 76px;
  height: auto;
  filter: drop-shadow(0 2px 8px rgb(0 0 0 / 0.5));
  transition: transform 150ms;
}
.hero-video-btn:hover .hero-video-play svg { transform: scale(1.08); }
.hero-video-fallback {
  position: absolute;
  bottom: 10px;
  right: 10px;
  z-index: 2;
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 11px;
  padding: 4px 8px;
  background: rgb(0 0 0 / 0.65);
  color: #fff;
  letter-spacing: 0.02em;
  text-decoration: none;
  border: 1px solid rgb(255 255 255 / 0.2);
  transition: background-color 150ms;
}
.hero-video-fallback:hover { background: rgb(0 0 0 / 0.85); }
.hero-video iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  pointer-events: none;
}

/* ============ Scroll to top ============ */
.scroll-top {
  position: fixed;
  right: 16px; bottom: 16px;
  z-index: 40;
  border: 1px solid rgb(var(--ink));
  background: rgb(var(--paper));
  color: rgb(var(--ink));
  padding: 8px 12px;
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  line-height: 1;
  opacity: 0;
  transform: translateY(16px);
  pointer-events: none;
  transition: opacity 200ms ease, transform 200ms ease, background-color 150ms, color 150ms;
  border-radius: 0;
}
.scroll-top.is-visible { opacity: 1; transform: translateY(0); pointer-events: auto; }
.scroll-top:hover { background: rgb(var(--ink)); color: rgb(var(--paper)); }

/* ============ ASCII rotating globe (lives inside the CTA box) ============ */
.cta-section { position: relative; overflow: hidden; }
.cta-content { position: relative; z-index: 2; }
.cta-globe-wrap {
  position: absolute;
  inset: 0;
  display: flex;
  justify-content: center;
  align-items: flex-end;   /* anchor canvas to bottom edge of CTA */
  pointer-events: none;
  z-index: 1;
  overflow: hidden;
}
.cta-globe {
  display: block;
  width: clamp(260px, 62%, 540px);
  aspect-ratio: 1 / 1;
  /* Push the canvas down so only the upper crown of the rendered disc
     sits inside the CTA box (slightly more than half → lower-lying horizon). */
  transform: translateY(58%);
  opacity: 1;
}
@media (max-width: 640px) {
  .cta-globe { width: clamp(220px, 80%, 360px); opacity: 1; }
}

/* ============ Scramble — per-char width lock, set by JS on init ============ */
#reorg { display: inline-block; vertical-align: baseline; white-space: nowrap; }
/* Each character gets its own inline-block box with its measured width baked
   in, so swapping a narrow glyph for a wider one during scramble can't push
   the layout. Vertical overflow stays visible so descenders (g, z, j …) are
   never clipped. */
#reorg .reorg-char {
  display: inline-block;
  text-align: center;
  vertical-align: baseline;
}
