/* ============================================================
   base.css — tokens, reset, typography, focus
   DevCrunch design system: "Signal / Pipeline"

   Colour rules enforced throughout this codebase:
     --signal (amber) = ACT. CTAs, active state, the pulse node.
                        Never used as text on a light surface (1.5:1).
     --trace  (teal)  = FLOW / MEASURE. The pipeline rail and metric
                        numerals only. Never a CTA.
   If either colour turns up doing a third job, it's a mistake.
   ============================================================ */

:root {
  /* ---- Colour ------------------------------------------------ */
  --ink:    #0B0F14;   /* primary background — deep charcoal-blue */
  --paper:  #EDEFF2;   /* primary text on dark                    */
  --signal: #FFB454;   /* amber — CTA, active, pulse   10.8:1 ✓   */
  --trace:  #4FD1C5;   /* teal — rail + metrics        10.2:1 ✓   */
  --slate:  #8B94A3;   /* secondary text, meta          6.2:1 ✓   */
  --line:   #1B222B;   /* hairlines, borders                      */

  /* Derived surfaces. Kept few on purpose — the palette is the
     palette, not a starting point for twelve greys. */
  --surface:     #10161D;  /* raised card on --ink */
  --surface-alt: #131A22;  /* hover / nested card  */
  --line-strong: #2A333F;  /* hover border, focus ring backdrop */

  /* Transparent tints, for washes that survive over any surface. */
  --signal-wash: rgba(255, 180, 84, 0.10);
  --trace-wash:  rgba(79, 209, 197, 0.10);
  --ink-veil:    rgba(11, 15, 20, 0.86);

  /* ---- Type -------------------------------------------------- */
  --font-display: "Space Grotesk", "Segoe UI", system-ui, sans-serif;
  --font-body:    "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono:    "JetBrains Mono", ui-monospace, "Cascadia Mono", Consolas, monospace;

  /* Scale: 14 / 16 / 20 / 28 / 40 / 64 / 96 */
  --fs-xs:  0.875rem;  /* 14 */
  --fs-sm:  1rem;      /* 16 */
  --fs-md:  1.25rem;   /* 20 */
  --fs-lg:  1.75rem;   /* 28 */
  --fs-xl:  2.5rem;    /* 40 */
  --fs-2xl: 4rem;      /* 64 */
  --fs-3xl: 6rem;      /* 96 */

  /* Fluid headings, clamped to the scale at both ends. */
  --fs-h1:      clamp(2.5rem, 1.15rem + 5.9vw, 6rem);      /* 40 → 96 */
  --fs-h1-page: clamp(2.25rem, 1.5rem + 3.3vw, 4rem);      /* 36 → 64 */
  --fs-h2:      clamp(1.75rem, 1.3rem + 2vw, 2.5rem);      /* 28 → 40 */
  --fs-h3:      clamp(1.25rem, 1.1rem + 0.7vw, 1.75rem);   /* 20 → 28 */

  --lh-tight: 1.02;
  --lh-snug:  1.18;
  --lh-body:  1.65;

  --track-display: -0.03em;  /* tight, geometric */
  --track-mono:     0.08em;  /* wide, technical  */

  /* ---- Space (4px base) -------------------------------------- */
  --sp-1:  0.25rem;
  --sp-2:  0.5rem;
  --sp-3:  0.75rem;
  --sp-4:  1rem;
  --sp-5:  1.25rem;
  --sp-6:  1.5rem;
  --sp-8:  2rem;
  --sp-12: 3rem;
  --sp-16: 4rem;
  --sp-24: 6rem;
  --sp-32: 8rem;
  --sp-40: 10rem;

  --section-y: clamp(4.5rem, 9vw, 8rem);

  /* ---- Layout ------------------------------------------------ */
  --wrap-max:    1280px;
  --wrap-narrow: 720px;
  --gutter:      clamp(1.25rem, 4vw, 3rem);
  --trace-col:   150px;  /* left spine column, ≥1200px only */

  /* ---- Form ------------------------------------------------- */
  --radius-sm: 4px;
  --radius:    8px;
  --radius-lg: 14px;

  /* ---- Motion ------------------------------------------------ */
  --ease-out:  cubic-bezier(0.16, 1, 0.3, 1);
  --ease-soft: cubic-bezier(0.4, 0, 0.2, 1);
  --dur-fast:  160ms;
  --dur:       260ms;
  --dur-slow:  400ms;

  color-scheme: dark;
}

/* ============================================================
   Reset
   ============================================================ */

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

* { margin: 0; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Sticky header height + breathing room, so #anchor targets
     don't land underneath the header. */
  scroll-padding-top: 6rem;
}

body {
  min-height: 100svh;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  line-height: var(--lh-body);
  font-synthesis-weight: none;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* Nothing may cause a horizontal scrollbar. Required down to 360px. */
  overflow-x: hidden;
}

img,
svg,
video {
  display: block;
  max-width: 100%;
  height: auto;
}

input,
button,
textarea,
select {
  font: inherit;
  color: inherit;
}

button { background: none; border: none; }

ul, ol { list-style: none; padding: 0; }

/* [hidden] must win. Several components set an explicit `display`
   (flex, grid) which would otherwise beat the UA stylesheet's
   `[hidden] { display: none }` and leave hidden nodes — empty error
   slots, the step-2 panel — rendered. */
[hidden] { display: none !important; }

p,
h1, h2, h3, h4 { overflow-wrap: break-word; }

table { border-collapse: collapse; }

/* ============================================================
   Typography
   ============================================================ */

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: var(--track-display);
  line-height: var(--lh-snug);
  text-wrap: balance;
}

h1 { font-size: var(--fs-h1); line-height: var(--lh-tight); }
h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-h3); font-weight: 600; }
h4 { font-size: var(--fs-md); font-weight: 600; }

a {
  color: inherit;
  text-decoration-color: color-mix(in srgb, var(--paper) 35%, transparent);
  text-underline-offset: 0.22em;
  text-decoration-thickness: 1px;
  transition: color var(--dur-fast) var(--ease-soft),
              text-decoration-color var(--dur-fast) var(--ease-soft);
}

a:hover {
  color: var(--signal);
  text-decoration-color: var(--signal);
}

strong { font-weight: 600; color: var(--paper); }

code, kbd, samp, pre {
  font-family: var(--font-mono);
  font-size: 0.9em;
}

::selection {
  background: var(--signal);
  color: var(--ink);
}

/* ---- Shared type utilities --------------------------------- */

/* The mono annotation that runs through the whole site: `// work` */
.eyebrow {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  font-weight: 400;
  letter-spacing: var(--track-mono);
  color: var(--slate);
  text-transform: lowercase;
}

.h-section {
  font-size: var(--fs-h2);
  margin-block-end: var(--sp-8);
}

/* Long-form body copy: articles, case-study sections, About. */
.prose {
  max-width: 68ch;
  color: color-mix(in srgb, var(--paper) 88%, var(--slate));
}

.prose > * + * { margin-block-start: var(--sp-6); }

.prose h2 {
  font-size: var(--fs-h3);
  color: var(--paper);
  margin-block-start: var(--sp-12);
}

.prose h3 {
  font-size: var(--fs-md);
  font-weight: 600;
  color: var(--paper);
  margin-block-start: var(--sp-8);
  letter-spacing: -0.015em;
}

.prose a {
  color: var(--paper);
  text-decoration: underline;
  text-decoration-color: var(--signal);
}

.prose a:hover { color: var(--signal); }

.prose code {
  background: var(--surface-alt);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 0.1em 0.35em;
  color: var(--trace);
  /* Inline code must wrap. A long identifier with nowrap pushes the
     whole document wider than the viewport at 360px, and no amount of
     overflow:hidden on an ancestor makes that correct — it only hides
     it. Breaking mid-token is the lesser evil. */
  overflow-wrap: anywhere;
}

.prose em { color: var(--paper); }

/* ============================================================
   Focus — visible, styled, never removed (WCAG 2.4.7)
   ============================================================ */

:focus { outline: none; }

:focus-visible {
  outline: 2px solid var(--signal);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}

/* Inputs get an inset ring instead, so the outline doesn't collide
   with the neighbouring field at tight vertical rhythm. */
.field__input:focus-visible {
  outline: 2px solid var(--signal);
  outline-offset: 0;
  border-color: var(--signal);
}

.skip-link {
  position: absolute;
  left: var(--sp-4);
  top: var(--sp-4);
  z-index: 200;
  transform: translateY(-200%);
  background: var(--signal);
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: var(--track-mono);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--radius);
  text-decoration: none;
  transition: transform var(--dur) var(--ease-out);
}

.skip-link:focus-visible {
  transform: translateY(0);
  color: var(--ink);
}

/* Screen-reader-only, still focusable. */
.visually-hidden:not(:focus):not(:active) {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Honeypot field — hidden from people, visible to bots. */
.hp {
  position: absolute !important;
  left: -9999px;
  opacity: 0;
  pointer-events: none;
}

/* ============================================================
   Reduced motion — global off switch.
   Individual components layer more on top in animations.css.
   ============================================================ */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
