/* Self-hosted Fraunces (variable) — no network dependency, works offline.
   Latin subset only; one file per style covers every weight via the variable
   axis, so there is no Google Fonts request and no Times fallback flash. */
@font-face {
  font-family: "Fraunces";
  font-style: normal;
  font-weight: 500 700;
  font-display: swap;
  src: url("fonts/fraunces-normal.woff2") format("woff2");
}
@font-face {
  font-family: "Fraunces";
  font-style: italic;
  font-weight: 500 600;
  /* block, not swap: italic is used only by the word "standard" in ABOUT, which
     starts invisible and reveals on scroll. block waits for the real font rather
     than flashing a fallback italic and then swapping (which made the tall "d"
     ascender visibly jump into place, reading as "the d arrives after the word").
     Preloaded in <head>, so the wait is imperceptible. */
  font-display: block;
  src: url("fonts/fraunces-italic.woff2") format("woff2");
}

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

:root {
  --black: #0a0a0a;
  --white: #ffffff;
  /* one horizontal gutter shared by every section — a single left/right spine
     so About, Services, Process and FAQ all line up to the same edges instead
     of each picking its own width and centering (the "random" feeling). */
  --gutter: 48px;
  /* single warm signal colour — used sparingly so the black/white stays the
     story, but it kills the "no warmth" coldness. */
  --accent: #ff4b2b;
  /* darker twin for small text on white: the vibrant --accent is only ~3.3:1
     on white (fails WCAG AA for 14px), this is ~4.9:1. Used for the tiny
     section index numbers; the bright one stays for big/expressive moments. */
  --accent-ink: #cc3a1c;
  /* editorial display serif for the monumental type; Helvetica still runs the
     UI, so the contrast (serif headline vs grotesque body) reads as designed. */
  --font-display: "Fraunces", "Times New Roman", Georgia, serif;
}

html,
body {
  height: 100%;
}

body {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  background: var(--white);
  color: var(--black);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* controlled, app-like feel: nothing selects by default. The two things a
     visitor may actually want to copy stay selectable below. */
  -webkit-user-select: none;
  user-select: none;
}

/* keep the contact address and form inputs selectable */
.footer__mail,
.cform__input {
  -webkit-user-select: text;
  user-select: text;
}

/* ---------- Keyboard focus ----------
   Visible only for keyboard users (:focus-visible), so mouse clicks stay clean.
   The accent ring reads >3:1 on both black and white — enough for a UI
   indicator under WCAG. */
a:focus-visible,
button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 1px;
}

/* the stretched service link fills the whole row — draw its ring just inside
   so it frames the row instead of spilling over the dividers/neighbours. */
.service__link:focus-visible {
  outline-offset: -5px;
}

/* ---------- Header ---------- */
.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 28px 40px;
  z-index: 10;
  /* logo + nav read black on white and invert to white over the black balls.
     The language flags are a separate fixed element (outside this blend) so
     their colours stay true. */
  mix-blend-mode: difference;
  /* no transition: blend-mode switches instantly, so fading the background
     would briefly leave white text blended over a white veil (reads as black).
     Switching state instantly keeps it clean. */
  transition: none;
}

/* once scrolled past the hero, drop the blend and lay a frosted white bar
   behind the nav so page text underneath never clashes with it; nav text turns
   dark to read on it. The translucent white also covers the dark contact
   section cleanly. Padding stays constant so the nav and the language chip keep
   the same line. */
.site-header.is-scrolled {
  mix-blend-mode: normal;
  background: rgba(255, 255, 255, 0.8);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.06);
}

.site-header.is-scrolled .logo,
.site-header.is-scrolled .nav a {
  color: var(--black);
}

.logo {
  font-size: 19px;
  font-weight: 800;
  letter-spacing: 0;
  white-space: nowrap;
  color: var(--white);
  text-decoration: none;
}

.logo sup {
  font-size: 0.5em;
  font-weight: 700;
  top: -0.8em;
}

.nav {
  display: flex;
  gap: 34px;
  margin-right: 96px;   /* clear the fixed language chip pinned to the corner */
}

.nav a {
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0.03em;
  color: var(--white);
  text-decoration: none;
  transition: opacity 0.2s ease;
}

.nav a:hover {
  opacity: 0.5;
}

/* fixed in the top-right corner, OUTSIDE the blended header, so the flag colours
   stay true (the header's difference blend would otherwise invert them). */
.lang {
  position: fixed;
  top: 28px;             /* = header padding-top */
  right: 40px;
  z-index: 11;
  /* both flags joined into one connected chip: a single rounded outline with
     a hairline divider between them, so it reads as one control */
  display: inline-flex;
  align-items: stretch;
  gap: 0;
  border-radius: 4px;
  overflow: hidden;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.12);
}

.lang__btn {
  background: none;
  border: none;
  margin: 0;
  padding: 4px 7px;
  cursor: pointer;
  line-height: 0;
  display: flex;
  align-items: center;
  /* the inactive half is gently muted, the active half full colour + filled */
  opacity: 0.5;
  filter: grayscale(0.5);
  transition: opacity 0.2s ease, filter 0.2s ease, background 0.2s ease;
}

.lang__btn + .lang__btn {
  border-left: 1px solid rgba(0, 0, 0, 0.12);
}

.lang__btn:hover {
  opacity: 0.85;
  filter: grayscale(0.1);
}

.lang__btn.is-active {
  opacity: 1;
  filter: grayscale(0);
  background: rgba(0, 0, 0, 0.05);
}

.lang__flag {
  display: block;
  width: 18px;
  height: 12px;
  border-radius: 1px;
  object-fit: cover;
}

/* ---------- Hero ---------- */
.hero {
  position: relative;
  /* No clip/mask: shadows render naturally past the box. The balls are held in by
     their wall physics (they cannot move past the hero bounds) — only the soft
     shadow feathers, which is what keeps the boundary natural. */
  isolation: isolate;
  background: var(--white);
  -webkit-user-select: none;
  user-select: none;
  cursor: default;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
}

/* Real white element so the difference-blended balls read as black.
   No z-index anywhere here on purpose: paint order is driven by DOM order
   (bg -> text -> balls) so the balls stay in the hero's blend group and
   blend against the white bg + black text instead of an empty layer. */
.hero__bg {
  position: absolute;
  inset: 0;
  background: var(--white);
}

.hero__inner {
  position: relative;
  display: inline-block;
}

/* Floating balls layer */
.hero__balls {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* Each ball = two stacked layers:
   1) .ball-base  white + mix-blend-mode:difference -> black body that
      inverts the text/nav behind it to white.
   2) .ball-gloss normal-blended glass sheen on top (highlight, rim,
      shadow) so the black sphere reads as premium 3D glass. */
.ball-base {
  position: absolute;
  top: 0;
  left: 0;
  border-radius: 50%;
  background: #fff;
  mix-blend-mode: difference;
  pointer-events: none;
  will-change: transform;
}

.ball-gloss,
.scroll-ball__gloss {
  position: absolute;
  top: 0;
  left: 0;
  border-radius: 50%;
  pointer-events: auto;
  cursor: pointer;
  touch-action: none;
  will-change: transform;
  /* fresnel glass: bright thin rim + soft edge glow + smooth environment
     sheen. Per-ball variables (set in JS) keep each sphere distinct. */
  --sx: 50%;
  --sy: -15%;
  --rim: 0.22;
  /* --d = the sphere's diameter (set per ball in JS). The inner glass shadows
     are sized as fractions of it so a small ball is shaded just like a big one,
     instead of a fixed 48px glow flooding the small ones to grey. */
  --d: 512px;
  background:
    radial-gradient(105% 64% at 50% 120%,
      rgba(255, 255, 255, 0.44) 0%,
      rgba(255, 255, 255, 0) 50%),
    radial-gradient(150% 42% at 50% 28%,
      rgba(255, 255, 255, 0.12) 0%,
      rgba(255, 255, 255, 0) 62%),
    radial-gradient(132% 102% at var(--sx) var(--sy),
      rgba(255, 255, 255, 0.78) 0%,
      rgba(255, 255, 255, 0.13) 32%,
      rgba(255, 255, 255, 0) 56%),
    radial-gradient(62% 62% at 50% 46%,
      rgba(255, 255, 255, 0.08) 0%,
      rgba(255, 255, 255, 0) 70%);
  box-shadow:
    inset 0 0 calc(var(--d) * 0.094) calc(var(--d) * 0.016) rgba(255, 255, 255, var(--rim)),
    inset calc(var(--d) * 0.047) calc(var(--d) * 0.051) calc(var(--d) * 0.125) rgba(255, 255, 255, 0.2),
    inset calc(var(--d) * -0.051) calc(var(--d) * -0.059) calc(var(--d) * 0.141) rgba(0, 0, 0, 0.64),
    0 calc(var(--d) * 0.094) calc(var(--d) * 0.188) rgba(0, 0, 0, 0.5);
}

/* ---------- Travelling ball (carried from the hero into ABOUT) ----------
   A fixed copy of the smallest sphere. mix-blend-mode:difference (on the
   base) means it inverts whatever sits behind it — black on the white
   about section — exactly like the hero trio inverts the headline. */
.scroll-ball {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 5;
}

/* A real black glass sphere — same look as the hero's smallest ball over
   white. We paint it solid black instead of using mix-blend-mode, because
   the fixed container forms its own stacking context and would isolate the
   blend (leaving a plain white disc). It only travels over white anyway. */
.scroll-ball__base {
  position: absolute;
  top: 0;
  left: 0;
  border-radius: 50%;
  background: #0a0a0a;
  will-change: transform;
}

.scroll-ball__gloss {
  /* only the little sphere is clickable, not the full-viewport layer */
  pointer-events: auto;
  cursor: pointer;
  touch-action: none;
  /* match looks[2] — the hero's smallest sphere */
  --sx: 50%;
  --sy: -18%;
  --rim: 0.46;
}

/* Docked period. Once the travelling dot arrives it hands off to THIS element,
   which lives inside .about (position: relative) and is absolutely placed once,
   so it scrolls natively with the text and never needs a per-frame JS follow —
   dead still, like a real period. Shown only while docked. */
.about__dot {
  position: absolute;
  top: 0;
  left: 0;
  border-radius: 50%;
  pointer-events: none;
  display: none;
}
.about__dot .scroll-ball__gloss { pointer-events: none; cursor: default; }

.hero__title {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-size: clamp(56px, 11vw, 185px);
  font-weight: 600;
  line-height: 0.95;
  letter-spacing: -0.01em;
  text-align: center;
  white-space: nowrap;
}

.hero__meta {
  display: flex;
  justify-content: space-between;
  margin-top: 8px;
}

.hero__meta span {
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 0.03em;
}

/* ---------- Shared section scaffolding ----------
   Hero DNA: bold, confident type — but carried by white space, not size.
   Weight 700 like the hero title; generous air keeps it feeling light. */
.section {
  position: relative;
  max-width: none;       /* full-bleed, edge to edge */
  margin: 0;
  padding: 150px var(--gutter);
}

.section + .section {
  border-top: 1px solid rgba(10, 10, 10, 0.1);
}

.section__head {
  display: flex;
  align-items: baseline;
  gap: 14px;
  margin-bottom: 64px;
}

/* tiny black-glass sphere — carries the hero/process orb motif into every
   section head (incl. Services & FAQ, which otherwise dropped the motif). */
.section__orb {
  flex: none;
  align-self: center;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background:
    radial-gradient(120% 95% at 32% 22%, rgba(255, 255, 255, 0.5) 0%, rgba(255, 255, 255, 0) 48%),
    var(--black);
  box-shadow:
    inset 2px 2px 5px rgba(255, 255, 255, 0.25),
    inset -2px -3px 6px rgba(0, 0, 0, 0.6),
    0 3px 7px rgba(0, 0, 0, 0.3);
}

.section__index {
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--accent-ink);   /* AA-safe on white */
}

.section__label {
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.18em;
}

/* ---------- About (normal scroll-reveal, no pin) ----------
   Was a tall pinned panel that "held" the screen while the words revealed — the
   second scroll-jack back-to-back with Process, which read as too much. Now it's
   a normal section and the words reveal on entry instead (the reveal JS falls
   back to a viewport-based trigger when .about-pin is absent). One pin left on
   the page, not two. */
.about {
  position: relative;
  padding: 150px 0;   /* horizontal gutter comes from .about-inner */
}

.about-inner {
  width: 100%;
  max-width: none;
  margin: 0;
  padding: 0 var(--gutter);   /* same left spine as every other section */
}

.about__statement {
  max-width: 22ch;
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-size: clamp(28px, 3.8vw, 52px);
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.01em;
}

.about__statement em {
  font-style: italic;
  color: var(--accent);
}

/* Scroll-reveal: the head fades in and the statement rises word by word —
   scrubbed straight from the scroll position (driven by JS, which sets each
   word's opacity/transform), so it advances gradually as you scroll and
   rewinds when you scroll back. */
.about .section__head,
.about__statement .word {
  opacity: 0;
}

.about__statement .word,
.about__statement .word__i {
  display: inline-block;
}

@media (prefers-reduced-motion: reduce) {
  .about .section__head,
  .about__statement .word {
    opacity: 1 !important;
    transform: none !important;
  }
}

/* ---------- Services (full-bleed, edge to edge) ----------
   No width override needed — every .section is full-bleed on the shared
   --gutter now, so Services lines up with FAQ instead of being a special case. */
.services__list {
  list-style: none;
  border-top: 1px solid rgba(10, 10, 10, 0.14);
}

.service {
  position: relative;
  display: grid;
  grid-template-columns: 90px minmax(0, 1fr) minmax(0, 30ch) 48px;
  align-items: center;
  gap: 48px;
  padding: 40px 8px;
  border-bottom: 1px solid rgba(10, 10, 10, 0.14);
  color: var(--black);
  transition: padding-left 0.5s cubic-bezier(0.16, 1, 0.3, 1),
              color 0.4s ease,
              opacity 0.8s ease,
              transform 0.8s cubic-bezier(0.16, 1, 0.3, 1);
}

/* ---------- Services: horizontal pin-scroll ----------
   The section pins to the viewport; scrolling drives the card track sideways
   (JS sets the pin height + translateX). Small screens fall back to a native
   horizontal swipe, so it still works with no JS. */
.services-pin {
  position: relative;
}
.services-sticky {
  position: sticky;
  top: 0;
  height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 56px;
  overflow: hidden;
}
.services-sticky .section__head {
  padding: 0 var(--gutter);
  margin: 0;
}
.services-track {
  display: flex;
  flex-wrap: nowrap;
  align-items: flex-start;
  gap: 40px;                 /* air between cards instead of divider lines */
  height: auto;
  border-top: none;
  padding: 0 var(--gutter);
  will-change: transform;
}
.services-track .service {
  flex: 0 0 auto;
  width: min(84vw, 500px);
  min-height: min(38vh, 330px);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: flex-start;   /* top-aligned so the gaps read equal on every
                                    card regardless of how long the text is */
  gap: 26px;
  padding: 56px 44px;
  border: none;                  /* no posts between cards — let them breathe */
}
/* stagger the cards on the Y axis with varied offsets (some runs go the same
   way) so the row reads as a deliberate scatter — on every screen, mobile too */
.services-track .service:nth-child(1) { margin-top: 6px; }    /* high  ┐ two high */
.services-track .service:nth-child(2) { margin-top: 20px; }   /* high  ┘ in a row  */
.services-track .service:nth-child(3) { margin-top: 112px; }  /* low   ┐ two low  */
.services-track .service:nth-child(4) { margin-top: 96px; }   /* low   ┘ in a row  */
.services-track .service:nth-child(5) { margin-top: 34px; }   /* high  */
.services-track .service:nth-child(6) { margin-top: 116px; }  /* low   */
.services-track .service:nth-child(7) { margin-top: 58px; }   /* mid   */

.services-track .service:hover {
  padding-left: 44px;            /* neutralise the list's indent-on-hover */
}
.services-track .service__name {
  font-size: clamp(32px, 3.4vw, 52px);
}

/* the black element: a wide angular bar pinned to the card bottom, so every
   card reads as clickable + "more to read" at the same spot (no hover needed).
   Inverts to white when the card fills black on hover. */
.services-track .service__toggle {
  align-self: stretch;           /* full card width */
  width: 100%;
  margin-top: auto;              /* pushed to the card bottom — same on every screen */
  display: flex;
  align-items: center;
  height: auto;
  background: none;
  color: var(--black);
  font-size: 0;                  /* hide the "→" glyph; the arrow is drawn below */
  opacity: 1;
  transition: color 0.4s ease;
}
/* one continuous arrow: a full-width line whose end carries the arrowhead,
   touching with no gap */
.services-track .service__toggle::before {
  content: "";
  flex: 1 1 auto;                /* the long line fills the whole card width */
  height: 2px;
  background: currentColor;
}
.services-track .service__toggle::after {
  content: "";
  width: 0;
  height: 0;
  margin-left: -1px;             /* base touches the line end, no gap */
  border-top: 6px solid transparent;
  border-bottom: 6px solid transparent;
  border-left: 14px solid currentColor;
}
.services-track .service:hover .service__toggle {
  color: var(--white);           /* the card fills black on hover */
}

/* small screens keep the very same pinned horizontal scroll — just tighter
   card sizing so a card and the next one's edge fit the narrow viewport */
/* small screens keep the same pinned scroll as desktop (scroll to move the
   cards sideways); just tighter card sizing */
@media (max-width: 900px) {
  .services-track .service {
    width: 82vw;
    padding: 48px 30px;
  }
}

/* touch / phone: a tap must NOT fill the service card black (iOS keeps :hover
   stuck after a tap). Covers both real touch (hover:none) and narrow/phone
   widths so it also holds up in responsive testing. */
@media (hover: none), (max-width: 900px) {
  .service:hover::before { transform: scaleY(0) !important; }
  .service:hover { color: var(--black) !important; }
  .service:hover .service__toggle,
  .services-track .service:hover .service__toggle { color: var(--black) !important; }
}

/* sweep fill that slides in on hover — premium, ties to the black motif */
.service::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--black);
  transform: scaleY(0);
  transform-origin: bottom;
  transition: transform 0.5s cubic-bezier(0.16, 1, 0.3, 1);
  z-index: -1;
}

.service:hover {
  padding-left: 32px;
  color: var(--white);
}

.service:hover::before {
  transform: scaleY(1);
}

/* stretched link: the whole row is now a real, clickable target (was a dead
   row with a link-implying ↗). Sits above the fill, below the text. */
.service__link {
  position: absolute;
  inset: 0;
  z-index: 1;
}

.service__no,
.service__name,
.service__desc,
.service__arrow {
  position: relative;
  z-index: 2;
  pointer-events: none;
}

.service__no {
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0.04em;
  opacity: 0.5;
}

.service__name {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-size: clamp(34px, 5.5vw, 84px);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.02em;
}

.service__desc {
  font-size: 15px;
  font-weight: 500;
  line-height: 1.5;
  opacity: 0.55;
}

.service__arrow {
  justify-self: end;
  font-size: 30px;
  line-height: 1;
  font-weight: 400;
  opacity: 0;
  transform: translate(-10px, 10px);
  transition: opacity 0.4s ease, transform 0.5s cubic-bezier(0.16, 1, 0.3, 1);
}

.service:hover .service__arrow {
  opacity: 1;
  transform: none;
  color: var(--accent);
}

/* the detail text lives hidden in each row and feeds the slide-in panel */
.service__detail {
  display: none;
}

/* affordance: an arrow that hints the row opens a detail panel */
.service__toggle {
  position: relative;
  z-index: 2;
  justify-self: end;
  font-size: 26px;
  line-height: 1;
  font-weight: 300;
  opacity: 0.4;
  pointer-events: none;
  transition: opacity 0.4s ease,
              transform 0.5s cubic-bezier(0.16, 1, 0.3, 1),
              color 0.4s ease;
}
.service:hover .service__toggle {
  opacity: 1;
  transform: translateX(6px);
  color: var(--accent);
}

/* ---------- Process (pinned: a black disc spins, the copy changes) ----------
   The pin holds the screen while you scroll; a tall spacer drives progress.
   No hairline above it (services -> process) since it isn't a .section. */
.process-pin {
  position: relative;
  height: 250vh; /* 100vh on screen + 150vh of pinned scrubbing (4 steps) —
                    ~37vh per step keeps it snappy without two long pins
                    (about + process) dragging back to back */
}

.process {
  position: sticky;
  top: 0;
  height: 100vh;
  display: flex;
  align-items: center;
  overflow: hidden;
}

.process-inner {
  width: 100%;
  max-width: none;
  margin: 0;
  padding: 0 var(--gutter);   /* same left spine as every other section */
}

.process__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: center;
  gap: 48px;
  margin-top: 56px;
  /* left-aligned (margin:0) so the copy shares the gutter spine, but capped so
     the disc doesn't fly to the far edge and leave a sparse gap on wide screens. */
  max-width: 1180px;
}

/* left: stacked steps, only the active one shown (crossfade) */
.process__copy {
  position: relative;
  min-height: 320px;
}

.pstep {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 0.5s cubic-bezier(0.16, 1, 0.3, 1),
              transform 0.5s cubic-bezier(0.16, 1, 0.3, 1);
  pointer-events: none;
}

.pstep.is-on {
  opacity: 1;
  transform: none;
}

.pstep__no {
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.14em;
  opacity: 0.45;
}

.pstep__title {
  margin-top: 18px;
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-size: clamp(44px, 6vw, 96px);
  font-weight: 600;
  line-height: 0.95;
  letter-spacing: -0.02em;
}

.pstep__text {
  margin-top: 20px;
  max-width: 38ch;
  font-size: 17px;
  font-weight: 500;
  line-height: 1.55;
  opacity: 0.55;
}

/* right: the big black disc that spins as you scroll */
.process__disc-wrap {
  position: relative;
  justify-self: end;
  width: clamp(260px, 36vw, 480px);
  aspect-ratio: 1 / 1;
}

.process__disc {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  /* exactly the hero spheres' fresnel glass — bright thin rim, soft environment
     sheen, deep bottom shade. The sheen sits off-centre so it glints as the
     disc spins. (Per-ball vars matched to the hero's biggest sphere.) */
  --sx: 42%;
  --sy: -14%;
  --rim: 0.34;
  background:
    radial-gradient(105% 64% at 50% 120%,
      rgba(255, 255, 255, 0.44) 0%, rgba(255, 255, 255, 0) 50%),
    radial-gradient(150% 42% at 50% 28%,
      rgba(255, 255, 255, 0.12) 0%, rgba(255, 255, 255, 0) 62%),
    radial-gradient(132% 102% at var(--sx) var(--sy),
      rgba(255, 255, 255, 0.78) 0%, rgba(255, 255, 255, 0.13) 32%, rgba(255, 255, 255, 0) 56%),
    radial-gradient(62% 62% at 50% 46%,
      rgba(255, 255, 255, 0.08) 0%, rgba(255, 255, 255, 0) 70%),
    #0a0a0a;
  box-shadow:
    inset 0 0 48px 8px rgba(255, 255, 255, var(--rim)),
    inset 24px 26px 64px rgba(255, 255, 255, 0.2),
    inset -26px -30px 72px rgba(0, 0, 0, 0.64);
  will-change: transform;
}

/* grounding drop shadow on the (non-rotating) wrapper, so it stays put under the
   disc instead of orbiting with the spin — same soft shadow the hero balls cast. */
.process__disc-wrap::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  box-shadow: 0 48px 96px rgba(0, 0, 0, 0.5);
}

/* a marker on the rim so the rotation is unmistakable */
.process__disc::after {
  content: "";
  position: absolute;
  top: 5.5%;
  left: 50%;
  width: 14px;
  height: 14px;
  margin-left: -7px;
  border-radius: 50%;
  background: var(--white);
}

/* the step number, centred and upright (does not spin) */
.process__disc-no {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--white);
  font-size: clamp(72px, 11vw, 168px);
  font-weight: 700;
  letter-spacing: -0.03em;
  pointer-events: none;
}

/* ---------- Contact / CTA ---------- */
.cta {
  max-width: none;
  text-align: center;
  background: var(--black);
  color: var(--white);
  padding: 180px 40px;
}

.cta .section__head {
  justify-content: center;
}

/* on the black CTA the darker ink would be too low-contrast — the bright accent
   reads ~6:1 on black, so restore it here. */
.cta .section__index {
  color: var(--accent);
}

.cta__title {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-size: clamp(60px, 13vw, 180px);
  font-weight: 600;
  line-height: 0.92;
  letter-spacing: -0.015em;
  margin: 28px 0 52px;
}

/* ---------- Contact form (on the black CTA) ---------- */
.cform {
  max-width: 560px;
  margin: 0 auto 48px;
  text-align: left;
}

/* honeypot: kept out of the layout and away from keyboard/AT users */
.cform__hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.cform__row {
  display: flex;
  gap: 20px;
}

.cform__row .cform__field {
  flex: 1;
}

.cform__field {
  display: block;
  margin-bottom: 22px;
}

.cform__label {
  display: block;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.5);
  margin-bottom: 11px;
}

.cform__input {
  width: 100%;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 12px;
  color: var(--white);
  font: inherit;
  font-size: 16px;
  padding: 16px 18px;
  transition: border-color 0.2s ease, background 0.2s ease;
}

.cform__input:hover {
  border-color: rgba(255, 255, 255, 0.28);
}

.cform__input::placeholder {
  color: rgba(255, 255, 255, 0.32);
}

.cform__input:focus {
  outline: none;
  border-color: var(--accent);
  background: rgba(255, 255, 255, 0.07);
}

.cform__textarea {
  resize: vertical;
  min-height: 120px;
  line-height: 1.5;
}

.cform__note {
  margin: 16px 0 0;
  font-size: 12px;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.4);
}

.cform__link {
  color: rgba(255, 255, 255, 0.62);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.cform__link:hover {
  color: var(--accent);
}

.cform__foot {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 16px;
  margin-top: 30px;
}

.cform__send {
  appearance: none;
  width: 100%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  background: var(--white);
  color: var(--black);
  border: 1px solid var(--white);
  border-radius: 999px;
  font: inherit;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 19px 34px;
  cursor: pointer;
  transition: background 0.25s ease, color 0.25s ease, border-color 0.25s ease, transform 0.12s ease;
}

.cform__send::after {
  content: "\2192";
  font-size: 16px;
  transition: transform 0.25s ease;
}

.cform__send:hover {
  background: var(--accent);
  color: var(--white);
  border-color: var(--accent);
}

.cform__send:hover::after {
  transform: translateX(5px);
}

.cform__send:active {
  transform: translateY(1px);
}

.cform__status {
  font-size: 14px;
  text-align: center;
  color: rgba(255, 255, 255, 0.7);
  min-height: 1.2em;
}

@media (max-width: 640px) {
  .cform__row {
    flex-direction: column;
    gap: 0;
  }
}


/* ---------- Footer ---------- */
.footer {
  display: flex;
  flex-direction: column;
  gap: 28px;
  /* extra bottom padding clears the floating Cookiebot privacy-trigger icon,
     which sits fixed at the viewport's bottom-left corner: this pushes the
     email link up above it instead of shifting the link's own text right. */
  padding: 56px 40px 100px;
  background: var(--black);
  color: var(--white);
  border-top: 1px solid rgba(255, 255, 255, 0.12);
}

.footer__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 20px;
}

.footer__row--bottom {
  padding-top: 28px;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
}

.footer__logo {
  font-size: 18px;
  font-weight: 800;
  letter-spacing: 0.02em;
}

.footer__logo sup {
  font-size: 0.5em;
  font-weight: 700;
  top: -0.8em;
}

.footer__nav {
  display: flex;
  gap: 28px;
}

.footer__nav a {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--white);
  text-decoration: none;
  transition: opacity 0.2s ease;
}

.footer__nav a:hover {
  opacity: 0.5;
}

.footer__mail {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--white);
  text-decoration: none;
  border-bottom: 1px solid rgba(255, 255, 255, 0.3);
  padding-bottom: 2px;
  transition: color 0.2s ease, border-color 0.2s ease;
}

.footer__mail:hover {
  color: var(--accent);
  border-color: var(--accent);
}

.footer__meta {
  display: flex;
  align-items: center;
  gap: 20px;
}

.footer__privacy {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--white);
  opacity: 0.6;
  text-decoration: none;
  transition: opacity 0.2s ease;
}

.footer__privacy:hover {
  opacity: 1;
}

.footer__copy {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  opacity: 0.45;
}

/* ---------- Responsive ---------- */
@media (max-width: 900px) {
  /* below this width two columns squeeze the copy down to one word per line,
     so stack the steps above the disc instead. NO justify-items:start: it would
     shrink the copy cell to its longest word. Keep the disc small enough that
     its soft shadow is not clipped by the section's overflow. */
  /* stacked: let the disc's soft shadow show fully instead of being clipped */
  .process {
    overflow: visible;
  }
  .process__grid {
    grid-template-columns: 1fr;
    gap: 28px;
  }
  .process__copy {
    min-height: 240px;
  }
  .process__disc-wrap {
    justify-self: center;
    width: clamp(170px, 30vw, 250px);
  }
  .service {
    grid-template-columns: 44px 1fr;
    gap: 12px 20px;
    align-items: baseline;
  }
  .service__name {
    grid-column: 2;
  }
  .service__desc {
    grid-column: 2;
  }
  .service__arrow {
    display: none;
  }
}

@media (max-width: 640px) {
  :root {
    --gutter: 20px;   /* tighten the shared spine on phones */
  }
  .site-header {
    padding: 20px;
  }
  .logo {
    font-size: 16px;
  }
  /* one-page scroll + the footer nav cover navigation; dropping the top nav
     keeps the small header clean for the logo + language toggle. */
  .nav {
    display: none;
  }
  .lang {
    top: 20px;
    right: 20px;
  }
  .hero__title {
    white-space: normal;
  }
  .section {
    padding: 96px 20px;
  }
  .services {
    padding: 96px 20px;
  }
  .process-inner {
    padding: 0 20px;
  }
  .process__grid {
    grid-template-columns: 1fr;
    gap: 28px;
  }
  .process__disc-wrap {
    justify-self: center;
    width: clamp(170px, 48vw, 230px);
  }
  .process__copy {
    min-height: 220px;
  }
  .footer {
    padding: 28px 20px 90px;
  }
}

/* ---------- Service detail: slide-in editorial panel ----------
   Click/tap a service to open it. A black sheet slides in from the right
   (full-width on phones), tying into the black hover motif. */
.svc-lock {
  overflow: hidden;
}

.svc-panel {
  position: fixed;
  inset: 0;
  z-index: 120;
  visibility: hidden;
  pointer-events: none;
}
.svc-panel.is-open {
  visibility: visible;
  pointer-events: auto;
}

.svc-panel__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(10, 10, 10, 0.5);
  opacity: 0;
  transition: opacity 0.5s ease;
}
.svc-panel.is-open .svc-panel__backdrop {
  opacity: 1;
}

.svc-panel__sheet {
  position: absolute;
  top: 0;
  right: 0;
  height: 100%;
  width: 100%;
  max-width: 560px;
  background: var(--black);
  color: var(--white);
  padding: clamp(32px, 6vw, 72px);
  display: flex;
  flex-direction: column;
  transform: translateX(100%);
  transition: transform 0.6s cubic-bezier(0.16, 1, 0.3, 1);
  overflow-y: auto;
}
.svc-panel.is-open .svc-panel__sheet {
  transform: none;
}

.svc-panel__close {
  align-self: flex-end;
  background: none;
  border: none;
  color: var(--white);
  font-size: 34px;
  line-height: 1;
  cursor: pointer;
  opacity: 0.7;
  transition: opacity 0.3s ease, transform 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}
.svc-panel__close:hover {
  opacity: 1;
  transform: rotate(90deg);
}

.svc-panel__no {
  margin-top: clamp(24px, 8vh, 80px);
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--accent);
}
.svc-panel__name {
  margin-top: 16px;
  min-width: 0;
  overflow-wrap: anywhere;       /* never clip a long name like "Automatsioonid" */
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-size: clamp(30px, 5.4vw, 52px);
  font-weight: 600;
  line-height: 1.04;
  letter-spacing: -0.02em;
}
.svc-panel__text {
  margin-top: 28px;
  max-width: 42ch;
  min-width: 0;
  overflow-wrap: anywhere;
  font-size: 17px;
  font-weight: 400;
  line-height: 1.6;
  opacity: 0.75;
}
.svc-panel__cta {
  margin-top: auto;
  padding-top: 40px;
  display: inline-flex;
  align-items: center;
  gap: 12px;
  color: var(--white);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
}
.svc-panel__cta::after {
  content: "\2192";
  transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}
.svc-panel__cta:hover::after {
  transform: translateX(8px);
}

@media (prefers-reduced-motion: reduce) {
  .svc-panel__sheet,
  .svc-panel__backdrop {
    transition: none;
  }
}

/* Cookiebot consent banner — matched to site palette */
#CybotCookiebotDialog {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif !important;
  border-radius: 0 !important;
}
#CybotCookiebotDialogBodyContentTitle {
  font-family: "Fraunces", Georgia, serif !important;
}
#CybotCookiebotDialog button[id*="Accept"],
#CybotCookiebotDialog button[id*="Allow"],
#CybotCookiebotDialog a[id*="Accept"],
#CybotCookiebotDialog a[id*="Allow"] {
  background-color: var(--accent) !important;
  border-color: var(--accent) !important;
  color: var(--white) !important;
}
#CybotCookiebotDialog button[id*="Accept"]:hover,
#CybotCookiebotDialog button[id*="Allow"]:hover {
  background-color: var(--accent-ink) !important;
  border-color: var(--accent-ink) !important;
}
#CybotCookiebotDialog button[id*="Decline"],
#CybotCookiebotDialog button[id*="Deny"],
#CybotCookiebotDialog a[id*="Decline"],
#CybotCookiebotDialog a[id*="Deny"] {
  background-color: transparent !important;
  border-color: var(--black) !important;
  color: var(--black) !important;
}
#CybotCookiebotDialog button[id*="Details"],
#CybotCookiebotDialog a[id*="Details"] {
  color: var(--black) !important;
  border-color: var(--black) !important;
}
#CybotCookiebotDialog [role="tab"] {
  color: var(--black) !important;
  border-color: transparent !important;
}
#CybotCookiebotDialog [role="tab"][aria-selected="true"],
#CybotCookiebotDialog .CybotCookiebotDialogActive,
#CybotCookiebotDialog [class*="Tab"][class*="ctive"] {
  color: var(--black) !important;
  border-color: var(--accent) !important;
}
#CybotCookiebotDialog a {
  color: var(--accent) !important;
}
#CybotCookiebotDialogBodyContentTitle,
#CybotCookiebotDialogBodyContentText,
.CybotCookiebotDialogBodyText {
  color: var(--black) !important;
}
#CybotCookiebotDialog .CybotCookiebotDialogBodyLevelButtonSlider {
  background-color: #ccc !important;
}
#CybotCookiebotDialog input:checked + .CybotCookiebotDialogBodyLevelButtonSlider {
  background-color: var(--accent) !important;
}
#CybotCookiebotDialogPoweredbyCybot,
#CybotCookiebotDialogPoweredByText {
  display: none !important;
}
#CookiebotWidget {
  display: none !important;
}
.cookie-trigger {
  position: fixed;
  left: 24px;
  bottom: 24px;
  width: 48px;
  height: 48px;
  padding: 0;
  border: none;
  background: transparent;
  cursor: pointer;
  z-index: 9998;
  filter: drop-shadow(0 10px 18px rgba(0, 0, 0, 0.45));
  transition: transform 0.25s ease;
}
.cookie-trigger svg {
  width: 100%;
  height: 100%;
  display: block;
}
.cookie-trigger:hover {
  transform: scale(1.08) translateY(-2px);
}
