/* Arcticside AI — site styles.
   Converted from the Claude Design canvas (Arcticside Landing.dc.html).
   Tokens come from _ds/…/tokens/*.css; this file holds page layout,
   components (buttons, cards, accordion, form) and interactions. */

/* Page-level font override: the landing uses Quicksand over the DS defaults */
:root {
  --font-sans: "Quicksand", "Manrope", system-ui, sans-serif;
  --font-display: "Quicksand", "Space Grotesk", system-ui, sans-serif;
}
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}
/* Anchor targets clear the fixed pill header */
[id] { scroll-margin-top: 90px; }
body { margin: 0; background: var(--surface-1); color: var(--text-body); font-family: var(--font-sans); min-height: 100%; }
a { color: var(--link); text-decoration: none; }
a:hover { color: var(--link-hover); }

.container { max-width: 1320px; width: 100%; box-sizing: border-box; margin: 0 auto; padding: 0 28px; }
[hidden] { display: none !important; }
.nowrap { white-space: nowrap; }

@keyframes hero-rise { from { transform: translate(-50%, 100%); opacity: 0; } to { transform: translate(-50%, 0); opacity: 1; } }
@keyframes header-drop { from { transform: translateY(-110%); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
@keyframes word-in { from { opacity: 0; transform: translateY(-0.6em); } to { opacity: 1; transform: translateY(0); } }

/* ---------- Buttons (from DS Button.jsx) ---------- */
.btn {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 46px;
  padding: 0 22px;
  font-family: var(--font-sans);
  font-weight: var(--fw-semibold);
  font-size: var(--text-base);
  letter-spacing: var(--ls-tight);
  line-height: 1;
  border-radius: var(--radius-pill);
  cursor: pointer;
  text-decoration: none;
  transition: transform var(--dur-fast) var(--ease-out), background-color 0s linear 0s, box-shadow 0.5s cubic-bezier(0.16, 1, 0.3, 1), color 0.3s cubic-bezier(0.16, 1, 0.3, 1);
  white-space: nowrap;
  /* The outline is an inset shadow, not a real border: overflow:hidden clips
     the hover fill to the padding box, so a border would stay uncovered and
     show as an arc at the pill's rounded ends. */
  border: none;
  box-shadow: none;
}
.btn:active { transform: scale(0.97); }
/* Design-system base.css puts a blue focus ring on every element; on pill
   buttons over the hero gradient it reads as a stray blue shadow. */
.btn:focus-visible, .btn:focus { outline: none; }
.btn-primary, .btn-primary:focus-visible { background: #33373f; color: #fff; box-shadow: inset 0 0 0 1.5px #33373f; }
.btn-primary:hover { color: #fff; }
.btn-secondary, .btn-secondary:focus-visible { background: var(--white); color: var(--ink-900); box-shadow: inset 0 0 0 1.5px var(--border-default); }
.btn-secondary:hover { color: var(--ink-900); }
.btn-inverse, .btn-inverse:focus-visible { background: var(--white); color: var(--ink-900); box-shadow: none; }
.btn-inverse:hover { color: var(--ink-900); }
.btn-block { display: flex; width: 100%; }
button.btn { appearance: none; }

/* Hover fill: a circle grows out of the pointer's entry point and floods the
   pill; the label color flips as it gets covered. Origin and diameter are set
   inline by initButtonFill (js/site.js) — the diameter reaches the farthest
   corner so the circle always covers the whole button. Keyboard focus fills
   from the center. Without JS the plain hover colors above still apply. */
.btn .btn-label { position: relative; z-index: 1; }
.btn .btn-fill {
  position: absolute;
  z-index: 0;
  border-radius: 50%;
  pointer-events: none;
  transform: translate(-50%, -50%) scale(0);
  transition: transform 0.5s cubic-bezier(0.16, 1, 0.3, 1);
}
.btn.is-filled .btn-fill { transform: translate(-50%, -50%) scale(1); }
/* While filled, the inset outline adopts the fill color so the hovered button
   reads as a clean color inversion with no visible ring. The base background
   flips to the fill color too, but only after the circle has finished covering
   the pill (delay 0.2s): the rounded clip is antialiased, so the old
   background bleeds a hairline at the caps if it stays underneath. Leaving
   resets the delay to 0s, so the base color is back before the circle
   retracts. */
.btn.is-filled { transition-delay: 0s, 0.2s, 0s, 0s; }
.btn-primary .btn-fill { background: var(--white); }
.btn-primary.is-filled, .btn-primary.is-filled:focus-visible { color: #33373f; background: var(--white); box-shadow: inset 0 0 0 1.5px var(--white); }
.btn-secondary .btn-fill, .btn-inverse .btn-fill { background: #33373f; }
.btn-secondary.is-filled, .btn-inverse.is-filled,
.btn-secondary.is-filled:focus-visible, .btn-inverse.is-filled:focus-visible { color: #fff; background: #33373f; box-shadow: inset 0 0 0 1.5px #33373f; }
@media (prefers-reduced-motion: reduce) {
  .btn .btn-fill { transition: none; }
  .btn.is-filled { transition-delay: 0s; }
}

/* Icon sizing helpers (DS Icon.jsx: 18 / 22 px, 2px stroke) */
.icon-18, .icon-22 { display: inline-flex; line-height: 0; color: currentColor; }
.icon-18 svg { width: 18px; height: 18px; }
.icon-22 svg { width: 22px; height: 22px; }

/* Placeholder for graphics not yet produced */
.graphic-placeholder {
  width: 100%; height: 100%;
  min-height: 60px;
  box-sizing: border-box;
  display: flex; align-items: center; justify-content: center;
  border: 1.5px dashed rgba(16,29,51,0.25);
  border-radius: 24px;
  color: rgba(16,29,51,0.45);
  font-size: 13px; font-weight: 600;
  text-align: center;
}

/* ---------- Hero ---------- */
.hero {
  position: relative;
  overflow: hidden;
  height: 100vh;
  /* Small-viewport units where supported: on phones 100vh is the tallest
     state of the viewport, so the hero would run under the browser chrome
     until the address bar collapses. */
  height: 100svh;
  min-height: 700px;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  /* The header is fixed (out of flow); this keeps the hero content where it
     sat when the header still occupied the top of the section. */
  padding-top: 79px;
  background: var(--grad-dawn);
}
.hero-header {
  position: fixed; top: 0; left: 0; right: 0; z-index: 50;
  margin: 0 auto;
  padding-top: 22px; padding-bottom: 22px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: rgba(255,255,255,0);
  border-radius: var(--radius-pill);
  box-shadow: 0 4px 18px rgba(16,29,51,0);
  /* Same duration, easing and delay as the mountain's hero-rise so both land
     together; "backwards" (not "both") for the same compositor-layer reason. */
  animation: header-drop 1.4s cubic-bezier(0.16,1,0.3,1) 0.2s backwards;
  transition:
    max-width 0.3s var(--ease-out),
    top 0.3s var(--ease-out),
    padding 0.3s var(--ease-out),
    background-color 0.3s var(--ease-out),
    box-shadow 0.3s var(--ease-out);
}
/* Same size in both header states on purpose: scaling a bitmap logo (via
   height or transform) makes it visibly re-rasterize when the collapse/expand
   transition settles, which reads as a small bounce. */
.hero-logo { height: 38px; width: auto; display: block; }
/* Two stacked logo variants cross-fade with the header background. Navy is the
   default so the shared header stays legible on any page (light background,
   scrolled white pill); the white variant is switched on only where the header
   sits over the dark part of the landing hero gradient. */
.hero-logo-wrap { position: relative; display: block; }
.hero-logo--light {
  position: absolute; top: 0; left: 0;
  opacity: 0;
  transition: opacity 0.3s var(--ease-out);
}
.hero-logo--dark { transition: opacity 0.3s var(--ease-out); }
.hero .hero-header:not(.scrolled) .hero-logo--light { opacity: 1; }
.hero .hero-header:not(.scrolled) .hero-logo--dark { opacity: 0; }
/* Absolutely centered so the asymmetric logo/CTA widths can't pull it off-axis */
.hero-nav {
  position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  display: flex; gap: 4px;
}
/* Ink by default (light backgrounds and the scrolled white pill); white only
   over the landing hero gradient, same rule as the logo above. */
.hero-nav a {
  padding: 8px 14px;
  border-radius: var(--radius-pill);
  font-size: 16px; font-weight: 600;
  color: var(--ink-900);
  transition: background-color var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out);
}
.hero-nav a:hover { color: var(--ink-900); background: rgba(16,29,51,0.08); }
.hero .hero-header:not(.scrolled) .hero-nav a { color: #fff; }
.hero .hero-header:not(.scrolled) .hero-nav a:hover { color: var(--ink-900); background: none; }

/* Scrolled: header collapses into a floating translucent pill (logo, nav and
   CTA pulled together), stays stuck to the top; reverts near the top of the page. */
.hero-header.scrolled {
  top: 16px;
  max-width: 1000px;
  width: calc(100% - 32px);
  padding: 12px 14px 12px 28px;
  background: rgba(255,255,255,0.8);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  box-shadow: 0 4px 18px rgba(16,29,51,0.08);
}
/* Right-hand header cluster: CTA + hamburger. The hamburger only exists
   below the nav breakpoint (900px), where .hero-nav is hidden. */
.hero-header-actions { display: flex; align-items: center; gap: 10px; }
.nav-toggle {
  display: none;
  width: 44px; height: 44px;
  padding: 0;
  border: none;
  border-radius: var(--radius-pill);
  /* Bare bars when closed; the tinted pill only appears with the open menu, as
     the button's "this is the thing you close" affordance. */
  background: transparent;
  color: var(--ink-900);
  cursor: pointer;
  align-items: center; justify-content: center;
  transition: background-color 0.3s var(--ease-out), color 0.3s var(--ease-out);
}
.nav-toggle[aria-expanded="true"] { background: rgba(16,29,51,0.07); }
.nav-toggle:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }
/* Light icon only over the landing hero gradient (see the logo rule above) */
.hero .hero-header:not(.scrolled) .nav-toggle { color: #fff; }
.hero .hero-header:not(.scrolled) .nav-toggle[aria-expanded="true"] { background: rgba(255,255,255,0.16); }
/* Two bars offset from the centre line; opening rotates both back onto that
   same line, so they cross exactly in the middle and read as a clean X. */
.nav-toggle-bars { position: relative; display: block; width: 20px; height: 14px; }
.nav-toggle-bars span {
  position: absolute; left: 0; top: 50%;
  width: 100%; height: 2px; margin-top: -1px;
  border-radius: 2px;
  background: currentColor;
  transition: transform 0.3s var(--ease-out);
}
.nav-toggle-bars span:nth-child(1) { transform: translateY(-4px); }
.nav-toggle-bars span:nth-child(2) { transform: translateY(4px); }
.nav-toggle[aria-expanded="true"] .nav-toggle-bars span:nth-child(1) { transform: rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle-bars span:nth-child(2) { transform: rotate(-45deg); }

/* Drop-down panel under the header. Fixed like the header itself so it stays
   put while the page scrolls; closed state keeps it out of the tab order. */
.mobile-nav {
  position: fixed;
  /* Clears the header in both its states (88-90px tall at the top of the
     page, 84px to its bottom edge once collapsed into the floating pill). */
  top: 98px; left: 14px; right: 14px;
  z-index: 49;
  display: none;
  flex-direction: column;
  gap: 6px;
  padding: 14px;
  box-sizing: border-box;
  border-radius: var(--radius-xl);
  background: rgba(255,255,255,0.94);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  box-shadow: 0 18px 50px -18px rgba(16,29,51,0.35);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-10px);
  transition: opacity 0.25s var(--ease-out), transform 0.25s var(--ease-out), visibility 0.25s;
}
.hero-header.scrolled ~ .mobile-nav { top: 92px; }
.mobile-nav.open { opacity: 1; visibility: visible; transform: none; }
/* Tablets keep the header CTA, so the panel only carries the links and can
   hang under the hamburger instead of stretching across the screen. */
@media (min-width: 601px) {
  .mobile-nav { left: auto; width: 300px; right: 24px; }
  .mobile-nav-cta { display: none; }
}
.mobile-nav-links { display: flex; flex-direction: column; }
.mobile-nav-links a {
  display: flex; align-items: center;
  min-height: 48px;
  padding: 0 14px;
  border-radius: var(--radius-lg);
  font-size: 17px; font-weight: 600;
  color: var(--ink-900);
  transition: background-color 0.2s var(--ease-out);
}
.mobile-nav-links a:hover, .mobile-nav-links a:active { background: rgba(16,29,51,0.06); color: var(--ink-900); }
.mobile-nav-cta { margin-top: 8px; }
.nav-backdrop {
  position: fixed; inset: 0;
  z-index: 48;
  display: none;
  background: rgba(16,29,51,0.28);
  opacity: 0;
  /* Closed it still covers the page, so it must not eat taps meant for the
     content underneath. */
  visibility: hidden;
  pointer-events: none;
  /* Stops the page scrolling under the open menu on iOS, where the body
     overflow lock alone is not always enough. */
  touch-action: none;
  transition: opacity 0.25s var(--ease-out), visibility 0.25s;
}
.nav-backdrop.open { opacity: 1; visibility: visible; pointer-events: auto; }
/* Page scroll is locked while the menu is open (set in js/site.js). */
body.nav-open { overflow: hidden; }
@media (prefers-reduced-motion: reduce) {
  .mobile-nav, .nav-backdrop, .nav-toggle-bars span { transition: none; }
}

.hero-content {
  position: relative; z-index: 2;
  flex: 1;
  display: flex; flex-direction: column; justify-content: center;
}
.hero h1 {
  font-family: var(--font-display);
  font-size: 58px;
  line-height: 1.06;
  letter-spacing: -0.025em;
  color: #101D33;
  margin: 0 0 24px;
  /* Wide enough that "Lämmitys- ja energia-alan" holds one line; the second
     line ("yrityksesi … huipulle") is a nowrap group and sets its own width. */
  max-width: 820px;
  text-wrap: pretty;
}
.rot-word {
  display: inline-grid;
  white-space: nowrap;
  justify-items: center;
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 400;
  /* Keep one stable compositor layer for the word rotation. Without this the
     word-in animation promotes/demotes a layer every 2.6 s, and mid-scroll
     churn repaints the CTA row below with stale gradient patches. */
  will-change: transform;
}
.rot-word > span { grid-area: 1 / 1; visibility: hidden; }
.rot-word > span.active { visibility: visible; animation: word-in 0.45s cubic-bezier(0.16,1,0.3,1) both; }
.hero-lead {
  font-size: 19px; line-height: 1.6;
  color: #101D33;
  max-width: 640px;
  margin: 0 0 36px;
  text-wrap: pretty;
  font-weight: 500;
}
.hero-ctas { display: flex; gap: 14px; flex-wrap: wrap; }
.hero-mountain {
  position: absolute;
  bottom: -7vh;
  /* Anchor to the content column, not the viewport edge, so the peak keeps
     the same distance from the headline on wide screens. */
  left: calc(50% + 330px);
  height: 68vh; width: auto;
  transform: translate(-50%, 0);
  /* fill "backwards", not "both": a forwards-filling transform animation keeps
     the image on a permanent compositor layer, which made scrolling leave a
     stale button-shaped ghost over the hero gradient in Chrome. */
  animation: hero-rise 1.4s cubic-bezier(0.16,1,0.3,1) 0.2s backwards;
  pointer-events: none;
}
.hero-fade {
  position: absolute; left: 0; right: 0; bottom: 0;
  height: 220px;
  /* Reaches full opacity at 70% so the bottom band is solid, not see-through */
  background: linear-gradient(180deg, rgba(244,245,248,0) 0%, var(--surface-1) 85%, var(--surface-1) 100%);
  pointer-events: none;
}

/* ---------- Section headers ---------- */
.eyebrow {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-brand);
  margin-bottom: 14px;
}
h2 {
  font-family: var(--font-display);
  font-size: 38px;
  letter-spacing: -0.02em;
  line-height: 1.15;
  color: var(--text-strong);
  margin: 0;
  max-width: 640px;
}
.section-head {
  display: grid;
  grid-template-columns: 1.1fr 1fr;
  gap: 60px;
  align-items: start;
  margin-bottom: 60px;
}
.section-head h2 { max-width: 560px; }
.section-head-lead {
  font-size: 17px; line-height: 1.6;
  color: #101D33;
  max-width: 460px;
  margin: 0;
  justify-self: end;
  align-self: end;
  text-wrap: pretty;
  font-weight: 500;
}

/* ---------- Ongelma ---------- */
.section-problem { padding-top: 130px; padding-bottom: 130px; }
.problem-cards { display: flex; gap: 20px; align-items: stretch; }
.problem-card {
  flex-grow: 1.05; flex-basis: 0; min-width: 0;
  box-sizing: border-box;
  border-radius: var(--radius-xl);
  padding: 30px;
  display: flex; flex-direction: column; justify-content: space-between;
  gap: 24px;
  height: 300px;
}
.problem-card h3 { font-size: 19px; margin: 0; max-width: 320px; }
.problem-card p { margin: 0; max-width: 320px; font-size: 15px; line-height: 1.55; font-weight: 500; }
.problem-card-wide {
  flex-grow: 1.8;
  background: linear-gradient(-30deg, #eef3fb 0%, #e7e9f6 48%, #cdd2ec 78%, #f0d3da 115%);
  position: relative;
  overflow: hidden;
}
.problem-card-wide h3, .problem-card-wide p {
  color: var(--text-strong);
  position: relative;
  z-index: 1;
  /* Graphic slot occupies the right 52% of the card; keep text clear of it
     at every viewport width. */
  max-width: min(320px, calc(62% - 40px));
}
.problem-graphic { position: absolute; top: 0; right: -6%; bottom: 0; width: 60%; }
.problem-graphic img { width: 100%; height: 100%; object-fit: contain; object-position: center bottom; display: block; }
.problem-card-dark { background: var(--surface-dark); }
.problem-card-dark h3, .problem-card-dark p { color: var(--text-inverse); }

/* ---------- Ratkaisu ---------- */
.section-solution { padding: 20px 0 40px; }
.section-head-solution { align-items: end; margin-bottom: 48px; }
.section-head-solution .section-head-title { padding-bottom: 40px; }
.section-head-solution .section-head-lead { align-self: auto; }
.solution-grid {
  display: grid;
  grid-template-columns: 1fr 1.25fr;
  gap: 40px;
  align-items: center;
}
.solution-cards { display: flex; flex-direction: column; gap: 16px; }
.sol-card {
  position: relative;
  cursor: pointer;
  padding: 24px 28px;
  border-radius: var(--radius-lg);
  background: transparent;
  border: 1px solid transparent;
  transition: background-color 0.2s var(--ease-out), border-color 0.2s var(--ease-out);
}
.sol-card.active { background: rgba(255,255,255,0.55); }
.sol-edge {
  position: absolute; inset: -1px;
  clip-path: inset(0 calc(100% - 24px) 0 0);
  opacity: 0;
  -webkit-mask-image: linear-gradient(180deg, transparent 3px, #000 13px, #000 calc(100% - 13px), transparent calc(100% - 3px));
  mask-image: linear-gradient(180deg, transparent 3px, #000 13px, #000 calc(100% - 13px), transparent calc(100% - 3px));
  pointer-events: none;
  transition: opacity 0.2s var(--ease-out);
}
.sol-card.active .sol-edge { opacity: 1; }
.sol-edge-grad {
  position: absolute; inset: 0;
  box-sizing: border-box;
  border-radius: var(--radius-lg);
  padding: 3px;
  background: linear-gradient(180deg, var(--arctic-500), var(--peri-400));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
}
.sol-card-head { display: flex; gap: 12px; align-items: center; margin-bottom: 10px; }
.sol-icon {
  width: 34px; height: 34px;
  border-radius: 10px;
  flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--arctic-100);
  color: var(--arctic-600);
  transition: background-color 0.2s var(--ease-out), color 0.2s var(--ease-out);
}
.sol-card.active .sol-icon { background: var(--surface-dark); color: #ffffff; }
.sol-card h3 {
  font-size: 18px; margin: 0;
  color: var(--text-muted);
  transition: color 0.2s var(--ease-out);
}
.sol-card p {
  margin: 0; font-size: 15px; line-height: 1.55;
  color: var(--text-muted);
  transition: color 0.2s var(--ease-out);
  font-weight: 500;
}
.sol-card.active h3, .sol-card.active p { color: var(--text-strong); }
.solution-visual {
  position: relative;
  height: 460px;
  border-radius: var(--radius-2xl);
  overflow: hidden;
  background: linear-gradient(160deg, var(--arctic-50) 0%, var(--peri-100) 48%, var(--peri-200) 78%, var(--rose-200) 115%);
}
.sol-panel {
  position: absolute; top: 36px; right: 36px; bottom: 36px; left: 36px;
  opacity: 0;
  pointer-events: none;
  /* No fade-out: when a panel loses .active its entrance animations detach
     and every element snaps to its end state, so a visible fade would flash
     the finished graphic. Hide instantly, fade only on the way in. */
  transition: none;
}
.sol-panel.active { opacity: 1; pointer-events: auto; transition: opacity 0.25s var(--ease-out); }

/* ---------- Ratkaisu: in-panel UI graphics ----------
   Each panel holds a small fake-UI composition (search results, service page,
   tracking dashboard) built in plain HTML/CSS. Elements are fully visible by
   default; entrance animations are layered on only for motion-friendly users
   once the visual has scrolled into view (.solution-visual.in-view, set in
   site.js), and they re-run every time a card re-activates its panel. */
.sol-mock {
  width: 100%; max-width: 440px; height: 100%;
  margin: 0 auto;
  display: flex; flex-direction: column; justify-content: center;
  gap: 12px;
  font-family: var(--font-sans);
}
.mock-card {
  background: var(--white);
  border-radius: 16px;
  box-shadow: 0 14px 34px -22px rgba(16, 29, 51, 0.4);
}
.mock-skel { height: 7px; border-radius: 4px; background: var(--ink-100); }

/* Panel 0: search visibility */
.mock-searchbar {
  display: flex; align-items: center; gap: 10px;
  height: 46px; padding: 0 18px; box-sizing: border-box;
  background: var(--white); border-radius: var(--radius-pill);
  box-shadow: 0 14px 34px -22px rgba(16, 29, 51, 0.4);
  font-size: 13px; font-weight: 600; color: var(--ink-800);
}
.mock-search-ico { color: var(--ink-400); }
.mock-search-ico svg { width: 16px; height: 16px; }
.mock-query { display: inline-block; overflow: hidden; white-space: nowrap; min-width: 0; }
.mock-caret { flex: none; width: 2px; height: 16px; margin-left: -6px; border-radius: 1px; background: var(--arctic-500); }
.mock-ai { padding: 12px 16px; border: 1px solid var(--peri-200); }
.mock-ai-head {
  display: flex; align-items: center; gap: 7px;
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--arctic-600);
}
.mock-ai-head svg { width: 14px; height: 14px; }
.mock-ai-text { margin: 7px 0 0; font-size: 12.5px; line-height: 1.5; font-weight: 500; color: var(--ink-600); }
.mock-ai-text strong { color: var(--ink-900); font-weight: 700; }
.mock-serp { display: flex; flex-direction: column; gap: 8px; }
.mock-result { display: flex; align-items: center; gap: 12px; padding: 10px 14px; border-radius: 14px; }
.mock-result-top { border: 1.5px solid var(--arctic-400); }
.mock-result-dim { background: rgba(255, 255, 255, 0.55); }
.mock-rank {
  flex: none; width: 22px; height: 22px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--arctic-600); color: var(--white);
  font-size: 11px; font-weight: 700;
}
.mock-rank-dim { background: var(--ink-100); color: var(--ink-500); }
.mock-result-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 5px; }
.mock-result-title { font-size: 12.5px; font-weight: 700; color: var(--ink-900); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mock-result-url { font-size: 11px; font-weight: 600; color: var(--ink-400); }

/* Panel 1: content that converts */
.sol-mock-content { position: relative; }
.mock-chips { display: flex; gap: 8px; justify-content: center; }
.mock-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px; border-radius: var(--radius-pill);
  background: var(--white);
  box-shadow: 0 10px 24px -18px rgba(16, 29, 51, 0.45);
  font-size: 11.5px; font-weight: 700; color: var(--ink-700);
}
.mock-chip svg { width: 13px; height: 13px; color: var(--arctic-600); }
.mock-page { position: relative; padding: 18px 20px 16px; }
/* Dim scrim over the page content while the success pop-up is showing;
   sits above the card content (z 1) but under the cursor (2) and pop-up (3). */
.mock-page::after {
  content: '';
  position: absolute; inset: 0;
  border-radius: inherit;
  background: rgba(16, 29, 51, 0.14);
  opacity: 0;
  pointer-events: none;
  z-index: 1;
}
.mock-page-kicker { font-size: 10px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--arctic-600); }
.mock-page-title { margin: 4px 0 12px; font-size: 16px; font-weight: 700; color: var(--ink-900); }
.mock-pline { margin: 7px 0; transform-origin: left center; }
.mock-page-sub { margin: 13px 0 8px; font-size: 12.5px; font-weight: 700; color: var(--ink-800); }
.mock-page-btn {
  display: inline-flex; margin-top: 13px; padding: 8px 16px;
  border-radius: var(--radius-pill);
  background: #33373f; color: var(--white);
  font-size: 12px; font-weight: 600;
}
/* Success pop-up: centers over the page card once the cursor "clicks" the CTA */
.mock-toast {
  position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  z-index: 3;
  display: flex; align-items: center; gap: 11px;
  padding: 13px 20px 13px 15px; border-radius: 16px;
  border: 1px solid var(--ink-050);
  box-shadow: 0 24px 50px -24px rgba(16, 29, 51, 0.5);
}
/* Fake cursor: rides in from the lower right and clicks the CTA button.
   Positioned so the arrow tip lands on the button; hidden unless animated. */
.mock-cursor {
  position: absolute; left: 64px; bottom: 10px;
  z-index: 2;
  width: 22px; height: 22px;
  opacity: 0;
  filter: drop-shadow(0 2px 4px rgba(16, 29, 51, 0.35));
  pointer-events: none;
}
.mock-cursor svg { width: 100%; height: 100%; display: block; }
@media (prefers-reduced-motion: reduce) {
  /* Static view: no cursor, and the pop-up rests beside the card instead of
     covering it mid-screen. */
  .mock-cursor { display: none; }
  .mock-toast { left: auto; top: auto; right: -4px; bottom: -8px; transform: none; }
}
.mock-toast-ico {
  flex: none; width: 28px; height: 28px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--success-100); color: var(--success-500);
}
.mock-toast-ico svg { width: 15px; height: 15px; }
.mock-toast-title { font-size: 12.5px; font-weight: 700; color: var(--ink-900); }
.mock-toast-sub { font-size: 11px; font-weight: 600; color: var(--ink-500); }

/* Panel 2: tracking dashboard */
.mock-dash { padding: 16px 18px 14px; }
.mock-dash-head { display: flex; align-items: center; justify-content: space-between; }
.mock-dash-title { font-size: 13px; font-weight: 700; color: var(--ink-900); }
.mock-dash-range { padding: 3px 10px; border-radius: var(--radius-pill); background: var(--surface-2); font-size: 10.5px; font-weight: 700; color: var(--ink-500); }
.mock-stats { display: flex; gap: 26px; margin: 10px 0 14px; }
.mock-stat { display: flex; flex-direction: column; }
.mock-stat-num { font-size: 22px; font-weight: 700; line-height: 1.1; color: var(--ink-900); }
.mock-stat-label { font-size: 10.5px; font-weight: 600; color: var(--ink-500); }
.mock-chart { display: flex; align-items: flex-end; gap: 10px; height: 92px; padding-top: 18px; box-sizing: content-box; border-bottom: 1px solid var(--ink-100); }
.mock-bar { position: relative; flex: 1; height: 100%; display: flex; align-items: flex-end; }
.mock-bar-fill { display: block; width: 100%; height: var(--h); border-radius: 4px 4px 0 0; background: var(--arctic-300); transform-origin: bottom center; }
.mock-bar-now .mock-bar-fill { background: var(--arctic-600); }
.mock-bar-val { position: absolute; bottom: calc(var(--h) + 5px); left: 50%; transform: translateX(-50%); font-size: 10.5px; font-weight: 700; color: var(--arctic-700); }
.mock-chart-axis { display: flex; gap: 10px; margin-top: 5px; }
.mock-chart-axis span { flex: 1; text-align: center; font-size: 9px; font-weight: 600; color: var(--ink-400); }
.mock-feed { display: flex; flex-direction: column; gap: 8px; }
.mock-feed-item { display: flex; align-items: center; gap: 10px; padding: 9px 14px; border-radius: 14px; }
.mock-feed-ico {
  flex: none; width: 28px; height: 28px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--arctic-50); color: var(--arctic-600);
}
.mock-feed-ico svg { width: 14px; height: 14px; }
.mock-feed-body { flex: 1; min-width: 0; }
.mock-feed-title { font-size: 12px; font-weight: 700; color: var(--ink-900); }
.mock-feed-sub { font-size: 10.5px; font-weight: 600; color: var(--ink-500); }
.mock-feed-time { font-size: 10px; font-weight: 600; color: var(--ink-400); white-space: nowrap; }

/* Entrance choreography: only with motion allowed and the visual in view.
   Re-activating a panel re-applies .active, so each sequence replays. */
@keyframes mock-pop { from { opacity: 0; transform: translateY(14px) scale(0.96); } to { opacity: 1; transform: none; } }
@keyframes mock-rise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@keyframes mock-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes mock-type { from { max-width: 0; } to { max-width: 320px; } }
@keyframes mock-blink { 0%, 45% { opacity: 1; } 50%, 95% { opacity: 0; } 100% { opacity: 1; } }
@keyframes mock-grow-x { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes mock-grow-y { from { transform: scaleY(0); } to { transform: scaleY(1); } }
@keyframes mock-popup-in {
  from { opacity: 0; transform: translate(-50%, -50%) scale(0.7); }
  60% { opacity: 1; transform: translate(-50%, -50%) scale(1.05); }
  to { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}
@keyframes mock-cursor-in {
  0% { transform: translate(190px, 96px); }
  74% { transform: translate(0, 0) scale(1); }
  82% { transform: translate(0, 0) scale(0.82); }
  92%, 100% { transform: translate(0, 0) scale(1); }
}
@keyframes mock-cursor-show {
  0% { opacity: 0; }
  20%, 100% { opacity: 1; }
}
@keyframes mock-btn-press {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(0.93); }
}
@media (prefers-reduced-motion: no-preference) {
  .solution-visual.in-view .sol-panel.active .mock-searchbar { animation: mock-pop 0.5s var(--ease-out) both; }
  .solution-visual.in-view .sol-panel.active .mock-query { animation: mock-type 1.2s steps(24, end) 0.35s both; }
  .solution-visual.in-view .sol-panel.active .mock-caret { animation: mock-blink 1.1s step-end infinite; }
  .solution-visual.in-view .sol-panel.active .mock-ai { animation: mock-rise 0.5s var(--ease-out) 1.5s both; }
  .solution-visual.in-view .sol-panel.active .mock-serp .mock-result:nth-child(1) { animation: mock-rise 0.45s var(--ease-out) 1.8s both; }
  .solution-visual.in-view .sol-panel.active .mock-serp .mock-result:nth-child(2) { animation: mock-rise 0.45s var(--ease-out) 1.95s both; }
  .solution-visual.in-view .sol-panel.active .mock-serp .mock-result:nth-child(3) { animation: mock-rise 0.45s var(--ease-out) 2.1s both; }
  .solution-visual.in-view .sol-panel.active .mock-chip:nth-child(1) { animation: mock-pop 0.45s var(--ease-out) 0s both; }
  .solution-visual.in-view .sol-panel.active .mock-chip:nth-child(2) { animation: mock-pop 0.45s var(--ease-out) 0.1s both; }
  .solution-visual.in-view .sol-panel.active .mock-chip:nth-child(3) { animation: mock-pop 0.45s var(--ease-out) 0.2s both; }
  .solution-visual.in-view .sol-panel.active .mock-page { animation: mock-rise 0.5s var(--ease-out) 0.25s both; }
  .solution-visual.in-view .sol-panel.active .mock-pline { animation: mock-grow-x 0.5s var(--ease-out) var(--d, 0.5s) both; }
  .solution-visual.in-view .sol-panel.active .mock-page-btn { animation: mock-pop 0.45s var(--ease-out) 1.1s both, mock-btn-press 0.3s var(--ease-out) 2.62s; }
  .solution-visual.in-view .sol-panel.active .mock-cursor { animation: mock-cursor-in 1.5s var(--ease-out) 1.45s both, mock-cursor-show 1.5s linear 1.45s both; }
  .solution-visual.in-view .sol-panel.active .mock-toast { animation: mock-popup-in 0.5s var(--ease-out) 3s both; }
  .solution-visual.in-view .sol-panel.active .mock-page::after { animation: mock-fade 0.45s var(--ease-out) 2.95s both; }
  .solution-visual.in-view .sol-panel.active .mock-dash { animation: mock-rise 0.5s var(--ease-out) both; }
  .solution-visual.in-view .sol-panel.active .mock-stat:nth-child(1) { animation: mock-fade 0.6s var(--ease-out) 0.3s both; }
  .solution-visual.in-view .sol-panel.active .mock-stat:nth-child(2) { animation: mock-fade 0.6s var(--ease-out) 0.45s both; }
  .solution-visual.in-view .sol-panel.active .mock-bar-fill { animation: mock-grow-y 0.6s cubic-bezier(0.22, 1, 0.36, 1) var(--d, 0.45s) both; }
  .solution-visual.in-view .sol-panel.active .mock-bar-val { animation: mock-fade 0.4s var(--ease-out) 1.15s both; }
  .solution-visual.in-view .sol-panel.active .mock-chart-axis { animation: mock-fade 0.5s var(--ease-out) 0.8s both; }
  .solution-visual.in-view .sol-panel.active .mock-feed-item:nth-child(1) { animation: mock-rise 0.45s var(--ease-out) 1.15s both; }
  .solution-visual.in-view .sol-panel.active .mock-feed-item:nth-child(2) { animation: mock-rise 0.45s var(--ease-out) 1.35s both; }
}
@media (max-width: 900px) {
  .sol-panel { top: 22px; right: 22px; bottom: 22px; left: 22px; }
  .sol-mock { gap: 8px; }
  .mock-ai-text { font-size: 11.5px; }
  .mock-serp .mock-result-dim:last-child { display: none; }
  .mock-page { padding: 14px 16px 13px; }
  .mock-page-title { font-size: 14px; margin-bottom: 9px; }
  .mock-pline { margin: 6px 0; }
  .mock-chart { height: 64px; }
  .mock-stats { margin: 8px 0 10px; }
  .mock-stat-num { font-size: 18px; }
  .mock-feed .mock-feed-item:last-child { display: none; }
}
@media (max-width: 600px) {
  .mock-searchbar { font-size: 12px; padding: 0 14px; }
  .mock-result-title { font-size: 11.5px; }
  .mock-chart-axis span { font-size: 8px; }
}

/* ---------- Prosessi ---------- */
.section-process { padding-top: 40px; padding-bottom: 55px; }
/* Heading row: eyebrow + h2 on the left, CTA bottom-aligned on the right;
   wraps under the heading on narrow screens. */
.process-head {
  display: flex; justify-content: space-between;
  align-items: flex-end; gap: 24px; flex-wrap: wrap;
  margin-bottom: 48px;
}
.process-head h2 { margin-bottom: 0; }
.process-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
  align-items: start;
}
.process-card {
  background: var(--surface-dark);
  border-radius: var(--radius-xl);
  padding: 32px;
}
.process-card-2 { margin-top: 110px; }
.process-card-3 { margin-top: 220px; }
.process-days {
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 0.14em;
  color: var(--arctic-300);
  margin-bottom: 16px;
  font-weight: 400;
}
.process-card h3 { font-size: 22px; margin: 0 0 40px; color: var(--text-inverse); }
.process-card p { margin: 0; font-size: 15px; line-height: 1.55; color: #F2F5FB; font-weight: 500; }

/* ---------- Miksi me (vertailu) ---------- */
.section-compare { padding-bottom: 100px; }
.section-compare h2 { margin-bottom: 18px; }
.compare-lead {
  font-size: 17px; line-height: 1.6;
  color: #101D33;
  max-width: 620px;
  margin: 0 0 48px;
  text-wrap: pretty;
  font-weight: 500;
}
.compare-row {
  display: grid;
  grid-template-columns: 180px 1fr 1fr;
  column-gap: 40px;
  align-items: start;
  padding: 32px 0;
  border-bottom: 1px solid var(--border-subtle);
}
.compare-header { align-items: center; padding: 20px 0; }
.compare-col-label { font-size: 17px; font-weight: 600; color: var(--text-muted); }
.compare-logo { display: flex; align-items: center; }
.compare-logo img { height: 30px; width: auto; }
.compare-topic { font-family: var(--font-display); font-size: 20px; font-weight: 600; color: var(--text-strong); }
.compare-title { font-size: 16px; font-weight: 700; color: var(--text-strong); margin-bottom: 6px; }
/* Only shown once the row stacks (below 900px), where the column header has
   scrolled out of reach and each block has to say who it describes. */
.compare-cell-label { display: none; }
.compare-row p { margin: 0; font-size: 15px; line-height: 1.55; font-weight: 500; color: var(--text-muted); }

/* ---------- Hinnoittelu ---------- */
.section-pricing { padding-bottom: 100px; }
.section-pricing h2 { margin-bottom: 18px; }
.pricing-lead {
  font-size: 17px; line-height: 1.6;
  color: #101D33;
  max-width: 560px;
  margin: 0 0 48px;
  text-wrap: pretty;
  font-weight: 500;
}
.pricing-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 20px;
  align-items: stretch;
}
.price-card {
  background: var(--surface-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xl);
  padding: 36px 32px;
  display: flex; flex-direction: column;
}
.price-tag {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: 10px;
}
.price-card h3 {
  font-family: var(--font-display);
  font-size: 24px;
  letter-spacing: -0.015em;
  margin: 0 0 14px;
  color: var(--text-strong);
}
.price-line { display: flex; align-items: baseline; gap: 6px; margin-bottom: 8px; }
.price-amount {
  font-family: var(--font-display);
  font-size: 44px;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--text-strong);
}
.price-period { font-size: 15px; color: var(--text-muted); font-weight: 500; white-space: nowrap; }
.price-old {
  font-family: var(--font-display);
  font-size: 20px;
  font-weight: 600;
  color: var(--text-subtle);
  text-decoration: line-through;
}
.price-founder-note {
  display: inline-block;
  font-size: 13px;
  font-weight: 600;
  color: var(--arctic-600);
  margin-bottom: 10px;
}
.price-founder-note:hover { color: var(--arctic-700); }
.price-card-dark .price-old { color: #7d8db0; }
.price-card-dark .price-founder-note { color: var(--arctic-300); }
.price-card-dark .price-founder-note:hover { color: var(--arctic-200); }
.price-desc { margin: 0 0 22px; font-size: 15px; line-height: 1.55; color: var(--text-muted); font-weight: 500; }
.price-includes { font-size: 13px; font-weight: 600; color: var(--text-strong); margin-bottom: 12px; }
.price-features {
  list-style: none;
  margin: 0 0 30px;
  padding: 0;
  display: flex; flex-direction: column; gap: 12px;
}
.price-features li { display: flex; gap: 10px; align-items: flex-start; }
.price-features .check { color: var(--arctic-500); flex-shrink: 0; margin-top: 1px; }
.price-features li > span:last-child { font-size: 15px; line-height: 1.5; color: var(--text-body); font-weight: 500; }
.price-cta { margin-top: auto; }
/* Pricing CTAs wrap to two lines gracefully */
.section-pricing .btn { white-space: normal; height: auto; min-height: 46px; padding: 11px 18px; line-height: 1.3; text-align: center; }

.price-card-dark { background: var(--surface-dark); border: none; }
.price-card-dark h3 { color: var(--text-inverse); }
.price-card-dark .price-amount { color: var(--text-inverse); }
.price-card-dark .price-period { color: #C9D6EC; }
.price-card-dark .price-desc { color: #F2F5FB; }
.price-card-dark .price-includes { color: var(--text-inverse); }
.price-card-dark .price-features .check { color: var(--arctic-300); }
.price-card-dark .price-features li > span:last-child { color: #F2F5FB; }

.price-badge-row { display: flex; margin-bottom: 10px; }
.badge-popular {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-950);
  background: var(--arctic-300);
  padding: 6px 12px;
  border-radius: var(--radius-pill);
  display: inline-flex; align-items: center; gap: 6px;
}
.pricing-note {
  margin: 20px 0 0;
  font-size: 13px; line-height: 1.55;
  color: var(--text-muted);
  font-weight: 500;
  text-align: center;
}

.founder-offer {
  margin-top: 40px;
  background: var(--arctic-50);
  border: 1px solid var(--arctic-100);
  border-radius: var(--radius-xl);
  padding: 36px 40px;
  display: grid;
  grid-template-columns: minmax(0,1fr) minmax(0,1fr);
  gap: 36px;
  align-items: stretch;
}
.founder-offer .price-badge-row { margin-bottom: 14px; }
.badge-founder {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-inverse);
  background: var(--surface-dark);
  padding: 6px 12px;
  border-radius: var(--radius-pill);
}
.founder-offer h3 {
  font-family: var(--font-display);
  font-size: 26px;
  letter-spacing: -0.015em;
  margin: 0 0 12px;
  color: var(--text-strong);
}
.founder-offer p {
  margin: 0 0 22px;
  font-size: 15px; line-height: 1.6;
  color: var(--text-body);
  font-weight: 500;
  text-wrap: pretty;
}
.founder-features { margin: 0; justify-content: center; height: 100%; }

/* ---------- UKK ---------- */
.section-faq {
  padding-bottom: 100px;
  display: grid;
  grid-template-columns: 1.1fr 1.4fr;
  gap: 60px;
  align-items: stretch;
}
.faq-intro { display: flex; flex-direction: column; }
.faq-intro h2 { margin-bottom: 18px; max-width: 420px; }
.faq-intro p {
  font-size: 17px; line-height: 1.6;
  color: #101D33;
  max-width: 420px;
  margin: 0;
  text-wrap: pretty;
  font-weight: 500;
}
/* Fixed height: the image must not grow when an accordion answer opens. */
.faq-image { width: 100%; flex: none; height: 600px; margin-top: auto; padding-top: 0; box-sizing: border-box; }
.faq-image img { width: 100%; height: 100%; object-fit: contain; object-position: left bottom; display: block; }
/* Reserve space for the tallest open answer (item 6, liidipalvelut) so the
   section keeps one height and content below never shifts. */
.faq-list { padding-top: 40px; display: flex; flex-direction: column; gap: 12px; min-height: 691px; }
@media (min-width: 901px) and (max-width: 1199px) {
  .faq-list { min-height: 800px; }
}
.faq-item {
  background: var(--white);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: none;
  transition: box-shadow var(--dur-base) var(--ease-out);
}
.faq-item.open { box-shadow: var(--shadow-sm); }
.faq-item button {
  width: 100%;
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px;
  padding: 18px 22px;
  border: none;
  background: none;
  cursor: pointer;
  text-align: left;
  font-family: var(--font-display);
  font-size: var(--text-md);
  font-weight: var(--fw-semibold);
  color: var(--text-strong);
}
.faq-plus {
  flex-shrink: 0;
  display: inline-flex;
  color: var(--arctic-500);
  transform: rotate(0);
  transition: transform 0.2s var(--ease-out);
}
.faq-item.open .faq-plus { transform: rotate(45deg); }
.faq-body {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.3s var(--ease-out);
}
.faq-item.open .faq-body { grid-template-rows: 1fr; }
.faq-body-inner { overflow: hidden; min-height: 0; }
.faq-answer {
  padding: 0 22px 20px;
  color: var(--text-body);
  font-size: var(--text-base);
  line-height: var(--lh-relaxed);
  font-weight: 500;
}

/* ---------- Yhteys ---------- */
.section-contact { padding-bottom: 100px; }
.contact-panel {
  background: var(--grad-dawn);
  border-radius: var(--radius-2xl);
  box-shadow: var(--shadow-lg);
  padding: 64px 56px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 60px;
  align-items: center;
}
.contact-panel h2 {
  font-size: 44px;
  letter-spacing: -0.025em;
  line-height: 1.08;
  color: var(--ink-950);
  margin: 0 0 18px;
}
.contact-accent { color: var(--arctic-700); }
.contact-lead {
  font-size: 17px; line-height: 1.6;
  color: var(--ink-800);
  max-width: 440px;
  margin: 0;
  text-wrap: pretty;
  font-weight: 500;
}
.contact-form {
  background: var(--surface-card);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-xl);
  padding: 36px;
  display: flex; flex-direction: column; gap: 18px;
}
.field { display: flex; flex-direction: column; gap: 6px; }
.field > label { font-size: var(--text-sm); font-weight: var(--fw-semibold); color: var(--text-strong); }
.field input[type="text"],
.field input[type="email"],
.field input[type="tel"] {
  width: 100%;
  height: 48px;
  padding: 0 18px;
  box-sizing: border-box;
  font-family: var(--font-sans);
  font-size: var(--text-base);
  color: var(--text-strong);
  background: var(--white);
  border: 1.5px solid var(--border-default);
  border-radius: var(--radius-pill);
  outline: none;
  transition: border-color var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}
.field textarea {
  width: 100%;
  padding: 14px 18px;
  box-sizing: border-box;
  font-family: var(--font-sans);
  font-size: var(--text-base);
  line-height: var(--lh-normal);
  color: var(--text-strong);
  background: var(--white);
  border: 1.5px solid var(--border-default);
  border-radius: var(--radius-lg);
  outline: none;
  resize: vertical;
  transition: border-color var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}
.field input:focus, .field textarea:focus { border-color: var(--arctic-500); box-shadow: var(--shadow-focus); }
.field.invalid input, .field.invalid textarea { border-color: var(--danger-500); box-shadow: none; }
.field-error {
  font-size: var(--text-xs);
  color: var(--danger-500);
  /* Enters from display:none, so keyframes (which run on render) rather
     than a transition (which can't fire from display:none). Restarting on
     every failed submit is fine; exit stays instant on purpose. */
  animation: error-in var(--dur-base) var(--ease-out);
}
@keyframes error-in {
  from { opacity: 0; transform: translateY(-2px); }
}
/* Submit failure notice under the button (network / HubSpot down). */
.form-error {
  margin: 0;
  font-size: var(--text-xs);
  color: var(--danger-500);
  animation: error-in var(--dur-base) var(--ease-out);
}
.form-error a { color: inherit; text-decoration: underline; }
/* Honeypot: taken out of the visual flow but still submitted by bots that
   fill every field. Not display:none — some bots skip hidden inputs. */
.field-hp {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.field-privacy { gap: 6px; }
.privacy-label {
  display: flex; align-items: flex-start; gap: 10px;
  cursor: pointer;
  font-size: 14px; line-height: 1.5;
  color: var(--text-muted);
  font-weight: 500;
}
.privacy-label a { color: var(--arctic-600); text-decoration: underline; }
.privacy-label input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  width: 18px; height: 18px;
  margin: 1px 0 0;
  flex-shrink: 0;
  cursor: pointer;
  border-radius: 50%;
  border: 1.5px solid var(--border-default);
  background: var(--white);
  transition: background-color 0.2s var(--ease-out), border-color 0.2s var(--ease-out);
}
.privacy-label input[type="checkbox"]:checked {
  border-color: var(--arctic-500);
  background-color: var(--arctic-500);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E");
  background-size: 11px 11px;
  background-position: center;
  background-repeat: no-repeat;
}
.privacy-label input[type="checkbox"]:focus-visible { outline: none; box-shadow: var(--shadow-focus); }
.field-privacy.invalid .privacy-label input[type="checkbox"] { border-color: var(--danger-500); }
.privacy-error { padding-left: 28px; font-weight: 500; font-size: 12px; }

.contact-success {
  background: var(--surface-card);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-xl);
  padding: 48px 40px;
  text-align: center;
}
.success-icon {
  width: 52px; height: 52px;
  border-radius: var(--radius-circle);
  background: var(--success-100);
  color: var(--success-500);
  display: inline-flex; align-items: center; justify-content: center;
  margin-bottom: 16px;
}
.contact-success h3 { font-family: var(--font-display); font-size: 22px; color: var(--text-strong); margin: 0 0 8px; }
.contact-success p { margin: 0; font-size: 15px; line-height: 1.55; color: var(--text-muted); font-weight: 500; }
/* Success card enters when the submit handler unhides it. Keyframes, not a
   transition: the card comes from display:none, where transitions can't fire
   but animations can. Runs once; the swap is not interruptible. `both` keeps
   the icon at opacity 0 during its delay instead of flashing visible first. */
.contact-success {
  animation: success-in 0.4s var(--ease-out) both;
}
.contact-success .success-icon {
  animation: success-icon-in 0.45s cubic-bezier(0.34, 1.56, 0.64, 1) 0.1s both;
}
@keyframes success-in {
  from { opacity: 0; transform: scale(0.96); }
}
@keyframes success-icon-in {
  from { opacity: 0; transform: scale(0.85); }
}

/* ---------- Legal pages (tietosuojaseloste) ---------- */
.legal-hero {
  position: relative;
  overflow: hidden;
  box-sizing: border-box;
  padding-top: 79px;
  background: var(--grad-dawn);
}
.legal-hero-content { position: relative; z-index: 2; padding-top: 120px; padding-bottom: 180px; }
.legal-hero h1 {
  font-family: var(--font-display);
  font-size: 52px;
  line-height: 1.08;
  letter-spacing: -0.025em;
  color: #101D33;
  margin: 0 0 16px;
  max-width: 680px;
  text-wrap: pretty;
}
.legal-updated {
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-800);
  margin: 0;
}
.legal-hero .hero-fade { height: 140px; }
/* Mountain peeks over the right edge of the legal hero for depth; same
   rise-in entrance as the landing hero, most of the image sits below the
   fold so only the peak shows. */
.legal-mountain {
  position: absolute;
  bottom: -16vh;
  left: calc(50% + 480px);
  height: 54vh; width: auto;
  transform: translate(-50%, 0);
  animation: hero-rise 1.4s cubic-bezier(0.16,1,0.3,1) 0.2s backwards;
  pointer-events: none;
}
.legal-content { max-width: 820px; padding-top: 20px; padding-bottom: 110px; }
.legal-section { margin-top: 56px; }
.legal-section h2 {
  font-size: 27px;
  margin: 0 0 18px;
  max-width: none;
}
.legal-section h3 {
  font-family: var(--font-display);
  font-size: 18px;
  letter-spacing: -0.01em;
  color: var(--text-strong);
  margin: 32px 0 10px;
}
.legal-section p {
  margin: 0 0 16px;
  font-size: 16px;
  line-height: 1.7;
  color: var(--text-body);
  font-weight: 500;
  text-wrap: pretty;
}
.legal-section ul, .legal-section ol {
  margin: 0 0 20px;
  padding: 0 0 0 4px;
  list-style: none;
  display: flex; flex-direction: column; gap: 10px;
}
.legal-section li {
  position: relative;
  padding-left: 26px;
  font-size: 16px;
  line-height: 1.6;
  color: var(--text-body);
  font-weight: 500;
}
.legal-section ul li::before {
  content: "";
  position: absolute;
  left: 4px; top: 0.62em;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--arctic-500);
}
.legal-section ol { counter-reset: legal-alpha; }
.legal-section ol li { counter-increment: legal-alpha; }
.legal-section ol li::before {
  content: counter(legal-alpha, lower-alpha) ".";
  position: absolute;
  left: 0; top: 0;
  font-weight: 700;
  color: var(--arctic-600);
}
.legal-facts { margin: 0; display: flex; flex-direction: column; gap: 12px; }
.legal-facts > div {
  display: grid;
  grid-template-columns: 150px 1fr;
  gap: 16px;
  align-items: baseline;
}
.legal-facts dt {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--text-muted);
  text-transform: uppercase;
}
.legal-facts dd { margin: 0; font-size: 16px; font-weight: 600; color: var(--text-strong); }
@media (max-width: 1250px) {
  .legal-mountain { left: calc(50% + 380px); height: 46vh; bottom: -14vh; }
}
@media (max-width: 900px) {
  .legal-hero h1 { font-size: 38px; }
  .legal-hero-content { padding-top: 75px; padding-bottom: 120px; }
  .legal-facts > div { grid-template-columns: 1fr; gap: 2px; }
  .legal-mountain { left: 85%; height: 32vh; bottom: -10vh; }
}

/* ---------- Footer ---------- */
/* Above the wordmark in the stack: the oversized wordmark is pulled up by a
   negative margin and would otherwise paint over and block the legal links. */
.footer-top { padding-top: 60px; position: relative; z-index: 1; }
.footer-cta-row {
  display: flex; justify-content: space-between;
  gap: 40px; flex-wrap: wrap;
  align-items: flex-start;
  margin-bottom: 44px;
}
.footer-cta-row h2 { font-size: 34px; line-height: 1.2; max-width: 340px; margin: 0; }
.footer-main { display: flex; gap: 40px; align-items: flex-start; }
.footer-cols {
  flex: 1;
  display: grid;
  grid-template-columns: 0.88fr 1.18fr 0.94fr;
  gap: 140px;
  align-items: stretch;
}
/* Placed explicitly: .footer-legal claims row 1 / column 1 below, and auto
   placement would otherwise push the three columns out of their tracks. */
.footer-col { display: flex; flex-direction: column; gap: 12px; grid-row: 1; }
.footer-col:nth-child(1) { grid-column: 1; }
.footer-col:nth-child(2) { grid-column: 2; }
.footer-col:nth-child(3) { grid-column: 3; }
.footer-col-title { font-size: 18px; font-weight: 700; color: var(--text-strong); margin-bottom: 4px; }
.footer-col > div:not(.footer-col-title):not(.footer-legal), .footer-col > a {
  font-size: 15px; color: var(--text-muted); font-weight: 500;
}
.footer-col > a:hover { color: var(--arctic-600); }
/* Shares the first column's grid cell, pinned to its bottom edge, so it keeps
   sitting under the Yritys column and level with the tallest column's last
   line. Smaller screens re-place it as a row of its own. */
.footer-legal { display: flex; align-items: center; gap: 8px; grid-column: 1; grid-row: 1; align-self: end; }
.footer-legal a { font-size: 15px; color: var(--text-muted); font-weight: 500; }
.footer-legal a:hover { color: var(--arctic-600); }
.footer-legal .dot { width: 4px; height: 4px; border-radius: 50%; background: var(--text-subtle); flex-shrink: 0; }
.footer-social { display: flex; gap: 10px; justify-content: flex-end; padding-right: 72px; }
.footer-social a {
  width: 38px; height: 38px;
  border-radius: var(--radius-circle);
  background: var(--white);
  color: var(--arctic-600);
  display: flex; align-items: center; justify-content: center;
  transition: background-color 0.2s var(--ease-out), color 0.2s var(--ease-out);
}
.footer-social a:hover { background: var(--arctic-500); color: #ffffff; }
/* padding-top gives the overflow crop headroom for the scroll-scrubbed
   -8% end lift (8% of the 22vw text ≈ 1.8vw) so ascenders don't clip;
   the matching negative margin keeps the layout position unchanged.
   Flex centering: the text is wider than the viewport, and a centered flex
   item overflows both sides evenly — text-align would dump all the overflow
   on the right. */
.footer-wordmark-wrap { overflow: hidden; display: flex; justify-content: center; padding-top: 2vw; margin-top: calc(-16px - 2vw); pointer-events: none; }
.footer-wordmark {
  font-family: 'Poppins', var(--font-display);
  font-weight: 600;
  /* Slightly wider than the viewport on purpose: the word bleeds off both
     sides, and the page bottom crops the lower part of the letters. */
  font-size: 22vw;
  line-height: 1;
  letter-spacing: -0.03em;
  text-transform: lowercase;
  color: var(--ink-900);
  text-align: center;
  white-space: nowrap;
  /* Deeper bottom crop: only the upper part of the letters stays visible */
  margin-bottom: -0.37em;
  flex: none;
}

/* ---------- Scroll reveal ----------
   Elements opt in with data-reveal="up|scale|pop|zoom|grow|words|lines"; js/site.js adds
   .revealed when they enter the viewport and removes the attribute once the
   transition ends so component transitions (buttons, FAQ shadow) come back.
   Hidden states are gated on html.js so nothing disappears without JS. */
html.js [data-reveal] {
  opacity: 0;
  transform: translateY(24px);
  transition:
    opacity 0.8s cubic-bezier(0.16, 1, 0.3, 1),
    transform 0.8s cubic-bezier(0.16, 1, 0.3, 1);
}
html.js [data-reveal="scale"] { transform: translateY(16px) scale(0.96); }
/* Grow: the footer wordmark's rise + scale + fade as a triggered reveal.
   Used by the Prosessi stairs; each card trips its own threshold, and the
   stair offsets make them fire one by one. Repeatable (data-reveal-repeat):
   the exit runs the same transition in reverse. */
html.js [data-reveal="grow"] { transform: translateY(60px) scale(0.8); }
/* Exit plays the entrance backwards: the un-revealed state carries the
   entrance curve mirrored (slow start, accelerating away). Scoped with
   :not(.revealed) so the entrance itself keeps the base ease-out — CSS
   transitions read the destination state's timing. */
html.js [data-reveal="grow"]:not(.revealed) {
  transition:
    opacity 0.8s cubic-bezier(0.7, 0, 0.84, 0),
    transform 0.8s cubic-bezier(0.7, 0, 0.84, 0);
}
/* Pricing tiers: longer travel than the default 24px so the left-to-right
   stagger (delays inline in index.html) reads card by card, not as one fade. */
html.js .price-card[data-reveal] { transform: translateY(80px); }
html.js .price-card[data-reveal].revealed { transform: none; }
/* Buttons: small pop as they come into view (springy back-out easing) */
html.js [data-reveal="pop"] {
  transform: scale(0.85);
  transition:
    opacity 0.45s cubic-bezier(0.16, 1, 0.3, 1),
    transform 0.65s cubic-bezier(0.34, 1.56, 0.64, 1);
}
/* FAQ boxes share the pop entrance, but a large surface at 0.85 reads as a
   lurch; start closer to full size so the overshoot stays a subtle bounce. */
html.js .faq-item[data-reveal="pop"] { transform: scale(0.94); }
/* Stagger delay lives on the revealed state only, so repeatable elements
   (data-reveal-repeat) slide back out immediately instead of waiting out
   their entrance delay. */
html.js [data-reveal].revealed { opacity: 1; transform: none; transition-delay: var(--reveal-delay, 0s); }
/* Buttons hovered before their reveal has finished (the hero pair right after
   page load, a CTA the pointer already rests on) would otherwise snap: the
   reveal rules above use the `transition` shorthand, which drops the button's
   own background-color/box-shadow/color entries, and the .revealed rule puts
   the stagger delay on every property. So the fill circle grew under a base
   colour that had already flipped, and the hover read as an instant colour
   swap until js/site.js removed data-reveal on transitionend. Buttons only
   ever use the "pop" reveal, so its timings are repeated here verbatim. */
html.js .btn[data-reveal] {
  transition:
    opacity 0.45s cubic-bezier(0.16, 1, 0.3, 1),
    transform 0.65s cubic-bezier(0.34, 1.56, 0.64, 1),
    background-color 0s linear 0s,
    box-shadow 0.5s cubic-bezier(0.16, 1, 0.3, 1),
    color 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}
html.js .btn[data-reveal].revealed { transition-delay: var(--reveal-delay, 0s), var(--reveal-delay, 0s), 0s, 0s, 0s; }
html.js .btn[data-reveal].is-filled,
html.js .btn[data-reveal].revealed.is-filled { transition-delay: var(--reveal-delay, 0s), var(--reveal-delay, 0s), 0.2s, 0s, 0s; }
/* Boxes that zoom in from their center with a small end bounce
   (90% -> ~102% -> 100%). Keyframes instead of a transition so the
   overshoot amount is exact. Never scale(0): nothing appears from nothing. */
html.js [data-reveal="zoom"] {
  opacity: 0;
  transform: scale(0.9);
  transition: none;
}
html.js [data-reveal="zoom"].revealed {
  animation: reveal-zoom 0.8s cubic-bezier(0.22, 0.9, 0.36, 1) both;
  animation-delay: var(--reveal-delay, 0s);
}
@keyframes reveal-zoom {
  0% { opacity: 0; transform: scale(0.9); }
  /* Opacity resolves early so the scale overshoot reads as a pop, not a
     wobble tacked onto the end of a fade */
  35% { opacity: 1; }
  /* ease-in-out on the settle segment so the return from the bounce
     peak starts and lands gently instead of stopping dead */
  65% { transform: scale(var(--zoom-peak, 1.02)); animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1); }
  100% { opacity: 1; transform: scale(1); }
}

/* Word-by-word heading reveal: JS wraps each word in .rw (clip box) > .rwi
   (slides up from below the line). Per-word transition-delay is set inline.
   Line-by-line body reveal: JS wraps words in .rl and groups them into lines
   at reveal time. Both containers stay visible; only the pieces hide, and JS
   unwraps everything back to plain text after the animation. */
html.js [data-reveal="words"],
html.js [data-reveal="lines"],
html.js [data-reveal="group"] {
  opacity: 1;
  transform: none;
  transition: none;
}
.rw, .rwi, .rl { display: inline-block; }
html.js [data-reveal="words"] .rw {
  overflow: hidden;
  vertical-align: top;
  /* Extend the clip box so descenders and italic overhang survive the clip */
  padding: 0.1em 0.05em 0.15em;
  margin: -0.1em -0.05em -0.15em;
}
html.js [data-reveal="words"] .rwi {
  transform: translateY(120%);
  transition: transform 0.9s cubic-bezier(0.16, 1, 0.3, 1);
}
html.js [data-reveal="words"].revealed .rwi { transform: none; }
/* Hero text rolls in slower than the rest of the page */
html.js .hero [data-reveal="words"] .rwi { transition-duration: 1.2s; }
html.js .hero [data-reveal="lines"] .rl { transition-duration: 1.1s; }
html.js [data-reveal="lines"] .rl {
  opacity: 0;
  transform: translateY(14px);
  transition:
    opacity 0.8s cubic-bezier(0.16, 1, 0.3, 1),
    transform 0.8s cubic-bezier(0.16, 1, 0.3, 1);
}
html.js [data-reveal="lines"].revealed .rl { opacity: 1; transform: none; }

/* Footer wordmark is scroll-scrubbed (initParallax in js/site.js): rises
   25% → -8% of its own height while scaling 0.8 → 1 and fading in, eased
   toward the scroll position each frame. No transition on purpose — JS owns
   the motion. Hidden start gated on html.js so the text shows without JS. */
html.js .footer-wordmark { transform: translateY(25%) scale(0.8); opacity: 0; }

@media (prefers-reduced-motion: reduce) {
  html.js [data-reveal],
  html.js [data-reveal="words"] .rwi,
  html.js [data-reveal="lines"] .rl {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
    animation: none !important;
  }
  /* Entrance keyframes and the rotating hero word are motion too */
  .hero-header,
  .hero-mountain,
  .legal-mountain,
  .rot-word > span.active {
    animation: none !important;
  }
  /* Contact section entrances: keep the fades, drop the movement.
     !important transform overrides the keyframed scale/translate, leaving
     an opacity-only animation. */
  .contact-success,
  .contact-success .success-icon {
    animation: success-in 0.2s ease both;
    transform: none !important;
  }
  .field-error { transform: none !important; }
  /* Scroll-scrubbed wordmark: initParallax bails under reduced motion, so
     the CSS hidden start must be lifted or the text would never appear. */
  html.js .footer-wordmark { transform: none !important; opacity: 1 !important; }
}

/* ---------- Diffuse depth shadows ----------
   Large, soft, low-opacity shadows so cards and panels pop off the page. */
.problem-card-wide { box-shadow: 0 24px 70px -30px rgba(16, 29, 51, 0.18); }
.problem-card-dark { box-shadow: 0 24px 70px -28px rgba(16, 29, 51, 0.35); }
.solution-visual { box-shadow: 0 40px 90px -40px rgba(16, 29, 51, 0.28); }
.process-card { box-shadow: 0 30px 80px -32px rgba(16, 29, 51, 0.38); }
.price-card { box-shadow: 0 24px 70px -32px rgba(16, 29, 51, 0.16); }
.price-card-dark { box-shadow: 0 30px 80px -30px rgba(16, 29, 51, 0.38); }
.founder-offer { box-shadow: 0 24px 70px -30px rgba(79, 109, 179, 0.28); }

/* ---------- Responsive ---------- */
@media (max-width: 1250px) {
  .hero-mountain { left: 80%; height: 62vh; bottom: -8vh; }
}
@media (max-width: 1024px) {
  .footer-cols { gap: 60px; }
  .hero h1 { font-size: 48px; }
}
@media (max-width: 900px) {
  /* Nav bar links give way to the hamburger + drop-down panel */
  .hero-nav { display: none; }
  .nav-toggle { display: inline-flex; }
  .mobile-nav, .nav-backdrop { display: flex; }
  .hero h1 { font-size: 40px; }
  .hero h1 .nowrap { white-space: normal; }
  .hero-lead { font-size: 17px; }
  .hero-mountain { left: 50%; height: 56vh; bottom: -10vh; }
  .section-head { grid-template-columns: 1fr; gap: 24px; }
  .section-head-lead { justify-self: start; }
  .section-problem { padding-top: 80px; padding-bottom: 80px; }
  .problem-cards { flex-direction: column; }
  /* Stacked: the flex-basis:0 + grow ratios that share the row on wide screens
     would collapse every card to its padding in an auto-height column. */
  .problem-card { flex: none; height: auto; min-height: 220px; }
  .solution-grid { grid-template-columns: 1fr; }
  /* js/site.js moves the visual in under the active card here, so it needs to
     read as part of that card's block rather than a separate section. */
  .solution-visual { height: 340px; margin: 4px 0 8px; }
  .sol-card { padding: 20px 22px; }
  .process-grid { grid-template-columns: 1fr; }
  .process-card-2, .process-card-3 { margin-top: 0; }
  .pricing-grid { grid-template-columns: 1fr; }
  /* Stacked founder offer: the CTA belongs after everything it is selling, so
     the box becomes one flex column and the text block dissolves into it
     (display: contents) to let the button be ordered past the benefit list.
     Spacing comes from the elements' own margins, hence gap: 0. */
  .founder-offer {
    display: flex;
    flex-direction: column;
    gap: 0;
    padding: 28px 24px;
  }
  .founder-offer > div { display: contents; }
  .founder-features { order: 1; height: auto; margin: 0; }
  .founder-offer .btn { order: 2; align-self: flex-start; margin-top: 24px; }
  .section-faq { grid-template-columns: 1fr; gap: 24px; }
  .faq-intro { height: auto; }
  .faq-image { display: none; }
  /* The reserved height only exists to keep the two-column layout steady */
  .faq-list { padding-top: 0; min-height: 0; }
  /* Footer columns sit side by side rather than in one long stack (see the two
     blocks below for how many across). Every line in a column gets the same
     height whether it is a link or plain text, so the rhythm stays even and the
     links still have a comfortable tap target. */
  .footer-col { gap: 2px; }
  .footer-col-title { margin-bottom: 6px; }
  .footer-col > div:not(.footer-col-title):not(.footer-legal),
  .footer-col > a,
  .footer-legal a {
    display: flex;
    align-items: center;
    min-height: 40px;
  }
  /* Long address must never be able to push the column wider than its track */
  .footer-col > a { overflow-wrap: anywhere; }
  .footer-legal { margin-top: 0; }
  .footer-social a { width: 44px; height: 44px; }
  .price-founder-note { padding: 6px 0; }
  /* Stacked panel: the heading and lead sit directly on the panel's padding,
     so 24px left them almost touching the gradient's edge. */
  .contact-panel { grid-template-columns: 1fr; padding: 36px 32px; gap: 32px; }
  .contact-panel h2 { font-size: 34px; }
  .footer-cols { gap: 30px 24px; }
  .footer-social { padding-right: 0; }
  /* The wordmark is pulled up over the block's last line; on desktop that line
     is empty space, here it is the legal links, which need the clearance. */
  .footer-top { padding-bottom: 56px; }
  h2 { font-size: 30px; }
}
/* Phones. The whole footer becomes one grid: the wrappers dissolve
   (display: contents) so the social icons can sit beside the CTA instead of
   below the columns, and the legal links close the block at the bottom. */
@media (max-width: 600px) {
  .footer-top { display: grid; grid-template-columns: 1fr auto; column-gap: 16px; }
  .footer-cta-row, .footer-main { display: contents; }
  .footer-cta-row h2 { grid-column: 1 / -1; grid-row: 1; margin-bottom: 26px; }
  /* Type scales with the viewport so the CTA and the icons share the row even
     on a 320px screen. */
  .footer-cta-row .btn {
    grid-column: 1; grid-row: 2;
    justify-self: start;
    height: 44px;
    padding: 0 clamp(12px, 3.2vw, 22px);
    font-size: clamp(12px, 3.4vw, 16px);
  }
  .footer-social { grid-column: 2; grid-row: 2; align-self: center; justify-content: flex-end; }
  /* Yritys and the site links share the top row, so the site links stay one
     under the other; the contact details take the full width below them. */
  /* Uneven tracks: the site links start around 60% across rather than at the
     halfway point, which sits them under the social icons instead of in the
     middle of the block. Left-aligned text, and a fixed proportion so the
     start point does not drift with the screen width. */
  .footer-cols { grid-column: 1 / -1; grid-row: 3; margin-top: 36px; grid-template-columns: 1.8fr 1fr; row-gap: 22px; }
  /* Contact details sit straight under Yritys in the left column; the site
     links run the full height of the right one. */
  .footer-col:nth-child(1) { grid-column: 1; grid-row: 1; }
  .footer-col:nth-child(2) { grid-column: 1; grid-row: 2; }
  .footer-col:nth-child(3) { grid-column: 2; grid-row: 1 / span 2; }
  .footer-legal { grid-column: 1 / -1; grid-row: 3; align-self: start; margin-top: 6px; }
  /* Half-width columns: a step down in size keeps the address and the business
     ID on one line each. */
  .footer-col > div:not(.footer-col-title):not(.footer-legal),
  .footer-col > a,
  .footer-legal a { font-size: 14px; }
}
/* Tablets: all three columns across, as on desktop. The contact column is
   widest because the email address sets the minimum. Type stays a step down
   through the narrow end of the range so the address keeps its own line. */
@media (min-width: 601px) and (max-width: 900px) {
  .footer-cols { grid-template-columns: 0.85fr 1.25fr 0.85fr; gap: 26px; }
}
/* Below this the three columns plus the social block cannot share a line, so
   the social icons stay under them as on phones. */
@media (min-width: 601px) and (max-width: 720px) {
  .footer-main { flex-direction: column; align-items: stretch; gap: 26px; }
  .footer-social { justify-content: flex-start; }
}
/* From here the desktop arrangement fits: columns on the left, social block
   on the right under the CTA button. */
@media (min-width: 721px) and (max-width: 900px) {
  .footer-main { gap: 28px; }
}
@media (min-width: 601px) and (max-width: 760px) {
  .footer-col > div:not(.footer-col-title):not(.footer-legal),
  .footer-col > a,
  .footer-legal a { font-size: 14px; }
}
/* Tablet only: the stacked card is much wider and shorter than its desktop
   share of the row, so the graphic reads oversized there. The image is
   contained and bottom-aligned, so pulling the box's top down is what actually
   shrinks it; the narrower width keeps it clear of the copy. Phones get their
   own, larger treatment below. */
@media (min-width: 601px) and (max-width: 900px) {
  .problem-graphic { width: 48%; right: -3%; top: 18%; }
  /* Tablets have room for the real two-column table: topic as a ruled header
     spanning both, the two sides beside each other split by a hairline. */
  /* Tablets keep the desktop table as-is, only tightened: a narrower topic
     column and smaller gap so the two comparison columns keep usable width.
     The column header row does the labelling, so no per-cell labels or marks. */
  .compare-row { grid-template-columns: 130px 1fr 1fr; column-gap: 24px; padding: 26px 0; }
  /* Bottom of the tablet range: give the two comparison columns back every
     pixel the topic column and gap can spare. */
  @media (max-width: 719px) {
    .compare-row { grid-template-columns: 104px 1fr 1fr; column-gap: 18px; }
    .compare-topic { font-size: 16px; }
  }
  .compare-header { padding: 18px 0; }
  .compare-topic { font-size: 18px; }
  .compare-col-label { font-size: 15px; }
  .compare-logo img { height: 26px; }
  .compare-title { font-size: 15px; }
  .compare-row p { font-size: 14px; }
}
@media (max-width: 600px) {
  /* Stacked comparison, spec-sheet style. The column header row cannot follow
     the columns once they sit on top of each other, so every topic becomes its
     own small table: a ruled header, then one row per side. Sides are told
     apart by a ✗/✓ mark, the column name (our logo) and text weight. Rules are
     the same hairline grey as the desktop table. */
  .compare-row {
    grid-template-columns: 1fr;
    row-gap: 0;
    padding: 0;
    margin-bottom: 26px;
    border-bottom: none;
  }
  .compare-header { display: none; }
  .compare-topic {
    font-size: 17px;
    padding-bottom: 10px;
    border-bottom: 1px solid var(--border-subtle);
  }
  .compare-cell {
    position: relative;
    padding: 15px 0 16px 28px;
    border-bottom: 1px solid var(--border-subtle);
  }
  /* Mark in the gutter: crossed out for the generic agency, checked for us. */
  .compare-cell::before {
    content: '';
    position: absolute;
    left: 0; top: 16px;
    width: 16px; height: 16px;
    background-repeat: no-repeat;
    background-position: center;
    background-size: 15px 15px;
  }
  .compare-cell-other::before {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238390a6' stroke-width='3' stroke-linecap='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'/%3E%3Cline x1='6' y1='6' x2='18' y2='18'/%3E%3C/svg%3E");
  }
  .compare-cell-us::before {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%233f63aa' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E");
  }
  .compare-cell-label {
    display: block;
    font-family: var(--font-mono);
    font-size: 10.5px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--text-subtle);
    /* Optical, not nominal: the mono label's own line box already adds ~2px
       under the glyphs, so this lands ~10px of visible space above the title. */
    margin-bottom: 8px;
  }
  /* Our side is named by the logo, exactly like the desktop column header. The
     image is a tight crop with no leading of its own, so it needs a larger
     margin than the text label opposite to leave the same visible gap. */
  .compare-cell-us .compare-cell-label img { height: 20px; width: auto; display: block; }
  .compare-cell-us .compare-cell-label { margin-bottom: 9px; }
  .compare-cell .compare-title { font-size: 15px; margin-bottom: 5px; }
  .compare-cell-other .compare-title { color: var(--text-muted); font-weight: 600; }
  .compare-cell-other p { color: var(--text-subtle); font-size: 14px; }
  .compare-cell-us p { color: var(--text-body); font-size: 14px; }

  /* On phones the header keeps only the logo and the hamburger; the CTA would
     crowd them out (and it is the first item inside the open menu anyway). */
  .header-cta { display: none; }
  .hero-logo { height: 32px; }
  /* Phone hero: shorter viewport, so the mountain sits lower and smaller and
     stops washing out the lead paragraph behind it. The two CTAs share one row
     (see below), which lets the whole section be shorter than a full screen. */
  .hero { height: 88svh; min-height: 520px; }
  .hero h1 { font-size: 34px; margin-bottom: 18px; }
  .hero-lead { font-size: 16px; margin-bottom: 24px; }
  .hero-mountain { height: 40vh; bottom: -8vh; }
  .hero-fade { height: 180px; }
  .hero-ctas .btn { width: 100%; }
  /* Keep the peak clear of the header: with no pill behind the hamburger, its
     bars would otherwise sit straight on the snow. */
  .legal-mountain { left: 92%; height: 26vh; bottom: -5vh; }
  /* Wide problem card keeps its side-by-side shape on phones: copy in a narrow
     column on the left, graphic pinned to the right. The text column is capped
     just short of the graphic so the two never overlap. */
  /* The pin artwork carries ~16% transparent padding on its left, so the copy
     can run past the graphic box's edge and still clear the visible pin by
     about 10px. Measured against the image, not eyeballed. */
  .problem-card-wide h3, .problem-card-wide p { max-width: calc(58% - 5px); }
  .problem-card-wide h3 { font-size: 17px; }
  .problem-card-wide p { font-size: 14px; }
  .problem-graphic { width: 52%; right: -2%; }
  .problem-card { min-height: 0; }
  .problem-card-wide { min-height: 260px; }
  .problem-card-dark { min-height: 190px; }
}
/* Both hero CTAs on one row on phones. Type and padding scale with the
   viewport so the pair fits without wrapping; below 341px the labels can no
   longer fit at a readable size, so there they stay stacked full width. */
@media (min-width: 341px) and (max-width: 600px) {
  .hero-ctas { flex-wrap: nowrap; gap: 8px; }
  .hero-ctas .btn {
    flex: 0 1 auto;
    width: auto;
    height: 44px;
    padding: 0 clamp(8px, 2.6vw, 18px);
    font-size: clamp(12px, 3.4vw, 15px);
  }
}
/* Narrow phones (360px Android, 320px older/split views). Without this the
   pricing card's price line can't shrink below ~374px and the whole page
   scrolls sideways. */
@media (max-width: 420px) {
  /* Inline only: the shorthand would reset the block padding that .footer-top
     relies on to keep the wordmark off the legal links. */
  .container { padding-inline: 18px; }
  .price-card { padding: 28px 22px; }
  .price-line { flex-wrap: wrap; }
  .price-amount { font-size: 38px; }
  .price-period { font-size: 14px; }
  .price-old { font-size: 18px; }
  .founder-offer { padding: 26px 20px; }
  .contact-panel { padding: 30px 28px; }
  /* The nowrap label's min-content width can exceed the padded panel on the
     narrowest phones and push the whole page 2-3px wide; let it wrap instead. */
  .contact-form .btn { white-space: normal; height: auto; min-height: 48px; padding: 11px 16px; line-height: 1.3; }
  .contact-form { padding: 24px 20px; }
  .problem-card { padding: 24px 22px; }
  .process-card { padding: 26px 24px; }
  .faq-item button { padding: 16px 18px; }
  .faq-answer { padding: 0 18px 18px; }
  .contact-panel h2 { font-size: 30px; }
}
