/* ===========================================================================
   THE FRONT PAGE — karyosa.com
   ===========================================================================

   Separate from app/styles.css on purpose. That file is the CHROME of a tool
   somebody uses forty times a day: quiet, dense, built to disappear. This is a
   page a stranger looks at for nine seconds and decides whether to keep
   reading. They are different jobs, and sharing one stylesheet would make both
   of them worse — every change to a button in the app would have to be
   re-argued against a sales page, and vice versa.

   What IS shared is the identity: the same blossom mauve, the same rounded
   display face, the same warm paper. So the tokens below are named like the
   app's and set to the same values, and a visitor who clicks through to the
   product does not feel handed to a different company.

   INLINE STYLE AND SCRIPT ARE FORBIDDEN HERE. The site's Content-Security-
   Policy (_headers) allows no `unsafe-inline`, which is the right setting for
   a site that holds payroll data and is not being weakened for a landing page.
   Hence this file and site.js rather than a <style> block.
   ========================================================================= */

:root {
  --accent-50: #FDF4F6;
  --accent-100: #FAE8EC;
  --accent-200: #F3D2DA;
  --accent-700: #BD5170;
  --accent-800: #A44661;
  --accent-900: #923851;

  --paper: #FDF7F5;
  --paper-2: #FFFFFF;
  --ink: #3A2226;
  --ink-2: #7A5A5C;
  --line: #F1DCD3;
  --line-2: #E7CBC4;

  --ok: #2F6B4F;

  /* THE SYSTEM STACK — no webfont is downloaded by this page at all.
     This is the same stack kreloses.com inherits from Bootstrap, and it is
     most of why their page feels quick and reads as software rather than as
     an app store listing: on a Mac it renders as San Francisco, on Windows as
     Segoe UI, on Android as Roboto. Every visitor gets the face they read
     everything else in, and the page spends zero bytes and zero round trips
     getting it.

     Both tokens are the same stack on purpose. They stay as two names because
     the rest of this file talks about display and text separately, and a
     future decision to give headlines their own face should only have to
     change one line. */
  --ff-display: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
    "Segoe UI Symbol";
  --ff-text: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
    "Segoe UI Symbol";

  /* How much of the next section shows above the fold. NOT zero: a first
     screen that ends in a clean edge looks finished, and a visitor who thinks
     a page is finished does not scroll. A strip of the white band peeking up
     is the oldest trick there is for saying "there is more" without a
     bouncing arrow. Kreloses shows about 40px of theirs; this is 44.
     Too much and the sliver competes with the buttons; too little and it
     reads as a rendering artefact rather than a page continuing. */
  --fold-peek: 44px;

  --wrap: 1120px;
  --gutter: 16px;
  --radius: 22px;
  --pill: 999px;

  --shadow-card: 0 1px 2px rgba(58, 34, 38, 0.05), 0 12px 32px -14px rgba(58, 34, 38, 0.22);
  --shadow-shot: 0 2px 6px rgba(58, 34, 38, 0.06), 0 30px 70px -28px rgba(58, 34, 38, 0.38);
}

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

html {
  -webkit-text-size-adjust: 100%; scroll-behavior: smooth;
  /* NO SCROLL SNAP. It was tried on 2026-09-25 to settle "Why it exists"
     exactly under the header, and even at `proximity` Chrome kept pulling the
     page back to it when the reader scrolled a little past: a section exactly
     one screen tall is "near" its snap point for most of the way through it.
     A page that resists the reader's own scrolling is worse than one that
     stops a few pixels off-centre. Do not bring it back.
     scroll-padding-top stays: it keeps the in-page links (What it does,
     Malaysian rules) landing clear of the 68px sticky header. */
  scroll-padding-top: 68px;
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: 0.001ms !important; transition-duration: 0.001ms !important; }
}

body {
  margin: 0;
  font-family: var(--ff-text);
  font-size: 17px;
  line-height: 1.65;
  color: var(--ink);
  background-color: var(--paper);
  /* the same warm corner light the app's signed-out screens have */
  background-image:
    radial-gradient(1100px 620px at 12% -14%, #FFF1E6 0%, transparent 64%),
    radial-gradient(820px 460px at 104% 2%, var(--accent-100), transparent 60%),
    radial-gradient(680px 420px at -14% 92%, var(--accent-50), transparent 62%);
  background-attachment: fixed;
}

h1, h2, h3 {
  font-family: var(--ff-display);
  /* 700, not 800. Baloo 2 needed 800 to have any weight at all; a system
     grotesque at 800 is a slab of ink, and on Windows there is no 800 to
     load so it gets synthesised and smears. */
  font-weight: 700;
  /* and much less negative tracking: these faces are already tight at
     display sizes, San Francisco optically more so. */
  letter-spacing: -0.011em;
  line-height: 1.14;
  margin: 0;
  color: var(--ink);
}

p { margin: 0; }
img { max-width: 100%; display: block; }

a { color: var(--accent-800); text-underline-offset: 3px; }
a:hover { color: var(--accent-900); }

.wrap { width: 100%; max-width: var(--wrap); margin: 0 auto; padding: 0 var(--gutter); }
.narrow { max-width: 760px; }

/* skip link — a keyboard user should not have to tab the whole header */
.skip {
  position: absolute; left: -9999px; top: 0; z-index: 50;
  background: var(--paper-2); color: var(--ink); padding: 12px 18px;
  border-radius: 0 0 14px 0; font-weight: 600;
}
.skip:focus { left: 0; }

:where(a, button, input, select, textarea, summary):focus-visible {
  outline: 3px solid var(--accent-700);
  outline-offset: 2px;
  border-radius: 6px;
}

/* ---------------------------------------------------------------- header */
.site-head {
  position: sticky; top: 0; z-index: 30;
  backdrop-filter: blur(14px) saturate(1.5);
  -webkit-backdrop-filter: blur(14px) saturate(1.5);
  background: rgba(253, 247, 245, 0.82);
  border-bottom: 1px solid transparent;
  transition: border-color 160ms ease-out, box-shadow 160ms ease-out;
}
.site-head.is-stuck {
  border-bottom-color: var(--line);
  box-shadow: 0 6px 20px -16px rgba(58, 34, 38, 0.5);
}
.head-row { display: flex; align-items: center; gap: 18px; min-height: 68px; }
/* min-height so the wordmark is a real target too — it was 41px, which is
   under the 44 every platform asks for and the one link people reach for
   first when they want to start again. */
.brand {
  display: inline-flex; align-items: center; gap: 10px; text-decoration: none;
  margin-right: auto; min-height: 44px;
}
.brand svg, .brand .mark { width: 30px; height: 30px; flex: none; display: block; }
/* The mark alone, no rounded-square tile. The colour is baked into mark.svg
   rather than set here: an <img> is its own document and inherits nothing
   from this page, so a `color` declaration on this rule would do nothing and
   `currentColor` inside the file would quietly resolve to black. */
.brand-name {
  font-family: var(--ff-display); font-weight: 700; font-size: 23px;
  /* Set in capitals, so it reads as a wordmark rather than as the first word
     of a sentence — the thing a system face cannot do for you by being
     distinctive. Capitals need positive tracking to stay legible. */
  text-transform: uppercase; letter-spacing: 0.045em; color: var(--ink);
}
.head-nav { display: flex; align-items: center; gap: 6px; }
.head-nav a {
  text-decoration: none; color: var(--ink-2); font-weight: 600; font-size: 15.5px;
  padding: 9px 13px; border-radius: var(--pill);
}
.head-nav a:hover { color: var(--ink); background: var(--accent-50); }
@media (max-width: 720px) {
  .head-nav .hide-sm { display: none; }
  .head-nav { gap: 2px; }
  .head-nav a { font-size: 15px; padding: 0 11px; min-height: 44px; display: inline-flex; align-items: center; }
}

/* ---------------------------------------------------------------- buttons */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  font: inherit; font-weight: 700; text-decoration: none; cursor: pointer;
  border-radius: var(--pill); border: 1px solid transparent;
  padding: 14px 30px; min-height: 52px;
  transition: box-shadow 140ms ease-out, transform 140ms ease-out, background-color 140ms ease-out;
}
/* Solid, with a white label — the same decision the app's own primary button
   arrived at, for the same reason: the one action a page exists for cannot be
   the palest thing on it. */
.btn-primary {
  color: #FFFFFF;
  background-color: var(--accent-800);
  background-image: linear-gradient(180deg, var(--accent-700) 0%, var(--accent-800) 58%, var(--accent-800) 100%);
  box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.22), inset 0 -2px 0 rgba(255, 255, 255, 0.1),
    0 2px 4px rgba(58, 34, 38, 0.12), 0 14px 28px -12px rgba(146, 56, 81, 0.6);
}
.btn-primary:hover { color: #FFFFFF; box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.34), inset 0 -2px 0 rgba(255, 255, 255, 0.16), 0 3px 6px rgba(58, 34, 38, 0.14), 0 18px 34px -12px rgba(146, 56, 81, 0.68); }
.btn-primary:active { transform: translateY(1px) scale(0.99); }
.btn-quiet {
  color: var(--accent-900); background: var(--paper-2);
  border-color: var(--line-2);
  box-shadow: 0 1px 2px rgba(58, 34, 38, 0.05);
}
.btn-quiet:hover { background: var(--accent-50); }
.btn-lg { font-size: 17.5px; min-height: 58px; padding: 16px 36px; }

/* ---------------------------------------------------------------- sections */
section { padding: 78px 0; }
@media (max-width: 720px) { section { padding: 54px 0; } }

.eyebrow {
  font-weight: 700; font-size: 13.5px; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--accent-800); margin-bottom: 14px;
}
.h2 { font-size: clamp(30px, 4.6vw, 44px); }
/* A two-line headline should break into two lines of similar length, never a
   full line and one word left hanging ("…for business / owners."). A
   non-breaking space cannot do it here, because site.js splits every headline
   into one span per word for the scroll animation. `balance` works on the
   laid-out lines instead, so it survives the split, and a browser that does
   not know it simply wraps as before. */
h2, .h2 { text-wrap: balance; }
.lede { font-size: clamp(17px, 2vw, 19.5px); color: var(--ink-2); margin-top: 16px; }
.center { text-align: center; }
.center .lede { margin-left: auto; margin-right: auto; max-width: 660px; }

/* ---------------------------------------------------------------- hero */
/* CENTRED, at the measurements taken off kreloses.com rather than guessed:
   headline 44px on 53px (1.2), lede 20px on 30px (1.5), the whole block on
   the page's centre line. Centring is not only what she liked — it is what
   fixes the old hero's real fault, which was that the headline, the lede and
   the buttons all sat in the left column and then 500px of nothing happened
   on the right. */
/* The top padding is a MEASURED number, not a taste: 204px puts the
   headline's ink 274.5px below the top of the viewport, which is where
   kreloses.com puts theirs. It assumes the 68px sticky header above it.
   tools/herocheck.py re-measures all three positions from a real render —
   run it after touching anything in this block. */
.hero {
  padding: 204px 0 clamp(40px, 6vw, 72px);
  text-align: center;
  /* Fill the first screen, so nothing shows below the buttons until the
     visitor scrolls. 68px is the sticky header above it; dvh where it exists,
     because on a phone 100vh is the height WITHOUT the browser's own bars and
     leaves the fold in the wrong place. The content still starts at the top
     of this box, so the measured text positions are untouched — the extra
     height is added underneath. */
  min-height: calc(100vh - 68px - var(--fold-peek));
}
@supports (height: 100dvh) { .hero { min-height: calc(100dvh - 68px - var(--fold-peek)); } }
@media (max-width: 860px) { .hero { padding-top: clamp(40px, 9vw, 96px); } }
/* THE HERO, BUILT TO KRELOSES'S MEASUREMENTS.
 *
 * Every number below was read off a screenshot of their page rather than
 * chosen: 44px on 52.5px for the headline, 20px on 30px for the lede, and the
 * vertical offsets tuned until this page's own render puts the ink in the same
 * places — headline ink 274.5px below the top of the viewport, lede at 400,
 * button row at 498.
 *
 * The offsets assume the sticky header is 68px tall. Change that and the
 * numbers below have to be re-measured, not guessed. tools/herocheck.py
 * prints the three positions from a real render.
 */
.hero h1.h1-kre {
  font-size: 44px;
  line-height: 52.5px;
  letter-spacing: -0.014em;
  max-width: none;
  margin: 0 auto;
}
.hero .lede.lede-kre {
  font-size: 20px;
  line-height: 30px;
  max-width: 772px;      /* their widest lede line measures 765px */
  margin: 17px auto 0;
  color: var(--ink-2);
}
@media (max-width: 860px) {
  .hero h1.h1-kre { font-size: clamp(27px, 5.2vw, 44px); line-height: 1.19; }
  .hero h1.h1-kre br { display: none; }
  .hero .lede.lede-kre { font-size: 17px; line-height: 1.5; }
}

.hero h1 {
  font-size: clamp(31px, 4.2vw, 44px);
  line-height: 1.2;
  letter-spacing: -0.014em;
  /* 720px is where this particular sentence breaks into two balanced lines
     at 44px — measured, not a round number chosen because it looks tidy.
     text-wrap: balance keeps it from going one-word-orphan at other sizes
     in the browsers that have it, and is ignored harmlessly elsewhere. */
  max-width: 820px;
  margin-left: auto; margin-right: auto;
}
.hero .lede {
  font-size: clamp(17px, 1.9vw, 20px);
  line-height: 1.5;
  max-width: 760px;
  margin-left: auto; margin-right: auto;
}
/* A line break that only exists on a wide screen. See the note on the h1 in
   index.html: with a system stack the metrics differ per platform, so where
   the sentence wraps is not something a max-width can pin down. */
.br-lg { display: none; }
@media (min-width: 900px) { .br-lg { display: inline; } }

.hero-cta { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 42px; justify-content: center; }
/* A class, not a style="" attribute: the CSP has no 'unsafe-inline', so an
   inline style is silently dropped and the thing simply does not centre. */
.hero-cta-center { justify-content: center; }
.hero-note { margin-top: 18px; font-size: 15px; color: var(--ink-2); }

.shot {
  margin-top: clamp(38px, 6vw, 62px);
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--paper-2);
  box-shadow: var(--shadow-shot);
  overflow: hidden;
}
.shot img { width: 100%; height: auto; }

/* THE SCREENSHOT'S OWN BACKGROUND — a separate surface, ending cleanly.
 *
 * Kreloses does not blend anything: their dark hero photo stops, and a plain
 * white block starts on the next pixel. That hard edge is what makes the two
 * read as two things. This page is light, so the change is gentler than
 * theirs — paper to pure white rather than a photograph to white — but it is
 * the same move, and the hairline above holds the edge where the tone
 * difference alone would be too quiet to register.
 *
 * Two earlier attempts are recorded here because both were wrong for
 * instructive reasons. A 160px FADE from paper to white separated nothing:
 * gradual is the opposite of separate, and the picture read as floating in
 * the hero. A MAUVE TINT separated loudly but put a pale pink panel behind an
 * app whose own chrome is pale pink, so the screenshot lost its edges into
 * its own background. White is the only surface here that the product's
 * interface can sit on and still look like an object.
 */
.shot-band {
  padding: clamp(52px, 7vw, 88px) 0 clamp(54px, 7vw, 96px);
  background: var(--paper-2);
  border-top: 1px solid var(--line);
}
.shot-band .shot { margin-top: 0; }
/* no double hairline where this white meets the white band after it */
.shot-band + .band { border-top: none; }
.shot-cap {
  font-size: 14.5px; color: var(--ink-2); text-align: center;
  margin-top: 14px;
}

/* ---------------------------------------------------------------- module grid */
.grid {
  display: grid; gap: 18px; margin-top: 44px;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
}
.card {
  background: var(--paper-2); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 26px 24px;
  box-shadow: var(--shadow-card);
}
.card h3 { font-size: 21px; margin-bottom: 8px; }
.card p { color: var(--ink-2); font-size: 16px; }
.card-ico {
  width: 46px; height: 46px; border-radius: 14px; margin-bottom: 16px;
  background: var(--accent-100); border: 1px solid var(--accent-200);
  display: grid; place-items: center; color: var(--accent-900);
}
.card-ico svg { width: 23px; height: 23px; }

/* A module that is being built and cannot be used yet.
 *
 * The tag is DELIBERATELY not styled as a warning. A red badge reads as
 * "broken"; this is not broken, it is honest. It is a quiet outline chip that
 * a buyer notices while reading rather than one that shouts across the grid —
 * and the card is set back a little so the four modules that actually work
 * come forward, which is the true state of affairs stated in visual terms.
 *
 * The card must NOT be faded so far that its text fails contrast: at 0.92
 * opacity on this paper the body copy still measures above 4.5:1. Do not
 * "tidy" this to 0.6. */
.card.is-soon {
  background: transparent;
  border-style: dashed;
  box-shadow: none;
}
.card.is-soon .card-ico { background: var(--paper-2); }
.tag {
  display: inline-block; vertical-align: 2px; margin-left: 8px;
  font-size: 12px; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent-900); background: var(--accent-50);
  border: 1px solid var(--accent-200); border-radius: var(--pill);
  padding: 3px 10px;
}
.grid-note {
  margin-top: 22px; font-size: 15.5px; color: var(--ink-2);
  text-align: center; max-width: 720px; margin-left: auto; margin-right: auto;
}
.grid-note b { color: var(--ink); }

/* small print that is not an aside: a caveat that has to be readable */
.small { font-size: 15px; }
.muted { color: var(--ink-2); }
.split .small.muted { margin-top: 18px; }

/* ---------------------------------------------------------------- split rows */
.split {
  display: grid; gap: clamp(28px, 5vw, 64px); align-items: center;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
}
.split + .split { margin-top: clamp(56px, 8vw, 96px); }
.split h2 { font-size: clamp(27px, 3.6vw, 38px); }
.split p { color: var(--ink-2); margin-top: 16px; }
.split .shot { margin-top: 0; }
/* <figure> brings the browser's own 40px side margins, which on a half-width
   column shrank every screenshot beside the text to two-thirds of its column.
   Found while building the industry pages, where the pictures are the point. */
.split > .shot { margin-left: 0; margin-right: 0; }
/* A single-column section with no picture beside it — "The hours", "Being
   built now". A bare <h2> outside .split would otherwise fall back to the
   browser's own 1.5em and read as a sub-heading. */
.wrap.narrow > h2 { font-size: clamp(26px, 3.4vw, 36px); }
.wrap.narrow > p { color: var(--ink-2); margin-top: 16px; }
/* A phone screenshot beside the words: phone-sized, not stretched to fill
   half the page, so the whole screen and its heading fit in one view. */
.split-phone { grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr); }
@media (max-width: 760px) { .split-phone { grid-template-columns: 1fr; } }
.shot-phone {
  /* never taller than the screen it sits on: 2.05 is the picture's height
     over its width, 244px is the header plus the section's own padding */
  width: min(100%, 290px, calc((100vh - 244px) / 2.05));
  width: min(100%, 290px, calc((100svh - 244px) / 2.05));
  justify-self: center;
  border-radius: 30px; border-width: 6px; border-color: #3b2a30;
}
/* the picture first on a phone, second on a wide screen, for alternating rows */
@media (min-width: 900px) { .split.flip > .shot { order: -1; } }

.pair { display: grid; gap: 20px; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); margin-top: 44px; }
.pair figure { margin: 0; }
.pair figcaption { font-size: 15px; color: var(--ink-2); margin-top: 12px; text-align: center; }
.pair .shot { margin-top: 0; }

/* ---------------------------------------------------------------- list */
.ticks { list-style: none; padding: 0; margin: 22px 0 0; display: grid; gap: 12px; }
.ticks li { display: flex; gap: 11px; align-items: flex-start; color: var(--ink-2); }
.ticks svg { width: 21px; height: 21px; flex: none; color: var(--ok); margin-top: 2px; }
.ticks b { color: var(--ink); font-weight: 650; }

/* ---------------------------------------------------------------- band */
.band {
  background: var(--paper-2);
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
}
/* ONE SCREEN TO ITSELF (Jana, 2026-09-25). "Why it exists" is four lines of
   story, and read with the screenshot above it and the next headline below
   it, the eye kept sliding off before the paragraph ended. So the section
   fills the screen under the sticky header (68px) and centres its words, and
   nothing else is in view while it is read.

   svh, not vh: on a phone, vh is measured with the address bar hidden, so a
   100vh block is taller than what is actually visible and the bottom of it
   hides under the browser's own toolbar. The vh line is the fallback for a
   browser without svh. */
.band-screen {
  display: flex; align-items: center;
  min-height: calc(100vh - 68px);
  min-height: calc(100svh - 68px);
  /* Its own soft tint, so the top and bottom edges can be SEEN. On plain
     white, between two white sections, the space above the words looked
     bigger than the space below whenever the page stopped a little short,
     because the tail of the section above was white too and read as part of
     this one. The words were centred all along; the edges were invisible. */
  background: var(--paper);
}
.band-screen > .wrap { width: 100%; }

/* ---------------------------------------------------------------- the form */
.form-card {
  background: var(--paper-2); border: 1px solid var(--line);
  border-radius: var(--radius); padding: clamp(24px, 4vw, 40px);
  box-shadow: var(--shadow-card);
  max-width: 560px; margin: 36px auto 0;
}
.field { display: grid; gap: 7px; margin-bottom: 18px; }
.field label { font-weight: 650; font-size: 15.5px; }
.field .hint { font-size: 14px; color: var(--ink-2); }
.field input, .field select, .field textarea {
  font: inherit; font-size: 16.5px; color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--line-2); border-radius: 16px;
  padding: 13px 16px; min-height: 52px; width: 100%;
  box-shadow: inset 0 2px 5px -3px rgba(58, 34, 38, 0.22);
}
.field textarea { min-height: 96px; resize: vertical; }
.field input:focus, .field select:focus, .field textarea:focus {
  border-color: var(--accent-700); background: var(--paper-2);
}
.field .err { font-size: 14.5px; color: #B23B40; font-weight: 600; }
.field input[aria-invalid="true"], .field select[aria-invalid="true"] { border-color: #B23B40; }
/* the spam trap: off-screen rather than display:none, because some bots skip
   anything that is not rendered. A person never reaches it — it is not in the
   tab order and it is labelled for screen readers as one to leave alone. */
.trap { position: absolute; left: -5000px; width: 1px; height: 1px; overflow: hidden; }
.form-legal { font-size: 14px; color: var(--ink-2); margin-top: 16px; }
.form-ok {
  background: #EAF5EE; border: 1px solid #C3E2CE; color: #1F4D38;
  border-radius: 16px; padding: 16px 18px; font-weight: 600; margin-bottom: 20px;
}

/* ---------------------------------------------------------------- footer */
.site-foot {
  border-top: 1px solid var(--line);
  padding: 46px 0 56px;
  color: var(--ink-2); font-size: 15px;
}
.foot-row { display: flex; flex-wrap: wrap; gap: 18px 34px; align-items: center; }
.foot-row nav { display: flex; flex-wrap: wrap; gap: 2px 10px; margin-left: auto; }
/* 44px of tappable height, not 25. These are the smallest targets on the
   page and they sit at the very bottom, which on a phone is exactly where a
   thumb is least accurate. The negative side margin keeps the row visually
   flush while the padding does the work. */
.foot-row nav a {
  color: var(--ink-2); text-decoration: none;
  display: inline-flex; align-items: center; min-height: 44px; padding: 0 10px; margin: 0 -10px;
}
.foot-row nav a:hover { color: var(--ink); text-decoration: underline; }
.foot-legal { margin-top: 22px; font-size: 14px; }

/* ---------------------------------------------------------------- dark */
/* No dark mode (Jana, 2026-10-16: "i dont prefer it to auto change if my
   phone is dark mode, just stay original theme (light)"). The site is
   always light, whatever the phone is set to. */


/* ---------------------------------------------------------------- clients
   The client line and the trades line: one page for every trade. */
.client-line { margin: 12px auto 0; }
.client-line b { color: var(--ink); }
.trades-line { max-width: 640px; margin: 20px auto 0; font-size: 15px; color: var(--ink-2); text-wrap: balance; }

.foot-legal a { display: inline-flex; align-items: center; min-height: 44px; vertical-align: middle; margin-left: 0.6em; color: var(--ink-2); white-space: nowrap; }

/* ---------------------------------------------------------------- policy
   policy.html, built by tools/policy.py from legal/*.md. Long reading: a
   narrow column, a quiet table of contents, headings that can be linked to. */
.policy { padding: 48px 0 72px; }
.policy h1 { font-size: clamp(30px, 4.2vw, 42px); }
.policy .lede { color: var(--ink-2); margin-top: 14px; }
.policy-toc {
  display: flex; flex-wrap: wrap; gap: 8px; margin: 26px 0 8px;
}
.policy-toc a {
  display: inline-flex; align-items: center; min-height: 44px; padding: 0 16px;
  border: 1px solid var(--line-2); border-radius: var(--pill);
  color: var(--ink); text-decoration: none; font-weight: 600; font-size: 15px;
  background: var(--paper-2);
}
.policy-toc a:hover { border-color: var(--accent-800); }
.policy-doc { padding-top: 34px; scroll-margin-top: 80px; }
.policy-doc + .policy-doc { margin-top: 30px; border-top: 1px solid var(--line); }
.policy-doc h2 { font-size: clamp(24px, 3vw, 30px); }
.policy-doc .ver { color: var(--ink-2); font-size: 15px; margin-top: 6px; }
.policy-doc h3 { font-size: 19px; margin-top: 30px; scroll-margin-top: 80px; }
.policy-doc p { margin-top: 12px; color: var(--ink); }
.policy-doc ul { margin: 12px 0 0; padding-left: 22px; }
.policy-doc li { margin-top: 6px; }
.policy-doc strong { font-weight: 650; }
.policy-draft {
  margin-top: 22px; padding: 14px 18px; border-radius: 16px;
  border: 1px solid var(--line-2); background: var(--accent-50); font-size: 15px;
}
.policy .tbc { background: var(--accent-100); border-radius: 6px; padding: 0 5px; font-style: italic; }

/* ---------------------------------------------------------------- reveal
   The scroll-in, set up by site/early.js (the .rv switch) and site/site.js
   (the tagging). Nothing here applies without .rv, so with JavaScript off or
   reduced motion asked for, the page is simply there. */
.rv:not(.rv-on) .hero h1,
.rv:not(.rv-on) .hero .lede,
.rv:not(.rv-on) .hero-cta { opacity: 0; }

.rv .rv-words .w {
  display: inline-block;
  opacity: 0; filter: blur(10px); transform: translateY(0.3em);
  transition: opacity 0.7s ease, filter 0.7s ease, transform 0.8s cubic-bezier(0.2, 0.7, 0.2, 1);
  transition-delay: calc(var(--i, 0) * 60ms);
}
.rv .rv-words.is-in .w { opacity: 1; filter: none; transform: none; }

.rv [data-rv] {
  opacity: 0;
  transition: opacity 0.8s ease, transform 0.9s cubic-bezier(0.2, 0.7, 0.2, 1);
  transition-delay: calc(var(--d, 0ms) + 120ms);
}
.rv [data-rv="up"] { transform: translateY(26px); }
.rv [data-rv="left"] { transform: translateX(-48px); }
.rv [data-rv="right"] { transform: translateX(48px); }
.rv [data-rv="zoom"] { transform: translateY(40px) scale(0.95); }
.rv [data-rv].is-in { opacity: 1; transform: none; }
/* the hero's lede and buttons follow the headline rather than racing it */
.rv .hero [data-rv] { transition-delay: calc(var(--d, 0ms) + 450ms); }
.rv .hero .hero-cta[data-rv] { transition-delay: 700ms; }

/* ---------------------------------------------------------------- pricing
   One yearly price per team size, then what every plan includes, the setup
   fee, the referral note and the small print. One column on a phone, the
   three sizes side by side from a tablet up. */
#pricing { scroll-margin-top: 64px; }
#pricing .lede { margin-top: 12px; }
.tiers { display: grid; gap: 14px; margin-top: 30px; }
@media (min-width: 860px) { .tiers { grid-template-columns: repeat(3, 1fr); gap: 18px; } }
.tier {
  background: var(--paper-2); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 20px; box-shadow: var(--shadow-card); text-align: center;
}
.tier-size { font-size: 15px; font-weight: 700; color: var(--ink-2); text-transform: uppercase; letter-spacing: 0.06em; }
.tier-amt { font-family: var(--ff-display); font-size: 34px; font-weight: 800; color: var(--accent-900); margin-top: 6px; line-height: 1.1; }
.tier-amt small { font-size: 15px; font-weight: 600; color: var(--ink-2); }
.tier-mo { font-size: 14px; color: var(--ink-2); margin-top: 4px; }
.incl {
  margin: 18px auto 0; max-width: 900px; background: var(--paper-2); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 16px 20px;
}
.incl h3 { font-size: 16px; text-align: center; }
.incl ul { list-style: none; margin: 10px 0 0; padding: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 6px 14px; }
@media (min-width: 760px) { .incl ul { grid-template-columns: repeat(4, 1fr); } }
.incl li, .psetup-inc li { position: relative; padding-left: 22px; font-size: 14.5px; }
.incl li::before, .psetup-inc li::before { content: "\2713"; position: absolute; left: 1px; color: var(--accent-800); font-weight: 800; }
.psetup {
  margin: 18px auto 0; max-width: 760px; background: var(--paper-2); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 18px 20px; box-shadow: var(--shadow-card);
}
.psetup-top { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.psetup h3 { font-size: 18px; }
.psetup-amt { font-family: var(--ff-display); font-size: 25px; font-weight: 800; color: var(--accent-900); }
.psetup-amt small { font-size: 14.5px; font-weight: 600; color: var(--ink-2); }
.psetup-inc { list-style: none; margin: 12px 0 0; padding: 12px 0 0; border-top: 1px solid var(--line); display: grid; gap: 6px; }
@media (min-width: 760px) { .psetup-inc { grid-template-columns: repeat(3, 1fr); gap: 12px; } }
.pref {
  margin: 18px auto 0; max-width: 720px; padding: 13px 16px; border-radius: 16px; text-align: center;
  background: #FFF5DA; border: 1px solid #F1DDA3; color: #6B4A0C; font-size: 15px;
}
.pnote { margin: 18px auto 0; text-align: center; color: var(--ink-2); font-size: 14px; line-height: 1.6; }
.pnote b { color: var(--ink); }
#pricing .btn { margin-top: 22px; }


/* ---------------------------------------------------------------- phones
 * THE EXAMPLES ARE PHONES (Jana, 2026-10-03): every picture of the app is the
 * app on an iPhone, the way most owners and all staff will use it. The frame
 * is part of the picture (site/img/phone-*.webp, 640 x 1338, transparent
 * corners), so the box around the old wide screenshots goes. */
.shot.shot-ph {
  border: 0; background: none; box-shadow: none; overflow: visible;
  width: min(100%, 320px); justify-self: center;
  margin-left: auto; margin-right: auto;
}
.shot.shot-ph img { display: block; width: 100%; height: auto; filter: drop-shadow(0 18px 30px rgba(80, 30, 45, 0.22)); }
.shot-band .shot.shot-ph-hero { width: min(78%, 330px); }
.split > .shot.shot-ph { margin-left: auto; margin-right: auto; }
.pair .shot.shot-ph { width: min(100%, 280px); }
.split-phone .shot-ph { width: min(100%, 320px); }

/* THE PAGE FOLLOWS THE APP (Jana, 2026-10-03): the modules in the app's own
   order, each section opening with its number and name. */
.mod-tag {
  display: inline-flex; align-items: center; gap: 8px; margin: 0 0 18px;
  padding: 7px 14px 7px 8px; border-radius: var(--pill);
  background: var(--accent-100); border: 1px solid var(--accent-200);
  color: var(--accent-900); font-weight: 700; font-size: 14px;
}
.mod-tag b {
  display: grid; place-items: center; width: 22px; height: 22px; border-radius: 50%;
  background: var(--accent-900); color: #fff; font-size: 12px;
}
.card-n { color: var(--accent-900); }
/* Seven modules in alternating bands leave "For every business" and Pricing
   both on paper; a hairline keeps them two things. */
#pricing { border-top: 1px solid var(--line); }

/* A feature inside a module that is built but not offered yet (the tax
 * estimate, 2026-10-05). Dashed like .card.is-soon, for the same reason. */
.soon-box { margin: 22px 0 0; padding: 18px 20px; border: 1.5px dashed var(--accent-200); border-radius: 18px; background: rgba(255, 255, 255, .45); }
.soon-h { margin: 0 0 6px; font-weight: 700; font-size: 18px; }
.soon-box p { margin: 0 0 10px; }
.soon-box .ticks { margin: 0; }
.soon-box .ticks li { margin: 6px 0; }
.soon-box .soon-note { margin: 12px 0 0; }

/* The yearly price, said per day (2026-10-05). Exact: the yearly price / 365. */
.tier-day { display: inline-block; margin: 10px 0 0; padding: 4px 12px; border-radius: var(--pill); background: var(--accent-50); border: 1px solid var(--accent-200); color: var(--accent-900); font-weight: 700; font-size: 14px; }
.tier-tea { margin: 14px 0 0; text-align: center; color: var(--ink-2); font-size: 15px; }

/* Request a demo: one WhatsApp button (2026-10-19) */
.wa-card { text-align: center; max-width: 560px; margin: 26px auto 0; padding: 34px 26px; }
.btn-wa { display: inline-flex; align-items: center; gap: 12px; background: #E7F8EE; color: #128C4A; font-weight: 700; font-size: 20px; padding: 16px 32px; border-radius: 999px; text-decoration: none; box-shadow: inset 0 0 0 1.5px #A8E3C0; }
.btn-wa:hover { background: #D6F3E2; }
.btn-wa:focus-visible { outline: 3px solid #128C7E; outline-offset: 3px; }
.wa-note { margin: 16px 0 0; color: #7A5A5C; font-size: 15px; }
.wa-float { position: fixed; right: 20px; bottom: 20px; z-index: 50; width: 58px; height: 58px; border-radius: 50%; display: grid; place-items: center; background: #E7F8EE; color: #128C4A; box-shadow: inset 0 0 0 1.5px #A8E3C0, 0 6px 18px rgba(0, 0, 0, .18); text-decoration: none; }
.wa-float:hover { background: #D6F3E2; }
.wa-float:focus-visible { outline: 3px solid #128C7E; outline-offset: 3px; }
@media print { .wa-float { display: none; } }
