/*
 * Tick — the home page.
 *
 * The home page is the one page on the site that shows the product rather than documenting
 * it, so it has its own stylesheet instead of growing style.css. The legal and support pages
 * (four of them generated by scripts/generate-web.mjs) keep their plain reading layout, and
 * nothing written here can leak into them.
 *
 * Every colour is a token from the app's design system (design_handoff_tick/README.md): zinc
 * for the neutral foundation, teal-700 as the brand, teal-300 as the accent on dark. The page
 * is dark-only on purpose. It uses the app's own dark scheme, and every screenshot on it is
 * dark, so a light page would put a bright border around each one.
 */

/* ---------- fonts ---------- */

/* Self-hosted, because the CSP allows fonts from this origin only. style.css declares the
   same four faces for the document pages; the files are shared, so a visitor who opens both
   downloads them once. Only 700 is preloaded (the headline). The rest swap in when ready. */
@font-face { font-family: Inter; font-style: normal; font-weight: 400; font-display: swap; src: url(/fonts/inter-400.woff2) format("woff2"); }
@font-face { font-family: Inter; font-style: normal; font-weight: 500; font-display: swap; src: url(/fonts/inter-500.woff2) format("woff2"); }
@font-face { font-family: Inter; font-style: normal; font-weight: 600; font-display: swap; src: url(/fonts/inter-600.woff2) format("woff2"); }
@font-face { font-family: Inter; font-style: normal; font-weight: 700; font-display: swap; src: url(/fonts/inter-700.woff2) format("woff2"); }

/* Arial resized to Inter's box, so text keeps its line breaks and height when Inter swaps
   in. Without this, `swap` reflows every paragraph a moment after first paint. Measured from
   the subset files (hhea ascent 1984, descent 494, UPM 2048) against Arial's advance widths
   over a sample of this page's copy. Where Arial is not installed (most Android phones) the
   local() source fails, and the stack falls through to the system font as before. */
@font-face { font-family: "Inter Fallback"; font-weight: 400; src: local("Arial"), local("ArialMT"); size-adjust: 107.19%; ascent-override: 90.38%; descent-override: 22.50%; line-gap-override: 0%; }
@font-face { font-family: "Inter Fallback"; font-weight: 700; src: local("Arial Bold"), local("Arial-BoldMT"); size-adjust: 102.92%; ascent-override: 94.12%; descent-override: 23.44%; line-gap-override: 0%; }

/* ---------- tokens ---------- */

:root {
  color-scheme: dark;

  --zinc-950: #09090B;
  --zinc-900: #18181B;
  --zinc-800: #27272A;
  --zinc-700: #3F3F46;
  --zinc-500: #71717A;
  --zinc-400: #A1A1AA;
  --zinc-300: #D4D4D8;
  --zinc-50: #FAFAFA;
  --teal-800: #115E59;
  --teal-700: #0F766E;
  --teal-300: #5EEAD4;
  --white: #FFFFFF;           /* label on the teal-700 button, as in the app */
  --bezel: #0D0D10;           /* the Open Graph card's bezel, a shade under zinc-950; device frame only */

  --bg: var(--zinc-950);
  --card: var(--zinc-900);
  --line: var(--zinc-900);     /* section dividers: quieter than a card border */
  --border: var(--zinc-800);   /* card and control borders, as in the app */
  --text: var(--zinc-50);
  --text-2: var(--zinc-400);   /* 7.6:1 on --bg, 6.9:1 on --card: body copy and metadata */
  --accent: var(--teal-300);
  --brand: var(--teal-700);    /* white on it is 5.4:1 */

  /* zinc-500 is left out of the text roles on purpose: 4.1:1 on this background is below
     WCAG AA for body-size text. It appears only on icons that sit next to their own label. */

  --radius: 14px;
  --radius-sm: 12px;
  --ease: cubic-bezier(.2, .6, .2, 1);
  --gutter: clamp(1rem, 4vw, 3rem);
  --max: 76rem;
}

/* ---------- base ---------- */

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

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  /* The header is sticky, so an anchor jump would otherwise land its heading underneath it. */
  scroll-padding-top: 5rem;
}

@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: Inter, "Inter Fallback", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  font-size: 1.0625rem;
  line-height: 1.6;
  letter-spacing: -0.011em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

::selection { background: rgba(94, 234, 212, .3); color: var(--zinc-50); }

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

a { color: var(--accent); text-underline-offset: .18em; text-decoration-thickness: 1px; }
a:hover { color: var(--zinc-50); }

:where(a, button, summary):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

h1, h2, h3 { margin: 0; color: var(--text); font-weight: 700; }
p { margin: 0; }

/* Tabular figures, the design system's rule for every amount, rate, count and date. They go
   on the numbers themselves, not the whole page, because Inter's tnum feature also swaps the
   hyphen, comma, full stop and colon for figure-width forms. Set on running text, that
   opens gaps like "five - second" and "14 - day". */
.num,
.steps__num,
.taxcard__big,
.taxlegend b,
.taxcard__foot strong { font-variant-numeric: tabular-nums; }

.container {
  width: 100%;
  max-width: calc(var(--max) + 2 * var(--gutter));
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.visually-hidden {
  position: absolute !important;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

.skip {
  position: absolute;
  left: 12px;
  top: 12px;
  z-index: 100;
  padding: 10px 16px;
  border-radius: var(--radius-sm);
  background: var(--zinc-50);
  color: var(--zinc-950);
  font-weight: 600;
  text-decoration: none;
  transform: translateY(-200%);
}

.skip:focus { transform: none; }

/* ---------- shared pieces ---------- */

.eyebrow {
  display: flex;
  align-items: center;
  gap: .5rem;
  margin: 0 0 1.1rem;
  font-size: .8125rem;
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--accent);
}

/* The brand's own tick as the eyebrow's marker: one stroke, the same path as the icon. 17px
   is the handoff's minimum for the mark on its own, so it goes no smaller. */
.eyebrow svg { width: 17px; height: 17px; flex: none; }

/* Keeps the hero's "Expense tracker for iPhone and Android" on one line on a 360px phone. */
@media (max-width: 400px) {
  .eyebrow { font-size: .75rem; letter-spacing: .06em; }
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  min-height: 48px;
  padding: .5rem 1.25rem;
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: var(--brand);
  color: var(--white);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  text-decoration: none;
  transition: background-color .15s, border-color .15s;
}

.btn:hover { background: var(--teal-800); color: var(--white); }

/* 44px: as close to the handoff's 48px touch target as a 60px header bar allows while
   keeping air above and below the button. */
.btn--small {
  min-height: 44px;
  padding: .35rem .95rem;
  border-radius: var(--radius-sm);
  font-size: .875rem;
}

.btn svg { width: 18px; height: 18px; flex: none; }

/* Official store artwork, untouched. Apple asks for at least 40px on screen and clear space
   of a quarter of the badge height; Google asks for its badge to be no smaller than any badge
   beside it. Both are the same height here, and the 12px gap covers the clear space. The
   badge itself never changes on hover (Apple: do not modify or animate it); only the ring
   around the link does. */
.badges {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  margin: 0;
  padding: 0;
}

.badges a {
  display: block;
  border-radius: 9px;
  transition: box-shadow .15s;
}

.badges a:hover { box-shadow: 0 0 0 3px var(--zinc-700); }

.badges img { height: 44px; width: auto; }

/* ---------- phone frame ---------- */

/* A device-neutral frame: a 1px top-lit rim, a dark bezel and a rounded screen, with no
   notch or buttons. It copies the parent site's PhoneFrame and the Open Graph card, so the
   page, the share preview and arkon-tech.cc all show the same device. Keeping it
   device-neutral is what makes tilting and shadowing it acceptable under Apple's marketing
   rules.

   The proportions are in container units, so the corners and bezel scale with the phone.
   A 110px phone in the mobile fan and a 290px one in a showcase keep the same shape, which
   fixed rem radii cannot do. The rem values before each cqi value are the fallback for
   browsers without container queries. */
.phone { container-type: inline-size; }

/* The white rim and the black drop shadow are the device's own light, not UI colour, so they
   sit outside the token set on purpose. White alphas and drop shadows appear on device
   artwork only: this frame, and the app icon in the closing section. The design system's
   no-shadow rule is about cards and lists, which keep their hairlines. */
.phone__frame {
  padding: 1px;
  border-radius: 2.4rem;
  border-radius: 14.8cqi;
  background: linear-gradient(to bottom, rgba(255, 255, 255, .25), rgba(255, 255, 255, .1) 50%, rgba(255, 255, 255, .05));
  box-shadow: 0 40px 80px -24px rgba(0, 0, 0, .75);
}

.phone__bezel {
  padding: .45rem;
  padding: 2.8cqi;
  border-radius: calc(2.4rem - 1px);
  border-radius: calc(14.8cqi - 1px);
  background: var(--bezel);
}

.phone__screen {
  overflow: hidden;
  border-radius: 1.95rem;
  border-radius: calc(12cqi - 1px);
  background: var(--zinc-950);
}

.phone__screen img { width: 100%; height: auto; }

/* The slow float the parent site uses: 8s, 12px, and out of phase between phones so the
   group drifts rather than bobbing in step. It lives on its own wrapper so it never
   competes with the tilt on the slot around it.

   It starts by itself and never ends, so WCAG 2.2.2 wants a way to pause it: the .motion
   button in the hero. That button needs script, so the float is opt-in on the same `js`
   class as the reveals. Without JavaScript the phones simply stand still, and there is
   nothing that would need pausing. */
@keyframes float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-12px); }
}

@media (prefers-reduced-motion: no-preference) {
  .js .float { animation: float 8s ease-in-out infinite; }
  .js .float--late { animation-delay: -2.6s; }
  .js .float--later { animation-delay: -5.2s; }
  .is-paused .float { animation-play-state: paused; }
}

/* Pause / play for the float. Quiet on purpose: a hairline circle in the corner of the fan,
   in the page's secondary text colour, brightening on hover like the header links. It shows
   only where the float can run. */
.motion {
  display: none;
  position: absolute;
  right: 0;
  bottom: 0;
  z-index: 2;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 50%;
  background: var(--bg);
  color: var(--text-2);
  cursor: pointer;
  transition: color .15s, border-color .15s;
}

.motion:hover { color: var(--text); border-color: var(--zinc-700); }

.motion svg { width: 18px; height: 18px; }

.motion[aria-pressed="true"] .motion__pause,
.motion[aria-pressed="false"] .motion__play { display: none; }

@media (prefers-reduced-motion: no-preference) {
  .js .motion { display: grid; }
}

/* A soft teal light behind a device. Devices only (the fan, a lone phone, the pair): the
   brief allows ambient light behind hardware, never behind a UI card. Built from radial
   gradients rather than a blurred element: no filter to repaint, and `closest-side` fades it
   to nothing at its own edges, so it never ends in a hard line where a section clips it. */
.glow {
  position: relative;
  isolation: isolate;
}

.glow::before {
  content: "";
  position: absolute;
  inset: -8% -6%;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(closest-side at 64% 36%, rgba(94, 234, 212, .13), rgba(94, 234, 212, .05) 55%, rgba(94, 234, 212, 0)),
    radial-gradient(closest-side, rgba(15, 118, 110, .5), rgba(15, 118, 110, .3) 38%, rgba(15, 118, 110, .12) 68%, rgba(15, 118, 110, 0));
}

/* ---------- header ---------- */

.top {
  position: sticky;
  top: 0;
  z-index: 50;
  border-bottom: 1px solid var(--line);
  background: rgba(9, 9, 11, .78);
  -webkit-backdrop-filter: saturate(140%) blur(14px);
  backdrop-filter: saturate(140%) blur(14px);
}

.top__inner {
  display: flex;
  align-items: center;
  gap: 1rem;
  min-height: 60px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 11px; /* 0.38 x the 28px mark, the handoff's lockup rule */
  color: var(--text);
  font-size: 1.25rem;
  font-weight: 700;
  letter-spacing: -0.03em;
  text-decoration: none;
}

.brand:hover { color: var(--text); }

.brand svg { width: 28px; height: 28px; flex: none; }

.top__nav {
  display: none;
  gap: .25rem;
  margin-left: auto;
}

.top__nav a {
  padding: .45rem .75rem;
  border-radius: var(--radius-sm); /* 12, the handoff's radius for small pills */
  color: var(--text-2);
  font-size: .9375rem;
  font-weight: 500;
  text-decoration: none;
}

.top__nav a:hover { background: var(--zinc-900); color: var(--text); }

.top .btn { margin-left: auto; }

@media (min-width: 820px) {
  .top__inner { min-height: 64px; }
  .top__nav { display: flex; }
  .top .btn { margin-left: .75rem; }
}

/* ---------- hero ---------- */

.hero {
  position: relative;
  overflow: hidden;
  overflow: clip;
  padding-block: clamp(2.75rem, 7vw, 6rem) clamp(3rem, 7vw, 5.5rem);
}

/* A faint wash of teal-800 from the top edge, so the hero reads as lit rather than flat. */
.hero::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 38rem;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(56% 60% at 50% 0%, rgba(17, 94, 89, .22), rgba(17, 94, 89, .08) 55%, rgba(17, 94, 89, 0));
}

.hero__grid {
  display: grid;
  gap: 2.5rem;
  align-items: center;
}

.hero__copy { container-type: inline-size; }

.hero h1 {
  font-size: clamp(2.75rem, 1.2rem + 5vw, 4.5rem);
  /* Sized against its own column, not the viewport. "Five seconds," is 6.27em wide in Inter
     Bold at this tracking, so 14.6cqi keeps it on one line in any column width, from a
     328px phone to the half-width desktop column, and the headline always breaks where the
     <br> is and nowhere else. */
  font-size: clamp(2.5rem, 14.6cqi, 5.25rem);
  line-height: 1.02;
  letter-spacing: -0.04em;
}

.hero h1 .accent { color: var(--accent); }

.hero__lede {
  max-width: 33rem;
  margin-top: 1.5rem;
  color: var(--text-2);
  font-size: clamp(1.125rem, 1.02rem + .35vw, 1.3125rem);
  line-height: 1.55;
  text-wrap: pretty;
}

.hero .badges { margin-top: 2.25rem; }

.hero__note {
  margin-top: 1.1rem;
  color: var(--text-2);
  font-size: .9375rem;
}

/* The fan: three phones, the centre one in front. The geometry is ProductShowcase's on
   arkon-tech.cc: sides at 36% of the fan and pulled 9% under the centre, dropped 2rem, scaled
   to .95 and tilted 6 degrees outwards. */
.fan {
  display: flex;
  align-items: center;
  justify-content: center;
  width: min(100%, 37rem);
  margin-inline: auto;
  padding-block: .5rem 2.5rem;
}

/* The hero's light is larger and brighter than the showcases' below it: it is the one place
   the page is meant to glow. It reaches past the fan sideways only; `closest-side` keeps it
   a circle no wider than the box, so on a phone it never climbs up behind the store badges,
   which need a plain background (Google's badge rule). */
.hero__visual.glow::before {
  inset: -20% -24%;
  background:
    radial-gradient(closest-side at 68% 32%, rgba(94, 234, 212, .24), rgba(94, 234, 212, .09) 50%, rgba(94, 234, 212, 0)),
    radial-gradient(closest-side at 50% 48%, rgba(15, 118, 110, .78), rgba(15, 118, 110, .52) 30%, rgba(15, 118, 110, .22) 60%, rgba(15, 118, 110, .06) 82%, rgba(15, 118, 110, 0));
}

.fan__slot { position: relative; flex: none; }

.fan__slot--centre { z-index: 1; width: 42%; }

.fan__slot--side { z-index: 0; width: 36%; }

.fan__slot--left { margin-right: -9%; transform: translateY(2rem) scale(.95) rotate(-6deg); }

.fan__slot--right { margin-left: -9%; transform: translateY(2rem) scale(.95) rotate(6deg); }

@media (min-width: 1024px) {
  .hero__grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.04fr);
    gap: 3.5rem;
  }

  .fan { padding-block: 1.5rem 3rem; }
}

/* ---------- facts strip ---------- */

.facts { border-block: 1px solid var(--line); }

/* Hairlines between the cells come from the list's background showing through a 1px gap,
   so the lines stay right whether the strip is two, three or six columns wide. */
.facts__list {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px;
  margin: 0;
  padding: 0;
  background: var(--line);
}

.facts__list li {
  display: flex;
  align-items: center;
  gap: .75rem;
  padding: 1.15rem .9rem;
  background: var(--bg);
  font-size: .9375rem;
  font-weight: 500;
  line-height: 1.35;
}

.facts__list svg {
  width: 22px;
  height: 22px;
  flex: none;
  color: var(--accent);
}

/* Balanced, so a fact that needs two lines splits into two even halves ("76 categories /
   in 11 groups") instead of leaving one word on a line of its own. */
.facts__text { text-wrap: balance; }

/* A 360px phone leaves each cell about 100px of text width, 2px short of "with ECB rates",
   which pushed that fact to three lines. A little less padding and gap buys the room. */
@media (max-width: 400px) {
  .facts__list li { gap: .6rem; padding-inline: .75rem; }
}

@media (min-width: 720px) {
  .facts__list { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .facts__list li { padding: 1.4rem 1.25rem; }
}

@media (min-width: 1180px) {
  .facts__list { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .facts__list li { flex-direction: column; align-items: flex-start; gap: .7rem; padding: 1.6rem 1.35rem; }
}

/* ---------- sections ---------- */

.section {
  position: relative;
  overflow: hidden;
  overflow: clip;
  padding-block: clamp(4rem, 7vw, 6.5rem);
}

.section + .section { border-top: 1px solid var(--line); }

/* A full-width change of ground, teal-800 at a tenth over the page: enough to mark a
   section off from its neighbours without turning into a coloured surface. The lighter
   hairlines above and below replace the usual divider. Browsers without color-mix() keep
   the plain page background. */
.section--band {
  background: var(--bg);
  background: color-mix(in srgb, var(--teal-800) 10%, var(--bg));
  border-block: 1px solid var(--border);
}

.section + .section--band { border-top-color: var(--border); }

.section--band + .section { border-top: 0; }

/* Sized so the longest two-line heading in a half-width column ("Categories, templates and
   shortcuts") still breaks into two lines, not three, at 960 and 1024px. */
.section h2 {
  font-size: clamp(2rem, 1.25rem + 2.1vw, 3.1rem);
  line-height: 1.08;
  letter-spacing: -0.032em;
  text-wrap: balance;
}

.section-head { max-width: 44rem; }

/* Centred from 720px only. On a phone, centred paragraphs are harder to read than the
   left-aligned ones in every other section, so there it keeps the common alignment. */
@media (min-width: 720px) {
  .section-head--centre { margin-inline: auto; text-align: center; }

  .section-head--centre .eyebrow { justify-content: center; }
}

.intro {
  margin-top: 1.25rem;
  color: var(--text-2);
  font-size: 1.125rem;
  line-height: 1.6;
  text-wrap: pretty;
}

/* Text beside a visual. Copy comes first in the source everywhere, so on a phone every
   section reads heading, then text, then picture. From 960px the picture takes the left
   column on alternate sections, which is only a change of order in the grid. */
.split {
  display: grid;
  gap: 3.25rem;
  align-items: center;
}

/* The eyebrow is a <p> as well, and `.copy p` (0,1,1) outranks `.eyebrow` (0,1,0), which
   turned every showcase eyebrow grey and pushed it down. :where() keeps this rule's weight
   exactly where it was while leaving the eyebrow to its own rule. */
.copy p:where(:not(.eyebrow)) {
  max-width: 34rem;
  margin-top: 1.15rem;
  color: var(--text-2);
  text-wrap: pretty;
}

.copy .intro { margin-top: 1.25rem; }

/* Tablet, one column: the copy keeps its reading measure and moves onto the centre line
   the pictures below it already use, instead of leaving the right third of each text block
   empty while step rules and chips run the full width. */
@media (min-width: 720px) and (max-width: 959px) {
  .split > .copy,
  .not__grid > * {
    width: 100%;
    max-width: 34rem;
    margin-inline: auto;
  }
}

@media (min-width: 960px) {
  .split {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: clamp(3rem, 6vw, 6rem);
  }

  .split--flip .split__visual { order: -1; }
}

.caption {
  max-width: 30rem;
  margin: 1.5rem auto 0;
  color: var(--text-2);
  font-size: .875rem;
  line-height: 1.55;
  text-align: center;
  text-wrap: pretty;
}

/* ---------- single and paired phones ---------- */

.stage {
  display: flex;
  justify-content: center;
  padding-block: 1rem 2rem;
}

.phone--solo { width: min(72%, 18.5rem); }

/* Two screens that belong together, side by side and staggered. They do not overlap: both
   carry their point in the right-hand column (the dinar amount and its dollar equivalent,
   the Manual rate), and any overlap would cover one of them. */
.pair {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(.75rem, 3vw, 1.5rem);
  align-items: start;
  width: min(100%, 32rem);
  margin-inline: auto;
  padding-block: .5rem 2rem;
}

.pair__lower { margin-top: 18%; }

/* ---------- how it works ---------- */

.steps {
  list-style: none;
  counter-reset: step;
  margin: 2.25rem 0 0;
  padding: 0;
}

.steps li {
  position: relative;
  display: grid;
  grid-template-columns: 3.25rem minmax(0, 1fr);
  column-gap: 1.1rem;
  padding-block: 1.35rem;
  border-top: 1px solid var(--line);
}

.steps li:last-child { border-bottom: 1px solid var(--line); }

.steps__num {
  color: var(--accent);
  font-size: 1.75rem;
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.03em;
}

.steps h3 {
  font-size: 1.1875rem;
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -0.015em;
}

.steps p {
  margin-top: .4rem;
  color: var(--text-2);
  font-size: 1rem;
  line-height: 1.6;
}

/* ---------- chips: currency codes and CSV columns ---------- */

/* A size container, so the currency grid below can count columns from the width it actually
   has rather than from the viewport: from 960px it sits in half a split, which is narrower
   than the full-width column it gets on a tablet. */
.chipset { margin: 2rem 0 0; max-width: 34rem; container-type: inline-size; }

.chipset figcaption {
  margin-bottom: .85rem;
  color: var(--text-2);
  font-size: .875rem;
  font-weight: 500;
}

.chipset figcaption strong { color: var(--text); font-weight: 600; }

.chips {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0;
  padding: 0;
}

.chips li {
  padding: .3rem .6rem;
  border: 1px solid var(--border);
  border-radius: 9px;
  background: var(--card);
  color: var(--zinc-300);
  font-size: .8125rem;
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: 0;
}

/* The thirty codes line up as a table in whole rows: six across, or ten across once the list
   is at least 31.5rem wide. Below that, ten chips leave the widest code (MXN, about 33px)
   under 6px of room on each side, which read as touching the border at 960-1100px. */
.chips--codes {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
}

.chips--codes li {
  padding-inline: 0;
  font-weight: 600;
  letter-spacing: .04em;
  text-align: center;
}

@container (min-width: 31.5rem) {
  .chips--codes { grid-template-columns: repeat(10, minmax(0, 1fr)); }
}

/* ---------- cards ---------- */

.card {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--card);
}

/* Offline: what happens to one expense, as three states on a line. A column with a vertical
   rail on a phone; from 720px a row, with the rail running through the three icons. */
.flowcard {
  width: min(100%, 30rem);
  margin: 2.5rem auto 0;
  padding: 1.75rem 1.75rem 1.5rem;
}

.flowcard__label {
  margin-bottom: 1rem;
  color: var(--text-2);
  font-size: .75rem;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
}

.flowcard ol {
  position: relative;
  list-style: none;
  margin: 0;
  padding: 0;
}

/* The dashed rail joins the three icons: the record travels down it, whenever it can. */
.flowcard ol::before {
  content: "";
  position: absolute;
  left: 23.25px;
  top: 40px;
  bottom: 40px;
  border-left: 1.5px dashed var(--zinc-700);
}

.flowcard li {
  position: relative;
  display: grid;
  grid-template-columns: 48px minmax(0, 1fr);
  column-gap: 1.1rem;
  align-items: center;
  padding-block: .95rem;
}

.flowcard__icon {
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border: 1px solid var(--border);
  border-radius: 50%;
  background: var(--zinc-950);
  color: var(--accent);
}

.flowcard__icon svg { width: 22px; height: 22px; }

/* The middle state is the one without a connection, so its ring is broken too. */
.flowcard li:nth-child(2) .flowcard__icon { color: var(--zinc-400); border-style: dashed; border-color: var(--zinc-700); }

.flowcard__title {
  font-size: 1.0625rem;
  font-weight: 600;
  letter-spacing: -0.012em;
}

.flowcard__text {
  margin-top: .15rem;
  color: var(--text-2);
  font-size: .9375rem;
  line-height: 1.5;
}

@media (min-width: 720px) {
  .flowcard {
    width: min(100%, 58rem);
    margin-top: 3rem;
    padding: 2rem 2rem 2.25rem;
  }

  .flowcard__label { margin-bottom: 1.75rem; text-align: center; }

  .flowcard ol {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    column-gap: 2rem;
  }

  /* From the centre of the first column to the centre of the last: a third of the row minus
     the two gaps, halved, on each side. */
  .flowcard ol::before {
    left: calc((100% - 4rem) / 6);
    right: calc((100% - 4rem) / 6);
    top: 24px;
    bottom: auto;
    border-left: 0;
    border-top: 1.5px dashed var(--zinc-700);
  }

  /* align-content: start keeps every icon on the rail. The row's height comes from its
     longest text, and a shorter step would otherwise spread its spare height over its own
     rows and sink its icon below the other two. */
  .flowcard li {
    grid-template-columns: minmax(0, 1fr);
    align-content: start;
    justify-items: center;
    row-gap: 1.1rem;
    padding-block: 0;
    text-align: center;
  }
}

/* The closing paragraph under the offline card. */
.section-foot {
  max-width: 42rem;
  margin: 2.5rem auto 0;
  color: var(--text-2);
  text-wrap: pretty;
}

@media (min-width: 720px) {
  .section-foot { margin-top: 3rem; text-align: center; }
}

/* Categories: the real taxonomy as a stacked bar in the group colours, the way the app's
   Summary tab draws spending. Colour stays inside the chart and its legend dots, which is
   the design system's rule for category colour. */
.taxcard {
  width: min(100%, 30rem);
  margin-inline: auto;
  padding: 1.6rem 1.5rem 1.4rem;
  container-type: inline-size; /* the legend picks its column count from the card's width */
}

.taxcard__head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: .35rem .6rem;
}

.taxcard__big {
  font-size: 2.75rem;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.035em;
}

.taxcard__sub { color: var(--text-2); font-size: .9375rem; }

/* Each segment carries its own small radius instead of the bar clipping one 6px radius off
   both ends. The clipped version turned Other, a single category and so a 3-5px segment,
   into a grey half-dot that read as a rendering glitch. The 4px minimum keeps it a visible
   sliver at 360px without changing the proportions anywhere else. */
.taxbar {
  display: flex;
  gap: 2px;
  height: 12px;
  margin-top: 1.25rem;
}

.taxbar span {
  flex: var(--n) 1 0;
  min-width: 4px;
  border-radius: 3px;
  background: var(--c);
}

.taxlegend {
  list-style: none;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: .55rem 1.25rem;
  margin: 1.35rem 0 0;
  padding: 0;
}

/* Two columns only once "Personal & Education" fits on one line in each; narrower than
   that (phones, and the half-width column at 960px), one column of even rows. */
@container (min-width: 24rem) {
  .taxlegend { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.taxlegend li {
  display: grid;
  grid-template-columns: 10px minmax(0, 1fr) auto;
  align-items: center;
  gap: .6rem;
  color: var(--zinc-300);
  font-size: .875rem;
  line-height: 1.35;
}

.taxlegend li::before {
  content: "";
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--c);
}

.taxlegend b { color: var(--text-2); font-weight: 500; }

.taxcard__foot {
  margin-top: 1.25rem;
  padding-top: 1.1rem;
  border-top: 1px solid var(--border);
  color: var(--text-2);
  font-size: .875rem;
}

.taxcard__foot strong { color: var(--text); font-weight: 600; }

/* A list whose marker is the brand tick. */
.ticks {
  list-style: none;
  margin: 1.75rem 0 0;
  padding: 0;
  max-width: 34rem;
}

.ticks li {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr);
  column-gap: .85rem;
  padding-block: 1rem;
  border-top: 1px solid var(--line);
  color: var(--text-2);
}

.ticks li:last-child { border-bottom: 1px solid var(--line); }

.ticks svg { width: 18px; height: 18px; margin-top: .25rem; color: var(--accent); }

.ticks strong { color: var(--text); font-weight: 600; }

/* ---------- what Tick is not ---------- */

.not__grid {
  display: grid;
  gap: 3rem;
  align-items: center;
}

.not__quote {
  margin-top: 1.5rem;
  max-width: 30rem;
  color: var(--text);
  font-size: clamp(1.3rem, 1.1rem + .8vw, 1.65rem);
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

.nots {
  list-style: none;
  margin: 0;
  padding: .5rem 1.5rem;
}

.nots li {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr);
  column-gap: .9rem;
  align-items: center;
  padding-block: 1.1rem;
  font-size: 1.0625rem;
  font-weight: 500;
  line-height: 1.4;
}

.nots li + li { border-top: 1px solid var(--border); }

.nots svg { width: 20px; height: 20px; color: var(--zinc-500); }

@media (min-width: 960px) {
  .not__grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 6rem; }
}

/* ---------- pricing ---------- */

.plans {
  list-style: none;
  display: grid;
  gap: 1rem;
  margin: 3rem 0 0;
  padding: 0;
}

.plan {
  position: relative;
  padding: 1.6rem 1.5rem 1.7rem;
}

.plan__when {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  color: var(--text-2);
  font-size: .8125rem;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
}

.plan__when::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--zinc-700);
}

.plan h3 {
  margin-top: .9rem;
  font-size: 1.3125rem;
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.02em;
}

.plan p:last-child {
  margin-top: .55rem;
  color: var(--text-2);
  font-size: 1rem;
  line-height: 1.6;
}

/* The permanent one: what survives with or without a subscription. The page's one teal
   border, because it is the promise the others hang on. */
.plan--always { border-color: var(--teal-800); }

.plan--always .plan__when { color: var(--accent); }

.plan--always .plan__when::before { background: var(--accent); }

/* Tablet: the two steps side by side and the permanent promise across both, rather than
   three full-width cards that each hold one short sentence. */
@media (min-width: 720px) {
  .plans { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  .plan--always { grid-column: 1 / -1; }
}

@media (min-width: 900px) {
  .plans { grid-template-columns: repeat(3, minmax(0, 1fr)); }

  .plan--always { grid-column: auto; }
}

/* ---------- FAQ ---------- */

.faq {
  display: grid;
  gap: 0 3.5rem;
  margin-top: 3rem;
}

.faq__item {
  padding-block: 1.5rem;
  border-top: 1px solid var(--line);
}

.faq h3 {
  font-size: 1.125rem;
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: -0.015em;
}

.faq p {
  margin-top: .5rem;
  color: var(--text-2);
  font-size: 1rem;
  line-height: 1.6;
}

.faq__more a {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  font-weight: 600;
  text-decoration: none;
}

.faq__more a:hover { text-decoration: underline; }

.faq__more svg { width: 16px; height: 16px; }

@media (min-width: 820px) {
  .faq { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ---------- closing ---------- */

.get {
  position: relative;
  overflow: hidden;
  overflow: clip;
  padding-block: clamp(5rem, 10vw, 8.5rem);
  border-top: 1px solid var(--line);
  text-align: center;
}

.get::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 0;
  z-index: -1;
  width: min(62rem, 140vw);
  height: 100%;
  transform: translateX(-50%);
  pointer-events: none;
  background: radial-gradient(closest-side, rgba(15, 118, 110, .34), rgba(15, 118, 110, .14) 55%, rgba(15, 118, 110, 0));
}

.get__icon {
  width: 76px;
  height: 76px;
  margin: 0 auto 2rem;
  border-radius: 22.5%; /* the icon's own corner (rx 7.2 of 32), so the shadow follows it */
  /* Device artwork like the phone frame: a faint white rim and a teal-700 drop shadow. */
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .12), 0 24px 60px -18px rgba(15, 118, 110, .7);
}

.get h2 {
  font-size: clamp(2.1rem, 1.4rem + 2.8vw, 3.5rem);
  line-height: 1.05;
  letter-spacing: -0.035em;
  text-wrap: balance;
}

.get__text {
  max-width: 32rem;
  margin: 1.1rem auto 0;
  color: var(--text-2);
  font-size: 1.125rem;
  text-wrap: balance;
}

/* Each sentence wraps as a unit: a line break lands between the two sentences, and only a
   sentence too long for the line on its own breaks inside itself. */
.get__text > span { display: inline-block; }

/* Plain buttons, not store badges: Apple allows one App Store badge per layout, and the
   hero already carries it. These say where they go in words instead, and look the same, so
   neither store reads as the preferred one. */
/* The closing call to action carries the store badges again, a size up from the hero's 44px.
   Both stay the same height (Google's rule), and the 12px gap from .badges is exactly the
   quarter-height clear space Apple asks for at 48px. */
.get .badges {
  justify-content: center;
  margin-top: 2.25rem;
}

.get .badges img { height: 48px; }

/* ---------- footer ---------- */

.foot {
  padding-block: 2.75rem 3.25rem;
  border-top: 1px solid var(--line);
  color: var(--text-2);
  font-size: .9375rem;
}

.foot__inner {
  display: grid;
  gap: 1.5rem;
}

.foot .brand { gap: 9px; color: var(--text); font-size: 1.125rem; } /* 0.38 x the 24px mark */

.foot .brand svg { width: 24px; height: 24px; }

.foot__links {
  display: flex;
  flex-wrap: wrap;
  gap: .35rem 1.35rem;
}

.foot a { color: var(--text-2); text-decoration: none; }

.foot a:hover { color: var(--text); text-decoration: underline; }

/* These two sit inside a sentence, where colour alone does not mark a link (WCAG 1.4.1:
   zinc-300 against the zinc-400 around it is 1.7:1, and 3:1 is the floor). So they keep an
   underline at rest. The document links above are a navigation list and need none. */
.foot__meta a {
  color: var(--zinc-300);
  text-decoration-line: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: .18em;
}

@media (min-width: 820px) {
  .foot__inner {
    grid-template-columns: auto 1fr;
    align-items: center;
    column-gap: 3rem;
  }

  .foot__links { justify-content: flex-end; }

  .foot__meta { grid-column: 1 / -1; }
}

/* ---------- reveal on scroll ---------- */

/* Opt-in: the inline script in <head> adds `js` to <html> only when IntersectionObserver
   exists. Without it, nothing here applies and every section is simply visible. */
.js .reveal {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity .8s var(--ease), transform .8s var(--ease);
}

.js .reveal.is-visible {
  opacity: 1;
  transform: none;
}

.js .reveal.d1 { transition-delay: 90ms; }
.js .reveal.d2 { transition-delay: 180ms; }

@media (prefers-reduced-motion: reduce) {
  .js .reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* Printing, or saving as PDF, before scrolling would otherwise print every block that has
   not been revealed yet as blank space. The pause button has nothing to do on paper. */
@media print {
  .js .reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }

  .motion { display: none !important; }
}
