/* Minibyte — shared styles for the site at minibyte.app.
 *
 * The palette is copied verbatim from the app's own DesignSystem.swift rather than invented,
 * so the page and the product read as one thing. Terracotta means "act on this" here exactly
 * as it does in the app; green is reserved for bytes that have actually gone, never a
 * forecast. If a token moves in Swift, move it here.
 *
 * Three surfaces, same as the app: ground (the page) → sunken (chips, tracks, passive notes)
 * → surface (raised cards), plus the accent card, which appears once on the whole site.
 *
 * Type is the system stack on purpose. The app ships SF Pro, and -apple-system renders real
 * SF on every device a visitor is likely to be holding — a closer match than any webfont,
 * and nothing to download.
 */

:root {
  --ground:      #EDEBE8;  /* Colors.ground */
  --surface:     #FFFFFF;  /* Colors.surface */
  --sunken:      #E2DFDB;  /* Colors.sunken */
  --ink:         #16130F;  /* Colors.ink */
  --ink-soft:    #6B6560;  /* Colors.inkSoft */
  --ink-faint:   #9C948C;  /* Colors.inkFaint — rules and tracks, never text */
  --hairline:    #DCD8D3;  /* Colors.hairline */
  --accent:      #D2542F;  /* Colors.accent — fills and controls */
  --accent-ink:  #AE4023;  /* Colors.accentInk — the value that carries text */
  --accent-wash: #F6E3DB;  /* Colors.accentWash */
  --done:        #2F7D4F;  /* Colors.positive */
  /* --done is a *fill* value, copied from the app, and white on it is 5.0:1. As text it
     lands at 4.24:1 on the ground and 3.7–4.2:1 on the paint tints, so a figure printed
     in green takes one step down. Same meaning, darker ink. */
  --done-text:   #276B43;
  --on-accent:   #FFFFFF;  /* Colors.onAccent */
  --bezel:       #23201D;
  --glow:        rgba(210,84,47,.16);
  --card-line:   transparent;

  /* Every filled control on the site. White on the #D2542F fill is 4.16:1 and dark ink on
     the dark-mode fill is what clears it there — there is no button exemption in 1.4.3, and
     no type size in this design reaches the large-text threshold (1.1rem is 17.6px, not the
     18.66px the exemption needs). So controls take the deeper terracotta in light, and the
     fill with dark ink in dark: 5.9:1 and 5.44:1. */
  --control-fill: #AE4023;
  --control-ink:  #FFFFFF;

  /* Ink for body text on a sunken surface. inkSoft clears 4.5:1 on ground and on surface,
     but lands at 4.33:1 on sunken, which is where the free-plan list and the hero chips
     live. */
  --ink-on-sunken: #635E58;

  /* The accent *card* is fixed in both appearances, as it is in the app: it is a light
     surface either way. It carries paragraphs, so it takes accentInk — white on it is
     5.9:1. */
  --accent-card: #AE4023;

  /* Depth is two shadows, never one: a tight contact shadow plus a wide faint one. */
  --shadow-card: 0 1px 2px rgba(22,19,15,.05), 0 14px 34px -18px rgba(22,19,15,.18);
  --shadow-lift: 0 2px 4px rgba(22,19,15,.06), 0 30px 60px -28px rgba(22,19,15,.30);
  --shadow-hero: 0 2px 6px rgba(174,64,35,.24), 0 22px 48px -22px rgba(210,84,47,.50);
  --shadow-phone: 0 2px 8px rgba(22,19,15,.14), 0 40px 80px -32px rgba(22,19,15,.45);


  /* --- Slab palette. New with the 2026 landing-page direction. -----------------------
     The page is a stack of full-bleed colour blocks rather than white cards on a warm
     ground, so the accent is often the *field* instead of the thing on it — the same
     inversion the light app icon makes. Four slabs, and each one is fixed in both
     appearances: a slab is a printed surface, not a themed one, so its ink never has to
     be re-checked when the page flips.

       accent  #BE4A28  the hero. Chosen over #D2542F because white on it is 5.00:1 and
                        this slab carries a lede, not just a headline. #D2542F stays the
                        fill for controls and chips, where no small text sits on it.
       ink     #23201D  the ticker, safety, pricing, footer. 16.2:1 with white.
       indigo  #3B3A9E  ONE decorative slab, the duplicates block. 9.2:1 with white.
                        Display only — it never means "act on this" and never appears
                        in the app.
       cream   #EDDFBE  a breather between two loud blocks. The one slab that is NOT
                        fixed across appearances, and the exception is forced: it is the
                        only one whose contents are ground-mode cards, and six #1F1D1B
                        cards on a cream field is not a light block, it is a broken one.
                        The first value was #F4EFE7 — 1.04:1 against the ground, a
                        650px-tall block that rendered as nothing. 16.2:1 with ink.

     The primary control is always the highest-contrast pill its slab allows: ink on the
     terracotta hero, white on indigo, terracotta on ink. */
  --slab-accent: #BE4A28;
  --slab-ink:    #23201D;
  --slab-indigo: #3B3A9E;
  --slab-cream:  #EDDFBE;
  --on-slab:      #FFFFFF;
  /* Body ink for the DARK slabs only — 10.4:1 on ink, 5.9:1 on indigo. There is no such
     value for the terracotta slab: white itself is only 5.00:1 there, so the softest tint
     that still clears 4.5:1 is #FAF2F0 — white with extra steps. Text on terracotta is
     therefore all white, and its hierarchy comes from size and weight, which is what the
     reference does too. */
  --on-slab-soft: #D6CEC6;

  /* --- Paints. Decoration only. -----------------------------------------------------
     A printed page uses more than one ink, and the six tools, the three measured jobs
     and the screenshot rail were all reading as one long grey stretch between the
     coloured slabs. Six paints join the palette to break that up.

     The rule that keeps them from competing with terracotta is the whole reason they
     are named apart from it: **a paint is a field or a tint, never a meaning.** It never
     fills a control, never carries a figure, never marks a state. Terracotta still means
     "act on this" and green is still only bytes that have gone.

     Each paint is three values: the field (--paint-*, a saturated hue used on light
     tints and in ornament), the tint (--tint-*, the surface it sits on), and nothing
     else — a paint that needs a fourth value is a paint too many.

       indigo   the duplicates slab, and the Find duplicates chip. The one paint that
                points at something: the tool and the block about it share a hue.
       butter   the privacy slab, and the Screenshots chip. Ink on #F2C85C is 11.2:1,
                which is why that slab carries ink rather than white.
       teal     Free up space.   sky   Convert format.   plum   Sort by hand.
     Shrink to share keeps terracotta: it is the app's headline tool, and the one chip
     in the grid allowed to look like a control does. */
  --paint-indigo: #3B3A9E;
  --paint-butter: #8A5A0B;  /* the ink of the butter pair — yellow can't carry a glyph */
  --paint-teal:   #0E6E64;
  --paint-sky:    #1E5FA8;
  --paint-plum:   #9C2F63;
  --tint-indigo:  #DCDBF6;
  --tint-butter:  #F9E8BE;
  --tint-teal:    #C9E6E0;
  --tint-sky:     #D2E3F5;
  --tint-plum:    #F4D8E6;
  --tint-accent:  #F4DBD1;
  --slab-butter:  #F2C85C;
  --mark-fill:    #F2C85C;

  --card-line-slab: transparent;

  /* The neutral pill. On the ground it must flip with the theme — a #16130F pill on a
     #121110 ground is an invisible button, which is exactly what the "Download" beside
     "Three real jobs" became in dark mode. On the terracotta slab it is always ink,
     because that slab is a fixed surface in both appearances. */
  --pill-neutral:     #16130F;
  --pill-neutral-ink: #FFFFFF;
  --radius-slab: clamp(22px, 2.6vw, 38px);

  --radius-hero: 30px;
  --radius:      26px;
  --radius-sm:   14px;

  --gutter:      1.25rem;
  --section:     clamp(4rem, 8vw, 6.5rem);
  --stack:       clamp(1.75rem, 3.5vw, 2.25rem);
}

/* Shadows do nothing on a near-black ground, so cards take a hairline instead — the same
   swap .cardStyle() makes in the app. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --ground:      #121110;
    --surface:     #1F1D1B;
    --sunken:      #1A1917;
    --ink:         #F5F2EE;
    --ink-soft:    #9C948C;
    --ink-faint:   #6B6560;
    --hairline:    #2C2A27;
    --accent:      #E0673C;
    --accent-ink:  #F2916D;
    --accent-wash: #33211A;
    --done:        #5CC98A;
    --done-text:   var(--done);
    --on-accent:   #FFFFFF;
    --bezel:       #000000;
    --glow:        rgba(224,103,60,.14);
    --card-line:   var(--hairline);
    --control-fill: var(--accent);
    --control-ink:  #16130F;
    --ink-on-sunken: var(--ink-soft);
    --slab-ink:    #2A2724;
  --pill-neutral:     #F5F2EE;
  --pill-neutral-ink: #16130F;
    --pill-neutral:     #F5F2EE;
    --pill-neutral-ink: #16130F;
    --slab-cream:  #1A1917;
    --card-line-slab: #35322E;
    /* Paints in dark: the field lightens to clear 4.5:1 on its own tint, and the tint
       drops to a near-ground surface. The butter *slab* is not here — a slab is a
       printed surface and keeps its colour in both appearances. */
    --paint-indigo: #A9A6FF;
    --paint-butter: #E7B549;
    --paint-teal:   #5FD3C4;
    --paint-sky:    #8FBCF0;
    --paint-plum:   #F09CC4;
    --tint-indigo:  #1E1D33;
    --tint-butter:  #2B2416;
    --tint-teal:    #132724;
    --tint-sky:     #15212F;
    --tint-plum:    #2A1723;
    --tint-accent:  #33211A;
    --mark-fill:    rgba(224,103,60,.34);
    --shadow-card: none;
    --shadow-lift: 0 2px 4px rgba(0,0,0,.5), 0 30px 60px -28px rgba(0,0,0,.8);
    --shadow-hero: 0 2px 6px rgba(0,0,0,.5), 0 22px 48px -22px rgba(0,0,0,.7);
    --shadow-phone: 0 2px 8px rgba(0,0,0,.6), 0 40px 80px -32px rgba(0,0,0,.85);
  }
}

:root[data-theme="dark"] {
  --slab-ink:    #2A2724;
  --slab-cream:  #1A1917;
  --card-line-slab: #35322E;
  --ground:      #121110;
  --surface:     #1F1D1B;
  --sunken:      #1A1917;
  --ink:         #F5F2EE;
  --ink-soft:    #9C948C;
  --ink-faint:   #6B6560;
  --hairline:    #2C2A27;
  --accent:      #E0673C;
  --accent-ink:  #F2916D;
  --accent-wash: #33211A;
  --done:        #5CC98A;
  --done-text:   var(--done);
  --on-accent:   #FFFFFF;
  --bezel:       #000000;
  --glow:        rgba(224,103,60,.14);
  --card-line:   var(--hairline);
  --control-fill: var(--accent);
  --control-ink:  #16130F;
  --ink-on-sunken: var(--ink-soft);
  /* Paints in dark: the field lightens to clear 4.5:1 on its own tint, and the tint
     drops to a near-ground surface. The butter *slab* is not here — a slab is a
     printed surface and keeps its colour in both appearances. */
  --paint-indigo: #A9A6FF;
  --paint-butter: #E7B549;
  --paint-teal:   #5FD3C4;
  --paint-sky:    #8FBCF0;
  --paint-plum:   #F09CC4;
  --tint-indigo:  #1E1D33;
  --tint-butter:  #2B2416;
  --tint-teal:    #132724;
  --tint-sky:     #15212F;
  --tint-plum:    #2A1723;
  --tint-accent:  #33211A;
  --mark-fill:    rgba(224,103,60,.34);
  --shadow-card: none;
  --shadow-lift: 0 2px 4px rgba(0,0,0,.5), 0 30px 60px -28px rgba(0,0,0,.8);
  --shadow-hero: 0 2px 6px rgba(0,0,0,.5), 0 22px 48px -22px rgba(0,0,0,.7);
  --shadow-phone: 0 2px 8px rgba(0,0,0,.6), 0 40px 80px -32px rgba(0,0,0,.85);
}

* { box-sizing: border-box; }

/* overflow-x lives on <html>, never on <body>: a scroll container on <body> silently
   breaks position:sticky and IntersectionObserver for everything inside it. */
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; overflow-x: hidden; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", Roboto,
               Helvetica, Arial, sans-serif;
  font-size: 17px;
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.wrap { max-width: 66rem; margin: 0 auto; padding: 0 var(--gutter); }
.wrap--prose { max-width: 44rem; }

.section { margin-top: var(--section); }
.measure { max-width: 34rem; }
.center  { text-align: center; }
.stack   { margin-top: var(--stack); }

/* ---------- masthead ---------- */
.masthead {
  /* Transparent until something scrolls under it. A translucent panel sitting over the hero's
     warm bloom draws a visible seam across the top of the page, and at the top of the page
     there is nothing to blur anyway. */
  position: sticky; top: 0; z-index: 20;
  border-bottom: 1px solid transparent;
  transition: border-color .2s ease, background-color .2s ease;
}
.masthead.is-stuck, .masthead--flat {
  background: color-mix(in srgb, var(--ground) 84%, transparent);
  -webkit-backdrop-filter: saturate(1.6) blur(14px);
  backdrop-filter: saturate(1.6) blur(14px);
  border-bottom-color: var(--hairline);
}
/* The gutter is set here, not inherited from .wrap: .wrap's own padding shorthand loses to
   any later padding declaration, and the wordmark ends up 20px off the page grid. */
.masthead__inner {
  display: flex; align-items: center; gap: .5rem;
  padding: .5rem var(--gutter);
}
.wordmark {
  display: inline-flex; align-items: center; gap: .6rem;
  font-size: .78rem; font-weight: 700; letter-spacing: .16em;
  text-transform: uppercase; color: var(--ink); text-decoration: none;
  margin-right: auto; padding: .6rem 0;
}
.wordmark svg { display: block; flex: none; color: var(--accent-ink); }
.masthead nav { display: flex; align-items: center; gap: .35rem; }
.masthead nav a {
  font-size: .92rem; color: var(--ink-soft); text-decoration: none;
  padding: .65rem; border-radius: var(--radius-sm);
}
.masthead nav a:hover, .masthead nav a[aria-current="page"] { color: var(--accent-ink); }
/* The download pill is a filled control, not a nav link — it keeps its own ink. */
.masthead nav a.cta, .masthead nav a.cta:hover { color: var(--control-ink); }

/* One accent surface per viewport: above the fold that is the hero button, so the pill in
   the masthead only arrives once the hero has scrolled past. */
.masthead .cta--small {
  display: none; margin-left: .4rem;
  opacity: 0; transform: translateY(-2px); transition: opacity .25s ease, transform .25s ease;
}
.masthead .cta--small { display: inline-flex; }
/* Below this the four nav items wrap and shove the wordmark off its own line. The links
   are all reachable from the footer, and the hero's own CTA is one screen away. */
@media (max-width: 45.99rem) { .masthead nav a:not(.cta) { display: none; } }
.masthead.is-stuck .cta--small { opacity: 1; transform: none; }
/* The subpages have no hero to scroll past, so their pill is there from the start. */
.masthead--flat .cta--small { opacity: 1; transform: none; }

/* ---------- type ---------- */
.eyebrow {
  font-size: .74rem; font-weight: 700; letter-spacing: .18em;
  text-transform: uppercase; color: var(--ink-soft); margin: 0 0 .85rem;
}
.display {
  font-size: clamp(2.9rem, 8.4vw, 4.6rem); font-weight: 800;
  letter-spacing: -.038em; line-height: .96; margin: 0 0 1.25rem;
  text-wrap: balance;
}
h1 { font-size: clamp(2.1rem, 6vw, 2.9rem); font-weight: 800; letter-spacing: -.03em;
     line-height: 1.05; margin: 0 0 1rem; text-wrap: balance; }
h2 { font-size: clamp(1.6rem, 3.6vw, 2.1rem); font-weight: 750; letter-spacing: -.025em;
     line-height: 1.12; margin: 0 0 .75rem; text-wrap: balance; }
h3 { font-size: 1.08rem; font-weight: 700; letter-spacing: -.012em; margin: 0 0 .35rem; }
p  { margin: 0 0 1rem; }
.lede { font-size: clamp(1.1rem, 2.2vw, 1.28rem); color: var(--ink-soft); text-wrap: pretty;
        line-height: 1.5; max-width: 34rem; }
.soft { color: var(--ink-soft); }
.fine { color: var(--ink-soft); font-size: .86rem; line-height: 1.5; }
.num  { font-variant-numeric: tabular-nums; font-feature-settings: "tnum" 1; }
a { color: var(--accent-ink); text-underline-offset: 3px; }

/* ---------- phone ---------- */
.phone {
  position: relative; width: 100%; max-width: 19rem; margin: 0 auto;
  border-radius: 13.5%/6.4%; padding: .55rem;
  background: linear-gradient(160deg, #3A3630, var(--bezel) 42%, #100E0C);
  box-shadow: var(--shadow-phone);
}
.phone img {
  display: block; width: 100%; height: auto;
  border-radius: 11%/5.2%;
  background: var(--sunken);
}

/* Two bars against the 25 MB line: why the result on the phone matters, rather than a second
   printing of what it says. The "before" bar is a track, not a control, so it takes no
   accent — the same way SavingsBar draws the original as a ghost. */
.gauge { position: relative; display: grid; gap: .5rem; padding-top: 1.15rem; }
.gauge-row { display: grid; grid-template-columns: 1fr 3.9rem; gap: .5rem; align-items: center; }
.gauge-bar { background: var(--sunken); border-radius: 999px; height: 11px; overflow: hidden; }
.gauge-label { font-size: .76rem; font-weight: 650; color: var(--ink-soft); }
.gauge-label.now { color: var(--done-text); }
.gauge-bar i {
  display: block; height: 100%; border-radius: 999px; background: var(--ink-soft);
  transform-origin: left center; transform: scaleX(var(--to, 1));
}
.gauge-bar i.is-result { background: var(--done); }
.gauge-bar i.is-animated { animation: contract 1.1s cubic-bezier(.22,.61,.36,1) both; }
.gauge-line {
  position: absolute; top: .95rem; bottom: -.2rem; width: 0;
  border-left: 1.5px dashed var(--ink-faint);
}
.gauge-line b {
  position: absolute; top: -1.2rem; left: .35rem;
  font-size: .68rem; font-weight: 700; letter-spacing: .04em; color: var(--ink-soft);
  white-space: nowrap;
}
@keyframes contract { from { transform: scaleX(var(--from, 1)); } to { transform: scaleX(var(--to, 1)); } }

/* ---------- cards ---------- */
.card {
  background: var(--surface); border: 1px solid var(--card-line);
  border-radius: var(--radius);
  padding: clamp(1.4rem, 3vw, 2.1rem); box-shadow: var(--shadow-card);
}
.card--accent {
  position: relative; overflow: hidden; border: 0;
  padding: clamp(1.6rem, 3.4vw, 2.4rem);
  background: var(--slab-accent); color: var(--on-slab);
  border-radius: var(--radius-slab); box-shadow: var(--shadow-hero);
}
.card--accent .eyebrow,
.card--accent h2 { color: var(--on-slab); }
.card--accent p { color: var(--on-slab); }
.card--accent .eyebrow { opacity: 1; }
.card--accent .mark-watermark {
  /* In the flow, not absolutely placed: the copy pushes the stamp down instead of running
     through it, whatever anyone writes here later. */
  display: none; width: 4.75rem; opacity: .3;
  margin: .35rem 0 0 auto; pointer-events: none;
}
@media (min-width: 58rem) { .card--accent .mark-watermark { display: block; } }

/* ---------- split rows: copy beside a phone ---------- */
.split { display: grid; gap: clamp(2rem, 5vw, 3.5rem); align-items: center; }
.split .phone { max-width: 17rem; }
@media (min-width: 58rem) {
  .split { grid-template-columns: minmax(0, 1fr) minmax(0, .8fr); }
  .split--flip > :first-child { order: 2; }
}

/* ---------- feature grid ---------- */
.features { display: grid; gap: .9rem; }
@media (min-width: 40rem) { .features { grid-template-columns: 1fr 1fr; } }
@media (min-width: 62rem) { .features { grid-template-columns: repeat(3, 1fr); } }
.feature {
  background: var(--surface); border: 1px solid var(--card-line);
  border-radius: var(--radius);
  padding: 1.5rem; box-shadow: var(--shadow-card);
}
.feature p { margin: 0; color: var(--ink-soft); font-size: .95rem; line-height: 1.55; }
.icon-chip {
  display: grid; place-items: center; width: 2.75rem; height: 2.75rem;
  border-radius: 999px; background: var(--sunken); color: var(--ink);
  margin-bottom: .95rem;
}
.icon-chip svg { display: block; }

/* ---------- screenshot rail ---------- */
.rail {
  display: grid; grid-auto-flow: column; grid-auto-columns: 14rem;
  gap: 1.5rem; overflow-x: auto; scroll-snap-type: x proximity;
  scroll-padding-left: var(--gutter);
  padding: .5rem var(--gutter) 1.5rem; margin: 0 calc(var(--gutter) * -1);
  scrollbar-width: thin;
}
@media (min-width: 46rem) { .rail { grid-auto-columns: 16rem; } }
.rail > figure { scroll-snap-align: start; margin: 0; }
.rail .phone { max-width: none; }
.rail figcaption {
  margin-top: 1rem; color: var(--ink-on-sunken); font-size: .9rem; line-height: 1.5;
  text-wrap: pretty;
}
.rail figcaption b { color: var(--ink); font-weight: 650; display: block; }

/* ---------- facts list ---------- */
.facts { margin: 1.5rem 0 0; padding: 0; list-style: none; display: grid; gap: .75rem; }
.facts li {
  display: grid; grid-template-columns: 1.35rem 1fr; gap: .7rem;
  color: var(--ink-soft); font-size: .97rem; line-height: 1.5;
}
.facts svg { margin-top: .35rem; color: var(--ink-soft); }

/* ---------- pricing ---------- */
.plans { display: grid; gap: 1rem; align-items: start; }
@media (min-width: 46rem) { .plans { grid-template-columns: 1fr 1fr; } }
.plan { background: var(--surface); border: 1px solid var(--card-line);
        border-radius: var(--radius); padding: 1.6rem; box-shadow: var(--shadow-card); }
/* The border is transparent in light and a hairline in dark — without it this card sits at
   #1A1917 on a #121110 ground beside a lifted ink slab, and reads as a hole. */
.plan--sunken { background: var(--sunken); box-shadow: none; border-color: var(--card-line); }
.plan ul { margin: 1rem 0 0; padding: 0; list-style: none; display: grid; gap: .55rem; }
.plan li { display: grid; grid-template-columns: 1.1rem 1fr; gap: .6rem;
           color: var(--ink-soft); font-size: .95rem; line-height: 1.5; }
.plan li svg { margin-top: .38rem; color: var(--ink-soft); }
/* Doubled class, and after the rule it overrides: .plan--sunken li ties with .plan li on
   specificity, so written above it the softer ink would simply lose. */
.plan.plan--sunken li,
.plan.plan--sunken li svg { color: var(--ink-on-sunken); }
.plan .price { font-weight: 700; color: var(--ink); font-size: 1rem; margin: .8rem 0 0; }

/* ---------- pill / cta ---------- */
.cta {
  display: inline-flex; align-items: center; gap: .5rem;
  background: var(--control-fill); color: var(--control-ink);
  font-size: 1.1rem; font-weight: 700; text-decoration: none;
  padding: .85rem 1.7rem; border-radius: 999px; box-shadow: var(--shadow-hero);
  transition: transform .18s cubic-bezier(.22,.61,.36,1), filter .18s ease;
}
.cta:hover { filter: brightness(1.06); transform: translateY(-1px); }
.cta:active { transform: translateY(0) scale(.985); }
.cta--small { font-size: .95rem; padding: .6rem 1.1rem; box-shadow: none; }
@media (max-width: 26rem) { .cta { font-size: 1rem; padding: .78rem 1.3rem; } }
.cta-row { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem 1.5rem; }
.cta-row .quiet { color: var(--ink-soft); text-decoration: none; font-weight: 600;
                  font-size: .95rem; padding: .55rem 0;
                  border-bottom: 1px solid var(--hairline); }
.cta-row .quiet:hover { color: var(--accent-ink); border-bottom-color: currentColor; }
.pill {
  display: inline-block; background: var(--accent-wash); color: var(--accent-ink);
  font-size: .78rem; font-weight: 700; padding: .25rem .65rem; border-radius: 999px;
}
.pill--neutral { background: var(--sunken); color: var(--ink-soft); }
.plan--sunken .pill--neutral { background: var(--surface); }

/* ---------- numbered policy sections ---------- */
.clause { border-top: 1px solid var(--hairline); padding-top: 1.6rem; margin-top: 2.1rem; }
.clause .clause-num {
  display: block; font-size: .72rem; font-weight: 700; letter-spacing: .16em;
  color: var(--accent-ink); margin-bottom: .55rem; font-variant-numeric: tabular-nums;
}
.clause h2 { font-size: 1.35rem; }
.clause p { color: var(--ink-soft); margin: 0; }

/* ---------- support Q&A ---------- */
.qa { margin: 1.5rem 0 0; }
.qa details { border-top: 1px solid var(--hairline); padding: .35rem 0; }
.qa summary {
  cursor: pointer; font-weight: 650; list-style: none; padding: .75rem 0;
  display: flex; justify-content: space-between; gap: 1rem;
}
.qa summary::-webkit-details-marker { display: none; }
.qa summary::after { content: "+"; color: var(--accent-ink); font-weight: 400; flex: none; }
.qa details[open] summary::after { content: "–"; }
.qa details p { color: var(--ink-soft); margin: 0 0 .9rem; }

/* ---------- contact block ---------- */
.contact {
  background: var(--surface); border: 1px solid var(--card-line);
  border-radius: var(--radius-sm);
  padding: 1.4rem; box-shadow: var(--shadow-card); margin: 2rem 0;
}
.contact a { font-weight: 700; font-size: 1.05rem; }
.contact p:last-child { margin: .5rem 0 0; color: var(--ink-soft); font-size: .92rem; }

/* ---------- footer ---------- */
footer {
  margin-top: var(--section); padding: 1.5rem 0 3rem;
  border-top: 1px solid var(--hairline);
  color: var(--ink-soft); font-size: .88rem;
  display: flex; flex-wrap: wrap; gap: .25rem 1.5rem; align-items: center;
}
footer a { color: var(--ink-soft); text-decoration: none; padding: .7rem 0; }
footer a:hover { color: var(--accent-ink); }
footer .wordmark { margin-right: 1rem; padding: .7rem 0; }
footer .spacer { margin-left: auto; }

/* Anchor targets clear the sticky masthead, which otherwise eats the eyebrow and half the
   heading of whatever was linked to. */
main [id] { scroll-margin-top: 5rem; }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 4px; }

/* ---------- reveal on scroll ---------- */
/* The hiding rule is scoped to .js, which the same script sets — so a script that never
   runs can't leave half the page invisible. Children stagger, so a grid arrives as items
   rather than as one slab. */
.js .reveal > * { opacity: 0; transform: translateY(14px); }
.js .reveal.is-in > * {
  opacity: 1; transform: none;
  transition: opacity .55s cubic-bezier(.22,.61,.36,1) var(--d, 0ms),
              transform .55s cubic-bezier(.22,.61,.36,1) var(--d, 0ms);
}
.js .reveal > :nth-child(2) { --d: 60ms; }
/* order: 2 moves the phone visually but not in the DOM, so the delays would run right to
   left in a flipped row. */
.js .split--flip > :nth-child(1) { --d: 60ms; }
.js .split--flip > :nth-child(2) { --d: 0ms; }
.js .reveal > :nth-child(3) { --d: 120ms; }
.js .reveal > :nth-child(4) { --d: 180ms; }
.js .reveal > :nth-child(5) { --d: 240ms; }
.js .reveal > :nth-child(6) { --d: 300ms; }

/* prose subpages start below the sticky masthead */
.page { padding-top: clamp(2rem, 5vw, 3.25rem); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
  .gauge-bar i { transform: scaleX(var(--to, 1)); }
  .js .reveal > * { opacity: 1; transform: none; }
}


/* =====================================================================================
   SLABS — the 2026 landing direction
   =====================================================================================
   The page is a stack of full-bleed colour blocks. A slab is a printed surface: its
   palette is fixed in both appearances, so nothing inside one has to be re-checked when
   the page flips. Everything that sits on a slab therefore takes its ink from the slab,
   never from --ink.

   These rules are landing-page furniture. privacy.html and support.html use none of
   them; the shared components above are what those pages are built from.
   ===================================================================================== */

.slab {
  position: relative; isolation: isolate; overflow: hidden;
  border-radius: var(--radius-slab);
  padding: clamp(1.6rem, 4vw, 3.25rem);
  border: 1px solid var(--card-line-slab);
}
.slab--accent { background: var(--slab-accent); color: var(--on-slab); }
.slab--ink    { background: var(--slab-ink);    color: var(--on-slab); }
.slab--indigo { background: var(--slab-indigo); color: var(--on-slab); }
.slab--cream  { background: var(--slab-cream);  color: var(--ink); border-color: transparent; }

/* One inheritance rule rather than a per-element list, so a paragraph added to a slab
   later can't come out in ground-mode ink. */
.slab--accent .eyebrow, .slab--ink .eyebrow, .slab--indigo .eyebrow,
.slab--accent h1, .slab--ink h1, .slab--indigo h1,
.slab--accent h2, .slab--ink h2, .slab--indigo h2,
.slab--accent h3, .slab--ink h3, .slab--indigo h3 { color: var(--on-slab); }
/* 80% white is 10.7:1 on ink and 6.5:1 on indigo. On terracotta it is 2.67:1, so the
   eyebrow there stays at full strength. */
.slab--ink .eyebrow, .slab--indigo .eyebrow { opacity: .8; }

.slab--ink p, .slab--ink .lede, .slab--ink .soft,
.slab--indigo p, .slab--indigo .lede { color: var(--on-slab-soft); }
.slab--accent p, .slab--accent .lede { color: var(--on-slab); }
.slab--ink .facts li, .slab--ink .facts svg { color: var(--on-slab-soft); }
.slab--ink a:not(.cta), .slab--indigo a:not(.cta) { color: var(--on-slab); }

/* The repeated wordmark behind the hero. Clipped by the slab, never selectable, and it
   sits under everything on the slab's own stacking context. */
.slab__watermark {
  display: none;
  position: absolute; inset: 0 auto auto -2%; width: 108%; z-index: -1;
  margin: 0; padding: 0; user-select: none; pointer-events: none;
  font-size: clamp(3.4rem, 10vw, 7.5rem); font-weight: 800; letter-spacing: -.05em;
  line-height: .82; text-transform: lowercase; color: #fff; opacity: .06;
  word-spacing: .1em;
}
@media (min-width: 62rem) { .slab__watermark { display: block; } }

/* A slab that is copy beside a stage. Same shape as .split, but the gap and the ordering
   belong to the slab, not to the page grid. */
.slab--indigo, .slab--ink:not(.footer__slab) { display: grid; gap: clamp(2rem, 4.5vw, 3.25rem); align-items: center; }
@media (min-width: 58rem) {
  .slab--indigo { grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr); }
  .slab--ink:not(.footer__slab) { grid-template-columns: minmax(0, 1fr) minmax(0, .62fr); }
}
.slab__copy > :last-child { margin-bottom: 0; }
.slab__stage .phone { max-width: 15.5rem; }

/* ---------- hero ---------- */
.hero { padding-top: clamp(1rem, 3vw, 2rem); }
/* The warm bloom went with the white hero it was lighting. A radial gradient behind a
   solid terracotta slab is invisible, and the slab does that job now. */
.hero__slab {
  display: grid; gap: clamp(2.5rem, 5vw, 3.5rem); align-items: center;
  padding-bottom: clamp(2.5rem, 5vw, 3.5rem);
}
@media (min-width: 62rem) {
  .hero__slab { grid-template-columns: minmax(0, 1.06fr) minmax(0, .94fr); }
}
.hero__copy > :last-child { margin-bottom: 0; }

.hero .display { margin-bottom: 1.1rem; }
.hero .lede { color: var(--on-slab); max-width: 30rem; }

.hero__claims { display: flex; flex-wrap: wrap; gap: .45rem; margin: 1.5rem 0 1.75rem;
                padding: 0; list-style: none; }
/* On the terracotta slab the chips invert: a sunken chip has no meaning on a field that
   is itself the accent, and white on white-at-16%-over-terracotta does not clear 4.5:1. */
.hero__claims li {
  background: #fff; color: #16130F;
  font-size: .82rem; font-weight: 650; padding: .32rem .8rem; border-radius: 999px;
}

.hero__stage { position: relative; max-width: 21rem; margin: 0 auto; }
.hero__stage .phone { max-width: none; position: relative; z-index: 2; }

/* Loose photos from the roll, behind the phone. Decorative and aria-hidden, so they are
   allowed to be cropped by the slab. */
.hero__snap {
  /* height:auto is load-bearing: the width/height attributes on the <img> map to a
     presentational hint for `height`, and that beats the height aspect-ratio would derive.
     Without it every cropped image on this page renders at its intrinsic pixel height. */
  display: none; position: absolute; z-index: 1; height: auto;
  border-radius: 12px; border: 4px solid #fff; object-fit: cover;
  box-shadow: 0 2px 6px rgba(0,0,0,.18), 0 24px 48px -20px rgba(0,0,0,.5);
}
@media (min-width: 62rem) {
  .hero__snap { display: block; }
  .hero__snap--a { width: 44%; aspect-ratio: 4/3; left: -30%; top: 4%;      transform: rotate(-10deg); }
  .hero__snap--b { width: 34%; aspect-ratio: 3/4; right: -19%; bottom: -1%; transform: rotate(8deg); }
  .hero__snap--c { width: 33%; aspect-ratio: 4/3; right: -13%; top: -1%;    transform: rotate(6deg); }
}

.hero__chip {
  background: var(--surface); border: 1px solid var(--card-line);
  border-radius: var(--radius-sm);
  padding: 1rem 1.1rem; box-shadow: var(--shadow-lift);
  margin: 1.25rem auto 0; max-width: 21rem;
}
@media (min-width: 62rem) {
  /* Low, not centred: the phone behind it is the home ledger now, and the rows in its
     middle third are the reason the shot is here. The chip clips the tool chips along the
     bottom edge instead — the one band of that screen nothing is being read off.

     This used to be pinned at 7.5rem, on the rule that anything below ~7rem crossed the
     Share button and made the hero open on a phone that looked broken. That rule belonged
     to the old hero shot, `01-shrink-video-result`, which had a Share button in it. The
     ledger screen does not, so the floor is gone — but check this again if the hero phone
     ever changes screens.

     There is no offset that clears everything: the chip is taller than the gap between the
     last ledger row and the accent button, and the copy column ends 8px to its left, so it
     cannot move sideways either. It is parked below the rows on purpose. The four figures
     are what the lede promises and what the hero is arguing; the button restates a claim
     the lede already makes, so it is the one to lose. */
  .hero__chip { position: absolute; left: -5rem; bottom: -2.9rem; z-index: 3;
                width: 15.5rem; margin: 0; }
}
.hero__chip .chip-title {
  margin: 0 0 .9rem; color: var(--ink); font-weight: 650; font-size: .92rem; line-height: 1.35;
}

/* The price, drawn as a receipt rather than a figure. The claim is not that it is cheap —
   it is that the transaction ends — so the rows are read down the right-hand edge and the
   two that matter say the same word. No accent and no green: green is reserved for bytes
   that have actually gone, and a price is neither measured nor gone. */
.chip-ledger { list-style: none; margin: 0; padding: 0; display: grid; gap: .5rem; }
.chip-ledger li {
  display: flex; justify-content: space-between; align-items: baseline; gap: .75rem;
  font-size: .82rem; color: var(--ink-soft);
  border-top: 1px dashed var(--card-line); padding-top: .5rem;
}
.chip-ledger li:first-child { border-top: 0; padding-top: 0; }
.chip-ledger b { font-weight: 700; color: var(--ink); white-space: nowrap; }
.chip-ledger b.is-none { color: var(--ink-faint); font-weight: 650; }

/* ---------- expressive type ---------- */
/* The dingbat is the page's one ornament: headline, section rule, pull-quote. Same shape
   in all three, so it reads as punctuation rather than as three separate decorations. */
.ding { display: inline-block; vertical-align: .06em; color: currentColor; }
.nobr { white-space: nowrap; }
.ding--display { width: .5em; height: .5em; opacity: .9; }
/* middle, matching the rule it closes — the two were on different optical lines. */
.ding--rule { width: 1.15rem; height: 1.15rem; color: var(--accent-ink); vertical-align: middle; }
.ding--big { display: block; width: 2rem; height: 2rem; margin: 0 auto 1.25rem;
             color: var(--accent-ink); }

/* The stroke under "send". Absolutely placed so it cannot add a line box and push the
   headline's leading around, and scaled to the word by the span it sits in. */
.ul { position: relative; white-space: nowrap; }
.ul .swash {
  position: absolute; left: 0; right: 0; top: 100%; margin-top: -.14em;
  width: 100%; height: .17em; color: currentColor; opacity: .85;
  overflow: visible;
}

/* A photo in a pill, set inline in a headline. Sized in em so it tracks the display
   clamp instead of needing its own breakpoints. */
.lozenge {
  display: inline-block; vertical-align: -.09em;
  width: 1.55em; height: .74em; border-radius: 999px; overflow: hidden;
  background: var(--sunken);
}
.lozenge img { display: block; width: 100%; height: 100%; object-fit: cover; }

.statement {
  font-size: clamp(1.4rem, 3.2vw, 2.2rem); font-weight: 700; letter-spacing: -.024em;
  line-height: 1.22; max-width: 48rem; margin: 0; text-wrap: pretty;
}
.statement__rule {
  display: inline-block; vertical-align: middle;
  width: min(16vw, 8rem); height: 2px; background: var(--ink-faint);
  margin: 0 .45rem 0 .8rem;
}

.pull {
  font-size: clamp(2rem, 5.4vw, 3.3rem); font-weight: 800; letter-spacing: -.038em;
  line-height: 1.02; margin: 0 0 1.25rem; text-wrap: balance;
}

/* A heading with a control on its right, the way a shop heads a product row. */
.head-row {
  display: flex; flex-wrap: wrap; gap: 1rem 1.5rem;
  align-items: flex-end; justify-content: space-between;
}
.head-row > :first-child { margin-bottom: 0; }
.head-row h2 { margin-bottom: 0; }
.rail-hint { margin: 0; }

/* ---------- ticker ---------- */
/* Full bleed. html already carries overflow-x:hidden, so the 100vw trick cannot widen
   the document — and the width must be vw, not %, to reach past .wrap's max-width. */
.ticker {
  margin: var(--section) 0 0;
  width: 100vw; margin-left: calc(50% - 50vw);
  background: var(--slab-ink); color: var(--on-slab);
  padding: .85rem 0; overflow: hidden;
}
.ticker__track { display: flex; width: max-content; animation: marquee 52s linear infinite; }
.ticker:hover .ticker__track, .ticker:focus-within .ticker__track { animation-play-state: paused; }
.ticker__run {
  display: flex; align-items: center; gap: 2.4rem;
  margin: 0; padding: 0 1.2rem 0 0; list-style: none;
}
.ticker__run li {
  display: inline-flex; align-items: center; gap: .65rem;
  white-space: nowrap; font-size: .95rem; color: var(--on-slab-soft);
}
.ticker__run li::after {
  content: ""; width: 5px; height: 5px; border-radius: 50%;
  background: var(--accent); margin-left: 1.75rem;
}
.ticker__run img {
  width: 2.2rem; height: 2.2rem; border-radius: 8px; object-fit: cover; flex: none;
}
.ticker__run b { color: var(--on-slab); font-weight: 700; }
@keyframes marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }

/* ---------- results row ---------- */
.results { display: grid; gap: 1.1rem; }
@media (min-width: 46rem) { .results { grid-template-columns: repeat(3, 1fr); } }
.result { margin: 0; }
.result img {
  display: block; width: 100%; height: auto; aspect-ratio: 4/3; object-fit: cover;
  border-radius: 20px; background: var(--sunken);
}
.result figcaption {
  display: flex; flex-wrap: wrap; gap: .15rem 1rem;
  align-items: baseline; justify-content: space-between;
  margin-top: .95rem; padding-top: .85rem; border-top: 1px solid var(--hairline);
}
.result figcaption b { font-weight: 650; font-size: .98rem; }
.result__figures { display: inline-flex; align-items: baseline; gap: .4rem; font-size: .92rem;
                   font-weight: 650; }
.result .was { color: var(--ink-soft); }
.result .arrow { color: var(--ink-faint); }
/* Green, here as everywhere, is a byte that has actually gone — these are measured
   results, not forecasts. --done-text rather than --done because these figures print on
   a paint tint now, and the fill value does not clear 4.5:1 on one. */
.result .now { color: var(--done-text); }

/* ---------- duplicate burst ---------- */
/* Five frames of one moment, overlapped the way they sit in a roll. The keeper is lifted
   and ringed rather than merely labelled, because the point of the block is that the app
   picks one — and the ring is the same gesture the app's rosette makes. */
.burst { display: flex; justify-content: center; align-items: center; padding: 1rem 0; }
.burst__frame {
  position: relative; display: block; flex: none;
  width: clamp(4.4rem, 13vw, 7.2rem); aspect-ratio: 1;
  border-radius: 16px; overflow: visible;
  margin-left: -1.1rem;
  box-shadow: 0 2px 6px rgba(0,0,0,.25), 0 18px 36px -16px rgba(0,0,0,.55);
}
.burst__frame:first-child { margin-left: 0; }
.burst__frame img {
  display: block; width: 100%; height: 100%; object-fit: cover;
  border-radius: 16px; border: 3px solid #fff;
  filter: saturate(.7) brightness(.86);
}
.burst__frame:nth-child(1) { transform: rotate(-7deg); }
.burst__frame:nth-child(2) { transform: rotate(3deg); }
.burst__frame:nth-child(4) { transform: rotate(-3deg); }
.burst__frame:nth-child(5) { transform: rotate(6deg); }
.burst__frame.is-keeper { z-index: 2; transform: scale(1.16) rotate(-1deg); }
.burst__frame.is-keeper img { filter: none; border-color: var(--accent); border-width: 3px; }
.burst__frame b {
  position: absolute; left: 50%; bottom: -.7rem; transform: translateX(-50%);
  /* Hardcoded, not --control-fill: this slab is fixed in both appearances, so the badge
     that sits on it has to be too. White on #AE4023 is 5.9:1. */
  background: #AE4023; color: #fff;
  font-size: .66rem; font-weight: 700; letter-spacing: .04em;
  padding: .16rem .5rem; border-radius: 999px; white-space: nowrap;
}

/* ---------- tools, on the cream breather ---------- */
.tools-slab { padding: clamp(1.75rem, 4.5vw, 3.5rem); }
/* Cream is a darker paper than the ground now, and inkSoft lands at 4.35:1 on it. Direct
   children only — the paragraphs inside the feature cards are on white and keep theirs. */
.slab--cream > .eyebrow, .slab--cream > .lede, .slab--cream > p { color: var(--ink-on-sunken); }
.feature { position: relative; }
.feature__num {
  position: absolute; top: 1.25rem; right: 1.35rem;
  font-size: .74rem; font-weight: 700; letter-spacing: .1em; color: var(--ink-faint);
}

/* Seven cards do not divide by three, and a lone seventh on the last row reads as a
   mistake. The lead card takes the whole first row instead — which is also the hierarchy
   the app itself uses, where Free Up Space is the one accent surface on the home screen
   and the other six jobs are rows and chips beneath it. Its paragraph keeps a readable
   measure rather than stretching to the full slab. */
@media (min-width: 40rem) {
  .feature--lead { grid-column: 1 / -1; }
  .feature--lead p { max-width: 34rem; }
}

/* ---------- pricing: the paid plan is the ink one ---------- */
.plan--ink {
  background: var(--slab-ink); color: var(--on-slab); border-color: transparent;
  box-shadow: var(--shadow-lift);
}
.plan--ink .price { color: var(--on-slab); }
.plan.plan--ink li, .plan.plan--ink li svg, .plan--ink .fine { color: var(--on-slab-soft); }
.plan--ink .pill { background: rgba(255,255,255,.14); color: #fff; }

/* ---------- footer slab ---------- */
/* privacy.html and support.html still use the bare <footer> rule above — a hairline row.
   The landing page's footer is a slab, so it has to undo that rule rather than inherit it. */
.footer {
  display: block; border-top: 0;
  margin-top: var(--section); padding: 0 0 clamp(1.5rem, 4vw, 3rem);
}
.footer__slab {
  display: grid; gap: clamp(2rem, 4vw, 3rem);
  padding: clamp(2rem, 5vw, 4rem);
}
@media (min-width: 52rem) {
  .footer__slab { grid-template-columns: minmax(0, 1.35fr) minmax(0, .65fr); }
  .footer__fine { grid-column: 1 / -1; }
}
.footer__close > :last-child { margin-bottom: 0; }
.footer__close .display { margin-bottom: .75rem; }
.footer__close .soft { color: var(--on-slab-soft); }

.footer__burst {
  position: absolute; right: -7rem; bottom: -9rem; width: 26rem; height: 26rem;
  z-index: -1; color: #fff; opacity: .13; pointer-events: none;
}

.footer__nav { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; align-content: start; }
.footer__nav h3 { font-size: .74rem; font-weight: 700; letter-spacing: .16em;
                  text-transform: uppercase; color: var(--on-slab); opacity: .55;
                  margin: 0 0 .35rem; }
.footer__nav a { display: block; color: var(--on-slab-soft); text-decoration: none;
                 padding: .4rem 0; font-size: .95rem; }
.footer__nav a:hover { color: var(--on-slab); }

.footer__fine {
  display: flex; flex-wrap: wrap; align-items: center; gap: .25rem 1.5rem;
  margin: 0; padding-top: 1.5rem; border-top: 1px solid rgba(255,255,255,.14);
  color: var(--on-slab-soft); font-size: .88rem;
}
.footer__fine .wordmark { color: var(--on-slab); margin-right: 0; padding: 0; }
.footer__fine .wordmark svg { color: var(--on-slab); opacity: .8; }
.footer__fine span { margin-left: auto; }

/* ---------- pill variants ----------
   The primary control is the highest-contrast pill its slab allows: ink on terracotta,
   white on indigo, terracotta on ink and on the ground. */
.cta--ink   { background: var(--pill-neutral); color: var(--pill-neutral-ink);
              box-shadow: 0 2px 6px rgba(0,0,0,.18), 0 18px 36px -18px rgba(0,0,0,.5); }
/* Fixed surface, fixed pill: on terracotta, ink is the highest-contrast control either way. */
.slab--accent .cta--ink { background: #16130F; color: #fff; }
.cta--light { background: #fff; color: #16130F; box-shadow: 0 2px 6px rgba(0,0,0,.18),
                                                            0 18px 36px -18px rgba(0,0,0,.5); }
.cta--ghost {
  background: transparent; color: #fff; box-shadow: none;
  border: 1.5px solid rgba(255,255,255,.55); font-size: 1rem; padding: .78rem 1.4rem;
}
.cta--ghost:hover { border-color: #fff; filter: none; background: rgba(255,255,255,.1); }
.head-row .cta--small { box-shadow: none; }

/* ---------- reveal: the extra grid children the new sections add ---------- */
.js .reveal > :nth-child(7) { --d: 360ms; }
.js .reveal > :nth-child(8) { --d: 420ms; }

@media (prefers-reduced-motion: reduce) {
  /* The marquee stops and becomes a row the reader scrolls themselves. Without the
     scroller it would simply be a clipped list with five items unreachable. */
  .ticker { overflow-x: auto; }
  .ticker__track { animation: none; width: auto; }
  .ticker__run + .ticker__run { display: none; }
}


/* =====================================================================================
   PAINTS — the colour pass on top of the slabs
   =====================================================================================
   The slabs gave the page four coloured blocks and left long grey runs between them:
   three measured jobs, six tool cards, six screenshots and the whole bottom third were
   all ground-on-ground. This section spends the paints defined at the top of the file
   on exactly those runs, and nowhere else.

   Two rules hold it together. A paint is a field or a tint, never a meaning — it never
   fills a control and never carries a figure. And anything sitting on a *fixed* surface
   (a slab) hardcodes its colour rather than reading a token, because a slab is a printed
   surface and does not flip with the page.
   ===================================================================================== */

/* Green as a filled badge rather than as text, which is the one thing --done can't do:
   white on it clears 5.0:1 in light, and in dark the fill lightens and takes dark ink. */
:root      { --done-fill: #2F7D4F; --done-ink: #FFFFFF; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { --done-fill: #5CC98A; --done-ink: #10231A; }
}
:root[data-theme="dark"] { --done-fill: #5CC98A; --done-ink: #10231A; }

/* ---------- the butter slab ----------
   The privacy promise was the page's one centred paragraph on bare ground, sitting
   between the ink safety slab and the pricing grid — the flattest screen on the site,
   and the one carrying the sentence the app is built around. It is a slab now.
   Butter takes ink rather than white: #16130F on #F2C85C is 11.2:1, white is 1.7:1. */
.slab--butter { background: var(--slab-butter); color: #16130F; border-color: transparent; }
.slab--butter .eyebrow, .slab--butter h2, .slab--butter h3, .slab--butter .pull { color: #16130F; }
.slab--butter p, .slab--butter .soft, .slab--butter .fine { color: #3A2E12; }   /* 8.4:1 */
.slab--butter .ding { color: #16130F; }
.slab--butter a:not(.cta) { color: #16130F; font-weight: 650; }

.privacy-slab {
  text-align: center;
  padding: clamp(2.5rem, 6vw, 4.5rem) clamp(1.5rem, 4vw, 3rem);
}
/* Absolute children excluded on purpose: a max-width on the burst resizes it, and the
   auto margins put it somewhere nobody chose. */
/* 34rem, not 40: the wider measure ran the prose into the burst's rays. */
.privacy-slab > :not(.slab__burst) { max-width: 34rem; margin-left: auto; margin-right: auto; }
.privacy-slab > :last-child { margin-bottom: 0; }
/* The same radial burst the footer draws, in the ink of the slab it sits on, and in the
   same place: a corner it runs off, not a halo behind the words. Drawn by the page
   script, which fills every [data-burst] it finds. */
.slab__burst {
  position: absolute; z-index: -1; pointer-events: none;
  right: -5rem; bottom: -6rem; width: 18rem; height: 18rem;
  color: #16130F; opacity: .14;
}

/* The caption is a two-row grid, not a wrapping flex row: "A holiday video" is short
   enough to keep its figures beside it while the other two wrapped, so the row rendered
   three cards in two different layouts. */
.result figcaption { display: grid; justify-content: start; gap: .15rem; }

/* ---------- three measured jobs, on three tints ----------
   The photographs were floating on the ground with a hairline under each. Sitting them
   on tinted mats gives the row the shape the rest of the page has, and the saving comes
   off the caption and onto the picture, where it is the first thing read. */
.results { gap: 1rem; }
.result {
  position: relative; --tint: var(--tint-teal);
  background: var(--tint); border-radius: var(--radius);
  padding: .7rem .7rem 1.15rem;
  transition: transform .28s cubic-bezier(.22,.61,.36,1), box-shadow .28s ease;
}
.result:nth-child(2) { --tint: var(--tint-indigo); }
.result:nth-child(3) { --tint: var(--tint-butter); }
.result:hover { transform: translateY(-5px); box-shadow: var(--shadow-lift); }
.result img { border-radius: 17px; }
.result figcaption {
  margin-top: .85rem; padding: .8rem .5rem 0 .5rem;
  border-top-color: color-mix(in srgb, var(--ink) 16%, transparent);
}
/* inkSoft is 4.24–4.39:1 on the tints; inkOnSunken is the value that clears them. */
.result .was { color: var(--ink-on-sunken); }
.save-badge {
  position: absolute; top: 1.25rem; left: 1.25rem;
  background: var(--done-fill); color: var(--done-ink);
  font-size: .78rem; font-weight: 700; letter-spacing: .01em;
  padding: .26rem .6rem; border-radius: 999px;
  box-shadow: 0 2px 8px rgba(22,19,15,.28);
}

/* ---------- the six tools, one paint each ----------
   Set by position rather than by a class per card, so the markup stays six identical
   blocks. The order is the order of the grid; moving a card moves its paint with it,
   which is the right answer for five of the six. The sixth is deliberate: Find
   duplicates is indigo because the block about duplicates is the indigo slab. */
.feature { --paint: var(--accent-ink); --tint: var(--tint-accent); }
.feature:nth-child(2) { --paint: var(--paint-sky);    --tint: var(--tint-sky); }
.feature:nth-child(3) { --paint: var(--paint-teal);   --tint: var(--tint-teal); }
.feature:nth-child(4) { --paint: var(--paint-indigo); --tint: var(--tint-indigo); }
.feature:nth-child(5) { --paint: var(--paint-butter); --tint: var(--tint-butter); }
.feature:nth-child(6) { --paint: var(--paint-plum);   --tint: var(--tint-plum); }
.icon-chip { background: var(--tint); color: var(--paint); }
.feature__num { color: var(--paint); opacity: .8; }
.feature { transition: transform .28s cubic-bezier(.22,.61,.36,1), box-shadow .28s ease; }
.feature:hover { transform: translateY(-3px); box-shadow: var(--shadow-lift); }

/* ---------- the screenshot rail, on the same six ----------
   Same cycle as the tools grid, in the same order, so the two rows read as one set
   rather than as two decorated ones. The columns widen to pay for the mat's padding —
   without it the phones shrink by the width of the frame they gained. */
.rail { grid-auto-columns: 15.5rem; }
@media (min-width: 46rem) { .rail { grid-auto-columns: 17.5rem; } }
.rail > figure {
  --tint: var(--tint-accent);
  background: var(--tint); border-radius: var(--radius);
  padding: 1.15rem 1.15rem 1.35rem;
  transition: transform .28s cubic-bezier(.22,.61,.36,1);
}
.rail > figure:nth-child(2) { --tint: var(--tint-sky); }
.rail > figure:nth-child(3) { --tint: var(--tint-teal); }
.rail > figure:nth-child(4) { --tint: var(--tint-indigo); }
.rail > figure:nth-child(5) { --tint: var(--tint-butter); }
.rail > figure:nth-child(6) { --tint: var(--tint-plum); }
.rail > figure:hover { transform: translateY(-4px); }
.rail figcaption { margin-top: .95rem; }

/* ---------- the ticker, lit ----------
   Hardcoded rather than tokenised: the ticker is the ink slab, a fixed surface in both
   appearances, so its paints are the light values either way. Every one of them clears
   7:1 on #23201D. */
.ticker__run li { --lit: #F3C969; }
.ticker__run li:nth-child(2) { --lit: #A9A6FF; }
.ticker__run li:nth-child(3) { --lit: #5FD3C4; }
.ticker__run li:nth-child(4) { --lit: #F09CC4; }
.ticker__run li:nth-child(5) { --lit: #8FBCF0; }
.ticker__run li:nth-child(6) { --lit: #E0673C; }
/* The numbers stay white. A paint is never a figure, and the teal that landed on
   "47 MB" read as green — which on this site means bytes that have already gone. The
   colour lives on the rule between items and on the ring round each photo instead. */
.ticker__run li::after { background: var(--lit); }
.ticker__run img { box-shadow: 0 0 0 2px var(--lit); }

/* ---------- the marked phrase in the statement ----------
   The one place on the page where terracotta is used as an ink on the ground. It marks
   the half of the sentence the whole app turns on, the way the reference marks a
   hashtag, and it takes the same swash the hero puts under "send". */
.mark {
  font-style: normal; color: inherit;
  background: linear-gradient(transparent 58%, var(--mark-fill) 58%, var(--mark-fill) 94%,
                              transparent 94%);
}

/* ---------- hero claim chips ---------- */
.hero__claims li { display: inline-flex; align-items: center; gap: .45rem; }
.hero__claims li::before {
  content: ""; width: .45rem; height: .45rem; border-radius: 50%; flex: none;
  /* Fixed values: the chips sit on the terracotta slab, which does not flip. */
  background: #0E6E64;
}
.hero__claims li:nth-child(2)::before { background: #3B3A9E; }
.hero__claims li:nth-child(3)::before { background: #9C2F63; }

/* ---------- the arrow onto the keeper ----------
   The indigo slab already says the app picks a frame and the reader can overrule it. The
   arrow is the part that gets read first. Gone below the width where the slab stacks and
   the copy is no longer beside the frames it points into. */
.burst { position: relative; }
.burst__arrow { display: none; }
@media (min-width: 58rem) {
  .burst__arrow {
    display: block; position: absolute; z-index: 3;
    left: 50%; top: -2.4rem; width: 4.5rem; height: 3.5rem;
    transform: translateX(-7.7rem) rotate(-6deg);
    color: #F3C969; pointer-events: none;
  }
}

/* ---------- pricing: the free plan is generous, so it gets a colour ----------
   Stretched rather than top-aligned: the paid card carries a control now, and two cards
   of different heights on a page built out of blocks read as one card that failed. */
.plans { align-items: stretch; }
.plan--sunken { background: var(--tint-teal); }
.plan--sunken .pill--neutral { background: var(--surface); color: var(--ink); }

/* ---------- the footer burst takes the accent ---------- */
/* Terracotta rather than white, and dropped far enough that only the tips of the rays
   clear the bottom edge — at any smaller offset the fan runs straight through
   "Everything runs on your device." and the rule above it. */
.footer__burst { color: var(--accent); opacity: .3; right: -8rem; bottom: -19.5rem; }

@media (prefers-reduced-motion: reduce) {
  .result:hover, .feature:hover, .rail > figure:hover { transform: none; }
}
