/* ============================================================
   Client Factory — design system
   Dark, typographic, motion where it earns its keep.
   Colour in oklch. Progressive enhancement throughout:
   scroll-driven animation and view transitions upgrade,
   never gate. Heavy effects are desktop-only by design.
   ============================================================ */

/* ---------- tokens ---------- */
:root {
  --ink:            oklch(11% 0.012 265);
  --ink-2:          oklch(15% 0.014 265);
  --ink-3:          oklch(19% 0.016 265);
  --line:           oklch(28% 0.014 265);
  --line-soft:      oklch(22% 0.012 265);
  --paper:          oklch(96% 0.006 90);
  --paper-2:        oklch(91% 0.008 90);
  --text:           oklch(93% 0.008 90);
  --text-dim:       oklch(72% 0.010 90);
  --text-faint:     oklch(56% 0.012 265);

  /* Surfaces are translucent so the backdrop glows faintly through them —
     that is what stops a page of dark cards reading as flat black rectangles.
     One light surface per row is the polarity break the eye lands on first. */
  --surface:        oklch(16% 0.013 265 / 0.74);
  --surface-2:      oklch(20% 0.015 265 / 0.78);
  --surface-lt:     oklch(93% 0.004 90);
  --surface-lt-ink: oklch(16% 0.012 265);

  --accent:         oklch(63% 0.166 42);      /* terracotta */
  --accent-hot:     oklch(70% 0.185 45);
  --accent-deep:    oklch(48% 0.140 40);
  --wa:             oklch(72% 0.190 152);     /* WhatsApp green — CTA only */
  --wa-deep:        oklch(58% 0.160 152);

  /* One variable face carries display and body. Monospace is a system stack:
     the labels it sets are 11px and nobody can tell Consolas from JetBrains at
     that size, which is not worth a second network request. */
  --display: Manrope, "Manrope fallback", system-ui, -apple-system, "Segoe UI", sans-serif;
  --body: Manrope, "Manrope fallback", system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: ui-monospace, "SF Mono", "JetBrains Mono", Consolas, "Liberation Mono", Menlo, monospace;

  /* Container measure taken from the reference: 1366px with 78 / 55 / 39
     side padding. Wider than the old 82rem and it reads calmer, because the
     backdrop gets to breathe on both sides of the column. */
  --gut: 39px;
  --max: 1366px;
  --rad: 18px;
  --rad-panel: 30px;

  /* easing — same curves used everywhere so motion feels like one hand */
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --dur: 620ms;

  --shadow: 0 1px 0 oklch(100% 0 0 / 0.05) inset, 0 18px 50px -20px oklch(0% 0 0 / 0.7);
}

/* Side padding steps at the reference's breakpoints. */
@media (min-width: 26.5625rem) { :root { --gut: 55px; } }
@media (min-width: 64rem)      { :root { --gut: 78px; } }

/* ---------- the typeface ----------
   Self-hosted, one file, the whole 200–800 weight axis. Three Google-hosted
   faces used to load here with display:swap; that swap was the entire measured
   CLS on a throttled phone (0.13, all of it one font event moving the hero and
   everything under it). Same origin plus a preload removes the connection setup
   and the render-blocking stylesheet; the fallback below removes what is left.

   Licence: SIL Open Font License 1.1, shipped alongside as OFL.txt. */
@font-face {
  font-family: Manrope;
  src: url("/assets/fonts/manrope-var-latin.woff2") format("woff2-variations"),
       url("/assets/fonts/manrope-var-latin.woff2") format("woff2");
  font-weight: 200 800;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
                 U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Metric-matched stand-in so the swap moves nothing. Ratios measured in a
   browser against the actual file — Manrope advance and font bounding box
   versus Arial at the same size — not guessed from a table.
   local() misses on platforms without the named face (Android has no Arial);
   there the stack simply falls through as it did before. */
@font-face {
  font-family: "Manrope fallback";
  src: local("Arial"), local("Helvetica"), local("Roboto"), local("Liberation Sans");
  size-adjust: 91.2%; ascent-override: 97.6%; descent-override: 24.1%; line-gap-override: 0%;
}

/* animatable custom props for gradient motion */
@property --spin { syntax: "<angle>"; inherits: false; initial-value: 0deg; }
@property --glow { syntax: "<percentage>"; inherits: false; initial-value: 0%; }

/* ---------- reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  color-scheme: dark;
}
body {
  background: var(--ink);
  color: var(--text);
  font-family: var(--body);
  font-size: clamp(1rem, 0.96rem + 0.2vw, 1.0625rem);
  line-height: 1.62;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* ---------- the backdrop ----------
   One fixed layer behind everything. It does not scroll, so the page reads as
   a single continuous object instead of a stack of bands, and it is painted
   once rather than per frame.

   Geometry is the reference's: fixed, inset -10%, 120% square, blurred, with a
   darkening overlay on top. The mesh itself is near-black through the middle
   and glows only at the edges — that is why the content column stays readable
   without a scrim of its own.

   The colour is ours, not the reference's magenta and blue: terracotta is on
   every button and link on this site already, and two accent families fighting
   would be worse than either alone. One cool counterpoint keeps it from
   reading as a single wash.

   No canvas. The reference animates this on a second WebGL context; this site
   spends its GPU budget on the spiral in the home hero, and two contexts on a
   mid-range Android is a regression nobody asked for. */
.bg {
  position: fixed;
  top: -10%; left: -10%;
  width: 120%; height: 120%;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(44% 52% at -4% 18%, oklch(64% 0.190 42), transparent 62%),
    radial-gradient(38% 46% at -6% 72%, oklch(56% 0.175 22), transparent 64%),
    radial-gradient(46% 54% at 104% 26%, oklch(50% 0.180 295), transparent 62%),
    radial-gradient(40% 46% at 102% 78%, oklch(54% 0.185 340), transparent 64%),
    radial-gradient(50% 42% at 50% 48%, oklch(10% 0.012 265) 24%, transparent 74%),
    var(--ink);
  filter: blur(70px);
}
/* The darkening pass: opaque at the bottom of the viewport, letting more
   colour through at the top. Same arrangement the reference uses. */
.bg::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(0deg, oklch(11% 0.012 265 / 0.80), oklch(11% 0.012 265 / 0.18));
}
/* Everything that is not the backdrop sits above it. */
.hdr, main, .ftr, .sticky, .menu, .drawer, .skip { position: relative; z-index: 1; }

/* On a phone the blur radius is the expensive part and the mesh is mostly
   off-screen anyway. Smaller blur, same picture. */
@media (max-width: 60rem) {
  .bg { filter: blur(40px); }
}
img, svg, video { display: block; max-width: 100%; height: auto; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
:focus-visible { outline: 2px solid var(--accent-hot); outline-offset: 3px; border-radius: 3px; }
::selection { background: var(--accent); color: oklch(14% 0.01 40); }

/* ---------- type ---------- */
/* Weight falls as size rises. This is the single biggest reason the old page
   read cheap: it set 8.5rem headlines at weight 700, which is a shout. The
   reference sets its hero around a regular weight and lets the size do the
   work. Manrope is variable, so these are real weights, not synthesised. */
h1, h2, h3, h4 {
  font-family: var(--display);
  font-weight: 500;
  line-height: 0.98;
  letter-spacing: -0.025em;
  text-wrap: balance;
}
/* Large display sizes need more leading than small ones: at 8.5rem a
   0.95 line-height collides ascenders with the line above (the "ffi"
   in "Traffic" was overlapping). Scale leading up with size. */
.h-xl { font-size: clamp(2.85rem, 1.4rem + 7.4vw, 7.5rem); line-height: 1.04; font-weight: 300; letter-spacing: -0.038em; }
.h-lg { font-size: clamp(2.3rem, 1.3rem + 4.4vw, 4.75rem);  line-height: 1.04; font-weight: 350; letter-spacing: -0.032em; }
.h-md { font-size: clamp(1.75rem, 1.25rem + 2.1vw, 3rem);   line-height: 1.08; font-weight: 450; letter-spacing: -0.026em; }
.h-sm { font-size: clamp(1.3rem, 1.1rem + 0.9vw, 1.85rem);  line-height: 1.14; font-weight: 550; letter-spacing: -0.018em; }
p { text-wrap: pretty; }
.lead {
  font-size: clamp(1.075rem, 1rem + 0.55vw, 1.4rem);
  line-height: 1.5;
  color: var(--text-dim);
  max-width: 46ch;
}
.label {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.label--accent { color: var(--accent); }
.dim { color: var(--text-dim); }
.faint { color: var(--text-faint); }
.acc { color: var(--accent); }
.mono { font-family: var(--mono); font-size: 0.8125em; letter-spacing: 0.02em; }
/* Bold inherits its colour. Painting every <b> in the paper colour was fine
   while every surface was dark; the moment one card in a row goes light, it
   turns bold text almost invisible. Weight is enough emphasis. */
strong, b { font-weight: 700; color: inherit; }

/* ---------- layout ---------- */
.wrap { width: 100%; max-width: var(--max); margin-inline: auto; padding-inline: var(--gut); }
.sec { padding-block: clamp(3.25rem, 6vw, 7rem); position: relative; }
.sec--tight { padding-block: clamp(2.25rem, 4vw, 4rem); }
.rule { height: 1px; background: var(--line-soft); border: 0; }
.grid { display: grid; gap: clamp(1rem, 2vw, 1.75rem); }
.g2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr)); }
.g3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr)); }
.g4 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr)); }
.split { display: grid; gap: clamp(1.5rem, 4vw, 4rem); align-items: start; }
@media (min-width: 62rem) { .split { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }
.sec-head { display: grid; gap: 1rem; margin-bottom: clamp(2rem, 4vw, 3.5rem); max-width: 62ch; }

/* ---------- buttons ---------- */
.btn {
  --bg: var(--paper);
  --fg: var(--ink);
  display: inline-flex; align-items: center; gap: 0.6em;
  padding: 0.95em 1.55em;
  background: var(--bg); color: var(--fg);
  border-radius: 100px;
  font-weight: 600; font-size: 0.9375rem;
  letter-spacing: -0.01em;
  border: 1px solid transparent;
  transition: transform 240ms var(--ease), background-color 240ms var(--ease), box-shadow 240ms var(--ease);
  will-change: transform;
}
.btn:hover { transform: translateY(-2px); box-shadow: 0 10px 30px -12px oklch(0% 0 0 / 0.8); }
.btn:active { transform: translateY(0); }
.btn--wa { --bg: var(--wa); --fg: oklch(18% 0.04 152); }
.btn--wa:hover { --bg: oklch(76% 0.195 152); }
.btn--accent { --bg: var(--accent); --fg: oklch(16% 0.03 40); }
.btn--accent:hover { --bg: var(--accent-hot); }
.btn--ghost {
  --bg: transparent; --fg: var(--text);
  border-color: var(--line);
}
.btn--ghost:hover { --bg: oklch(100% 0 0 / 0.05); border-color: var(--text-faint); }
.btn--sm { padding: 0.7em 1.15em; font-size: 0.875rem; }
.btn svg { width: 1.05em; height: 1.05em; flex: none; }
.btns { display: flex; flex-wrap: wrap; gap: 0.7rem; align-items: center; }

.tlink {
  display: inline-flex; align-items: center; gap: 0.45em;
  font-weight: 600; color: var(--accent);
  border-bottom: 1px solid oklch(63% 0.166 42 / 0.35);
  padding-bottom: 1px;
  transition: border-color 200ms, gap 200ms var(--ease);
}
.tlink:hover { border-color: var(--accent); gap: 0.75em; }

/* ---------- header ---------- */
/* Transparent at the top of the page so the backdrop reads edge to edge, then
   it earns a surface once you have scrolled past the hero. The reference goes
   further and collapses the whole nav into one control on scroll — the links
   are still reachable, they just stop competing with the page. */
.hdr {
  position: sticky; top: 0; z-index: 60;
  background: transparent;
  border-bottom: 1px solid transparent;
  transition: border-color 300ms, background-color 300ms, backdrop-filter 300ms;
}
.hdr[data-stuck="1"] {
  background: oklch(11% 0.012 265 / 0.68);
  backdrop-filter: blur(18px) saturate(1.4);
  border-bottom-color: oklch(100% 0 0 / 0.06);
}
@media (min-width: 60rem) {
  .hdr[data-stuck="1"] .nav { opacity: 0; pointer-events: none; transform: translateY(-4px); }
  .hdr .nav { transition: opacity 260ms var(--ease), transform 260ms var(--ease); }
  .hdr[data-stuck="1"] .burger { display: grid; }
}
.hdr__in {
  display: flex; align-items: center; gap: 1.25rem;
  height: 68px;
  width: 100%; max-width: var(--max); margin-inline: auto;
  padding-inline: var(--gut);
}
.brand { display: inline-flex; align-items: center; gap: 0.6rem; font-family: var(--display); font-weight: 700; letter-spacing: -0.04em; font-size: 1.0625rem; }
.brand svg { width: 26px; height: 26px; flex: none; }
.nav { display: none; margin-left: auto; gap: 0.25rem; align-items: center; }
@media (min-width: 60rem) { .nav { display: flex; } }
.nav a {
  padding: 0.5rem 0.8rem; border-radius: 100px;
  font-size: 0.9375rem; font-weight: 500; color: var(--text-dim);
  transition: color 200ms, background-color 200ms;
}
.nav a:hover, .nav a[aria-current] { color: var(--paper); background: oklch(100% 0 0 / 0.06); }
.hdr__cta { margin-left: auto; display: flex; gap: 0.5rem; align-items: center; }
@media (min-width: 60rem) { .hdr__cta { margin-left: 0; } }
.burger { display: grid; place-items: center; width: 40px; height: 40px; border: 1px solid var(--line); border-radius: 10px; }
@media (min-width: 60rem) { .burger { display: none; } }
.burger svg { width: 18px; height: 18px; }

/* mobile menu — native popover, no JS state */
.menu {
  position: fixed; inset: 0; width: 100%; max-width: none; height: 100%;
  margin: 0; padding: 0; border: 0;
  background: var(--ink); color: var(--text);
  overflow-y: auto;
}
.menu::backdrop { background: oklch(8% 0.01 265 / 0.9); }
.menu__in { padding: 1.1rem var(--gut) 3rem; display: grid; gap: 0.15rem; }
.menu__top { display: flex; align-items: center; justify-content: space-between; height: 46px; margin-bottom: 1.25rem; }
.menu a.menu__i {
  font-family: var(--display); font-weight: 400; letter-spacing: -0.03em;
  font-size: 1.65rem; padding: 0.55rem 0;
  border-bottom: 1px solid var(--line-soft);
}
.menu__sub { display: grid; gap: 0.1rem; padding: 1.25rem 0 0; }
.menu__sub a { color: var(--text-dim); font-size: 0.9375rem; padding: 0.35rem 0; }

/* ---------- hero ---------- */
.hero { position: relative; padding-block: clamp(3.5rem, 8vw, 7rem) clamp(3rem, 6vw, 6rem); }
.hero__grid { position: relative; z-index: 2; display: grid; gap: clamp(2rem, 5vw, 4rem); align-items: center; }
.hero h1 { margin-bottom: 1.5rem; max-width: 15ch; }
.hero__sub { max-width: 44ch; margin-bottom: 2rem; }

/* The spiral gets its own column on a wide screen and disappears below it —
   on a phone the headline should own the first screen, not share it. */
.hero__gl { display: none; }
@media (min-width: 60rem) {
  .hero__grid { grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr); }
  .hero__gl { display: block; position: relative; aspect-ratio: 1; max-height: 32rem; justify-self: center; width: 100%; }
}
.hero__gl canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: none; }
html.motion .hero__gl canvas { display: block; }
/* The flat mark holds the same box until — or unless — the canvas takes over,
   so nothing reflows when the capability gate says yes. */
.hero__mark { position: absolute; inset: 12%; display: grid; place-items: center; color: var(--accent); opacity: 0.5; }
.hero__mark svg { width: 100%; height: 100%; }
html.motion .hero__mark { display: none; }

/* Superseded by the site-wide backdrop: two blurred gradient fields stacked on
   one another read as mud, and the hero no longer needs its own. Kept as a
   no-op so no template has to be edited to stop using it. */
.field, #fx { display: none; }
.field-unused {
  position: absolute; inset: -10% -5% auto -5%; height: 130%;
  z-index: 0; pointer-events: none;
  opacity: 0.55;
  background:
    radial-gradient(58% 44% at 74% 18%, oklch(63% 0.166 42 / 0.30), transparent 68%),
    radial-gradient(46% 40% at 22% 8%, oklch(48% 0.14 265 / 0.24), transparent 70%);
  filter: blur(30px);
}
.field::after {
  content: ""; position: absolute; inset: 0;
  background-image:
    linear-gradient(to right, oklch(100% 0 0 / 0.045) 1px, transparent 1px),
    linear-gradient(to bottom, oklch(100% 0 0 / 0.045) 1px, transparent 1px);
  background-size: 74px 74px;
  mask-image: radial-gradient(70% 55% at 60% 35%, #000 20%, transparent 78%);
  filter: blur(0.2px);
}
#fx { position: absolute; inset: 0; z-index: 1; width: 100%; height: 100%; opacity: 0.5; pointer-events: none; }

/* ---------- stat strip ---------- */
.stats { display: grid; gap: 1px; background: oklch(100% 0 0 / 0.06); border: 1px solid oklch(100% 0 0 / 0.055); border-radius: var(--rad-panel); overflow: hidden; grid-template-columns: repeat(2, 1fr); }
@media (min-width: 48rem) { .stats { grid-template-columns: repeat(4, 1fr); } }
.stat { background: var(--surface); backdrop-filter: blur(14px); padding: clamp(1.3rem, 2.4vw, 2rem) clamp(1.1rem, 2vw, 1.7rem); }
.stat__v { font-family: var(--display); font-size: clamp(1.6rem, 1.1rem + 1.8vw, 2.6rem); font-weight: 350; letter-spacing: -0.035em; line-height: 1; margin-bottom: 0.4rem; }
.stat__l { font-size: 0.8125rem; color: var(--text-faint); line-height: 1.35; }

/* ---------- cards ---------- */
.card {
  position: relative;
  background: var(--surface);
  backdrop-filter: blur(14px);
  border: 1px solid oklch(100% 0 0 / 0.055);
  border-radius: var(--rad-panel);
  padding: clamp(1.5rem, 2.4vw, 2rem);
  display: grid;
  gap: 0.85rem;
  align-content: start;
  transition: border-color 280ms var(--ease), transform 280ms var(--ease), background-color 280ms;
}
a.card:hover, .card--hov:hover { border-color: oklch(100% 0 0 / 0.14); transform: translateY(-3px); background: var(--surface-2); }

/* The polarity break: exactly one light surface in a row of dark ones. Applied
   to a card, a work tile or a panel — whatever the row is made of.
   The compound selectors are load-bearing: .work and .tier set their own
   background further down the file, and at equal specificity the later rule
   wins, so a bare .lt silently did nothing on exactly the tiles it was for. */
.lt, .card.lt, .work.lt, .tier.lt, .panel.lt, .logo-t.lt {
  background: var(--surface-lt);
  color: var(--surface-lt-ink);
  border-color: transparent;
}
.lt h2, .lt h3, .lt h4 { color: var(--surface-lt-ink); }
.lt p, .lt li, .lt .dim { color: oklch(38% 0.012 265); }
.lt .label, .lt .faint, .lt .work__m { color: oklch(48% 0.012 265); }
.lt .acc, .lt .label--accent, .lt .card__n { color: oklch(48% 0.150 40); }
.lt .ticks li::before { background: oklch(52% 0.150 40); }
a.lt:hover, .lt.card--hov:hover { background: oklch(97% 0.004 90); border-color: transparent; }
.work.lt .work__img { background: oklch(88% 0.006 90); }
.work.lt .work__m i { background: oklch(52% 0.150 40); }
.card__n { font-family: var(--mono); font-size: 0.6875rem; color: var(--accent); letter-spacing: 0.16em; }
.card h3 { font-size: 1.25rem; line-height: 1.12; }
.card p { color: var(--text-dim); font-size: 0.9375rem; }
.card__price { font-family: var(--mono); font-size: 0.8125rem; color: var(--paper-2); margin-top: auto; padding-top: 0.35rem; }

/* spotlight follows cursor — desktop pointer only */
@media (hover: hover) and (min-width: 60rem) {
  .card--spot::before {
    content: ""; position: absolute; inset: 0; border-radius: inherit;
    background: radial-gradient(20rem 20rem at var(--mx, 50%) var(--my, 0%), oklch(63% 0.166 42 / 0.10), transparent 62%);
    opacity: 0; transition: opacity 320ms var(--ease); pointer-events: none;
  }
  .card--spot:hover::before { opacity: 1; }
}

/* ---------- list ---------- */
.ticks { display: grid; gap: 0.55rem; list-style: none; padding: 0; }
.ticks li { display: grid; grid-template-columns: 1.15em 1fr; gap: 0.6em; font-size: 0.9375rem; color: var(--text-dim); line-height: 1.45; }
.ticks li::before { content: ""; width: 0.72em; height: 0.72em; margin-top: 0.42em; border-radius: 2px; background: var(--accent); opacity: 0.85; }
.ticks--wa li::before { background: var(--wa); }

/* ---------- pricing ---------- */
.tiers { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr)); align-items: stretch; }
.tier {
  background: var(--surface); backdrop-filter: blur(14px);
  border: 1px solid oklch(100% 0 0 / 0.055);
  border-radius: var(--rad-panel); padding: clamp(1.5rem, 2.2vw, 2rem);
  display: grid; gap: 1rem; align-content: start;
  position: relative;
}
.tier--pop { border-color: oklch(58% 0.15 42 / 0.45); background: linear-gradient(180deg, oklch(24% 0.045 42 / 0.85), var(--surface) 58%); }
/* Package cards carry six blocks (name, price, summary, features, CTA,
   footnote). Letting the feature list absorb the slack keeps the CTAs on
   one line across cards of differing content length. */
.tier--pkg { align-content: stretch; grid-template-rows: auto auto auto 1fr auto auto; }
.tier__badge {
  position: absolute; top: -0.7rem; left: clamp(1.35rem, 2.2vw, 1.9rem);
  font-family: var(--mono); font-size: 0.625rem; letter-spacing: 0.16em; text-transform: uppercase;
  background: var(--accent); color: oklch(16% 0.03 40);
  padding: 0.32em 0.7em; border-radius: 100px; font-weight: 700;
}
.tier__name { font-family: var(--mono); font-size: 0.75rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-faint); }
.tier__p { display: flex; align-items: baseline; gap: 0.4rem; flex-wrap: wrap; }
.tier__p b { font-family: var(--display); font-size: clamp(2.1rem, 1.5rem + 1.8vw, 2.9rem); font-weight: 350; letter-spacing: -0.04em; color: var(--paper); line-height: 1; }
.tier__p s { color: var(--text-faint); font-size: 1rem; }
.tier__u { font-size: 0.8125rem; color: var(--text-faint); }
.tier__foot { font-size: 0.75rem; color: var(--text-faint); font-family: var(--mono); padding-top: 0.35rem; border-top: 1px solid var(--line-soft); }

/* ---------- work ---------- */
.works { display: grid; gap: clamp(1rem, 2vw, 1.5rem); grid-template-columns: repeat(auto-fit, minmax(min(100%, 21rem), 1fr)); }
.work { position: relative; display: block; border-radius: var(--rad-panel); overflow: hidden; border: 1px solid oklch(100% 0 0 / 0.055); background: var(--surface); backdrop-filter: blur(14px); transition: border-color 300ms, transform 300ms var(--ease); }
.work:hover { border-color: oklch(100% 0 0 / 0.14); transform: translateY(-3px); }
.work__img { aspect-ratio: 16 / 10; overflow: hidden; background: oklch(22% 0.014 265); }
.work__img img { width: 100%; height: 100%; object-fit: cover; object-position: top center; transition: transform 700ms var(--ease), filter 500ms; filter: saturate(0.92); }
.work:hover .work__img img { transform: scale(1.035); filter: saturate(1.05); }
.work__b { padding: 1.15rem 1.25rem 1.35rem; display: grid; gap: 0.45rem; }
.work__m { display: flex; gap: 0.6rem; align-items: center; font-family: var(--mono); font-size: 0.6875rem; letter-spacing: 0.1em; color: var(--text-faint); text-transform: uppercase; }
.work__m i { width: 3px; height: 3px; border-radius: 50%; background: var(--accent); display: inline-block; }
.work h3 { font-size: 1.2rem; }
.work p { font-size: 0.9rem; color: var(--text-dim); }
.work--num .work__img { display: grid; place-items: center; background: linear-gradient(145deg, oklch(20% 0.03 42), var(--ink-2)); }
.work--num .work__nums { display: flex; gap: clamp(1rem, 3vw, 2.25rem); padding: 1.5rem; flex-wrap: wrap; justify-content: center; }
.work--num .work__nums div { text-align: center; }
.work--num .work__nums b { display: block; font-family: var(--display); font-size: clamp(1.5rem, 1rem + 1.7vw, 2.2rem); letter-spacing: -0.04em; line-height: 1; color: var(--paper); }
.work--num .work__nums span { font-size: 0.6875rem; font-family: var(--mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-faint); }

/* ---------- table ---------- */
.tbl-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; border: 1px solid oklch(100% 0 0 / 0.055); border-radius: var(--rad-panel); background: var(--surface); backdrop-filter: blur(14px); }
table { width: 100%; border-collapse: collapse; font-size: 0.9rem; min-width: 34rem; }
th, td { text-align: left; padding: 0.85rem 1.1rem; border-bottom: 1px solid var(--line-soft); }
th { font-family: var(--mono); font-size: 0.6875rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--text-faint); background: oklch(100% 0 0 / 0.03); font-weight: 500; }
td { color: var(--text-dim); }
tbody tr:last-child td { border-bottom: 0; }
tbody tr:last-child td { color: var(--paper); font-weight: 600; }

/* ---------- process ---------- */
.steps { display: grid; gap: 1px; background: oklch(100% 0 0 / 0.06); border: 1px solid oklch(100% 0 0 / 0.055); border-radius: var(--rad-panel); overflow: hidden; }
@media (min-width: 48rem) { .steps { grid-template-columns: repeat(3, 1fr); } }
.step { background: var(--surface); backdrop-filter: blur(14px); padding: clamp(1.5rem, 2.2vw, 1.9rem); display: grid; gap: 0.5rem; align-content: start; }
.step__t { display: flex; justify-content: space-between; gap: 1rem; align-items: baseline; }
.step__n { font-family: var(--mono); font-size: 1.5rem; color: oklch(30% 0.04 42); font-weight: 700; letter-spacing: -0.02em; }
.step__d { font-family: var(--mono); font-size: 0.6875rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--accent); }
.step h3 { font-size: 1.1rem; }
.step p { font-size: 0.9rem; color: var(--text-dim); }

/* ---------- faq ---------- */
.faq { border-top: 1px solid oklch(100% 0 0 / 0.08); }
.faq details { border-bottom: 1px solid oklch(100% 0 0 / 0.08); }
.faq summary {
  display: flex; gap: 1rem; align-items: baseline; justify-content: space-between;
  padding: 1.15rem 0; cursor: pointer; list-style: none;
  font-family: var(--display); font-weight: 550; font-size: clamp(1.0625rem, 1rem + 0.35vw, 1.3rem);
  letter-spacing: -0.02em; line-height: 1.2;
  transition: color 200ms;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary:hover { color: var(--accent); }
.faq summary::after { content: "+"; font-family: var(--mono); font-size: 1.35rem; color: var(--accent); flex: none; transition: transform 300ms var(--ease); line-height: 1; }
.faq details[open] summary::after { transform: rotate(45deg); }
.faq__a { padding: 0 0 1.35rem; color: var(--text-dim); max-width: 68ch; font-size: 0.9375rem; }

/* ---------- prose (articles) ---------- */
.prose { max-width: 66ch; }
.prose > * + * { margin-top: 1.15rem; }
.prose h2 { font-size: clamp(1.4rem, 1.15rem + 1vw, 2rem); margin-top: 2.75rem; }
.prose ul { padding-left: 1.15rem; display: grid; gap: 0.55rem; color: var(--text-dim); }
.prose li::marker { color: var(--accent); }
.prose a { color: var(--accent); border-bottom: 1px solid oklch(63% 0.166 42 / 0.3); }
.prose a:hover { border-color: var(--accent); }
.prose .tbl-wrap { margin-top: 1.5rem; }
.srcs { margin-top: 3rem; padding-top: 1.25rem; border-top: 1px solid var(--line-soft); font-size: 0.8125rem; }
.srcs ul { list-style: none; padding: 0; display: grid; gap: 0.4rem; margin-top: 0.6rem; }

/* ---------- chips / pills ---------- */
.chips { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.chip {
  display: inline-flex; align-items: center; gap: 0.4em;
  padding: 0.4em 0.8em; border: 1px solid var(--line); border-radius: 100px;
  font-size: 0.8125rem; color: var(--text-dim);
  transition: border-color 200ms, color 200ms, background-color 200ms;
}
a.chip:hover { border-color: var(--accent); color: var(--paper); background: oklch(63% 0.166 42 / 0.08); }
.chip--mono { font-family: var(--mono); font-size: 0.6875rem; letter-spacing: 0.1em; text-transform: uppercase; }

/* ---------- marquee-free ticker: a static credibility bar ---------- */
.bar { display: flex; flex-wrap: wrap; gap: 0.5rem 1.5rem; align-items: center; font-family: var(--mono); font-size: 0.6875rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--text-faint); }
.bar span { display: inline-flex; align-items: center; gap: 0.5rem; }
.bar span::before { content: ""; width: 4px; height: 4px; background: var(--accent); border-radius: 50%; }

/* ---------- callout ---------- */
.note {
  border-left: 2px solid var(--accent);
  padding: 0.15rem 0 0.15rem 1.15rem;
  color: var(--text-dim);
  font-size: 0.9375rem;
  max-width: 64ch;
}
.panel {
  background: var(--surface); backdrop-filter: blur(14px);
  border: 1px solid oklch(100% 0 0 / 0.055);
  border-radius: var(--rad-panel); padding: clamp(1.5rem, 2.6vw, 2.4rem);
}
.panel--accent { background: linear-gradient(150deg, oklch(24% 0.05 42 / 0.9), var(--surface) 62%); border-color: oklch(55% 0.13 42 / 0.4); }

/* ---------- CTA band ---------- */
.cta {
  position: relative; overflow: clip;
  border-radius: var(--rad-panel);
  background: linear-gradient(140deg, oklch(24% 0.05 42 / 0.88), oklch(15% 0.02 265 / 0.8) 62%);
  backdrop-filter: blur(16px);
  border: 1px solid oklch(55% 0.12 42 / 0.35);
  padding: clamp(1.85rem, 5vw, 4rem);
}
.cta::before {
  content: ""; position: absolute; inset: -60% -20% auto auto; width: 60%; aspect-ratio: 1;
  background: conic-gradient(from var(--spin), oklch(63% 0.166 42 / 0.30), transparent 40%, oklch(63% 0.166 42 / 0.22) 70%, transparent);
  filter: blur(48px); opacity: 0.75; pointer-events: none;
}
@media (min-width: 60rem) and (prefers-reduced-motion: no-preference) {
  .cta::before { animation: spin 22s linear infinite; }
}
@keyframes spin { to { --spin: 360deg; } }
.cta > * { position: relative; }

/* ---------- footer ---------- */
.ftr { border-top: 1px solid oklch(100% 0 0 / 0.06); padding-block: clamp(2.5rem, 5vw, 4.5rem) 2rem; background: oklch(9.5% 0.01 265 / 0.6); backdrop-filter: blur(16px); }
.ftr__grid { display: grid; gap: clamp(1.75rem, 3vw, 2.5rem); grid-template-columns: repeat(auto-fit, minmax(min(100%, 11rem), 1fr)); }
.ftr h4 { font-family: var(--mono); font-size: 0.6875rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--text-faint); font-weight: 500; margin-bottom: 0.9rem; }
.ftr ul { list-style: none; padding: 0; display: grid; gap: 0.5rem; }
.ftr a { font-size: 0.875rem; color: var(--text-dim); transition: color 180ms; }
.ftr a:hover { color: var(--paper); }
.ftr__base { margin-top: clamp(2rem, 4vw, 3rem); padding-top: 1.35rem; border-top: 1px solid oklch(100% 0 0 / 0.06); display: flex; flex-wrap: wrap; gap: 0.75rem 1.5rem; justify-content: space-between; font-size: 0.75rem; color: var(--text-faint); }

/* ---------- persistent enquiry pill ----------
   The reference keeps one white pill bottom-right on every screen of the page;
   it is present in all nine of the screenshots taken while studying it. That is
   the whole trick — the visitor never has to go looking for how to start.
   Replaces the old full-width mobile bar, which ate a fifth of a phone screen
   and did not exist on desktop at all. */
.sticky {
  position: fixed; z-index: 55;
  right: clamp(0.85rem, 2vw, 1.75rem);
  bottom: calc(clamp(0.85rem, 2vw, 1.75rem) + env(safe-area-inset-bottom));
  display: flex; gap: 0.55rem; align-items: center;
}
.sticky .btn {
  box-shadow: 0 12px 34px -10px oklch(0% 0 0 / 0.75);
  padding: 1em 1.5em;
}
.sticky .btn--ghost {
  background: oklch(11% 0.012 265 / 0.72);
  backdrop-filter: blur(14px);
}
/* On a phone one control, not two: the secondary link is reachable from the
   menu and a second pill would cover half the width of the screen. */
@media (max-width: 40rem) { .sticky .btn--ghost { display: none; } }

/* ---------- enquiry drawer ----------
   A native <dialog>, so focus trapping, Escape and the backdrop come from the
   platform instead of from hand-written JavaScript that gets it wrong. */
.drawer {
  border: 0; padding: 0;
  width: min(100%, 30rem);
  max-width: 100%; max-height: 100%;
  margin: 0 0 0 auto; height: 100%;
  background: oklch(13% 0.013 265 / 0.94);
  backdrop-filter: blur(22px);
  color: var(--text);
  overflow-y: auto;
}
.drawer::backdrop { background: oklch(6% 0.01 265 / 0.72); backdrop-filter: blur(3px); }
.drawer__in { padding: clamp(1.5rem, 4vw, 2.5rem); display: grid; gap: 1.35rem; align-content: start; min-height: 100%; }
.drawer__top { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.drawer h2 { font-size: clamp(1.5rem, 1.2rem + 1.2vw, 2.1rem); font-weight: 400; letter-spacing: -0.03em; }
.drawer__or {
  display: flex; align-items: center; gap: 0.9rem;
  font-family: var(--mono); font-size: 0.6875rem; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--text-faint);
}
.drawer__or::before, .drawer__or::after { content: ""; height: 1px; flex: 1; background: oklch(100% 0 0 / 0.09); }
.drawer .btn { width: 100%; justify-content: center; }

.form { display: grid; gap: 0.8rem; }
.form label { display: grid; gap: 0.35rem; font-size: 0.8125rem; color: var(--text-dim); }
.form input, .form textarea {
  font: inherit; font-size: 0.9375rem;
  color: var(--text);
  background: oklch(100% 0 0 / 0.045);
  border: 1px solid oklch(100% 0 0 / 0.1);
  border-radius: 14px;
  padding: 0.8em 0.95em;
  width: 100%;
  transition: border-color 180ms, background-color 180ms;
}
.form textarea { resize: vertical; min-height: 5.5rem; }
.form select {
  font: inherit; font-size: 0.9375rem;
  color: var(--text);
  background: oklch(100% 0 0 / 0.045);
  border: 1px solid oklch(100% 0 0 / 0.1);
  border-radius: 14px;
  padding: 0.8em 0.95em;
  width: 100%;
  appearance: none;
}
/* The dropdown list is painted by the platform, which on a light OS means
   black on white. Set it here or half the options disappear into the page. */
.form select option { background: oklch(14% 0.012 265); color: var(--text); }
.form input:focus, .form textarea:focus, .form select:focus {
  outline: none; border-color: oklch(63% 0.166 42 / 0.6); background: oklch(100% 0 0 / 0.07);
}

/* ---------- a photograph as a full-width plate ----------
   Same radius as the surfaces around it, so the picture reads as another panel
   in the stack rather than a picture dropped onto the page. The inset ring is
   what stops a near-black frame from bleeding into a near-black background. */
.shot {
  margin: 0;
  border-radius: var(--rad-panel);
  overflow: hidden;
  box-shadow: 0 0 0 1px oklch(100% 0 0 / 0.07) inset, var(--shadow);
}
.shot img { width: 100%; aspect-ratio: 16 / 10; object-fit: cover; }

/* ---------- the three steps ---------- */
.form__step { display: grid; gap: 1.1rem; }
.form__step:focus { outline: none; }
.form__step[hidden] { display: none; }

.form__dots { display: flex; gap: 0.5rem; list-style: none; padding: 0; margin: 0; }
.form__dots li {
  flex: 1; font-family: var(--mono); font-size: 0.625rem; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--text-faint);
  padding-top: 0.55rem; border-top: 2px solid var(--line-soft);
  transition: color 220ms, border-color 220ms;
}
.form__dots li[data-on] { color: var(--text-dim); border-top-color: var(--accent); }

.opts { border: 0; padding: 0; margin: 0; display: grid; gap: 0.45rem; }
.opts legend { font-size: 0.8125rem; color: var(--text-dim); padding: 0 0 0.55rem; }
/* Qualified by `.form` on purpose. `.form label` sets display:grid and wins on
   specificity over a bare `.opt`, which stacked the radio above its own words
   and doubled the height of every card. */
.form .opt {
  display: flex; align-items: center; gap: 0.7rem;
  font-size: 0.9375rem; color: var(--text);
  background: oklch(100% 0 0 / 0.045);
  border: 1px solid oklch(100% 0 0 / 0.1);
  border-radius: 14px;
  padding: 0.72em 0.95em;
  cursor: pointer;
  transition: border-color 180ms, background-color 180ms;
}
.form .opt:hover { border-color: oklch(100% 0 0 / 0.2); }
/* The radio stays in the layout rather than being hidden: it carries the focus
   ring the keyboard needs, and a ring drawn by hand on the label is always
   slightly wrong somewhere. */
.form .opt input { width: 1.05rem; height: 1.05rem; accent-color: var(--accent); flex: none; margin: 0; }
.form .opt:has(input:checked) { border-color: oklch(63% 0.166 42 / 0.65); background: oklch(63% 0.166 42 / 0.09); }

/* Same specificity qualifier as .opt — a checkbox beside its wording, not
   stacked above it by the grid that `.form label` would otherwise apply. */
.form .consent { display: flex; align-items: start; gap: 0.7rem; font-size: 0.75rem; line-height: 1.5; }
.form .consent[hidden] { display: none; }
.form .consent input { width: 1.05rem; height: 1.05rem; accent-color: var(--accent); flex: none; margin-top: 0.15rem; }

.form__nav { display: flex; gap: 0.6rem; }
.form__nav .btn[hidden] { display: none; }
.form__nav .btn { flex: 1; }

.form__note { font-size: 0.75rem; color: var(--text-faint); line-height: 1.45; }
.form__msg { font-size: 0.875rem; line-height: 1.45; min-height: 1.2em; }
.form__msg[data-state="ok"] { color: var(--wa); }
.form__msg[data-state="err"] { color: var(--accent-hot); }
.form[data-busy="1"] button[type="submit"] { opacity: 0.6; pointer-events: none; }
/* Honeypot — a real field to a bot, invisible and unfocusable to a person. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* ---------- breadcrumbs ---------- */
.crumbs { display: flex; flex-wrap: wrap; gap: 0.4rem; align-items: center; font-family: var(--mono); font-size: 0.6875rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-faint); margin-bottom: 1.5rem; }
.crumbs a:hover { color: var(--accent); }
.crumbs i { opacity: 0.4; font-style: normal; }

/* ---------- horizontal rows ----------
   The reference runs cases, journal, clients and awards sideways, with the last
   card deliberately cut off by the viewport edge. That clip is the whole point:
   it removes any doubt that more exists. Implemented by bleeding the track out
   of the container gutters, so the cut happens at the screen edge rather than
   at a padding boundary.

   Native overflow scrolling means touch swipe and keyboard both work for free;
   the arrows are an affordance on top, not the only way in. */
.row {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: min(78vw, 371px);
  gap: clamp(0.75rem, 1.4vw, 1.25rem);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  scroll-padding-inline: var(--gut);
  margin-inline: calc(var(--gut) * -1);
  padding-inline: var(--gut);
  padding-block: 0.35rem;
  scrollbar-width: none;
}
.row::-webkit-scrollbar { display: none; }
.row > * { scroll-snap-align: start; min-width: 0; }
/* Row cards are a fixed height in the reference so the row reads as a band
   rather than a ragged edge. Images take the slack. */
.row .work { display: grid; grid-template-rows: minmax(0, 1fr) auto; height: clamp(23rem, 42vw, 31.25rem); }
.row .work__img { aspect-ratio: auto; height: 100%; min-height: 0; }
/* The metrics tile has no photograph, so its numbers have to fill the slack
   rather than sit in a fixed-height box that no longer exists. */
.row .work--num .work__img { display: grid; place-items: center; padding: 1rem; }
.row .work--num .work__nums { flex-wrap: wrap; }
.row .card { height: clamp(23rem, 42vw, 31.25rem); align-content: space-between; }

.row-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 1.5rem; flex-wrap: wrap; margin-bottom: clamp(1.5rem, 3vw, 2.5rem); }
.row-head > div { max-width: 46ch; }
.row-nav { display: none; gap: 0.5rem; }
@media (min-width: 60rem) { .row-nav { display: flex; } }
.row-nav button {
  width: 46px; height: 46px; border-radius: 50%;
  border: 1px solid oklch(100% 0 0 / 0.14);
  display: grid; place-items: center;
  color: var(--text-dim);
  transition: color 200ms, border-color 200ms, background-color 200ms;
}
.row-nav button:hover { color: var(--paper); border-color: oklch(100% 0 0 / 0.3); background: oklch(100% 0 0 / 0.05); }
.row-nav button[disabled] { opacity: 0.3; pointer-events: none; }
.row-nav svg { width: 16px; height: 16px; }

/* ---------- client logo tiles ----------
   Evidence, not decoration: every tile links to that client's case page. The
   list is drawn from the cases already in the repository — there is no slot
   here for a logo we have not earned. */
.logo-t {
  display: grid; place-items: center;
  height: clamp(7rem, 12vw, 9rem);
  background: var(--surface);
  backdrop-filter: blur(14px);
  border: 1px solid oklch(100% 0 0 / 0.055);
  border-radius: var(--rad-panel);
  padding: 1.25rem;
  transition: border-color 240ms, background-color 240ms, transform 240ms var(--ease);
}
a.logo-t:hover { border-color: oklch(100% 0 0 / 0.16); background: var(--surface-2); transform: translateY(-3px); }
.logo-t span {
  font-family: var(--display); font-weight: 600;
  font-size: clamp(1rem, 0.9rem + 0.5vw, 1.35rem);
  letter-spacing: -0.03em;
  color: var(--text-dim);
  text-align: center; line-height: 1.15;
  transition: color 240ms;
}
a.logo-t:hover span { color: var(--paper); }
.logo-t img { max-height: 3rem; width: auto; object-fit: contain; }
.row--logos { grid-auto-columns: min(44vw, 15rem); }

/* ---------- verifiable facts ----------
   The slot where the reference lists its industry awards. We have none, so it
   carries claims a visitor can check from this site inside a minute. Same
   treatment as the reference's award row: pure typography, no boxes, no badges
   — which reads stricter than any medal would. */
.facts { grid-auto-columns: min(64vw, 17rem); }
.fact { display: grid; gap: 0.5rem; align-content: start; padding-right: 1rem; }
.fact__v {
  font-family: var(--display);
  font-size: clamp(2rem, 1.4rem + 2.4vw, 3.25rem);
  font-weight: 300; letter-spacing: -0.04em; line-height: 1;
  color: var(--paper);
}
.fact__k { font-family: var(--mono); font-size: 0.6875rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--accent); }
.fact__d { font-size: 0.875rem; color: var(--text-dim); line-height: 1.45; max-width: 24ch; }

/* Asymmetric section head: title left, description set right on the same
   baseline. The reference uses it for Блог, Наши клиенты and Награды. */
.sec-head--wide { max-width: none; display: grid; gap: 1rem; }
@media (min-width: 60rem) {
  .sec-head--wide { grid-template-columns: minmax(0, 1fr) minmax(0, 26rem); align-items: end; justify-content: space-between; }
  .sec-head--wide > :last-child { justify-self: end; text-align: right; }
}

/* ============================================================
   MOTION
   Scroll-driven where supported, IntersectionObserver fallback,
   and switched off entirely for reduced-motion users.
   ============================================================ */
@media (prefers-reduced-motion: no-preference) {
  .rise { opacity: 0; transform: translateY(18px); }
  .rise.in { opacity: 1; transform: none; transition: opacity 700ms var(--ease), transform 700ms var(--ease); }

  @supports (animation-timeline: view()) {
    .rise { opacity: 1; transform: none; animation: rise linear both; animation-timeline: view(); animation-range: entry 5% cover 26%; }
    .rise.in { transition: none; }
  }
  @keyframes rise { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: none; } }

  /* stagger children of a grid */
  .stagger > * { animation-delay: calc(var(--i, 0) * 55ms); }
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .rise { opacity: 1 !important; transform: none !important; }
  *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; }
}

/* Cross-document view transitions — upgrade only, ignored where unsupported */
@view-transition { navigation: auto; }
@media (prefers-reduced-motion: no-preference) {
  ::view-transition-old(root) { animation: vt-out 220ms var(--ease-in-out) both; }
  ::view-transition-new(root) { animation: vt-in 320ms var(--ease) both; }
}
@keyframes vt-out { to { opacity: 0; } }
@keyframes vt-in { from { opacity: 0; transform: translateY(8px); } }

/* Heavy decoration is desktop-only. Small screens and low-power
   devices get the same layout with none of the paint cost. */
@media (max-width: 60rem) {
  .field { opacity: 0.4; filter: blur(40px); }
  .field::after { display: none; }
  #fx { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  #fx { display: none; }
}

/* ── /direct/ niche pages ──────────────────────────────────
   Only what the shared vocabulary could not already do. Concept cards reuse
   .works/.work, steps reuse .steps/.step, the FAQ reuses .faq. */

/* Tighter rhythm than the marketing site: these pages are read in one pass by
   someone deciding whether to message, not browsed. The main site keeps its
   airier spacing. */
body.direct .sec { padding-block: clamp(2.75rem, 5.5vw, 5.5rem); }
body.direct .sec-head { margin-bottom: clamp(1.5rem, 2.8vw, 2.5rem); }
/* .split columns are uneven by nature; without this the shorter one leaves a
   crater under itself on desktop. */
@media (min-width: 60rem) { body.direct .split { align-items: center; } }
/* .tier--pkg gives the feature list a 1fr row so the buttons line up; the list
   is itself a grid, so without this the shortest tier fans its bullets apart. */
.tier--pkg .ticks { align-content: start; }

.dhero { position: relative; overflow: clip; padding-block: clamp(3rem, 7vw, 6.5rem) clamp(2.5rem, 5vw, 4.5rem); }
.dhero__img { position: absolute; inset: 0; z-index: 0; }
.dhero__img img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 60%; }
/* Two scrims, not one: the vertical keeps the headline legible, the horizontal
   stops the right edge of the photo fighting the copy on wide screens. */
.dhero__img::after {
  content: ""; position: absolute; inset: 0;
  background:
    linear-gradient(180deg, var(--ink) 2%, oklch(11% 0.012 265 / 0.72) 38%, oklch(11% 0.012 265 / 0.9) 88%, var(--ink)),
    linear-gradient(90deg, var(--ink) 4%, oklch(11% 0.012 265 / 0.55) 46%, transparent 82%);
}
.dhero > .wrap { position: relative; z-index: 1; }

.dtrust {
  display: flex; flex-wrap: wrap; gap: 0.55rem 1.4rem; margin-top: 2rem;
  font-family: var(--mono); font-size: 0.6875rem; letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--text-faint);
}
.dtrust span { display: inline-flex; align-items: center; gap: 0.5rem; }
.dtrust span::before { content: ""; width: 4px; height: 4px; border-radius: 50%; background: var(--wa); flex: none; }

/* concept shots sit on a light mat — they are light designs and float on ink */
.work--shot .work__img { background: oklch(88% 0.006 90); aspect-ratio: 16 / 10; }
.work--shot .work__img img { object-position: top center; filter: none; }

.rules { display: grid; gap: 0; counter-reset: r; }
.rules li {
  list-style: none; display: grid; grid-template-columns: 2.4rem 1fr; gap: 0.9rem;
  padding: 0.85rem 0; border-bottom: 1px solid var(--line-soft);
  font-size: 0.9375rem; color: var(--text-dim); line-height: 1.45; align-items: baseline;
}
.rules li::before {
  counter-increment: r; content: counter(r, decimal-leading-zero);
  font-family: var(--mono); font-size: 0.6875rem; color: var(--accent); letter-spacing: 0.08em;
}

/* print — people do print quotes */
@media print {
  .hdr, .sticky, .bg, .drawer, .row-nav, .field, #fx, .cta { display: none !important; }
  body { background: #fff; color: #000; padding: 0; }
  a { color: #000; }
}

/* ---------- mobile chrome ----------
   The wordmark was wrapping to two lines and the header WhatsApp button was
   shoving it there. That button is redundant on a phone anyway: the persistent
   pill is on screen at all times and does the same job with a bigger target. */
.brand { white-space: nowrap; }
@media (max-width: 48rem) {
  .hdr__cta .btn--wa { display: none; }
  .hdr__in { height: 60px; }
}
