/* ==========================================================================
   copium.games — Copium Games LLC
   Studio layout · Terminal detailing · scrolling capability ticker.
   Palette follows the DEID core tokens so the two properties read as siblings.
   ========================================================================== */

:root {
  /* Brand */
  --cg-green:     #00ff41;
  --cg-green-rgb: 0, 255, 65;
  --cg-mint:      #14ff99;
  --cg-lime:      #b9ff2e;

  /* Ground — hue-biased toward the accent, not a neutral grey */
  --cg-bg:        #0a0a0b;
  --cg-panel:     #0c0e0d;
  --cg-panel-lit: #111412;

  /* Borders — #27272a is the floor, nothing darker */
  --cg-line:      #27272a;
  --cg-line-lit:  #3a3f3c;

  /* Text */
  --cg-text:      #ffffff;
  --cg-body:      #b3b8b5;
  --cg-muted:     #969b98;
  --cg-dim:       #5f6663;

  --cg-red:       #ff6b6b;
  --cg-amber:     #ffaa00;

  --cg-mono: ui-monospace, "Cascadia Mono", "Cascadia Code", "SF Mono", Menlo,
             Consolas, "Liberation Mono", monospace;
  --cg-sans: "Segoe UI Variable Text", "Segoe UI", system-ui, -apple-system,
             "Helvetica Neue", Arial, sans-serif;

  --cg-radius:      4px;
  --cg-radius-card: 8px;
  --cg-radius-pill: 999px;
  --cg-transition:  0.2s ease;

  /* Container width. .shell reads this, so a section can opt down to a tighter
     measure by redefining the variable on itself — no competing max-width rules
     to fight over specificity. */
  --cg-shell: 1776px;

  /* How far down the page the rain reaches before it is fully gone. The fade is
     weighted so it is already thinning around the 50vh mark. */
  --cg-rain-height: 88vh;
}

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

/* Ground lives on html, not body. With the rain sitting at z-index -1, a body
   background would propagate to the viewport canvas and the layering gets
   harder to reason about. */
html {
  -webkit-text-size-adjust: 100%;
  background: var(--cg-bg);
  /* Keeps anchor targets clear of the sticky header instead of landing behind
     it. One declaration here beats scroll-margin on every heading. */
  scroll-padding-top: 5.5rem;
}
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

body {
  margin: 0;
  /* Positioned so .rain anchors to body rather than the initial containing
     block — deterministic, and unaffected by the overflow-x rule below. */
  position: relative;
  background: transparent;
  color: var(--cg-text);
  font-family: var(--cg-sans);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  /* MUST be clip, not hidden. overflow-x:hidden turns body into a scroll
     container, which silently breaks position:sticky on the header — the
     header would scroll away instead of pinning. clip does the same visual
     job without creating a scrollport. */
  overflow-x: clip;
}

img { max-width: 100%; height: auto; }

a { color: var(--cg-lime); }

:focus-visible {
  outline: 2px solid var(--cg-green);
  outline-offset: 2px;
}

/* Skip link — visible only when focused */
.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  background: var(--cg-green);
  color: #05140a;
  font-family: var(--cg-mono);
  font-size: 0.8rem;
  padding: 0.7rem 1.1rem;
  text-decoration: none;
}
.skip:focus { left: 0; }

.shell {
  max-width: var(--cg-shell);
  margin: 0 auto;
  padding-left: clamp(1rem, 4vw, 3rem);
  padding-right: clamp(1rem, 4vw, 3rem);
}

/* ── Matrix rain layer ───────────────────────────────────────────────────── */
/* Descended from the DEID holiday-rain engine. Absolute rather than fixed, and
   anchored to the top of the document, so the vertical fade belongs to the page
   instead of the screen — a fixed layer would drag its fade line down with the
   viewport as you scroll, which reads as a rendering bug.
   Must be a direct child of body: inside .masthead its overflow would clip it.
   Opaque panels (.card, .term) sit on top and read as cut-outs against it. */
.rain {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: var(--cg-rain-height);
  z-index: -1;
  pointer-events: none;
  overflow: hidden;
}
.rain canvas {
  display: block;
  width: 100%;
  height: 100%;
  /* Full strength behind the headline, well into the fade by ~50vh, gone by the
     bottom edge — so nothing below the hero sits on a moving field. */
  -webkit-mask-image: linear-gradient(to bottom, rgba(0,0,0,1) 0%, rgba(0,0,0,.78) 34%, rgba(0,0,0,.3) 66%, transparent 100%);
          mask-image: linear-gradient(to bottom, rgba(0,0,0,1) 0%, rgba(0,0,0,.78) 34%, rgba(0,0,0,.3) 66%, transparent 100%);
}

/* ── Header ──────────────────────────────────────────────────────────────── */
/* Sticky, and it condenses once you leave the top of the page. The .is-stuck
   class is driven by an IntersectionObserver on a 1px sentinel rather than a
   scroll handler — no listener firing on every frame. */
.nav-sentinel {
  position: absolute;
  top: 0;
  height: 1px;
  width: 1px;
  pointer-events: none;
}
.site-header {
  position: sticky;
  top: 0;
  z-index: 30;
  border-bottom: 1px solid transparent;
  transition: background-color var(--cg-transition),
              border-color var(--cg-transition),
              backdrop-filter var(--cg-transition);
}
.site-header.is-stuck {
  background: rgba(8, 9, 10, 0.82);
  backdrop-filter: blur(10px);
  border-bottom-color: rgba(var(--cg-green-rgb), 0.18);
}

/* ── Nav ─────────────────────────────────────────────────────────────────── */
.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding-top: 1.1rem;
  padding-bottom: 1.1rem;
  transition: padding var(--cg-transition);
}
.site-header.is-stuck .nav {
  padding-top: 0.5rem;
  padding-bottom: 0.5rem;
}
.site-header.is-stuck .brand img {
  width: 30px;
  height: 30px;
}
.brand {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  text-decoration: none;
  flex: 0 0 auto;
}
.brand img {
  width: 38px;
  height: 38px;
  display: block;
  border-radius: 50%;
  transition: width var(--cg-transition), height var(--cg-transition);
}
.brand-name {
  font-family: var(--cg-mono);
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--cg-text);
}
.navlinks {
  display: flex;
  /* Wraps rather than overflowing — four items plus the pill is tight on a
     narrow phone once the wordmark is hidden. */
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 0.55rem clamp(0.85rem, 2.4vw, 1.8rem);
  align-items: center;
}
.navlinks a {
  font-family: var(--cg-mono);
  font-size: 0.73rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  text-decoration: none;
  color: #b6bcb8;
  transition: color var(--cg-transition);
}
.navlinks a:hover { color: var(--cg-text); }
.navlinks a[aria-current="page"] { color: var(--cg-text); }
.navcta {
  font-family: var(--cg-mono);
  font-size: 0.71rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
  border: 1px solid var(--cg-line);
  color: var(--cg-text);
  padding: 0.46rem 1rem;
  border-radius: 999px;
  transition: border-color var(--cg-transition), color var(--cg-transition);
}
.navcta:hover { border-color: var(--cg-green); color: var(--cg-green); }

@media (max-width: 460px) {
  .brand-name { display: none; }
}

/* ── Hero ────────────────────────────────────────────────────────────────── */
.hero {
  padding-top: clamp(3rem, 8vw, 6.5rem);
  padding-bottom: clamp(2.2rem, 5vw, 4rem);
  /* Independent of the shell — the headline gets more room on a wide screen,
     but never so much that the line length stops reading as a statement. */
  max-width: 60rem;
}
.prompt {
  font-family: var(--cg-mono);
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  margin: 0 0 1.3rem;
  color: var(--cg-lime);
}
.prompt .sig { color: #4e5a52; }

.hero h1 {
  font-size: clamp(2rem, 5vw, 4.25rem);
  font-weight: 650;
  letter-spacing: -0.025em;
  line-height: 1.08;
  margin: 0 0 1.2rem;
  text-wrap: balance;
}
.hero h1 em { font-style: normal; color: var(--cg-green); }
.hero .sub {
  font-size: clamp(1rem, 1.6vw, 1.14rem);
  color: var(--cg-muted);
  max-width: 54ch;
  margin: 0 0 2rem;
  line-height: 1.7;
}

/* ── Buttons ─────────────────────────────────────────────────────────────── */
.btns { display: flex; flex-wrap: wrap; gap: 0.8rem; }
.btn {
  font-family: var(--cg-mono);
  font-size: 0.74rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
  padding: 0.8rem 1.5rem;
  border-radius: var(--cg-radius);
  background: var(--cg-green);
  color: #05140a;
  font-weight: 600;
  border: 1px solid var(--cg-green);
  cursor: pointer;
  transition: box-shadow var(--cg-transition);
}
.btn:hover { box-shadow: 0 0 24px rgba(var(--cg-green-rgb), 0.4); }
.btn.ghost {
  background: transparent;
  color: var(--cg-text);
  border-color: var(--cg-line);
  font-weight: 500;
}
.btn.ghost:hover { border-color: var(--cg-text); box-shadow: none; }

/* ── Ticker ──────────────────────────────────────────────────────────────── */
.ticker {
  position: relative;
  border-top: 1px solid rgba(var(--cg-green-rgb), 0.22);
  border-bottom: 1px solid rgba(var(--cg-green-rgb), 0.22);
  background: rgba(0, 0, 0, 0.55);
  overflow: hidden;
  padding: 0.68rem 0;
  /* Feather both ends so items enter and leave instead of being guillotined at
     the viewport edge. */
  -webkit-mask-image: linear-gradient(to right, transparent 0%, #000 7%, #000 93%, transparent 100%);
          mask-image: linear-gradient(to right, transparent 0%, #000 7%, #000 93%, transparent 100%);
}
.ticker-track {
  display: flex;
  width: max-content;
  font-family: var(--cg-mono);
  font-size: 0.72rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--cg-green);
  text-shadow: 0 0 9px rgba(var(--cg-green-rgb), 0.4);
  white-space: nowrap;
  /* Duration is tied to track length, not taste — the shift is a fixed -25%, so
     adding terms speeds the pixels up. Lengthen this whenever the term list
     grows or the ticker starts to read as frantic. */
  animation: cg-scroll 38s linear infinite;
}

/* Each copy carries its own trailing space. Flex `gap` cannot be used here:
   gap renders only *between* items, so a track of n copies is n*S + (n-1)*G
   wide and a -100%/n shift lands a fraction of a gap short — the seam stutters
   every cycle. Padding makes every copy exactly S+P, so the shift is exact. */
.ticker-track > span { padding-right: 2.4rem; }

/* Separators drop back so the terms themselves carry the green. */
.ticker-track em { font-style: normal; color: rgba(var(--cg-green-rgb), 0.32); text-shadow: none; }
.ticker:hover .ticker-track { animation-play-state: paused; }
/* Four copies, shifted by one copy's width (-100%/4). At the end of a cycle the
   layout is pixel-identical to the start, so the reset is invisible — and three
   copies still span the viewport at that point, even at 4K. */
@keyframes cg-scroll {
  from { transform: translateX(0); }
  to   { transform: translateX(-25%); }
}

/* ── Hover glitch ────────────────────────────────────────────────────────── */
/* Ported from .cdcore-glitch-cta in custom-deid-core (cdcore-primitives.css).
   One-shot chromatic aberration — red/cyan text-shadow offsets with sub-pixel
   translation. The CORE original also carries an idle sheen sweep and glow
   pulse; those are left out here so the page stays calm until touched.
   NOTE: transform is inert on non-replaced inline elements, so anything using
   this needs display:inline-block to get the shift as well as the colour. */
@keyframes cg-glitch {
  0%, 100% { text-shadow: 0 0 6px rgba(var(--cg-green-rgb), 0.45); transform: translate(0); }
  20%      { text-shadow: -2px 0 0 #ff003c, 2px 0 0 #00ffff, 0 0 4px var(--cg-green); transform: translateX(0.5px); }
  40%      { text-shadow: 2px 0 0 #ff003c, -2px 0 0 #00ffff, 0 0 6px var(--cg-green); transform: translateX(-0.5px); }
  60%      { text-shadow: 0 0 8px var(--cg-green); transform: translate(0); }
  80%      { text-shadow: -1px 0 0 #ff003c, 1px 0 0 #00ffff; transform: translateY(0.5px); }
}

/* Chromatic only — a green glow is invisible against the solid green fill. */
@keyframes cg-glitch-solid {
  0%, 100% { transform: translate(0); }
  20%      { text-shadow: -2px 0 0 #ff003c, 2px 0 0 #00ffff; transform: translateX(0.5px); }
  40%      { text-shadow: 2px 0 0 #ff003c, -2px 0 0 #00ffff; transform: translateX(-0.5px); }
  60%      { text-shadow: none; transform: translate(0); }
  80%      { text-shadow: -1px 0 0 #ff003c, 1px 0 0 #00ffff; transform: translateY(0.5px); }
}

.navlinks a,
.foot-in a,
.plat-copy .out { display: inline-block; }

.navlinks a:hover,
.navlinks a:focus-visible,
.navcta:hover,
.navcta:focus-visible,
.foot-in a:hover,
.foot-in a:focus-visible,
.plat-copy .out:hover,
.plat-copy .out:focus-visible,
.btn.ghost:hover,
.btn.ghost:focus-visible,
.card:hover h3 {
  animation: cg-glitch 0.45s ease-in-out both;
}

.btn:not(.ghost):hover,
.btn:not(.ghost):focus-visible {
  animation: cg-glitch-solid 0.45s ease-in-out both;
}

/* ── Section heads ───────────────────────────────────────────────────────── */
.shead {
  display: flex;
  align-items: baseline;
  gap: 0.9rem;
  margin-bottom: 1.4rem;
}
.shead h2 {
  font-size: 1.35rem;
  font-weight: 650;
  letter-spacing: -0.015em;
  margin: 0;
}
.shead .idx {
  font-family: var(--cg-mono);
  font-size: 0.68rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--cg-green);
  flex: 0 0 auto;
}
.shead .line { flex: 1; height: 1px; background: var(--cg-line); }

/* ── Service cards ───────────────────────────────────────────────────────── */
/* Matches .operations so both grids run three across at the same card width.
   Six cards land as a balanced 3x2; at the full 1776px they would be 4 + a
   stranded row of 2. */
.services {
  --cg-shell: 1400px;
  padding-top: clamp(2.4rem, 6vw, 4rem);
  padding-bottom: clamp(1.6rem, 4vw, 2.4rem);
}
/* auto-fit would happily stretch four cards across 1776px, giving each ~420px
   of width for two lines of text. Capping the track keeps the proportions and
   lets the row sit left rather than smearing edge to edge. */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 400px));
  gap: 1.25rem;
}
.card {
  border: 1px solid var(--cg-line);
  border-radius: var(--cg-radius-card);
  background: var(--cg-panel);
  padding: 1.45rem 1.35rem 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  transition: border-color var(--cg-transition), transform var(--cg-transition);
}
.card:hover { border-color: var(--cg-line-lit); transform: translateY(-2px); }
.card .tag {
  font-family: var(--cg-mono);
  font-size: 0.63rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--cg-lime);
}
.card h3 { font-size: 1.04rem; font-weight: 600; margin: 0; }
.card p { margin: 0; font-size: 0.91rem; color: var(--cg-muted); line-height: 1.62; }
.card .meta {
  font-family: var(--cg-mono);
  font-size: 0.66rem;
  color: var(--cg-dim);
  letter-spacing: 0.05em;
  margin-top: auto;
  padding-top: 0.8rem;
}

/* ── Method ──────────────────────────────────────────────────────────────── */
/* Full-bleed band so this section reads as a statement rather than another row
   of the grid. The hairlines borrow the CDDS show-more pattern — a gradient
   that fades from transparent at the edges into green at the centre, breathing
   on the same 2.4s cycle. Only the rules pulse; animating the prose behind them
   would fight legibility. */
.method-band {
  position: relative;
  background:
    linear-gradient(180deg,
      rgba(var(--cg-green-rgb), 0.04) 0%,
      transparent 42%,
      transparent 58%,
      rgba(var(--cg-green-rgb), 0.04) 100%),
    rgba(0, 0, 0, 0.3);
}
.method-band::before,
.method-band::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  height: 1px;
  background: linear-gradient(to right,
    transparent 0%,
    rgba(var(--cg-green-rgb), 0.55) 50%,
    transparent 100%);
  animation: cg-breathe 2.4s ease-in-out infinite;
  pointer-events: none;
}
.method-band::before { top: 0; }
.method-band::after  { bottom: 0; }

@keyframes cg-breathe {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.55; }
}

/* Prose, not cards. The page is card-heavy by this point and this is a
   statement of practice — it should read differently from a capability list. */
.method {
  --cg-shell: 1400px;
  padding-top: clamp(2rem, 5vw, 3rem);
  padding-bottom: clamp(2rem, 5vw, 3rem);
}
.method-grid {
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.3fr);
  gap: clamp(1.5rem, 4vw, 3.5rem);
  align-items: start;
}
.method-lead p {
  margin: 0;
  font-size: clamp(1.2rem, 2.1vw, 1.55rem);
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -0.02em;
  color: var(--cg-text);
  text-wrap: balance;
}
.method-lead p em {
  font-style: normal;
  color: var(--cg-green);
}
.method-body p {
  margin: 0 0 1rem;
  color: var(--cg-muted);
  font-size: 1rem;
  line-height: 1.78;
}
.method-body p:last-of-type { margin-bottom: 0; }
.method-body strong { color: #dfe6e1; font-weight: 600; }

.method-points {
  display: flex;
  flex-wrap: wrap;
  gap: 0.55rem;
  margin: 1.35rem 0 0;
  padding: 0;
  list-style: none;
}
.method-points li {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-family: var(--cg-mono);
  font-size: 0.66rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--cg-body);
  border: 1px solid rgba(var(--cg-green-rgb), 0.28);
  border-radius: var(--cg-radius-pill, 999px);
  padding: 0.4rem 0.85rem;
  background: rgba(var(--cg-green-rgb), 0.04);
}
.method-points li::before {
  content: "✓";
  color: var(--cg-green);
  font-size: 0.72rem;
  line-height: 1;
}

@media (max-width: 780px) {
  .method-grid { grid-template-columns: 1fr; }
}

/* ── Operations ──────────────────────────────────────────────────────────── */
/* Opts down so three cards fill their row as completely as four do at full
   width — same 400px track, so card width matches the services grid exactly. */
.operations {
  --cg-shell: 1400px;
  padding-top: clamp(1.6rem, 4vw, 2.4rem);
  padding-bottom: clamp(2rem, 5vw, 3rem);
}

/* ── Platform / case study ───────────────────────────────────────────────── */
/* Opts down from the full shell: a terminal panel 870px wide holding six short
   lines is mostly empty space. */
.platform {
  --cg-shell: 1400px;
  padding-top: clamp(2rem, 5vw, 3.5rem);
  padding-bottom: clamp(2.4rem, 6vw, 4rem);
}
.plat-list {
  display: flex;
  flex-direction: column;
  gap: clamp(2rem, 4vw, 3.25rem);
}
/* A rule between projects so two identical layouts read as a list rather than
   one block that happens to repeat. */
.plat-list > * + * {
  border-top: 1px solid var(--cg-line);
  padding-top: clamp(2rem, 4vw, 3.25rem);
}
.plat-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: 1.6rem;
  align-items: start;
}
.plat-tag {
  display: inline-block;
  font-family: var(--cg-mono);
  font-size: 0.63rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--cg-lime);
  margin: 0 0 0.5rem;
}
.plat-tag.is-nda { color: var(--cg-amber); }
.plat-copy h3 {
  font-size: 1.5rem;
  font-weight: 650;
  margin: 0 0 0.7rem;
  letter-spacing: -0.02em;
}
.plat-copy p {
  margin: 0 0 1rem;
  color: var(--cg-muted);
  font-size: 0.98rem;
  line-height: 1.72;
}
/* Scope evidence. Numbers side by side make the reader conclude the scale on
   their own — the page saying "impressive" about itself would undercut it. */
.plat-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 1.1rem 2.75rem;
  margin: 1.35rem 0;
  padding-top: 1.15rem;
  border-top: 1px solid var(--cg-line);
  list-style: none;
}
.plat-stat { display: flex; flex-direction: column; gap: 0.1rem; }
.plat-stat .n {
  font-family: var(--cg-mono);
  font-size: 1.55rem;
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--cg-green);
  font-variant-numeric: tabular-nums;
  text-shadow: 0 0 14px rgba(var(--cg-green-rgb), 0.3);
}
.plat-stat .l {
  font-family: var(--cg-mono);
  font-size: 0.63rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--cg-dim);
}

.plat-note {
  font-family: var(--cg-mono);
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  color: var(--cg-dim);
  margin: 0;
}
.plat-copy .out {
  font-family: var(--cg-mono);
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--cg-lime);
  text-decoration: none;
}
.plat-copy .out:hover { text-decoration: underline; text-underline-offset: 4px; }

/* Terminal panel — the one place the Terminal register earns its keep */
.term {
  border: 1px solid var(--cg-line);
  border-radius: 6px;
  background: rgba(4, 8, 5, 0.9);
  overflow: hidden;
}
/* Reads as a terminal tab title, so lowercase with normal tracking — the
   uppercase letter-spaced treatment used elsewhere looks like a HUD label. */
.term-bar {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.45rem 0.8rem;
  border-bottom: 1px solid var(--cg-line);
  font-family: var(--cg-mono);
  font-size: 0.7rem;
  letter-spacing: 0.02em;
  color: var(--cg-dim);
}
.term-bar .led {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--cg-green);
  box-shadow: 0 0 8px var(--cg-green);
}
.term-body {
  padding: 1rem;
  margin: 0;
  font-family: var(--cg-mono);
  font-size: 0.79rem;
  line-height: 2.05;
  overflow-x: auto;
}
/* PS1, coloured the way a real shell prompt is — user@host green, path in a
   second hue, the sigil dim. This is most of what sells it as a terminal. */
.term-body .ps1 { color: var(--cg-green); font-weight: 600; }
.term-body .pwd { color: var(--cg-mint); }
.term-body .sig { color: #4e5a52; }

.term-body .cmd { color: #ffffff; }
.term-body .flag { color: var(--cg-lime); }
.term-body .k { color: #4e5a52; display: inline-block; min-width: 11ch; }
.term-body .v { color: #dfe6e1; }
.term-body .ok { color: var(--cg-green); }
.term-body .nda { color: var(--cg-amber); }
/* Redaction uses literal █ glyphs rather than a coloured span over real text —
   nothing to reveal in view-source, and it copies as blocks. */
.term-body .rd {
  color: #333b36;
  letter-spacing: -0.06em;
  user-select: none;
}
.cursor {
  display: inline-block;
  width: 0.55em;
  height: 1em;
  background: var(--cg-green);
  vertical-align: -0.12em;
  margin-left: 0.15em;
  animation: cg-blink 1.1s steps(1) infinite;
}
@keyframes cg-blink {
  0%, 50%      { opacity: 1; }
  50.01%, 100% { opacity: 0; }
}

/* ── Contact band ────────────────────────────────────────────────────────── */
.band {
  border-top: 1px solid var(--cg-line);
  background: rgba(0, 0, 0, 0.4);
}
/* space-between across the full 1776px would fling the copy and the button to
   opposite ends of the screen and read as two unrelated things. */
.band-in {
  --cg-shell: 1400px;
  padding-top: clamp(2.2rem, 5vw, 3.2rem);
  padding-bottom: clamp(2.2rem, 5vw, 3.2rem);
  display: flex;
  flex-wrap: wrap;
  gap: 1.4rem;
  align-items: center;
  justify-content: space-between;
}
.band h2 {
  font-size: 1.3rem;
  font-weight: 650;
  margin: 0 0 0.35rem;
  letter-spacing: -0.015em;
}
.band p { margin: 0; color: var(--cg-muted); font-size: 0.95rem; }

/* ── Footer ──────────────────────────────────────────────────────────────── */
.foot { border-top: 1px solid var(--cg-line); }
.foot-in {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.45rem 1.4rem;
  padding-top: 1.6rem;
  padding-bottom: 1.9rem;
  font-family: var(--cg-mono);
  font-size: 0.71rem;
  letter-spacing: 0.1em;
}
.foot-in a { color: #b6bcb8; text-decoration: none; }
.foot-in a:hover { color: var(--cg-text); }
.foot-in .copy {
  width: 100%;
  text-align: center;
  color: var(--cg-dim);
  letter-spacing: 0.06em;
  margin-top: 0.35rem;
}

/* ── Back to top ─────────────────────────────────────────────────────────── */
/* Progressive enhancement: no JS means it simply never appears. visibility
   rather than [hidden] so the fade can transition. */
.to-top {
  position: fixed;
  right: 16px;
  bottom: 16px;
  z-index: 40;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  cursor: pointer;
  color: var(--cg-green);
  background: rgba(6, 8, 7, 0.88);
  border: 1px solid rgba(var(--cg-green-rgb), 0.35);
  border-radius: var(--cg-radius);
  backdrop-filter: blur(6px);
  opacity: 0;
  visibility: hidden;
  transform: translateY(8px);
  transition: opacity var(--cg-transition), transform var(--cg-transition),
              visibility var(--cg-transition), border-color var(--cg-transition),
              box-shadow var(--cg-transition);
}
.to-top.is-on {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}
.to-top:hover,
.to-top:focus-visible {
  border-color: var(--cg-green);
  box-shadow: 0 0 18px rgba(var(--cg-green-rgb), 0.35);
}
.to-top svg { width: 16px; height: 16px; display: block; }

@media (max-width: 560px) {
  .to-top { width: 40px; height: 40px; right: 12px; bottom: 12px; }
}

/* ── Long-form legal ─────────────────────────────────────────────────────── */
.legal {
  max-width: 1000px;
  margin: 0 auto;
  padding-top: clamp(2.4rem, 6vw, 3.6rem);
  padding-bottom: clamp(2.4rem, 6vw, 3.6rem);
}
.legal .lk {
  font-family: var(--cg-mono);
  font-size: 0.7rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--cg-green);
  margin: 0 0 0.8rem;
}
.legal h1 {
  font-size: clamp(1.7rem, 4vw, 2.3rem);
  font-weight: 650;
  letter-spacing: -0.02em;
  margin: 0 0 0.5rem;
  line-height: 1.15;
}
.legal .updated {
  font-family: var(--cg-mono);
  font-size: 0.73rem;
  color: var(--cg-dim);
  letter-spacing: 0.05em;
  margin: 0 0 1.6rem;
  padding-bottom: 1.3rem;
  border-bottom: 1px solid var(--cg-line);
}
.legal .scope {
  border: 1px solid var(--cg-line);
  border-left: 3px solid var(--cg-green);
  border-radius: 0 6px 6px 0;
  background: var(--cg-panel);
  padding: 0.95rem 1.2rem;
  margin-bottom: 2rem;
}
.legal .scope p { margin: 0; font-size: 0.93rem; color: var(--cg-muted); line-height: 1.68; }
.legal .scope strong { color: var(--cg-text); }
.legal h2 {
  font-size: 1.08rem;
  font-weight: 650;
  margin: 2rem 0 0.65rem;
  letter-spacing: -0.01em;
  display: flex;
  gap: 0.7rem;
  align-items: baseline;
  /* No scroll-margin here — html's scroll-padding-top already clears the sticky
     header, and the two offsets ADD, which would drop every anchored section
     7rem down the page instead of just below the header. */
}
.legal h2 .num {
  font-family: var(--cg-mono);
  font-size: 0.76rem;
  color: var(--cg-green);
  flex: 0 0 auto;
  font-weight: 600;
}
.legal h3 { font-size: 0.95rem; font-weight: 650; margin: 1.4rem 0 0.5rem; color: #dfe6e1; }
/* A 1000px measure runs long for body text, so the type is set up a step and
   given extra leading — a taller line makes the return sweep easier to track
   across the wider column. */
.legal p { margin: 0 0 1.05rem; color: var(--cg-body); font-size: 1.06rem; line-height: 1.85; }
.legal ul { margin: 0 0 1.1rem; padding-left: 1.2rem; color: var(--cg-body); }
.legal li { margin-bottom: 0.5rem; line-height: 1.8; font-size: 1.06rem; }
.legal a { color: var(--cg-lime); text-decoration: underline; text-underline-offset: 3px; }
.legal strong { color: #dfe6e1; }
.legal .toc {
  border: 1px solid var(--cg-line);
  border-radius: 6px;
  background: var(--cg-panel);
  padding: 1.05rem 1.3rem;
  margin-bottom: 1.8rem;
}
.legal .toc h2 {
  font-family: var(--cg-mono);
  font-size: 0.65rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--cg-dim);
  margin: 0 0 0.65rem;
  font-weight: 600;
  display: block;
}
.legal .toc ol { margin: 0; padding-left: 1.2rem; color: var(--cg-muted); font-size: 0.89rem; }
.legal .toc li { margin-bottom: 0.28rem; }
.legal .toc a { color: var(--cg-muted); text-decoration: none; }
.legal .toc a:hover { color: var(--cg-lime); text-decoration: underline; }

/* ── Contact form ────────────────────────────────────────────────────────── */
/* Sized to the form itself, not to .legal's 1000px measure.
   A 1000px container around a 680px form — inputs any wider stop being usable —
   left 320px of dead space on the right and read as misaligned. Matching the
   container to its contents centres the whole block and gives the heading, the
   fields and the footnote one shared left edge.
   Prose and a form legitimately want different measures; forcing them to agree
   only ever aligned the heading. */
.cform {
  max-width: 680px;
  margin: 0 auto;
  padding-top: clamp(2.4rem, 6vw, 3.4rem);
  padding-bottom: clamp(2.4rem, 6vw, 3.4rem);
}
.cform .lk {
  font-family: var(--cg-mono);
  font-size: 0.7rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--cg-green);
  margin: 0 0 0.8rem;
}
.cform h1 {
  font-size: clamp(1.7rem, 4vw, 2.3rem);
  font-weight: 650;
  margin: 0 0 0.65rem;
  letter-spacing: -0.02em;
}
.cform .intro { color: var(--cg-muted); margin: 0 0 1.9rem; font-size: 1.06rem; line-height: 1.78; }
.field { display: flex; flex-direction: column; gap: 0.4rem; margin-bottom: 1.05rem; }
.field label {
  font-family: var(--cg-mono);
  font-size: 0.67rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--cg-muted);
}
.field label .req { color: var(--cg-red); }
.field input,
.field select,
.field textarea {
  width: 100%;
  font-family: inherit;
  font-size: 0.97rem;
  background: var(--cg-panel);
  color: #e8eae9;
  border: 1px solid var(--cg-line);
  border-radius: var(--cg-radius);
  padding: 0.7rem 0.85rem;
  transition: border-color var(--cg-transition), box-shadow var(--cg-transition);
}
.field textarea { resize: vertical; min-height: 128px; line-height: 1.6; }
.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--cg-green);
  box-shadow: 0 0 0 3px rgba(var(--cg-green-rgb), 0.14);
}
.field input:user-invalid,
.field textarea:user-invalid { border-color: var(--cg-red); }
.row { display: grid; grid-template-columns: 1fr 1fr; gap: 1.05rem; }

/* Honeypot — off-screen rather than display:none, which some bots detect */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.turnstile-slot { margin-bottom: 1.15rem; min-height: 65px; }

.cform .privacy { margin: 1.05rem 0 0; font-size: 0.82rem; color: var(--cg-dim); line-height: 1.6; }
/* 404 page reuses .cform for its measure. A class rather than an inline style —
   the CSP has no 'unsafe-inline' for style-src, which covers style attributes. */
.cform .btns { margin-top: 1.5rem; }

/* Form status messages */
.fstatus {
  margin: 1.05rem 0 0;
  padding: 0.85rem 1rem;
  border-radius: var(--cg-radius);
  font-size: 0.92rem;
  border: 1px solid var(--cg-line);
  background: var(--cg-panel);
}
.fstatus[hidden] { display: none; }
.fstatus.is-ok { border-color: rgba(var(--cg-green-rgb), 0.4); color: #dfe6e1; }
.fstatus.is-ok strong { color: var(--cg-green); }
.fstatus.is-err { border-color: rgba(255, 107, 107, 0.45); color: #dfe6e1; }
.fstatus.is-err strong { color: var(--cg-red); }
.is-sending { opacity: 0.6; pointer-events: none; }

/* ── Responsive ──────────────────────────────────────────────────────────── */
@media (max-width: 780px) {
  .plat-grid { grid-template-columns: 1fr; }
}
@media (max-width: 560px) {
  .row { grid-template-columns: 1fr; }
}

@media (prefers-reduced-motion: reduce) {
  .cursor, .ticker-track { animation: none; }
  .card, .btn, .navcta, .navlinks a { transition: none; }
  /* The breathing rules are decorative — hold them at full strength. */
  .method-band::before, .method-band::after { animation: none; }
  .site-header, .nav, .brand img, .to-top { transition: none; }
  /* No chromatic flicker for anyone who asked motion to stop. Hover still
     signals itself through the colour and border changes above. */
  .navlinks a:hover, .navlinks a:focus-visible,
  .navcta:hover, .navcta:focus-visible,
  .foot-in a:hover, .foot-in a:focus-visible,
  .plat-copy .out:hover, .plat-copy .out:focus-visible,
  .btn:hover, .btn:focus-visible,
  .card:hover h3 { animation: none; }
}
