/* ===================================================================
   CodiVibes — marketing site
   -------------------------------------------------------------------
   Direction: industrial / utilitarian. A workshop spec sheet, not a
   startup landing page. Hairline rules, numbered sections, monospaced
   metadata, square corners, one hot accent on a warm near-black ground.
   The point is to look like equipment for running a business, because
   that is what is being sold — not "an AI product".

   Every face here carries Cyrillic (Unbounded / Manrope / JetBrains
   Mono). That is a hard constraint: the Bulgarian pages and the
   invoices share this type. Do not substitute a Latin-only display
   font.
   =================================================================== */

@import url('https://fonts.googleapis.com/css2?family=Unbounded:wght@400;600;800&family=Manrope:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap');

:root {
  --bg:        #0c0a09;
  --bg-2:      #141010;
  --bg-3:      #1a1513;
  --line:      #2c2320;
  --line-soft: #1e1917;
  --ink:       #f7f2ec;
  --muted:     #a9a09a;
  --muted-2:   #8a817b;   /* was #776f6a — 3.68:1 on cards, under AA */

  /* Sampled from the printed logo, not picked by eye. The previous #b45309
     was both a different orange from the mark and only 3.93:1 here, which
     fails AA for the small mono labels it was being used on. */
  --brand:      #cc6126;   /* the logo's ink            — 4.99:1 on --bg */
  --brand-hot:  #ee7f3e;   /* emphasis text and hovers  — 7.28:1 on --bg */
  --brand-wash: rgba(204, 97, 38, 0.13);
  --sand:       #d9c3a0;   /* the logo's second ink     — 11.5:1 on --bg */
  /* Orange this bright cannot carry white text (3.96:1), so anything sitting
     ON the brand colour uses the page ink instead (4.99:1). */
  --on-brand:   #0c0a09;

  --display: 'Unbounded', 'Trebuchet MS', sans-serif;
  --body:    'Manrope', 'Segoe UI', sans-serif;
  --mono:    'JetBrains Mono', 'Consolas', monospace;

  --gutter: clamp(20px, 5vw, 64px);
  --maxw: 1180px;
}

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

/* The masthead is sticky and 68px tall, so an anchor jump left the target's
   marker and the top of its heading underneath it — 87px of every "Apply" and
   "Get in touch" section was hidden on arrival. scroll-padding-top on the
   scrolling element fixes it once for smooth anchors, browser find, and
   focus-driven scrolling alike, rather than needing scroll-margin on each id. */
html { scroll-behavior: smooth; scroll-padding-top: 92px; }

body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--body);
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  /* Faint blueprint grid + a warm bloom behind the masthead. Atmosphere
     without an illustration to go stale. */
  background-image:
    radial-gradient(60rem 30rem at 78% -8%, rgba(204, 97, 38, 0.16), transparent 62%),
    linear-gradient(var(--line-soft) 1px, transparent 1px),
    linear-gradient(90deg, var(--line-soft) 1px, transparent 1px);
  background-size: 100% 100%, 88px 88px, 88px 88px;
  background-attachment: fixed, scroll, scroll;
}

img, svg { display: block; max-width: 100%; }
svg { stroke-width: 1.6; }

::selection { background: var(--brand); color: var(--on-brand); }

/* Keyboard focus. The browser default here is a 1px rgb(16,16,16) ring, which
   on this near-black ground is 1.06:1 — a keyboard user could not see where
   they were on any page. --brand-hot is 7.28:1 on --bg, and the 3px offset
   keeps the ring on the page background even around the solid orange button,
   where the two oranges would otherwise sit on top of each other.
   :focus-visible, not :focus, so a mouse click never draws it. */
:focus-visible {
  outline: 2px solid var(--brand-hot);
  outline-offset: 3px;
  border-radius: 2px;
}

/* ── Layout ──────────────────────────────────────────────────────── */

/* padding-inline, not the shorthand: nearly every <section> is also a .shell, and
   a class beats an element selector — so `padding: 0 …` here silently zeroed the
   vertical rhythm the `section` rule below asks for, butting each section's text
   against the next one's marker. Declaring only the inline axis leaves the block
   axis to `section` (and to `.hero`, which sets its own). */
.shell { max-width: var(--maxw); margin: 0 auto; padding-inline: var(--gutter); }

section { padding: clamp(56px, 8vw, 108px) 0; border-top: 1px solid var(--line-soft); }
section:first-of-type { border-top: 0; }

/* Numbered section marker — "03 / PRICING". The serial numbering is the
   spec-sheet cue that ties the whole site together. */
.marker {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted-2);
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 26px;
}
.marker::after { content: ''; flex: 1; height: 1px; background: var(--line); }
.marker b { color: var(--brand-hot); font-weight: 500; }

/* ── Typography ──────────────────────────────────────────────────── */

h1, h2, h3 { font-family: var(--display); font-weight: 800; line-height: 1.06; letter-spacing: -0.02em; }
h1 { font-size: clamp(34px, 6.2vw, 68px); }
h2 { font-size: clamp(26px, 3.9vw, 42px); }
h3 { font-size: clamp(17px, 2vw, 21px); font-weight: 600; line-height: 1.25; }

.lede { font-size: clamp(17px, 2.1vw, 21px); color: var(--muted); max-width: 60ch; }
.small { font-size: 14px; color: var(--muted); }
.tiny { font-family: var(--mono); font-size: 12px; letter-spacing: 0.08em; color: var(--muted-2); }
.hot { color: var(--brand-hot); }
strong { font-weight: 700; color: var(--ink); }

a { color: inherit; }

/* ── Buttons ─────────────────────────────────────────────────────── */

.btn {
  display: inline-flex; align-items: center; gap: 10px;
  font-family: var(--body); font-weight: 700; font-size: 15px;
  padding: 14px 24px;
  background: var(--brand); color: var(--on-brand);
  border: 1px solid var(--brand); border-radius: 2px;
  text-decoration: none; cursor: pointer;
  transition: background .16s ease, transform .16s ease, box-shadow .16s ease;
}
.btn:hover { background: var(--brand-hot); border-color: var(--brand-hot); transform: translateY(-1px); box-shadow: 0 6px 22px rgba(204, 97, 38, .28); }
.btn.ghost { background: transparent; color: var(--ink); border-color: var(--line); box-shadow: none; }
.btn.ghost:hover { border-color: var(--brand-hot); color: var(--brand-hot); background: transparent; transform: translateY(-1px); }
.btn.sm { padding: 10px 16px; font-size: 14px; }

.btn-row { display: flex; flex-wrap: wrap; gap: 14px; align-items: center; }

/* ── Masthead ────────────────────────────────────────────────────── */

.masthead {
  position: sticky; top: 0; z-index: 40;
  background: rgba(12, 10, 9, 0.88);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line-soft);
}
.masthead .shell { display: flex; align-items: center; gap: 20px; height: 68px; }

/* The logo ships as one cached file rather than inline markup: at 7KB a copy,
   inlining it in the masthead and the footer of all 15 pages would add more
   bytes to every page than it saves in requests. width/height on the <img>
   carry the aspect ratio, so height alone sizes it without layout shift. */
.wordmark { display: block; text-decoration: none; flex: none; }
.wordmark img { display: block; height: 28px; width: auto; }
.foot .wordmark img { height: 26px; }

.mainnav { display: flex; gap: 26px; margin-left: auto; }
.mainnav a {
  font-size: 14px; font-weight: 600; color: var(--muted); text-decoration: none;
  padding: 6px 0; border-bottom: 1px solid transparent; transition: color .14s, border-color .14s;
}
.mainnav a:hover, .mainnav a[aria-current] { color: var(--ink); border-color: var(--brand); }

.mast-actions { display: flex; align-items: center; gap: 14px; }

/* Language pill — EN | BG. Present on every page that has both. */
.langsw { display: flex; border: 1px solid var(--line); border-radius: 2px; overflow: hidden; }
.langsw a {
  font-family: var(--mono); font-size: 12px; letter-spacing: .06em;
  padding: 6px 10px; text-decoration: none; color: var(--muted-2);
  transition: background .14s, color .14s;
}
.langsw a:hover { color: var(--ink); }
.langsw a[aria-current] { background: var(--brand-wash); color: var(--brand-hot); }
/* On a touch screen the pill is only 31px tall — under the 44px a fingertip
   needs. Grow the target, not the text, and only where there is no cursor.
   The detail-page breadcrumb has the same problem; padding on an inline <a>
   enlarges the hit area without touching the line box, so nothing moves. */
@media (pointer: coarse) {
  .langsw a { padding-block: 13px; }
  .crumb a  { padding-block: 12px; }
}

.navtoggle { display: none; background: none; border: 1px solid var(--line); border-radius: 2px; padding: 8px; color: var(--ink); cursor: pointer; }

/* ── Hero ────────────────────────────────────────────────────────── */

/* padding-block, not the shorthand: .hero and .shell have equal specificity, so
   a shorthand here would win the left/right slots too and zero out .shell's
   gutter — putting the h1 and lede flush against the screen edge on anything
   narrower than the 1180px max-width. */
.hero { padding-block: clamp(56px, 9vw, 110px) clamp(48px, 7vw, 88px); border-top: 0; }
.hero h1 { max-width: 16ch; }
.hero .lede { margin-top: 24px; }
.hero .btn-row { margin-top: 36px; }

/* The two home pages, which are where the advertising lands and the only
   heroes that have to fit four things above the fold — eyebrow, headline,
   button, and what the button costs. On a 1280 x 800 laptop the shared hero
   spends 110px of padding and four lines of 68px headline before the reader
   reaches any of that; a 16ch measure is what makes it four lines, and this
   headline is longer than the ones it was set for. Wider measure, shorter
   run-up. Every other hero on the site keeps the roomier setting, which suits
   a page someone arrived at on purpose. */
.hero-lead { padding-block: clamp(40px, 5.5vw, 72px) clamp(48px, 7vw, 88px); }
/* 50px rather than the shared 68px, and the 16ch measure lifted. Measured, not
   guessed: the Bulgarian headline takes four lines down to 54px and three from
   52px, and three lines is what puts the price line above the fold on a
   1366 x 768 laptop instead of below it. Set at 50 and not at the 52 where the
   break happens — a wrap threshold is a cliff, and a headline one pixel from
   the edge of one comes back as four lines the first time a font falls back.
   A headline nobody scrolls past is not worth the extra points. */
.hero-lead h1 { max-width: none; font-size: clamp(34px, 4.6vw, 50px); }

/* Origin badge, above the eyebrow. A Bulgarian buyer weighing an unknown brand
   is pricing in a risk — who answers the phone, who issues the invoice, who
   there is to chase. Naming the country costs a line and settles it. Set in
   --sand at 11.5:1 rather than in the brand orange, which belongs to the
   button: this is a fact about the seller, not a call to do anything. */
.origin {
  display: inline-block; margin-bottom: 16px;
  border: 1px solid var(--line); border-radius: 999px;
  padding: 5px 13px;
  font-family: var(--mono); font-size: 11px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--sand);
  background: rgba(217, 195, 160, .045);
}

/* The hero as copy plus a picture of the thing being sold. One column by
   default, so with no .hero-shot in the markup this is exactly the single
   column that was here before and the empty slot costs nothing. See the
   commented figure in site/index.html for what belongs in it. */
.hero-split { display: flex; flex-wrap: wrap; gap: 32px 44px; align-items: center; }
.hero-copy { flex: 1 1 100%; min-width: 0; }
.hero-shot { flex: 1 1 100%; min-width: 0; margin: 0; }
.hero-shot img {
  display: block; width: 100%; height: auto;
  border: 1px solid var(--line); border-radius: 6px;
}
.hero-shot figcaption { margin-top: 10px; font-family: var(--mono); font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted-2); }
/* Two columns only where there is room for both to be worth having, and the
   switch driven by an explicit width rather than by flex bases racing the
   gutter — the two disagreed around 1024px and left a single column wearing the
   two-column type. Below this the picture drops under the copy, which leaves
   the headline, the buttons and the ticks exactly where they were: it never
   pushes the button off the first screen, so there is nothing to hide. */
@media (min-width: 1000px) {
  /* Ratios, not bases: the copy keeps roughly 3:2 on the picture at every width
     from 1000px up. */
  .hero-lead:has(.hero-shot) .hero-copy { flex: 1.45 1 0; }
  .hero-lead:has(.hero-shot) .hero-shot { flex: 1 1 0; }
  /* A picture beside the headline takes about 410px of the 1052 the shell has,
     and the run that fits the remaining measure at 50px is five lines, not
     three. Measured with a stand-in image at 1366 x 700: 40px gives four lines
     and keeps the ticks 48px clear of the fold. Scoped by :has() so the
     single-column case keeps its own size — re-measure against the real
     screenshot if it lands at a different aspect ratio. */
  .hero-lead:has(.hero-shot) h1 { font-size: clamp(32px, 3.2vw, 40px); }
  .hero-lead:has(.hero-shot) .lede { font-size: 18px; }
}

/* What the button costs, as four things to glance at rather than a sentence to
   read. A cold visitor from an ad gives the area under a button about as long
   as it takes to decide whether there is a catch; four ticks answer that in one
   sweep, where a sentence has to be started.
   Full --ink at 17.75:1, not the .small grey this argument spent its life in —
   it is part of the case, not a footnote to it. The tick itself carries the
   accent (--brand-hot, 7.3:1) and is drawn rather than typed, so the label stays
   clean text for anything reading the page aloud. */
.ticks {
  display: flex; flex-wrap: wrap; gap: 9px 26px;
  margin: 18px 0 0; padding: 0; list-style: none;
}
.ticks li {
  display: flex; gap: 8px; align-items: baseline;
  font-size: 15px; line-height: 1.4; color: var(--ink);
}
.ticks li::before { content: "✓"; color: var(--brand-hot); font-weight: 700; flex: 0 0 auto; }

/* The one number the page is built around, set as a spec-sheet stat. */
.statline {
  display: flex; flex-wrap: wrap; gap: 0;
  margin-top: 52px; border: 1px solid var(--line);
}
.statline > div { flex: 1 1 180px; padding: 20px 22px; border-right: 1px solid var(--line); }
.statline > div:last-child { border-right: 0; }
/* For a stat whose figure is a range rather than a single value — "€1,200 –
   €3,500" needs about 40% more column than "~1 week". Widening beats shrinking
   the type: when the number wraps, its label drops below the other three and
   the row loses its baseline, and this is the figure the page is selling on. */
.statline > div.wide { flex: 1.4 1 220px; }
.statline .n { font-family: var(--display); font-weight: 800; font-size: 26px; color: var(--brand-hot); letter-spacing: -0.02em; }
.statline .k { font-family: var(--mono); font-size: 11px; letter-spacing: .12em; text-transform: uppercase; color: var(--muted-2); margin-top: 6px; }
/* The two cells that carry the argument — €29 a month against the €15,000 an
   agency quotes for the same thing. Four stats given equal weight read as a
   spec sheet and get skimmed as one; these two are the comparison the page is
   asking the reader to make, so they are set larger, and their labels are
   lifted out of --muted-2 to match.

   The emphasis is spent on the difference between the sizes rather than on
   absolute size. The row has only 1052px to divide, and a 34px "от 29 €/мес."
   breaks over two lines inside an equal quarter of it — which reads as a
   mistake rather than as emphasis. 30 against 23 in unequal columns is the
   stronger pair and still sets every figure on one line; below the width where
   four columns can hold them the row goes two up, then one.

   Opt-in by class, and the sizing scoped to .hero-lead: the other seventy
   pages carrying a .statline have their own ordering, are not making this
   comparison, and their equal quarters are fine. */
.statline > div.key .k { color: var(--muted); }
.hero-lead .statline > div { flex: 1 1 200px; padding-inline: 18px; }
.hero-lead .statline > div .n { font-size: 23px; }
.hero-lead .statline > div.key { flex: 1 1 290px; }
.hero-lead .statline > div.key .n { font-size: 30px; }

@media (max-width: 1240px) {
  .hero-lead .statline > div,
  .hero-lead .statline > div.key { flex: 1 1 46%; }
}
@media (max-width: 760px) {
  .hero-lead .statline > div,
  .hero-lead .statline > div.key { flex: 1 1 100%; }
}

/* On a phone the hero has one job: get the headline, the button and what the
   button costs onto the first screen together. A headline that fills the
   screen by itself is not a strong headline, it is a page with no visible way
   forward — and this page is paid for by the click.
   Measured against 390 x 844 and 360 x 640, the second being the one with no
   room to spare. Everything here buys vertical space: the display face is cut
   down, 16ch stops constraining a line that is already as narrow as the
   screen, and the gaps between the four elements close up. */
@media (max-width: 560px) {
  /* .hero-lead named alongside .hero rather than left to source order: the two
     have the same specificity, so this block only wins by coming later in the
     file, and that is not a thing to leave a phone layout resting on. */
  .hero, .hero-lead { padding-block: 24px 42px; }
  /* There was a `.hero .tiny { font-size: 11px }` here, added to keep the home
     page eyebrow on one line at 360px. That eyebrow is gone, and on the longest
     one left — /bg/partnyori/ — the smaller size wraps to two lines anyway and
     saves 3px. So the heroes go back to the site-wide 12px. */
  .hero h1, .hero-lead h1 { font-size: clamp(26px, 7.4vw, 31px); max-width: none; }
  .hero .lede { margin-top: 14px; font-size: 16px; line-height: 1.5; }
  .hero .btn-row { margin-top: 20px; }
  .origin { margin-bottom: 12px; padding: 4px 11px; font-size: 10.5px; letter-spacing: .07em; }
  /* Two buttons, one under the other and each the full width of the screen —
     a thumb aiming at half a phone's width misses. */
  .hero .btn-row .btn { width: 100%; justify-content: center; }
  /* Two per row, fixed. Left to flex the four ticks land 3 + 1 or 2 + 2
     depending on the screen, and the long fourth one on its own line reads as
     an afterthought. A grid pins the pairing; the long tick wraps inside its
     own cell instead of taking a row from the others. */
  .ticks { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; margin-top: 14px; }
  .ticks li { font-size: 13.5px; line-height: 1.35; gap: 6px; }
  .hero-split { gap: 26px; }
  .statline { margin-top: 30px; }
}

/* The short phone. 360 x 640 has to hold a badge, a headline, a lede, two
   buttons and four ticks; on a tall handset that all lands with 150px to spare,
   so the squeeze belongs on a height query rather than a width one — a
   360 x 780 phone keeps the roomier setting it can afford. Scoped to .hero-lead
   throughout: only the two home pages take paid traffic and owe anyone a button
   on the first screen. Everywhere else a short phone just scrolls.

   The headline is the whole saving. Measured line by line at 360px, the
   Bulgarian run is five lines from 24px up and four at 23.5 and below, and four
   lines of 23px is 40px shorter than five of 26 — a point of type for a fifth
   of the screen. 23 and not the 23.5 where the break sits, for the same reason
   the desktop size stands clear of its own cliff. Worth saying that this is not
   only the cheaper setting: a five-line headline on a phone reads worse than a
   four-line one, whatever the point size.

   Dropping the eyebrow gave 31px back, and every attempt to spend it landed on
   a wrap cliff in Bulgarian — the lede goes from five lines to six at 16px, the
   ticks grow 7px the moment the long fourth one wraps. So it is banked as
   clearance instead: 77px under the ticks in Bulgarian, 94px in English, on a
   screen where the consent bar is 190px tall and sits on top of all of it. */
@media (max-width: 560px) and (max-height: 700px) {
  .hero-lead { padding-block: 16px 34px; }
  .hero-lead .origin { margin-bottom: 8px; }
  .hero-lead h1 { font-size: clamp(22px, 6.4vw, 23px); line-height: 1.15; }
  .hero-lead .lede { margin-top: 10px; font-size: 15px; line-height: 1.45; }
  .hero-lead .btn-row { margin-top: 16px; gap: 10px; }
  .hero-lead .btn-row .btn { padding: 13px 20px; }
  .hero-lead .ticks { margin-top: 12px; gap: 6px 12px; }
  .hero-lead .ticks li { font-size: 12.5px; }
}

/* ── The offer band ──────────────────────────────────────────────────

   The free week spent its life as a grey line of .small under the hero
   buttons: the strongest thing on the page, set in the weakest type on it.
   The nearest competitor's free tier grants nothing until a €16 pack is
   bought, so ten thousand credits before a card is the one comparison we win
   outright — it earns a band.

   The eyebrow reads "current offer" deliberately. TRIAL.credits is temporary
   (see plans.mjs) and a number this size, printed as a plain fact, becomes a
   promise the owner is held to long after it changes. Saying it is an offer
   costs nothing today and buys the right to move it later.

   Kept to a left rule and a wash rather than a filled banner: the page is dark
   and a solid brand block here would outshout the h1 two lines above it. */
.offer {
  margin-top: 28px; padding: 18px 20px;
  border: 1px solid var(--line); border-left: 3px solid var(--brand);
  background: linear-gradient(90deg, rgba(204, 97, 38, .10), transparent 72%);
}
.offer .k {
  font-family: var(--mono); font-size: 11px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--brand-hot);
}
.offer .n {
  font-family: var(--display); font-weight: 800;
  font-size: clamp(19px, 2.1vw, 24px); letter-spacing: -0.01em;
  margin-top: 8px; color: var(--ink);
}
.offer .t { font-size: 15px; color: var(--muted); margin-top: 9px; max-width: 64ch; }

/* ── Grids & panels ──────────────────────────────────────────────── */

.grid { display: grid; gap: 1px; background: var(--line); border: 1px solid var(--line); }
.grid.c2 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.grid.c3 { grid-template-columns: repeat(auto-fit, minmax(268px, 1fr)); }
/* Six credit packs. At c3's 268px minimum a six-cell row breaks 4 + 2 on a
   wide screen and leaves two orphans under four siblings, which reads as a
   mistake rather than a ladder. 196px fits all six across on a desktop and
   still folds cleanly to 3 + 3 and 2 + 2 + 2 on the way down. Used on the two
   pricing pages only. */
.grid.c6 { grid-template-columns: repeat(auto-fit, minmax(196px, 1fr)); }
.grid.c6 .cell { padding: 26px 20px; }

/* Cells sit on the grid's 1px background, so the rules between them are
   shared — a drawn table, not a row of floating cards. Border OR shadow,
   never both. */
.cell { background: var(--bg); padding: 28px 26px; }
.cell h3 { margin-bottom: 10px; }
.cell p { color: var(--muted); font-size: 15px; }
.cell .idx { font-family: var(--mono); font-size: 12px; color: var(--brand); display: block; margin-bottom: 14px; }

.panel { border: 1px solid var(--line); background: var(--bg-2); padding: clamp(24px, 4vw, 40px); }
.panel.accent { border-left: 3px solid var(--brand); }

.split { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: clamp(28px, 5vw, 64px); align-items: start; }

/* ── Pricing ─────────────────────────────────────────────────────── */

/* Explicit column counts rather than auto-fit. With four plans the content box
   at --maxw is ~1052px, so a 280px minimum fits three across and drops the
   fourth onto a row of its own — an orphan that reads as a different kind of
   offer rather than the top of the ladder. The steps below keep the four cards
   on one row where there is room, and in a 2×2 block where there is not, so the
   ladder is always read as one set. */
.plans { display: grid; grid-template-columns: 1fr; gap: 1px; background: var(--line); border: 1px solid var(--line); }
@media (min-width: 620px)  { .plans { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1020px) { .plans { grid-template-columns: repeat(4, 1fr); } }
.plan { background: var(--bg); padding: 32px 28px; display: flex; flex-direction: column; }
.plan.featured { background: var(--bg-2); position: relative; }
.plan.featured::before {
  content: attr(data-tag);
  position: absolute; top: 0; left: 0;
  font-family: var(--mono); font-size: 11px; letter-spacing: .12em; text-transform: uppercase;
  background: var(--brand); color: var(--on-brand); padding: 5px 12px;
}
.plan .pname { font-family: var(--display); font-weight: 600; font-size: 15px; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.plan.featured .pname { margin-top: 16px; }
.plan .price { font-family: var(--display); font-weight: 800; font-size: 46px; letter-spacing: -0.03em; margin: 14px 0 2px; }
.plan .price small { font-family: var(--body); font-size: 15px; font-weight: 500; color: var(--muted-2); letter-spacing: 0; }
.plan .allowance { font-family: var(--mono); font-size: 13px; color: var(--brand-hot); margin-bottom: 20px; }
.plan ul { list-style: none; display: grid; gap: 11px; margin-bottom: 26px; }
.plan li { font-size: 14.5px; color: var(--muted); display: flex; gap: 10px; align-items: flex-start; }
.plan li svg { flex: none; margin-top: 3px; color: var(--brand); }
.plan .btn { margin-top: auto; justify-content: center; }

/* Four across leaves ~262px a card; claw back the horizontal padding and take
   the price down a step so "€249 / month" sits on one line with room to spare.
   Two things this has to be, or it silently does nothing:
   - AFTER the .plan rules above. Same specificity, so source order decides —
     placed before them, the padding applied and the font-size did not.
   - No upper bound. .shell caps at --maxw, so the cards stay 262px at every
     width past ~1116px and never get the room back.
   At 46px the €249 wrapped where €29/€79/€149 did not: "1" is narrower than
   "2", so size against the widest price, not the longest-looking one. */
@media (min-width: 1020px) {
  .plan { padding: 30px 22px; }
  .plan .price { font-size: 40px; }
  .plan li { font-size: 14px; }
  /* 12px is the step where "15,000 build credits a month" stops wrapping. It
     only wrapped on Max, so the four bullet lists started at different heights
     and the row lost its rhythm. Bulgarian wraps to two lines on all four
     cards, which is even, so it never had the problem. */
  .plan .allowance { font-size: 12px; }
}

/* One line, not a ladder. From 4 September 2026 there is a single monthly
   charge — the hosting fee — and the four-column grid above would strand it in
   a quarter of the page with three empty columns behind it. !important because
   the column counts above are set in media queries, which a plain rule here
   would lose to at every width. The card then lays itself out sideways: price
   on the left, what it covers on the right, so a full-width card reads as one
   row rather than as a tall banner with a lot of air in it. */
.plans.one { grid-template-columns: 1fr !important; }
@media (min-width: 760px) {
  .plans.one .plan { display: grid; grid-template-columns: minmax(0, 300px) 1fr; column-gap: 48px; }
  .plans.one .plan .pname     { grid-column: 1; grid-row: 1; }
  .plans.one .plan .price     { grid-column: 1; grid-row: 2; }
  .plans.one .plan .allowance { grid-column: 1; grid-row: 3; }
  .plans.one .plan .btn       { grid-column: 1; grid-row: 4; margin-top: 4px; align-self: start; }
  .plans.one .plan ul         { grid-column: 2; grid-row: 1 / span 4; margin-bottom: 0; align-content: start; }
}

/* ── Template gallery ────────────────────────────────────────────── */

.tpl { background: var(--bg); padding: 0; display: flex; flex-direction: column; text-decoration: none; transition: background .16s ease; }
.tpl:hover { background: var(--bg-2); }
.tpl:hover .tpl-name { color: var(--brand-hot); }
.tpl-head { padding: 24px 26px 0; }
.tpl-vertical { font-family: var(--mono); font-size: 11px; letter-spacing: .12em; text-transform: uppercase; color: var(--brand); }
.tpl-name { font-family: var(--display); font-weight: 600; font-size: 19px; line-height: 1.25; margin: 12px 0 10px; transition: color .16s; }
.tpl-body { padding: 0 26px 24px; }
.tpl-body p { color: var(--muted); font-size: 14.5px; }
.tpl-outcome {
  margin-top: 18px; padding-top: 16px; border-top: 1px dashed var(--line);
  font-size: 14px; color: var(--ink);
}
.tpl-outcome span { color: var(--brand-hot); font-family: var(--mono); font-size: 11px; letter-spacing: .1em; text-transform: uppercase; display: block; margin-bottom: 5px; }

/* Sector filter + search. The bar is [hidden] in the markup and revealed by
   script, so with JavaScript off there is no dead control — all twenty cards
   are simply on the page. */
.tplbar {
  display: flex; flex-wrap: wrap; gap: 14px; align-items: center;
  justify-content: space-between; margin-bottom: 34px;
}
.chips { display: flex; flex-wrap: wrap; gap: 8px; }
.chip {
  font-family: var(--mono); font-size: 11.5px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted); background: transparent; border: 1px solid var(--line);
  border-radius: 2px; padding: 8px 13px; cursor: pointer; transition: color .14s, border-color .14s;
}
.chip:hover { color: var(--ink); border-color: var(--muted-2); }
.chip.on { color: var(--brand-hot); border-color: var(--brand); background: var(--brand-wash); }
/* With seven chips the row wraps on most screens; margin-left:auto keeps the
   search at the right edge so the wrap reads as deliberate rather than as an
   orphaned control. */
.tplsearch { position: relative; display: flex; align-items: center; flex: 0 1 260px; margin-left: auto; }
.tplsearch svg { position: absolute; left: 12px; color: var(--muted-2); pointer-events: none; }
.tplsearch input {
  width: 100%; background: var(--bg-2); border: 1px solid var(--line); border-radius: 2px;
  color: var(--ink); font-family: var(--body); font-size: 14.5px; padding: 10px 12px 10px 34px;
}
.tplsearch input::placeholder { color: var(--muted-2); }
.tplsearch input:focus { outline: none; border-color: var(--brand); }
/* Must follow the rule above, not precede it: both selectors are (0,2,1), so at
   equal specificity the later declaration wins and the global ring would be
   cancelled back to none for anyone arriving by keyboard. */
.tplsearch input:focus-visible { outline: 2px solid var(--brand-hot); outline-offset: 2px; }
.tplsearch input::-webkit-search-cancel-button { filter: invert(.6); }

/* Sector sections stack with breathing room between them. */
[data-section] + [data-section] { margin-top: 46px; }
.tplempty { margin-top: 28px; font-size: 15px; color: var(--muted); }
.reach {
  margin-top: 18px; font-size: 15px; color: var(--muted-2);
  padding-left: 14px; border-left: 1px solid var(--line);
}

@media (max-width: 560px) {
  .tplbar { flex-direction: column; align-items: stretch; }
  /* margin-left:auto right-aligns the box when the chips wrap on desktop; in a
     stacked column it would instead stop it from filling the width. */
  .tplsearch { flex: 1 1 auto; margin-left: 0; }
}

/* Screen frame for template detail pages — a browser chrome that is a
   drawing, not a fake screenshot of software that does not exist. */
.frame { border: 1px solid var(--line); background: var(--bg-2); }
.frame .bar { display: flex; gap: 6px; padding: 10px 14px; border-bottom: 1px solid var(--line); }
.frame .bar i { width: 9px; height: 9px; border-radius: 50%; background: var(--line); display: block; }
.frame .body { padding: 26px; }

/* ── Steps ───────────────────────────────────────────────────────── */

.steps { display: grid; gap: 0; counter-reset: step; }
.step { display: grid; grid-template-columns: 62px 1fr; gap: 22px; padding: 26px 0; border-bottom: 1px solid var(--line-soft); }
.step:last-child { border-bottom: 0; }
.step .num {
  font-family: var(--display); font-weight: 800; font-size: 30px;
  color: transparent; -webkit-text-stroke: 1px var(--brand); line-height: 1;
}
.step h3 { margin-bottom: 7px; }
.step p { color: var(--muted); font-size: 15px; }

/* ── Forms ───────────────────────────────────────────────────────── */

.form { display: grid; gap: 16px; }
.field { display: grid; gap: 7px; }
.field label { font-family: var(--mono); font-size: 11px; letter-spacing: .12em; text-transform: uppercase; color: var(--muted-2); }
.field input, .field select, .field textarea {
  font-family: var(--body); font-size: 15px; color: var(--ink);
  background: var(--bg); border: 1px solid var(--line); border-radius: 2px;
  padding: 12px 14px; width: 100%;
}
.field textarea { min-height: 118px; resize: vertical; }
.field input:focus, .field select:focus, .field textarea:focus { outline: none; border-color: var(--brand); }
/* Same ordering constraint as .tplsearch above. */
.field input:focus-visible, .field select:focus-visible, .field textarea:focus-visible {
  outline: 2px solid var(--brand-hot); outline-offset: 2px;
}
.field.row2 { grid-column: span 2; }
.form-note { font-size: 13px; color: var(--muted-2); }
.form-msg { font-size: 14.5px; min-height: 20px; }
.form-msg.err { color: #f87171; }
.form-msg.ok { color: var(--brand-hot); }
@media (min-width: 720px) { .form.two { grid-template-columns: 1fr 1fr; } }

/* ── FAQ ─────────────────────────────────────────────────────────── */

details { border-bottom: 1px solid var(--line-soft); padding: 18px 0; }
details summary { cursor: pointer; font-weight: 700; font-size: 16px; list-style: none; display: flex; gap: 14px; align-items: baseline; }
details summary::-webkit-details-marker { display: none; }
details summary::before { content: '+'; font-family: var(--mono); color: var(--brand); flex: none; }
details[open] summary::before { content: '−'; }
details p { color: var(--muted); font-size: 15px; margin-top: 12px; padding-left: 28px; }

/* ── Table ───────────────────────────────────────────────────────── */

table { width: 100%; border-collapse: collapse; font-size: 15px; }
th, td { text-align: left; padding: 14px 16px; border-bottom: 1px solid var(--line-soft); }
th { font-family: var(--mono); font-size: 11px; letter-spacing: .12em; text-transform: uppercase; color: var(--muted-2); font-weight: 500; }
td { color: var(--muted); }
td:first-child { color: var(--ink); font-weight: 600; }

/* ── CTA band ────────────────────────────────────────────────────── */

.cta { background: var(--bg-2); border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.cta .shell { display: flex; flex-wrap: wrap; gap: 28px; align-items: center; justify-content: space-between; }
.cta h2 { max-width: 18ch; }

/* ── Footer ──────────────────────────────────────────────────────── */

footer { border-top: 1px solid var(--line-soft); padding: 48px 0 60px; }
/*
   Six tracks — the brand block and five columns. Explicit rather than
   auto-fit: at six columns auto-fit drops to a two-row grid somewhere around
   1100px and leaves one orphan column on its own line, which reads as a
   mistake. The ladder below steps 6 → 3 → 2 instead.
*/
.foot { display: grid; grid-template-columns: 1.3fr repeat(5, minmax(0, 1fr)); gap: 30px 24px; }
.foot-brand { grid-column: span 1; }
.foot h4 { font-family: var(--mono); font-size: 11px; letter-spacing: .12em; text-transform: uppercase; color: var(--muted-2); font-weight: 500; margin-bottom: 14px; }
.foot a { display: block; font-size: 14.5px; color: var(--muted); text-decoration: none; padding: 5px 0; }
.foot a:hover { color: var(--brand-hot); }
/* "Talk it through first", moved down here out of the hero. Set to read like
   the links beside it rather than as a third button style — it is a way out
   for the reader who has got to the bottom without being convinced, not
   something to compete with the sign-up at the top of the page. The reset is
   explicit because it is a <button>: it opens the consultant in place, and a
   <button> inherits none of the anchor styling around it. */
.foot-talk {
  display: block; margin-top: 16px; padding: 0;
  background: none; border: 0; border-bottom: 1px solid var(--line);
  font-family: var(--body); font-size: 14.5px; color: var(--sand);
  padding-bottom: 3px; cursor: pointer; text-align: left;
}
.foot-talk:hover { color: var(--brand-hot); border-bottom-color: var(--brand-hot); }
.foot-base { margin-top: 40px; padding-top: 22px; border-top: 1px solid var(--line-soft); display: flex; flex-wrap: wrap; gap: 14px; justify-content: space-between; font-size: 13px; color: var(--muted-2); }

/* ── Language banner ─────────────────────────────────────────────── */
/*
   A dismissible offer, never an auto-redirect: silently rewriting the URL
   breaks shared links and the back button, and mis-serves the many
   Bulgarian users whose browsers report an English locale.
*/
.langbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  background: var(--brand); color: var(--on-brand);
  display: flex; align-items: center; gap: 16px;
  padding: 13px var(--gutter);
  transform: translateY(100%);
  animation: slideup .34s cubic-bezier(.2, .8, .3, 1) .7s forwards;
}
.langbar p { font-size: 15px; font-weight: 600; }
.langbar a { color: var(--on-brand); font-weight: 700; text-decoration: underline; text-underline-offset: 3px; }
.langbar button {
  margin-left: auto; background: none; border: 1px solid rgba(12,10,9,.45); border-radius: 2px;
  color: var(--on-brand); padding: 6px 12px; font-family: var(--body); font-size: 13px; font-weight: 600; cursor: pointer;
}
.langbar button:hover { background: rgba(12,10,9,.14); }
@keyframes slideup { to { transform: translateY(0); } }

/* ── Voice consultant launcher ───────────────────────────────────── */
/*
   Only the button lives here. Everything the panel needs is in voice.css,
   which is fetched with voice.js the first time this is pressed — the
   visitors who never press it pay nothing for it.

   Bottom-right. The language banner runs the full width of the screen and its
   dismiss button sits on this side, so while that banner is showing the
   launcher lifts clear above it rather than covering a one-time offer to read
   the site in your own language.
*/
.voicelaunch {
  position: fixed; right: var(--gutter); bottom: 22px; z-index: 55;
  display: inline-flex; align-items: center; gap: 10px;
  padding: 12px 18px 12px 14px;
  background: var(--brand); color: var(--on-brand);
  border: 1px solid var(--brand); border-radius: 2px;
  font-family: var(--body); font-weight: 700; font-size: 14.5px;
  cursor: pointer;
  box-shadow: 0 8px 28px rgba(0, 0, 0, .45);
  transition: background .16s ease, transform .16s ease, opacity .2s ease;
}
.voicelaunch:hover { background: var(--brand-hot); border-color: var(--brand-hot); transform: translateY(-1px); }
.voicelaunch svg { flex: none; }
/* A quiet pulse on the mark, so it reads as something live rather than
   another cookie widget. One ring, slow, and gone under reduced motion. */
.voicelaunch .ring {
  position: absolute; left: 0; top: 0; right: 0; bottom: 0;
  border: 1px solid var(--brand-hot); border-radius: 2px;
  animation: voicering 3.4s ease-out infinite; pointer-events: none;
}
@keyframes voicering {
  0%       { opacity: .8; transform: scale(1); }
  40%, 100% { opacity: 0;  transform: scale(1.14); }
}

/* The language banner is full-width across the bottom at every size, and on
   this side it carries the dismiss button. The launcher sits above it until it
   has been answered rather than on top of it. */
body:has(.langbar) .voicelaunch { bottom: 74px; }

@media (max-width: 720px) {
  .voicelaunch { right: 14px; bottom: 14px; padding: 11px 15px 11px 12px; font-size: 13.5px; }
  body:has(.langbar) .voicelaunch { bottom: 76px; }
}

@media (prefers-reduced-motion: reduce) {
  .voicelaunch .ring { animation: none; opacity: 0; }
}

/* ── Entrance motion ─────────────────────────────────────────────── */
/*
   One orchestrated page load beats scattered micro-interactions. Staggered
   only in the hero; everything below reveals on scroll via site.js.
*/
.rise { opacity: 0; transform: translateY(14px); animation: rise .62s cubic-bezier(.2,.8,.3,1) forwards; }
.rise:nth-child(2) { animation-delay: .07s; }
.rise:nth-child(3) { animation-delay: .14s; }
.rise:nth-child(4) { animation-delay: .21s; }
.rise:nth-child(5) { animation-delay: .28s; }
@keyframes rise { to { opacity: 1; transform: none; } }

/*
   Scroll reveal is opt-in on scripting: site.js adds .seen. Guarded so that a
   browser with JavaScript off — or one too old to know the query — never hides
   the content it will not be able to reveal.
*/
@media (scripting: enabled) {
  .reveal { opacity: 0; transform: translateY(18px); transition: opacity .6s ease, transform .6s cubic-bezier(.2,.8,.3,1); }
  .reveal.seen { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; animation-delay: 0ms !important; transition-duration: .01ms !important; }
  .reveal { opacity: 1; transform: none; }
}

/* ── Long-form text (privacy, terms) ─────────────────────────────── */
/*
   Legal text is the one thing on this site people read top to bottom rather
   than scan, so it gets a reading measure and generous leading — everything
   else here is built for scanning.
*/
.legal { max-width: 68ch; }
.legal h2 { font-size: clamp(21px, 2.6vw, 27px); margin: 46px 0 14px; }
.legal h2:first-child { margin-top: 0; }
.legal h3 { margin: 26px 0 8px; }
.legal p, .legal li { color: var(--muted); line-height: 1.72; }
.legal p { margin: 0 0 14px; }
.legal ul { margin: 0 0 14px; padding-left: 20px; }
.legal li { margin-bottom: 7px; }
.legal a { color: var(--brand-hot); text-underline-offset: 3px; }
.legal strong { color: var(--ink); font-weight: 600; }
.legal .updated { font-family: var(--mono); font-size: 12px; letter-spacing: .08em;
  text-transform: uppercase; color: var(--muted-2); }
/* The one table on these pages: who else touches the data, and why. */
.legal table { width: 100%; border-collapse: collapse; margin: 0 0 18px; font-size: 15px; }
.legal th, .legal td { text-align: left; padding: 11px 14px 11px 0; vertical-align: top;
  border-bottom: 1px solid var(--line-soft); color: var(--muted); }
.legal th { color: var(--ink); font-weight: 600; }

/* ── Documentation ───────────────────────────────────────────────── */
/*
   Reference pages, so they get a permanent index rather than the linear
   hero-then-sections rhythm the marketing pages use: you arrive from a search
   result, read one answer, and leave. The tree is plain links with no script
   behind it, so it is there on first paint and works in a text browser.
*/
.docs-layout { display: grid; grid-template-columns: 236px minmax(0, 1fr); gap: 52px; align-items: start; }

.docs-side { position: sticky; top: 92px; border-left: 1px solid var(--line); padding-left: 18px; font-size: 14px; }
.docs-side-top { margin: 0 0 20px; }
.docs-side-top a { color: var(--brand-hot); text-decoration: none; }
.docs-side-group { margin: 24px 0 8px; color: var(--muted-2); }
.docs-side-group:first-of-type { margin-top: 0; }
.docs-side ul { list-style: none; margin: 0; padding: 0; }
.docs-side li { margin: 0; }
.docs-side a { display: block; padding: 4px 0; line-height: 1.45; color: var(--muted); text-decoration: none; }
.docs-side a:hover { color: var(--ink); }
.docs-side a[aria-current="page"] { color: var(--brand-hot); font-weight: 700; }
/* The headings of the page you are on, nested under it. */
.docs-sub { margin: 4px 0 8px; padding-left: 12px; border-left: 1px solid var(--line); }
.docs-sub a { font-size: 13px; color: var(--muted-2); }

.docs-body { max-width: 72ch; }
.docs-body > .panel ul { margin: 0; padding-left: 20px; }

/* The "what are you trying to build?" box on the hub. */
.docs-searchbar { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 22px; }
.docs-searchbar input {
  flex: 1 1 280px; min-width: 0;
  background: var(--bg); border: 1px solid var(--line); border-radius: 0;
  color: var(--ink); font: inherit; font-size: 15px; padding: 12px 14px;
}
.docs-searchbar input::placeholder { color: var(--muted-2); }
.docs-searchbar input:focus { outline: none; border-color: var(--brand); }
.docs-searchbar input:focus-visible { outline: 2px solid var(--brand-hot); outline-offset: 2px; }
.docs-searchbar input::-webkit-search-cancel-button { filter: invert(.6); }

.docs-hits { margin-top: 24px; border-top: 1px solid var(--line); }
.docs-hits > .tiny { margin: 18px 0 2px; }
.docs-hit { display: block; padding: 13px 0; border-bottom: 1px solid var(--line-soft); text-decoration: none; }
.docs-hit:last-child { border-bottom: 0; }
.docs-hit .k { font-family: var(--mono); font-size: 11px; letter-spacing: .08em;
  text-transform: uppercase; color: var(--brand); }
.docs-hit .t { color: var(--ink); font-weight: 600; margin-top: 3px; }
.docs-hit .d { color: var(--muted); font-size: 14px; line-height: 1.55; margin-top: 3px; }
.docs-hit:hover .t, .docs-hit:focus-visible .t { color: var(--brand-hot); }
.docs-empty { color: var(--muted); font-size: 15px; padding: 16px 0 4px; }

/* Visible to screen readers, not to the eye — the search field's label. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ── Responsive ──────────────────────────────────────────────────── */

@media (max-width: 1080px) {
  /* The brand block takes the whole first row; the five columns share three. */
  .foot { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .foot-brand { grid-column: 1 / -1; }

  /*
     One column, and the tree moves below the article: on a narrow screen a
     twelve-item index above the text pushes the answer off the screen, and
     the in-page anchors are useless once you have scrolled past them.
  */
  .docs-layout { grid-template-columns: minmax(0, 1fr); gap: 40px; }
  .docs-side { position: static; order: 2; border-left: 0; border-top: 1px solid var(--line);
    padding: 24px 0 0; }
  .docs-sub { display: none; }
  .docs-body { order: 1; }
}

@media (max-width: 860px) {
  .navtoggle { display: block; order: 3; margin-left: auto; }
  .mainnav {
    display: none; position: absolute; top: 68px; left: 0; right: 0;
    flex-direction: column; gap: 0; margin: 0;
    background: var(--bg-2); border-bottom: 1px solid var(--line); padding: 8px var(--gutter) 18px;
  }
  .mainnav.open { display: flex; }
  .mainnav a { padding: 13px 0; border-bottom: 1px solid var(--line-soft); }
  .mast-actions .btn { display: none; }
  .step { grid-template-columns: 44px 1fr; gap: 16px; }
  .cta .shell { display: block; }
  .cta .btn-row { margin-top: 24px; }
}

@media (max-width: 640px) {
  .foot { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 26px 18px; }

  /*
     Three columns inside 350px leaves about one word per line. Stacked, each
     processor reads as a short paragraph — who they are, what they do, what
     they see — which is the same information in the order you would say it.
  */
  .legal table, .legal tbody, .legal tr, .legal td { display: block; width: 100%; }
  .legal thead { display: none; }
  .legal tr { padding: 14px 0; border-bottom: 1px solid var(--line-soft); }
  .legal tr:last-child { border-bottom: 0; }
  .legal td { border: 0; padding: 0 0 4px; }
  .legal td:first-child { color: var(--ink); font-weight: 600; padding-bottom: 6px; }
}
