/* ===========================================================================
   v2 — base tokens, reset, and shared primitives.

   Design language adapted from the supplied Doppler reference. Every surface
   and text colour below is carried over verbatim from the live site; the only
   colour change is one of discipline, described under "Accent grammar".
   =========================================================================== */

/* Tokens are declared on `body.v2`, deliberately NOT on `:root`.

   `:root` matches the <html> element, which no class on <body> can ever scope.
   A `:root` block in this file would therefore apply globally the instant this
   stylesheet were loaded on any other page — silently restyling the live site,
   which is the one thing v2 must never be able to do. Declaring on body.v2
   contains the tokens properly, and inheritance still carries them to
   everything inside. */
body.v2 {
  /* --- Surfaces: identical values to the live site --- */
  --bg-void: #131b2e;
  --bg-surface: #1c2740;
  --bg-surface-alt: #24304d;
  --border-subtle: #2e3b59;
  --border-strong: #3a4a6b;

  /* The reference separates surfaces with a light hairline at 10-15% opacity
     rather than with shadows. Derived from --text-primary so it reads as light
     catching an edge, which a flat navy border does not. */
  --hairline: rgba(238, 241, 248, 0.09);
  --hairline-strong: rgba(238, 241, 248, 0.16);

  /* --- Text: identical values to the live site --- */
  --text-primary: #eef1f8;
  --text-muted: #93a0bf;

  /* --- Accent grammar -------------------------------------------------
     The reference's defining trait is two accents with strictly separated
     jobs, so a visitor learns "this colour means click, that colour means
     brand" without being told. Adopting its layout without that rationing
     loses most of what makes it read as deliberate.

     The live site has one accent doing every job. v2 splits the palette it
     already has into the same two roles, inventing no new colour:

       --accent        coral, ACTION ONLY. Buttons and CTAs. Never on a
                       non-interactive element. Max one filled coral button
                       per viewport.
       --accent-voice  marine blue, BRAND VOICE ONLY. Eyebrow labels,
                       highlighted headline words, card labels. Never body
                       copy.

     Coral is the warm hue opposite the navy canvas, so it carries the most
     visual force — correctly spent on the thing that must be clicked. Blue
     already exists in the live palette (--hero-blue). */
  --accent: #dd7867;
  --accent-soft: rgba(221, 120, 103, 0.15);
  --accent-glow: rgba(221, 120, 103, 0.35);
  --accent-voice: #6cc0ff;
  --accent-voice-deep: #3f8cff;
  /* Informational note surfaces. Marine, NOT coral: a coral-tinted box read as a
     warning or an error to Buğra on 2026-09-13, because coral is the action and
     error colour. Errors keep their own coral .account-error. */
  --accent-voice-soft: rgba(108, 192, 255, 0.08);
  --accent-voice-line: rgba(108, 192, 255, 0.28);

  --font-heading: 'Sora', -apple-system, sans-serif;
  --font-body: 'Inter', -apple-system, sans-serif;

  /* --- Radius: the reference's four-step scale. The live site has only two
         (12/20), so small elements and pills had nothing of their own. --- */
  --radius-sm: 8px;
  --radius-btn: 12px;
  --radius-card: 20px;
  --radius-pill: 9999px;

  /* --- Spacing: 8px base unit --- */
  --s-1: 8px;
  --s-2: 16px;
  --s-3: 24px;
  --s-4: 32px;
  --s-5: 40px;
  --s-6: 56px;
  --s-7: 80px;
  --s-8: 120px;

  --container-width: 1200px;
  --nav-height: 68px;
}

/* ===== Reset ===== */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; }

body.v2 {
  background: var(--bg-void);
  color: var(--text-primary);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  /* `clip` not `hidden`: overflow-x:hidden forces the y axis to `auto`, which
     turns the page into its own scroll container and breaks position:sticky on
     the nav. `clip` constrains one axis without touching the other. */
  overflow-x: clip;
}

.v2 img { max-width: 100%; display: block; }
.v2 a { color: inherit; text-decoration: none; }
.v2 button { font-family: inherit; cursor: pointer; }

/* ===== Type scale =====
   Minor third from 16px. The reference tightens tracking as size grows and
   opens it at caption sizes; both are what stop large headings reading loose
   and small labels reading cramped. */
.v2 h1, .v2 h2, .v2 h3, .v2 h4 {
  font-family: var(--font-heading);
  font-weight: 500;
  line-height: 1.15;
  letter-spacing: -0.02em;
}

.v2 .t-display {
  font-size: clamp(38px, 6.2vw, 64px);
  line-height: 1.04;
  letter-spacing: -0.03em;
  font-weight: 700;
}
.v2 .t-h2 { font-size: clamp(28px, 4vw, 44px); }
.v2 .t-h3 { font-size: 24px; letter-spacing: -0.01em; }
.v2 .t-body { font-size: 16px; line-height: 1.6; }
.v2 .t-body-sm { font-size: 15px; line-height: 1.6; }
.v2 .t-caption { font-size: 12px; line-height: 1.5; letter-spacing: 0.03em; }

/* ===== Layout ===== */
.v2 .container {
  width: 100%;
  max-width: var(--container-width);
  margin: 0 auto;
  padding: 0 var(--s-3);
}
.v2 .section { padding: var(--s-7) 0; }
@media (min-width: 768px) {
  .v2 .section { padding: var(--s-8) 0; }
}

/* ===== Section headings ===== */
/* Eyebrow is brand voice, so it takes blue — never coral, which in v2 means
   "clickable" and would be a lie on a static label. */
.v2 .eyebrow {
  display: block;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent-voice);
  margin-bottom: var(--s-2);
}
.v2 .section-head {
  max-width: 700px;
  margin: 0 auto var(--s-6);
  text-align: center;
}
.v2 .section-head .eyebrow { text-align: center; }
.v2 .section-head p {
  color: var(--text-muted);
  font-size: 17px;
  line-height: 1.6;
  margin-top: var(--s-2);
  text-wrap: pretty;
}
.v2 .section-title { text-wrap: balance; }

/* Gradient run across the highlighted words of a headline, mirroring the
   reference's violet-to-orange treatment.

   Deliberately blue-to-light-blue rather than blue-to-coral, for two reasons.
   Grammatically, coral means "clickable" in v2, and a headline is not. Visually,
   blue and coral sit near-opposite on the wheel, so a gradient between them
   passes through a desaturated grey at its midpoint — with three highlighted
   words the middle one lands squarely in it and reads as washed out. A ramp
   within one hue family stays saturated the whole way across.

   inline-block is required — background-clip:text on an inline element breaks
   across line boxes and clips to the wrong geometry. */
.v2 .grad-words {
  display: inline-block;
  background: linear-gradient(96deg, var(--accent-voice-deep) 4%, var(--accent-voice) 96%);
  -webkit-background-clip: text;
          background-clip: text;
  -webkit-text-fill-color: transparent;
          color: transparent;
}

/* ===== Buttons =====
   Coral is action-only, and the reference caps filled accent buttons at one
   per viewport. Everything secondary is a ghost button. */
.v2 .btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-1);
  padding: 13px 24px;
  border-radius: var(--radius-btn);
  font-weight: 600;
  font-size: 15px;
  line-height: 1;
  border: 1px solid transparent;
  transition: transform 0.15s ease, box-shadow 0.15s ease,
              background 0.15s ease, border-color 0.15s ease;
}
.v2 .btn-primary {
  background: var(--accent);
  color: #1a0f0c;
}
.v2 .btn-primary:hover {
  transform: translateY(-1px);
  box-shadow: 0 10px 28px var(--accent-glow);
}
.v2 .btn-ghost {
  background: transparent;
  border-color: var(--hairline-strong);
  color: var(--text-primary);
}
.v2 .btn-ghost:hover {
  background: var(--bg-surface);
  border-color: var(--border-strong);
}
/* Trailing arrow affordance, per the reference's link/CTA spec. */
.v2 .btn .arrow { transition: transform 0.15s ease; }
.v2 .btn:hover .arrow { transform: translateX(3px); }

/* ===== Nav =====
   Glass from page load rather than materializing on scroll, per the
   reference's sticky-glass header spec. */
.v2 .nav {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgba(19, 27, 46, 0.72);
  backdrop-filter: blur(14px) saturate(140%);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  border-bottom: 1px solid var(--hairline);
}
.v2 .nav .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  height: var(--nav-height);
}
.v2 .nav-logo {
  display: flex;
  align-items: center;
  gap: var(--s-1);
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 18px;
  letter-spacing: -0.01em;
  flex-shrink: 0;
}
.v2 .nav-logo img { width: 24px; height: 24px; object-fit: contain; }
/* Touch: the logo is also the link home, and at 27px tall it was a thin strip
   to aim at. Height only — the bar is 68px, so this changes nothing visually. */
@media (pointer: coarse) { .v2 .nav-logo { min-height: 44px; } }
.v2 .nav-links {
  display: none;
  gap: var(--s-3);
  list-style: none;
}
@media (min-width: 860px) { .v2 .nav-links { display: flex; } }
.v2 .nav-links a {
  font-size: 14px;
  color: var(--text-muted);
  transition: color 0.15s ease;
}
.v2 .nav-links a:hover { color: var(--text-primary); }

/* The account link is the only item in this list that is not a section of the
   site, so a hairline sets it apart instead of letting it read as a fifth
   content link. Desktop only: below 860px the list becomes the drop-down
   panel, where `li + li` already draws a top border between every row and a
   left border would cut across it. */
@media (min-width: 860px) {
  .v2 .nav-account {
    padding-left: var(--s-3);
    border-left: 1px solid var(--hairline);
  }
}

/* ===== Mobile menu (below 860px) =====
   Above this width the links sit inline and the toggle does not exist. Below
   it they used to be `display: none` with nothing in their place, which left
   every section of the site unreachable from the nav on a phone — the CTA was
   the only thing a visitor could press. */
.v2 .nav-toggle { display: none; }

@media (max-width: 859px) {
  .v2 .nav-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* 44px is the tap-target floor; the bars inside are much smaller, so the
       button is padded out to reach it rather than being drawn that big. */
    width: 44px;
    height: 44px;
    margin: 0;
    padding: 0;
    flex-shrink: 0;
    background: none;
    border: 1px solid var(--hairline);
    border-radius: var(--radius-btn);
    color: var(--text-primary);
    cursor: pointer;
  }

  /* The middle bar is the element itself; the other two are its pseudo-
     elements, offset above and below. Collapsing to an X is then just
     rotating those two and hiding the middle one. */
  .v2 .nav-toggle-bars,
  .v2 .nav-toggle-bars::before,
  .v2 .nav-toggle-bars::after {
    display: block;
    width: 18px;
    height: 2px;
    border-radius: 2px;
    background: currentColor;
    transition: transform 0.2s ease, opacity 0.2s ease;
  }
  .v2 .nav-toggle-bars { position: relative; }
  .v2 .nav-toggle-bars::before,
  .v2 .nav-toggle-bars::after { content: ""; position: absolute; left: 0; }
  .v2 .nav-toggle-bars::before { top: -6px; }
  .v2 .nav-toggle-bars::after  { top: 6px; }

  .v2 .nav-toggle[aria-expanded="true"] .nav-toggle-bars { background: transparent; }
  .v2 .nav-toggle[aria-expanded="true"] .nav-toggle-bars::before { transform: translateY(6px) rotate(45deg); }
  .v2 .nav-toggle[aria-expanded="true"] .nav-toggle-bars::after  { transform: translateY(-6px) rotate(-45deg); }

  /* The panel. Positioned against .nav (sticky, so it is a containing block)
     rather than .nav .container, so it spans the full width of the bar
     instead of stopping at the container's gutters. */
  .v2 .nav-links {
    display: block;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    padding: var(--s-2) var(--s-3) var(--s-3);
    /* Fully opaque, unlike the bar above it. The bar's glass works because
       what shows through is page background; this panel hangs over the hero,
       and at 96% alpha the headline ghosted through it clearly enough to read
       — the letters sat right behind the link labels. A menu has to be legible
       before it is pretty, so this one is solid. */
    background: var(--bg-surface);
    border-bottom: 1px solid var(--hairline);
    box-shadow: 0 18px 40px rgba(0, 0, 0, 0.45);
    /* visibility (not just opacity) so the links are genuinely unreachable by
       keyboard or screen reader while closed, and it is still transitionable
       — display:none would kill the animation outright. */
    visibility: hidden;
    opacity: 0;
    transform: translateY(-8px);
    transition: opacity 0.18s ease, transform 0.18s ease, visibility 0.18s;
  }
  .v2 .nav-links.is-open {
    visibility: visible;
    opacity: 1;
    transform: none;
  }
  .v2 .nav-links li + li { border-top: 1px solid var(--hairline); }
  .v2 .nav-links a {
    display: flex;
    align-items: center;
    min-height: 48px;
    font-size: 16px;
    color: var(--text-primary);
  }

  /* Tighten the bar so logo + CTA + toggle all still fit on one row at common
     phone widths. Without this the row needed ~410px and the CTA had to be
     dropped at 390px — an extremely common phone size, and the CTA is the
     whole point of the bar. Trimming type and padding buys back ~55px, which
     is enough down to 360px. */
  .v2 .nav .container { gap: var(--s-2); }
  .v2 .nav-logo { font-size: 16px; }
  .v2 .nav-cta {
    /* Horizontal padding is what buys the space, so trim only that. min-height
       holds the button at a full tap target — without it, the reduced padding
       took it to 38px tall, trading one mobile problem for another. */
    padding: 11px 14px;
    font-size: 14px;
    min-height: 44px;
  }

  /* Below ~360px even the tightened row runs out of space. The CTA is what
     gives: the hero's own primary button repeats it a short scroll down,
     whereas the toggle is the only route to the rest of the site. */
  @media (max-width: 359px) {
    .v2 .nav-cta { display: none; }
  }
}

@media (prefers-reduced-motion: reduce) {
  .v2 .nav-links,
  .v2 .nav-toggle-bars,
  .v2 .nav-toggle-bars::before,
  .v2 .nav-toggle-bars::after { transition: none; }
}

/* ===== Footer =====
   Reworked 2026-09-10, from a render rather than from the code.

   What was wrong: the ANPC banners sat at the TOP, and being two bright white
   cards on dark navy they were the largest, highest-contrast objects on the
   page's last screen — so the eye landed on a legal obligation before it found
   the brand or the menu. There was no brand mark here at all, and everything
   was one centred column of muted 14px text, which gives a reader no hierarchy
   to read.

   Four changes: the banners moved below the navigation (Buğra's call, and most
   of the fix), the wordmark now anchors the top, the menu was promoted from
   muted 14px to primary-colour 15px, and the top edge became a gradient
   hairline instead of a flat rule.

   A left/right split (brand hard left, menu hard right) was built first and
   rejected on sight: at 1280 it left ~900px of dead space between the two, and
   a three-column menu to fill it produced ragged columns pairing links that
   have nothing to do with each other. Centred and symmetrical is the honest
   answer for six links and one wordmark. */
.v2 .footer {
  padding: var(--s-6) 0 var(--s-4);
  color: var(--text-muted);
  font-size: 14px;
  position: relative;
}

/* The one deliberate flourish, and the only place brand colour appears down
   here: the top edge fades in from nothing, peaks in marine, and fades out
   again, rather than ruling flat across. A border cannot hold a gradient, so
   it is a 1px pseudo-element.

   Marine, not coral: this is brand voice, not an action. Coral means "click me"
   in this codebase and is rationed to one filled button per viewport — spending
   it on a rule nobody can press would blunt the signal everywhere else. */
.v2 .footer::before {
  content: "";
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  height: 1px;
  background: linear-gradient(
    to right,
    transparent,
    var(--hairline) 22%,
    rgba(108, 192, 255, 0.34) 50%,
    var(--hairline) 78%,
    transparent
  );
}

/* --- Brand, then menu, centred --- */
.v2 .footer-main {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--s-4);
  padding-bottom: var(--s-5);
}

.v2 .footer-brand {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}
.v2 .footer-brand img {
  display: block;
  width: 152px;
  height: auto;
}
/* The wordmark is a link, so it should say so on hover — the image alone does
   not — and it needs a focus ring like any other. */
.v2 .footer-brand a {
  display: inline-block;
  border-radius: var(--radius-sm);
  opacity: .92;
  transition: opacity .15s ease;
}
.v2 .footer-brand a:hover { opacity: 1; }

.v2 .footer-tagline {
  margin: 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--text-muted);
}

/* --- The menu, deliberately promoted ---
   Brighter (primary, not muted), a step larger, medium weight: the brief was
   that it should stand out, and previously it read as an afterthought beneath
   the banners.

   FLEX-WRAP, NOT A COLUMN GRID. `grid-auto-flow: column` was tried and is
   actively broken on a phone: it compresses the columns into each other rather
   than wrapping, so at 390px "Contact" and "Pricing" overlapped into
   "ConPraicting". Worse, it passed an overflow check — nothing crossed the
   viewport edge, because the links were squashed rather than pushed out. Only
   the screenshot caught it. A wrapping flex row needs no media query to behave
   at any width. */
.v2 .footer-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px var(--s-4);
}
.v2 .footer-links a {
  position: relative;
  color: var(--text-primary);
  font-size: 15px;
  font-weight: 500;
  line-height: 1.4;
}
/* Coral earns its place here: the underline appears only on hover or keyboard
   focus, so it marks the interactive state rather than decorating a resting
   element. */
.v2 .footer-links a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -3px;
  height: 1.5px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .18s ease;
}
.v2 .footer-links a:hover::after,
.v2 .footer-links a:focus-visible::after { transform: scaleX(1); }

@media (prefers-reduced-motion: reduce) {
  .v2 .footer-links a::after { transition: none; }
  .v2 .footer-brand a { transition: none; }
}

/* Touch devices: pad the footer links out to a real tap target. They were 21px
   tall — the text's own line box — which is half the 44px guideline and hard
   to hit accurately with a thumb. Scoped to coarse pointers so a mouse-driven
   layout keeps its tighter rhythm. */
@media (pointer: coarse) {
  .v2 .footer-links a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
}

/* --- Netopia payment mark ---
   Restored 2026-09-11: Revolut declined the merchant API application, so the
   processor is Netopia again. It was removed 2026-09-10 for the mirror-image
   reason — see MARKETING-ROADMAP.md. Netopia also require the mark displayed
   as a condition of opening the point of sale, so this is a storefront
   obligation, not only a trust signal.

   White lettering on transparency: it depends on the footer staying dark and
   would vanish on a light background.

   140px, not the ANPC banners' 200px. White lettering on a dark ground carries
   far more visual weight than their navy-on-white cards, so matching their
   ~50px height BY EYE means going narrower — measured equality would read as
   the payment mark shouting over the legal ones. */
.v2 .footer-netopia {
  display: flex;
  justify-content: center;
  align-items: center;
  padding-bottom: var(--s-3);
}
.v2 .footer-netopia img {
  display: block;
  width: 140px;
  max-width: 100%;
  height: auto;
}

/* --- ANPC consumer-protection banners (SAL + SOL) ---
   Required for Romanian e-commerce, and real links to ANPC's and the EU
   Commission's own pages — a decorative image alone does not satisfy it.

   MUST NOT BE RECOLOURED OR FILTERED, being official marks. They are therefore
   NOT dimmed at rest: the demotion is by position and size only. Both source
   images are white cards with navy text, so they read correctly on the dark
   footer untouched. They wrap to their own lines on narrow screens rather than
   shrinking, so the text inside stays legible. */
.v2 .footer-anpc {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  justify-content: center;
  align-items: center;
  padding-bottom: var(--s-4);
}
.v2 .footer-anpc img {
  display: block;
  width: 200px;
  max-width: 100%;
  height: auto;
}
.v2 .footer-anpc a {
  display: block;
  border-radius: 6px;
  transition: opacity .15s ease;
}
.v2 .footer-anpc a:hover { opacity: .85; }
@media (prefers-reduced-motion: reduce) {
  .v2 .footer-anpc a { transition: none; }
}

/* --- Baseline --- */
.v2 .footer-bottom {
  text-align: center;
  padding-top: var(--s-3);
  border-top: 1px solid var(--hairline);
  font-size: 13px;
}
.v2 .footer-legal { margin: 0; }
.v2 .footer-made {
  margin: 6px 0 0;
  color: var(--text-muted);
}
/* Segoe UI Emoji draws the heart on a different baseline from Inter, so it sits
   low against the text. -1.35px measured, not guessed (tools/measure-heart.mjs).
   This read translateY(1px) until 2026-09-11 -- which moved it DOWN, deepening
   the very gap the comment claimed to close. */
.v2 .footer-made span {
  display: inline-block;
  transform: translateY(-1.35px);
  font-size: 12px;
}

@media (max-width: 720px) {
  .v2 .footer { padding-top: var(--s-5); }
  .v2 .footer-main { gap: var(--s-3); padding-bottom: var(--s-4); }
}
/* ===== Scroll reveal =====
   Implemented as @keyframes, not transitions — the same hard-won constraint as
   the live site's main.css. A transition-based reveal collides with component
   hover styles over the same properties: the component's own `transition`
   declaration replaces the reveal's wholesale, and stagger applied as
   transition-delay persists after entry and then delays every later hover by a
   different amount per element. Animations are a separate system, so a
   component keeps `transition` for hover untouched, and stagger uses
   animation-delay, which cannot leak. */
.v2 [data-reveal] { opacity: 0; }
.v2 [data-reveal].is-visible {
  animation: v2-reveal-up 0.7s cubic-bezier(.22,.61,.36,1) both;
  will-change: opacity, transform;
}
.v2 [data-reveal="left"].is-visible  { animation-name: v2-reveal-left; }
.v2 [data-reveal="right"].is-visible { animation-name: v2-reveal-right; }

/* Dropped on animationend. This matters beyond tidiness: a running animation
   with fill-mode `both` outranks normal declarations, so its final keyframe
   (transform: none) would otherwise permanently beat any component's :hover
   transform. */
.v2 [data-reveal].reveal-done {
  animation: none;
  opacity: 1;
  will-change: auto;
}

@keyframes v2-reveal-up {
  from { opacity: 0; transform: translateY(24px); }
  to   { opacity: 1; transform: none; }
}
@keyframes v2-reveal-left {
  from { opacity: 0; transform: translateX(-30px); }
  to   { opacity: 1; transform: none; }
}
@keyframes v2-reveal-right {
  from { opacity: 0; transform: translateX(30px); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .v2 [data-reveal],
  .v2 [data-reveal].is-visible,
  .v2 [data-reveal].reveal-done {
    opacity: 1;
    transform: none;
    animation: none !important;
  }
  .v2 .btn:hover { transform: none; }
  .v2 html { scroll-behavior: auto; }
}
