/*
 * v2 design foundation — the "fjordgrønn" brand palette from
 * Co-work/landing-prototypes/a-nasjonalromantisk.html, ported verbatim.
 *
 * SCOPING (dispatch 2026-07-15-landing-vekstanalyse.md, job item 1):
 * landing has no token layer today — the existing home hardcodes bone/ink/
 * fjord via tailwind.config.ts `theme.extend.colors` (a GLOBAL Tailwind
 * palette, used by app/page.tsx + friends). This new palette must NOT
 * touch that config or leak onto /, /claim, /preview, /personvern.
 *
 * So instead of a :root block (which the prototype uses and which WOULD
 * leak — CSS custom properties on :root are visible to the whole
 * document), every rule below is scoped under the `.v2` wrapper class.
 * Every selector requires a `.v2` ancestor, so it has zero effect on any
 * element outside a `<div className="v2">…</div>` boundary — old routes
 * never render that wrapper.
 *
 * WHY THIS LIVES IN public/ (not app/styles/, imported as a CSS module):
 * a plain `import "./v2.css"` from a component reachable in `/page.tsx`'s
 * module graph gets pulled into Next's per-route CSS manifest for `/`
 * REGARDLESS of which runtime branch actually renders — verified live: even
 * behind a `v2Enabled ? <HomeV2/> : <HomeClassic/>` (and even behind an
 * `await import()`), the built `/` still emitted an extra
 * `<link rel="stylesheet">` + RSC `HL[...,"style"]` preload entry, which
 * fails the "byte-identical to main" guard even though it's visually inert.
 * Next's CSS extraction runs on the static module graph, before any
 * env-based dead-code elimination. Serving this file as a plain public
 * asset (`/styles/v2.css`) and loading it via a `<link rel="stylesheet">`
 * tag rendered INSIDE the v2 component tree (see HomeV2.tsx /
 * takbefaringer/page.tsx) sidesteps Next's CSS pipeline entirely — the
 * browser only requests it when a v2 page actually renders the tag, and
 * `/`'s classic-branch module graph never references this file at all.
 *
 * This is the FULL prototype stylesheet (not just the sections this lane
 * renders) — it's the shared design foundation for every v2 surface,
 * including the vekstanalyse scanner UI another lane is building
 * concurrently (analyse-bar input/toggle/scan-row/gate classes are kept
 * so that lane can consume the same tokens instead of reinventing them,
 * §C-9 one brain / one design system).
 */

.v2,
.v2 * {
  box-sizing: border-box;
}
.v2 * {
  margin: 0;
}

.v2 {
  --paper: #f6f3ec;
  --surface: #efebe0;
  --ink: #15140f;
  --muted: #6b675e;
  --line: #dcd6c6;
  --accent: #2f6b57;
  --accent-2: #25553f;
  --accent-light: #5f9b82;
  --soft: #dce8e0;
  --panel: #0e0d0a;
  --pmuted: #8a857a;

  min-height: 100vh;
  font-family: "Geist", system-ui, sans-serif;
  background: var(--paper);
  color: var(--ink);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

.v2 h1,
.v2 h2,
.v2 h3 {
  font-weight: 500;
  letter-spacing: -0.025em;
  line-height: 1.08;
}
.v2 .serif {
  font-family: "Instrument Serif", serif;
  font-style: italic;
  font-weight: 400;
  letter-spacing: -0.01em;
}
.v2 .mono {
  font-family: "Geist Mono", monospace;
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.v2 .wrap {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 32px;
}
.v2 a {
  text-decoration: none;
  color: inherit;
}
.v2 .pill {
  display: inline-block;
  border-radius: 999px;
  padding: 14px 30px;
  font-size: 15px;
  font-weight: 500;
  cursor: pointer;
  border: none;
  font-family: inherit;
  transition: background 0.18s ease, transform 0.18s ease;
}
.v2 .pill:active {
  transform: scale(0.98);
}
.v2 .pill.primary {
  background: var(--accent);
  color: #fff;
}
.v2 .pill.primary:hover {
  background: var(--accent-2);
}
.v2 .pill.paper {
  background: var(--paper);
  color: var(--ink);
}
.v2 .pill.ghost {
  background: transparent;
  color: #fff;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.35);
}
.v2 .pill.ghost:hover {
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.7);
}

/* ── hero ── */
.v2 .hero {
  position: relative;
  min-height: 104vh;
  display: flex;
  flex-direction: column;
  color: #fff;
}
.v2 .hero .bg {
  position: absolute;
  inset: 0;
  overflow: hidden;
}
.v2 .hero .bg img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 38%;
}
.v2 .hero .bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    rgba(10, 10, 7, 0.82) 0%,
    rgba(10, 10, 7, 0.38) 30%,
    rgba(10, 10, 7, 0.18) 52%,
    rgba(10, 10, 7, 0.44) 78%,
    var(--paper) 100%
  );
}
.v2 .hero > .wrap {
  position: relative;
}
.v2 nav {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 26px 44px;
  width: 100%;
}
.v2 .wordmark {
  font-family: "Geist Mono", monospace;
  font-weight: 500;
  letter-spacing: 0.34em;
  font-size: 14px;
  color: #fff;
}
.v2 nav .links {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 36px;
  align-items: center;
}
.v2 nav .links a {
  color: rgba(255, 255, 255, 0.72);
  font-size: 14px;
}
.v2 nav .links a:hover {
  color: #fff;
}
.v2 nav .cta .pill {
  padding: 10px 20px;
  font-size: 13.5px;
}
/* The nav utility link ("Logg inn"). Deliberately NOT a pill: it serves an
 * existing customer, not a prospect, and anything button-shaped beside the CTA
 * reads as a second offer. Quiet, legible on the hero photo.
 *
 * ▲ These three rules used to live at the very END of this file, appended after
 * the `Logg inn` lane shipped. That put them AFTER the `max-width:900px` block
 * below, which hides `.v2 nav .cta` on mobile — same selector, same
 * specificity, so the later declaration won and the nav never actually
 * collapsed. The phone rendered wordmark + «Logg inn» + the pill jammed into
 * one centred row, running off the right edge (owner screenshot, 2026-08-06).
 * A rule that a media query is supposed to override has to be declared BEFORE
 * it; hence the move up here, beside the nav rules it belongs to. */
.v2 nav .cta {
  display: flex;
  align-items: center;
  gap: 20px;
}
.v2 nav .cta .navlink {
  font-size: 13.5px;
  color: rgba(255, 255, 255, 0.72);
  white-space: nowrap;
}
.v2 nav .cta .navlink:hover {
  color: #fff;
}
.v2 .hero-inner {
  position: relative;
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 40px 32px 200px;
}
.v2 .hero .mono {
  color: var(--accent-light);
  margin-bottom: 26px;
}
.v2 .hero h1 {
  font-size: clamp(44px, 7vw, 92px);
  max-width: 1000px;
  color: var(--paper);
}
.v2 .hero h1 .serif {
  color: #fff;
}
.v2 .hero p.sub {
  font-size: clamp(15px, 1.5vw, 18px);
  color: rgba(246, 243, 236, 0.82);
  max-width: 540px;
  margin: 28px auto 40px;
}
.v2 .cta-row {
  display: flex;
  gap: 14px;
  justify-content: center;
  flex-wrap: wrap;
}
.v2 .hero .trust {
  margin-top: 44px;
  color: rgba(246, 243, 236, 0.55);
  font-size: 12px;
  letter-spacing: 0.14em;
}
.v2 .credit {
  position: absolute;
  bottom: 18px;
  width: 100%;
  text-align: center;
  font-family: "Geist Mono", monospace;
  font-size: 10px;
  letter-spacing: 0.12em;
  color: rgba(246, 243, 236, 0.5);
}

/* ── analyse bar ── */
.v2 .analyse {
  position: relative;
  margin-top: -120px;
  padding-bottom: 0;
  z-index: 3;
}
.v2 .abar {
  background: #fffdf8;
  border: 1px solid var(--line);
  border-radius: 24px;
  padding: 34px 38px;
  box-shadow: 0 30px 80px -40px rgba(21, 20, 15, 0.35);
}
.v2 .abar .top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
  margin-bottom: 20px;
}
.v2 .abar h2 {
  font-size: clamp(22px, 2.4vw, 30px);
}
.v2 .abar .top p {
  font-size: 14px;
  color: var(--muted);
  max-width: 380px;
}
.v2 .aform {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  align-items: center;
}
.v2 .toggle {
  display: inline-flex;
  background: var(--surface);
  border-radius: 999px;
  padding: 4px;
}
.v2 .toggle button {
  border: none;
  background: transparent;
  border-radius: 999px;
  padding: 9px 18px;
  font-size: 13px;
  font-family: inherit;
  color: var(--muted);
  cursor: pointer;
}
.v2 .toggle button.on {
  background: var(--ink);
  color: var(--paper);
  font-weight: 500;
}
.v2 .aform input {
  flex: 1;
  min-width: 220px;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 14px 22px;
  font-size: 15px;
  font-family: inherit;
  background: var(--paper);
  outline: none;
}
.v2 .aform input:focus {
  border-color: var(--accent);
}
.v2 .ameta {
  display: flex;
  gap: 0;
  margin-top: 24px;
  border-top: 1px solid var(--line);
  padding-top: 18px;
  flex-wrap: wrap;
}
.v2 .ameta div {
  flex: 1;
  min-width: 150px;
  padding-right: 24px;
}
.v2 .ameta .k {
  font-family: "Geist Mono", monospace;
  font-size: 10.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}
.v2 .ameta .v {
  font-size: 14px;
  margin-top: 4px;
}
.v2 .ameta .v.warn {
  color: #8a5514;
}
.v2 .ameta .v.ok {
  color: var(--accent-2);
}
/* scanner (consumed by the vekstanalyse lane) */
.v2 #scan {
  margin-top: 8px;
}
.v2 .srow {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 20px;
  padding: 12px 2px;
  border-bottom: 1px solid var(--line);
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity 0.45s ease, transform 0.45s ease;
}
.v2 .srow.in {
  opacity: 1;
  transform: none;
}
.v2 .srow .sk {
  font-family: "Geist Mono", monospace;
  font-size: 10.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}
.v2 .srow .sv {
  font-size: 14.5px;
  text-align: right;
}
.v2 .srow .sv.ok {
  color: var(--accent-2);
}
.v2 .srow .sv.warn {
  color: #8a5514;
}
.v2 .srow.lock .sv {
  filter: blur(5px);
  user-select: none;
}
.v2 .srow .sv .demo {
  filter: none;
  font-family: "Geist Mono", monospace;
  font-size: 9.5px;
  letter-spacing: 0.12em;
  color: var(--muted);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 2px 8px;
  margin-left: 8px;
  vertical-align: 1px;
}
.v2 .spin {
  display: inline-block;
  width: 12px;
  height: 12px;
  border: 2px solid var(--line);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: v2-spin 0.7s linear infinite;
  vertical-align: -1px;
}
@keyframes v2-spin {
  to {
    transform: rotate(360deg);
  }
}
.v2 .gate {
  margin-top: 22px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 20px;
  padding: 26px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 26px;
  align-items: center;
}
.v2 .gate h3 {
  font-size: 20px;
  margin-bottom: 6px;
}
.v2 .gate p {
  font-size: 13.5px;
  color: var(--muted);
}
.v2 .gate form {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.v2 .gate input[type="email"],
.v2 .gate input[type="tel"] {
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 12px 20px;
  font-size: 14.5px;
  font-family: inherit;
  background: #fff;
  outline: none;
}
.v2 .gate input:focus {
  border-color: var(--accent);
}
.v2 .gate .consent {
  display: flex;
  gap: 8px;
  align-items: flex-start;
  font-size: 12px;
  color: var(--muted);
}
.v2 .gate .consent input {
  margin-top: 2px;
}
.v2 #post {
  margin-top: 22px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 20px;
  background: var(--soft);
  border-radius: 20px;
  padding: 22px 26px;
  flex-wrap: wrap;
}
.v2 #post .pt {
  font-size: 15px;
  font-weight: 500;
  color: var(--accent-2);
}
.v2 #post .pm {
  font-size: 12.5px;
  color: var(--muted);
  margin-top: 2px;
}
.v2 .scanerr {
  margin-top: 14px;
  font-size: 13.5px;
  color: #9b2a2a;
}
.v2 .abar-placeholder {
  margin-top: 8px;
  padding: 22px;
  border: 1px dashed var(--line);
  border-radius: 16px;
  color: var(--muted);
}
@media (max-width: 700px) {
  .v2 .gate {
    grid-template-columns: 1fr;
  }
}

/* ── sections ── */
.v2 section {
  padding: 110px 0;
}
.v2 .eyebrow {
  display: flex;
  align-items: baseline;
  gap: 18px;
  border-top: 1px solid var(--ink);
  padding-top: 16px;
  margin-bottom: 56px;
}
.v2 .eyebrow .mono {
  color: var(--muted);
}
.v2 .eyebrow h2 {
  font-size: clamp(30px, 3.6vw, 46px);
}
.v2 .split {
  display: grid;
  grid-template-columns: 5fr 7fr;
  gap: 60px;
  align-items: start;
}
.v2 .split .lede {
  font-size: 17px;
  color: var(--muted);
  max-width: 400px;
}

/* bransjer rows */
.v2 .rows {
  border-top: 1px solid var(--line);
}
.v2 .row {
  display: grid;
  grid-template-columns: 70px 1fr 2fr auto;
  gap: 24px;
  align-items: center;
  padding: 26px 0;
  border-bottom: 1px solid var(--line);
}
.v2 .row .no {
  font-family: "Geist Mono", monospace;
  font-size: 12px;
  color: var(--muted);
}
.v2 .row h3 {
  font-size: clamp(20px, 2.2vw, 28px);
  font-weight: 500;
}
.v2 .row p {
  font-size: 14px;
  color: var(--muted);
  max-width: 480px;
}
.v2 .row .go {
  font-size: 14px;
  font-weight: 500;
  color: var(--accent);
  white-space: nowrap;
}
.v2 .row.active h3::after {
  content: "Aktiv nå";
  font-family: "Geist Mono", monospace;
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent-2);
  background: var(--soft);
  border-radius: 999px;
  padding: 4px 10px;
  margin-left: 14px;
  vertical-align: 3px;
}
.v2 .row.soon {
  opacity: 0.45;
}
.v2 .row.soon .go {
  color: var(--muted);
  font-weight: 400;
}

/* steps */
.v2 .steps {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 40px;
}
.v2 .step {
  border-top: 1px solid var(--ink);
  padding-top: 20px;
}
.v2 .step .mono {
  color: var(--muted);
}
.v2 .step h3 {
  font-size: 21px;
  margin: 14px 0 10px;
}
.v2 .step p {
  font-size: 14.5px;
  color: var(--muted);
}

/* quote band */
.v2 .band {
  position: relative;
  overflow: hidden;
}
.v2 .band img {
  width: 100%;
  height: 440px;
  object-fit: cover;
  object-position: center 58%;
  display: block;
}
.v2 .band .ov {
  position: absolute;
  inset: 0;
  background: rgba(10, 10, 7, 0.52);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 32px;
}
.v2 .band .ov p {
  font-family: "Instrument Serif", serif;
  font-style: italic;
  font-size: clamp(26px, 3.6vw, 44px);
  color: var(--paper);
  max-width: 760px;
  line-height: 1.25;
}
.v2 .band .ov .mono {
  color: rgba(246, 243, 236, 0.6);
  margin-top: 20px;
}

/* proof (dark) */
.v2 .dark {
  background: var(--panel);
  color: var(--paper);
}
.v2 .dark .eyebrow {
  border-top-color: var(--paper);
}
.v2 .dark .eyebrow .mono {
  color: var(--pmuted);
}
.v2 .proofgrid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 40px;
}
.v2 .pf {
  border-top: 1px solid rgba(246, 243, 236, 0.25);
  padding-top: 22px;
}
.v2 .pf .n {
  font-size: clamp(48px, 5.5vw, 76px);
  font-weight: 500;
  letter-spacing: -0.03em;
  color: var(--paper);
}
.v2 .pf .n em {
  font-style: normal;
  color: var(--accent-light);
}
.v2 .pf .l {
  font-size: 14px;
  color: var(--pmuted);
  margin-top: 8px;
  max-width: 240px;
}

/* system */
.v2 .sys ul {
  list-style: none;
  border-top: 1px solid var(--line);
}
.v2 .sys li {
  display: flex;
  justify-content: space-between;
  gap: 20px;
  padding: 18px 0;
  border-bottom: 1px solid var(--line);
  font-size: 16px;
}
.v2 .sys li span:last-child {
  color: var(--muted);
  font-size: 14px;
  text-align: right;
}
.v2 .shot {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 24px;
  min-height: 380px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
  font-family: "Geist Mono", monospace;
  font-size: 11px;
  letter-spacing: 0.14em;
}

/* final */
.v2 .final {
  background: var(--panel);
  color: var(--paper);
  text-align: center;
  padding: 150px 0;
}
.v2 .final .mono {
  color: var(--accent-light);
}
.v2 .final h2 {
  font-size: clamp(36px, 5vw, 64px);
  margin: 22px 0 14px;
}
.v2 .final p {
  color: var(--pmuted);
  margin-bottom: 36px;
  font-size: 16px;
}
.v2 footer {
  background: var(--panel);
  color: var(--pmuted);
  padding: 30px 0;
  border-top: 1px solid rgba(246, 243, 236, 0.12);
}
.v2 footer .wrap {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  font-family: "Geist Mono", monospace;
  font-size: 10.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* live loop (slik fungerer det) */
.v2 .loopwrap {
  display: grid;
  grid-template-columns: 7fr 5fr;
  gap: 60px;
  align-items: start;
}
.v2 .feed {
  background: #fffdf8;
  border: 1px solid var(--line);
  border-radius: 24px;
  padding: 26px;
  min-height: 380px;
}
.v2 .feed .fh {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 18px;
}
.v2 .feed .fh .mono {
  color: var(--muted);
}
.v2 .feed .dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
  animation: v2-pulse 1.6s infinite;
}
@keyframes v2-pulse {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.35;
  }
}
.v2 .fitem {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  padding: 13px 0;
  border-bottom: 1px solid var(--line);
  opacity: 0;
  transform: translateY(-6px);
  transition: opacity 0.5s ease, transform 0.5s ease;
}
.v2 .fitem.in {
  opacity: 1;
  transform: none;
}
.v2 .fitem:last-child {
  border-bottom: none;
}
.v2 .fitem .ic {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--soft);
  color: var(--accent-2);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
  flex-shrink: 0;
}
.v2 .fitem.win .ic {
  background: var(--accent);
  color: #fff;
}
.v2 .fitem .t {
  font-size: 14.5px;
}
.v2 .fitem .t strong {
  font-weight: 500;
}
.v2 .fitem .m {
  font-family: "Geist Mono", monospace;
  font-size: 10.5px;
  letter-spacing: 0.08em;
  color: var(--muted);
  margin-top: 2px;
}
.v2 .fitem.win .t strong {
  color: var(--accent-2);
}

/* takbefaringer spoke — offer stack + kvalifiseringskrav lists */
.v2 .offer-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.v2 .offer-list li {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  font-size: 15px;
  line-height: 1.55;
}
.v2 .offer-list .ic {
  flex-shrink: 0;
  font-size: 18px;
  line-height: 1.4;
}
.v2 .req-list {
  list-style: none;
  counter-reset: req;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.v2 .req-list li {
  counter-increment: req;
  display: flex;
  gap: 14px;
  align-items: baseline;
  font-size: 14.5px;
  color: var(--muted);
}
.v2 .req-list li::before {
  content: counter(req);
  font-family: "Geist Mono", monospace;
  font-size: 12px;
  color: var(--accent-2);
  flex-shrink: 0;
}
.v2 .contrast-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
}
.v2 .contrast-card {
  border-radius: 20px;
  padding: 28px;
  border: 1px solid var(--line);
}
.v2 .contrast-card.bad {
  background: var(--surface);
}
.v2 .contrast-card.good {
  background: var(--soft);
  border-color: var(--accent-light);
}
.v2 .contrast-card h3 {
  font-size: 18px;
  margin-bottom: 12px;
}
.v2 .contrast-card p {
  font-size: 14px;
  color: var(--muted);
  line-height: 1.6;
}
.v2 .tak-hero {
  background: var(--panel);
  color: var(--paper);
  padding: 90px 0 70px;
}
.v2 .tak-hero .eyebrow {
  border-top-color: var(--paper);
  margin-bottom: 28px;
}
.v2 .tak-hero .eyebrow .mono {
  color: var(--accent-light);
}
.v2 .tak-hero h1 {
  font-size: clamp(36px, 5vw, 58px);
  max-width: 820px;
}
.v2 .tak-hero p.sub {
  margin-top: 20px;
  max-width: 560px;
  color: var(--pmuted);
  font-size: 16px;
}

@media (max-width: 900px) {
  .v2 .split,
  .v2 .loopwrap {
    grid-template-columns: 1fr;
    gap: 28px;
  }
  .v2 .steps,
  .v2 .proofgrid,
  .v2 .contrast-grid {
    grid-template-columns: 1fr;
    gap: 28px;
  }
  .v2 .row {
    grid-template-columns: 1fr;
    gap: 8px;
  }
  .v2 .row .no {
    display: none;
  }
  /* Every `.v2` nav gets the tighter phone padding; only the HOME HERO's nav
   * gets restructured below. `/vekstanalyse` renders its own `<nav>` with just
   * a wordmark and a booking pill, and `/os` + `/takbefaringer` put a bare
   * `.wordmark` in a plain `.wrap` with no nav at all — an unscoped
   * `.v2 .wordmark{position:absolute}` would rip the brand out of flow on
   * those three pages and collapse the row it was holding open. */
  .v2 nav {
    justify-content: center;
    padding: 14px 18px;
    /* /vekstanalyse's nav centres a wordmark next to a booking pill with
     * nothing between them — at this width they touched. No effect on the home
     * hero, whose wordmark is out of flow. */
    gap: 12px;
  }
  .v2 nav .links {
    display: none;
  }
  .v2 nav .wordmark,
  .v2 nav .cta .navlink {
    /* Tap area, not visual weight: the wordmark's own line box is 14px, so
     * without this the target is 22px tall — half the 44px minimum. */
    padding: 11px 8px;
  }

  /* ── the phone header: wordmark dead centre, «Logg inn» top right ─────────
   * Owner steer 2026-08-06. Three items on one centred row is what broke it —
   * the wordmark read as a prefix to «Logg inn» and the pill ran off the edge.
   * So the row carries exactly two things, and they don't share a lane:
   *   · the wordmark is taken OUT of flow and pinned to the centre (the same
   *     trick `.links` uses on desktop) — it is the brand, not a nav item;
   *   · «Logg inn» is the only in-flow child left, so `justify-content:flex-end`
   *     parks it top-right where a phone user's thumb already expects account
   *     stuff to be.
   * «Book en prat» leaves the header entirely and re-appears inside the hero,
   * under the copy it belongs to — see `.hero .talk` further down. Scoped to
   * `.hero` because that trade only works where the hero re-offers it: on
   * `/vekstanalyse` the nav pill is the page's ONLY way to book, so it stays. */
  .v2 .hero nav {
    justify-content: flex-end;
  }
  .v2 .hero nav .cta .pill {
    display: none;
  }
  .v2 .hero nav .wordmark {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
  }
  .v2 .hero-inner {
    padding-bottom: 170px;
  }
}

/* ── vekstanalyse: confirm-loop + honest markers ──────────────────────────────
 * ADDITIVE BLOCK (scanner lane). Everything below is NEW surface the prototype
 * never had — the confirm-loop is spec v2 §2, and the «estimat» marker exists
 * because §C-8 requires a derived value to announce itself on screen.
 *
 * Rules: appended, never editing an existing rule above; every selector scoped
 * under `.v2` (never `:root`) so nothing can leak onto the classic home; colours
 * come from the vars declared on `.v2` — no new palette.
 *
 * The prototype's `.toggle` rules above are deliberately left in place but
 * UNUSED: spec v2 §1 replaced the org-nr/nettside mode switch with one smart
 * field that classifies the input itself. Kept rather than deleted — it is the
 * other lane's file.
 */

/* The «estimat» badge. Modelled on `.srow .sv .demo` (the prototype's badge for
 * its fabricated demo rows — which are OMITTED, not ported), but named for what
 * it actually marks. `filter: none` is load-bearing: inside a blurred
 * `.srow.lock .sv` the NUMBER blurs while this label stays crisp, so a locked
 * estimate still announces itself as an estimate rather than hiding behind the
 * gate. */
.v2 .srow .sv .estimat {
  filter: none;
  font-family: "Geist Mono", monospace;
  font-size: 9.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 2px 8px;
  margin-left: 8px;
  vertical-align: 1px;
  white-space: nowrap;
}

/* A row's supporting note (the engine's `detail`, or an estimat's `basis` — the
 * audit trail that keeps a computed number honest).
 *
 * Scoped to `.v2 .snote`, NOT `.v2 .srow .sv .snote`: the same element is used in
 * BOTH the scan rows and the confirm strip's `.ameta` («Vi sjekket 3 kilder»).
 * Scoping it to `.srow .sv` left the confirm-strip copy `display:inline`, which
 * ran the sentences together — "Ingen nettside funnetVi sjekket 3 kilder."
 * One class, one behaviour, wherever it appears. */
.v2 .snote {
  display: block;
  font-size: 11.5px;
  color: var(--muted);
  margin-top: 3px;
  font-weight: 400;
}

/* An unmeasured value. Mirrors drift's «Ikke målt» rendering — an explicit
 * non-measurement, never a "—" or a 0 standing in for one. */
.v2 .srow .sv .unmeasured {
  color: var(--muted);
  font-style: italic;
}

/* Small inline text action (rediger / bekreft / legg til). Not a `.pill` — these
 * sit inside a data row and must not compete with the primary CTA. */
.v2 .clink {
  border: none;
  background: transparent;
  font-family: inherit;
  font-size: 12.5px;
  color: var(--accent);
  cursor: pointer;
  padding: 0;
  margin-left: 8px;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.v2 .clink:hover {
  color: var(--accent-2);
}
.v2 .clink.quiet {
  color: var(--muted);
}

/* The stronger ask on a low-confidence / needsConfirm resolution: the machine
 * guessed, and a human should look before we build a sales call on it. */
.v2 .ameta .ask {
  display: block;
  font-family: "Geist Mono", monospace;
  font-size: 9.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #8a5514;
  margin-top: 4px;
}

/* Inline edit affordance inside the confirm strip. */
.v2 .cedit {
  display: flex;
  gap: 6px;
  align-items: center;
  margin-top: 6px;
  flex-wrap: wrap;
}
.v2 .cedit input {
  flex: 1;
  min-width: 150px;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 7px 14px;
  font-size: 13px;
  font-family: inherit;
  background: var(--paper);
  outline: none;
}
.v2 .cedit input:focus {
  border-color: var(--accent);
}

/* A social profile line inside the confirm strip. */
.v2 .ameta .sprofile {
  display: block;
  margin-bottom: 3px;
  word-break: break-all;
}

/* The confirm strip's columns WRAP on a narrow screen (`.ameta` is flex-wrap).
 * Wrapped flex items get no vertical gap from `gap:0`, so the stacked
 * «Nettside» and «Sosiale profiler» groups ran together on mobile. Give them
 * breathing room only once they've actually stacked. */
@media (max-width: 720px) {
  .v2 .ameta div {
    padding-right: 0;
    margin-bottom: 14px;
  }
  .v2 .ameta div:last-child {
    margin-bottom: 0;
  }
}

/* Field-level gate errors. */
.v2 .gate .gerr {
  font-size: 12px;
  color: #9b2a2a;
  margin: -4px 0 2px 20px;
}
.v2 .gate input.bad {
  border-color: #9b2a2a;
}

/* ── /vekstanalyse — the dedicated scanner page (scanner lane, additive) ─────
 * The home's analyse card overlaps the HERO PAINTING. This page has no painting,
 * so it grows its own compact dark band for the card to overlap — same visual
 * grammar (card breaking a dark fold), no second design language, no new
 * palette: `--panel` and `--pmuted` are the existing v2 vars.
 *
 * Reusing `.v2 nav`/`.wordmark` here is why the band must be DARK: those rules
 * set `color:#fff` for the hero, so a light band would render the wordmark
 * invisible.
 */
.v2 .vapage {
  background: var(--paper);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
.v2 .vahead {
  background: var(--panel);
  padding-bottom: 96px;
}
.v2 .vaintro {
  padding-top: 26px;
}
.v2 .vaintro .mono {
  color: var(--pmuted);
}
.v2 .vaintro h1 {
  font-family: "Instrument Serif", Georgia, serif;
  font-weight: 400;
  font-size: clamp(30px, 4.4vw, 50px);
  line-height: 1.06;
  color: #fff;
  margin-top: 12px;
  letter-spacing: -0.01em;
}
.v2 .vaintro p {
  color: var(--pmuted);
  font-size: 15.5px;
  margin-top: 14px;
  max-width: 560px;
}
/* Push the footer to the bottom on a short scan-less page — `.vapage` is the
 * flex column that makes this work, so the paper background can't leave a dead
 * band under the footer. */
.v2 .vapage footer {
  margin-top: auto;
}

/* Opt out of the hero overlap; overlap this page's own band instead. */
.v2 .analyse.standalone {
  margin-top: -64px;
  margin-bottom: 72px;
}
@media (max-width: 720px) {
  .v2 .vahead {
    padding-bottom: 80px;
  }
  .v2 .analyse.standalone {
    margin-top: -56px;
    margin-bottom: 48px;
  }
}

/* ── /os — the Driftbase OS product page (agency/OS split, additive) ─────────
 * No new palette and no new form language: the page reuses `.gate`,
 * `.offer-list`, `.contrast-grid`, `.req-list` and `.tak-hero` as they stand.
 * The two rules below exist because the OS page is the first to need them, not
 * because it wants to look different.
 */

/* The gate card was written for the vekstanalyse form, whose only fields are an
 * email and a phone — so the pill styling was keyed to those two input types and
 * a `type="text"` field lands unstyled. The OS list asks for a company name and
 * a bransje, both free text. Widening the selector fixes it everywhere at once
 * rather than adding a second, near-identical rule for this page. */
.v2 .gate input[type="text"] {
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 12px 20px;
  font-size: 14.5px;
  font-family: inherit;
  background: #fff;
  outline: none;
}

/* `.offer-list .ic` holds a single emoji on /takbefaringer, so it needs no
 * width. On /os the slot carries a mono TAG ("push + SMS", "egen side") whose
 * width varies per row — without a fixed column the bullet text starts at a
 * different x on every line. */
.v2 .offer-list .ic.mono {
  width: 116px;
  padding-top: 3px;
  color: var(--accent-2);
  letter-spacing: 0.04em;
}
@media (max-width: 720px) {
  .v2 .offer-list li {
    flex-direction: column;
    gap: 6px;
  }
  .v2 .offer-list .ic.mono {
    width: auto;
  }
}

/* The benefit clarifier under the hero CTA. Small, quiet, and directly under the
 * button — the position is the point: it answers "what happens if I click" at
 * the moment of hesitation, which is what the ~9 % lift is attributed to. */
.v2 .hero .cta-note {
  margin-top: 14px;
  font-family: "Geist Mono", monospace;
  font-size: 11.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent-light);
  opacity: 0.85;
}

/* The one-line niche handoff that replaced three "Kommer" rows. */
.v2 .niche-line {
  font-size: 14.5px;
  color: var(--muted);
  padding-top: 22px;
  border-top: 1px solid var(--line);
}
.v2 .niche-line strong {
  color: var(--ink);
  font-weight: 500;
}
.v2 .niche-line a {
  color: var(--accent-2);
  font-weight: 500;
  white-space: nowrap;
}


/* ── The integrasjoner / trust row ─────────────────────────────────────────
 * Static, not a marquee. An infinite-scroll ticker animates forever, costs a
 * compositor layer on every frame, and has to be disabled under
 * prefers-reduced-motion anyway — for five short wordmarks that all fit on one
 * line, the motion buys nothing a static row does not already give.
 */
.v2 .integrasjoner {
  /* Pulled up into the preceding section's 110px bottom padding. The row is a
   * footnote to the promise above it, not its own chapter — 164px of stacked
   * padding read as a section break and orphaned it. */
  margin-top: -66px;
  padding: 0 0 30px;
}
.v2 .integrasjoner .cap {
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 18px;
}
.v2 .integrasjoner ul {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 14px 40px;
}
.v2 .integrasjoner li {
  font-size: 19px;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--ink);
  opacity: 0.62;
}
.v2 .integrasjoner .ai-note {
  margin-top: 26px;
  max-width: 640px;
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--muted);
  padding-top: 20px;
  border-top: 1px solid var(--line);
}
@media (max-width: 620px) {
  .v2 .integrasjoner ul {
    gap: 12px 26px;
  }
  .v2 .integrasjoner li {
    font-size: 16px;
  }
}

/* Source line under the proof stats. Small and quiet — a citation should be
 * findable, not loud; the point is that it EXISTS. */
.v2 .dark .src {
  margin-top: 26px;
  font-family: "Geist Mono", monospace;
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--pmuted);
}

/* The risk reversal — the page's substitute for proof it does not have.
 * Bordered off inside the dark band so it reads as the conclusion drawn FROM
 * the stats above, not as a fourth stat. */
.v2 .dark .riskrev {
  margin-top: 46px;
  padding-top: 34px;
  border-top: 1px solid rgba(255, 255, 255, 0.14);
  max-width: 720px;
}
.v2 .dark .riskrev h3 {
  font-size: clamp(21px, 2.4vw, 27px);
  margin-bottom: 14px;
  color: var(--paper);
}
.v2 .dark .riskrev p {
  font-size: 15px;
  line-height: 1.65;
  color: var(--pmuted);
}

/* ── "Vi gjør / Du gjør" — the division of labour ─────────────────────────── */
.v2 .split-work {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 44px;
  margin-top: 64px;
  padding-top: 34px;
  border-top: 1px solid var(--line);
}
.v2 .split-work .mono {
  color: var(--accent-2);
  margin-bottom: 16px;
}
.v2 .split-work ul {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.v2 .split-work li {
  font-size: 15px;
  line-height: 1.5;
  padding-left: 20px;
  position: relative;
}
.v2 .split-work li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 9px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent-light);
}
.v2 .split-work p {
  margin-top: 16px;
  font-size: 13px;
  line-height: 1.6;
  color: var(--muted);
}
@media (max-width: 860px) {
  .v2 .split-work {
    grid-template-columns: 1fr;
    gap: 32px;
  }
}

/* ── "01 — Kjenner du deg igjen?" — the lost-job timeline ──────────────────
 * The dead zone's WIDTH carries the argument, so the horizontal layout is the
 * point of the component, not decoration. Under 760px a horizontal track stops
 * being readable at all, so it flips to a vertical timeline — same nodes, same
 * order, track drawn as a left border instead of a centre line.
 */
.v2 .tapt {
  margin: 42px 0 40px;
}
.v2 .tapt figcaption {
  color: var(--muted);
  margin-bottom: 10px;
}

.v2 .tapt .track {
  position: relative;
  height: 340px;
  margin-top: 8px;
}
.v2 .tapt .line {
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--line);
}

/* The gap, drawn to scale. Hatched rather than solid so it reads as "nothing
 * happened here" rather than as a filled stage in a process. */
.v2 .tapt .dead {
  position: absolute;
  top: calc(50% - 26px);
  height: 52px;
  border-radius: 6px;
  background: repeating-linear-gradient(
    -45deg,
    rgba(155, 42, 42, 0.07) 0 6px,
    transparent 6px 12px
  );
  border: 1px dashed rgba(155, 42, 42, 0.28);
  display: flex;
  align-items: center;
  justify-content: center;
}
.v2 .tapt .dead span {
  font-family: "Geist Mono", monospace;
  font-size: 10.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #9b2a2a;
  opacity: 0.85;
  text-align: center;
  padding: 0 8px;
}

.v2 .tapt .node {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 0;
}
.v2 .tapt .dot {
  position: absolute;
  top: 50%;
  left: -6px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--accent);
  transform: translateY(-50%);
  box-shadow: 0 0 0 5px var(--paper);
}
.v2 .tapt .node.lost .dot {
  background: #9b2a2a;
}
.v2 .tapt .card {
  position: absolute;
  left: 0;
  width: 246px;
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.v2 .tapt .node.top .card {
  bottom: calc(50% + 30px);
}
.v2 .tapt .node.bottom .card {
  top: calc(50% + 30px);
}
/* The last node would overflow the container at left:88% — pull it back so the
 * card's right edge lands inside the wrap. */
.v2 .tapt .node:last-child .card {
  left: auto;
  right: 0;
  text-align: right;
}
.v2 .tapt .card .t {
  color: var(--accent-light);
}
.v2 .tapt .node.lost .card .t {
  color: #9b2a2a;
}
.v2 .tapt .card strong {
  font-size: 17px;
  font-weight: 500;
  line-height: 1.25;
}
.v2 .tapt .card .b {
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--muted);
}

@media (max-width: 760px) {
  .v2 .tapt .track {
    height: auto;
    padding-left: 26px;
    display: flex;
    flex-direction: column;
    gap: 30px;
  }
  .v2 .tapt .line {
    top: 6px;
    bottom: 6px;
    left: 5px;
    right: auto;
    width: 1px;
    height: auto;
  }
  .v2 .tapt .dead {
    position: relative;
    left: auto !important;
    width: auto !important;
    top: auto;
    height: auto;
    padding: 12px 14px;
  }
  .v2 .tapt .dead span {
    text-align: left;
    padding: 0;
  }
  .v2 .tapt .node,
  .v2 .tapt .node:last-child .card {
    position: relative;
    left: auto !important;
    right: auto;
    top: auto;
    bottom: auto;
    width: auto;
    text-align: left;
  }
  .v2 .tapt .node .card {
    position: relative;
    left: auto;
    right: auto;
    top: auto;
    bottom: auto;
    width: auto;
  }
  .v2 .tapt .dot {
    top: 6px;
    left: -26px;
    transform: none;
  }
}

/* ═══ MOBILE ═══════════════════════════════════════════════════════════════
 * Owner review on a real iPhone, 2026-08-06. Everything above this line was
 * authored desktop-first from the prototype, and the phone only ever got the
 * two collapse rules in the `max-width:900px` block — enough to stop the grids
 * from overflowing, not enough to make the page read well in the hand.
 *
 * The theme of the fixes below is space, not restyling: at 390px the page was
 * spending its width on padding (the analyse card sat 70px in from each edge)
 * and its height on desktop rhythm (110px section padding, a 380px empty
 * screenshot slot), so the reader scrolled 8 000px for content that wants
 * about 6 000. No colours, no type families, no component structure changes —
 * a phone visitor should recognise the same page, just one that fits.
 *
 * 900px is the breakpoint the file already collapses at; reusing it keeps
 * "mobile" one thing rather than three competing thresholds.
 */
@media (max-width: 900px) {
  /* ── the frame ────────────────────────────────────────────────────────── */

  /* 32px × 2 of gutter is 16 % of a 390px screen. 20px still separates the
   * text from the bezel and buys back 24px of line length everywhere at once. */
  .v2 .wrap {
    padding: 0 20px;
  }

  /* Desktop rhythm read as dead air on a phone — 220px of stacked padding
   * between two sections is most of a viewport with nothing in it. */
  .v2 section {
    padding: 68px 0;
  }
  .v2 .final {
    padding: 84px 0;
  }

  /* The section headers are `display:flex` — the mono kicker and the h2 share
   * a row. At this width the kicker wraps to four lines ("03 — HVORFOR / FART
   * VINNER") while squeezing the h2 into a ~250px column, so "Den som ringer
   * først, vinner." came out four lines tall in a narrow gutter. Stacked, the
   * heading gets the full width and the kicker gets its one line. */
  .v2 .eyebrow {
    flex-direction: column;
    align-items: flex-start;
    gap: 10px;
    margin-bottom: 34px;
  }

  /* ── hero ─────────────────────────────────────────────────────────────── */

  /* 104vh was a deliberate "there is more below" overhang on a desktop screen.
   * On a phone `vh` is the LARGE viewport — the height with the browser chrome
   * retracted — so 104vh put the trust line and the painting credit behind
   * Safari's toolbar on first paint. `svh` is the small viewport: the hero
   * fits what is actually visible before a single scroll. The `vh` line above
   * it is the fallback for browsers without `svh` (pre-15.4 iOS). */
  .v2 .hero {
    min-height: 100vh;
    min-height: 100svh;
  }

  /* `clamp(44px, 7vw, 92px)` bottoms out at 44px, and 7vw only overtakes that
   * at 630px — so every phone got the 44px floor regardless of width. At 390px
   * "Ingen oppstartskost." then needs ~430px and wraps mid-line, turning three
   * authored lines into five and pushing the CTA off the fold. This clamp is
   * the mobile half of the same curve: it scales with the screen (8.4vw) and
   * hands back to the desktop value at the breakpoint. */
  .v2 .hero h1 {
    font-size: clamp(29px, 8.4vw, 46px);
  }
  .v2 .hero .mono {
    margin-bottom: 18px;
  }
  .v2 .hero p.sub {
    margin: 20px auto 30px;
  }

  /* Shrink-wrapped pills centre-align to different widths and read as a ragged
   * stack. Full width gives one clean column and a much bigger tap target. */
  .v2 .cta-row {
    flex-direction: column;
    align-self: center;
    width: 100%;
    /* Below ~440px this never binds and the stack goes edge-to-edge, which is
     * what a phone wants. It exists for the top of this breakpoint: a 728px-wide
     * pill on a tablet stops reading as a button. */
    max-width: 420px;
    gap: 10px;
  }
  .v2 .cta-row .pill {
    display: block;
    width: 100%;
    text-align: center;
    padding: 16px 22px;
  }

  /* The relocated «Book en prat» — see the comment in V2Hero.tsx. */
  .v2 .hero .talk {
    display: inline-block;
    margin-top: 18px;
    padding: 11px 4px;
    font-size: 14.5px;
    color: rgba(246, 243, 236, 0.9);
    text-decoration: underline;
    text-underline-offset: 4px;
    text-decoration-color: rgba(246, 243, 236, 0.45);
  }

  /* Both of these are one-line strings that wrapped onto two ragged centred
   * lines at 390px (the clarifier needed ~370px, the trust row ~430px).
   * Tightened just enough that each lands on one. */
  .v2 .hero .cta-note {
    font-size: 10.5px;
    letter-spacing: 0.04em;
  }
  .v2 .hero .trust {
    margin-top: 26px;
    font-size: 10px;
    letter-spacing: 0.07em;
  }

  /* The painting credit was `position:absolute; bottom:18px` — i.e. inside the
   * bottom 120px of the hero, which is exactly the strip the analyse card
   * overlaps (`.analyse{margin-top:-120px}`). On a phone the card is nearly
   * full-bleed, so it covered the credit completely: the provenance line for a
   * Nasjonalmuseet painting was on the page but unreadable. Putting it back in
   * flow under the trust line, and moving the card's clearance from
   * `.hero-inner`'s padding onto the credit's own, puts it above the overlap
   * instead of under it. */
  .v2 .hero-inner {
    padding: 24px 20px 34px;
  }
  .v2 .credit {
    /* `relative`, not `static`: the scrim (`.hero .bg`) is absolutely
     * positioned and comes first in the DOM, so it paints above every
     * non-positioned in-flow sibling. Going static to get back into the flow
     * therefore hid the credit UNDER the gradient — a different way of being
     * invisible than the one this block is fixing. Relative keeps it in flow
     * and in the positioned layer; `bottom` is reset because the base rule's
     * `bottom:18px` would otherwise shift it as an offset. */
    position: relative;
    bottom: auto;
    width: auto;
    padding: 0 20px 132px;
    font-size: 9.5px;
    line-height: 1.5;
    /* In flow it now lands around 82 % of the hero's height, which is where the
     * scrim is already handing over to `--paper` — light 50 %-alpha text on a
     * near-light background is not a credit, it's a ghost (measured on the
     * render: unreadable against the water). The scrim is what makes type legible
     * over this painting everywhere else in the hero; this is the same idea at
     * one line's scale, since the gradient can't be darkened here without
     * breaking the handoff to the section below. */
    color: rgba(246, 243, 236, 0.8);
    text-shadow: 0 1px 7px rgba(10, 10, 7, 0.9);
  }

  /* ── the analyse card ─────────────────────────────────────────────────── */

  /* 38px of card padding on top of the wrap's gutter left the heading a 250px
   * column — "Hvor lekker bedriften / din kunder?" broke after four words. */
  .v2 .abar {
    padding: 24px 20px;
    border-radius: 20px;
  }
  .v2 .aform {
    flex-direction: column;
    align-items: stretch;
  }
  .v2 .aform input,
  .v2 .aform .pill {
    width: 100%;
    min-width: 0;
  }
  .v2 .aform .pill {
    padding: 15px 22px;
  }
  .v2 .gate {
    padding: 22px 20px;
  }

  /* ── sections that were sized for a desktop column ────────────────────── */

  /* A 440px band of photo is over half a phone viewport for one pull quote. */
  .v2 .band img {
    height: 320px;
  }
  .v2 .band .ov {
    padding: 28px 22px;
  }

  /* Both are `min-height:380px` reserving room for content that is either
   * shorter than that on a phone (the feed) or is a labelled placeholder with
   * nothing in it at all (the screenshot slot) — 380px of empty box is half a
   * viewport of scrolling past nothing. */
  .v2 .feed {
    min-height: 0;
    padding: 22px 18px;
  }
  .v2 .shot {
    min-height: 168px;
    border-radius: 20px;
  }

  /* `justify-content:space-between` on a two-item row: the label takes the
   * left, the tag is pushed right and wraps ("push + / SMS", "leads → / jobber
   * → kr"). Stacked, the tag reads as the label's annotation, which is what it
   * is. */
  .v2 .sys li {
    flex-direction: column;
    align-items: flex-start;
    gap: 3px;
  }
  .v2 .sys li span:last-child {
    text-align: left;
    font-size: 13px;
  }

  /* ── footer ───────────────────────────────────────────────────────────── */

  /* space-between wrapped the six items into a ragged two-column block where
   * the second column's right edge was the only thing aligning. One column,
   * and the links get a real tap box (16px line height → 44px). */
  .v2 footer .wrap {
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
  }
  .v2 footer .wrap a {
    display: block;
    padding: 12px 0;
  }
  .v2 footer .wrap span {
    padding: 6px 0;
  }

  /* The one remaining sub-44px target: the niche handoff link. It sits at the
   * end of a paragraph, so it can't take block padding without knocking the
   * line rhythm out — `inline-block` + vertical padding grows the hit box
   * while the text stays on its line. */
  .v2 .niche-line a {
    display: inline-block;
    padding: 12px 0;
  }
}

/* The hero's «Book en prat» is the phone's copy of a link the header already
 * carries above 900px. Hidden rather than duplicated on screen, so a desktop
 * visitor is never offered the same booking page twice in one viewport. */
@media (min-width: 901px) {
  .v2 .hero .talk {
    display: none;
  }
}

/* ═══ THE MODEL, THE PAYMENT STRUCTURE, AND THE OS MODAL ═══════════════════
 * Added 2026-08-06 with the offer-clarity pass. Three new blocks, no new
 * palette and no new form language — every colour below is an existing `.v2`
 * var and the modal borrows `.gate`'s card grammar wholesale.
 */

/* ── «Slik fungerer avtalen» — the deal in three lines ─────────────────────
 * Sits where the niche paragraph used to, at the close of seksjon 01. Styled
 * as a bordered block rather than a card: it is the conclusion of the section
 * above it, not a separate object, and a card would have read as a third
 * element competing with the timeline. */
.v2 .modell {
  margin-top: 34px;
  padding-top: 26px;
  border-top: 1px solid var(--ink);
}
.v2 .modell > .mono {
  color: var(--accent-2);
  margin-bottom: 20px;
}
.v2 .modell ul {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.v2 .modell li {
  display: flex;
  gap: 16px;
  align-items: baseline;
  font-size: clamp(17px, 1.9vw, 21px);
  line-height: 1.45;
}
/* Fixed column so the three sentences start at the same x — the parallel
 * structure IS the readability, and a ragged left edge destroys it. */
.v2 .modell li .k {
  flex-shrink: 0;
  width: 42px;
  font-family: "Geist Mono", monospace;
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}
.v2 .modell li:last-child .t {
  font-weight: 500;
}
.v2 .modell .ingen {
  margin-top: 20px;
  padding-left: 58px;
  font-size: 14.5px;
  color: var(--muted);
}

/* ── «Byrå eller Driftbase?» — the comparison table ────────────────────────
 * Replaced the two-prose-card version (`.betalt` + `.contrast-grid`), which the
 * owner read on the live site and called boring — correctly: a comparison laid
 * out as two paragraphs makes the reader do the comparing.
 *
 * The visual anchor is the HIGHLIGHTED Driftbase column, not the marks. A table
 * of ticks and crosses on flat paper is still just text in a grid; the tinted
 * column running the full height is what makes the eye land on the answer
 * before it reads a single row. Same trick a pricing table uses to mark the
 * recommended plan, and it costs one background colour.
 */
.v2 .vs {
  margin-top: 56px;
  padding-top: 34px;
  border-top: 1px solid var(--line);
}
.v2 .vs > .mono {
  color: var(--accent-2);
  margin-bottom: 20px;
}

/* One grid for the whole table (not a grid per row) so the three columns line
 * up down the page without a fixed width anywhere — the criterion column takes
 * whatever the two mark columns leave. */
.v2 .vs-table {
  display: grid;
  grid-template-columns: 1fr 210px 210px;
  align-items: stretch;
  position: relative;
}
.v2 .vs-head,
.v2 .vs-row {
  display: contents;
}
.v2 .vs-head > span {
  padding: 0 22px 12px;
  font-family: "Geist Mono", monospace;
  font-size: 10.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  border-bottom: 1px solid var(--ink);
}
.v2 .vs-head > span:first-child {
  padding-left: 0;
}
.v2 .vs-row .krav {
  padding: 20px 24px 20px 0;
  font-size: 16.5px;
  line-height: 1.4;
  border-bottom: 1px solid var(--line);
  display: flex;
  align-items: center;
}
.v2 .vs-row .cell {
  padding: 20px 22px;
  border-bottom: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  gap: 6px;
  align-items: flex-start;
}

/* The tinted column. Applied per-cell rather than as one background element,
 * because `display:contents` on the rows means there is no row box to paint and
 * no column box exists in CSS grid at all. */
.v2 .vs-row .cell.drift,
.v2 .vs-head > span:last-child {
  background: var(--soft);
}
.v2 .vs-head > span:last-child {
  color: var(--accent-2);
  border-bottom-color: var(--accent-2);
  border-radius: 14px 14px 0 0;
}
.v2 .vs-row:last-child .cell.drift {
  border-radius: 0 0 14px 14px;
}

.v2 .vs .mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  font-size: 12px;
  line-height: 1;
  flex-shrink: 0;
}
.v2 .vs .mark.x {
  background: rgba(21, 20, 15, 0.06);
  color: var(--muted);
}
.v2 .vs .mark.v {
  background: var(--accent);
  color: #fff;
  font-size: 13px;
}
.v2 .vs .note {
  font-size: 13.5px;
  line-height: 1.45;
  color: var(--muted);
}
/* Visible only on mobile, where the column headers are gone — see the
 * breakpoint block at the end of this file. */
.v2 .vs .lbl {
  display: none;
}
/* Both notes read as the cell's answer, so the Driftbase column no longer needs
 * a visually-hidden one — the ✓ stays aria-hidden decoration over real text. */
.v2 .vs-row .cell.drift .note {
  color: var(--accent-2);
}
.v2 .vs .kanalnote {
  margin-top: 24px;
  max-width: 720px;
  font-size: 14.5px;
  line-height: 1.65;
  color: var(--muted);
}
.v2 .vs .kanalnote strong {
  color: var(--ink);
  font-weight: 500;
}

/* ── The Driftbase OS modal ─────────────────────────────────────────────── */
.v2 .osmodal {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: rgba(10, 10, 7, 0.62);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  /* The dialog can be taller than a short window (the form has five fields and
   * a consent row); scrolling the BACKDROP rather than the card keeps the close
   * button reachable at any height. */
  overflow-y: auto;
}
.v2 .osmodal-card {
  background: var(--paper);
  border-radius: 24px;
  padding: 28px;
  width: 100%;
  max-width: 560px;
  /* `auto` rather than `0` — a modal that traps its own focus ring is worse
   * than a visible outline nobody looks at. */
  outline: auto;
}
.v2 .osmodal-card:focus:not(:focus-visible) {
  outline: none;
}
.v2 .osmodal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 18px;
}
.v2 .osmodal-head h2 {
  font-size: 24px;
}
.v2 .osmodal-x {
  border: none;
  background: var(--surface);
  border-radius: 50%;
  width: 40px;
  height: 40px;
  flex-shrink: 0;
  cursor: pointer;
  font-family: inherit;
  font-size: 14px;
  color: var(--muted);
  line-height: 1;
}
.v2 .osmodal-x:hover {
  color: var(--ink);
}
/* `.gate` is a two-column grid by default (copy left, form right). At the
 * modal's width that would give each column ~240px, so it stacks here always —
 * the same thing `.gate` already does for itself under 700px. */
.v2 .osmodal .gate {
  grid-template-columns: 1fr;
  gap: 18px;
  padding: 0;
  border: none;
  background: transparent;
  border-radius: 0;
}
.v2 .osmodal-more {
  display: inline-block;
  margin-top: 18px;
  font-size: 13.5px;
  color: var(--accent-2);
  text-decoration: underline;
  text-underline-offset: 3px;
}

@media (max-width: 900px) {
  .v2 .modell li {
    /* The 42px label column plus a 21px sentence does not survive a 350px
     * line — the sentences wrapped to three lines each and the parallel
     * structure the column exists to protect was gone anyway. Stacked, the
     * kicker becomes a label above its line and the sentence gets full width. */
    flex-direction: column;
    gap: 3px;
    font-size: 17px;
  }
  .v2 .modell li .k {
    width: auto;
  }
  .v2 .modell .ingen {
    padding-left: 0;
  }

  /* ── the comparison table, un-tabled ────────────────────────────────────
   * Three columns need ~420px before the criterion text stops shredding, so
   * below this width the table stops being a table: each row becomes a block
   * with the criterion as its heading and the two verdicts stacked under it.
   *
   * The column headers go with it, which is why every cell carries a `.lbl`
   * span in the markup — on desktop it is `display:none` and the header row
   * names the columns; here it is the other way round. Two labellings, one
   * visible at a time, so a row is never a mark with nothing saying whose. */
  .v2 .vs-table {
    display: block;
  }
  .v2 .vs-head {
    display: none;
  }
  .v2 .vs-row {
    display: block;
    padding: 18px 0;
    border-bottom: 1px solid var(--line);
  }
  .v2 .vs-row:last-child {
    border-bottom: none;
  }
  .v2 .vs-row .krav {
    display: block;
    padding: 0 0 12px;
    font-size: 16.5px;
    font-weight: 500;
    border-bottom: none;
  }
  /* The tint moves from a full-height column to the single Driftbase cell —
   * there is no column left to run down. */
  .v2 .vs-row .cell,
  .v2 .vs-row:last-child .cell.drift {
    flex-direction: row;
    align-items: center;
    gap: 10px;
    padding: 8px 12px;
    border-bottom: none;
    border-radius: 10px;
  }
  .v2 .vs-row .cell.drift {
    margin-top: 6px;
  }
  .v2 .vs .lbl {
    display: block;
    flex-shrink: 0;
    width: 86px;
    font-family: "Geist Mono", monospace;
    font-size: 9.5px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--muted);
  }
  .v2 .vs-row .cell.drift .lbl {
    color: var(--accent-2);
  }

  /* `.integrasjoner` pulls itself up 66px so it reads as a footnote to the
   * section above rather than its own chapter. That was measured against the
   * desktop rhythm (110px of section padding, leaving ~44px of air); against
   * this breakpoint's 68px it leaves TWO pixels, and «Ingen oppstartskost…»
   * ended up welded to «JOBBER SAMMEN MED». Same intent, re-measured for the
   * padding that actually applies here. */
  .v2 .integrasjoner {
    margin-top: -24px;
  }

  .v2 .osmodal {
    padding: 0;
    align-items: flex-end;
  }
  /* Bottom sheet on a phone: full width, square at the bottom edge, and capped
   * so the backdrop stays tappable above it as a way out. */
  .v2 .osmodal-card {
    max-width: none;
    border-radius: 22px 22px 0 0;
    max-height: 92vh;
    max-height: 92svh;
    overflow-y: auto;
    padding: 22px 20px 28px;
  }
}

/* ═══ THE REBUILD: PRODUCT VISUAL + LIGHT/DARK RHYTHM ══════════════════════
 * Owner read the live page 2026-08-06: "just beige and text… no visual
 * understanding". Everything below serves the two structural fixes — show the
 * product, and give the page chapters the eye can feel. No new palette: every
 * colour is an existing `.v2` var.
 */

/* ── 02 «Vi fyller denne» — the dark product band ─────────────────────────── */
.v2 .kalender .lede {
  color: var(--pmuted);
  font-size: 17px;
  max-width: 460px;
}
.v2 .kal-grid {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 64px;
  align-items: center;
}
.v2 .kal-points {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 22px;
  margin-top: 34px;
  padding-top: 28px;
  border-top: 1px solid rgba(246, 243, 236, 0.14);
}
.v2 .kal-points li {
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--pmuted);
  max-width: 440px;
}
.v2 .kal-points .mono {
  display: block;
  color: var(--accent-light);
  margin-bottom: 5px;
}
.v2 .kal-os {
  margin-top: 30px;
  padding-top: 24px;
  border-top: 1px solid rgba(246, 243, 236, 0.14);
  font-size: 14px;
  line-height: 1.6;
  color: var(--pmuted);
  max-width: 460px;
}
.v2 .kal-os strong {
  color: var(--paper);
  font-weight: 500;
}
/* The OS trigger is a plain `.pill.ghost` — white on transparent, which is
 * already correct against this band. It used to carry a `.dark-ghost` variant
 * for the light section it lived in before the rebuild; that rule is gone,
 * because on the dark band it painted the button near-black on near-black. */
.v2 .kalender .pill.ghost {
  margin-top: 16px;
}

/* ── the phone ────────────────────────────────────────────────────────────
 * A device frame, not a screenshot: ~2 kB of DOM, sharp at any density, and it
 * can animate — which is the point, since the rows ARRIVING is the promise.
 */
.v2 .kaltel-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}
.v2 .kaltel {
  width: 300px;
  flex-shrink: 0;
  background: #24221c;
  border-radius: 40px;
  padding: 11px;
  box-shadow: 0 40px 90px -30px rgba(0, 0, 0, 0.75), inset 0 0 0 1px rgba(246, 243, 236, 0.09);
}
.v2 .kaltel-screen {
  background: var(--paper);
  border-radius: 30px;
  padding: 22px 18px 18px;
  /* Fixed height so the frame does not jolt taller as rows appear — the whole
   * illusion depends on the phone being a physical object. */
  min-height: 396px;
}
.v2 .kaltel-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding-bottom: 12px;
  margin-bottom: 6px;
  border-bottom: 1px solid var(--line);
}
.v2 .kaltel-top .mono {
  color: var(--muted);
}
.v2 .kaltel-count {
  font-size: 19px;
  font-weight: 500;
  color: var(--accent-2);
  font-variant-numeric: tabular-nums;
}
.v2 .kaltel-count span {
  font-size: 11.5px;
  font-weight: 400;
  color: var(--muted);
}
.v2 .kaltel-list {
  list-style: none;
}
.v2 .kaltel-list li {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 11px 12px;
  margin-top: 7px;
  border-radius: 12px;
  background: var(--soft);
  border-left: 3px solid var(--accent);
  opacity: 0;
  transform: translateY(-6px);
  transition: opacity 0.45s ease, transform 0.45s ease;
}
.v2 .kaltel-list li.in {
  opacity: 1;
  transform: none;
}
.v2 .kaltel-list .when {
  font-family: "Geist Mono", monospace;
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent-2);
}
.v2 .kaltel-list .what {
  font-size: 13.5px;
  line-height: 1.3;
  color: var(--ink);
}
.v2 .kaltel-wrap figcaption {
  font-family: "Geist Mono", monospace;
  font-size: 9.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--pmuted);
  text-align: center;
  max-width: 300px;
  line-height: 1.6;
}
/* Motion is decoration here — the resting state (all rows visible) is the
 * honest one, and the component already skips the effect for these users. This
 * kills any transition that a mid-flight state might leave running. */
@media (prefers-reduced-motion: reduce) {
  .v2 .kaltel-list li {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* ── 03 «Slik fungerer det» + 04 «Byrå eller Driftbase?» as sections ───────
 * Both were `<div>`s inside other sections until the rebuild. As their own
 * sections they inherit `.v2 section`'s padding, so the margin/border that used
 * to separate them from a sibling above would now double it. */
.v2 .modell,
.v2 .vs {
  margin-top: 0;
  padding-top: 0;
  border-top: none;
}
/* The kicker duplicated the section eyebrow once these grew headings. */
.v2 .modell > .mono,
.v2 .vs > .mono {
  display: none;
}
.v2 .vs-section {
  padding-top: 0;
}

/* ── the rhythm ───────────────────────────────────────────────────────────
 * `.dark` sections used to be a one-off (the proof band). Now that they carry
 * the page's chapter structure they need the same eyebrow treatment wherever
 * they appear, not only under `.dark .eyebrow`. */
.v2 .dark h2,
.v2 .dark h3 {
  color: var(--paper);
}
.v2 .dark .lede {
  color: var(--pmuted);
}

@media (max-width: 900px) {
  /* The phone goes UNDER the copy, not beside it — and centred, because a
   * device image floated left on a phone reads as a broken column. */
  .v2 .kal-grid {
    grid-template-columns: 1fr;
    gap: 38px;
  }
  .v2 .kaltel {
    width: 100%;
    max-width: 300px;
    margin: 0 auto;
  }
  .v2 .kal-points,
  .v2 .kal-os,
  .v2 .kalender .lede {
    max-width: none;
  }
}
