/* =====================================================================
   GROWWITHRAM — design system, 2026.

   Direction set by Ram's note of 20 Sep 2026: dark, technical, motion-led.
   This REPLACES the ink-on-cream editorial system in /future rather than
   extending it — the two do not mix, and his six references are all in
   this family.

   The rules that carry it:

   1. TWO GROUNDS, ONE SIGNAL. Near-black and near-white, plus a single
      signal colour used for the machine toggle, the progress bar and
      critical severity. Everything else is opacity.
   2. MONOSPACE IS META. Every number, label, date, severity and key is
      monospace. Prose is never monospace. That split is most of the
      "machine" character and it costs nothing.
   3. ONE ACCENT PER CASE. Chrome stays neutral; each case study sets
      --case. Eight case studies read as distinct without eight designs.
      (lamalama.com's move.)
   4. SQUARE. Carried over from /future — border-radius is 0 almost
      everywhere. It is doing real work.
   5. EVERY MOTION IS OPTIONAL. Anything that moves is behind
      prefers-reduced-motion, and the page is complete without it.
   ===================================================================== */

:root {
  /* ---- Grounds ---------------------------------------------------- */
  --bg:        #09090B;
  --bg-2:      #0E0E11;
  --bg-3:      #141418;
  --fg:        #F2F2F4;
  --dim:       #9B9BA6;   /* 7.23:1 on --bg */
  /*  Was #6A6A74, which measured 3.72:1 and failed WCAG AA. It carries
      every small monospace label on the site (eyebrows, meta keys, dates,
      captions, footer legal), all of them 10-12px, so the 4.5:1 rule for
      normal text applies rather than the 3:1 large-text exception. */
  --dimmer:    #8A8A96;   /* 5.61:1 on --bg */
  --rule:      rgba(242, 242, 244, 0.10);
  --rule-soft: rgba(242, 242, 244, 0.055);

  /* ---- The one signal --------------------------------------------- */
  /*  ONE accent for the whole site. The case cards used to carry eight
      invented hues (a light blue, a pink, two violets) picked only to
      look varied. Nothing outside this token block is a colour now: the
      cards use --signal and differentiate on their severity data. */
  --signal:    #FF4D2E;

  /*  There was a --on-light-dim here, the dimmed ink for the inverted
      band while that band was near-white. The band is now --signal and
      every ink on it is --bg, so the token had no remaining use. A
      token nothing references is a colour waiting to be misapplied. */

  /* ---- Severity. Used on dark only; each passes 4.5:1 on --bg ----- */
  --sev-critical: #FF5C42;
  --sev-high:     #FF9F45;
  --sev-medium:   #E8C84A;
  --sev-low:      #6FD38A;

  /* ---- Per-case accent. Overridden on each card and case page ----- */
  --case: var(--fg);

  /* ---- Type ------------------------------------------------------- */
  --sans: "Archivo", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  /* ---- Measure and rhythm ----------------------------------------- */
  --gutter:  clamp(16px, 4vw, 64px);
  --maxw:    1280px;
  --prose:   62ch;
  --section: clamp(72px, 11vh, 148px);

  /* ---- The sticky bar --------------------------------------------- */
  /*  Three places encoded this independently and disagreed: .split-head
      sat at top: 84px, the bar itself is 56px, and the anchor handler
      subtracted 64. Nothing was broken enough to see, but any change to
      the bar had to be found in three files or headings would tuck
      under it. The bar height is the token; offsets derive from it.
      The anchor handler now measures the real element instead, because
      on a phone the bar is auto-height and no constant is correct. */
  --bar-h:   56px;
  --bar-gap: 28px;

  /* ---- Motion ----------------------------------------------------- */
  --ease:    cubic-bezier(0.22, 1, 0.36, 1);
  --fast:    180ms;
  --slow:    720ms;
}

/* Light mode is not offered. This is a deliberately dark design and a
   half-converted light theme would be worse than none. The scheme is
   declared so form controls and scrollbars render correctly. */
:root { color-scheme: dark; }

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  /* NO scroll-behavior: smooth here. The JS smoother owns wheel scrolling
     on pointer devices; declaring both makes anchor jumps fight. */
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.55;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

img, svg, video { max-width: 100%; height: auto; display: block; }

a { color: inherit; text-decoration: none; }

:where(a, button, [tabindex]):focus-visible {
  outline: 2px solid var(--signal);
  outline-offset: 3px;
}

/* Skip link — present in the markup, visible only on focus. */
.skip {
  position: absolute; left: -9999px; top: 0;
  background: var(--fg); color: var(--bg);
  padding: 12px 18px; font: 600 13px/1 var(--mono); z-index: 200;
}
.skip:focus { left: 0; }

/* =====================================================================
   Layout primitives
   ===================================================================== */

.wrap {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section { padding-block: var(--section); border-top: 1px solid var(--rule-soft); }
.section:first-of-type { border-top: 0; }

/* The eyebrow: a numbered monospace label above every section. */
.eyebrow {
  font: 500 11px/1 var(--mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--dimmer);
  display: flex; align-items: center; gap: 12px;
  margin: 0 0 28px;
}
.eyebrow::after {
  content: ""; flex: 1; height: 1px; background: var(--rule);
}

h1, h2, h3 { font-weight: 700; letter-spacing: -0.025em; margin: 0; }

/*  Sized so the two authored lines stay TWO lines. At the old clamp
    max (6.4rem) each line re-wrapped inside the hero's 1.55fr column and
    the headline rendered as four, which the design skill counts as a
    font-size error rather than a copy-length one. */
.h-display {
  font-size: clamp(2.1rem, 4.6vw, 4.2rem);
  line-height: 1.0;
  letter-spacing: -0.035em;
  font-weight: 700;
  text-wrap: balance;
}
.h-section {
  font-size: clamp(1.7rem, 4.2vw, 3rem);
  line-height: 1.06;
  max-width: 20ch;
}

.lede  { font-size: clamp(1rem, 1.7vw, 1.22rem); color: var(--dim); max-width: var(--prose); }
.prose { max-width: var(--prose); color: var(--dim); }
.prose p { margin: 0 0 1.1em; }
.prose p:last-child { margin-bottom: 0; }
.prose strong { color: var(--fg); font-weight: 600; }

/* =====================================================================
   Top tabs — sticky, minimal. (Lusion's top tabs, Adcker's sticky nav.)
   ===================================================================== */

.topbar {
  position: sticky; top: 0; z-index: 90;
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--rule-soft);
}
/*  .topbar-in, .tabs and .brand used to be declared here. wordmark.css
    re-declares the bar as a grid later in the cascade and sets every one
    of those properties, and topbar() stopped emitting .brand entirely, so
    all three were dead weight that a token change would have had to fight.
    The bar's geometry now lives in one file. Its height is --bar-h. */
.tab {
  font: 500 12px/1 var(--mono);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--dim);
  padding: 9px 13px;
  border: 1px solid transparent;
  transition: color var(--fast) var(--ease), border-color var(--fast) var(--ease);
}
.tab:hover { color: var(--fg); border-color: var(--rule); }
/*  "page", not "true". The builder emits aria-current="page", which is
    the correct value for the current item in a set of links; this
    selector said "true", so it never matched anything and the tab for
    the page you were on looked exactly like the other four. */
.tab[aria-current="page"] { color: var(--fg); border-color: var(--rule); }

/* On narrow screens the tabs used to scroll horizontally rather than
   collapse into a menu. The argument written here was that four items
   fit and a menu would hide the only navigation behind an extra tap.

   On a real phone four items do not fit. At 351px the strip is
   justify-content: flex-end, so it rests SCROLLED TO THE END and the
   first item, Work, sits off the left edge with no scrollbar and no
   affordance to say so. A link nobody can see is worse than a link
   behind a tap, so the tabs now live in .menu (see wordmark.css) and
   Contact stays out of it, visible in the bar.

   The overflow rules are gone with them: there is nothing left in the
   bar wide enough to need scrolling. */
/*  The phone rules that used to sit here are gone too, for the same
    reason as the desktop ones above: wordmark.css sets height, gap and
    padding-block on .topbar-in at its own breakpoint and wins on load
    order, so these never applied. They were also still pinned to 720px
    after that breakpoint moved to 800px, which would have left a
    721-800px band styled by a rule nothing else agreed with. */

/* Scroll progress, pinned to the very top edge. */
#progress {
  position: fixed; inset: 0 0 auto 0; height: 2px; z-index: 100;
  background: transparent; pointer-events: none;
}
#progress span {
  display: block; height: 100%; background: var(--signal);
  transform: scaleX(0); transform-origin: 0 50%;
}

