/*
 * Supplement to vendor/tapvixo-ui.css — NOT a second design system.
 *
 * Tailwind only emits the utilities its source actually uses, and the
 * reference design never used `sr-only`, so those classes are simply absent
 * from its compiled stylesheet. Without this the skip link renders as visible
 * text above the header.
 *
 * Most of what follows is accessibility the reference did not have, and it
 * changes no colour, size or spacing the reference set.
 */

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border-width: 0;
}

/* The skip link is the first tab stop on every page and has to become visible
   when it takes focus — that is the entire point of it. */
.focus\:not-sr-only:focus {
  position: static;
  width: auto;
  height: auto;
  padding: 0;
  margin: 0;
  overflow: visible;
  clip: auto;
  white-space: normal;
}

/*
 * The site's typeface: Noto Sans, self-hosted (audit 2026-10-06, Q6).
 *
 * The design asked for Inter from Google Fonts, but the apex CSP never allowed
 * fonts.googleapis.com, so no visitor ever saw it: every page fell back to the
 * system font and logged a CSP error. Noto Sans is the app's own font, it
 * covers Devanagari and Gujarati for later pages, and served from our origin
 * it needs no third-party connection.
 *
 * - Two files, both with the weight axis trimmed to 400–900, the weights the
 *   design uses (36 KB → 27.5 KB): the Latin subset @fontsource-variable/
 *   noto-sans 5.2.10 ships, and ONE glyph, the rupee sign (1.2 KB), cut from
 *   its latin-ext subset because the Latin one does not carry it. Rebuilt
 *   with fontTools: `subset.Subsetter` (unicodes U+20B9, rupee only), then
 *   `varLib.instancer.instantiateVariableFont(font, {'wght': (400, 900)})`.
 * - `font-display: swap` over a FALLBACK FACE whose metrics are adjusted to
 *   Noto Sans, so the swap moves nothing. Arial/Liberation Sans (desktop,
 *   iOS, Linux) and Roboto (Android) need different adjustments, so each has
 *   its own face; a face whose local() font is absent is skipped. Values:
 *   size-adjust = Noto's average glyph width ÷ the fallback's, and the
 *   overrides are Noto's ascent/descent (1069/293 per 1000) ÷ size-adjust —
 *   the method next/font and Capsize use. Metrics: Noto Sans from the woff2;
 *   Arial and Roboto from Capsize's published tables.
 * - Both are preloaded in the head partial. Found by layout instead, the
 *   rupee file cost a round trip after the stylesheets on every priced page
 *   (home mobile LCP 1.95 s → 1.8 s, lab, 2026-10-06), and 1.2 KB on a page
 *   with no price costs nothing measurable.
 *
 * `--font-inter` is the variable the reference's compiled `.font-inter`
 * utility reads, so every element that asked for the design's font gets this
 * one without touching a page. Unlayered, it beats the vendor sheet's
 * `@layer theme` definition.
 */
@font-face {
  font-family: 'Tapvixo Sans';
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url('/fonts/noto-sans-latin-wght-normal.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304,
    U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Tapvixo Sans';
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url('/fonts/noto-sans-rupee-wght-normal.woff2') format('woff2');
  unicode-range: U+20B9;
}

@font-face {
  font-family: 'Tapvixo Sans Fallback';
  src: local('Arial'), local('ArialMT'), local('Liberation Sans'), local('LiberationSans');
  size-adjust: 107.04%;
  ascent-override: 99.87%;
  descent-override: 27.37%;
  line-gap-override: 0%;
}

@font-face {
  font-family: 'Tapvixo Sans Fallback Android';
  src: local('Roboto'), local('Roboto-Regular');
  size-adjust: 106.23%;
  ascent-override: 100.63%;
  descent-override: 27.58%;
  line-gap-override: 0%;
}

:root {
  --font-inter: 'Tapvixo Sans', 'Tapvixo Sans Fallback', 'Tapvixo Sans Fallback Android', sans-serif;
}

/*
 * Decorative motion stops on its own (WCAG 2.2.2 Pause, Stop, Hide: anything
 * that moves by itself for more than five seconds beside other content needs
 * a pause control, and decoration does not earn one). The reference looped the
 * hero's float, its glow and the back-to-top bounce forever.
 *
 * On a phone the float and the glow do not run at all: the glow is a 60px blur
 * over a third of the first screen, and repainting it on a mid-range phone is
 * main-thread time the first tap is waiting for (audit 2026-10-06, B).
 */
.animate-float {
  animation-iteration-count: 1;
}

.animate-pulse {
  animation-iteration-count: 2;
}

#back-to-top .animate-bounce {
  animation-iteration-count: 3;
}

@media (max-width: 63.999rem) {
  .animate-float,
  .animate-pulse {
    animation: none;
  }
}

/* Motion in this design is decoration — a floating hero image, a pulsing glow,
   a marquee. Anyone who asks for less gets the page with none of it. The
   reference shipped no reduced-motion handling at all. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/*
 * FAQ open state.
 *
 * The reference drives its accordion from React state and restyles the whole
 * card when a question is open — blue border, blue question text, chevron
 * flipped. This uses <details>/<summary>, which gives the keyboard and screen
 * reader behaviour for free, but Tailwind emitted no `[open]:` variants for
 * it, so the open card looked identical to a closed one.
 */
.faq-item[open] {
  border-color: rgb(37 99 235 / 0.5);
  box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
}

.faq-item[open] > summary > span:first-child {
  color: #2563eb;
}

.faq-item[open] .faq-chevron {
  transform: rotate(180deg);
  background-color: rgb(37 99 235 / 0.1);
  color: #2563eb;
}

/* On the dark card the reference's blue is 2.8:1, under AA's 4.5; blue-400 is 5.8:1. */
:root.dark .faq-item[open] > summary > span:first-child,
:root.dark .faq-item[open] .faq-chevron {
  color: #60a5fa;
}

/*
 * ────────────────────────────────────────────────────────────────────────────
 * The honeypot's mask.
 *
 * OFF-SCREEN, never `display: none` and never `visibility: hidden`. Both of
 * those are the first thing a form-filling script checks before deciding
 * whether a field is real, so hiding the decoy that way hides it from the only
 * thing it is meant to catch. Moving it out of the viewport leaves it present,
 * rendered and fillable — which is exactly what we want it to look like.
 *
 * It is kept away from PEOPLE by three other means, none of them CSS:
 * `aria-hidden="true"` takes it out of the accessibility tree,
 * `tabindex="-1"` takes it out of the tab order, and `autocomplete="off"` asks
 * the browser not to fill it. A screen reader never meets it and a keyboard
 * user never lands on it.
 *
 * `left` rather than a transform, deliberately: a transformed element still
 * occupies its original box for scrolling, and a stray 1px scroll region at
 * the bottom of a form is a real bug on a phone.
 */
.hp-field {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/*
 * ────────────────────────────────────────────────────────────────────────────
 * The plan comparison table.
 *
 * The renderer builds `<table class="matrix">` with `td.yes` / `td.no` cells
 * and a `.matrix-note` line beneath it — and NOTHING styled any of it. Not
 * here, and not in vendor/tapvixo-ui.css, because the reference design has no
 * comparison table for Tailwind to have compiled one from. So the one part of
 * the pricing page that exists to be READ rendered as a raw browser-default
 * table: Times-ish serif metrics, no borders, no padding, columns sized by
 * content, on a page where everything else is designed.
 *
 * This is the third time a class has been written with no compiled rule behind
 * it (`sr-only`, the cycle toggle, now this). The pattern to watch: markup
 * generated by a script the designer never saw.
 *
 * Sticky first column and a horizontal scroll on narrow screens, because a
 * comparison is unreadable the moment you cannot see which ROW you are on.
 */

.matrix-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.matrix {
  width: 100%;
  border-collapse: separate;
  /* `separate` + zero spacing, not `collapse`: a collapsed border cannot be
     drawn on a sticky cell without it detaching as the column scrolls. */
  border-spacing: 0;
  font-size: 0.9375rem;
  text-align: left;
  color: #3d3d3d;
}

.matrix th,
.matrix td {
  padding: 0.875rem 1rem;
  border-bottom: 1px solid rgb(0 0 0 / 0.06);
  white-space: nowrap;
}

/* The header row names the plans; it is the table's own legend. */
.matrix thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background-color: #f8f9fb;
  font-weight: 700;
  color: #111827;
  border-bottom: 2px solid rgb(37 99 235 / 0.25);
}

/* The row header stays put while the plan columns scroll under it. */
.matrix tbody th,
.matrix thead th:first-child {
  position: sticky;
  left: 0;
  z-index: 1;
  background-color: #fff;
  font-weight: 600;
  color: #111827;
  /* A right edge, so the pinned column reads as pinned rather than as text
     sliding over the cells behind it. */
  box-shadow: 1px 0 0 rgb(0 0 0 / 0.06);
}

.matrix thead th:first-child {
  z-index: 3;
  background-color: #f8f9fb;
}

.matrix tbody tr:last-child th,
.matrix tbody tr:last-child td {
  border-bottom: 0;
}

/* Values are compared down a column, so they are centred under their plan. */
.matrix td {
  text-align: center;
  font-weight: 600;
  color: #111827;
}

.matrix td.yes {
  color: #10b981;
  font-size: 1.125rem;
}

.matrix td.no {
  color: #d1d5db;
  font-size: 1.125rem;
}

.matrix-note {
  margin-top: 1rem;
  text-align: center;
  font-size: 0.9375rem;
  color: #6b7280;
}

:root.dark .matrix {
  color: #d1d5db;
}

:root.dark .matrix th,
:root.dark .matrix td {
  border-bottom-color: rgb(255 255 255 / 0.08);
}

:root.dark .matrix thead th,
:root.dark .matrix thead th:first-child {
  background-color: #111827;
  color: #fff;
}

:root.dark .matrix tbody th {
  background-color: #1f2937;
  color: #fff;
  box-shadow: 1px 0 0 rgb(255 255 255 / 0.08);
}

:root.dark .matrix td {
  color: #fff;
}

:root.dark .matrix td.no {
  color: #4b5563;
}

:root.dark .matrix-note {
  color: #9ca3af;
}

/*
 * A link inside running text: underlined as well as coloured, because colour
 * alone does not tell every reader it is a link. Used by the FAQ answers that
 * send a reader to the pricing page instead of quoting a number.
 */
.inline-link {
  color: #2563eb;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.inline-link:hover {
  color: #1d4ed8;
}

:root.dark .inline-link {
  color: #60a5fa;
}

:root.dark .inline-link:hover {
  color: #93c5fd;
}

/*
 * The Terms and the Privacy Notice (identity PRD rule 19), and the feature
 * and use-case pages (.article): long prose the reference design never had,
 * so its stylesheet has no rule for a list or a heading inside an article.
 * Spacing and weight only; the text colour is the article's own utilities',
 * and links are .inline-link.
 */
.legal,
.article {
  font-size: 1rem;
  line-height: 1.75;
}

.legal p,
.legal ul,
.article p,
.article ul,
.article ol {
  margin: 0 0 1rem;
}

.legal ul,
.article ul {
  list-style: disc;
  padding-left: 1.5rem;
}

.article ol {
  list-style: decimal;
  padding-left: 1.5rem;
}

.legal li,
.article li {
  margin-bottom: 0.5rem;
}

.legal h2,
.article h2 {
  margin: 2.5rem 0 1rem;
  font-size: 1.5rem;
  line-height: 1.3;
  font-weight: 700;
  color: #111827;
  scroll-margin-top: 7rem;
}

.legal h3,
.article h3 {
  margin: 1.5rem 0 0.75rem;
  font-size: 1.125rem;
  font-weight: 600;
  color: #111827;
}

:root.dark .legal h2,
:root.dark .legal h3,
:root.dark .article h2,
:root.dark .article h3 {
  color: #ffffff;
}

.legal strong,
.article strong {
  font-weight: 600;
}

/*
 * The trail on a nested page (`{{{slot.breadcrumb}}}`, built from the same
 * crumbs as its BreadcrumbList). The reference design had no nested page.
 * Grey-600 on white is 7.6:1; the links are .inline-link's blue.
 */
.crumbs ol {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 0.5rem;
  margin: 0 0 1.5rem;
  padding: 0;
  list-style: none;
  font-size: 0.875rem;
  color: #4b5563;
}

.crumbs li + li::before {
  content: "›";
  margin-right: 0.5rem;
  color: #6b7280;
}

.crumbs a {
  color: #2563eb;
  text-decoration: underline;
  text-underline-offset: 3px;
}

:root.dark .crumbs ol {
  color: #d1d5db;
}

:root.dark .crumbs li + li::before {
  color: #9ca3af;
}

:root.dark .crumbs a {
  color: #60a5fa;
}

/* A blank the founder fills before the page is published (site.test.mjs fails while one remains). */
.legal-fill {
  background: #fef08a;
  color: #713f12;
  padding: 0 0.25rem;
  border-radius: 0.25rem;
}

/*
 * The phone's contact bar (replaced the arrival modal, audit 2026-10-06).
 * Fixed and served in the HTML, so it never shifts the page when it appears.
 * Phones only: from 768px up the side rail carries the same links. The body
 * gets the bar's height as bottom padding so the footer's last line is never
 * underneath it, and back-to-top moves up to clear it.
 */
.mobile-cta {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 60;
  display: flex;
  gap: 0.5rem;
  padding: 0.5rem 0.75rem calc(0.5rem + env(safe-area-inset-bottom));
  background-color: #fff;
  border-top: 1px solid #e5e7eb;
  box-shadow: 0 -4px 16px rgb(0 0 0 / 0.06);
}

.mobile-cta a {
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 3rem;
  border-radius: 0.75rem;
  font-weight: 700;
  font-size: 0.9375rem;
  text-decoration: none;
}

/* White on #2563eb is 5.2:1; WhatsApp's own green fails AA with white text. */
.mobile-cta-wa {
  background-color: #2563eb;
  color: #fff;
}

.mobile-cta-call {
  background-color: #fff;
  color: #111827;
  border: 1px solid #d1d5db;
}

:root.dark .mobile-cta {
  background-color: #0f172a;
  border-top-color: #1f2937;
}

:root.dark .mobile-cta-call {
  background-color: #1f2937;
  color: #fff;
  border-color: #374151;
}

@media (max-width: 767.98px) {
  body {
    padding-bottom: calc(4rem + env(safe-area-inset-bottom));
  }

  #back-to-top {
    bottom: calc(4.75rem + env(safe-area-inset-bottom));
  }
}

@media (min-width: 768px) {
  .mobile-cta {
    display: none;
  }
}

/*
 * The yearly total under each card's per-month figure (founder 2026-10-07:
 * sold yearly, shown per month). Plain sight, not fine print: the buyer reads
 * what they pay before they tap.
 */
.billed {
  font-weight: 600;
}

/*
 * Utilities the markup uses that the reference build never compiled — found by
 * marketing-site.wire.spec.ts on 2026-10-06, the fourth instance of the bug it
 * guards (a class with no rule renders as the browser default). Each had been
 * doing nothing since launch: the card headings sat flush on their taglines,
 * the comparison table had no gap above it, and every home-page FAQ question
 * carried the browser's disclosure triangle.
 */
.mb-1 {
  margin-bottom: calc(var(--spacing) * 1);
}

.mt-14 {
  margin-top: calc(var(--spacing) * 14);
}

.list-none {
  list-style-type: none;
}

summary.list-none::-webkit-details-marker {
  display: none;
}

/*
 * The rest of them, from the same scan over every page and partial (the wire
 * spec now covers all of them). Two were user-visible: the skip link's focus
 * styles were never compiled, so a keyboard user who tabbed to "Skip to
 * content" got an unstyled inline link instead of the pill; and `not-italic`
 * was missing, so every <address> on the site rendered in the browser's
 * default italics.
 */
.focus\:absolute:focus {
  position: absolute;
}

.focus\:top-2:focus {
  top: calc(var(--spacing) * 2);
}

.focus\:left-2:focus {
  left: calc(var(--spacing) * 2);
}

.focus\:z-\[100\]:focus {
  z-index: 100;
}

.focus\:px-4:focus {
  padding-inline: calc(var(--spacing) * 4);
}

.focus\:py-2:focus {
  padding-block: calc(var(--spacing) * 2);
}

.focus\:rounded-lg:focus {
  border-radius: 0.5rem;
}

.focus\:bg-blue-600:focus {
  background-color: #2563eb;
}

.focus\:text-white:focus {
  color: #fff;
}

.not-italic {
  font-style: normal;
}

.font-normal {
  font-weight: 400;
}

.mt-4 {
  margin-top: calc(var(--spacing) * 4);
}

.pb-8 {
  padding-bottom: calc(var(--spacing) * 8);
}

.pb-16 {
  padding-bottom: calc(var(--spacing) * 16);
}

.resize-y {
  resize: vertical;
}

.hover\:underline:hover {
  text-decoration-line: underline;
}

@media (min-width: 48rem) {
  .md\:p-10 {
    padding: calc(var(--spacing) * 10);
  }
}

/*
 * The feature deck: fourteen sticky cards that stack as the home page and
 * /features scroll. A card never cuts anything off, and the deck stays flush.
 *
 * - A MINIMUM height, never a fixed one. The reference fixed each card's height
 *   behind `overflow-hidden`, so copy that wrapped further than it expected was
 *   simply lost: from 768 to 1023 px eleven of the fourteen cards cut lines off
 *   top and bottom (2026-10-18), and below 346 px the longest cut the foot of
 *   its picture. A card that needs more room now grows instead.
 * - Flush, because each card stays stuck behind the cards that cover it: one
 *   taller than the next shows its bottom edge beneath it, and beneath every
 *   card after. So the heights hold the longest card's copy. From 768 px the
 *   text takes three fifths of the card and the padding is 40 px — at 768 px
 *   that is a 340 px column, which fits the longest card in 600 px, where an
 *   even split at the reference's 56 px needed about 700. From 1024 px it is the
 *   reference's own even split and padding, unchanged.
 * - `basis-0` beside `flex-1` on both columns: `flex-1`'s 0% basis needs a
 *   definite height to resolve against, and under a min-height falls back to
 *   the content's size, which moved every phone's picture down by up to 13 px.
 *   A length basis keeps the even split the fixed height gave.
 *
 * Pinned by apps/frontend/e2e-marketing/feature-deck.spec.ts, every width from
 * 320 to 1440 px.
 */
.min-h-\[650px\] {
  min-height: 650px;
}

.basis-0 {
  flex-basis: calc(var(--spacing) * 0);
}

@media (min-width: 48rem) {
  .md\:min-h-\[600px\] {
    min-height: 600px;
  }

  .md\:flex-\[3\] {
    flex: 3;
  }

  .md\:flex-\[2\] {
    flex: 2;
  }
}

@media (min-width: 64rem) {
  .lg\:p-14 {
    padding: calc(var(--spacing) * 14);
  }

  .lg\:flex-1 {
    flex: 1;
  }
}
