/* Tighina Capital — homepage
   Color system: two 12-step scales on Radix Colors' step semantics, seeded from the
   original flat palette so the appearance is preserved — this is a systematization,
   not a redesign. The original colors land exactly on their semantic steps:
     parchment #F5F2EA → --sand-2   ink #24221D    → --sand-12
     muted    #5D5849  → --sand-11  faint #8A8477   → --sand-10
     moss     #55613B  → --olive-9  moss-dark #3E4A2C → --olive-11
   Radix step roles (both scales): 1 app bg · 2 subtle bg · 3-5 component bg ·
   6 subtle border · 7 UI border · 8 hover border · 9 solid · 10 hovered solid ·
   11 low-contrast text · 12 high-contrast text. */

:root {
  /* Sand — warm neutral (parchment → ink) */
  --sand-1:  #FAF8F2;
  --sand-2:  #F5F2EA;
  --sand-3:  #F0EDE5;
  --sand-4:  #EBE8E0;
  --sand-5:  #E5E2DB;
  --sand-6:  #E0DDD6;
  --sand-7:  #D6D3CB;
  --sand-8:  #C4C1B9;
  --sand-9:  #A6A194;
  --sand-10: #8A8477;
  --sand-11: #5D5849;
  --sand-12: #24221D;

  /* Olive — moss accent */
  --olive-1:  #F6F8F2;
  --olive-2:  #EDF1E6;
  --olive-3:  #E2E8D6;
  --olive-4:  #D6DEC6;
  --olive-5:  #C9D3B4;
  --olive-6:  #B9C69F;
  --olive-7:  #A5B587;
  --olive-8:  #869A6A;
  --olive-9:  #55613B;
  --olive-10: #4A5533;
  --olive-11: #3E4A2C;
  --olive-12: #2C3520;

  --serif: "EB Garamond", Georgia, serif;
  --sans: "Instrument Sans", system-ui, sans-serif;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--sand-2);
  color: var(--sand-12);
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
}

a { color: var(--olive-9); text-decoration: none; }
a:hover { color: var(--olive-11); }
a:focus-visible { outline: 2px solid var(--olive-9); outline-offset: 3px; border-radius: 1px; }
::selection { background: color-mix(in srgb, var(--olive-9) 20%, transparent); }

.page {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

.container {
  max-width: 1280px;
  width: 100%;
  margin: 0 auto;
  flex: 1;
  display: flex;
  flex-direction: column;
}

main { display: flex; flex-direction: column; }

/* Sticky № navigation — fixed to the left edge on viewports wide enough that
   it clears the 1280px container. Plain anchors, so it works without JS; the
   .active state is set by the section observer. */

.side-nav {
  position: fixed;
  left: 22px;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  flex-direction: column;
  gap: 16px;
  z-index: 10;
}

.side-nav a {
  font-family: var(--serif);
  font-size: 14px;
  color: var(--sand-9);
  font-variant-numeric: oldstyle-nums;
  transition: color 0.25s ease;
  white-space: nowrap;
}

.side-nav a:hover { color: var(--olive-11); }
.side-nav a.active { color: var(--olive-9); }

.side-nav a.active::after {
  content: "";
  display: inline-block;
  width: 14px;
  height: 1px;
  background: var(--olive-9);
  vertical-align: middle;
  margin-left: 8px;
}

@media (max-width: 1419px) { .side-nav { display: none; } }

/* Header */

.site-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
  padding: 36px 64px;
  border-bottom: 1px solid var(--sand-12);
}

.wordmark {
  display: block;
  height: 30px;
  width: auto;
  /* Flexbox takes an image's baseline as its bottom edge, but the logotype's
     baseline sits ~5px higher (the "g" descender reaches the bottom). Pull the
     margin edge up so the tagline aligns to the wordmark's optical baseline. */
  margin-bottom: -5px;
}

.tagline {
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sand-11);
}

/* Numbered rows */

.row {
  display: grid;
  grid-template-columns: 220px minmax(0, 1fr);
  border-bottom: 1px solid var(--sand-7);
}

.row--contact { border-bottom: 1px solid var(--sand-12); }

.rail {
  padding: 64px 0 64px 64px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.num {
  font-family: var(--serif);
  font-size: 16px;
  color: var(--olive-9);
  /* NOTE: no-op for the current font. The Google Fonts / Fontsource build of
     EB Garamond ships only oldstyle (text) figures with no lining alternate, so
     these numerals are already oldstyle by default and this declaration produces
     no visible change (verified: oldstyle-nums, lining-nums and normal render
     identically). Kept as an explicit statement of intent — it would take effect
     if the serif is ever swapped for a font that defaults to lining figures. */
  font-variant-numeric: oldstyle-nums;
}

.label {
  margin: 0;
  font-family: var(--sans);
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--sand-10);
}

.content { padding: 64px 64px 72px 48px; min-width: 0; }

/* Cross-section link lines ("Start a conversation →" etc.) */

.next-link { margin: 0; font-size: 15px; color: var(--sand-11); }

/* Section graphics (SVG line art) — hand-drawn diagrams sharing a draw-in
   load animation (see @keyframes tighina-draw below) and a small set of
   hover micro-interactions. */

.gfx {
  fill: none;
  stroke: var(--olive-9);
  stroke-width: 1.25;
  stroke-linecap: round;
  stroke-linejoin: round;
  justify-self: end;
  max-width: 100%;
  height: auto;
}

.gfx-reveal { opacity: 0; transition: opacity 0.45s ease; }
svg:hover .gfx-reveal { opacity: 1; }

.gfx-curve { transition: stroke-width 0.3s ease; }
svg:hover .gfx-curve { stroke-width: 2.4px !important; }

.gfx-area {
  fill: color-mix(in srgb, var(--olive-9) 5%, transparent);
  stroke: none;
  transition: fill 0.45s ease;
}
svg:hover .gfx-area { fill: color-mix(in srgb, var(--olive-9) 10%, transparent); }

.gfx-alt { opacity: 0.55; transition: opacity 0.4s ease; }
svg:hover .gfx-alt { opacity: 0.9; }

.gfx-pulse { opacity: 0; transform-box: fill-box; transform-origin: center; }

.gfx-win { fill: transparent; transition: fill 0.35s ease; }
svg:hover .gfx-win { fill: color-mix(in srgb, var(--olive-9) 22%, transparent); }

.gfx-slice { fill: transparent; stroke: none; transition: fill 0.3s ease; }
.gfx-slice-a { fill: color-mix(in srgb, var(--olive-9) 16%, transparent); }
.gfx-slice:hover { fill: color-mix(in srgb, var(--olive-9) 32%, transparent); }

@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }

  svg:hover .gfx-pulse { animation: tighina-ringgrow 2.4s ease-out infinite; }

  .gfx-coin { transition: transform 1.1s cubic-bezier(0.45, 0.05, 0.35, 1); }
  svg:hover .gfx-coin { transform: translateX(80px); }

  /* Balance beam — the beam tilts, the pans counter-rotate to hang plumb,
     and the extra coin settles with a slight delay. */
  .gfx-beam { transform-origin: 150px 52px; transition: transform 0.9s cubic-bezier(0.34, 1.2, 0.64, 1); }
  svg:hover .gfx-beam { transform: rotate(-3.5deg); }

  .gfx-hangl { transform-origin: 62px 52px; transition: transform 0.9s cubic-bezier(0.34, 1.2, 0.64, 1); }
  .gfx-hangr { transform-origin: 238px 52px; transition: transform 0.9s cubic-bezier(0.34, 1.2, 0.64, 1); }
  svg:hover .gfx-hangl,
  svg:hover .gfx-hangr { transform: rotate(3.5deg); }

  .gfx-coin3 { transition: transform 0.6s cubic-bezier(0.34, 1.56, 0.64, 1) 0.3s; }
  svg:hover .gfx-coin3 { transform: translateY(-2.5px); }
}

/* № 04 — Investment lifecycle ecosystem.
   A full-width diagram of seven stages on a running path: particles flow
   left → right and nodes pulse and ripple over a faint background grid, with
   the stage description revealed on hover. The continuous motion is gated two
   ways: it only runs once the graphic scrolls into view (JS adds .running)
   and only under prefers-reduced-motion: no-preference (the keyframes live in
   the motion block below, so under reduced motion the diagram renders
   static). Without JS there is no .js class, the pause rule below never
   applies, and it animates on load instead. */

.eco {
  display: block;
  width: 100%;
  min-width: 0;
  max-width: 100%;
  height: auto;
  fill: none;
  stroke: var(--olive-9);
  stroke-width: 1.25;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.eco-wrap { display: flex; flex-direction: column; gap: 18px; min-width: 0; }

/* Two renderings of the same diagram: the wide serpentine (.eco--h) and a
   vertical variant (.eco--v) swapped in below 640px, where the horizontal
   layout scales the labels into illegibility. */
.eco--v { display: none; }

.eco-head { display: flex; align-items: center; gap: 16px; }

.eco-head-label {
  margin: 0;
  font-family: var(--sans);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--sand-10);
  white-space: nowrap;
}

.eco-head-rule { flex: 1; height: 1px; background: var(--sand-6); }

.eco-part { opacity: 0; }

.eco-num { font-family: var(--serif); font-size: 14px; fill: var(--olive-9); stroke: none; }

.eco-name {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.09em;
  fill: var(--sand-11);
  stroke: none;
  transition: fill 0.3s ease;
}

.eco-desc {
  font-family: var(--sans);
  font-size: 10.5px;
  fill: var(--sand-10);
  stroke: none;
  opacity: 0;
  transform: translateY(-3px);
  transition: opacity 0.35s ease, transform 0.35s cubic-bezier(0.16, 1, 0.3, 1);
}

.eco-stage { cursor: default; }
.eco-stage:hover .eco-desc { opacity: 1; transform: none; }
.eco-stage:hover .eco-name { fill: var(--sand-12); }
.eco-stage:hover .eco-node { stroke-width: 2; }

/* Hold the diagram still until it scrolls into view — only when JS is running. */
body.js .eco:not(.running) * { animation-play-state: paused !important; }

.content--gfx {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 280px;
  gap: 64px;
  align-items: center;
}

/* № 01 — Hero */

.row--hero .content {
  padding: 100px 64px 108px 48px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: 56px;
  align-items: center;
}

h1 {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(38px, 4.6vw, 58px);
  line-height: 1.18;
  margin: 0;
  max-width: 820px;
  text-wrap: pretty;
}

.lede {
  font-size: 16.5px;
  line-height: 1.65;
  color: var(--sand-11);
  max-width: 560px;
  margin: 36px 0 0;
}

.hero-aud {
  font-size: 14px;
  line-height: 1.7;
  color: var(--sand-10);
  max-width: 560px;
  margin: 26px 0 0;
}

.hero-aud-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--sand-10);
  margin-right: 6px;
}

.row--hero .next-link { margin-top: 30px; }

/* Hairline card grids — 1px gaps over a sand-6 backdrop, so the seams read
   as hairline rules. 2×2 by default (№ 05 audiences); .cards--three lays the
   № 03 capability cards in a single row of three. */

.content--what { display: flex; flex-direction: column; gap: 40px; }

.cards {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1px;
  background: var(--sand-6);
  border: 1px solid var(--sand-6);
}

.cards--three { grid-template-columns: 1fr 1fr 1fr; }

.support--intro { margin: 0; max-width: 640px; }

.card {
  background: var(--sand-2);
  padding: 36px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.card-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 16px;
}

.card-head .gfx { flex: none; }

.card h3 {
  margin: 0;
  font-family: var(--serif);
  font-weight: 400;
  font-size: 26px;
}

.card p {
  font-size: 15px;
  line-height: 1.65;
  color: var(--sand-11);
  margin: 0;
}

.card-facts {
  margin: auto 0 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  font-size: 14px;
}

.card-facts > div {
  display: flex;
  gap: 12px;
  justify-content: space-between;
  border-top: 1px solid var(--sand-6);
  padding-top: 8px;
}

.card-facts dt {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--sand-10);
}

.card-facts dd { margin: 0; }

/* № 02 Capital management · № 06 Why Tighina — statement + graphic layouts */

.content--invest { display: flex; flex-direction: column; gap: 48px; }

/* № 02 — Capital-allocation framework grid */

.framework {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  background: var(--sand-6);
  border: 1px solid var(--sand-6);
}

.framework > div {
  background: var(--sand-2);
  padding: 24px 26px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.framework h3 {
  margin: 0;
  font-family: var(--sans);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--sand-11);
}

.framework p {
  margin: 0;
  font-size: 14px;
  line-height: 1.65;
  color: var(--sand-11);
}

/* № 06 — Differentiation pillars */

.pillars {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 56px;
  max-width: 980px;
}

.pillar {
  border-top: 1px solid var(--sand-6);
  padding: 26px 0 30px;
}

.pillar h3 {
  margin: 0 0 10px;
  font-family: var(--serif);
  font-weight: 400;
  font-size: 21px;
}

.pillar p {
  margin: 0;
  font-size: 14.5px;
  line-height: 1.7;
  color: var(--sand-11);
}

.pullquote {
  margin: 0;
  padding: 36px 0;
  border-top: 1px solid var(--sand-12);
  border-bottom: 1px solid var(--sand-12);
}

.pullquote blockquote {
  margin: 0;
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(28px, 3.4vw, 42px);
  line-height: 1.25;
  color: var(--sand-12);
  text-wrap: pretty;
}

/* Serif statements */

.statement {
  font-family: var(--serif);
  margin: 0;
  text-wrap: pretty;
}

.statement--invest {
  font-size: clamp(24px, 2.6vw, 31px);
  line-height: 1.45;
  max-width: 760px;
}

.statement--firm {
  font-size: clamp(22px, 2.4vw, 28px);
  line-height: 1.5;
  max-width: 760px;
}

.statement--contact {
  font-size: clamp(26px, 2.8vw, 34px);
  line-height: 1.35;
  max-width: 680px;
}

.support {
  font-size: 15px;
  line-height: 1.65;
  color: var(--sand-11);
  margin: 28px 0 0;
  max-width: 560px;
}

/* № 04 — Investment approach: statement, full-width lifecycle diagram, then
   the process expanded via progressive disclosure. */

.content--firm { display: flex; flex-direction: column; gap: 52px; }

.process {
  max-width: 900px;
  border-top: 1px solid var(--sand-6);
  border-bottom: 1px solid var(--sand-6);
}

.process summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 24px;
  padding: 22px 0;
  font-family: var(--serif);
  font-size: 20px;
  color: var(--sand-12);
}

.process summary::-webkit-details-marker { display: none; }

.process summary::after {
  content: "+";
  font-family: var(--serif);
  font-size: 22px;
  color: var(--olive-9);
  line-height: 1;
}

.process[open] summary::after { content: "−"; }

.process summary:hover { color: var(--olive-11); }

.process summary:focus-visible {
  outline: 2px solid var(--olive-9);
  outline-offset: 3px;
  border-radius: 1px;
}

.process-list {
  margin: 0 0 28px;
  padding: 0 0 0 22px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px 48px;
}

.process-list li {
  font-size: 14.5px;
  line-height: 1.7;
  color: var(--sand-11);
}

.process-list strong { font-weight: 600; color: var(--sand-12); }

/* № 07 — The founder */

.content--founder { max-width: 800px; }

.founder-bio {
  display: flex;
  flex-direction: column;
  gap: 22px;
  max-width: 640px;
}

.founder-bio h3 {
  margin: 0;
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(26px, 2.8vw, 32px);
}

.founder-bio .bio {
  margin: 0;
  font-size: 15.5px;
  line-height: 1.75;
  color: var(--sand-11);
}

.founder-credo {
  margin: 0;
  font-family: var(--serif);
  font-size: 20px;
  line-height: 1.55;
  color: var(--sand-12);
  text-wrap: pretty;
}

/* № 08 — Perspectives */

.content--persp { display: flex; flex-direction: column; gap: 40px; }

.persp-list {
  list-style: none;
  margin: 0;
  padding: 0;
  max-width: 880px;
  border-top: 1px solid var(--sand-6);
}

.persp-list li {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 24px;
  padding: 20px 0;
  border-bottom: 1px solid var(--sand-6);
}

.persp-title { font-family: var(--serif); font-size: 20px; color: var(--sand-12); }

.persp-tag {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--sand-10);
  white-space: nowrap;
}

.content--persp .support { margin: 0; }

/* № 09 — Contact */

.content--contact {
  padding-bottom: 88px;
  display: flex;
  flex-direction: column;
  gap: 40px;
}

.content--contact .support { margin: -14px 0 0; }

.entries {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 1px;
  background: var(--sand-6);
  border: 1px solid var(--sand-6);
}

.entry {
  background: var(--sand-2);
  padding: 26px 28px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  color: var(--sand-12);
  transition: background 0.25s ease;
}

.entry:hover { background: var(--sand-3); color: var(--sand-12); }

.entry-title { font-family: var(--serif); font-size: 21px; }
.entry-desc { font-size: 13.5px; color: var(--sand-11); }

.contact-direct { display: flex; flex-direction: column; gap: 16px; }

.contact-line {
  display: flex;
  gap: 48px;
  font-size: 16px;
  align-items: baseline;
  flex-wrap: wrap;
}

.contact-email {
  color: var(--sand-12);
  border-bottom: 1px solid var(--sand-9);
  padding-bottom: 2px;
}

.contact-email:hover { color: var(--olive-11); }

.contact-phone { color: var(--sand-11); }
.contact-phone:hover { color: var(--olive-11); }

.contact-place {
  color: var(--sand-10);
  font-size: 14px;
}

.contact-note {
  font-size: 13px;
  color: var(--sand-10);
  margin: 0;
}

/* Footer — firm description, navigation, contact, then the general
   disclosure and the copyright bar. */

.site-footer {
  display: flex;
  flex-direction: column;
  gap: 32px;
  padding: 52px 64px 32px;
  font-size: 13px;
  color: var(--sand-10);
  margin-top: auto;
}

.footer-main {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) auto auto;
  gap: 56px;
  align-items: start;
}

.footer-brand {
  display: flex;
  flex-direction: column;
  gap: 14px;
  max-width: 480px;
}

.footer-wordmark {
  display: block;
  height: 22px;
  width: auto;
  align-self: flex-start;
}

.footer-desc { margin: 0; line-height: 1.7; }

.footer-nav { display: flex; flex-direction: column; gap: 10px; }
.footer-nav a { color: var(--sand-11); }
.footer-nav a:hover { color: var(--olive-11); }

.footer-reach { display: flex; flex-direction: column; gap: 10px; }
.footer-reach a { color: var(--sand-11); }
.footer-reach a:hover { color: var(--olive-11); }

.footer-disclosure {
  margin: 0;
  max-width: 920px;
  font-size: 12px;
  line-height: 1.75;
  border-top: 1px solid var(--sand-6);
  padding-top: 24px;
}

.footer-bar {
  border-top: 1px solid var(--sand-6);
  padding-top: 20px;
  font-size: 12.5px;
}

/* Motion — the page's motion budget, in three layers:
   1. A load-in on the hero only: headline, № marker, then the lede.
      (Sections below the fold reveal on scroll instead of load.)
   2. Scroll-triggered reveals: content blocks fade/slide up as they enter view.
   3. The № 04 lifecycle ecosystem: looping particle flow and node
      pulses/ripples, running only once scrolled into view.
   Everything is gated on prefers-reduced-motion: no-preference, so under
   reduced-motion nothing animates and every element renders in its final
   state (no `both` fill-mode or opacity:0 leaking a hidden start state). */

@media (prefers-reduced-motion: no-preference) {
  @keyframes tighina-rise {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
  }

  @keyframes tighina-draw {
    from { stroke-dashoffset: 1; }
    to   { stroke-dashoffset: 0; }
  }

  /* № 04 ecosystem: a marker travelling an offset-path, node pulses and
     ripples. tighina-ringgrow doubles as the hero endpoint's hover pulse. */
  @keyframes tighina-flow {
    0%   { offset-distance: 0%;   opacity: 0; }
    5%   { opacity: 1; }
    95%  { opacity: 1; }
    100% { offset-distance: 100%; opacity: 0; }
  }

  @keyframes tighina-pulse {
    0%   { transform: scale(1);   opacity: 0.5; }
    75%  { transform: scale(2.1); opacity: 0; }
    100% { transform: scale(2.1); opacity: 0; }
  }

  @keyframes tighina-ringgrow {
    0%   { transform: scale(0.35); opacity: 0.55; }
    100% { transform: scale(2.5);  opacity: 0; }
  }

  .row--hero h1,
  .row--hero .num,
  .lede {
    animation: tighina-rise 400ms cubic-bezier(0.16, 1, 0.3, 1) both;
  }

  .row--hero h1 { animation-delay: 0ms; }
  .row--hero .num { animation-delay: 70ms; }
  .lede { animation-delay: 120ms; }

  /* № 04 ecosystem — continuous motion (paused until in view via the .running
     gate above) plus the one-shot draw-in / fade-in of the diagram itself. */
  .eco-part {
    offset-rotate: 0deg;
    animation: tighina-flow 16s linear infinite;
    filter: drop-shadow(0 0 3px color-mix(in srgb, var(--olive-9) 45%, transparent));
  }
  .eco-part.p2 { animation-delay: 4s; }
  .eco-part.p3 { animation-delay: 8s; }
  .eco-part.p4 { animation-delay: 12s; }

  .eco-pulse {
    transform-box: fill-box;
    transform-origin: center;
    animation: tighina-pulse 4.6s cubic-bezier(0.25, 0.6, 0.4, 1) infinite;
  }

  .eco-ring {
    transform-box: fill-box;
    transform-origin: center;
    animation: tighina-ringgrow 5.6s linear infinite;
  }

  .eco-drawline { stroke-dasharray: 1; animation: tighina-draw 1800ms cubic-bezier(0.16, 1, 0.3, 1) both; }
  .eco-fade { animation: tighina-rise 800ms cubic-bezier(0.16, 1, 0.3, 1) both; }

  /* Scroll reveals — content fades/slides in as it enters the viewport.
     Gated on body.js so that without JS everything is simply visible. */
  body.js .reveal {
    opacity: 0;
    transform: translateY(14px);
    transition: opacity 0.9s cubic-bezier(0.16, 1, 0.3, 1),
                transform 0.9s cubic-bezier(0.16, 1, 0.3, 1);
  }
  body.js .reveal.in-view { opacity: 1; transform: none; }
}

/* Responsive — the design is desktop-first; collapse the rail below 900px */

@media (max-width: 1120px) {
  .row--hero .content { grid-template-columns: minmax(0, 1fr) 240px; gap: 40px; }
  .content--gfx { grid-template-columns: minmax(0, 1fr) 210px; gap: 40px; }
}

@media (max-width: 900px) {
  .site-header { padding: 28px 28px; }

  .row { grid-template-columns: minmax(0, 1fr); }

  .rail {
    padding: 40px 28px 0;
    flex-direction: row;
    align-items: baseline;
    gap: 14px;
  }

  .content,
  .row--hero .content { padding: 24px 28px 52px; }

  .row--hero .content { grid-template-columns: minmax(0, 1fr); gap: 36px; }
  .hero-gfx { justify-self: start; width: 240px; height: 184px; }

  .cards,
  .cards--three { grid-template-columns: 1fr; }

  .framework { grid-template-columns: 1fr; }

  .pillars { grid-template-columns: 1fr; }

  .process-list { grid-template-columns: 1fr; }

  .content--gfx { grid-template-columns: minmax(0, 1fr); gap: 36px; }
  .content--gfx .gfx { justify-self: start; }

  .entries { grid-template-columns: 1fr; }

  .contact-line { gap: 20px 32px; }

  /* Too small to read at this scale, and hover is unreliable on touch. */
  .eco .eco-desc { display: none; }

  .site-footer { padding: 36px 28px 24px; gap: 24px; }

  .footer-main { grid-template-columns: 1fr; gap: 28px; }
}

@media (max-width: 640px) {
  .tagline { display: none; }

  /* Swap the lifecycle diagram to its vertical rendering. Descriptions come
     back (there is room beside each node) and stay visible — hover is
     unreliable on touch. Type sizes are bumped to offset the narrower
     viewBox-to-pixel scale. */
  .eco--h { display: none; }
  .eco--v { display: block; }
  .eco--v .eco-desc {
    display: block;
    opacity: 1;
    transform: none;
    font-size: 12px;
  }
  .eco--v .eco-name { font-size: 12.5px; }
  .eco--v .eco-num { font-size: 15px; }
}

@media (max-width: 480px) {
  .site-header {
    flex-direction: column;
    gap: 6px;
    align-items: flex-start;
  }
}
