/* =========================================================================
   PayMQR — Public website
   =========================================================================
   The marketing surface: landing, features, pricing, how it works,
   developers, security, FAQ, about, contact and the three legal pages.

   A SEPARATE STYLESHEET FROM merchant.css, on purpose. The merchant
   console is a dense application shell; this is a wide, quiet reading
   surface, and a public visitor should not download 82KB of table,
   sidebar and form styling to read a pricing page. The two share a brand,
   not a stylesheet.

   Served as a static file from public/, so it is covered by
   `style-src 'self'` and needs no CSP change. No build step, no
   preprocessor, no framework, no webfont request, no external host.

   Owner-approved palette (Stage 13 / P02):
     deep navy   var(--ink)   trust      surfaces, headings, footer
     trust blue  var(--si-blue)   action     primary CTA, links, active nav
     emerald     #10B981   success    status accents only
     light bg    var(--ground)   ground     alternating sections
     ink         var(--ink)   body text

   Intended balance is roughly 70% white/light, 20% navy, 7% blue, 3%
   emerald — so the accents are used sparingly and deliberately.

   Sections
     1. Tokens
     2. Reset & base
     3. Header & mobile nav
     4. Footer
     5. Layout: sections, containers, headings
     6. Buttons & links
     7. Hero
     8. Product visuals (shared pieces)
     9. Cards, grids, feature blocks
    10. Steps & flows
    11. Pricing
    12. FAQ / accordion
    13. Prose (legal & long-form)
    14. Contact
    15. Utilities & responsive
    16. Product visuals: console, checkout, poster, payments screen
    17. Landing layout pieces
    18. Auth
   ========================================================================= */

/* ---------- 1. Tokens ---------------------------------------------------- */

/*
 * EVERY VALUE BELOW COMES FROM brand.css. This block keeps the `--si-*`
 * vocabulary the 2593 lines beneath it already speak, but it no longer owns
 * a single brand literal — so a brand change is an edit to brand.css §1 and
 * nothing here moves.
 *
 * The names that say "navy" and "blue" are kept ON PURPOSE. Renaming 424
 * references would be a large diff carrying no behaviour, and the risk of a
 * missed one is a page that loses a colour. What they MEAN has changed and
 * the mapping below is where that is written down:
 *
 *      --si-navy*   ->  charcoal   (the dark surface family)
 *      --si-blue    ->  the ACTION family, and it is now THREE tokens
 *                       because #FFC400 is 1.60:1 on white and cannot be
 *                       both a button fill and a link colour.
 */
:root {
    /* The dark surface family. Charcoal, not navy. */
    --si-navy: var(--charcoal-800);
    --si-navy-2: var(--charcoal-700);
    --si-navy-3: #3A3A3A;

    /* THE ACTION FAMILY. `--si-blue` is now the FILL and nothing else; any
       rule that paints TEXT reaches for `--si-action-ink` instead. The two
       are not interchangeable and that is the whole point. */
    --si-blue: var(--action-fill);
    --si-blue-hover: var(--action-fill-hover);
    --si-blue-soft: var(--action-soft);
    --si-blue-border: var(--action-border);

    /* Brand-coloured TEXT on a light ground: links, active nav, eyebrows.
       6.65:1. Never `--si-blue`. */
    --si-action-ink: var(--action-ink);
    /* The same role on a dark section, where the yellow IS the readable
       choice at 10.32:1. */
    --si-action-ink-dark: var(--action-ink-on-dark);
    /* Text that sits ON a yellow fill. */
    --si-on-action: var(--action-on-fill);
    /* A brand-family shape that must be seen on white (3.26:1). */
    --si-action-graphic: var(--action-graphic);

    /* SEMANTIC, AND UNCHANGED BY THE REBRAND. Green still means settled.
       docs/BRAND_SYSTEM.md §4. */
    --si-emerald: var(--state-ok);
    --si-emerald-soft: var(--state-ok-soft);
    --si-emerald-border: var(--state-ok-border);
    --si-amber: var(--state-warn-solid);
    --si-danger: var(--state-error);

    /* THE CANVAS IS NOT WHITE. A soft off-white ground is what lets a
       white card read as a raised SURFACE rather than as a bordered
       rectangle drawn on the same paper — the single cheapest way to buy
       depth without a shadow. `--si-bg-alt` has to stay separable from it
       at a glance, so the alternating band went a step deeper with it. */
       WARM, NOT BLUE-GREY, since the rebrand. A cool canvas under a yellow
       brand reads as two unrelated decisions; the same off-white shifted a
       few degrees warm makes the yellow look chosen. */
    --si-bg: var(--ground);
    --si-bg-alt: var(--ground-alt);
    --si-surface: var(--surface);

    /* THREE INK LEVELS, AND THE MIDDLE ONE IS DARKER THAN IT WAS. A page
       where body copy, captions and metadata all sit around #6B7280 reads
       as washed out rather than restrained — the eye finds no primary
       text. `--si-muted` is now the colour of real BODY COPY (8.3:1) and
       `--si-subtle` is reserved for genuine metadata. */
    --si-text: var(--ink);
    --si-muted: var(--ink-muted);
    --si-subtle: var(--ink-subtle);
    --si-invert: var(--ink-invert);
    --si-invert-muted: var(--ink-invert-muted);

    --si-border: var(--line);
    --si-border-strong: var(--line-strong);

    /* SURFACES AND STATES THIS FILE REFERENCED WITHOUT EVER DEFINING. Every
       one was reaching a var() fallback, which meant the value lived at the
       use site and could not be re-themed. They are real tokens now.

       The warning family is the one the rebrand MOVED: its old amber sat ten
       degrees from #FFC400, so on a page carrying both, "PayMQR" and "this
       needs attention" were the same colour. docs/BRAND_SYSTEM.md §4.2. */
    --si-surface-2: var(--ground-alt);
    --si-text-muted: var(--ink-muted);
    --si-warning-soft: var(--state-warn-soft);
    --si-warning-border: var(--state-warn-border);
    --si-warning-text: var(--state-warn-ink);

    /* Info stays BLUE, and is now the only blue on the site — which is what
       makes it read as information rather than as brand. */
    --si-info: var(--state-info);
    --si-info-soft: var(--state-info-soft);
    --si-info-border: var(--state-info-border);
    --si-info-text: var(--state-info-ink);

    /* Muted text ON a dark section. Warm, to sit with the charcoal. */
    --si-on-dark: var(--ink-invert);
    --si-on-dark-muted: var(--ink-invert-muted);
    --si-on-dark-subtle: #A9A296;

    /* THREE RADII, ONE PER SCALE OF THING — controls, cards, product
       visuals. Nothing on this site is a pill except a status chip, and
       nothing is squarer than 9px: over-rounding is the loudest tell of a
       template, and hard corners read as unfinished at this type size. */
    --si-radius-sm: 9px;    /* controls: buttons, inputs, small tiles */
    --si-radius: 15px;      /* cards and panels */
    --si-radius-lg: 19px;   /* large product visuals only */

    /* =================================================================
       ELEVATION IS A RING PLUS A CAST, NEVER A BLUR
       =================================================================
       A hairline `border` and a soft `box-shadow` fight each other: the
       border is a hard 1px at full opacity, the shadow a wide 10% wash,
       and together they read as a sticker. Every surface here is instead
       one 1px RING (drawn as a zero-blur shadow, so it is crisp at any
       device pixel ratio and costs no layout) plus a short contact
       shadow and, at the top of the stack, a long low-opacity cast.

       The ring lightens as elevation rises. That is what makes a card
       look like it is ABOVE the page rather than drawn on it. */
       THE SHADOW INK IS A TOKEN NOW. It was `rgba(var(--shadow-rgb),…)` — the old
       navy — written out in 61 places in this file alone. `--shadow-rgb`
       carries the charcoal, so the cast matches the surfaces it falls
       from. */
    --si-ring-hair: 0 0 0 1px rgba(var(--shadow-rgb), .055);
    --si-shadow-sm: var(--si-ring-hair), 0 1px 1.5px rgba(var(--shadow-rgb), .04);
    --si-shadow: var(--si-ring-hair), 0 1px 2px rgba(var(--shadow-rgb), .05), 0 8px 20px -12px rgba(var(--shadow-rgb), .22);
    --si-shadow-lg:
        0 0 0 1px rgba(var(--shadow-rgb), .07),
        0 1px 2px rgba(var(--shadow-rgb), .05),
        0 12px 24px -12px rgba(var(--shadow-rgb), .16),
        0 34px 64px -28px rgba(var(--shadow-rgb), .30);

    /* THE DARK SURFACE IS NOT ONE COLOUR. A flat panel is the cheapest-
       looking thing on a page; a charcoal that lifts towards its own top
       edge reads as a lit material. Neutral warm greys, so the yellow sitting
       on it stays the only chromatic thing in the section. */
    --si-navy-surface:
        radial-gradient(130% 90% at 50% -14%, #343029 0%, #262320 42%, #171614 100%);

    /* FOCUS. A solid ring carries the 3:1; the soft one makes it read as a
       focus state rather than a border. brand.css §5. */
    --si-ring: var(--focus-ring);

    --si-s1: .25rem;
    --si-s2: .5rem;
    --si-s3: .75rem;
    --si-s4: 1rem;
    --si-s5: 1.5rem;
    --si-s6: 2rem;
    --si-s7: 3rem;
    --si-s8: 4.5rem;

    --si-max: 1200px;
    --si-max-narrow: 720px;

    /* MOBILE IS THE PRIMARY TARGET, so the two rhythm values a phone
       actually feels are tokens rather than numbers buried in a media
       query: the page gutter and the distance between major sections.
       The desktop overrides for both live at the foot of §5. */
    /* The first pass set these chasing total page height, and 56px between
       major sections on a phone is the rhythm of an admin console, not of a
       page you are meant to want to read. Compactness is hygiene; it is not
       what makes a page feel expensive. */
    --si-gutter: 1.25rem;    /* 20px — the page's horizontal padding */
    --si-sect: 3.75rem;      /* 60px — major section rhythm */
}

/* ---------- 2. Reset & base ---------------------------------------------- */

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

/* THE PAGE GROUND CARRIES ONE VERY SLOW VERTICAL TONE. Flat var(--ground) for
   6,000px is what makes a long page feel like paper; a 2% shift across it
   is invisible as a gradient and reads as depth. */
body {
    margin: 0;
    background: var(--si-bg);
    background-image: linear-gradient(180deg, #FFFFFF 0%, var(--si-bg) 420px, var(--si-bg) 100%);
    background-attachment: fixed;
    color: var(--si-text);
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    font-size: 1rem;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
}

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

/* HEADINGS CARRY THE WEIGHT CONTRAST. 700 against a 400 body is the
   default every template ships; 780 against 420 is a voice. The system
   stack resolves 780 to SF Pro / Segoe Semibold-to-Bold and degrades to
   700 elsewhere, so nothing synthesises. */
h1, h2, h3, h4 { color: var(--si-navy); margin: 0; line-height: 1.18; letter-spacing: -.018em; font-weight: 780; }
p { margin: 0; }
ul, ol { margin: 0; padding: 0; }

a { color: var(--si-action-ink); }
a:hover { color: var(--si-blue-hover); }

/* A TWO-TONE FOCUS RING: a 2px white separator inside a 2px blue ring, so
   it stays visible on a white card, on the navy band and on the blue
   button itself. A single blue halo disappears against the primary CTA,
   which is the one control most likely to be reached by keyboard. */
:focus-visible {
    outline: none; border-radius: var(--si-radius-sm);
    box-shadow: 0 0 0 2px #fff, 0 0 0 4px var(--si-blue);
}
.si-section--navy :focus-visible, .si-cta :focus-visible, .si-footer :focus-visible {
    box-shadow: 0 0 0 2px var(--si-navy), 0 0 0 4px var(--si-action-ink-dark);
}

.si-skip {
    position: absolute; left: -9999px; top: 0; z-index: 100;
    background: var(--si-navy); color: #fff; padding: .75rem 1rem;
    border-radius: 0 0 var(--si-radius-sm) 0; text-decoration: none;
}
.si-skip:focus { left: 0; color: #fff; }

/* ---------- 3. Header & mobile nav ---------------------------------------- */

/* Translucent white over a blur, a hairline, and NO shadow: a sticky bar
   that casts a shadow onto the page announces itself on every scroll
   event, which is the opposite of restrained. The border is the whole
   separation. */
.si-header {
    position: sticky; top: 0; z-index: 50;
    /* .82 ALPHA WAS TOO TRANSPARENT, and this page's own navy sections are
       what proved it: scrolled over the dashboard band the bar rendered
       mid-grey, the logo went dull and the muted nav labels lost most of
       their contrast. A sticky header has to stay legible over EVERY
       surface it crosses, and three of this page's nine are dark. At .94
       the blur still reads as depth where the page is light and the bar
       stays white where it is not. */
    background: rgba(255, 255, 255, .94);
    backdrop-filter: saturate(180%) blur(16px);
    -webkit-backdrop-filter: saturate(180%) blur(16px);
    border-bottom: 1px solid rgba(var(--shadow-rgb), .07);
}
/* A browser without backdrop-filter gets an opaque bar rather than text
   sliding under text. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .si-header { background: #fff; }
}

/* A 56px BAR ON A PHONE, and the lockup is what sets it: 43px of artwork
   plus 6px of air each side. 46px + 7px was 61px — a tenth of the first
   screen spent on navigation the visitor did not come for, and enough to
   read as a masthead rather than as a bar.

   43px is not an arbitrary trim: the supplied lockup is 37% transparent
   padding, so 43px of box is ~27px of ink and a ~19px "PayMQR" at 129px
   wide. Below about 40px the wordmark stops holding its weight. A 1200px
   desktop bar can afford the full 48px and takes it (§19). */
.si-header__inner {
    max-width: var(--si-max);
    margin: 0 auto;
    padding: .375rem var(--si-gutter);
    position: relative;
    display: flex; align-items: center; gap: var(--si-s5);
}

/* --- The PayMQR lockup -------------------------------------------------
   Mark plus wordmark. Sized so the header lockup lands at ~152px wide on
   desktop and ~137px on mobile — the mark is a fixed box and the wordmark
   is real text, so both scale with the root font rather than a bitmap. */
/* =====================================================================
   THE LOCKUP IS NUDGED LEFT, AND THE NUMBER IS MEASURED
   =====================================================================
   `logo-horizontal.png` carries 5.8% of transparent padding down its left
   edge (measured off the file's own alpha channel, 2172x724). Set flush to
   the 20px gutter, its INK therefore starts at 27.5px while the menu tile
   opposite — a drawn box with no padding — starts at exactly 20px from its
   own edge. The bar looked ~7px heavier on the left and nothing in the CSS
   explained why.

   The offset is a fixed share of the lockup's height (0.058 x the 3.0
   aspect = 0.174), so it is stated per size rather than as one magic pixel
   count: 7px at the phone's 43px, 8px at the desktop's 48px. */
.si-logo {
    display: inline-flex; align-items: center; gap: .5rem;
    text-decoration: none; flex: 0 0 auto; line-height: 1;
    margin-left: -7px;
}
/* THE APPROVED LOCKUP, AS A FILE.
   HEIGHT IS SET, WIDTH IS AUTO — never both. That single rule is what
   makes stretching impossible: the intrinsic 2172x724 on the <img> does
   the rest, so the tagline and the QR mark keep their exact proportions
   at every breakpoint.
   56px is chosen against the artwork, not by eye: the supplied file is
   37% transparent padding, so 56px of box is ~35px of ink and a ~24px
   "PayMQR". Below about 44px the wordmark stops holding its weight in a
   header. */
.si-logo__img { display: block; height: 43px; width: auto; max-width: 100%; }

/* THE SIDE NAV IS A DESKTOP OBJECT. On a phone the sheet below is the
   only navigation there is, so the base state hides this and 861px brings
   it back — not the other way round. */
.si-nav { display: none; align-items: center; gap: var(--si-s2); margin-left: auto; }
/* =====================================================================
   THE BAR IS COMPOSED, NOT JUST LAID OUT
   =====================================================================
   Three deliberate moves over a default flex row:

   The links sit in their own group with real tracking between them, and
   hover is a soft pill that FADES rather than snapping to a grey block.

   The current page is marked by a 2px underline under the label rather
   than by colouring it blue — blue is this site's action colour, and a nav
   item that is merely where you already are is not an action.

   And the actions are separated from the links by a hairline divider, so
   "Log in / Start free" reads as a different kind of thing from
   "Product / Pricing". That 1px is most of the difference between a
   designed header and a row of anchors. */
.si-nav__list { display: flex; align-items: center; gap: .125rem; list-style: none; }
.si-nav__link {
    position: relative; display: inline-block;
    padding: .4rem .65rem; border-radius: 8px;
    color: var(--si-muted); text-decoration: none;
    font-size: .875rem; font-weight: 550; letter-spacing: -.008em;
    transition: color .18s ease, background-color .18s ease;
}
.si-nav__link:hover { color: var(--si-navy); background: rgba(var(--shadow-rgb), .045); }
.si-nav__link[aria-current="page"] { color: var(--si-navy); font-weight: 650; }
.si-nav__link[aria-current="page"]::after {
    content: ""; position: absolute; left: .65rem; right: .65rem; bottom: -.1rem;
    height: 2px; border-radius: 2px; background: var(--si-blue);
}

.si-actions {
    display: flex; align-items: center; gap: .375rem;
    margin-left: var(--si-s4); padding-left: var(--si-s4);
    border-left: 1px solid rgba(var(--shadow-rgb), .09);
}
.si-actions .si-btn--ghost { font-weight: 600; }

/* The mobile menu is a <details>. No JavaScript: it is keyboard-operable,
   announced by assistive tech, and works with `script-src 'self'` intact. */
/* THE CONTROL IS THE ICON, NOT THE WORD. A 40px square tile sits beside a
   46px lockup as a peer; the old bordered "Menu" pill was 42px tall and
   96px wide and read as the loudest thing in the bar. The word stays in
   the markup — hidden visually, kept for the accessible name — so nothing
   about the scriptless <details> changes. */
.si-menu { display: block; margin-left: auto; }
.si-menu > summary {
    list-style: none; cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center;
    width: 38px; height: 38px;
    border: 0; border-radius: 10px; color: var(--si-navy);
    background: #fff; box-shadow: var(--si-shadow-sm);
    transition: border-color .18s ease, color .18s ease, background-color .18s ease;
}
.si-menu > summary svg { width: 18px; height: 18px; }
.si-menu > summary:hover { box-shadow: 0 0 0 1px rgba(var(--shadow-rgb), .18), 0 1px 3px rgba(var(--shadow-rgb), .1); }
.si-menu > summary > span {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.si-menu > summary::-webkit-details-marker { display: none; }
.si-menu[open] > summary { border-color: var(--si-navy); background: var(--si-navy); color: #fff; }

/* The sheet slides and fades in one 180ms move. `<details>` gives no
   close transition without script, so the open state is the only one
   animated — a one-way ease reads as deliberate; a half-built two-way one
   does not. */
.si-menu__panel {
    position: absolute; left: 0; right: 0; top: 100%;
    background: #fff; border-bottom: 1px solid var(--si-border);
    box-shadow: var(--si-shadow-lg);
    padding: var(--si-s3) var(--si-gutter) var(--si-s4);
    animation: si-sheet-in .18s ease-out both;
}
@keyframes si-sheet-in { from { opacity: 0; transform: translateY(-6px); } }
.si-menu__list { list-style: none; display: flex; flex-direction: column; }
.si-menu__list a {
    display: block; padding: .6rem .125rem; color: var(--si-navy);
    text-decoration: none; font-weight: 550; font-size: .9375rem;
    border-bottom: 1px solid var(--si-border);
}
.si-menu__list li:last-child a { border-bottom: 0; }
.si-menu__list a[aria-current="page"] { color: var(--si-action-ink); }
.si-menu__actions { display: flex; gap: var(--si-s2); margin-top: var(--si-s3); }
.si-menu__actions .si-btn { flex: 1 1 0; }

/* ---------- 4. Footer ----------------------------------------------------- */

/* The footer is the page's last surface, so it is lit like the others — and
   it carries the same hairline of light along its top edge the closing band
   does, which stops two adjacent navy blocks reading as one slab. */
/* NOT `--si-navy-surface`. That gradient lights from its own top edge,
   and the closing band above the footer ends on its DARKEST value — so two
   of them stacked put a light band directly under a dark one and drew a
   visible seam across the bottom of the page. The footer instead CONTINUES
   downward from where the band left off. */
.si-footer {
    position: relative; color: var(--si-invert);
    background: linear-gradient(180deg, #262320 0%, #171614 100%);
    margin-top: var(--si-s7);
}
.si-footer::before {
    content: ""; position: absolute; left: 0; right: 0; top: 0; height: 1px; pointer-events: none;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .12) 20%, rgba(255, 255, 255, .12) 80%, transparent);
}
/* The footer margin is breathing room after a LIGHT section. Above a navy
   closing band it draws a white stripe between two navy surfaces — a
   rendering fault, on the landing page and on /features, /developers and
   /security, all four of which end dark. A browser without `:has()` drops
   the rule and keeps today's behaviour. */
main:has(> .si-cta:last-child) + .si-footer,
main:has(> .si-section--navy:last-child) + .si-footer { margin-top: 0; }
/* MOBILE-FIRST, AND THE MOBILE SHAPE IS TWO COLUMNS OF SMALL TYPE.
   Stacked in one column the four link groups ran 938px on a 375px phone —
   most of it whitespace between three-item lists. Paired, the same links
   are a few hundred pixels and every one is still a 15px tap row. */
.si-footer__inner { max-width: var(--si-max); margin: 0 auto; padding: var(--si-s6) var(--si-gutter) var(--si-s5); }
.si-footer__top { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--si-s5) var(--si-s4); }
.si-footer__brandcol { grid-column: 1 / -1; }
/* STACKED, NOT INLINE. The brand column is 1.4fr of five, so
   "Payment Gateway Connectors" beside a badge always wrapped onto a
   second line and read as a rendering fault. Badge above label wraps
   nowhere and is deliberate at every width. */
.si-footer__text { margin-top: var(--si-s3); color: var(--si-invert-muted); font-size: .8125rem; line-height: 1.6; max-width: 44ch; }
.si-footer__heading { color: #fff; font-size: .625rem; text-transform: uppercase; letter-spacing: .1em; font-weight: 700; margin-bottom: var(--si-s2); }
.si-footer__list { list-style: none; display: flex; flex-direction: column; gap: .4rem; }
.si-footer__list a { color: var(--si-on-dark-muted); text-decoration: none; font-size: .84375rem; transition: color .18s ease; }
.si-footer__list a:hover { color: #fff; }
.si-footer__bottom {
    margin-top: var(--si-s5); padding-top: var(--si-s4);
    border-top: 1px solid rgba(255, 255, 255, .12);
    display: flex; flex-wrap: wrap; gap: var(--si-s2) var(--si-s5);
    align-items: center; justify-content: space-between;
    color: var(--si-on-dark-subtle); font-size: .75rem; line-height: 1.6;
}
.si-footer__legal { max-width: 62ch; }

/* ---------- 5. Layout ----------------------------------------------------- */

/* 3.5rem, not 4: the owner's brief is a compact page, and this one
   change tightens twelve public pages at once without touching a
   single component's internal rhythm. */
/* ONE TOKEN DECIDES THE PAGE'S VERTICAL RHYTHM, at every width. Changing
   `--si-sect` at a breakpoint retunes all twelve public pages at once
   without any component knowing a breakpoint exists. */
.si-section { padding: var(--si-sect) var(--si-gutter); }
/* The tinted band gets its own slow tone too, so two adjacent light
   sections never meet as two flat fills. */
.si-section--alt { background: linear-gradient(180deg, var(--surface) 0%, var(--si-bg-alt) 55%, var(--ground-alt) 100%); }
/* THE DARK SECTION IS A LIT MATERIAL. See `--si-navy-surface`. The bloom
   over the top edge is what makes the white product panel inside it read
   as the brightest thing on the page. */
.si-section--navy {
    position: relative; overflow: hidden;
    background: var(--si-navy-surface); color: var(--si-invert);
}
.si-section--navy::before {
    content: ""; position: absolute; inset: -30% -10% auto; height: 70%; pointer-events: none;
    background: radial-gradient(48% 62% at 50% 50%, rgba(var(--brand-rgb), .07), rgba(var(--brand-rgb), 0) 70%);
}
.si-section--navy > * { position: relative; }
/* A navy section inverts the three things a light one styles by default:
   the heading, the lede and the eyebrow. Scoped to the section so no
   component needs an `--onnavy` twin. */
.si-section--navy h2, .si-section--navy h3 { color: #fff; }
.si-section--navy .si-lede { color: var(--si-on-dark-muted); }
.si-eyebrow--invert { color: var(--si-action-ink-dark); }
.si-section--navy h2, .si-section--navy h3 { color: #fff; }
.si-section--tight { padding-top: var(--si-s6); padding-bottom: var(--si-s6); }
.si-wrap { max-width: var(--si-max); margin: 0 auto; }
.si-wrap--narrow { max-width: var(--si-max-narrow); }

.si-head { max-width: 46rem; margin-bottom: var(--si-s6); }
.si-head--center { margin-left: auto; margin-right: auto; text-align: center; }
/* THE ONE CENTRED HEADING THAT STOPS BEING CENTRED. Everything under it is
   a left-aligned two-column spread, and a centred title over an asymmetric
   body is the commonest way a page loses its axis. Below 961px the columns
   stack and centred is right again. */
@media (min-width: 961px) {
    #links .si-head--center { margin-left: 0; margin-right: 0; text-align: left; max-width: 34ch; }
}
/* AN EYEBROW IS META, NOT A HEADING. At 12px with a heavy weight it
   competed with the h2 underneath it; at 10.5px with wider tracking it
   labels the section and gets out of the way, which is the whole job. */
/* AN EYEBROW WITH A RULE. The label alone floated; a 14px leading rule in
   the same blue ties it to the heading under it and gives every section
   the same opening gesture — which is what a design SYSTEM reads like. */
.si-eyebrow {
    display: inline-flex; align-items: center; gap: .5rem;
    font-size: .6875rem; font-weight: 700;
    letter-spacing: .13em; text-transform: uppercase; color: var(--si-action-ink);
    margin-bottom: var(--si-s3);
}
.si-eyebrow::before {
    content: ""; width: 14px; height: 2px; border-radius: 2px;
    background: currentColor; opacity: .85; flex: 0 0 auto;
}
.si-head--center .si-eyebrow::before { display: none; }
.si-section--navy .si-eyebrow { color: var(--si-action-ink-dark); }
/* `balance` because these headings are short and their default ragging
   leaves a one-word last line often enough to notice — "Choose how you
   want to get / paid." was the one that gave it away on a 360px phone.
   Ignored by browsers that do not support it, which simply get today's
   ragging. */
/* 25px on a phone, 34px at 1200 — one step up from the first pass, which
   had shrunk section headings to the point where they no longer opened a
   section, they just labelled it. */
.si-h2 { font-size: clamp(1.5625rem, 1.06rem + 1.85vw, 2.125rem); letter-spacing: -.028em; line-height: 1.14; text-wrap: balance; }
/* A two-sentence heading: two lines on a wide screen, one balanced flow on
   a phone. Forcing the break below 560px gave three lines with the second
   sentence's last word alone on the third — all four of these orphaned
   that way. Spans, not a `<br>`: a hidden `<br>` leaves "directly.Stop"
   with no space and no pseudo-element can put one back. */
.si-h2--two > span { display: block; }
@media (max-width: 560px) {
    .si-h2--two { text-wrap: balance; }
    .si-h2--two > span { display: inline; }
}
.si-h3 { font-size: 1.125rem; font-weight: 750; letter-spacing: -.022em; text-wrap: balance; }
@media (min-width: 961px) { .si-h3 { font-size: 1.3125rem; } }
/* 15px on a phone, 17px from tablet up. The first pass took this to 14px
   chasing height and made the page's supporting voice too quiet to read
   comfortably — small type is hygiene, not premium. 58ch is the measure:
   past that the eye loses the line return. */
.si-lede { margin-top: var(--si-s3); color: var(--si-muted); font-size: .9375rem; line-height: 1.6; max-width: 58ch; }
.si-section--navy .si-lede { color: var(--si-on-dark-muted); }

/* ---------- 6. Buttons ---------------------------------------------------- */

/* 44px TALL, 13.5px TYPE, 9px RADIUS — a control, not a mobile-app slab.
   The height is a `min-height` rather than padding arithmetic so a button
   whose label wraps grows instead of bursting its own box. */
.si-btn {
    display: inline-flex; align-items: center; justify-content: center; gap: .45rem;
    min-height: 2.75rem; padding: .5rem 1.1rem; border-radius: var(--si-radius-sm);
    font-size: .84375rem; font-weight: 650; line-height: 1.25; letter-spacing: -.005em;
    text-decoration: none; border: 1px solid transparent; cursor: pointer; white-space: nowrap;
    transition: background-color .18s ease, border-color .18s ease, color .18s ease, box-shadow .18s ease;
}
/* NO GRADIENT AND NO GLOW — but not flat either. A 1px inset highlight
   along the top edge and a coloured contact shadow give the control the
   same material the surfaces have; a pure flat rectangle of var(--si-blue) is
   the one thing on this page that would still look like a framework
   default. It presses 1px on `:active`, which is the cheapest piece of
   tactility there is. */
.si-btn--primary {
    background: var(--si-blue); color: var(--si-on-action); border-color: var(--si-action-graphic);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .17), 0 1px 2px rgba(var(--brand-deep-rgb), .24), 0 4px 10px -4px rgba(var(--brand-rgb), .45);
}
/* THE INK DOES NOT CHANGE ON HOVER, AND THAT IS THE FIX RATHER THAN THE
   STYLE. `color: #fff` survived here from the blue identity, where white
   was the ink on the action colour. On the yellow it is white on #E6AC00
   — 2.06:1, which fails every contrast floor — while the resting ink
   (`--si-on-action`, the charcoal) is 8.09:1 on the same fill. A control
   that becomes unreadable at the moment a person reaches for it is the
   one state that must not be decorative, so hover changes the FILL only
   and the ink is inherited from the resting rule above. */
.si-btn--primary:hover { background: var(--si-blue-hover); border-color: var(--si-blue-hover); }
.si-btn:active { transform: translateY(1px); }
.si-btn--primary:active { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .12), 0 1px 1px rgba(var(--brand-deep-rgb), .3); }
.si-btn--secondary {
    background: #fff; color: var(--si-navy); border-color: transparent;
    box-shadow: 0 0 0 1px rgba(var(--shadow-rgb), .11), 0 1px 2px rgba(var(--shadow-rgb), .05);
}
.si-btn--secondary:hover { color: var(--si-navy); box-shadow: 0 0 0 1px rgba(var(--shadow-rgb), .22), 0 1px 3px rgba(var(--shadow-rgb), .08); }
.si-btn--ghost { background: transparent; color: var(--si-muted); }
.si-btn--ghost:hover { color: var(--si-navy); background: var(--si-bg-alt); }
.si-btn--onnavy { background: #fff; color: var(--si-navy); border-color: #fff; }
.si-btn--onnavy:hover { background: var(--line); color: var(--si-navy); }
.si-btn--outline-navy { background: transparent; color: #fff; border-color: rgba(255, 255, 255, .35); }
.si-btn--outline-navy:hover { border-color: #fff; color: #fff; }
/* `--lg` IS NOW A NUDGE, NOT A SIZE JUMP. It used to be 16px type in a
   55px box, which is the giant mobile-app button the brief rules out; it
   is now 2px of extra type and a wider waist, so a hero control reads as
   the page's most important button without becoming its largest object. */
.si-btn--lg { min-height: 2.875rem; padding: .55rem 1.35rem; font-size: .875rem; }

.si-ctarow { display: flex; flex-wrap: wrap; align-items: center; gap: var(--si-s3); }
/* A LONE CTA ROW STRETCHES ON A PHONE; THE HERO'S DOES NOT. The hero pairs
   a solid button with a quiet inline action, and stretching both would put
   the weight back on the secondary one the pairing exists to take it off. */
@media (max-width: 720px) {
    .si-ctarow:not(.si-hero__cta):not(.si-pricingcta) .si-btn { flex: 1 1 auto; }
}

/* =====================================================================
   THE PRICING HAND-OFF
   =====================================================================
   The section that used to carry a Free strip and three priced cards is
   now a heading and one control pointing at `/pricing`. Centred, and
   sized to its own label at every width — stretched edge to edge on a
   phone (which is what the rule above does to a lone call-to-action row)
   a single secondary button becomes a 350px slab, and a slab is the
   "another large card" this section exists to avoid being. */
.si-pricingcta { justify-content: center; }
.si-pricingcta .si-btn { flex: 0 0 auto; }

.si-textlink { color: var(--si-action-ink); font-weight: 650; font-size: .8125rem; text-decoration: none; }
.si-textlink:hover { text-decoration: underline; }
/* `margin-left`, NOT a leading space in the `content` string: the space
   is INSIDE the inline-block and gets collapsed away, which is how the
   link rendered as "View all FAQs→". */
.si-textlink::after { content: "→"; display: inline-block; margin-left: .3rem; transition: transform .18s ease; }
.si-textlink:hover::after { transform: translateX(2px); }

/* ---------- 7. Hero ------------------------------------------------------- */

/* =====================================================================
   THE HERO GROUND IS LIT, NOT PAINTED
   =====================================================================
   Three stacked gradients, none of them visible as a gradient: a wide blue
   wash behind the product composition, a much fainter emerald one under
   the left copy (the brand's success colour at 5% — it registers as warmth
   rather than as colour), and a slow vertical settle into the page ground.
   Flat white here was the single biggest reason the first pass read as a
   template: a white card on a white page has no material.

   The hero also OWNS its horizontal overflow (`clip`, not `hidden`, so
   nothing vertical is cut) — a lit ground is the one place a decorative
   layer can outgrow the viewport without anyone noticing until a
   scrollbar appears. */
.si-hero {
    position: relative; overflow-x: clip;
    padding: 2.25rem var(--si-gutter) var(--si-s6);
    background:
        radial-gradient(1000px 540px at 82% 2%, rgba(var(--brand-rgb), .11), transparent 62%),
        radial-gradient(560px 460px at 0% 34%, rgba(16, 185, 129, .045), transparent 62%),
        linear-gradient(180deg, #FFFFFF 0%, var(--surface) 46%, var(--si-bg) 100%);
}
/* THE COPY COLUMN IS THE WIDER ONE. The visual had the larger share while
   the headline was two short phrases; at 506px the second sentence could
   not hold one line at any hero-scale type. Swapping gives the copy the
   room and leaves the console still wider than it renders stacked. */
.si-hero__grid { max-width: var(--si-max); margin: 0 auto; display: grid; gap: var(--si-s5); align-items: center; }

/* =====================================================================
   THE PHONE HERO IS RE-ORDERED WITHOUT RE-ORDERING THE MARKUP
   =====================================================================
   `display: contents` dissolves the copy column into the grid below
   961px, so the product visual can be lifted between the trust strip and
   the fine print — the product is on screen inside the FIRST phone
   screen rather than after five paragraphs of it.

   THE SOURCE ORDER IS UNTOUCHED, which matters: PublicCopyParityTest
   reads `.si-hero__copy` as the span from that div to the `<figure>` and
   asserts what the hero's COPY may claim. Moving the figure in the
   markup would move it inside that span. Moving it in CSS cannot. */
@media (max-width: 960px) {
    .si-hero__copy { display: contents; }
    /* AND THE GRID'S OWN GAP GOES TO ZERO WITH IT. Dissolved, each element
       becomes a grid ITEM, so the 24px row gap would be added on top of
       every margin the components already carry — which is how a headline
       and its lede ended up 90px apart. The margins are the rhythm; the
       grid just stacks them. */
    .si-hero__grid { row-gap: 0; }
    .si-hero__title { order: 1; }
    .si-hero__lede  { order: 2; }
    .si-hero__cta   { order: 3; }
    .si-hero__facts { order: 4; }
    /* `.si-hero__grid >` is not decoration: `.si-figure { margin: 0 }` is
       declared in §16, later in this file and at the same specificity, so a
       single-class rule here loses the cascade to it. */
    /* The extra top margin is the verified stamp's room: it sits above the
       console's top edge rather than on top of its content. */
    .si-hero__grid > .si-heroviz { order: 5; margin-top: 2.75rem; }
    .si-hero__note  { order: 6; }

    /* =================================================================
       AND EVERY OTHER CHILD OF THE DISSOLVED COPY NEEDS AN ORDER TOO
       =================================================================
       `display: contents` above makes each of these a grid ITEM, and an
       item with no `order` defaults to 0 — which puts it AHEAD of the
       headline at order 1. The landing hero happens to contain only the
       six elements numbered above, so the gap was invisible until a
       second hero was built: `/merchant-payments` adds an eyebrow and a
       flow chain, and both jumped above the H1 on a phone while looking
       perfectly correct at 1440.

       THE EYEBROW KEEPS THE DEFAULT 0 deliberately — it belongs above the
       headline, and it is first in the markup.

       THE CHAIN TAKES 2, THE SAME AS THE LEDE. Order is a sort key, not a
       position: items sharing a value stay in document order, and the
       chain follows the lede there. That slots it between the lede and
       the CTA row without renumbering controls the landing page relies on.

       THE FIGURE TAKES 5 the same way. `.si-heroviz` is one particular
       hero figure; any `.si-figure` sitting directly in the grid belongs
       in the same slot. The child combinator is not decoration — see the
       note above the `.si-heroviz` rule. */
    .si-hero__chain { order: 2; }
    .si-hero__grid > .si-figure { order: 5; margin-top: 2.75rem; }
}

/* =====================================================================
   THE HEADLINE, RESOLVED
   =====================================================================
   The first pass capped this at 27px on a 390px phone, and the reasoning
   was sound for the markup it had: with a `<br>` the whole heading is ONE
   block, `text-wrap: balance` will not rebalance across the break
   (measured — `wrap`, `balance` and `pretty` all produce the identical
   282 / 136 split), so any larger size orphaned "PayMQR." on a third
   line. Right call, wrong markup.

   Each sentence is now its own BLOCK, so each balances independently and
   the second breaks 239 / 179. The size is free: 34px at 390 and 36px at
   430 against 27.5px before, and the hero finally out-weighs everything
   under it — which is the whole job of a hero.

   800 / -.04em / 1.06 are DISPLAY settings, not body settings. At 34px+
   the stack's default tracking is visibly loose and its default leading
   opens a channel between the two sentences; 16ch holds the measure so
   the first sentence cannot stretch to one thin line on a tablet. */
.si-hero__title {
    font-size: clamp(2.125rem, 1.5rem + 2.3vw, 2.5rem);
    font-weight: 800; letter-spacing: -.04em; line-height: 1.06;
    color: var(--si-navy); max-width: 16ch;
}
.si-hero__title > span { display: block; text-wrap: balance; }
/* The one viewport where 34px stops fitting "Payments go to you." on a
   single line: 320px leaves a 284px column and the line needs ~305px. */
@media (max-width: 359px) { .si-hero__title { font-size: 1.75rem; max-width: none; } }
/* 16px on a 46ch measure. The first pass had this at 15px across 34rem —
   small type on a long line, the least readable combination there is. */
/* 20px under a three-line 34px headline, not 16: at display size the
   headline's own descenders eat most of a 16px gap and the lede starts
   reading as a fourth line of it. */
.si-hero__lede { margin-top: 1.25rem; font-size: 1rem; line-height: 1.62; color: var(--si-muted); max-width: 46ch; }
/* The call to action is the hero's second focal point, so it gets real
   separation from the paragraph above it rather than paragraph spacing. */
.si-hero__cta { margin-top: 1.625rem; gap: var(--si-s2) var(--si-s5); }
/* ONE HEAVY CONTROL, ONE LIGHT ONE. Two equally weighted buttons make a
   visitor choose before they have read anything; a solid primary beside a
   quiet inline action does not. The secondary keeps its `si-btn--secondary`
   class (the suite asserts the pair by class and destination) and simply
   stops looking like a button. */
.si-hero__cta .si-btn--secondary {
    background: transparent; border-color: transparent; box-shadow: none;
    color: var(--si-navy-3); padding-left: .2rem; padding-right: .2rem;
}
.si-hero__cta .si-btn--secondary::after { content: "→"; margin-left: .1rem; transition: transform .18s ease; }
.si-hero__cta .si-btn--secondary:hover { color: var(--si-action-ink); background: transparent; border-color: transparent; }
.si-hero__cta .si-btn--secondary:hover::after { transform: translateX(2px); }
.si-hero__note { margin-top: var(--si-s4); color: var(--si-subtle); font-size: .78125rem; max-width: 48ch; line-height: 1.62; }
/* THE TRUST STRIP IS META, NOT CONTENT — four values at 11.5px reading as
   one object under the call to action. At 15px it was four 20px rows and
   the single heaviest thing between the headline and the product.

   IT PACKS, IT DOES NOT COLUMN. Two equal columns give each item ~145px of
   text and "Automated payment checks" needs 157px, so a forced grid wraps
   exactly one of the four onto a second line and the strip stops looking
   like a strip. Allowed to size to their content the four pack into two
   tidy lines at every phone width. */
/* A RULED META ROW, NOT FOUR MORE BULLETS. The strip sits under a hairline
   spanning the copy column, which CLOSES the hero's left half as a
   composition instead of letting it trail off into fine print. 12.5px is
   legible; the first pass's 11.5px was small for the sake of small.

   IT PACKS ON A PHONE AND COLUMNS ON DESKTOP. Left to pack at 1440 the
   four items fell 3 + 1, stranding "Success-page redirect" alone under a
   full line — a ragged second row reads as a mistake where a 2x2 block
   reads as a unit. Below 961px they pack 2 + 2 on their own. */
.si-hero__facts {
    list-style: none; margin-top: 1.625rem; padding-top: var(--si-s4);
    border-top: 1px solid rgba(var(--shadow-rgb), .08);
    display: flex; flex-wrap: wrap; gap: .5rem 1.15rem; max-width: 32rem;
}
@media (min-width: 961px) {
    .si-hero__facts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .55rem 1rem; max-width: 30rem; }
}
.si-hero__facts li { display: flex; gap: .4rem; align-items: center; color: var(--si-navy-3); font-size: .78125rem; font-weight: 600; letter-spacing: -.005em; }
.si-hero__facts .si-tick { flex: 0 0 auto; width: 14px; height: 14px; }
.si-tick { flex: 0 0 auto; width: 16px; height: 16px; color: var(--si-emerald); }

/* THE ONE PIECE OF DECORATION ON THE PAGE: a soft blue bloom behind the
   product visual, which is what stops a white card on an off-white ground
   reading as a floating rectangle. `isolation` keeps the negative z-index
   inside the figure so it can never slide behind the section itself. */
/* ONE DOMINANT PRODUCT VISUAL ON A PHONE. Stacked, the console AND a
   checkout card are two mocks before the page's first sentence; the same
   checkout is shown in full, at full width, two sections down. The markup
   stays — the suite asserts both visuals carry the customer's five facts —
   and the CSS decides which one a phone shows. */
/* ONE ENTRANCE, ON ONE ELEMENT. The product visual rises 8px and fades in
   over 260ms; the headline and the lede do NOT, because text a reader is
   waiting for should never arrive late. `both` fill means the reduced-
   motion block at the foot of this file — which collapses the duration to
   0.01ms — lands the figure on its FINAL state rather than hiding it. */
.si-heroviz { position: relative; isolation: isolate; animation: si-viz-in .26s ease-out both; }
@keyframes si-viz-in { from { opacity: 0; transform: translateY(8px); } }
.si-heroviz .si-quote { display: none; }
/* The bloom under the composition, drawn INSIDE the figure's own box — the
   first cut was `width: 128%` centred with a transform, which put its
   right edge 32px past a 390px viewport and gave the document a horizontal
   scrollbar for a gradient nobody can see. An ellipse sized in PERCENTAGES
   OF THE BOX reaches the same spread with nothing outside it. */
.si-heroviz::before {
    content: ""; position: absolute; z-index: -1; pointer-events: none;
    inset: -4% -2% 6%;
    background:
        radial-gradient(58% 54% at 52% 40%, rgba(var(--brand-rgb), .13), rgba(var(--brand-rgb), 0) 100%),
        radial-gradient(40% 40% at 18% 86%, rgba(16, 185, 129, .10), rgba(16, 185, 129, 0) 100%);
}

/* =====================================================================
   THE VERIFIED STAMP — THE HERO'S ONE ACCENT
   =====================================================================
   A product state, not a badge: the same emerald the console's Verified
   tile uses, on a white chip that sits ON the composition rather than
   beside it. One of exactly two overlays, because three floating fragments
   is a collage and not an art direction.

   PLACEMENT IS A COLLISION PROBLEM, NOT A TASTE ONE, AND IT DIFFERS BY
   WIDTH. On a phone the console fills the column edge to edge, so there is
   no clear air beside it and any vertical position lands on a payment row
   — the first cut clipped "₹2,400" off ORD-2049. It therefore straddles
   the TOP-RIGHT corner, half over the chrome bar (whose right third is
   empty now that the traffic-light dots are gone) and half above the card:
   a toast that just arrived, attached to the product, covering nothing.

   On desktop it moves OUT of the composition entirely, into the column gap
   at the console's left edge, level with the status tiles it is describing
   — and clear of the checkout card layered on the right, which is what the
   first cut landed on top of.

   ON A PHONE IT CLEARS THE CARD ALTOGETHER. The console runs edge to edge
   there, so EVERY position inside it lands on content: at the bottom it
   clipped "₹2,400" off a payment row, and at the top-right it clipped the
   address pill to "paymqr.com/merchant,". Sitting just above the top edge
   it reads as a toast resting on the surface, overlaps nothing, and the
   figure's own top margin gives it the room. */
.si-vstamp {
    position: absolute; z-index: 3; right: .25rem; top: -1.9rem;
    display: inline-flex; align-items: center; gap: .4rem;
    padding: .42rem .7rem .42rem .5rem; border-radius: 11px;
    background: #fff; color: var(--si-navy);
    font-size: .75rem; font-weight: 700; letter-spacing: -.012em; white-space: nowrap;
    box-shadow:
        0 0 0 1px rgba(var(--shadow-rgb), .06),
        0 2px 4px rgba(var(--shadow-rgb), .05),
        0 14px 28px -14px rgba(var(--shadow-rgb), .34);
}
.si-vstamp__tick {
    display: inline-flex; align-items: center; justify-content: center;
    width: 17px; height: 17px; border-radius: 50%; flex: 0 0 auto;
    background: var(--si-emerald-soft); color: var(--state-ok-ink);
    box-shadow: inset 0 0 0 1px var(--si-emerald-border);
}
.si-vstamp__tick svg { width: 11px; height: 11px; }

/* ---------- 8. Product visuals -------------------------------------------
   The composed console, checkout, poster and record mocks live in
   section 16. This slot keeps the small shared pieces they and the rest
   of the site share. */

.si-chip {
    display: inline-flex; align-items: center; gap: .3rem;
    padding: .18rem .5rem; border-radius: 999px;
    font-size: .6875rem; font-weight: 600; letter-spacing: .01em;
}
.si-chip--ok { background: var(--si-emerald-soft); color: var(--state-ok-ink); border: 1px solid var(--si-emerald-border); }
.si-chip--info { background: var(--si-info-soft); color: var(--si-info-text); border: 1px solid var(--si-info-border); }
.si-chip--wait { background: var(--state-warn-soft); color: var(--state-warn-ink); border: 1px solid var(--state-warn-border); }

/* ---------- 9. Cards, grids, feature blocks ------------------------------- */

.si-grid { display: grid; gap: var(--si-s4); grid-template-columns: minmax(0, 1fr); }
.si-grid--2, .si-grid--3, .si-grid--4 { grid-template-columns: minmax(0, 1fr); }

/* NO BORDER: `--si-shadow-sm` carries its own 1px ring since the elevation
   system landed, and a border on top of it drew every card edge twice. */
.si-card {
    background: var(--si-surface); border: 0;
    border-radius: var(--si-radius); padding: var(--si-s5);
    box-shadow: var(--si-shadow-sm);
}
.si-card--lift { transition: box-shadow .18s ease; }
.si-card--lift:hover { box-shadow: var(--si-shadow); }
.si-card__icon {
    display: inline-flex; align-items: center; justify-content: center;
    width: 38px; height: 38px; border-radius: 10px;
    background: var(--si-blue-soft); color: var(--si-action-ink);
    border: 1px solid var(--si-blue-border); margin-bottom: var(--si-s3);
}
.si-card__icon svg { width: 19px; height: 19px; }
.si-card__title { font-size: 1rem; font-weight: 650; color: var(--si-navy); }
.si-card__text { margin-top: var(--si-s2); color: var(--si-muted); font-size: .9375rem; }
.si-card__list { margin-top: var(--si-s3); list-style: none; display: flex; flex-direction: column; gap: .4rem; }
.si-card__list li { display: flex; gap: .45rem; color: var(--si-muted); font-size: .875rem; }
.si-card__list li::before { content: ""; flex: 0 0 auto; width: 5px; height: 5px; border-radius: 50%; background: var(--si-blue); margin-top: .55rem; }

/* MOBILE-FIRST: one column, and the two-column shapes are opted into at
   961px (foot of this file). Every `--visual` variant used to need naming
   inside the stacking query purely because it out-specified the single
   class it was overriding; declared this way round, none of them do. */
.si-split { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--si-s5); align-items: center; }

/* ---------- 10. Steps & flows --------------------------------------------- */

/* =====================================================================
   THE PROCESS IS A RAIL, NOT THREE CARDS
   =====================================================================
   Three bordered boxes, each an icon-less title over a paragraph, is the
   most recognisable shape on a generated landing page — and on a phone it
   was three 170px slabs for eleven words apiece.

   What replaces it owns no box at all: a numbered marker on a hairline
   rail, the step title beside it, one line of text under that. The rail
   runs vertically on a phone and horizontally from 721px, so the
   progression is read the way the device is held. */
.si-steps { list-style: none; display: grid; gap: 0; counter-reset: si-step; }
/* `align-content: start` IS LOAD-BEARING, NOT TIDINESS. Laid out in a row,
   every step is stretched to the tallest one, and a grid with auto rows
   distributes that spare height BETWEEN its rows — so each step's title sat
   at a different height depending on how long its own paragraph was. Three
   headings on three different baselines is the most visible alignment fault
   a three-up can have. */
.si-step { position: relative; display: grid; align-content: start; grid-template-columns: 1.75rem minmax(0, 1fr); column-gap: .8rem; padding-bottom: var(--si-s6); }
.si-step:last-child { padding-bottom: 0; }
/* THE RAIL FADES AT BOTH ENDS. A hard 1px line butting into two tiles
   draws attention to the joins; a line that arrives and leaves reads as
   continuous flow. */
.si-step:not(:last-child)::before {
    content: ""; position: absolute; left: .84375rem; top: 1.95rem; bottom: .3rem;
    width: 1px;
    background: linear-gradient(180deg, rgba(var(--shadow-rgb), .22), rgba(var(--shadow-rgb), .13) 55%, rgba(var(--shadow-rgb), .04));
}
/* A SQUARED TILE, NOT A CIRCLE. A numeral in a circle is a bullet; a
   numeral in a rounded square with a ring is a NODE, which is what a
   system diagram is made of. Mono figures because these are identifiers,
   not quantities. */
.si-step__num {
    grid-column: 1; grid-row: 1 / span 2; align-self: start;
    display: inline-flex; align-items: center; justify-content: center;
    width: 1.75rem; height: 1.75rem; border-radius: 9px;
    background: #fff; color: var(--si-navy);
    box-shadow: 0 0 0 1px rgba(var(--shadow-rgb), .09), 0 1px 2px rgba(var(--shadow-rgb), .05);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: .625rem; font-weight: 700; letter-spacing: 0;
    font-variant-numeric: tabular-nums;
}
/* THE FIRST NODE IS THE ENTRY POINT, so it carries the accent — the only
   state styling on the rail, and the thing that stops three identical
   tiles reading as a numbered list. */
.si-step:first-child .si-step__num {
    background: var(--si-navy); color: #fff;
    box-shadow: 0 0 0 1px var(--si-navy), 0 2px 6px -1px rgba(var(--shadow-rgb), .35);
}
.si-step__who { font-size: .625rem; text-transform: uppercase; letter-spacing: .1em; color: var(--si-subtle); font-weight: 700; }
.si-step__title { grid-column: 2; grid-row: 1; align-self: center; margin: 0; font-size: 1rem; font-weight: 700; letter-spacing: -.016em; color: var(--si-navy); }
.si-step__text { grid-column: 2; grid-row: 2; margin-top: .35rem; color: var(--si-muted); font-size: .875rem; line-height: 1.6; max-width: 40ch; }

/* =====================================================================
   THE VERIFICATION FLOW, AS A RAIL
   =====================================================================
   Four stages: what the customer does, what PayMQR does, what moves, and
   where the customer ends up. On a phone that was four full-width pills
   with a rotated arrow glyph between them — 240px of chrome for eight
   words.

   Here each stage is a dot on a rail with a compact chip beside it, and
   the `<span class="si-flow__arrow">` between stages stops being a glyph
   and BECOMES the rail segment (`font-size: 0` drops the arrow, the box
   stays). Nothing is added to the markup and the four-node reading order
   the suite pins is untouched. From 721px it is a horizontal row again
   and the arrow is an arrow. */
.si-flow { list-style: none; display: grid; gap: 0; }
.si-flow li { display: grid; grid-template-columns: 1.125rem minmax(0, 1fr); grid-template-rows: auto auto auto; column-gap: .6rem; }
/* The stage marker. Always the middle row, so it lines up with its node
   whichever side of the node the connector sits on. */
.si-flow li::after {
    content: ""; grid-column: 1; grid-row: 2; justify-self: center; align-self: center;
    width: 7px; height: 7px; border-radius: 50%;
    border: 1.5px solid var(--si-border-strong); background: #fff;
}
.si-flow li:last-child::after { background: var(--si-navy); border-color: var(--si-navy); }
/* =====================================================================
   THE CONNECTOR GOES WHERE THE MARKUP PUTS IT, AND THE TWO PAGES DISAGREE
   =====================================================================
   The landing page writes `arrow, node` — the arrow introduces the stage
   after it. /how-it-works writes `node, arrow` — the arrow trails the
   stage before it. Both are correct as prose; pinning the connector to
   row 1 drew a segment ABOVE "Create" on /how-it-works and none below
   "Check", which reads as a rail that starts nowhere and stops early.

   So position is taken from the ORDER, not assumed: an arrow that opens
   its item sits above the node, an arrow that follows one sits below. */
.si-flow__arrow {
    grid-column: 1; justify-self: center;
    font-size: 0; line-height: 0; width: 1px; height: .8rem;
    background: var(--si-border-strong);
}
.si-flow__arrow:first-child { grid-row: 1; }
.si-flow__node + .si-flow__arrow { grid-row: 3; }
.si-flow__node {
    grid-column: 2; grid-row: 2; justify-self: start;
    display: inline-block; padding: .3rem .7rem; border-radius: 8px;
    background: #fff; border: 1px solid var(--si-border);
    font-size: .78125rem; font-weight: 600; color: var(--si-navy);
}
.si-flow__node--end { background: var(--si-navy); color: #fff; border-color: var(--si-navy); }
/* The same flow on navy: the nodes go translucent and the LAST one — the
   merchant's own page — is the solid one, because that is the end of the
   sentence the row is telling. */
/* =====================================================================
   THE SECOND STAGE IS THE ONE PAYMQR SELLS, SO IT IS THE ONE THAT LOOKS
   DIFFERENT
   =====================================================================
   Four identical chips describe a sequence; they do not say which part of
   it is the product. "PayMQR checks" is the only stage the merchant is
   buying, so it carries the emerald — the same success colour used on the
   Verified tile and the hero stamp, and used NOWHERE else on this rail.

   The last chip stays solid white because it is the merchant's OWN page,
   not PayMQR's: a different kind of emphasis, and the reason the two
   accents do not compete. */
.si-flow--invert .si-flow__node { background: rgba(255, 255, 255, .055); border-color: rgba(255, 255, 255, .17); color: var(--line); }
.si-flow--invert li:nth-child(2) .si-flow__node {
    background: rgba(16, 185, 129, .13); border-color: rgba(52, 211, 153, .42);
    color: #6EE7B7; font-weight: 700;
}
.si-flow--invert .si-flow__node--end { background: #fff; border-color: #fff; color: var(--si-navy); font-weight: 700; }
.si-flow--invert .si-flow__arrow { background: rgba(255, 255, 255, .22); color: var(--ink-subtle); }
.si-flow--invert li::after { background: transparent; border-color: rgba(255, 255, 255, .32); }
.si-flow--invert li:nth-child(2)::after { background: #34D399; border-color: #34D399; box-shadow: 0 0 0 4px rgba(52, 211, 153, .18); }
.si-flow--invert li:last-child::after { background: #fff; border-color: #fff; }

/* ---------- 11. Pricing --------------------------------------------------- */

.si-plans { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr)); gap: var(--si-s3); max-width: 44rem; margin: 0 auto; }
/* THE BORDER IS 2px ON EVERY CARD, and only its COLOUR marks the
   recommended one. With a 1px border on two cards and 2px on the third,
   the recommended card was 2px narrower inside — enough, at 1024px, to
   wrap one feature label onto a second line and knock the three cards'
   rows out of alignment. Reserving the width on all three fixes it at
   every width at once. */
/* THE BORDER IS A RING, AND THE RECOMMENDED CARD IS LIFTED RATHER THAN
   OUTLINED. A 2px blue rectangle around one of three cards is how every
   pricing table since 2014 has marked its middle tier; a card that sits
   physically in front of its neighbours says the same thing without
   drawing a frame. */
/* =====================================================================
   A PLAN IS A CARD WITH AN EDGE, NOT A SHADOW THAT HINTS AT ONE
   =====================================================================
   The card drew no border at all: `--si-shadow-sm` opens with
   `--si-ring-hair`, a 1px ring at 5.5% ink, and against the near-white
   `--ground` (#FFFDF7) that reads as a smudge rather than as a boundary.
   Four plans a merchant is comparing need four unmistakable containers.

   A REAL `border`, NOT A RING. A box-shadow ring paints outside the box
   and cannot be given a different width per card without the cards
   ending up different sizes; a border is part of the box, so `border-box`
   keeps every card identical on the outside while Growth carries a
   heavier edge.

   THE RING COMES OFF THE SHADOW with it. Left in, the two would paint one
   inside the other and every card would have a visible double edge.

   The two edge colours are named here so a card carries its own contract
   and the hover rule below has something to refer to rather than a second
   literal. `--hairline-strong` is the brand layer's own next step down,
   which is what "slightly darker" should mean. */
.si-plan {
    --si-plan-edge: #E7E1D6;
    --si-plan-edge-hover: var(--hairline-strong);

    position: relative; display: flex; flex-direction: column;
    background: #fff;
    border: 1px solid var(--si-plan-edge);
    border-radius: var(--si-radius);
    padding: var(--si-s5) var(--si-s4);
    box-shadow: 0 1px 2px rgba(var(--shadow-rgb), .04);
    transition: border-color .18s ease, box-shadow .18s ease, transform .18s ease;
}

/* HOVER IS A POINTER AFFORDANCE, so it is gated on one. `.si-plan:hover`
   used to apply on touch as well, where it fires on tap and sticks.

   THE BORDER WIDTH NEVER CHANGES — only its colour. Thickening an edge on
   hover moves every word inside the card by a pixel, which is the layout
   shift this brief rules out; the lift is a transform, which composites
   and reflows nothing. */
@media (hover: hover) {
    .si-plan:hover {
        border-color: var(--si-plan-edge-hover);
        box-shadow:
            0 1px 2px rgba(var(--shadow-rgb), .05),
            0 10px 24px -14px rgba(var(--shadow-rgb), .26);
        transform: translateY(-2px);
    }
}

/* The state survives; the travel does not. */
@media (prefers-reduced-motion: reduce) {
    .si-plan { transition: border-color .18s ease, box-shadow .18s ease; }
    .si-plan:hover { transform: none; }
}
.si-plan--featured { box-shadow: var(--si-shadow); }
.si-plan__head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--si-s3); }
.si-plan__name { font-size: .78125rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--si-subtle); }
/* THE PRICE IS THE CARD'S HEADLINE, so it is set like one — display size,
   display tracking, tabular figures so three cards' prices align on their
   own rhythm. */
/* The price and its cycle arrive as ONE catalogue string ("₹1,999 / month")
   the view may only echo, so the hierarchy has to come from the setting
   rather than from splitting it: display size, tight tracking, tabular
   figures, and a rule underneath that separates the commitment from the
   entitlements it buys. */
.si-plan__price {
    margin-top: .35rem; padding-bottom: var(--si-s4);
    font-size: 1.9375rem; font-weight: 780; line-height: 1.08;
    color: var(--si-navy); letter-spacing: -.042em; font-variant-numeric: tabular-nums;
}
.si-plan__cycle { margin-top: .1rem; color: var(--si-subtle); font-size: .75rem; }
.si-plan__desc { margin-top: var(--si-s3); color: var(--si-muted); font-size: .8125rem; }
.si-plan__features { margin-top: 0; padding-top: var(--si-s4); border-top: 1px solid rgba(var(--shadow-rgb), .08); list-style: none; display: flex; flex-direction: column; gap: .7rem; }
.si-plan__row { display: flex; align-items: baseline; justify-content: space-between; gap: var(--si-s3); font-size: .8125rem; line-height: 1.4; }
.si-plan__label { color: var(--si-muted); }
.si-plan__value { font-weight: 650; color: var(--si-navy); font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; }
/* NO RULE ABOVE THE BUTTON. Two hairlines in one card — one under the
   price and one over the foot — chopped it into three boxed registers. The
   entitlement list ends, there is air, and then the action. */
.si-plan__foot { margin-top: var(--si-s5); padding-top: 0; border-top: 0; }
.si-plan__foot .si-btn { width: 100%; }
/* The helper belongs TO the button — 8px under it, and quieter, so it reads
   as a footnote on the action rather than as a fifth feature row. */
.si-plan__note { margin-top: .5rem; font-size: .71875rem; line-height: 1.45; color: var(--si-subtle); text-align: center; }

.si-note {
    display: flex; gap: var(--si-s3); padding: var(--si-s4);
    background: var(--si-blue-soft); border: 1px solid var(--si-blue-border);
    border-radius: var(--si-radius); color: var(--state-info-ink); font-size: .8125rem; line-height: 1.6;
}
.si-note--plain { background: var(--si-bg-alt); border-color: var(--si-border); color: var(--si-muted); }
.si-note svg { flex: 0 0 auto; width: 18px; height: 18px; margin-top: .15rem; }

/* ---------- 12. FAQ / accordion ------------------------------------------- */

/* =====================================================================
   ROWS WITH SEPARATORS, NOT A STACK OF CARDS
   =====================================================================
   Five bordered, shadowed, rounded boxes for five one-sentence answers
   is five times the chrome the content needs. A hairline between rows
   says the same thing, and the list reads as ONE object — which is what
   an FAQ is.

   The marker is a rotating chevron drawn in CSS, so the transition is a
   real 180ms rotate rather than a "+" swapping to a "-" on a frame. */
.si-faq { display: flex; flex-direction: column; border-top: 1px solid var(--si-border); }
.si-faq__item { border-bottom: 1px solid rgba(var(--shadow-rgb), .09); }
.si-faq { border-top-color: rgba(var(--shadow-rgb), .09); }
.si-faq__q {
    list-style: none; cursor: pointer; display: flex; align-items: center; justify-content: space-between;
    gap: var(--si-s4); padding: 1.05rem .125rem;
    font-weight: 650; color: var(--si-navy); font-size: .9375rem; line-height: 1.45; letter-spacing: -.015em;
    transition: color .18s ease;
}
.si-faq__q:hover { color: var(--si-action-ink); }
.si-faq__q::-webkit-details-marker { display: none; }
.si-faq__q::after {
    content: ""; flex: 0 0 auto; width: 7px; height: 7px;
    border-right: 1.5px solid var(--si-subtle); border-bottom: 1.5px solid var(--si-subtle);
    transform: rotate(45deg) translate(-2px, -2px); transform-origin: center;
    transition: transform .18s ease, border-color .18s ease;
}
.si-faq__item[open] .si-faq__q { color: var(--si-navy); }
.si-faq__item[open] .si-faq__q::after { transform: rotate(225deg) translate(-2px, -2px); border-color: var(--si-action-graphic); }
.si-faq__a { padding: 0 2rem 1.1rem .125rem; color: var(--si-muted); font-size: .875rem; line-height: 1.65; max-width: 62ch; animation: si-faq-in .18s ease-out both; }
@keyframes si-faq-in { from { opacity: 0; transform: translateY(-3px); } }
.si-faq__a p + p { margin-top: var(--si-s3); }

/* ---------- 13. Prose (legal & long-form) --------------------------------- */

.si-prose { color: var(--si-muted); font-size: .9688rem; }
.si-prose h2 { font-size: 1.25rem; margin-top: var(--si-s7); }
.si-prose h2:first-child { margin-top: 0; }
.si-prose h3 { font-size: 1rem; margin-top: var(--si-s5); }
.si-prose p { margin-top: var(--si-s3); }
.si-prose ul, .si-prose ol { margin-top: var(--si-s3); padding-left: 1.25rem; display: flex; flex-direction: column; gap: .4rem; }
.si-prose li { padding-left: .15rem; }
.si-prose strong { color: var(--si-navy); }
.si-prose__meta { margin-bottom: var(--si-s6); padding-bottom: var(--si-s4); border-bottom: 1px solid var(--si-border); color: var(--si-subtle); font-size: .875rem; }
.si-toc { list-style: none; display: flex; flex-wrap: wrap; gap: var(--si-s2) var(--si-s4); margin-bottom: var(--si-s6); }
.si-toc a { font-size: .875rem; text-decoration: none; }
.si-toc a:hover { text-decoration: underline; }

/* ---------- 14. Contact --------------------------------------------------- */

.si-contact { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--si-s4); }

/* ---------- 15. Code, utilities & responsive ------------------------------ */

/* The API example is a SURFACE too — the same lit navy the dark section
   and the QR panel use. A flat var(--ink) block beside two lit panels looked
   like a different design system had been pasted in. */
.si-code {
    position: relative;
    background: var(--si-navy-surface); color: var(--line);
    border-radius: var(--si-radius);
    padding: 1.05rem 1.1rem; overflow-x: auto;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: .71875rem; line-height: 1.75; margin: 0;
    box-shadow: 0 1px 2px rgba(var(--shadow-rgb), .2), 0 16px 32px -20px rgba(var(--shadow-rgb), .5);
}
/* The same hairline of light the QR panel and the closing band carry, so
   all three dark surfaces are lit from the same direction. */
.si-code::before {
    content: ""; position: absolute; left: 0; right: 0; top: 0; height: 1px; pointer-events: none;
    border-radius: inherit;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .2) 25%, rgba(255, 255, 255, .2) 75%, transparent);
}
.si-code b { color: var(--si-action-ink-dark); font-weight: 600; }
.si-code i { color: #6EE7B7; font-style: normal; }
.si-code span { color: var(--si-on-dark-subtle); }

.si-mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: .9em; }
.si-muted { color: var(--si-muted); }
.si-small { font-size: .75rem; line-height: 1.6; }
.si-center { text-align: center; }
.si-mt-3 { margin-top: var(--si-s3); }
.si-mt-4 { margin-top: var(--si-s4); }
.si-mt-5 { margin-top: var(--si-s5); }
.si-mt-6 { margin-top: var(--si-s6); }
.si-sr {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ======================================================================
   STATUS LANGUAGE
   Two states, deliberately unlike each other. "Live" is emerald because
   emerald means done everywhere else in this system; "Coming soon" is
   amber because it must never be mistakable for done at a glance, in a
   screenshot, or by someone who does not read the label.
   ====================================================================== */
.si-status {
    display: inline-flex; align-items: center; gap: .3rem;
    padding: .18rem .5rem; border-radius: 6px; white-space: nowrap;
    font-size: .625rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
}
.si-status--live { background: var(--si-emerald-soft); color: var(--state-ok-ink); border: 1px solid var(--si-emerald-border); }
.si-status--soon { background: var(--state-warn-soft); color: var(--state-warn-ink); border: 1px solid var(--state-warn-border); }
.si-status--planned { background: var(--si-bg-alt); color: var(--si-navy-3); border: 1px solid var(--si-border-strong); }
.si-status--lg { font-size: .75rem; padding: .35rem .85rem; }

/* --- Pricing ------------------------------------------------------------ */
/* Equal-height cards so the three "Get started" buttons sit on one line
   however many feature rows a tier has — the foot is pushed down rather
   than the list padded out. */
/* One column until 881px (see §19): three price cards stop being readable
   long before they stop fitting. The extra row gap is clearance for the
   "Recommended" flag, which sits half outside its own card. */
.si-plans--three { grid-template-columns: minmax(0, 1fr); max-width: 30rem; gap: 1.25rem; align-items: stretch; }
.si-plans--three .si-plan__foot { margin-top: auto; padding-top: var(--si-s4); }
@media (min-width: 881px) { .si-plans--three { max-width: 64rem; } }
/* A phone card is read one at a time, so it does not need a desktop card's
   internal air: 20px of waist and a shorter gap under the price take ~46px
   off each of the three without touching a single type size. */
@media (max-width: 880px) {
    .si-plan { padding: var(--si-s4) 1.25rem; }
    .si-plan__price { padding-bottom: var(--si-s3); }
    .si-plan__features { padding-top: var(--si-s3); gap: .6rem; }
    .si-plan__foot { margin-top: var(--si-s4); }
    .si-free { padding: .85rem 1rem; }
}
/* THE RECOMMENDED CARD IS RAISED, NOT MOVED.

   It used to sit 6px higher than its neighbours, which broke the one thing
   a three-card price comparison has to get right: the prices and all four
   entitlement rows no longer shared a baseline across the row, so a reader
   comparing "Team members" had to scan diagonally. The blue ring, the
   deeper cast and the flag already say which one PayMQR recommends —
   moving it off the row only made the row harder to read. */
/* THE RECOMMENDED CARD CARRIES THE BRAND EDGE AT FULL STRENGTH.

   It was a 1.5px ring at 45% brand — a wash of the yellow rather than the
   yellow. `--si-blue` is `--action-fill` is `--brand-500` (#FFC400), the
   same value the CTA inside this card is filled with, so the card and its
   button now agree instead of nearly agreeing.

   ONLY THIS CARD IS YELLOW. The other three keep the neutral edge; the
   warm cast below is a shadow, not a border, and it is what separates
   "recommended" from "also for sale". */
.si-plan--popular {
    border: 1.5px solid var(--si-blue);
    box-shadow:
        /* THE HALF PIXEL BLINK THROWS AWAY, PUT BACK AS A RING.
           Chrome FLOORS `border-width` to whole CSS pixels — measured:
           a 1.5px border yields the same 42px box a 1px border does, at
           DPR 1 and DPR 2 alike. Declared alone it would leave Growth's
           edge exactly as heavy as the other three, distinguished only by
           hue, which is not the emphasis this card is meant to carry.
           A box-shadow spread DOES render fractionally, so a .5px ring in
           the same token completes the 1.5px the design asks for. It
           paints outside the border box, so it adds no size and cannot
           shift the grid — the four cards stay identical on the outside. */
        0 0 0 .5px var(--si-blue),
        0 2px 4px rgba(var(--shadow-rgb), .05),
        0 20px 44px -24px rgba(var(--brand-rgb), .45);
}

@media (hover: hover) {
    /* One step darker on the same hue — `--brand-600` is the fill the
       primary button already moves to on hover, so the card and the
       control inside it react together. */
    .si-plan--popular:hover {
        border-color: var(--brand-600);
        box-shadow:
            0 0 0 .5px var(--brand-600),
            0 2px 4px rgba(var(--shadow-rgb), .06),
            0 24px 50px -24px rgba(var(--brand-rgb), .55);
    }
}
.si-plan__flag {
    position: absolute; top: 0; left: 50%; transform: translate(-50%, -50%);
    padding: .25rem .7rem; border-radius: 999px; background: var(--si-blue); color: var(--si-on-action);
    font-size: .5625rem; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; white-space: nowrap;
}


/* =========================================================================
   16. PRODUCT VISUALS  (Public Website / P01A)
   =========================================================================
   Four composed mocks — the merchant console, the hosted checkout, a
   merchant QR poster and a single payment record. All of them are HTML,
   CSS and inline SVG: no screenshot, no image request, no script.

   THEY BORROW THE MERCHANT CONSOLE'S OWN COLOUR LANGUAGE rather than the
   marketing palette, because the whole point is that a visitor is looking
   at the real product. Those values are declared locally on `.si-console`
   and friends instead of in `:root`, so the console greys can never leak
   into a marketing surface and quietly desaturate it.

   Every mock is `aria-hidden` inside a labelled `role="img"` wrapper: the
   figures are decoration for a sentence the page already makes, and a
   screen reader walking a fake table row by row would be reading out
   invented data as though it mattered.
   ========================================================================= */

.si-figure { margin: 0; }
.si-figure__caption {
    margin-top: var(--si-s4); font-size: .71875rem; line-height: 1.6;
    color: var(--si-subtle); text-align: center;
}
/* AFTER THE BASE RULE, NOT BEFORE IT. Same specificity, so source order
   decides — declared above, this lost and the caption stayed #6B7280 on
   navy: 3.7:1, under the floor, and invisible as a bug because grey on
   navy still looks deliberate. var(--si-on-dark-subtle) on navy is 7.1:1. */
.si-figure__caption--invert { color: var(--si-on-dark-subtle); }

/* One status dot. Meaning is carried by the word beside it; the dot is
   the same shorthand the merchant console uses on its own badges. */
.si-dot {
    display: inline-block; flex: 0 0 auto;
    width: 6px; height: 6px; border-radius: 50%; margin-right: .4rem;
    background: var(--si-on-dark-subtle); vertical-align: middle;
}
.si-dot.is-ok, .si-dot.is-verified { background: var(--state-ok); }
.si-dot.is-wait, .si-dot.is-review { background: var(--state-warn); }
.si-dot.is-idle { background: var(--si-on-dark-subtle); }

/* --- The merchant console ------------------------------------------------ */

/* =====================================================================
   THE CONSOLE IS THE PAGE'S HERO OBJECT, SO IT IS BUILT LIKE ONE
   =====================================================================
   No `border`. A 1px ring plus a four-stop cast (see `--si-shadow-lg`)
   reads as a surface lifted off the page; a hairline border plus a soft
   blur reads as a sticker with a drop shadow, which is what it was.

   The `::after` is a one-pixel INTERNAL highlight along the top edge —
   the oldest trick in interface rendering and still the thing that most
   cleanly separates "a white box" from "a lit surface". It is inside the
   radius, `pointer-events: none`, and paints nothing anywhere else. */
.si-console {
    --c-bg: var(--ground-alt);
    --c-line: var(--line);
    --c-ink: var(--ink);
    --c-muted: var(--ink-muted);
    --c-subtle: var(--ink-subtle);
    --c-blue: var(--si-action-ink);
    --c-blue-active: #E8EEFF;

    position: relative;
    background: #fff;
    border-radius: var(--si-radius-lg); box-shadow: var(--si-shadow-lg);
    overflow: hidden;
}
.si-console::after {
    content: ""; position: absolute; inset: 0; pointer-events: none;
    border-radius: inherit;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .9), inset 0 0 0 1px rgba(var(--shadow-rgb), .035);
}

/* ONE HAIRLINE BAR CARRYING THE REAL PATH — that is the whole chrome.
   The traffic-light dots are gone from the markup: they are the web's most
   recognisable "this is a mockup" signal, and they drew somebody else's
   browser on top of PayMQR's product. The pill is centred, because with
   nothing to its left there is nothing to align it to. */
.si-console__chrome {
    display: flex; align-items: center; justify-content: center;
    padding: .38rem .7rem;
    background: linear-gradient(180deg, var(--surface), var(--ground-alt));
    border-bottom: 1px solid var(--c-line);
}
.si-console__dot { display: none; }
.si-console__url {
    padding: .16rem .7rem; border-radius: 7px;
    background: #fff; box-shadow: 0 0 0 1px rgba(var(--shadow-rgb), .06);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: .625rem; letter-spacing: -.01em; color: var(--ink-subtle);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%;
}

/* THE RAIL IS A NAVIGATION THE READER CANNOT USE. On a phone it costs a
   third of the mock and earns nothing, so the console shows the screen it
   is illustrating instead; 721px brings the sidebar back. */
.si-console__app { display: grid; grid-template-columns: minmax(0, 1fr); background: var(--c-bg); }

.si-console__rail {
    display: none; flex-direction: column; gap: .1rem;
    padding: .8rem .55rem; background: var(--ground); border-right: 1px solid var(--c-line);
}
.si-console__brand {
    padding: .1rem .45rem .7rem; font-size: .9375rem;
    font-weight: 750; letter-spacing: -.03em; line-height: 1;
}
/* The illustration's lockup is the real rail's, at illustration scale:
   the approved mark beside the word. Square box, square source — nothing
   here can distort it. */
.si-console__brand { display: flex; align-items: center; gap: 6px; }
.si-console__mark { display: block; width: 18px; height: 18px; flex: 0 0 auto; object-fit: contain; }
.si-console__word { color: var(--c-ink); font-weight: inherit; }

.si-console__nav {
    display: flex; align-items: center; gap: .45rem;
    padding: .38rem .45rem; border-radius: 6px;
    font-size: .6875rem; font-weight: 500; color: var(--c-muted);
    white-space: nowrap; overflow: hidden;
}
.si-console__nav svg { flex: 0 0 auto; width: 13px; height: 13px; }
.si-console__nav.is-active { background: var(--c-blue-active); color: var(--c-blue); font-weight: 650; }

.si-console__main { padding: .8rem; display: grid; gap: .6rem; min-width: 0; }

.si-console__head { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; }
.si-console__h { font-size: .875rem; font-weight: 700; color: var(--c-ink); letter-spacing: -.01em; }
.si-console__pill {
    padding: .12rem .45rem; border-radius: 6px;
    background: #fff; box-shadow: 0 0 0 1px var(--c-line);
    font-size: .5625rem; font-weight: 700; letter-spacing: .07em;
    text-transform: uppercase; color: var(--c-subtle);
}

.si-console__kpis { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .45rem; }
/* THE THREE FIGURES SIT ON ONE BASELINE. "Awaiting payment" is the only
   label that takes two lines, so with auto rows its number dropped 12px
   below the other two and the row read as misaligned rather than as three
   tiles. A flexible label row and a bottom-aligned value fixes it without
   shortening anybody's label. */
/* A 3px STATUS SPINE, NOT A COLOURED BORDER. Drawn as a pseudo-element
   inside the tile so the tile keeps one uniform 1px ring on all four
   sides — a thick left border makes the content 3px narrower than its
   neighbours and the row stops aligning. */
.si-console__kpi {
    position: relative; overflow: hidden;
    display: grid; grid-template-rows: 1fr auto; gap: .1rem; padding: .5rem .6rem .5rem .75rem;
    background: linear-gradient(180deg, #FFFFFF, var(--surface));
    box-shadow: 0 0 0 1px var(--c-line); border-radius: 9px;
}
.si-console__kpi::before {
    content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
    background: var(--line-strong);
}
.si-console__kpi.is-ok::before { background: var(--state-ok); }
.si-console__kpi.is-wait::before { background: var(--state-warn); }
.si-console__kpi.is-idle::before { background: var(--line-strong); }
.si-console__kpilabel { font-size: .5625rem; text-transform: uppercase; letter-spacing: .06em; color: var(--c-subtle); font-weight: 700; }
/* The three figures are the most product-looking thing on the page, so
   they get display treatment: heavier, tighter, tabular. */
.si-console__kpivalue { font-size: 1.5rem; font-weight: 780; color: var(--c-ink); line-height: 1.05; letter-spacing: -.03em; font-variant-numeric: tabular-nums; }

.si-console__caption {
    margin-top: .15rem; font-size: .5625rem; font-weight: 700;
    text-transform: uppercase; letter-spacing: .07em; color: var(--c-subtle);
}

.si-console__table {
    width: 100%; border-collapse: separate; border-spacing: 0; table-layout: fixed;
    background: #fff; box-shadow: 0 0 0 1px var(--c-line); border-radius: 9px;
    overflow: hidden; font-size: .6875rem; color: var(--c-muted);
}
.si-console__table td { padding: .42rem .55rem; border-top: 1px solid var(--c-line); white-space: nowrap; }
.si-console__table tr:first-child td { border-top: 0; }
.si-console__ref { font-weight: 650; color: var(--c-ink); width: 27%; }
.si-console__amt { text-align: right; color: var(--c-ink); font-weight: 650; font-variant-numeric: tabular-nums; width: 22%; }
.si-console__at { text-align: right; color: var(--c-subtle); width: 17%; }

/* --- The hosted checkout -------------------------------------------------- */

.si-pay {
    position: relative; max-width: 20.5rem; margin: 0 auto;
    background: #fff;
    border-radius: var(--si-radius-lg); box-shadow: var(--si-shadow-lg);
    overflow: hidden;
}
.si-pay::after {
    content: ""; position: absolute; inset: 0; pointer-events: none; border-radius: inherit;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .9), inset 0 0 0 1px rgba(var(--shadow-rgb), .035);
}
.si-pay__top {
    display: flex; align-items: center; justify-content: space-between; gap: var(--si-s3);
    padding: .7rem .9rem;
    border-bottom: 1px solid var(--si-border);
}
.si-pay__eyebrow { font-size: .5625rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--si-subtle); }
.si-pay__who { margin-top: .05rem; font-size: .875rem; font-weight: 700; color: var(--si-navy); letter-spacing: -.01em; }
.si-pay__timer { flex: 0 0 auto; font-size: .625rem; font-weight: 650; color: var(--si-navy-3); white-space: nowrap; }
.si-pay__body { padding: .85rem .9rem 1rem; text-align: center; }
.si-pay__body .si-pay__eyebrow { display: block; }
.si-pay__amount {
    margin-top: .1rem; font-size: 1.75rem; font-weight: 700; line-height: 1.15;
    color: var(--si-navy); letter-spacing: -.035em; font-variant-numeric: tabular-nums;
}
.si-pay__plate {
    margin: .7rem auto 0; width: 118px; padding: .4rem;
    background: #fff; border: 1px solid var(--si-border); border-radius: 11px;
}
.si-pay__plate svg { width: 100%; height: auto; }
.si-pay__hint { margin-top: .5rem; font-size: .6875rem; font-weight: 650; color: var(--si-navy-3); }
.si-pay__body .si-apps { margin-top: .5rem; }
.si-pay__cta {
    display: block; margin-top: .8rem;
    padding: .6rem 1rem; border-radius: var(--si-radius-sm);
    background: var(--si-blue); color: var(--si-on-action);
    font-size: .78125rem; font-weight: 650;
}

/* --- The UPI app marks ----------------------------------------------------
   THE PRODUCT'S OWN ROW, and sized the way the live checkout sizes it:
   height only, width auto. The four files are brand WORDMARKS between
   2.5:1 and 3.3:1 wide, so a fixed width letterboxes them — the exact
   defect Checkout P04 had to fix on gpay.svg. `flex-wrap` is the
   guarantee that the row folds rather than overflows at any width. */

.si-apps {
    display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
    gap: .45rem .7rem; margin: 0; padding: 0; list-style: none;
}
.si-apps li { display: flex; align-items: center; min-width: 0; }
.si-apps img { height: 15px; width: auto; display: block; object-fit: contain; flex: 0 0 auto; }
.si-apps--sm { justify-content: flex-start; gap: .3rem .5rem; }
.si-apps--sm img { height: 13px; }

/* --- The hero composition -------------------------------------------------
   Two surfaces, one figure: the merchant's dashboard and the customer's
   checkout, layered so the two read as one object rather than as two
   unrelated cards.

   THE WHOLE COMPOSITION IS A DESKTOP SHAPE and now lives in §19 under
   `min-width: 961px`. It used to live here, unconditioned — which meant a
   phone, where the checkout card is not drawn at all, still paid the 48px
   of empty console floor that the overlap needs to land on. That gap was
   the largest single piece of dead space in the mobile hero. */

.si-quote {
    position: relative;
    display: grid; grid-template-columns: minmax(0, 1fr) auto;
    gap: var(--si-s4); align-items: center;
    padding: .9rem 1rem;
    background: #fff;
    border-radius: var(--si-radius);
    box-shadow:
        0 0 0 1px rgba(var(--shadow-rgb), .07),
        0 2px 4px rgba(var(--shadow-rgb), .06),
        0 24px 44px -22px rgba(var(--shadow-rgb), .34);
}
.si-quote::after {
    content: ""; position: absolute; inset: 0; pointer-events: none; border-radius: inherit;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .9);
}
.si-quote__eyebrow { font-size: .5625rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--si-subtle); }
.si-quote__who { margin-top: .1rem; font-size: .8125rem; font-weight: 700; color: var(--si-navy); letter-spacing: -.01em; }
.si-quote__amount {
    margin-top: .1rem; font-size: 1.5rem; font-weight: 700;
    color: var(--si-navy); letter-spacing: -.03em; font-variant-numeric: tabular-nums; line-height: 1.15;
}
.si-quote__cta {
    display: block; margin-top: .55rem; padding: .5rem .75rem;
    border-radius: var(--si-radius-sm); background: var(--si-blue); color: var(--si-on-action);
    font-size: .75rem; font-weight: 650; text-align: center; white-space: nowrap;
}
.si-quote__main .si-apps { margin-top: .55rem; }
.si-quote__side { display: grid; justify-items: center; gap: .3rem; }
.si-quote__plate {
    display: block; width: 84px; padding: .35rem;
    background: #fff; border: 1px solid var(--si-border); border-radius: 10px;
}
.si-quote__plate svg { width: 100%; height: auto; display: block; }
.si-quote__scan { font-size: .5625rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--si-subtle); }

/* --- Payment links & the merchant QR poster ------------------------------- */

/* =====================================================================
   THE TWO WAYS TO BE PAID, AS BENTO MODULES
   =====================================================================
   Two panels, and on a phone they were 350px and 510px tall for four
   sentences between them. The copy is unchanged; what shrank is
   everything around it — a 30px icon tile ON THE TITLE LINE rather than
   above it, 13px body, and a product detail (the link bar, the QR
   poster) that illustrates the feature instead of restating it. */
/* `start`, NOT the default stretch: in an open two-column spread the
   columns are allowed to end where their content ends. Stretched, the
   shorter one grew a tail of empty space to match the taller. */
.si-duo { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--si-s4); align-items: start; }
/* What the panel IS, in two words, under its name. It replaces a
   paragraph that said the same thing in a sentence. */
.si-duo__kind { margin-top: .05rem; font-size: .625rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--si-action-ink); }
/* =====================================================================
   NO CARD AROUND EITHER OF THEM
   =====================================================================
   Both panels now contain a real piece of product interface — a link field
   with its Copy action and a segmented type control on one side, an
   acceptance panel with a live-looking code on the other. Wrapping each of
   those in a second rounded white box put a surface inside a surface and
   turned two product demonstrations back into two feature cards.

   What separates them is a rule: a hairline between them when they stack,
   a vertical one when they sit side by side (§19). That is how an editorial
   spread divides two columns, and it costs no chrome at all. */
.si-duo__panel {
    display: flex; flex-direction: column;
    padding: 0 0 var(--si-s5);
}
.si-duo__panel + .si-duo__panel {
    padding-top: var(--si-s5); border-top: 1px solid rgba(var(--shadow-rgb), .10);
}
.si-duo__panel:last-child { padding-bottom: 0; }
.si-duo__head { display: flex; gap: .7rem; align-items: center; }
/* A WHITE TILE WITH A NAVY MARK, exactly like the process rail's numbered
   nodes. A blue glyph in a blue rounded square is the single most common
   feature-card chip on the web, and two of them at the top of this section
   were the last thing on the page that looked bought rather than made. */
.si-duo__head .si-card__icon {
    margin-bottom: 0; width: 34px; height: 34px; border-radius: 10px;
    background: #fff; color: var(--si-navy);
    border: 0; box-shadow: 0 0 0 1px rgba(var(--shadow-rgb), .09), 0 1px 2px rgba(var(--shadow-rgb), .05);
}
.si-duo__head .si-card__icon svg { width: 16px; height: 16px; }
.si-duo__title { font-size: 1.0625rem; font-weight: 700; color: var(--si-navy); letter-spacing: -.022em; }
.si-duo__text { margin-top: .75rem; color: var(--si-muted); font-size: .875rem; line-height: 1.6; max-width: 44ch; }
.si-duo__list { list-style: none; margin-top: var(--si-s4); display: grid; gap: .5rem; }
.si-duo__list li {
    padding: .5rem .75rem; background: var(--si-bg-alt);
    border: 1px solid var(--si-border); border-radius: var(--si-radius-sm);
    font-size: .875rem; color: var(--si-muted);
}
.si-duo__list strong { color: var(--si-navy); font-weight: 650; }
.si-duo__list strong::after { content: " — "; color: var(--si-border-strong); font-weight: 400; }
.si-duo__note {
    padding-top: var(--si-s3);
    font-size: .78125rem; line-height: 1.65; color: var(--si-subtle); max-width: 52ch;
}

/* A REAL FIELD WITH A REAL BUTTON IN IT — the control a merchant actually
   uses after creating a link. A navy slab with grey text on it was a
   decoration OF a field; this is the field: white surface, inset ring,
   monospace URL, and a solid blue action sitting inside the well. */
/* =====================================================================
   THE LINK UI AS ONE QUIET SURFACE
   =====================================================================
   The field and the type control were two loose elements on the section's
   own ground while the half opposite carries a solid navy acceptance
   block; at 1440 the left column measured 213px against the right's 306px.

   Grouping them on one tinted well with an inset ring gives the left half
   the mass it was missing and — more importantly — makes them read as ONE
   control surface, which is what they are in the product: you create a
   link of a chosen type, and you copy it. No new feature, no new copy, and
   not the card the redesign deliberately removed: no shadow, no white
   fill, no border. */
.si-linkui {
    margin-top: var(--si-s4); padding: .85rem;
    border-radius: 14px;
    background: linear-gradient(180deg, rgba(var(--shadow-rgb), .028), rgba(var(--shadow-rgb), .045));
    box-shadow: inset 0 0 0 1px rgba(var(--shadow-rgb), .055);
}
.si-linkbar {
    display: flex; align-items: center; gap: .4rem;
    margin-top: 0; padding: .3rem .3rem .3rem .65rem;
    background: #fff; border-radius: 11px;
    box-shadow: 0 0 0 1px rgba(var(--shadow-rgb), .09), inset 0 1px 2px rgba(var(--shadow-rgb), .05);
}
.si-linkbar__url {
    flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: .71875rem; letter-spacing: -.01em; color: var(--si-navy);
}
.si-linkbar__copy {
    flex: 0 0 auto; padding: .36rem .65rem; border-radius: 8px;
    background: var(--si-blue); color: var(--si-on-action);
    font-size: .65625rem; font-weight: 700; letter-spacing: .01em;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .18), 0 1px 2px rgba(var(--brand-deep-rgb), .26);
}

/* AN ACCEPTANCE PANEL, NOT A POSTER PRINT. Deep navy with the same lit
   tone the dark section uses, a bright plate, and a hairline of light
   along its top edge — the counter-side equivalent of the checkout card
   opposite. The name and the instruction sit BESIDE the code rather than
   above it, which halves the block and stops a marketing page rendering a
   full-size QR. */
.si-poster {
    position: relative; overflow: hidden;
    /* The panel is sized around the CODE, not around two short lines of
       text: without a floor the block collapsed to 105px and an 88px plate
       inside it read as overflowing its own container. */
    margin-top: var(--si-s4); padding: 1.15rem 7rem 1.15rem 1.1rem;
    min-height: 6.75rem; display: flex; flex-direction: column; justify-content: center;
    text-align: left;
    background: var(--si-navy-surface); border-radius: 13px; color: #fff;
    box-shadow: 0 1px 2px rgba(var(--shadow-rgb), .18), 0 10px 22px -14px rgba(var(--shadow-rgb), .45);
}
.si-poster::before {
    content: ""; position: absolute; left: 0; right: 0; top: 0; height: 1px; pointer-events: none;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .22) 30%, rgba(255, 255, 255, .22) 70%, transparent);
}
.si-poster > * { position: relative; }
/* THE TEXT COLUMN IS ONE BLOCK, CENTRED AGAINST THE PLATE. Laying the two
   lines into separate grid rows let the plate's height push them apart —
   `align-self` narrowed the gap but could not close it, because each line
   still owned half of an 88px span. A nested flex column owns its own
   height and simply centres. */
.si-poster__who { font-size: .9375rem; font-weight: 700; letter-spacing: -.018em; }
.si-poster__hint { margin-top: .3rem; font-size: .625rem; line-height: 1.45; letter-spacing: .07em; text-transform: uppercase; color: var(--ink-subtle); }
/* ABSOLUTE, NOT A SPANNING GRID ITEM. A code that spans both text rows
   FORCES those rows to sum to its own height, which is what held the
   business name and the scan instruction 38px apart with nothing between
   them — `align-self` could narrow that gap but never close it. Taken out
   of flow the two lines size themselves and the plate simply centres
   against them. */
.si-poster__plate {
    position: absolute; right: .95rem; top: 50%; transform: translateY(-50%);
    width: 74px; margin: 0; padding: .3rem;
    background: #fff; border-radius: 9px;
    box-shadow: 0 0 0 1px rgba(255, 255, 255, .14), 0 6px 14px -6px rgba(0, 0, 0, .5);
}
.si-poster__plate svg { width: 100%; height: auto; }

/* --- The payments screen -------------------------------------------------
   The list a merchant actually works from, and deliberately NOT a second
   copy of the hero console: no browser chrome, no sidebar, no KPI tiles.
   A status filter, the real columns, and a footer that counts.

   This replaced a single-payment-record card. The record showed depth but
   answered the wrong headline — "one operational view" is a list, and a
   visitor who has to imagine the list from one row has not been shown it. */

/* ON NAVY, THE SHADOW DOES NOTHING AND THE RING DOES EVERYTHING. A dark
   cast is invisible against a dark section; what separates this surface
   from the ground is a bright 1px rim and the sheer luminance difference,
   so the elevation here is a white-tinted ring plus a deep halo that
   reads as the panel sitting in front of the section. */
.si-board {
    --b-line: var(--line);
    --b-ink: var(--ink);
    --b-muted: var(--ink-muted);
    --b-subtle: var(--ink-subtle);

    position: relative; background: #fff;
    border-radius: var(--si-radius-lg);
    box-shadow:
        0 0 0 1px rgba(255, 255, 255, .10),
        0 2px 6px rgba(0, 0, 0, .28),
        0 30px 60px -26px rgba(0, 0, 0, .70);
    overflow: hidden;
}

.si-board__head {
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--si-s2); flex-wrap: wrap;
    padding: .6rem .75rem; border-bottom: 1px solid var(--b-line);
}
.si-board__h { font-size: .8125rem; font-weight: 700; color: var(--b-ink); letter-spacing: -.01em; }
.si-board__filters { display: flex; gap: 2px; min-width: 0; }
/* =====================================================================
   ON A PHONE THE FILTER TAKES ITS OWN ROW
   =====================================================================
   Four segments plus their well need ~294px; beside the "Payments" title
   in a 350px card there are 248px, so the control ran past the card's
   right edge and "Awaiting" was clipped by its own rounded corner. Sharing
   a line was never going to fit — the fix is the one a real responsive
   product UI makes: the title keeps its row, the segmented control gets a
   full-width one underneath, and the four segments share it equally. */
@media (max-width: 560px) {
    .si-board__head { flex-direction: column; align-items: stretch; gap: .5rem; }
    .si-board__filters { justify-content: space-between; }
    .si-board__filter { flex: 1 1 0; min-width: 0; text-align: center; padding-left: .25rem; padding-right: .25rem; }
}
/* A SEGMENTED FILTER, which is what the product draws — one well, four
   segments, the active one raised out of it. Four separate outlined pills
   read as four buttons nobody has pressed. */
.si-board__filters { padding: 3px; border-radius: 9px; background: var(--ground-alt); box-shadow: inset 0 0 0 1px rgba(var(--shadow-rgb), .05); }
.si-board__filter {
    padding: .2rem .5rem; border-radius: 6px; border: 0; background: transparent;
    font-size: .625rem; font-weight: 650; color: var(--b-subtle); white-space: nowrap;
}
.si-board__filter.is-on {
    background: #fff; color: var(--si-action-ink);
    box-shadow: 0 0 0 1px rgba(var(--brand-rgb), .22), 0 1px 2px rgba(var(--shadow-rgb), .08);
}

.si-board__table {
    width: 100%; border-collapse: collapse; table-layout: fixed;
    font-size: .6875rem; color: var(--b-muted);
}
.si-board__table th {
    padding: .45rem .55rem; text-align: left;
    background: var(--ground); border-bottom: 1px solid var(--b-line);
    font-size: .5625rem; font-weight: 700; letter-spacing: .07em;
    text-transform: uppercase; color: var(--b-subtle); white-space: nowrap;
}
.si-board__table td { padding: .48rem .55rem; border-top: 1px solid var(--b-line); white-space: nowrap; }
.si-board__table tbody tr:first-child td { border-top: 0; }
/* THE COLUMN SHARES LIVE ON THE HEADER ROW, NOT ON THE BODY CELLS.
   This table is `table-layout: fixed`, and under `fixed` THE FIRST ROW
   FIXES THE COLUMNS — a `width` on a `<td>` further down is read too late
   and does nothing at all. These four shares were on the `<td>`s, so the
   browser had been falling back to four EQUAL columns the whole time. It
   looked right at 1120px+ because equal quarters happen to be wide
   enough there; in the dashboard section's split column at 1024 it gave
   the status 122px against 123px of content and clipped "Awaiting
   payment" to "Awaiting pay…". */
/* ON A PHONE THE SCREEN LOSES ITS LEAST LOAD-BEARING COLUMN: a timestamp
   a visitor cannot act on. Reference, amount and status are the three
   that carry the sentence beside them, and their shares are set HERE, on
   the header row — under `table-layout: fixed` the FIRST ROW fixes the
   columns and a width on a `<td>` further down is read too late to do
   anything. That is what once left "Awaiting payment" clipped to
   "Awaiting pay…". 721px restores the fourth column and the wide shares. */
.si-board__table th:nth-child(4), .si-board__table td:nth-child(4) { display: none; }
.si-board__table th:nth-child(1) { width: 30%; }
.si-board__table th:nth-child(2) { width: 22%; }
.si-board__table th:nth-child(3) { width: 48%; }
.si-board__ref { font-weight: 650; color: var(--b-ink); }
.si-board__amt { text-align: right; color: var(--b-ink); font-weight: 650; font-variant-numeric: tabular-nums; }
.si-board__status { overflow: hidden; text-overflow: ellipsis; }
.si-board__at { text-align: right; color: var(--b-subtle); font-variant-numeric: tabular-nums; }
.si-board__table th:nth-child(2), .si-board__table th:nth-child(4) { text-align: right; }

.si-board__foot {
    padding: .45rem .75rem; border-top: 1px solid var(--b-line); background: var(--ground);
    font-size: .5625rem; font-weight: 700; letter-spacing: .06em;
    text-transform: uppercase; color: var(--b-subtle);
}

/* --- The developer code column -------------------------------------------- */

.si-codestack { display: grid; gap: 0; }
.si-codestack .si-code { border-radius: var(--si-radius); }

/* =========================================================================
   17. LANDING LAYOUT PIECES
   ========================================================================= */

/* --- Compact label chips ---------------------------------------------------
   Three link TYPES, named and not explained — the panel only has to
   establish that the choice exists. */
/* `margin-top: auto` inside a panel, so the chips settle on its floor the
   way `.si-duo__note` does opposite — a link bar is much shorter than a
   QR poster, and the gap belongs above the last row, not below it. */
/* A SEGMENTED CONTROL, which is what choosing a link type actually looks
   like in the product — one well, three segments, the first selected.
   Three loose outlined pills looked like tags on a blog post. */
/* FULL WIDTH INSIDE THE WELL, three equal segments. Shrink-wrapped it
   stopped short of the field above it and left a ragged right edge inside
   a surface whose whole job is to square the two controls up. */
.si-tags {
    list-style: none; display: flex; gap: 2px;
    margin-top: .55rem; padding: 3px; border-radius: 10px;
    background: #fff;
    box-shadow: inset 0 0 0 1px rgba(var(--shadow-rgb), .07);
}
.si-tags li { flex: 1 1 0; min-width: 0; text-align: center; }
/* NO FLOOR ALIGNMENT. `margin-top: auto` existed to square off the bottom
   edges of two bordered cards; with the cards gone it only opened a 90px
   hole under the link field, because the right column happens to be
   taller. In an open composition the two columns are allowed to end at
   different heights — that is what makes it a spread rather than a table. */
.si-duo__panel > .si-tags { align-self: flex-start; }
.si-duo__note { margin-top: var(--si-s4); }
.si-tags li {
    padding: .34rem .5rem; border-radius: 7px;
    color: var(--si-subtle); font-size: .6875rem; font-weight: 650; letter-spacing: -.005em;
}
.si-tags li:first-child {
    background: var(--si-navy); color: #fff;
    box-shadow: 0 1px 2px rgba(var(--shadow-rgb), .25);
}

/* --- The security row ------------------------------------------------------
   FOUR LINES, NOT FOUR CARDS: a bordered box around reassurance reads as
   a feature the visitor has to evaluate. */
/* =====================================================================
   FOUR ITEMS, AND THEY ARE NOT FOUR EQUAL CARDS
   =====================================================================
   An equal 2x2 or 1x4 grid of title-plus-sentence tiles says all four
   matter the same amount, which is both untrue and the most generic shape
   a features block can take. The first item — the money going straight to
   the merchant — is the one a stranger is actually deciding on, so it is
   a RAISED PANEL with an emerald keyline and display type, and the other
   three are quiet ruled columns with no box at all.

   One strong element and three supporting ones is hierarchy. Four of
   anything identical is a grid. */
/* THE CLOSING RULE IS THE GRID'S, NOT THE FINE PRINT'S. Drawn on the
   paragraph it inherited that paragraph's 74ch measure and stopped
   two-thirds of the way across, so a band whose four cells each open on a
   full-width rule closed on a short one. On the grid it spans every
   column. */
.si-trust {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--si-s3) var(--si-s4);
    padding-bottom: var(--si-s5); border-bottom: 1px solid rgba(var(--shadow-rgb), .09);
}

.si-trust__item { padding-top: var(--si-s3); border-top: 1px solid rgba(var(--shadow-rgb), .12); }
.si-trust__title { font-size: .84375rem; font-weight: 700; color: var(--si-navy); letter-spacing: -.012em; }
.si-trust__text { margin-top: .3rem; color: var(--si-muted); font-size: .75rem; line-height: 1.55; }

/* =====================================================================
   THE LEAD ITEM IS AN EMPHASISED CELL, NOT A CARD PARKED BESIDE THREE
   TEXT COLUMNS
   =====================================================================
   It was a raised white panel with a shadow and a rounded corner sitting
   against a tinted band next to three bare ruled columns — two different
   component languages in one row, which is exactly why it read as random.

   Now it is the SAME cell as the other three: same top-rule position, same
   padding rhythm, no shadow, no card. Only the EMPHASIS differs — the rule
   above it is 2px of emerald instead of 1px of neutral, and a
   barely-there emerald wash fades out beneath it. One band, one accent, no
   second component. */
.si-trust__item:first-child {
    grid-column: 1 / -1;
    position: relative; overflow: hidden;
    padding: var(--si-s4) var(--si-s4) var(--si-s4) 0;
    border-top: 0; border-radius: 0 0 10px 10px;
    background: linear-gradient(180deg, rgba(16, 185, 129, .07), rgba(16, 185, 129, 0) 78%);
    box-shadow: none;
}
.si-trust__item:first-child::before {
    content: ""; position: absolute; left: 0; right: 0; top: 0; height: 2px;
    background: linear-gradient(90deg, #059669, #10B981);
}
.si-trust__item:first-child .si-trust__title { font-size: 1.0625rem; letter-spacing: -.022em; }
.si-trust__item:first-child .si-trust__text { font-size: .84375rem; margin-top: .35rem; max-width: 46ch; }
/* Four items in two columns leaves the last one alone; it takes the row. */
.si-trust__item:last-child { grid-column: 1 / -1; }

/* The one disclaimer on the front page. Quiet type, full width, no panel:
   a bordered note made it look like a warning about the product. */
/* The band's footnote: no rule of its own (the grid above carries it) and
   close enough to read as belonging to what it qualifies. */
.si-fineprint {
    margin-top: var(--si-s4); padding-top: 0;
    border-top: 0;
    color: var(--si-subtle); font-size: .78125rem; line-height: 1.65; max-width: 74ch;
}

/* --- The developer strip ---------------------------------------------------
   Shares the trust section rather than taking a screen: a stranger needs
   to see that an API exists, not to read its rules. */
.si-devstrip {
    display: grid; gap: var(--si-s4);
    margin-top: var(--si-s5); padding-top: var(--si-s5);
    border-top: 1px solid rgba(var(--shadow-rgb), .09);
}

/* A tick list. The same emerald check the hero facts use, at paragraph
   width rather than in a row. */
.si-ticks { list-style: none; display: grid; gap: .45rem; }
.si-ticks li { display: flex; gap: .5rem; align-items: flex-start; color: var(--si-muted); font-size: .8125rem; line-height: 1.55; }
.si-ticks .si-tick { width: 14px; height: 14px; margin-top: .22rem; }

/* A closing sentence under a section, quieter than a `.si-note` panel. */
.si-foot {
    margin-top: var(--si-s5); padding-top: var(--si-s4);
    border-top: 1px solid var(--si-border);
    color: var(--si-subtle); font-size: .8125rem; line-height: 1.65; text-align: center;
}

/* A split whose second column is a product visual: the visual is given
   the wider share, and the columns align to the top so a tall mock does
   not drag its paragraph into the middle of the section. */
/* `--visual` STACKS THE FIGURE LAST on a narrow screen, because everywhere
   it is used the sentence beside the mock introduces it. In the dashboard
   section the sentence is the section head, ABOVE the split, so the figure
   has already been introduced and leads. */
.si-split--visual > .si-figure { order: 2; }
.si-split--leadvisual > .si-figure { order: 0; }

/* --- The verification block ------------------------------------------------
   No border, no icon, no panel: the section's own navy already does the
   separating a box would do. */
.si-auto__title { font-size: 1.125rem; letter-spacing: -.02em; line-height: 1.25; text-wrap: balance; }
.si-auto__text { margin-top: var(--si-s3); color: var(--si-on-dark-muted); font-size: .8125rem; line-height: 1.62; max-width: 46ch; }
.si-auto__note { margin-top: var(--si-s4); color: var(--si-on-dark-subtle); font-size: .6875rem; line-height: 1.6; max-width: 48ch; }

/* --- The Free tier strip --------------------------------------------------
   Free is a fact about every account, not a fourth card competing with
   three priced ones — so it reads as a line, above them. */
/* Free is a STATEMENT ABOUT EVERY ACCOUNT, not a fourth product. It reads
   as a ruled strip on the section's own ground rather than as a card, so
   it cannot be mistaken for a tier competing with the three below it. */
.si-free {
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--si-s3) var(--si-s5); flex-wrap: wrap;
    /* THE SAME MEASURE AS THE PLAN GRID BELOW IT. Free was 62rem and the
       cards 64rem, so the two blocks' left and right edges missed each
       other by 16px — small enough to look like a rendering fault rather
       than a decision, and the fastest way to make one pricing system read
       as two unrelated ones. */
    max-width: 64rem; margin: 0 auto var(--si-s4);
    padding: .9rem 1.1rem;
    background: rgba(255, 255, 255, .7);
    border-radius: var(--si-radius);
    box-shadow: 0 0 0 1px rgba(var(--shadow-rgb), .08);
}
.si-free > :first-child { flex: 1 1 14rem; min-width: 0; }
/* Below the pairing width the button has already wrapped onto its own row,
   so it takes that row rather than sitting in the left third of it. */
.si-free .si-btn { flex: 1 1 100%; }
@media (min-width: 600px) { .si-free .si-btn { flex: 0 0 auto; } }
.si-free__name { font-size: 1rem; font-weight: 700; letter-spacing: -.02em; color: var(--si-navy); }
/* NOT `--si-emerald`. #10B981 on white is 2.5:1, and this is 17px text,
   not an icon — under the 4.5:1 floor with no large-text exemption to
   fall back on. var(--state-ok-ink) is the same hue at 5.5:1 and still reads as the
   system's success colour beside the word Free. */
.si-free__price { margin-left: .5rem; font-weight: 700; color: var(--state-ok-ink); }
.si-free__text { margin-top: .15rem; color: var(--si-muted); font-size: .75rem; line-height: 1.55; }
.si-free__meta { white-space: nowrap; }
.si-free__meta strong { color: var(--si-navy); font-weight: 650; }


/* --- The plan comparison table --------------------------------------------
   A real <table> with a real <caption> and real row headers, because it is
   real tabular data and a grid of <div>s would be unreadable to anyone
   navigating it by row. It scrolls inside its own wrapper rather than
   pushing the page sideways. */
.si-tablewrap { overflow-x: auto; border: 1px solid var(--si-border); border-radius: var(--si-radius); background: #fff; }
.si-table { width: 100%; border-collapse: collapse; font-size: .9375rem; min-width: 40rem; }
.si-table th, .si-table td { padding: .8rem 1rem; text-align: left; border-top: 1px solid var(--si-border); }
.si-table thead th { border-top: 0; vertical-align: bottom; background: var(--si-bg-alt); }
.si-table thead th:first-child { font-size: .6875rem; text-transform: uppercase; letter-spacing: .07em; color: var(--si-subtle); }
.si-table tbody th { font-weight: 500; color: var(--si-muted); width: 34%; }
.si-table td { color: var(--si-navy); font-weight: 650; font-variant-numeric: tabular-nums; white-space: nowrap; }
.si-table__plan { display: block; font-size: 1rem; font-weight: 700; color: var(--si-navy); }
.si-table__price { display: block; margin-top: .15rem; font-size: .8125rem; font-weight: 500; color: var(--si-subtle); white-space: nowrap; }
.si-table tbody tr:hover { background: var(--si-bg-alt); }

/* --- The closing call to action ------------------------------------------- */
/* THE CLOSING BAND. Navy, one action, and a radial lift behind the
   heading so it does not read as the footer starting early. */
.si-cta {
    position: relative; overflow: hidden;
    padding: var(--si-sect) var(--si-gutter);
    background: var(--si-navy-surface); color: var(--si-invert);
}
.si-cta::before {
    content: ""; position: absolute; inset: auto 0 auto 50%; top: -34%;
    width: 46rem; height: 34rem; transform: translateX(-50%); pointer-events: none;
    background: radial-gradient(closest-side, rgba(var(--brand-rgb), .10), rgba(var(--brand-rgb), 0) 72%);
}
/* A hairline of light along the top edge, so the band starts rather than
   simply changing colour. */
.si-cta::after {
    content: ""; position: absolute; left: 0; right: 0; top: 0; height: 1px; pointer-events: none;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .16) 22%, rgba(255, 255, 255, .16) 78%, transparent);
}
.si-cta > * { position: relative; }
.si-cta h2 { color: #fff; }
.si-cta .si-lede { color: var(--si-on-dark-muted); margin-left: auto; margin-right: auto; }
.si-cta__note { margin-top: var(--si-s4); color: var(--si-on-dark-subtle); font-size: .78125rem; }
/* AND ITS ACTION IS A BUTTON, NOT A BAR. Every other call-to-action row on
   a phone stretches to the gutters, which is right for a pair of equals;
   stretched to 354px on navy, ONE white button reads as an app install
   prompt. It keeps a comfortable minimum and stays centred. */
.si-cta .si-ctarow .si-btn { flex: 0 0 auto; min-width: 11rem; }

/* ======================================================================
   18. AUTH — /login, /signup and the account-created page
   ======================================================================
   ONE COMPACT CENTRED CARD, not a two-panel marketing split.

   The previous entry was a navy product panel beside the form: a
   headline, four capability ticks and a plan line. That is landing-page
   work, and it was doing it on the screen where a merchant has already
   decided and only wants to get in. The card is now the whole page, and
   the product argument is left to the pages built to make it.

   The measurements below are deliberate and small. An authentication
   form is the densest surface in the product — six or seven controls,
   no data, no navigation — so it is sized like a control panel rather
   than like a page: 12px labels, 14px inputs, one 46px control height
   shared by every input and the button, and a 408px column that holds a
   comfortable line at 13px.

   The three pages share this block on purpose, so the page a merchant
   lands on after signing up cannot drift away from the page they signed
   up on. No script here either — the whole public surface, auth
   included, still runs on zero JavaScript.
   ====================================================================== */
.si-auth {
    min-height: 100vh;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    padding: var(--si-s6) var(--si-s5);
    background: var(--si-bg-alt);
}
.si-auth__main {
    width: 100%; max-width: 25.5rem;
    display: flex; flex-direction: column; align-items: stretch;
}

/* The lockup sits above the card at 44px rather than the 56px the site
   header uses. The supplied artwork is ~37% transparent padding, so 44px
   of box is ~28px of ink — present, and not the loudest thing on a page
   whose job is a password field. */
.si-auth__brand { display: flex; justify-content: center; margin-bottom: var(--si-s5); }
.si-auth__brand .si-logo__img { height: 44px; }

.si-auth__card {
    background: #fff;
    border: 1px solid var(--si-border);
    border-radius: 15px;
    padding: 1.75rem;
    /* Two very soft layers: a hairline that separates the card from the
       ground, and a wide low-opacity lift. Nothing that reads as a drop
       shadow at a glance. */
    box-shadow: 0 1px 2px rgba(var(--shadow-rgb), .04), 0 10px 28px -14px rgba(var(--shadow-rgb), .14);
}

.si-auth__title { font-size: 1.375rem; line-height: 1.25; letter-spacing: -.018em; }
.si-auth__text { margin-top: .375rem; color: var(--si-muted); font-size: .8125rem; line-height: 1.55; }

.si-auth__form { margin-top: 1.25rem; display: grid; gap: .8125rem; }
.si-auth__form .si-btn {
    width: 100%; height: 46px; padding: 0 1rem;
    border-radius: 10px; font-size: .875rem; font-weight: 600;
}
/* Air between the last field and the commit control, so the button is
   never read as one more row of the form. */
.si-auth__form .si-btn { margin-top: .4375rem; }

.si-auth__foot {
    margin-top: 1.125rem; padding-top: .875rem;
    border-top: 1px solid var(--si-border);
    font-size: .75rem; color: var(--si-subtle); text-align: center;
}
.si-auth__foot a { font-weight: 600; }

/* The small way-out under a field — today only "Forgot your password?".
   RIGHT-ALIGNED AND QUIET: it sits where a merchant's eye already is
   after a failed password, without competing with the field's own error
   message, which is the thing directly above it. */
.si-field__aside {
    margin: .375rem 0 0;
    font-size: .75rem;
    text-align: right;
}
.si-field__aside a { color: var(--si-subtle); font-weight: 500; }
.si-field__aside a:hover { color: var(--si-text); }

/* The one line of reassurance, under the card and deliberately quiet.
   It says what this screen is, and claims nothing about how it is
   protected. */
.si-auth__trust {
    margin-top: var(--si-s4);
    display: flex; align-items: center; justify-content: center; gap: .3rem;
    font-size: .6875rem; color: var(--si-subtle);
}
.si-auth__trust svg { width: 12px; height: 12px; flex: 0 0 auto; }

.si-auth__legal {
    margin-top: .625rem; text-align: center;
    font-size: .6875rem; line-height: 1.55; color: var(--si-subtle);
}
.si-auth__legal a { color: var(--si-subtle); }
.si-auth__links { margin-top: .375rem; font-size: .6875rem; color: var(--si-subtle); text-align: center; }
/* The fine print reads as fine print. Four blue underlined links under a
   sign-in card compete with the one link that is actually an action —
   "Create account" — so these stay grey until they are pointed at. */
.si-auth__links a { color: var(--si-subtle); text-decoration-color: var(--si-border-strong); }
.si-auth__links a:hover { color: var(--si-navy-3); text-decoration-color: currentColor; }

/* --- Fields ------------------------------------------------------------ */
.si-field { display: grid; gap: .3125rem; }
.si-label { font-size: .75rem; font-weight: 600; color: var(--si-navy); letter-spacing: .005em; }
.si-hint { display: block; margin-top: .1rem; font-weight: 400; font-size: .6875rem; color: var(--si-subtle); }
.si-input {
    width: 100%; height: 46px; padding: 0 .875rem;
    font: inherit; font-size: .875rem; color: var(--si-text);
    background: #fff; border: 1px solid var(--si-border-strong); border-radius: 10px;
    transition: border-color .15s ease, box-shadow .15s ease;
}
.si-input:hover { border-color: var(--si-navy-3); }
/* A 2px ring at 14% rather than the 3px/28% the rest of the site uses.
   On a form that is almost entirely inputs, the site-wide ring reads as
   a highlight; this reads as focus. */
.si-input:focus { outline: none; border-color: var(--si-action-graphic); box-shadow: 0 0 0 2px rgba(var(--brand-rgb), .14); }
.si-input[aria-invalid="true"] { border-color: var(--si-danger); }
.si-input[aria-invalid="true"]:focus { box-shadow: 0 0 0 2px rgba(220, 38, 38, .16); }
.si-fielderror { display: flex; align-items: flex-start; gap: .3rem; color: var(--si-danger); font-size: .6875rem; line-height: 1.5; }
.si-fielderror svg { flex: 0 0 auto; width: 13px; height: 13px; margin-top: .15rem; }

/* --- The mobile number field ------------------------------------------
   PayMQR asks Indian merchants for an Indian mobile number, so the
   country code is not a question — it is a label. It is drawn INSIDE the
   control, divided from the number, and it is a <span>: nothing extra is
   submitted, and the merchant types the ten digits and nothing else.
   The wrapper carries the border and the focus state so the prefix and
   the number read as one field rather than two controls side by side. */
.si-phone {
    display: flex; align-items: stretch; height: 46px; overflow: hidden;
    background: #fff; border: 1px solid var(--si-border-strong); border-radius: 10px;
    transition: border-color .15s ease, box-shadow .15s ease;
}
.si-phone:hover { border-color: var(--si-navy-3); }
.si-phone:focus-within { border-color: var(--si-action-graphic); box-shadow: 0 0 0 2px rgba(var(--brand-rgb), .14); }
.si-phone__cc {
    flex: 0 0 52px;
    display: flex; align-items: center; justify-content: center;
    border-right: 1px solid var(--si-border);
    background: var(--si-bg-alt);
    font-size: .8125rem; font-weight: 600; color: var(--si-navy-3);
}
.si-phone__num {
    flex: 1 1 auto; min-width: 0;
    border: 0; background: transparent; padding: 0 .875rem;
    font: inherit; font-size: .875rem; color: var(--si-text); letter-spacing: .015em;
}
.si-phone__num:focus { outline: none; }
.si-phone--invalid { border-color: var(--si-danger); }
.si-phone--invalid:focus-within { box-shadow: 0 0 0 2px rgba(220, 38, 38, .16); }

/* --- The account-created page -----------------------------------------
   The same card, the same width, the same type scale — so the page that
   confirms an account looks like the page that created it. */
.si-auth__done { text-align: center; }
.si-auth__mark {
    width: 48px; height: 48px; margin: 0 auto var(--si-s4);
    display: flex; align-items: center; justify-content: center;
    border-radius: 50%;
    background: var(--si-emerald-soft);
    border: 1px solid var(--si-emerald-border);
    color: var(--si-emerald);
}
.si-auth__mark svg { width: 22px; height: 22px; stroke-width: 2.2; }
/* TWO MORE TONES ON THE SAME BADGE. Four outcomes reach views/auth/
   outcome.php and only two of them are successes, so the green tick
   cannot be the only mark the shell knows how to draw.

   "In flight" wears the brand, because waiting for an email is the
   normal path and not a problem. "Expired" is MUTED rather than red: a
   link that ran out is not a mistake the merchant made, and a red cross
   would tell them something is wrong with their account. */
.si-auth__mark--sent {
    background: var(--action-soft);
    border-color: var(--action-border);
    color: var(--action-graphic);
}
.si-auth__mark--expired {
    background: var(--si-bg);
    border-color: var(--si-border);
    color: var(--si-subtle);
}
.si-auth__done .si-auth__text { margin-top: .375rem; }
.si-auth__done .si-btn {
    margin-top: 1.25rem; width: 100%; height: 46px; padding: 0 1rem;
    border-radius: 10px; font-size: .875rem; font-weight: 600;
}

/* One quiet entrance, once. The reduced-motion block at the end of this
   file neutralises it for anyone who has asked for that. */
@keyframes si-auth-in {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: none; }
}
.si-auth__card { animation: si-auth-in .32s ease-out both; }

@media (max-width: 600px) {
    .si-auth { padding: var(--si-s6) 1.0625rem; justify-content: flex-start; }
    .si-auth__card { padding: 1.375rem 1.25rem; }
    .si-auth__brand { margin-bottom: 1.125rem; }
    .si-auth__brand .si-logo__img { height: 40px; }
    .si-auth__title { font-size: 1.25rem; }
}

/* =========================================================================
   19. RESPONSIVE — MOBILE-FIRST
   =========================================================================
   EVERY RULE ABOVE THIS POINT DESCRIBES A PHONE. This section is the set
   of things a larger screen may ADD: columns, a little more air, a little
   more type. Written the other way round — a desktop page unwound by
   max-width queries — the phone is whatever is left after six overrides,
   which is exactly how the page arrived at 10,730px of scroll on a 375px
   device.

   Four steps, and each one is a real change of shape rather than a
   number nudge:

     base     phone    one column, rails, compact type, no side nav
     >= 600   phablet  the two-way panels pair up
     >= 721   tablet   the rails go horizontal, the product mocks come back
                       whole, and the rhythm opens up
     >= 961   desktop  the page becomes two-column and the hero composes
   ========================================================================= */

/* --- >= 600px: the paired panels ------------------------------------------ */
@media (min-width: 600px) {
    /* Side by side the divider turns vertical and the gap doubles around
       it, so the rule sits in real air rather than against either column. */
    .si-duo { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--si-s6); }
    .si-duo__panel { padding-bottom: 0; }
    .si-duo__panel + .si-duo__panel {
        padding-top: 0; padding-left: var(--si-s6); border-top: 0;
        border-left: 1px solid rgba(var(--shadow-rgb), .10);
    }
    .si-contact { grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr)); }
}

/* --- >= 721px: tablet ------------------------------------------------------ */
@media (min-width: 721px) {
    :root { --si-gutter: 1.75rem; --si-sect: 4.5rem; }

    .si-lede { font-size: 1rem; }
    .si-hero__lede { font-size: 1.0625rem; }
    .si-hero__note { font-size: .8125rem; }
    .si-hero__facts { gap: .5rem var(--si-s4); }
    .si-hero__facts li { font-size: .8125rem; }
    .si-hero__facts .si-tick { width: 15px; height: 15px; }
    .si-btn { font-size: .875rem; }
    .si-btn--lg { font-size: .9375rem; min-height: 3rem; }
    .si-eyebrow { font-size: .6875rem; }
    .si-figure__caption { font-size: .75rem; }
    .si-textlink { font-size: .875rem; }

    /* THE PROCESS RAIL TURNS HORIZONTAL. Same markup, same three markers;
       the hairline that ran down the rail now runs across it, from the
       right edge of one marker to the left edge of the next. */
    .si-steps { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--si-s5); }
    /* FOUR ACROSS WHEN THERE ARE FOUR, opted into like `.si-plans--four`.
       The three-up is the landing page's rail; a four-step sequence run
       through it leaves the last step alone on a second row with the
       connecting hairline pointing at nothing, which reads as a broken
       rail rather than as a fourth step. */
    .si-steps--four { grid-template-columns: repeat(4, minmax(0, 1fr)); }
    .si-step { grid-template-columns: minmax(0, 1fr); padding-bottom: 0; }
    .si-step:not(:last-child)::before {
        left: 2.25rem; right: calc(var(--si-s5) * -1); top: .875rem; bottom: auto;
        width: auto; height: 1px;
        background: linear-gradient(90deg, rgba(var(--shadow-rgb), .22), rgba(var(--shadow-rgb), .13) 55%, rgba(var(--shadow-rgb), .04));
    }
    .si-step__num { grid-column: 1; grid-row: 1; margin-bottom: .7rem; }
    .si-step__title { grid-column: 1; grid-row: 2; }
    .si-step__text { grid-column: 1; grid-row: 3; font-size: .875rem; }

    /* THE PLAIN FLOW GOES HORIZONTAL; THE INVERTED ONE DOES NOT.
       `.si-flow` on /how-it-works is a wide lifecycle row and wants the
       space. `.si-flow--invert` is the LANDING PAGE'S VERIFICATION VISUAL,
       and it lives in the narrow half of a split: four nodes wrapped
       3 + 1 there, stranding "Your success page" on a second line behind a
       lone arrow. Kept vertical it reads as the top-to-bottom sequence it
       is describing — proof in, check, status, the merchant's own page —
       at every width, which is also the shape the brief asks for.

       The `si-flow__arrow` span goes back to being an arrow glyph rather
       than a rail segment, but only where the row is horizontal. */
    .si-flow:not(.si-flow--invert) { display: flex; flex-wrap: wrap; gap: var(--si-s2); align-items: center; }
    .si-flow:not(.si-flow--invert) li { display: flex; align-items: center; gap: var(--si-s2); }
    .si-flow:not(.si-flow--invert) li::after { display: none; }
    .si-flow:not(.si-flow--invert) .si-flow__arrow {
        font-size: .8125rem; line-height: 1; width: auto; height: auto;
        background: none; color: var(--si-subtle);
    }
    .si-flow__node { font-size: .8125rem; padding: .38rem .75rem; }
    .si-flow:not(.si-flow--invert) .si-flow__node { border-radius: 999px; }
    /* A little more air on the rail once there is room for it. */
    .si-flow--invert li { grid-template-columns: 1.25rem minmax(0, 1fr); column-gap: .7rem; }
    .si-flow--invert .si-flow__arrow { height: 1rem; }

    /* ONE ROW, FOUR UNEQUAL SHARES. The lead panel takes 1.6 of the 4.6
       and the three ruled columns share the rest — the hierarchy survives
       the row rather than being a mobile-only treatment. */
    .si-trust { grid-template-columns: 1.6fr 1fr 1fr 1fr; gap: var(--si-s4); align-items: stretch; }
    .si-trust__item { padding-top: var(--si-s4); }
    .si-trust__item:first-child { grid-column: auto; padding: var(--si-s4) var(--si-s5) var(--si-s5) 0; }
    .si-trust__item:last-child { grid-column: auto; }
    .si-trust__title { font-size: .875rem; }
    .si-trust__text { font-size: .78125rem; }
    .si-trust__item:first-child .si-trust__title { font-size: 1.125rem; }

    .si-duo__text { font-size: .875rem; }
    .si-duo__title { font-size: 1rem; }
    .si-step__text, .si-ticks li { font-size: .875rem; }
    .si-auto__title { font-size: 1.25rem; }
    .si-auto__text { font-size: .9375rem; }
    .si-code { font-size: .75rem; padding: var(--si-s4) var(--si-s5); }
    .si-faq__q { font-size: .9375rem; padding: .95rem .25rem; }
    .si-faq__a { font-size: .875rem; padding: 0 2.25rem 1rem .25rem; }
    .si-plan__name { font-size: 1.125rem; }
    .si-plan__price { font-size: 1.75rem; }
    .si-plan__row { font-size: .84375rem; }
    .si-free__name { font-size: 1rem; }
    .si-free__text { font-size: .8125rem; }

    /* THE PRODUCT MOCKS COME BACK WHOLE. Below this width the console
       drops its sidebar (a navigation the reader cannot use), the payments
       screen drops its timestamp column, and the hero shows one surface
       rather than two. All three are room, not preference. */
    .si-console__app { grid-template-columns: 132px minmax(0, 1fr); }
    .si-console__rail { display: flex; }
    .si-console__main { padding: var(--si-s4); }
    .si-board__table th:nth-child(4), .si-board__table td:nth-child(4) { display: table-cell; }
    .si-board__table th:nth-child(1) { width: 26%; }
    .si-board__table th:nth-child(2) { width: 20%; }
    .si-board__table th:nth-child(3) { width: 36%; }
    .si-board__table th:nth-child(4) { width: 18%; }
    .si-board__table { font-size: .75rem; }
    .si-pay { max-width: 21rem; }
    .si-apps img { height: 17px; }

    .si-footer__top { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--si-s5); }
    .si-footer__text { font-size: .875rem; }
    .si-footer__list a { font-size: .84375rem; }

    .si-grid--2, .si-grid--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* --- >= 881px: three prices side by side ---------------------------------- */
@media (min-width: 881px) {
    /* Three price cards stop being READABLE well before they stop fitting,
       so this is their own breakpoint rather than the generic one. */
    .si-plans--three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .si-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .si-grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* --- >= 861px: the desktop menu replaces the sheet ------------------------ */
@media (min-width: 861px) {
    .si-nav { display: flex; }
    .si-menu { display: none; }
    /* The phone bar is sized against the phone's content; a 1200px bar can
       carry the lockup at its intended weight without costing anything. */
    .si-logo__img { height: 48px; }
    .si-logo { margin-left: -8px; }
    .si-header__inner { padding-top: .5rem; padding-bottom: .5rem; }
}

/* --- >= 961px: desktop ----------------------------------------------------- */
@media (min-width: 961px) {
    /* =================================================================
       108px OF PADDING ON BOTH SIDES OF EVERY SECTION IS 216px BETWEEN
       THEM — a quarter of a 900px screen of nothing, repeated eight times.
       That is not luxury whitespace; past a certain width it reads as a
       layout that did not finish.

       The base comes down to 76px (152px between), and the two sections
       that have earned room keep more via `--si-sect` overrides below.
       Section-specific, not a global shrink. */
    :root { --si-gutter: 2rem; --si-sect: 4.75rem; }

    /* THE PAGE'S ANCHOR AND ITS CLOSING STATEMENT BREATHE; the short ones
       do not. `--si-sect` is read by `.si-section` and `.si-cta` alike, so
       overriding the variable ON the section is the whole mechanism — no
       per-section padding rules to keep in sync. */
    #dashboard { --si-sect: 6rem; }
    .si-cta { --si-sect: 5.5rem; }
    #links, #faq { --si-sect: 4.25rem; }

    .si-section--tight { padding-top: var(--si-s7); padding-bottom: var(--si-s7); }
    .si-head { margin-bottom: var(--si-s6); }

    /* THE COPY COLUMN IS THE WIDER ONE. The visual had the larger share
       while the headline was two short phrases, and the second sentence
       could not hold one line at any hero-scale type. */
    /* NOT `--si-s8` AT THE FOOT. 72px of hero padding plus 88px of section
       padding put 160px of nothing between the product composition and the
       next heading — on the one screen where the two should read as a
       single argument. */
    .si-hero { padding: var(--si-s7) var(--si-gutter) var(--si-s6); }
    .si-hero__grid { align-items: center; }
    .si-hero__grid { grid-template-columns: minmax(0, 1.12fr) minmax(0, 1fr); gap: var(--si-s7); }
    /* PAST THE STACK THE COPY COLUMN, NOT THE VIEWPORT, IS THE BINDING
       WIDTH. With both sentences balancing independently the ceiling is no
       longer "does line two fit" but "does line one" — 19 characters, so
       the measure opens to 18ch and the type runs to 54px at 1440. */
    .si-hero__title { font-size: clamp(2.625rem, 1.35rem + 2.35vw, 3.375rem); max-width: 18ch; }
    .si-hero__lede { margin-top: var(--si-s4); font-size: 1.125rem; }
    .si-hero__cta { margin-top: var(--si-s5); }
    .si-hero__facts { margin-top: var(--si-s5); }

    .si-split { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--si-s7); }
    .si-split--reverse > :first-child { order: 2; }
    .si-split--visual { grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr); }
    .si-split--leadvisual { grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); }
    /* `start`, NOT `center`. The code block is ~380px tall and the copy
       beside it ~180px; centred, the eyebrow began 170px below the top of
       the thing it introduces and the column read as an accident. Aligned
       to the top — with a small nudge so the eyebrow sits on the code's
       first line — the two columns start together. */
    /* 48px of margin plus 48px of padding put 96px of nothing between the
       security band's fine print and the rule that opens the developer
       block. Two thirds of that was air nobody asked for. */
    .si-devstrip {
        grid-template-columns: minmax(0, .85fr) minmax(0, 1.15fr);
        gap: var(--si-s6) var(--si-s7); align-items: start;
        margin-top: var(--si-s6); padding-top: var(--si-s6);
    }
    .si-devstrip > :first-child { padding-top: .25rem; }

    .si-footer__top { grid-template-columns: minmax(0, 1.4fr) repeat(4, minmax(0, 1fr)); gap: var(--si-s6); }
    .si-footer__brandcol { grid-column: auto; }
    .si-footer__inner { padding-top: var(--si-s7); }

    .si-duo { gap: var(--si-s7); }
    .si-duo__panel + .si-duo__panel { padding-left: var(--si-s7); }
    .si-trust { gap: var(--si-s4); }
    .si-plans--three { gap: var(--si-s4); }
    .si-plan { padding: var(--si-s5); }
    .si-pay { max-width: 22rem; }
    .si-auto__title { font-size: 1.375rem; }

    /* THE LAYERED HERO COMPOSITION. The checkout is pulled up under the
       console's bottom edge and inset from the left so the two read as one
       object. The overlap must land on EMPTY CARD, not on a table row —
       hence the extra floor inside the console's main pane. */
    /* THE SECOND SURFACE APPEARS ONLY WHERE IT CAN BE COMPOSED. Below this
       width it would be a second full-size mock stacked under the first —
       at 768px that alone made the hero 300px taller than the phone's. The
       same checkout is shown in full, at full width, two sections down. */
    .si-heroviz .si-quote { display: grid; }
    .si-vstamp { right: auto; top: auto; left: -1.5rem; bottom: 46%; }
    .si-heroviz .si-console { position: relative; z-index: 1; }
    .si-heroviz .si-quote { position: relative; z-index: 2; width: 90%; margin: -1.75rem 0 0 auto; }
    .si-heroviz .si-console__main { padding-bottom: 3rem; }
}

/* Past the split and below it, the console and the payments screen are the
   widest things on the page; capping them keeps a stacked hero from turning
   into a full-bleed screenshot. */
@media (max-width: 960px) {
    .si-console, .si-board, .si-quote, .si-heroviz { max-width: 34rem; margin-left: auto; margin-right: auto; }
    .si-split--leadvisual > .si-auto { margin-top: var(--si-s4); }
}

/* Below 340px the widest pair stops sharing a line; the strip simply
   takes a third one rather than clipping. Nothing to declare. */

@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    *, *::before, *::after {
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
    }
}

@media print {
    .si-header, .si-footer, .si-hero__cta, .si-menu { display: none !important; }
    body { background: #fff; }
    .si-card, .si-plan, .si-step, .si-board, .si-quote { border-color: #ccc; box-shadow: none; break-inside: avoid; }
}


/* =========================================================================
   20. PUBLIC PRICING — FOUR CARDS  (/pricing)
   =========================================================================
   The public page presents the SAME four-plan structure the merchant
   console compares, so Free stopped being a strip above three priced cards
   and became the first of four equals. Everything here extends the
   `.si-plan` vocabulary in §15; nothing replaces it, and `.si-plans--three`
   is untouched for any surface still using it.

   ONE COLUMN, THEN TWO, THEN FOUR. There is no three-across step: four
   plans across three columns strands one card on a second row, which reads
   as an afterthought rather than as a tier. 2×2 at tablet widths keeps the
   grid square, and the 1200px wrap gives four cards ~288px each — measured
   against the longest row on the page ("Payment verifications ·
   10,000/month") rather than assumed.

   GROWTH IS LIFTED, NOT ENLARGED. It carries §15's blue ring and deeper
   cast and the same flag; its type, waist and rhythm are identical to its
   neighbours. Scaling it up is what makes the other three look like the
   plans nobody should buy, and the brief forbids that explicitly. */

.si-plans--four {
    grid-template-columns: minmax(0, 1fr);
    max-width: 30rem;
    /* Clearance for the Recommended flag, which sits half outside its own
       card — the same 1.25rem `.si-plans--three` reserves. */
    gap: 1.25rem;
    align-items: stretch;
}

/* THE FOOT IS PUSHED DOWN, NOT THE LIST PADDED OUT, so four buttons sit on
   one line however many rows a plan has. Scale carries eight Payment Page
   points that Free does not; `margin-top: auto` is what stops that
   difference becoming four different button positions. */
.si-plans--four .si-plan__foot { margin-top: auto; padding-top: var(--si-s4); }

/* THE BREAKPOINTS ARE SET BY THE LONGEST ROW, NOT BY DEVICE NAMES.

   "Payment verifications · 10,000/month" is the widest line on the page and
   it needs ~233px of row at .78125rem. A column narrower than ~288px wraps
   it, and a wrapped row on one card knocks that card's whole list off its
   neighbours' baseline. Swept 320-1920: two columns earns its step at 700px
   (~320px cards) and four at 1280px (288px cards). Four columns from 1040px
   was tried and gave 232px cards and ELEVEN wrapped rows — the grid fitted,
   the content did not. */
@media (min-width: 700px) {
    .si-plans--four { grid-template-columns: repeat(2, minmax(0, 1fr)); max-width: 44rem; }
}

@media (min-width: 1280px) {
    .si-plans--four { grid-template-columns: repeat(4, minmax(0, 1fr)); max-width: none; gap: var(--si-s4); }
}

/* --- The price, as a figure with a period attached --------------------- */
/* Two elements rather than one string: the amount is the headline and the
   cadence is a footnote on it, and the pair cannot break across a line in
   the middle of the number. `baseline` alignment is what keeps "/month"
   sitting on the figure's own baseline instead of its box's. */
.si-plan__price { display: flex; align-items: baseline; gap: .15rem; flex-wrap: nowrap; }
.si-plan__amount { font: inherit; letter-spacing: inherit; }
.si-plan__per {
    font-size: .8125rem; font-weight: 600; letter-spacing: -.01em;
    color: var(--si-subtle); white-space: nowrap;
}

/* --- A ticked allowance row ------------------------------------------- */
/* THREE CHILDREN NOW, so `space-between` alone would push the tick, the
   label and the value to three corners. The tick is fixed, the label takes
   the slack, and the value is pinned right with tabular figures so four
   columns of numbers read down as well as across. */
.si-plan__row { align-items: flex-start; gap: .5rem; }
.si-plan__row .si-tick { width: 14px; height: 14px; margin-top: .18rem; }
.si-plan__row .si-plan__label { flex: 1 1 auto; min-width: 0; }
.si-plan__row .si-plan__value { flex: 0 0 auto; }

/* --- The Payment Page Customisation points ---------------------------- */
/* A CAPABILITY IS NOT A QUANTITY, so these are not allowance rows with an
   empty value column — they are full-width ticked lines under a hairline.
   Drawing them as rows would leave a ragged column of blanks beside the
   plans that have them and nothing beside the plans that do not.

   NOTHING IS WRITTEN AROUND THEM: no eyebrow, no heading, no note. Each is
   a capability the plan grants today, and a hedge beside a shipped
   capability is a false claim in the other direction. */
.si-plan__points {
    margin-top: .7rem; padding-top: .7rem;
    border-top: 1px solid rgba(var(--shadow-rgb), .08);
    list-style: none; display: flex; flex-direction: column; gap: .55rem;
}
.si-plan__points li {
    display: flex; align-items: flex-start; gap: .5rem;
    font-size: .8125rem; line-height: 1.4; color: var(--si-muted);
}
.si-plan__points .si-tick { width: 14px; height: 14px; margin-top: .18rem; }
/* The first point NAMES the group the rest belong to, so it is set as the
   line a reader stops on. It is still a point and still resolved from
   `plan_features` like every other — only its weight differs. */
.si-plan__points li:first-child { color: var(--si-navy); font-weight: 650; }

/* --- Four across is the tight case, and only there ------------------- */
/* 288px of card, ~256px inside it. The allowance label drops half a point
   and the description is trimmed to two lines so no card's rows fall out of
   step with its neighbours'. Below 1280px the cards are wide and none of
   this applies. */
@media (min-width: 1280px) {
    .si-plan--quad { padding: var(--si-s5) 1.125rem; }
    .si-plan--quad .si-plan__price { font-size: 1.75rem; }
    .si-plan--quad .si-plan__row,
    .si-plan--quad .si-plan__points li { font-size: .78125rem; }
    /* THE DESCRIPTION RESERVES TWO LINES WHETHER IT NEEDS THEM OR NOT.

       Three of the four catalogue descriptions fit one line at 288px and
       the fourth does not, so the fourth card's entire allowance list sat
       ~20px below its neighbours' and a reader comparing "Team members"
       had to scan diagonally. Reserving the taller of the two heights on
       every card puts all four lists back on one another's baseline, and
       costs nothing on the cards that use one line. */
    .si-plan--quad .si-plan__desc { font-size: .78125rem; line-height: 1.45; min-height: 2.9em; }
    .si-plan--quad .si-btn { padding-inline: .7rem; font-size: .8125rem; }
}

/* --- The comparison table's tick -------------------------------------- */
/* Centred in its cell and emerald like every other tick on the site. The
   em-dash alternative is `aria-hidden` with a screen-reader word beside it,
   because "—" is read aloud as nothing at all. */
.si-tick--cell { display: inline-flex; width: 15px; height: 15px; vertical-align: -2px; }

/* --- The narrowest phones ------------------------------------------- */
/* A 320px viewport leaves a 280px card and ~240px of row, which is 7px short
   of the longest allowance line. Half a point off the row and 4px off each
   waist buys it back without touching any other width. */
@media (max-width: 359px) {
    .si-plan--quad { padding-inline: 1rem; }
    .si-plan--quad .si-plan__row,
    .si-plan--quad .si-plan__points li { font-size: .78125rem; }
}

/* =========================================================================
   21. FREE PUBLIC TOOLS  (/tools and every tool page)
   =========================================================================
   The tools family is the same design system as the marketing site — the
   same tokens, the same elevation, the same 9px controls, the same form
   primitives the auth pages introduced (`.si-field`, `.si-label`,
   `.si-input`, `.si-fielderror`, reused here unchanged).

   WHAT IS DIFFERENT IS THE WEIGHT. A marketing page leads with a claim
   and supports it with a visual. A tool page leads with the tool: the
   heading is one line, there is no hero, no illustration and no band of
   colour above the fold, and the first thing below the H1 is a form the
   visitor can type into. Everything here is in service of that — the
   chrome is deliberately quiet so the product UI is the only thing on the
   page with any visual weight.

   Mobile-first like §19: the base rules describe a phone, and the two
   breakpoints below add columns.
   ========================================================================= */

/* --- `hidden` HAS TO OUT-RANK A LAYOUT RULE ------------------------------ */
/*
   The browser's own `[hidden] { display: none }` lives in the USER-AGENT
   stylesheet, and any author rule beats it however specific — so
   `.si-fielderror { display: flex }` un-hides every hidden error message
   on this page, and `.si-qrpanel__meta { display: flex }` prints a column
   of empty labels under an empty QR plate. It did exactly that on the
   first render.

   The tool toggles visibility with `el.hidden`, which is the property a
   screen reader reads, so the fix belongs here rather than in the
   JavaScript: these elements are hidden when the attribute says so, and
   the layout rule applies only when it does not.
*/
.si-fielderror[hidden],
.si-qrpanel__meta[hidden],
.si-qrpanel__row[hidden],
.si-qrpanel__empty[hidden],
.si-qrdest[hidden],
.si-qractions .si-btn[hidden] { display: none; }

/* --- The breadcrumb and switcher bar ------------------------------------ */
/* One bar, two jobs, and on a phone they stack. It sits ABOVE the H1 and
   is set at the smallest type on the site: it is orientation, not
   content, and the moment it competes with the heading it has failed. */
.si-toolbar {
    max-width: var(--si-max);
    margin: 0 auto;
    padding: var(--si-s4) var(--si-gutter) 0;
    display: flex; flex-wrap: wrap; align-items: center; gap: var(--si-s3) var(--si-s4);
}

.si-crumbs {
    display: flex; flex-wrap: wrap; align-items: center; gap: .35rem;
    list-style: none; font-size: .75rem; color: var(--si-subtle);
}
.si-crumbs a { color: var(--si-subtle); text-decoration: none; }
.si-crumbs a:hover { color: var(--si-navy); text-decoration: underline; }
/* The separator is generated, so it is never read aloud and never
   selected when the trail is copied. */
.si-crumbs li + li::before { content: "/"; margin-right: .35rem; color: var(--si-border-strong); }
.si-crumbs [aria-current="page"] { color: var(--si-navy-3); font-weight: 600; }

/* THE SWITCHER IS A ROW OF LINKS, NOT A MENU.
   With one tool live it is one chip and a link to the hub; at six it
   scrolls sideways on a phone rather than becoming a disclosure. A menu
   would cost a click on every page of a family whose whole point is that
   moving between tools is instant. */
/* Left-aligned under the breadcrumb on a phone, where the bar stacks and
   a right-aligned row would sit under nothing. It only moves to the right
   once the two share a line (see the 721px block below). */
.si-switch {
    display: flex; align-items: center; gap: .35rem;
    max-width: 100%;
    overflow-x: auto; -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
}
.si-switch::-webkit-scrollbar { display: none; }
.si-switch__item {
    display: inline-flex; align-items: center; gap: .35rem; white-space: nowrap;
    padding: .3rem .6rem; border-radius: 7px;
    font-size: .75rem; font-weight: 600; color: var(--si-muted); text-decoration: none;
    transition: background-color .18s ease, color .18s ease, box-shadow .18s ease;
}
.si-switch__item svg { width: 14px; height: 14px; }
.si-switch__item:hover { color: var(--si-navy); background: rgba(var(--shadow-rgb), .045); }
/* The current tool is a filled chip. It is still a link — a visitor who
   clicks it reloads the tool they are on, which is harmless — but
   `aria-current` is what actually announces it. */
.si-switch__item.is-current {
    color: var(--si-navy); background: #fff;
    box-shadow: var(--si-ring-hair), 0 1px 2px rgba(var(--shadow-rgb), .06);
}
.si-switch__all {
    white-space: nowrap; padding: .3rem .5rem;
    font-size: .75rem; font-weight: 650; color: var(--si-action-ink); text-decoration: none;
}
.si-switch__all:hover { text-decoration: underline; }

/* --- The tool heading ---------------------------------------------------- */
/* ONE LINE AND ONE SENTENCE. No eyebrow, no badge, no pair of buttons: a
   visitor who searched for a UPI QR generator has already decided, and
   everything between them and the first field is friction. */
.si-toolhead { max-width: 46rem; margin-bottom: var(--si-s5); }
.si-toolhead .si-h2 { font-size: clamp(1.4375rem, 1.05rem + 1.5vw, 1.875rem); }
.si-toolhead .si-lede { margin-top: var(--si-s2); }

/* The tool section's own top padding is smaller than a marketing
   section's: the breadcrumb bar above it already supplies air, and the
   generator has to start inside the first viewport on a phone. */
.si-qrsec { padding-top: var(--si-s4); }

/* --- The generator ------------------------------------------------------- */
/* STACKED, AND BOUNDED WHILE IT IS.
   A phone is narrower than this and never sees the cap. A tablet is not:
   at 768px an uncapped stack gives 728px-wide text inputs, which is the
   look of a form that was never laid out for that width. The cap is
   removed at 961px, where the two columns take over. */
.si-qrgen {
    display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--si-s5);
    max-width: 34rem; margin-inline: auto;
}
.si-qrgen__form { display: grid; gap: var(--si-s4); align-content: start; min-width: 0; }

/* "Optional" IS A WORD, NOT A COLOUR. Marking the optional fields rather
   than the required one is the right way round here: four of the five are
   optional, so the mark that carries information is the one on them. */
.si-optional {
    margin-left: .35rem; font-size: .625rem; font-weight: 600;
    letter-spacing: .04em; text-transform: uppercase; color: var(--si-subtle);
}

/* The rupee sign is drawn INSIDE the control and is `aria-hidden`: the
   field is already labelled "Amount", and a screen reader announcing
   "rupees amount edit" adds nothing. The input carries the border so the
   prefix and the number read as one control. */
.si-inputwrap { position: relative; display: block; }
.si-inputwrap__prefix {
    position: absolute; left: .875rem; top: 50%; transform: translateY(-50%);
    font-size: .875rem; color: var(--si-subtle); pointer-events: none;
}
.si-input--prefixed { padding-left: 2rem; }

/* The folded reference field. `<details>` — keyboard operable, announced,
   and no script. */
.si-more > summary {
    display: inline-flex; align-items: center; gap: .35rem;
    cursor: pointer; list-style: none;
    font-size: .8125rem; font-weight: 650; color: var(--si-action-ink);
}
.si-more > summary::-webkit-details-marker { display: none; }
.si-more > summary::before { content: "+"; font-weight: 700; }
.si-more[open] > summary::before { content: "−"; }
.si-more > summary:hover { text-decoration: underline; }

/* --- The result column --------------------------------------------------- */
.si-qrgen__result { display: grid; gap: var(--si-s3); align-content: start; }

/* THE MODE SWITCH IS TWO WORDS IN A TRACK, not a dropdown.
   There are two outputs and a merchant should be able to see both in one
   glance and one click. A <select> would hide the poster behind a menu on
   the page whose whole point is the poster. */
.si-qrmodes {
    display: inline-flex; align-self: start; gap: .2rem; padding: .2rem;
    border-radius: 10px; background: var(--si-bg-alt);
    box-shadow: inset 0 0 0 1px rgba(var(--shadow-rgb), .06);
}
.si-qrmode {
    appearance: none; border: 0; cursor: pointer;
    padding: .38rem .8rem; border-radius: 8px;
    font: inherit; font-size: .78125rem; font-weight: 650; color: var(--si-muted);
    background: transparent;
    transition: background-color .18s ease, color .18s ease, box-shadow .18s ease;
}
.si-qrmode:hover { color: var(--si-navy); }
.si-qrmode.is-on {
    color: var(--si-navy); background: #fff;
    box-shadow: var(--si-ring-hair), 0 1px 2px rgba(var(--shadow-rgb), .07);
}

/*
   THE OUTPUT BOX IS A CONTAINER, and that is what makes the preview an
   exact scale model of the download.

   The poster is designed on a 680-unit canvas (public/assets/js/
   qr-poster.js). Here `1em` is set to ten of those units through
   `cqw`, so every size below is the design's own number divided by ten
   — 34-unit type is 3.4em, a 444-unit plate is 44.4em. The preview and
   the PNG cannot drift apart by a rounding, because they are the same
   arithmetic.

   The bare `font-size` before it is the fallback for an engine without
   container queries: it lands within a pixel of the computed value at
   the desktop column width.
*/
.si-qrout {
    container-type: inline-size;
    position: relative; width: 100%;
    display: flex; align-items: center; justify-content: center;
    min-height: 20rem;
    border-radius: var(--si-radius);
    background: var(--si-bg-alt);
    box-shadow: inset 0 0 0 1px rgba(var(--shadow-rgb), .06);
    transition: background-color .18s ease, box-shadow .18s ease;
}
/* Once there is a poster the box is just its ground: the poster brings
   its own card, and a second frame around it reads as a picture of a
   picture. */
.si-qrout:has(.si-qrposter:not([hidden])),
.si-qrout:has(.si-urlcard:not([hidden])),
.si-qrout:has(.si-qrplain:not([hidden])) { background: transparent; box-shadow: none; min-height: 0; }

.si-qrpanel__empty {
    display: flex; flex-direction: column; align-items: center; gap: .6rem;
    padding: var(--si-s6) var(--si-s4); text-align: center;
    color: var(--si-muted); font-size: .8125rem; line-height: 1.55;
}
.si-qrpanel__empty svg { width: 26px; height: 26px; color: var(--si-border-strong); }

/* --- The poster ---------------------------------------------------------- */
/*
   `si-qrposter`, NOT `si-poster`.

   `.si-poster` was already taken — by the landing page's merchant-poster
   MOCK (§16), which is `position: relative; overflow: hidden` with an
   absolutely-positioned `.si-poster__plate`. Reusing the name inherited
   all of that: the QR plate left the flow, the lines after it drew on top
   of the symbol, and the card collapsed to a third of its height. It
   looked like a broken layout rather than a name collision, which is what
   makes this worth a comment.

   Everything below is a scale model of the download — see the note on
   `.si-qrout`.
*/
.si-qrposter {
    font-size: 6.3px;
    font-size: calc(100cqw / 68);
    width: 100%;
    padding: 2em;
    text-align: center;
    background: var(--si-surface);
    border-radius: 2.8em;
    box-shadow: var(--si-shadow);
    color: var(--si-navy);
}
.si-qrposter__label {
    font-size: 1.3em; font-weight: 700; letter-spacing: .14em;
    text-transform: uppercase; color: var(--si-subtle);
}
.si-qrposter__payee {
    margin-top: .8em; font-size: 3.4em; font-weight: 700;
    letter-spacing: -.02em; line-height: 1.24; overflow-wrap: anywhere;
}
.si-qrposter [data-upiqr-row="amount"] { margin-top: 2.2em; }
.si-qrposter__amount {
    margin-top: .4em; font-size: 5.4em; font-weight: 800; letter-spacing: -.03em; line-height: 1;
}
.si-qrposter__open { margin-top: 2.2em; font-size: 2.4em; font-weight: 600; }

/* The white plate is not decoration: the quiet zone is part of the QR
   specification, and a symbol drawn straight onto a tinted card
   intermittently fails to scan. */
.si-qrposter__plate {
    width: 43.6em; max-width: 100%; margin: 2.8em auto 0; padding: 1.8em;
    border-radius: 2.2em; background: #fff;
    box-shadow: 0 0 0 .15em var(--si-border);
}
.si-qrposter__plate svg { display: block; width: 100%; height: auto; }
.si-qrposter__scan { margin-top: 2.6em; font-size: 1.9em; font-weight: 600; }

/* The acceptance row on its own quiet well: four marks floating on a card
   read as four logos somebody pasted on; the same four inside a tinted,
   hairlined well read as a compatibility strip, which is what they are. */
.si-qrposter__apps {
    display: flex; align-items: center; justify-content: center; gap: 2.8em;
    margin: 1.8em auto 0; padding: 0 2em; height: 6.2em;
    border-radius: 1.6em; background: var(--si-bg-alt);
    box-shadow: inset 0 0 0 .1em var(--si-border);
}
/* Width and height come from PayMQR\Qr\QrPosterMarks::htmlRow(), so the
   box is reserved before the SVG arrives and the row cannot shift. */
.si-qrposter__app { display: block; height: 3em; width: auto; }

/* The detail block carries the margin the address used to, so the label
   and the address move together. Both numbers have twins in qr-poster.js
   at ten times the size — see the note on `.si-qrout`. */
.si-qrposter__detail { margin-top: 2.4em; }
.si-qrposter__upilabel {
    font-size: 1.1em; font-weight: 700; letter-spacing: .14em;
    text-transform: uppercase; color: var(--si-subtle);
}
.si-qrposter__upi { margin-top: .5em; font-size: 1.5em; color: var(--si-subtle); overflow-wrap: anywhere; }
.si-qrposter__note { margin-top: .9em; font-size: 1.4em; color: var(--si-subtle); overflow-wrap: anywhere; }
.si-qrposter__brand {
    margin-top: 2.2em; padding-top: 2.2em;
    border-top: .1em solid var(--si-border);
    font-size: 1.3em; font-weight: 600; letter-spacing: .06em; color: var(--si-subtle);
}

/* --- The link card ------------------------------------------------------- */
/*
   THE URL TOOL'S CARD — a sibling of the payment poster above, not a mode
   of it.

   It shares the design language deliberately (same 680-unit canvas, same
   white plate, same hairline over the attribution) and shares none of the
   payment vocabulary: no payee, no amount, no acceptance row. A link is
   opened by a camera, and a row of payment logos under a menu link would
   be a plain lie.

   EVERY NUMBER BELOW HAS A TWIN IN qr-card.js AT TEN TIMES THE SIZE.
   `.si-qrout` is a `container-type: inline-size` and this `font-size` is
   `100cqw / 68`, so `1em` is ten design units and the preview is an exact
   scale model of the 2040px download. Change one, change both.
*/
.si-urlcard {
    font-size: 6.3px;
    font-size: calc(100cqw / 68);
    width: 100%;
    padding: 2em;
    text-align: center;
    background: var(--si-surface);
    border-radius: 2.8em;
    box-shadow: var(--si-shadow);
    color: var(--si-navy);
}
.si-urlcard__eyebrow {
    font-size: 1.3em; font-weight: 700; letter-spacing: .14em;
    text-transform: uppercase; color: var(--si-subtle);
}
/* WITH NO LABEL THE CARD CLOSES UP. The row is `hidden`, not emptied, so
   the margin below goes with it — an empty band where a heading would be
   reads as a broken render rather than as a plain card. */
.si-urlcard__title {
    margin-top: 1em; font-size: 3.4em; font-weight: 700;
    letter-spacing: -.02em; line-height: 1.24; overflow-wrap: anywhere;
}
/* The white plate is not decoration: the quiet zone is part of the QR
   specification, and a symbol drawn straight onto a tinted card
   intermittently fails to scan. */
.si-urlcard__plate {
    width: 43.6em; max-width: 100%; margin: 2.4em auto 0; padding: 1.8em;
    border-radius: 2.2em; background: #fff;
    box-shadow: 0 0 0 .15em var(--si-border);
}
.si-urlcard__plate svg { display: block; width: 100%; height: auto; }
/* THE DESTINATION IS THE SECOND-LARGEST THING ON THE CARD, under the
   symbol it belongs to. Somebody deciding whether to scan reads the host;
   a card that hides it is asking them to trust an anonymous square. */
.si-urlcard__dest {
    margin-top: 2.2em; font-size: 2.2em; font-weight: 600;
    letter-spacing: -.01em; line-height: 1.3; overflow-wrap: anywhere;
}
.si-urlcard__scan { margin-top: 1.1em; font-size: 1.5em; color: var(--si-subtle); }
.si-urlcard__brand {
    margin-top: 2.2em; padding-top: 2.2em;
    border-top: .1em solid var(--si-border);
    font-size: 1.3em; font-weight: 600; letter-spacing: .06em; color: var(--si-subtle);
}

/* --- What the code actually contains ------------------------------------- */
/*
   The card shows the address as a person reads it — no scheme, no `www.`,
   a long query string trimmed. This is the unshortened original, so
   nobody has to trust that shortening or scan their own code to find out
   what is in it. It is a panel rather than a caption because a 300-
   character URL is a paragraph, and it must be able to wrap without
   pushing the card around.
*/
.si-qrdest {
    display: grid; gap: .25rem;
    padding: var(--si-s3) var(--si-s4);
    border-radius: 12px;
    background: var(--si-bg-alt);
    box-shadow: inset 0 0 0 1px rgba(var(--shadow-rgb), .06);
}
.si-qrdest__label {
    font-size: .6875rem; font-weight: 700; letter-spacing: .05em;
    text-transform: uppercase; color: var(--si-muted);
}
/* `--si-muted`, not `--si-subtle`: this sits on the tinted ground, where
   `--si-subtle` measures 4.35:1 and misses AA for small text. */
.si-qrdest__value { font-size: .8125rem; line-height: 1.55; color: var(--si-navy); overflow-wrap: anywhere; }


/* The raw exports, folded away. A designer's need, not the visitor's
   first decision — see the note in the view. */
.si-more--raw > summary { font-size: .8125rem; }


/* --- The bare symbol ----------------------------------------------------- */
.si-qrplain {
    width: 100%;
    background: var(--si-surface); border-radius: var(--si-radius);
    padding: var(--si-s5); box-shadow: var(--si-shadow);
}
.si-qrpanel__code {
    width: 100%; max-width: 19rem; margin: 0 auto;
    aspect-ratio: 1 / 1;
    display: flex; align-items: center; justify-content: center;
    border-radius: 12px; background: #fff;
}
.si-qrpanel__code svg { display: block; width: 100%; height: auto; border-radius: 8px; }

/* WHAT IS IN THE CODE, IN WORDS. A merchant cannot proof-read a QR
   symbol; they can proof-read five lines of text. */
.si-qrpanel__meta {
    margin-top: var(--si-s4); padding-top: var(--si-s4);
    border-top: 1px solid var(--si-border);
    display: flex; flex-direction: column; gap: .55rem;
}
.si-qrpanel__row { display: grid; grid-template-columns: 5.5rem minmax(0, 1fr); gap: var(--si-s3); align-items: baseline; }
.si-qrpanel__row dt { font-size: .6875rem; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--si-subtle); }
.si-qrpanel__row dd { font-size: .875rem; color: var(--si-navy); overflow-wrap: anywhere; }
.si-qrpanel__row dd.si-mono { font-size: .8125rem; }

/* --- Status, actions and the privacy line -------------------------------- */
/* The live region is a real line of text rather than a toast: a toast that
   has faded is a message a slow reader never received. */
.si-qrstatus { min-height: 1.15rem; font-size: .75rem; color: var(--si-subtle); }
.si-qrstatus:empty { min-height: 0; }

/* ONE PRIMARY ACTION, THEN THE REST. Six equal buttons is a toolbar, and a
   toolbar makes the merchant choose before they know what the choices
   mean. */
.si-qractions { display: grid; gap: var(--si-s2); }
.si-qractions__primary { width: 100%; }
.si-qractions__primary svg { width: 16px; height: 16px; }
.si-qractions__more { display: flex; flex-wrap: wrap; gap: var(--si-s2); }
.si-qractions__more .si-btn { flex: 1 1 auto; min-height: 2.375rem; font-size: .8125rem; padding-inline: .8rem; }
/*
   FOUR SHORT LABELS COLLAPSE INTO ONE CRAMPED ROW, AND THIS STOPS THEM.

   The base rule for a secondary row is `flex: 1 1 auto`, which was
   written for the payment tool's six buttons and its longer labels ("QR
   only (PNG)", "Copy UPI link") — those wrap on a phone and each one
   ends up wide. This tool has four short ones, and at 390px they all
   fitted on a single line: 71px targets separated by 8px of gap, which
   is exactly the cramped multi-button row a thumb cannot use.

   A flex-basis wide enough for two per row is what fixes it, rather
   than a column count: two fit at 390px and grow to 171px each, three
   fit once there is room, and nothing is left holding an empty cell the
   way a fixed two-column grid does when Share is present on a phone and
   absent on a desktop.
*/
.si-qractions__more--pairs .si-btn { flex: 1 1 8rem; min-height: 2.75rem; }
/* A disabled action is dimmed AND announced as disabled. Dimmed rather
   than hidden, so the row does not change shape when it fills in. */
.si-qractions .si-btn:disabled { opacity: .38; cursor: not-allowed; }
.si-qractions .si-btn:disabled:active { transform: none; }

.si-qrprivacy {
    display: flex; align-items: flex-start; gap: .5rem;
    font-size: .75rem; line-height: 1.55; color: var(--si-muted);
}
.si-qrprivacy svg { flex: 0 0 auto; width: 15px; height: 15px; margin-top: .1rem; color: var(--si-emerald); }

/* --- Import an existing QR ----------------------------------------------- */
/*
   It sits above the first field because the merchant it is for does not
   know their UPI ID — which is why they are uploading a code.

   ON A PHONE IT IS AN ACTION, NOT A CARD.

   The tinted panel, its ring and its 16px of waist are what made this
   read as a feature card — the largest object above the fold on the page
   whose first job is a form. A phone has no room to spend 32px of
   padding introducing one button. So the mobile treatment is the button
   itself with a quiet line under it, and the card comes back at 721px
   where the column is wide enough for it to read as composition rather
   than as bulk.

   NOTHING ABOUT THE CONTROL CHANGES: same label, same input, same focus
   ring, same copy.
*/
.si-import {
    display: grid; gap: .4rem; justify-items: start;
    padding: 0; border-radius: 0; background: none; box-shadow: none;
}
.si-import__btn {
    display: inline-flex; align-items: center; gap: .45rem; cursor: pointer;
    min-height: 2.375rem; padding: .45rem .9rem; border-radius: var(--si-radius-sm);
    background: #fff; color: var(--si-navy);
    font-size: .8125rem; font-weight: 650;
    box-shadow: 0 0 0 1px rgba(var(--shadow-rgb), .13), 0 1px 2px rgba(var(--shadow-rgb), .05);
    transition: box-shadow .18s ease;
}
.si-import__btn svg { width: 15px; height: 15px; color: var(--si-action-ink); }
.si-import__btn:hover { box-shadow: 0 0 0 1px rgba(var(--shadow-rgb), .24), 0 1px 3px rgba(var(--shadow-rgb), .08); }
/* The input keeps focus and keyboard operation (it is `.si-sr`, clipped
   rather than removed); the label carries the ring so the control still
   looks focused. */
.si-import input:focus-visible + .si-import__btn {
    box-shadow: 0 0 0 1px var(--si-blue), 0 0 0 3px rgba(var(--brand-rgb), .28);
}
/* `--si-muted`, NOT `--si-subtle`. The hint sits on the import card's
   tinted ground rather than on the page, and `--si-subtle` against that
   tint measures 4.35:1 — under the 4.5 a 12px line needs. It is the same
   trap the QR placeholder fell into. */
.si-import__hint { font-size: .6875rem; line-height: 1.45; color: var(--si-muted); max-width: 46ch; }
.si-import__msg { font-size: .75rem; line-height: 1.5; font-weight: 600; }
.si-import__msg.is-good { color: var(--state-ok-ink); }
.si-import__msg.is-bad { color: var(--si-danger); }

/* --- The tools hub ------------------------------------------------------- */
/* The hub's column. See the note in views/public/tools/hub.php. */
.si-toolhub { max-width: 46rem; }

/* AUTO-FIT, SO THE COUNT DECIDES THE SHAPE. One tool fills the column as
   a wide card; two sit side by side; four wrap to two rows. Nothing here
   names a number of tools, so adding the second one changes no CSS. */
.si-toolcards {
    display: grid; gap: var(--si-s4); align-items: stretch;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
}
/* ICON BESIDE THE CONTENT, not above it: a 46rem-wide card with the icon
   stacked on top leaves a band of empty white under a two-line summary,
   which is the "oversized empty area" a one-tool hub falls into first. */
.si-toolcard {
    display: grid; grid-template-columns: auto minmax(0, 1fr);
    gap: var(--si-s4); align-items: start;
    background: var(--si-surface); border-radius: var(--si-radius);
    padding: var(--si-s5); text-decoration: none;
    box-shadow: var(--si-shadow-sm);
    transition: box-shadow .18s ease;
}
.si-toolcard:hover { box-shadow: var(--si-shadow); }
.si-toolcard .si-card__icon { margin-bottom: 0; }
.si-toolcard__body { display: flex; flex-direction: column; align-items: flex-start; height: 100%; }
.si-toolcard__title { font-size: 1rem; font-weight: 700; color: var(--si-navy); letter-spacing: -.012em; }
.si-toolcard__text { margin-top: var(--si-s2); font-size: .875rem; line-height: 1.55; color: var(--si-muted); }
/* The card is one link, so the affordance at the foot is a word, not a
   nested control: a button inside an anchor is invalid markup and a
   second tab stop for the same destination. */
.si-toolcard__go { margin-top: auto; padding-top: var(--si-s4); font-size: .8125rem; font-weight: 650; color: var(--si-action-ink); }
.si-toolcard__go::after { content: "→"; display: inline-block; margin-left: .3rem; transition: transform .18s ease; }
.si-toolcard:hover .si-toolcard__go::after { transform: translateX(2px); }

/* The roadmap: one heading and a line of names. Names of things that do
   not exist deserve exactly this much page. */
.si-toolsoon { margin-top: var(--si-s6); padding-top: var(--si-s5); border-top: 1px solid var(--si-border); }
.si-toolsoon p { margin-top: var(--si-s2); font-size: .875rem; line-height: 1.7; color: var(--si-subtle); }

.si-toolfoot { max-width: 46rem; }
.si-toolfoot .si-lede { margin-top: var(--si-s2); }
.si-toolfoot .si-btn + .si-btn { margin-left: var(--si-s2); }

/* --- The explanatory article -------------------------------------------- */
/* `.si-prose` already sets the type; this only adjusts what a page with a
   code sample and a list of failure modes needs. */
.si-qrarticle .si-code { margin: var(--si-s4) 0; font-size: .6875rem; }
.si-qrarticle .si-prose ul { margin-top: var(--si-s3); padding-left: 1.1rem; display: flex; flex-direction: column; gap: .6rem; }
.si-qrarticle .si-prose li { line-height: 1.6; }
.si-qrarticle .si-prose strong { color: var(--si-navy); font-weight: 650; }
.si-qrbridge .si-ticks { margin-top: 0; }

/* --- >= 721px ------------------------------------------------------------ */
@media (min-width: 721px) {
    .si-switch { margin-left: auto; }

    /* The card, once there is room for it to be composition. */
    .si-import {
        gap: .45rem;
        padding: var(--si-s4); border-radius: 12px;
        background: var(--si-bg-alt);
        box-shadow: inset 0 0 0 1px rgba(var(--shadow-rgb), .06);
    }
    .si-import__hint { font-size: .75rem; line-height: 1.5; }

    /* On a phone every secondary action is a full-width row because thumbs
       need the target. With room they size to their labels, and Reset
       falls to the right of the group it is not part of. */
    .si-qractions__more .si-btn { flex: 0 0 auto; }
    .si-qractions__more #upiqr-reset,
    .si-qractions__more #urlqr-reset { margin-left: auto; }
}

/* --- >= 961px: form left, code right ------------------------------------- */
@media (min-width: 961px) {
    /*
       TWO BOUNDED COLUMNS, CENTRED — NOT ONE FLEXIBLE AND ONE FIXED.

       `1fr` for the form gives it 780px on a 1200px page, and a 780px-wide
       text input beside a 350px QR code reads as a form that has been
       stretched rather than laid out. Both columns take their natural
       size and the pair sits in the middle of the page, which is how a
       focused utility is composed and what keeps the generator inside the
       first viewport at every desktop width.
    */
    /*
       THE RESULT COLUMN IS NOW THE WIDER OF THE TWO.

       It was 27rem of form against 22rem of result, which made the form
       the page's main object — on a page whose main object is the
       payment poster a merchant is about to print. Reversing the ratio
       puts roughly 60px more into the poster and takes it off a column
       of 46px-tall inputs that did not need it.
    */
    .si-qrgen {
        grid-template-columns: minmax(0, 25rem) minmax(0, 27rem);
        justify-content: center;
        gap: var(--si-s6);
        max-width: none;
    }
    /* THE RESULT FOLLOWS THE MERCHANT DOWN THE FORM. `align-self: start`
       is what makes the sticky work inside a grid row; the offset clears
       the sticky header. */
    .si-qrgen__result { position: sticky; top: 5.5rem; align-self: start; }
    .si-qrpanel__code { max-width: none; }

    /* In a 430px column the secondary row is two even columns: five
       auto-width buttons wrapping there leave a different ragged edge on
       every line. Reset takes the full width beneath them, because it is
       destructive and should not sit in a pair with Print. */
    .si-qractions__more {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    .si-qractions__more .si-btn { flex: none; }
    .si-qractions__more #upiqr-reset,
    .si-qractions__more #urlqr-reset { grid-column: 1 / -1; margin-left: 0; }
}

/* --- Print: the poster, and nothing else --------------------------------- */
/*
   A merchant printing this page wants the card for their counter, not a
   web page with a QR code somewhere in it. So everything else is removed:
   the header, the footer, the breadcrumb, the form, the article and the
   product hand-off.

   WHAT PRINTS IS WHAT IS ON SCREEN. The poster and the bare symbol are
   both real markup, so the selected preview prints as itself — there is
   no third layout that could print an amount different from the one the
   merchant just checked.
*/
/* =========================================================================
   22. GOOGLE REVIEW QR GENERATOR  (/tools/google-review-qr-code-generator)
   =========================================================================
   The second QR tool, and deliberately a SIBLING of §21 rather than a
   second copy of it. Everything structural is reused unchanged — the
   breadcrumb, the switcher, `.si-qrgen`, `.si-qrout`, `.si-qrmodes`,
   `.si-qractions`, `.si-import`, the form primitives — because two tools
   in one family that lay out differently is the failure this whole
   section exists to prevent.

   What is new is only what this tool genuinely has and the UPI one does
   not: a review poster with its own hierarchy, a share panel, a handoff
   to another tool, and the quiet note about a listing link.

   THE CLASS IS `si-grp`, NOT `si-poster` OR `si-reviewposter`.
   `.si-poster` is the landing page's merchant-poster mock (§16) and
   reusing it collapsed the UPI card the first time — the third `si-*`
   collision on this codebase. Grep before naming.
   ========================================================================= */

/* --- `hidden` HAS TO OUT-RANK A LAYOUT RULE, AGAIN ----------------------- */
/*
   `[hidden] { display: none }` lives in the USER-AGENT stylesheet and any
   author rule beats it however specific. Every class below that sets a
   `display` and is toggled with `el.hidden` needs its own escape, or the
   page renders an empty share menu, an empty handoff and a note about a
   link nobody pasted — which is exactly what §21 shipped on its first
   render. The tool toggles `el.hidden` because that is the property a
   screen reader reads, so the fix belongs here.
*/
.si-grp[hidden],
.si-tpl[hidden],
.si-handoff[hidden],
.si-kindnote[hidden],
.si-sharemenu[hidden],
.si-sharemenu__item[hidden] { display: none; }

/* The result box is the poster's ground, not a frame around it — the same
   rule §21 applies to `.si-qrposter`, stated separately so the two tools
   do not share a selector that both must edit. */
.si-qrout:has(.si-grp:not([hidden])) { background: transparent; box-shadow: none; min-height: 0; }

/* --- The review poster, replayed from compiled primitives ---------------- */
/*
   THE PREVIEW IS THE DOWNLOAD AT A DIFFERENT SCALE.

   `review-poster.js` compiles a template into a list of primitives
   positioned in a 680-unit space, and paints that list twice: onto a
   canvas for the PNG, and into this element for the preview. Every
   position below is written by the script as `calc(var(--u) * N)` with
   the SAME N the canvas uses, so there is nothing here to keep in step —
   the two cannot disagree without the arithmetic itself being wrong.

   THE ONLY JOB THIS BLOCK HAS is to define one design unit and to make
   the children obey their inline geometry. `--u` comes from the
   container's own width, so the same markup is a 110px thumbnail and a
   430px preview with no second code path.

   The `px` fallback lands first for engines without container queries;
   `--grp-h` is set inline by the painter, because a poster's height
   depends on how the merchant's name wrapped.
*/
.si-grp {
    --u: .63px;
    --u: calc(100cqw / 680);
    position: relative;
    width: 100%;
    height: calc(var(--u) * var(--grp-h, 850));
    overflow: hidden;
    border-radius: calc(var(--u) * var(--grp-radius, 30));
    background: var(--grp-bg, #fff);
    box-shadow: var(--si-shadow);
    /* A poster is a picture of text, not a paragraph: selecting across it
       yields a jumble of absolutely-positioned fragments in DOM order. */
    user-select: none;
}

/* The decoration and shape layers. Painted from the same path data the
   canvas feeds to `Path2D`, in the same 680-unit viewBox. */
.si-grp__layer {
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    overflow: visible;
    pointer-events: none;
}

.si-grp__rect { position: absolute; }

/* `line-height: 1` is load-bearing: the painter positions each line by
   subtracting the font's own ascent from the baseline it wants, and that
   calculation assumes a one-em line box. */
.si-grp__text {
    position: absolute;
    line-height: 1;
    white-space: nowrap;
    display: inline-block;
}

.si-grp__qr { position: absolute; }
.si-grp__qr svg { display: block; width: 100%; height: auto; }

/* --- The design gallery --------------------------------------------------- */
/*
   SIX DESIGNS, SHOWN AS SIX DESIGNS.

   A name is not a preview: "Warm Editorial" tells a merchant nothing
   about what they are about to print. Each option therefore carries a
   real miniature of its own poster, rendered by the same painter as the
   large one — which is also why there is no sprite sheet and no six
   exported images to ship.

   On a phone the rail scrolls sideways and snaps. Six cards stacked
   vertically would push the download button off the second screen, and a
   3x2 grid at 360px gives thumbnails too small to tell apart.
*/
/*
   `min-width: 0` IS WHAT MAKES THE RAIL SCROLL AT ALL.

   A grid item's `min-width` defaults to `auto`, which resolves to its
   MIN-CONTENT width — and the rail's min-content is six 110px cards that
   have been told `flex: 0 0 auto`, so ~710px. `overflow-x: auto` cannot
   help, because the box never gets asked to be narrower than its
   contents: instead the whole result column grew to 710px and pushed the
   page sideways at every phone width.

   Both ancestors need it. The rail is inside `.si-tpl`, which is inside
   `.si-qrgen__result`, and a single `auto` anywhere in that chain is
   enough to re-inflate the lot.
*/
.si-qrgen__result { min-width: 0; }
.si-tpl { margin-top: var(--si-s4); min-width: 0; }
.si-tpl[hidden] { display: none; }

.si-tpl__label {
    font-size: .6875rem; font-weight: 700; letter-spacing: .08em;
    text-transform: uppercase; color: var(--si-subtle);
    margin-bottom: .6rem;
}

.si-tpl__rail {
    display: flex; gap: .6rem;
    min-width: 0;
    overflow-x: auto; -webkit-overflow-scrolling: touch;
    scroll-snap-type: x proximity;
    scrollbar-width: none;
    /* Room for the focus ring and the lifted selected card, which a
       plain `overflow: auto` would otherwise clip. */
    padding: .3rem .2rem .55rem;
    margin: -.3rem -.2rem -.55rem;
}
.si-tpl__rail::-webkit-scrollbar { display: none; }

/* WIDE ENOUGH TO READ A DESIGN FROM.

   At 6.9rem the miniatures were legible as shapes and not as posters —
   a merchant could see that six things differed without being able to
   see how. 8.5rem is the width at which the headline, the plate and the
   footer treatment all resolve, and four still fit across a 360px phone
   with the fifth peeking in to say the row scrolls. */
.si-tpl__opt {
    flex: 0 0 auto;
    scroll-snap-align: center;
    width: 9.6rem;
    display: flex; flex-direction: column; gap: .5rem;
    padding: 0; border: 0; background: none;
    font: inherit; text-align: center; cursor: pointer;
    border-radius: 16px;
}
.si-tpl__opt:focus-visible { outline: 2px solid var(--si-blue); outline-offset: 3px; }

/* The miniature. Its own container, so `--u` inside resolves against
   this width and the poster scales with nothing else to change. */
/* The miniature sits on its own ground with a little air around it, so a
   poster whose own edge is pale does not dissolve into the page. Its own
   container, so `--u` inside resolves against this width and the poster
   scales with nothing else to change. */
.si-tpl__frame {
    container-type: inline-size;
    display: block; width: 100%;
    padding: .28rem;
    border-radius: 12px;
    background: var(--si-bg-alt);
    box-shadow: 0 0 0 1px var(--si-border);
    transition: box-shadow .16s ease, transform .16s ease, background-color .16s ease;
}
.si-tpl__frame .si-grp {
    display: block;
    border-radius: 6px;
    box-shadow: 0 1px 3px rgba(var(--shadow-rgb), .1);
}

.si-tpl__name {
    font-size: .8125rem; font-weight: 600; color: var(--si-subtle);
    line-height: 1.3;
    overflow-wrap: anywhere;
}

.si-tpl__opt:hover .si-tpl__frame {
    background: var(--si-surface);
    box-shadow: 0 0 0 1px var(--si-border-strong), 0 4px 12px rgba(var(--shadow-rgb), .08);
}

/* THE SELECTED STATE IS THREE SIGNALS, NOT A COLOUR.

   `aria-checked` carries it to a screen reader, the ring carries it to
   everyone else, and the name goes solid and dark so the choice survives
   a monochrome print-out and a colour-blind reader. Selection that lives
   only in a border colour is selection a third of people cannot see. */
.si-tpl__opt.is-on .si-tpl__frame {
    background: var(--si-surface);
    box-shadow: 0 0 0 2px var(--si-blue), 0 8px 20px rgba(var(--shadow-rgb), .14);
    transform: translateY(-2px);
}
.si-tpl__opt.is-on .si-tpl__name { color: var(--si-navy); font-weight: 700; }

/* --- Desktop: the gallery becomes a rail beside the preview -------------- */
/*
   A TEMPLATE BROWSER, NOT A ROW OF SETTINGS.

   Below 1200px the rail stays where the markup puts it — under the
   preview, scrolling sideways — because a third column at 1024px leaves
   the poster too small to judge, which is the one thing the page exists
   to let a merchant do.

   Above it there is room for both: the preview takes the width it needs
   and the six designs sit beside it, all visible at once with nothing to
   scroll. The areas are named so the rail can span the whole right-hand
   side without the status line, the actions and the privacy note moving.
*/
@media (min-width: 1200px) {
    /*
       THE POSTER IS THE PRODUCT, SO IT TAKES THE SPACE.

       The form is two fields and an import button; at 22rem it was a
       narrow column with a lot of air under it while the preview — the
       thing a merchant is actually judging — was capped well below the
       width available. The form shrinks to what it needs and the poster
       and its rail take the rest.
    */
    .si-qrgen {
        grid-template-columns: minmax(0, 20.5rem) minmax(0, 46rem);
        gap: var(--si-s6);
        align-items: start;
    }

    .si-qrgen__result {
        display: grid;
        grid-template-columns: minmax(0, 1fr) 10.4rem;
        grid-template-areas:
            "out     rail"
            "status  rail"
            "actions rail"
            "privacy rail";
        gap: 0 1rem;
        align-items: start;
    }

    .si-qrout     { grid-area: out; }
    .si-qrstatus  { grid-area: status; }
    .si-qractions { grid-area: actions; }
    .si-qrprivacy { grid-area: privacy; }

    /* The rail turns vertical and stops scrolling: six options fit the
       column, so snapping and an overflow are machinery with nothing to
       do. */
    .si-tpl {
        grid-area: rail;
        margin-top: 0;
        position: sticky; top: 5.5rem;
    }
    .si-tpl__rail {
        flex-direction: column;
        overflow: visible;
        scroll-snap-type: none;
        gap: .55rem;
    }
    .si-tpl__opt { width: 100%; }
}

/* --- The note under the link field --------------------------------------- */
/*
   NOT an error and not styled as one. A Maps share link produces a
   working poster; it is simply one tap longer for the customer. Amber
   would make a merchant think they had done something wrong and go
   looking for a fix they do not need.
*/
.si-kindnote {
    display: flex; align-items: flex-start; gap: .45rem;
    margin-top: .5rem;
    font-size: .75rem; line-height: 1.5; color: var(--si-muted);
}
.si-kindnote svg { flex: none; width: 15px; height: 15px; margin-top: .1rem; color: var(--si-border-strong); }
.si-kindnote strong { font-weight: 650; color: var(--si-navy-3); }

/* --- The handoff to another tool ----------------------------------------- */
/*
   Shown only when what was pasted is something ANOTHER live PayMQR tool
   handles. The view renders its targets from ToolCatalog, so this cannot
   point at a page that does not exist.
*/
.si-handoff { display: block; margin-top: .45rem; font-size: .75rem; }
.si-handoff a { color: var(--si-action-ink); font-weight: 600; text-decoration: none; }
.si-handoff a:hover { text-decoration: underline; }

/* --- Share ---------------------------------------------------------------- */
/*
   ONE CONTROL THAT OPENS A PANEL, NOT FOUR MORE BUTTONS IN THE ROW.

   A merchant sharing a poster has one intention and the channel is a
   detail inside it. Four equal-weight buttons make them answer the detail
   first, and on a phone they become a squeezed grid that pushes the
   download out of the first screen.
*/
/* THE WRAP FLEXES LIKE A BUTTON, BECAUSE IT CONTAINS ONE.

   `.si-qractions__more .si-btn { flex: 1 1 auto }` (§21) only reaches
   DIRECT children, and Share is one level down inside this wrapper — so
   without these two lines the wrapper collapses to its content and sits
   at 63px next to a stretched Print and Reset. */
.si-sharewrap { position: relative; display: inline-flex; flex: 1 1 auto; }
.si-sharewrap > .si-btn { width: 100%; }

.si-sharemenu {
    position: absolute; z-index: 20; left: 0; bottom: calc(100% + .4rem);
    min-width: 14rem; padding: .35rem;
    display: flex; flex-direction: column;
    background: var(--si-surface);
    border-radius: 12px;
    box-shadow: 0 10px 30px rgba(var(--shadow-rgb), .14), inset 0 0 0 1px var(--si-border);
}

.si-sharemenu__item {
    display: flex; align-items: center; gap: .55rem;
    padding: .55rem .6rem;
    border: 0; border-radius: 9px; background: none;
    font: inherit; font-size: .8125rem; font-weight: 550; text-align: left;
    color: var(--si-navy); text-decoration: none; cursor: pointer;
}
.si-sharemenu__item:hover { background: var(--si-bg-alt); }
.si-sharemenu__item:focus-visible { outline: 2px solid var(--si-blue); outline-offset: -2px; }
.si-sharemenu__item svg { flex: none; width: 17px; height: 17px; color: var(--si-subtle); }

/* --- The "where do I find my link" disclosure ---------------------------- */
.si-more__body { margin-top: .6rem; font-size: .8125rem; line-height: 1.6; color: var(--si-muted); }
.si-more__body p + p { margin-top: .5rem; }
.si-more__body strong { font-weight: 650; color: var(--si-navy-3); }

/* --- Phone ---------------------------------------------------------------- */
/*
   The panel opens ABOVE the button on a phone and is pinned to the row's
   width, because a 14rem menu anchored to a button near the right edge
   hangs off the screen — and a share menu that causes a horizontal scroll
   is a share menu that gets closed.
*/
@media (max-width: 30rem) {
    /*
       THE PANEL ANCHORS TO THE ACTIONS ROW, NOT TO THE BUTTON.

       `left: 0; right: 0` resolves against the nearest POSITIONED
       ancestor, which was `.si-sharewrap` — so on a phone the panel came
       out exactly as wide as the Share button: 63px, with "Share on
       WhatsApp" wrapping to four lines inside it. Measured at 390px and
       360px; the earlier `min-width: 0` made it worse rather than better,
       which is the tell that the anchor was wrong and not the width.

       Making the row the containing block gives the panel the row's full
       width, and costs nothing above this breakpoint where the 14rem
       minimum already fits beside the button.
    */
    .si-qractions__more { position: relative; }
    .si-sharewrap { position: static; }
    .si-sharemenu { left: 0; right: 0; min-width: 0; }
}

/* At the two-column step (§21) the row is a grid, so Reset — the one
   action that is not a sibling of the other two in meaning — takes the
   full width rather than stranding itself in a half-width cell. */
@media (min-width: 961px) {
    .si-qractions__more #grqr-reset { grid-column: 1 / -1; }
}

/* =========================================================================
   22. The acquisition page (/merchant-payments)
   =========================================================================
   A high-intent landing page has a different job from the twelve pages
   above it: a stranger who has just been refused a payment gateway must
   understand the offer in seconds and find the price without reading.

   So these four primitives are all about WEIGHT AND SCANNING, not new
   colour. Every value comes from the same tokens the rest of this file
   uses, and nothing here is loaded by any other page.
   ========================================================================= */

/* ---------- The hero chain: ONE WORKFLOW, NOT FIVE PILLS ---------------
   Five loose `.si-flow` chips read as five unrelated labels. What the
   reader needs is a sequence, so each stop carries a brand node and the
   stops are joined by the arrows rather than merely separated by them —
   and the last one inverts, because a workflow needs somewhere to end.

   A DEDICATED COMPONENT RATHER THAN MORE `.si-flow` OVERRIDES. `si-flow`
   is shared with the landing page and `/how-it-works`; this hero wanted
   different type, different chip weight and a different terminal, and
   three overrides on a shared primitive is how a primitive stops being
   one. Nothing else uses `si-chain`.

   THE WIDTH IS MEASURED. The hero copy column is 609px at 1440 and the
   five stops come to ~560px here, so the row does not wrap. Re-measure
   before lengthening a label. */
.si-chain { list-style: none; display: flex; flex-wrap: wrap; align-items: center; gap: .3rem 0; }
.si-chain li { display: inline-flex; align-items: center; }
.si-chain__node {
    display: inline-flex; align-items: center; gap: .3rem;
    padding: .26rem .5rem .26rem .42rem; border-radius: 999px;
    background: var(--si-surface); color: var(--si-navy);
    font-size: .6875rem; font-weight: 650; letter-spacing: -.005em; white-space: nowrap;
    box-shadow: 0 0 0 1px rgba(var(--shadow-rgb), .1), 0 1px 1.5px rgba(var(--shadow-rgb), .04);
}
/* The node marker, in the brand. A ring rather than a larger dot, so the
   chip height is set by the type and every stop sits on one baseline. */
.si-chain__dot {
    width: 5px; height: 5px; border-radius: 50%; flex: 0 0 auto;
    background: var(--si-blue); box-shadow: 0 0 0 2.5px rgba(var(--brand-rgb), .22);
}
.si-chain li:last-child .si-chain__node { background: var(--si-navy); color: var(--si-invert); box-shadow: none; }
.si-chain li:last-child .si-chain__dot { box-shadow: 0 0 0 2.5px rgba(var(--brand-rgb), .3); }
.si-chain__arrow { color: var(--si-subtle); font-size: .6875rem; padding: 0 .22rem; }

/* ON A PHONE IT TURNS, IT DOES NOT SHRINK. A five-stop row at 375px
   either wraps into a ragged block or squeezes the type below legibility;
   a column reads in one pass and costs 5 short lines. */
@media (max-width: 600px) {
    .si-chain { flex-direction: column; align-items: flex-start; gap: 0; }
    .si-chain li { flex-direction: column; align-items: flex-start; }
    .si-chain__arrow { transform: rotate(90deg); padding: .05rem 0 .05rem .6rem; }

    /* AND THE ACTION OVERTAKES IT.

       Turned vertical the chain is five rows — about 180px — and it sat
       between the lede and the button, which put Start free at y=707 on a
       812px phone: visible, but only just, and only on a tall one. Swapped,
       the button lands around y=530 with the chain reading underneath it,
       which costs the chain nothing (it is a diagram, not a step the reader
       must take first) and buys the page its primary action above the fold.

       `order` is a sort key on the hero grid — see §7, where the copy
       column dissolves into it — so this is two integers, not a reflow. */
    .si-hero__cta { order: 2; }
    .si-hero__chain { order: 3; margin-top: var(--si-s5); }
}

/* ---------- The hero product composition -------------------------------
   FOUR REAL PAYMQR SURFACES, ARRANGED AS ONE PICTURE.

   The hero used to show a single checkout card. That says what the
   customer sees and nothing about what the merchant gets, so the reader
   had to take the money path from a paragraph. This draws it: the
   account the money lands in, the checkout that asks for it, the
   verification that settles it, and the dashboard row it becomes —
   top to bottom, in that order.

   FOUR, AND NOT MORE. The landing page's own rule is that three floating
   fragments is a collage; these are not floating. The source bar and the
   ledger strip are anchored to the composition's own column and the
   verification card is the single overlay, so the group reads as one
   object rather than as scattered chrome.

   Everything here is `aria-hidden` under one labelled `role="img"`: it is
   a picture of the product, and a screen reader should hear the sentence
   once, not the contents of four mock cards. */
.si-viz { position: relative; isolation: isolate; display: grid; gap: .55rem; }

/* The glow and the dot field, both behind everything (`z-index: -1`
   inside the component's own isolation, so neither can slide behind the
   section itself). Two very quiet layers, no gradient anywhere else. */
.si-viz::before {
    content: ""; position: absolute; z-index: -1; pointer-events: none;
    inset: -12% -8% 18% -8%;
    background:
        radial-gradient(60% 45% at 50% 32%, rgba(var(--brand-rgb), .30), rgba(var(--brand-rgb), 0) 70%);
}
.si-viz::after {
    content: ""; position: absolute; z-index: -1; pointer-events: none;
    inset: 0; border-radius: var(--si-radius-lg);
    background-image: radial-gradient(rgba(var(--shadow-rgb), .13) 1px, transparent 1px);
    background-size: 16px 16px;
    /* Fades out at the edges so the field reads as texture under the
       cards rather than as a bordered panel behind them. */
    mask-image: radial-gradient(70% 55% at 50% 45%, #000 35%, transparent 78%);
    -webkit-mask-image: radial-gradient(70% 55% at 50% 45%, #000 35%, transparent 78%);
}

/* Each stop carries its own name. This is what replaces the paragraph:
   the labels ARE the flow, read down the composition. */
.si-viz__step {
    display: flex; align-items: center; gap: .4rem;
    font-size: .625rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
    color: var(--si-subtle);
}
.si-viz__step::before {
    content: ""; width: 5px; height: 5px; border-radius: 50%; flex: 0 0 auto;
    background: var(--si-blue); box-shadow: 0 0 0 2.5px rgba(var(--brand-rgb), .2);
}
/* The connector: a hairline from each label down to the surface it names. */
.si-viz__step::after {
    content: ""; flex: 1 1 auto; height: 1px;
    background: linear-gradient(90deg, rgba(var(--shadow-rgb), .18), rgba(var(--shadow-rgb), 0));
}

/* The account the money actually lands in — the fact this whole page is
   about, drawn first because it is the merchant's own. */
.si-viz__acct {
    display: flex; align-items: center; gap: .5rem;
    padding: .5rem .7rem; border-radius: 12px;
    background: var(--si-surface);
    box-shadow: 0 0 0 1px rgba(var(--shadow-rgb), .09), 0 1px 2px rgba(var(--shadow-rgb), .04);
}
.si-viz__vpa { font-size: .75rem; font-weight: 650; color: var(--si-navy); font-variant-numeric: tabular-nums; }
.si-viz__owner { font-size: .6875rem; color: var(--si-subtle); margin-left: auto; }

/* The checkout, and the one element allowed to overlap it. */
.si-viz__main { position: relative; }
.si-viz__main .si-pay { max-width: 19rem; }

.si-viz__ok {
    /* MEASURED: at 1440 the card is 304px in a 543px column, so the
       overlay covers 84px of the card's right edge and NONE of the QR —
       it annotates the surface rather than sitting on it. Flush with the
       figure's own right edge, because hanging past it clips at the
       narrower desktop column between 961px and 1280px. */
    position: absolute; z-index: 2; right: 0; top: 38%; max-width: 14rem;
    display: inline-flex; align-items: center; gap: .45rem;
    padding: .45rem .7rem .45rem .5rem; border-radius: 12px;
    background: #fff; color: var(--si-navy);
    font-size: .75rem; font-weight: 700; letter-spacing: -.012em; white-space: nowrap;
    box-shadow:
        0 0 0 1px rgba(var(--shadow-rgb), .06),
        0 2px 4px rgba(var(--shadow-rgb), .05),
        0 16px 30px -16px rgba(var(--shadow-rgb), .36);
}
.si-viz__ok small { display: block; font-size: .625rem; font-weight: 500; color: var(--si-subtle); letter-spacing: 0; }

/* The record it becomes. Two rows is enough to say "this is a list you
   can work from"; six would be a second product visual. */
.si-viz__log {
    border-radius: 12px; overflow: hidden; background: var(--si-surface);
    box-shadow: 0 0 0 1px rgba(var(--shadow-rgb), .09), 0 1px 2px rgba(var(--shadow-rgb), .04);
}
.si-viz__row {
    display: flex; align-items: center; gap: .5rem;
    padding: .45rem .7rem; font-size: .6875rem; color: var(--si-muted);
}
.si-viz__row + .si-viz__row { border-top: 1px solid rgba(var(--shadow-rgb), .07); }
.si-viz__ref { font-weight: 650; color: var(--si-navy); font-variant-numeric: tabular-nums; }
.si-viz__amt { margin-left: auto; font-weight: 650; color: var(--si-navy); font-variant-numeric: tabular-nums; }
.si-viz__state { display: inline-flex; align-items: center; min-width: 5.4rem; }

/* PHONES UN-OVERLAP IT. An overlay on a 375px column either covers the
   card it annotates or shrinks below reading size; static, it becomes the
   fourth thing in a four-item sequence, which is what it always was. */
@media (max-width: 600px) {
    .si-viz__main .si-pay { max-width: none; }
    .si-viz__ok { position: static; width: 100%; justify-content: flex-start; }
}

@media (min-width: 961px) {
    /* The composition is the hero's tallest object at desktop; letting it
       breathe against the copy column is what stops the two reading as a
       card beside a paragraph. */
    .si-viz { gap: .7rem; }
}

/* ---------- Situation cards --------------------------------------------
   The four places this reader is stuck.

   THE SECTION HAD TO CARRY MORE WEIGHT THAN A PARAGRAPH IN A BOX. It is
   the moment a stranger decides the page is about them, and four plain
   `.si-card`s said "here is some more text". These are the same card
   language — same surface, same radius, same ring — with three additions
   that cost no colour and no noise: a brand wash behind the glyph, a
   filled icon tile rather than a tinted one, and a ghosted index so the
   four read as a set rather than as four unrelated statements.

   The hover is a real affordance even though nothing here is clickable:
   it is what makes a grid of cards feel like a product surface rather
   than a printed page. */
.si-sits { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--si-s4); }

.si-sit {
    position: relative; overflow: hidden; isolation: isolate;
    background: var(--si-surface);
    border-radius: var(--si-radius);
    padding: var(--si-s5);
    box-shadow: var(--si-shadow-sm);
    transition: box-shadow .2s ease, transform .2s ease;
}
/* The wash sits BEHIND the content (`z-index: -1` inside the card's own
   isolation) so the glyph and the title keep their full contrast. */
.si-sit::before {
    content: ""; position: absolute; top: 0; left: 0; z-index: -1;
    width: 15rem; height: 11rem; pointer-events: none;
    transform: translate(-30%, -48%);
    background: radial-gradient(closest-side, rgba(var(--brand-rgb), .22), rgba(var(--brand-rgb), 0) 74%);
}
/* A BRAND RULE ALONG THE TOP EDGE, drawn in and not merely revealed: it
   grows from the left, which is the direction the row is read in. Always
   present at 0 width so nothing reflows on approach. */
.si-sit__edge {
    position: absolute; top: 0; left: 0; height: 3px; width: 0;
    border-radius: var(--si-radius) var(--si-radius) 0 0;
    background: linear-gradient(90deg, var(--si-blue), rgba(var(--brand-rgb), .35));
    transition: width .28s ease;
}
@media (hover: hover) {
    .si-sit:hover {
        transform: translateY(-2px);
        box-shadow: 0 0 0 1px rgba(var(--brand-rgb), .5),
                    0 1px 2px rgba(var(--shadow-rgb), .05),
                    0 14px 28px -16px rgba(var(--shadow-rgb), .38);
    }
    .si-sit:hover .si-sit__edge { width: 100%; }
}
/* Reduced motion keeps the state, drops the travel. */
@media (prefers-reduced-motion: reduce) {
    .si-sit, .si-sit__edge, .si-sit__n { transition: none; }
    .si-sit:hover { transform: none; }
}

.si-sit__icon {
    display: inline-flex; align-items: center; justify-content: center;
    width: 42px; height: 42px; border-radius: 12px;
    background: var(--si-blue); color: var(--si-on-action);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .22),
                0 2px 8px -3px rgba(var(--brand-rgb), .8);
}
.si-sit__icon svg { width: 20px; height: 20px; }

/* THE GLYPH AND THE NUMERAL SHARE A ROW, AND A HAIRLINE CLOSES IT.

   The index used to float in the corner with nothing to belong to, which
   reads as decoration on a card rather than as part of a set. Paired with
   the icon across one ruled row it becomes the card's header: symbol on
   the left, position on the right, the statement underneath. Three
   registers instead of two, and no extra text to get there. */
.si-sit__head {
    display: flex; align-items: center; gap: var(--si-s3);
    padding-bottom: var(--si-s4);
    border-bottom: 1px solid rgba(var(--shadow-rgb), .08);
}
.si-sit__n {
    margin-left: auto;
    font-size: 1.125rem; font-weight: 700; letter-spacing: .02em;
    color: var(--si-border-strong); font-variant-numeric: tabular-nums;
    transition: color .2s ease;
}
@media (hover: hover) {
    .si-sit:hover .si-sit__n { color: var(--si-action-ink); }
}
.si-sit__title {
    margin-top: var(--si-s4);
    font-size: 1.0625rem; font-weight: 650; color: var(--si-navy);
    letter-spacing: -.014em; line-height: 1.3;
}
.si-sit__text {
    margin-top: .45rem;
    color: var(--si-muted); font-size: .875rem; line-height: 1.6;
}

/* ---------- The relevance strip ----------------------------------------
   Four properties, ruled rather than boxed.

   Deliberately NOT another card grid: the situation cards above and the
   plan cards below are the page's two card moments, and a third between
   them turns a rhythm into wallpaper. A brand rule over each cell is
   enough structure for four short statements.

   This is `.si-trust` without its emerald lead cell, which promotes one
   of four arbitrary items on a page whose accent is the yellow. */
.si-why { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--si-s5) var(--si-s5); }
.si-why__item { padding-top: var(--si-s3); border-top: 2px solid var(--si-blue); }
.si-why__title {
    font-size: .9375rem; font-weight: 700; color: var(--si-navy); letter-spacing: -.012em;
}
.si-why__text { margin-top: .35rem; color: var(--si-muted); font-size: .8125rem; line-height: 1.6; }

@media (min-width: 720px) {
    .si-sits { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .si-why { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 961px) {
    .si-why { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* ---------- Plans: NOTHING IS OVERRIDDEN HERE, ON PURPOSE --------------
   `/merchant-payments` renders the SAME `.si-plan--quad` cards `/pricing`
   does, from the same catalogue array and with the same nine rows — so
   the two pages cannot disagree about a price, a ceiling or a capability,
   and a merchant who arrives here sees the section they would have seen
   on the pricing page.

   A two-column step for large phones was written here and then removed:
   §15's breakpoints are MEASURED, not chosen. Two columns before 700px
   gives ~215px cards, and "Payment verifications · 10,000/month" needs
   ~233px — every card would wrap that row, and a wrapped row knocks one
   card's list off its neighbours' baseline. Stacking below 700px is the
   correct mobile presentation, and it is exactly what /pricing does.
   Consistency here is parity of component and data, not a second grid. */

@media print {
    .si-skip,
    .si-header,
    .si-footer,
    .si-toolbar,
    .si-section:not(.si-qrsec) { display: none !important; }

    .si-qrsec { padding: 0 !important; }
    .si-qrsec .si-toolhead,
    .si-qrgen__form,
    .si-qrmodes,
    .si-qrstatus,
    .si-qractions,
    .si-qrdest,
    .si-qrprivacy { display: none !important; }

    .si-qrgen { display: block !important; max-width: none !important; }
    .si-qrout {
        background: none !important; box-shadow: none !important;
        min-height: 0 !important; display: block !important;
    }

    /* 150mm of a 680-unit design: an A4 sheet with a printable counter
       card in the middle of it. */
    .si-qrposter {
        font-size: 2.2mm;
        width: 150mm; margin: 0 auto;
        box-shadow: 0 0 0 .15em var(--si-border) !important;
        break-inside: avoid;
    }
    .si-qrplain { box-shadow: none !important; max-width: 120mm; margin: 0 auto; }

    /* The link card, at the same 150mm of a 680-unit design. */
    .si-urlcard {
        font-size: 2.2mm;
        width: 150mm; margin: 0 auto;
        box-shadow: 0 0 0 .15em var(--si-border) !important;
        break-inside: avoid;
    }

    /* Backgrounds are dropped by default in print, and the acceptance
       well and the plate are both defined by theirs. */
    .si-qrposter, .si-qrposter__plate, .si-qrposter__apps,
    .si-urlcard, .si-urlcard__plate {
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }

    /* THE REVIEW POSTER PRINTS ON THE SAME TERMS (§22).

       The tools share `.si-qrsec`, `.si-qrgen__form`, `.si-qractions` and
       the rest, so everything above already hides the right things on
       this page too — a second tool inherits the print stylesheet by
       using the family's class names. Only the poster itself is its own
       element, and it needs the same 150mm and the same colour
       adjustment, or the plate prints as white-on-white and the symbol
       loses the quiet zone that makes it scannable. */
    /* THE DESIGN PICKER IS NOT PART OF THE POSTER. It sits outside
       `.si-qractions`, so it needs its own line here or a merchant gets a
       sheet of paper with six thumbnails on it. */
    .si-tpl { display: none !important; }

    /* 150mm ON THE CONTAINER, NOT ON THE POSTER.

       `.si-grp` derives its design unit from `100cqw` — its container's
       width — so constraining the poster itself would leave every
       position inside it scaled to the screen. Bounding `.si-qrout` is
       what actually resizes the card, and the poster follows at 100%. */
    .si-qrout { width: 150mm !important; margin: 0 auto !important; }

    .si-grp {
        box-shadow: 0 0 0 .3mm var(--si-border) !important;
        break-inside: avoid;
    }

    /* Backgrounds are dropped by default in print, and on these six
       designs the ground, the plate and every band are defined by
       theirs — without this the symbol prints white on white. */
    .si-grp, .si-grp__rect, .si-grp__layer, .si-grp__qr {
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }
}
