/* ============================================================================
   Components — cards, buttons, stats, badges, tables, forms.
   House rule: cards carry NO coloured top strip. Colour enters as an accent —
   eyebrows, numerals, hairline hovers, icon glyphs, bar fills.
   ========================================================================== */

/* --- card ---------------------------------------------------------------- */
.card {
  position: relative;
  /* Column, so a card with a call to action can pin it to the foot. Cards in a
     grid row already stretch to the tallest; without this the CTA floats at
     whatever height the copy above happens to end, and a row of them stair-steps. */
  display: flex;
  flex-direction: column;
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-radius: var(--r);
  padding: 1.4rem 1.5rem;
  box-shadow: var(--sh-card);
  transition: transform var(--d-mid) var(--ease-out),
              border-color var(--d-mid) var(--ease),
              box-shadow var(--d-mid) var(--ease-out);
}

/* margin-top: auto eats the slack, so every CTA in a row sits on one line. */
.card-cta {
  margin-top: auto;
  padding-top: 1.2rem;
  color: var(--accent);
  font-size: var(--t-small);
}

.card:hover, .card:focus-within {
  transform: translateY(-3px);
  border-color: var(--border-hi);
  box-shadow: var(--sh-lift);
}

.card-link { color: inherit; }  /* display comes from .card's flex column */
.card-link:hover h3 { color: var(--accent); }
.card h3 { transition: color var(--d-fast) var(--ease); }

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1.1rem;
}
.card-grid-3 { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
.card-grid-4 { grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); }

/* --- stat ---------------------------------------------------------------- */
.stat-label {
  font-family: var(--mono);
  font-size: var(--t-micro);
  letter-spacing: var(--track-mid);
  text-transform: uppercase;
  color: var(--muted);
}
.stat-num {
  font-size: var(--t-num);
  font-weight: 700;
  line-height: 1;
  margin: 0.55rem 0 0.35rem;
  font-variant-numeric: tabular-nums;
  color: var(--fg-hi);
}
.stat-num.is-accent { color: var(--accent); }
.stat-num.is-cyan { color: var(--at-cyan); }
.stat-foot { color: var(--muted); font-size: var(--t-small); line-height: 1.6; }

/* --- badges / tags -------------------------------------------------------- */
.tag {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-family: var(--mono);
  font-size: var(--t-micro);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 0.15rem 0.5rem;
  border-radius: 0;
  border: 1px solid var(--border);
  color: var(--muted);
  background: var(--bg-raised-2);
  white-space: nowrap;
}
.tag-accent { color: var(--accent); border-color: rgba(232, 163, 61, 0.4); background: var(--accent-dim); }
.tag-cyan   { color: var(--at-cyan); border-color: rgba(24, 191, 255, 0.4); background: rgba(24, 191, 255, 0.1); }
.tag-good   { color: var(--good); border-color: rgba(63, 185, 80, 0.4); background: var(--good-dim); }
.tag-crit   { color: var(--crit); border-color: rgba(248, 81, 73, 0.4); background: var(--crit-dim); }
.tag-row { display: flex; flex-wrap: wrap; gap: 0.4rem; }

.kicker {
  display: inline-block;
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
  border: 1px solid var(--border);
  border-left: 2px solid var(--accent);
  padding: 0.3rem 0.7rem;
  background: var(--bg-raised);
}

/* --- buttons -------------------------------------------------------------- */
.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  font-family: var(--mono);
  font-size: var(--t-small);
  letter-spacing: 0.06em;
  padding: 0.72rem 1.35rem;
  border-radius: var(--r);
  border: 1px solid var(--border-hi);
  background: var(--bg-raised);
  color: var(--fg);
  cursor: pointer;
  overflow: hidden;
  transition: transform var(--d-fast) var(--ease-out),
              border-color var(--d-fast) var(--ease),
              color var(--d-fast) var(--ease),
              box-shadow var(--d-mid) var(--ease-out);
}
/* One-pass shine on hover — transform only, compositor-friendly. */
.btn::after {
  content: "";
  position: absolute;
  top: 0; bottom: 0; left: -60%;
  width: 45%;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, 0.09), transparent);
  transform: translateX(0);
  transition: transform 0.55s var(--ease-out);
  pointer-events: none;
}
.btn:hover::after { transform: translateX(340%); }
.btn:hover { border-color: var(--accent); color: var(--fg-hi); }
.btn:active { transform: translateY(1px); }

.btn-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: #14100a;
  font-weight: 500;
}
.btn-primary:hover {
  background: var(--accent-hi);
  border-color: var(--accent-hi);
  color: #14100a;
  box-shadow: 0 10px 26px -12px rgba(232, 163, 61, 0.8);
}
.btn-ghost { background: transparent; }
.btn:disabled { opacity: 0.4; cursor: not-allowed; transform: none; }
.btn:disabled::after { display: none; }

/* Arrow that eases out on hover */
.btn .arw { transition: transform var(--d-mid) var(--ease-out); }
.btn:hover .arw { transform: translateX(3px); }

/* --- link ----------------------------------------------------------------- */
.lnk {
  color: var(--at-cyan);
  border-bottom: 1px solid rgba(24, 191, 255, 0.3);
  overflow-wrap: anywhere;
  transition: border-color var(--d-fast) var(--ease), color var(--d-fast) var(--ease);
}
.lnk:hover { border-bottom-color: var(--at-cyan); color: #6fd6ff; }

/* --- note / callout -------------------------------------------------------- */
.note {
  background: var(--bg-raised-2);
  border: 1px solid var(--border);
  border-left: 2px solid var(--accent);
  border-radius: var(--r);
  padding: 1rem 1.2rem;
  font-size: var(--t-small);
  color: var(--muted);
}
.note b { color: var(--accent); font-weight: 500; }

/* --- bars ------------------------------------------------------------------ */
.bar-track {
  height: 8px;
  background: var(--bg-raised-2);
  border-radius: 0;
  overflow: hidden;
}
.bar-fill {
  height: 100%;
  border-radius: 0;
  background: var(--accent);
  transform-origin: left;
  transform: scaleX(var(--fill, 0));
  transition: transform 0.9s var(--ease-out);
}
.in-view .bar-fill, .no-anim .bar-fill { transform: scaleX(var(--fill, 0)); }
.bar-fill.is-cyan { background: var(--at-cyan); }
.bar-fill.is-good { background: var(--good); }
.bar-fill.is-crit { background: var(--crit); }

/* --- tables ----------------------------------------------------------------- */
.scroll-x { overflow-x: auto; -webkit-overflow-scrolling: touch; }
table.data { width: 100%; border-collapse: collapse; font-size: var(--t-small); }
table.data th {
  text-align: left;
  font-family: var(--mono);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-size: var(--t-micro);
  color: var(--muted);
  border-bottom: 1px solid var(--border);
  padding: 0.55rem 0.7rem 0.55rem 0;
  vertical-align: bottom;
}
table.data td {
  padding: 0.6rem 0.7rem 0.6rem 0;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}
table.data tbody tr { transition: background var(--d-fast) var(--ease); }
table.data tbody tr:hover { background: var(--bg-raised); }
table.data th.n, table.data td.n {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  padding-right: 1.1rem;
}
table.data th:last-child, table.data td:last-child { padding-right: 0; }

/* --- forms ------------------------------------------------------------------- */
.field { display: block; margin-bottom: 1.1rem; }
.field-label {
  display: block;
  font-family: var(--mono);
  font-size: var(--t-micro);
  letter-spacing: var(--track-mid);
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 0.45rem;
}
.input, .textarea, .select {
  width: 100%;
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-radius: var(--r);
  color: var(--fg);
  font-family: var(--mono);
  font-size: var(--t-small);
  padding: 0.7rem 0.85rem;
  transition: border-color var(--d-fast) var(--ease), box-shadow var(--d-fast) var(--ease);
}
.input::placeholder, .textarea::placeholder { color: var(--dim); }
.input:focus, .textarea:focus, .select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-dim);
}
.textarea { min-height: 130px; resize: vertical; line-height: 1.6; }

/* --- disclosure (details) ------------------------------------------------------ */
details.fold { border-top: 1px solid var(--border); }
details.fold > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 0.55rem;
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--accent);
  padding: 0.8rem 0 0.5rem;
  user-select: none;
  transition: color var(--d-fast) var(--ease);
}
details.fold > summary::-webkit-details-marker { display: none; }
details.fold > summary::before {
  content: "";
  width: 0; height: 0;
  border-left: 6px solid var(--accent);
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
  transition: transform var(--d-fast) var(--ease);
  flex: 0 0 auto;
}
details.fold[open] > summary::before { transform: rotate(90deg); }
details.fold > summary:hover { color: var(--accent-hi); }

/* --- utility -------------------------------------------------------------------- */
.stack > * + * { margin-top: 1rem; }
.row { display: flex; flex-wrap: wrap; gap: 0.8rem; align-items: center; }
.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* ── closing CTA panel ────────────────────────────────────────────────────
   Was inline in homepage.html until the Ferox pages needed it too. Shared
   here so the two cannot drift; a page using .cta-panel with no styles behind
   it renders left-aligned and looks broken. */
.cta-panel {
  text-align: center;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background:
    radial-gradient(ellipse 60% 120% at 50% 0%, rgba(232, 163, 61, 0.07), transparent 70%),
    var(--bg-raised);
  padding: clamp(2.4rem, 1.6rem + 3vw, 4rem) var(--gut);
}
.cta-panel h2 { margin-bottom: 0.8rem; }
.cta-panel p { margin: 0 auto; color: var(--muted); }

/* ══ grid spotlight ═══════════════════════════════════════════════════════
   Shared because two pages use it now (the homepage hero and the Ferox page
   hero). The markup is a .hero-band wrapping a .hero-glow, placed as a SIBLING
   of the section it lights, and carrying data-glow-for="<selector>" so
   ui.js knows which section's band to track.
*/
/* ── grid spotlight ───────────────────────────────────────────────
   The page grid lights up amber under the cursor, hero only.

   This layer repeats the SAME geometry as the base grid in base.css and is
   likewise position: fixed, which is the whole trick: both are laid out
   against the viewport, so their 64px lattices line up exactly and the amber
   lines land on the grey ones instead of between them.

   It must live OUTSIDE .hero. The hero carries will-change: transform for the
   scroll reveal, which makes it the containing block for any fixed-position
   descendant -- the layer would then be measured from the hero's top-left
   while the cursor is reported in viewport coordinates, putting the light
   ~108px to the right of the pointer and knocking the grid out of phase.

   Only the mask position changes per frame, so the browser repaints the small
   damaged region rather than re-laying anything out. JS sets --mx / --my here
   and --b-top / --b-bot on the band. Full bleed left to right, so the light
   carries into the page gutters where the grey grid already runs edge to
   edge. */
/* Outer layer: bounds the effect to the hero's vertical band and feathers
   both edges. This is a mask rather than the clip-path it replaces, because
   a clip can only cut a hard line -- the light used to stop dead on the
   hero's bottom border. Above --b-top and below --b-bot the gradient holds
   its transparent end stops, so nothing paints outside the band at all. */
.hero-band {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  --b-top: 0px;
  --b-bot: 0px;
  --b-fade: 104px;
  --band: linear-gradient(
    to bottom,
    rgb(0 0 0 / 0) var(--b-top),
    rgb(0 0 0 / 1) calc(var(--b-top) + var(--b-fade)),
    rgb(0 0 0 / 1) calc(var(--b-bot) - var(--b-fade)),
    rgb(0 0 0 / 0) var(--b-bot)
  );
  mask-image: var(--band);
  -webkit-mask-image: var(--band);
}

.hero-glow {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.28s var(--ease-out);
  background-image:
    linear-gradient(rgba(232, 163, 61, 0.4) 1px, transparent 1px),
    linear-gradient(90deg, rgba(232, 163, 61, 0.4) 1px, transparent 1px);
  background-size: 64px 64px;
  --mx: -999px;
  --my: -999px;
  --glow-r: 265px;
  --pool: radial-gradient(
    circle var(--glow-r) at var(--mx) var(--my),
    rgb(0 0 0 / 0.95) 0%,
    rgb(0 0 0 / 0.68) 26%,
    rgb(0 0 0 / 0.3) 56%,
    rgb(0 0 0 / 0) 100%
  );
  /* Keeps the headline off the lit grid. JS supplies the block's centre and
     radii; defaults are inert so the pool is whole until it measures. */
  --hx: -999px;
  --hy: -999px;
  --hw: 0px;
  --hh: 0px;
  --shade: radial-gradient(
    ellipse var(--hw) var(--hh) at var(--hx) var(--hy),
    rgb(0 0 0 / 1) 0%,
    rgb(0 0 0 / 0.85) 62%,
    rgb(0 0 0 / 0) 100%
  );
  mask-image: var(--pool);
  -webkit-mask-image: var(--pool);
}

/* Subtracting the headline shade needs mask-composite. Where it is missing
   the page simply keeps the undivided pool, which is still correct. */
@supports (mask-composite: subtract) {
  .hero-glow {
    mask-image: var(--pool), var(--shade);
    mask-composite: subtract;
  }
}
.hero-glow.is-lit { opacity: 1; }

/* A cursor-tracking light has no meaning without a cursor, and it is motion
   the reader did not ask for. Off for touch, off under reduced motion. */
@media (hover: none), (pointer: coarse) {
  .hero-band { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .hero-band { display: none; }
}
