/* Meridian.
   Light, calm, sidebar app shell. Benchmarked on what Nigerian customers
   already recognise rather than on Western SaaS.

   The palette derives from the two tokens the backend emits, so one colour
   choice in the owner console moves the whole pack.

   ⚠ ONE HUE, NEVER TWO. The balance card and the signed-out panel carry a
   tonal ramp of the owner's own colour — dark stop to full stop, plus a wide
   soft glow of their accent. Owner's decision, 16 October 2026, replacing an
   earlier blanket "no gradients" rule. What that rule was actually protecting
   against is a MESH of unrelated hues, which is the thing that reads as
   machine-made; a single colour going lighter across a balance card is what
   Moniepoint, Opay and Kuda all do, and it is the one place on the page where
   depth is worth having. Two hues meeting in a diagonal is still forbidden.

   ⚠ THE RAMP IS DERIVED, NOT WRITTEN. The demo this pack is benchmarked
   against hardcodes one blue for all three stops. Copying those literals
   would paint every tenant the same blue and silently throw away the branding
   they chose, so every stop below is a `color-mix` off `--t-brand`.

   ⚠ The dark stop DARKENS and never lightens, and that is load-bearing.
   `--t-brand-ink` is picked server side for contrast against the flat brand:
   white for a dark brand, near-black for a pale one. Darkening can only help
   white ink, and a pale brand darkened by a fifth is still pale enough for
   dark ink. Lightening the stop instead would break the white-ink case, which
   is most tenants. */

:root {
  --rif-template-id: "rif-tpl-mer-4a17c9e2";

  --brand:      var(--t-brand);
  --brand-ink:  var(--t-brand-ink);
  --accent:     var(--t-accent);
  --accent-ink: var(--t-accent-ink);

  --brand-dark: color-mix(in srgb, var(--t-brand) 82%, black);
  --brand-deep: color-mix(in srgb, var(--t-brand) 76%, black);
  --brand-50:   color-mix(in srgb, var(--t-brand) 8%,  white);
  --brand-100:  color-mix(in srgb, var(--t-brand) 16%, white);

  --ink:       #0A1628;
  --ink-2:     #334155;
  --muted:     #64748B;
  --line:      #E4E8EF;
  --line-soft: #EEF1F6;
  --bg:        #FFFFFF;
  --surface:   #F6F8FB;
  --surface-2: #EFF3F8;

  --ok:     #12A150;  --ok-bg:     #E7F6EC;
  --warn:   #B7791F;  --warn-bg:   #FDF4E3;
  --danger: #D64545;  --danger-bg: #FCEDED;

  /* ⚠ The ramp is scaled by the console's radius choice, which until now
     reached the landing page and stopped at the app shell: every corner of
     the signed-in site ignored it. `--t-radius-scale` defaults to 1.00, so a
     tenant who left it alone renders byte-identically to before. */
  --r-xs: calc(8px  * var(--t-radius-scale, 1));
  --r-sm: calc(10px * var(--t-radius-scale, 1));
  --r:    calc(14px * var(--t-radius-scale, 1));
  --r-lg: calc(20px * var(--t-radius-scale, 1));
  --r-pill: 999px;

  --shadow-sm: 0 1px 2px rgba(16,24,40,.05);
  --shadow: 0 1px 2px rgba(16,24,40,.05), 0 8px 24px rgba(16,24,40,.05);

  --sidebar: 260px;
  --topbar:  64px;
}

/* The two layers every brand-filled surface uses. ⚠ ONE RULE, BOTH
   SELECTORS, rather than a utility class the templates have to remember or a
   second copy of the stops. The balance card and the signed-out panel are the
   only two surfaces in this pack that are filled with the owner's colour, and
   a change of mind about depth has to be one edit or they drift. */
.balance,
.auth__aside {
  background:
    radial-gradient(620px 320px at 92% 6%,
      color-mix(in srgb, var(--t-accent) 30%, transparent), transparent 64%),
    linear-gradient(140deg, var(--brand-deep) 0%, var(--brand) 100%);
  color: var(--brand-ink);
}

/* ── shell ───────────────────────────────────────────────────── */

.shell { display: grid; grid-template-columns: var(--sidebar) minmax(0, 1fr);
         min-height: 100vh; }

.side {
  background: var(--bg);
  border-right: 1px solid var(--line);
  display: flex; flex-direction: column;
  position: sticky; top: 0; height: 100vh;
}

/* The sidebar scrolls its own nav and keeps the brand and the sign-out
   anchored. ⚠ `min-height: 0` on the scrolling child: a flex item defaults
   to `auto`, which refuses to shrink below its content, so a shop selling
   all eight services pushed sign-out off the bottom of the screen instead
   of scrolling the list. */
.side__brand { padding: 18px 16px 14px; border-bottom: 1px solid var(--line-soft);
               flex: none; }
.side__nav { flex: 1; min-height: 0; overflow-y: auto; padding: 14px 12px 20px; }
.side__foot { padding: 12px; border-top: 1px solid var(--line-soft); flex: none; }

/* The group headings. A flat list of eleven links reads as a wall; four
   labelled runs of two or three is the shape every banking app uses, and it
   is the difference between a nav you scan and one you read. */
.side__group { font-size: .68rem; font-weight: 800; text-transform: uppercase;
               letter-spacing: .09em; color: #94A0B0;
               padding: 0 12px; margin: 18px 0 6px; }
.side__group:first-child { margin-top: 0; }

.brand { display: flex; align-items: center; gap: 10px; font-weight: 750;
         font-family: var(--t-font-display), var(--ui-stack); text-decoration: none;
         font-size: 1.05rem; }
.brand__mark {
  width: 34px; height: 34px; border-radius: var(--r-sm); display: grid; place-items: center;
  background: var(--brand); color: var(--brand-ink); font-weight: 800; flex: none;
}
.brand__logo { height: 34px; width: auto; max-width: 150px; }

.nav { display: flex; flex-direction: column; gap: 2px; }
.nav a {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; border-radius: var(--r-sm);
  text-decoration: none; color: var(--ink-2); font-weight: 550; font-size: .94rem;
}
.nav a:hover { background: var(--surface); color: var(--ink); }
.nav a[aria-current="page"] { background: var(--brand-50); color: var(--brand-dark);
                              font-weight: 650; }
.nav svg { width: 18px; height: 18px; flex: none; color: var(--muted); }
.nav a:hover svg { color: var(--ink-2); }
.nav a[aria-current="page"] svg { color: var(--brand); }
/* Pushed to the far end of its row: a count, or a word like "Add-on". */
.nav__tail { margin-left: auto; }

.main { min-width: 0; display: flex; flex-direction: column; }

.topbar {
  display: flex; align-items: center; gap: 12px;
  min-height: var(--topbar); padding: 10px 24px;
  border-bottom: 1px solid var(--line); background: var(--bg);
  position: sticky; top: 0; z-index: 60;
}
.topbar__title { font-weight: 700; font-family: var(--t-font-display), var(--ui-stack);
                 font-size: 1.02rem; }
.topbar__acts { margin-left: auto; display: flex; align-items: center; gap: 10px; }

/* The burger. Hidden wherever the sidebar is permanent — a control that
   opens something already open is worse than no control. */
.topbar__toggle { display: none; width: 40px; height: 40px; place-items: center;
                  border-radius: var(--r-xs); border: 1px solid var(--line);
                  background: var(--bg); color: var(--ink-2); flex: none; }
.topbar__toggle:hover { background: var(--surface); }
.topbar__toggle svg { width: 19px; height: 19px; }

/* Who is signed in. Was a bare email string in a row of two; a shop's
   customer should be able to tell at a glance which account they are in. */
.avatar { display: flex; align-items: center; gap: 9px; min-width: 0; }
.avatar__mark {
  width: 32px; height: 32px; border-radius: 50%; flex: none;
  display: grid; place-items: center;
  background: var(--brand-100); color: var(--brand-dark);
  font-size: .78rem; font-weight: 800;
}
.avatar__text { min-width: 0; line-height: 1.25; }
.avatar__name { font-size: .84rem; font-weight: 700; display: block;
                overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
                max-width: 22ch; }
.avatar__meta { font-size: .72rem; color: var(--muted); display: block; }

.content { padding: 24px; flex: 1; }

/* The page's own heading, below the bar rather than inside it. The bar
   carries one short label that never wraps; this is where a greeting and a
   sentence of context go. */
.page__head { margin-bottom: 20px; }
.page__head h1 { font-size: clamp(1.35rem, 1.2rem + .7vw, 1.7rem); margin-bottom: 4px; }
.page__head p { color: var(--muted); font-size: .9rem; margin: 0; }

/* ── pieces ──────────────────────────────────────────────────── */

.card {
  background: var(--bg); border: 1px solid var(--line);
  border-radius: var(--r); padding: 20px;
}
.card--flush { padding: 0; overflow: hidden; }

/* The head of a FLUSH card, which is the only kind that has one.
   ⚠ `.card` in this pack is padded (20px) and raw children are correct —
   that is the pack's contract and two sibling packs have the opposite one.
   So a head here belongs to `.card--flush`, and putting one inside a plain
   `.card` double-pads it. A one-region padded card wants `.row--between`
   instead, which `shared/base.css` already provides. */
.card--flush > .card__head {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 15px 20px; border-bottom: 1px solid var(--line-soft);
}
.card--flush > .card__head h2 { font-size: 1rem; margin: 0; }
.card--flush > .card__head a { font-size: .84rem; font-weight: 700;
                               color: var(--brand-dark); text-decoration: none;
                               white-space: nowrap; }
.card--flush > .card__body { padding: 20px; }

/* ⚠ NO `background` AND NO `color` HERE. Both come from the one brand-fill
   rule at the top of this file, which this rule would otherwise override by
   sitting later in the file at the same specificity. */
.balance { border-radius: var(--r-lg); padding: 24px; border: 0;
           position: relative; overflow: hidden; }
.balance__label { opacity: .82; font-size: .82rem; letter-spacing: .04em;
                  text-transform: uppercase;
                  display: inline-flex; align-items: center; gap: 7px; }
.balance__label svg { width: 15px; height: 15px; }
.balance__value { font-size: clamp(1.9rem, 1.5rem + 1.4vw, 2.5rem); font-weight: 760;
                  font-family: var(--t-font-display), var(--ui-stack); margin-top: 4px;
                  letter-spacing: -.03em; }
.balance__meta { opacity: .82; font-size: .84rem; margin-top: 8px; }

/* Hide-balance. The one gesture every Nigerian banking app has, because the
   balance is read in public. ⚠ Still only an `.icon-btn` reset underneath,
   so the resting background has to be set here or the browser's own grey
   `buttonface` rectangle lands in the middle of a brand-coloured card. */
.balance__top { display: flex; align-items: flex-start; justify-content: space-between;
                gap: 16px; }
.balance__eye { width: 36px; height: 36px; flex: none;
                display: grid; place-items: center; border-radius: var(--r-xs);
                background: rgba(255,255,255,.18); color: inherit; }
.balance__eye:hover { background: rgba(255,255,255,.3); }
.balance__eye svg { width: 18px; height: 18px; }
.balance__acts { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 20px; }

/* The foot states the account number money is transferred into, which is the
   single most-asked question a wallet gets. ⚠ Rendered only when a virtual
   account actually exists — see the note in `dashboard.html`. */
.balance__foot { display: flex; flex-wrap: wrap; gap: 10px 26px;
                 margin-top: 20px; padding-top: 16px;
                 border-top: 1px solid rgba(255,255,255,.22); font-size: .82rem; }
.balance__stat b { display: block; font-size: 1rem; font-weight: 800; }
.balance__stat span { opacity: .78; }

/* A button that sits ON the brand fill. The primary button is brand on
   brand there, which is invisible, and the ghost button's white face with a
   grey border reads as disabled. */
.btn--onbrand { background: var(--bg); color: var(--brand-dark); border: 0; }
.btn--onbrand:hover { background: var(--surface); }
.btn--onbrand-line { background: rgba(255,255,255,.14); color: inherit;
                     border: 1px solid rgba(255,255,255,.4); }
.btn--onbrand-line:hover { background: rgba(255,255,255,.24); }

/* A figure with a label and a mark. Two bare divs with an inline font-size
   was what the dashboard had; this is the shape the pack's own demo uses. */
.metric { background: var(--bg); border: 1px solid var(--line);
          border-radius: var(--r); padding: 18px; box-shadow: var(--shadow-sm); }
.metric__head { display: flex; align-items: center; justify-content: space-between;
                gap: 10px; }
.metric__label { font-size: .82rem; color: var(--muted); font-weight: 600; }
.metric__ico { width: 34px; height: 34px; flex: none; border-radius: var(--r-xs);
               display: grid; place-items: center;
               background: var(--brand-50); color: var(--brand-dark); }
.metric__ico svg { width: 17px; height: 17px; }
.metric__value { font-size: 1.5rem; font-weight: 800; letter-spacing: -.03em;
                 margin-top: 10px;
                 font-family: var(--t-font-display), var(--ui-stack); }
.metric__meta { font-size: .78rem; color: var(--muted); margin-top: 2px; }
.metric__meta a { color: var(--brand-dark); font-weight: 650; text-decoration: none; }

/* The heading above a section inside the page, as against the page's own
   heading. `h2` inherits the display family and 1.2 line height from
   `shared/base.css`; this is only the size and the space under it, which
   every page was setting with an inline `style="margin-top:32px"`. */
.section-title { font-size: 1.02rem; margin-bottom: 12px; }

/* The service grid. ⚠ ITS OWN GRID AND NOT `.grid--4`, which collapses to a
   SINGLE column at 560px — eight full-width rows to scroll past on the page
   a customer opens to buy something. Three across on a phone and two on a
   small one is what the pack's demo does and what every Nigerian payments
   app opens with. */
.tiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; }
@media (max-width: 1080px) { .tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 420px)  { .tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.tile {
  display: flex; flex-direction: column; gap: 10px; text-decoration: none;
  background: var(--bg); border: 1px solid var(--line); border-radius: var(--r);
  padding: 18px; color: inherit;
}
.tile:hover { border-color: var(--brand); }
.tile__icon {
  width: 42px; height: 42px; border-radius: var(--r-sm); display: grid; place-items: center;
  background: var(--brand-50); color: var(--brand-dark);
}
.tile__icon svg { width: 20px; height: 20px; }
.tile__name { font-weight: 650; }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 12px 18px; border-radius: var(--r-sm); border: 1px solid transparent;
  font: inherit; font-weight: 640; cursor: pointer; text-decoration: none;
}
/* ⚠⚠ AN `<svg>` WITH NO WIDTH, NO HEIGHT AND NO RULE AGAINST IT RENDERS AT
   THE CSS DEFAULT 300x150. Not small, not invisible: three hundred pixels
   wide, inside the button. Techsub and Kobopay have both had this line since
   they were written and Meridian never did — which went unnoticed only
   because no button in this pack had ever carried an icon until the balance
   card got one. Seen in a browser on the first look; no test asks the size of
   anything. */
.btn svg { width: 18px; height: 18px; flex: none; }
.btn--primary { background: var(--brand); color: var(--brand-ink); }
.btn--primary:hover { background: var(--brand-dark); }
.btn--accent { background: var(--accent); color: var(--accent-ink); }
.btn--ghost { background: var(--bg); border-color: var(--line); color: var(--ink); }
.btn--block { width: 100%; }

/* Tip presets. Meridian has no chip vocabulary, so these read as its own
   ghost buttons rather than borrowing another pack's idiom. Selection is
   `aria-pressed` because that is what tells a screen reader which amount is
   chosen; a class would style it and say nothing. */
.tip-opts { display: flex; flex-wrap: wrap; gap: 8px; }
.tip-opt { padding: 9px 14px; border-radius: var(--r); cursor: pointer;
           border: 1px solid var(--line); background: var(--bg);
           color: var(--ink); font-size: .9rem; font-weight: 600; }
.tip-opt:hover { border-color: var(--brand); }
.tip-opt[aria-pressed="true"] { background: var(--brand); border-color: var(--brand);
                                color: #fff; }
/* A bare button stretches to the full width of `.field` and a button's text
   centres by default, so it reads as a centred link. All three properties are
   set because the packs lay `.field` out differently: meridian is flex, where
   `align-self` does it, and techsub is grid, where only `justify-self` does.
   Setting both costs nothing and stops this depending on a detail of whichever
   pack happens to be installed. */
.tip-custom { align-self: flex-start; justify-self: start; text-align: left;
              margin-top: 8px; padding: 0; border: 0;
              background: none; cursor: pointer; color: var(--muted);
              font-size: .8rem; font-weight: 600; text-decoration: underline; }
.tip-custom-box { margin-top: 8px; }
.tip-custom-box[hidden] { display: none; }

/* ⚠ THE STATUS CHIP IS `.pill` AND STAYS `.pill`. The pack's demo calls the
   same component `.badge`; adding that name would give this pack two chips
   that look alike and drift, and `_status.html` — the one partial every
   order, receipt and history row reads — would have to pick. The demo's
   contribution here is the ICON, not a second class name. */
.pill {
  display: inline-flex; align-items: center; gap: 5px; padding: 3px 10px;
  border-radius: var(--r-pill); font-size: .78rem; font-weight: 650;
  /* ⚠ A chip that wraps reads as two statuses. "Failed, refunded" broke
     after the comma and "In progress" after "In" in a 128px column, which is
     the one word a customer is looking for split across two lines inside a
     coloured pill. The table scrolls instead; the chip does not fold. */
  white-space: nowrap;
}
.pill svg { width: 13px; height: 13px; flex: none; }
.pill--ok      { background: var(--ok-bg);     color: var(--ok); }
.pill--warn    { background: var(--warn-bg);   color: var(--warn); }
.pill--danger  { background: var(--danger-bg); color: var(--danger); }
.pill--neutral { background: var(--surface);   color: var(--muted); }

/* ── forms ───────────────────────────────────────────────────── */

.field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 16px; }
.field label { font-size: .875rem; font-weight: 600; color: var(--ink-2); }
.field input, .field select {
  width: 100%; padding: 12px 14px; font: inherit;
  border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--bg);
  color: var(--ink);
}
.field input:focus, .field select:focus {
  outline: 2px solid var(--brand-100); outline-offset: 1px; border-color: var(--brand);
}
.field .help { font-size: .8rem; color: var(--muted); }
.field .error { font-size: .82rem; color: var(--danger); }

.notice { padding: 12px 14px; border-radius: var(--r-sm); margin-bottom: 16px;
          font-size: .9rem; }
.notice--success { background: var(--ok-bg);     color: var(--ok); }
.notice--error   { background: var(--danger-bg); color: var(--danger); }
.notice--info    { background: var(--brand-50);  color: var(--brand-dark); }

/* ── tables become cards on a phone ──────────────────────────── */

.table { width: 100%; border-collapse: collapse; }
.table th, .table td { padding: 13px 16px; text-align: left; border-bottom: 1px solid var(--line-soft); }
.table th { font-size: .78rem; text-transform: uppercase; letter-spacing: .04em;
            color: var(--muted); font-weight: 650; }
.table tr:last-child td { border-bottom: 0; }

/* A `.table` with no `<thead>` is a label/value list, not a grid. Its labels
   live in `data-label`, and the rule that reveals those sits in the narrow
   media query below, so at desktop width those pages rendered bare values with
   nothing to say which was which. Harmless-looking on a receipt with one
   amount; on one showing an item price, a tip and a total it is three
   unexplained numbers. Add `table--kv` to any headerless table.
   The receipt uses it; beneficiaries, fund, funding and support have the same
   shape and still want it. */
.table--kv td { display: flex; justify-content: space-between; gap: 16px; }
.table--kv td::before { content: attr(data-label); color: var(--muted);
                        font-size: .8rem; font-weight: 600; }

/* A cell that carries two facts: what was bought, and where it went. One of
   them is the thing the customer is scanning for and the other is how they
   tell two identical purchases apart, so a single line holding both reads as
   neither. ⚠ These survive the phone's card mode: the `td` becomes a flex
   row with the `data-label` as its first item, and this is simply the second. */
.cell-main { display: flex; align-items: center; gap: 11px; min-width: 0; }
.cell-ico { width: 34px; height: 34px; flex: none; border-radius: var(--r-xs);
            display: grid; place-items: center;
            background: var(--brand-50); color: var(--brand-dark); }
.cell-ico svg { width: 16px; height: 16px; }
/* ⚠ The title is usually a LINK to the receipt, and a link inside a table
   arrives underlined in the browser's own link blue-on-black. Underlining
   every row of a six-row table turns the column into a wall of rules; the
   underline comes back on hover, where it means something. */
.cell-title { font-weight: 650; display: block; color: var(--ink);
              text-decoration: none; }
a.cell-title:hover { text-decoration: underline; }
/* ⚠ Capped and clipped, and 24ch is measured rather than picked. The
   destination is a phone number, an IUC or a meter number on most rows — 11
   to 13 characters, which never truncates — and a full post URL on a social
   marketing one. Uncapped, one of those rendered 273px wide and dragged the
   whole table to 739px inside a 655px card. At 24ch the table comes to 641
   and the status chip stops scrolling out of sight. A truncated URL still
   shows its host, and the row links to the receipt, which shows it whole. */
.cell-sub { font-size: .78rem; color: var(--muted); display: block;
            max-width: 24ch; overflow: hidden; text-overflow: ellipsis;
            white-space: nowrap; }
/* The time column. Its own class rather than `.cell-sub`, which is capped
   and clipped for a reason that does not apply to "18 Sep, 14:07" — and
   which must not wrap into three lines, as it did at 980px. */
.cell-when { font-size: .78rem; color: var(--muted); white-space: nowrap; }
/* Money arriving reads as a credit; money leaving is just the amount. A
   colour on both would make the table a traffic light. */
.amount-in { color: var(--ok); font-weight: 700; }

/* ── auth ────────────────────────────────────────────────────── */

/* ⚠⚠ MERIDIAN WAS THE LAST PACK ON A BARE CENTRED CARD, and it is the
   DEFAULT one, so it was most buyers' sign-in page. Techsub has had a two
   column signed-out shell since 16 September 2026 and Kobopay its own
   shape; this pack's own demo has had one all along. Half an empty screen
   on the first page a shop's customer ever sees.

   ⚠ THE DEMO'S TESTIMONIAL DOES NOT SHIP, and the slot it sat in is gone
   rather than refilled. It reads "Sample testimonial, placeholder content",
   which is honest under a demo ribbon and is fabricated social proof on a
   real business's shop, in their name, to their customers. Techsub set that
   precedent and this follows it: every line in the panel is something the
   money path actually does. */
.auth { min-height: 100vh; display: grid; grid-template-columns: 1.05fr 1fr;
        background: var(--surface); }

.auth__aside {
  position: relative; overflow: hidden;
  padding: 48px; display: flex; flex-direction: column; gap: 36px;
}
.auth__aside h2 { color: inherit; max-width: 20ch; margin-bottom: 14px; }
.auth__aside p { opacity: .82; max-width: 42ch; margin: 0; }
/* Brand on brand is invisible. The mark becomes a frosted square here, the
   same treatment the balance card's eye button gets. */
.auth__aside .brand__mark { background: rgba(255,255,255,.18); color: inherit; }

.auth__points { list-style: none; display: grid; gap: 15px; margin: 30px 0 0;
                padding: 0; }
.auth__points li { display: flex; gap: 12px; align-items: flex-start;
                   font-size: .9rem; opacity: .94; }
.auth__points svg { width: 19px; height: 19px; flex: none; margin-top: 2px; }
/* ⚠ The AUTO MARGIN IS ON THE COPY, not on the address, and not
   `justify-content` on the panel. The address is CONDITIONAL — an owner who
   has set none gets no line at all — so anything that distributes the free
   space between children lays the panel out differently depending on whether
   they filled in a field. `margin-block: auto` on the copy absorbs all of it
   into its own two margins: brand at the top, copy centred in what is left,
   address at the bottom if there is one, and the same picture either way.
   Measured at 1440x950 with no address set, where the copy had been sitting
   against the top with a third of the panel empty below it. */
.auth__aside > div { margin-block: auto; }
.auth__contact { opacity: .78; font-size: .84rem; margin: 0; }

.auth__main { display: grid; place-items: center; padding: 48px 24px;
              background: var(--bg); }
.auth__card { width: 100%; max-width: 420px; background: var(--bg);
              border: 0; border-radius: var(--r-lg); padding: 0; }
.auth__card .brand { margin-bottom: 22px; }
.auth__card h1 { font-size: clamp(1.5rem, 1.3rem + .8vw, 1.85rem); margin-bottom: 7px; }
.auth__card > p { font-size: .92rem; margin: 0 0 24px; }
.auth__switch { margin-top: 22px; font-size: .9rem; color: var(--muted);
                text-align: center; }
.auth__switch a { color: var(--brand-dark); font-weight: 700; text-decoration: none; }
.auth__switch a:hover { text-decoration: underline; }

/* The forgot-password line, which belongs ABOVE the submit button rather
   than in a third paragraph under it: somebody who needs it is looking at
   the password field, not past the button.

   ⚠ THE DEMO'S "KEEP ME SIGNED IN" TICK BOX IS NOT HERE, and that is on
   purpose: `sign_in` has no remember-me handling at all, so the box would
   have been a control that renders perfectly, is tickable, and decides
   nothing. `flex-end` and not `space-between` because there is one child; a
   second one arriving is the moment to change it. */
.form-aside { display: flex; align-items: center; justify-content: flex-end;
              gap: 12px; margin-bottom: 18px; }
.form-aside a { font-size: .84rem; color: var(--brand-dark); font-weight: 650;
                text-decoration: none; white-space: nowrap; }
.form-aside a:hover { text-decoration: underline; }

/* Show the password. ⚠ A reveal belongs on a password field on a phone,
   where a mistyped character is invisible and the only other way through is
   a password reset. Wired by `_form.html` for every password field in the
   pack, so register, reset-confirm and the PIN pages get it too.
   ⚠ `.icon-btn` resets the browser's own button face; without that reset a
   grey rectangle lands inside the field. */
.input-group { position: relative; }
.input-group input { padding-right: 46px; }
.input-group__btn { position: absolute; right: 5px; top: 50%;
                    transform: translateY(-50%);
                    width: 34px; height: 34px; display: grid; place-items: center;
                    border-radius: var(--r-xs); color: var(--muted); }
.input-group__btn:hover { background: var(--surface); color: var(--ink); }
.input-group__btn svg { width: 18px; height: 18px; }

/* ── landing ─────────────────────────────────────────────────── */

.hero { background: var(--brand); color: var(--brand-ink); }
.hero__in { padding-block: 72px; }   /* padding-block, never the shorthand */
.hero h1 { font-size: clamp(1.9rem, 4vw, 3rem); }
.hero p { opacity: .9; max-width: 52ch; }

/* ── phone ───────────────────────────────────────────────────── */

.tabbar { display: none; }

/* ⚠ The scrim exists at every width and is only made visible by the drawer
   below, because `shared/storefront.js` binds click-to-close to exactly this
   class and a conditionally-rendered one would be absent when it binds. */
.shell__scrim { position: fixed; inset: 0; z-index: 78; display: none;
                background: rgba(10,22,40,.45);
                opacity: 0; transition: opacity .22s ease, visibility .22s ease; }

@media (max-width: 900px) {
  .shell { grid-template-columns: minmax(0, 1fr); }

  /* ⚠⚠ THE SIDEBAR USED TO BE `display: none` HERE WITH NO BURGER ANYWHERE,
     and that is not a styling choice, it is four pages becoming unreachable.
     The tab bar carries six entries — dashboard, the first THREE services,
     orders and wallet — so on a phone a customer could not open Add money,
     Saved numbers, Profile or Support, and could not buy anything from the
     fourth service onwards. Adding money was reachable only by first opening
     a service page, which is to say: by a route nobody would guess.

     Techsub and Kobopay have both had this drawer since they were written.
     Meridian is the DEFAULT pack, so it was every shop that had not chosen
     otherwise, including both live ones. Found 16 October 2026 by listing
     what a 375px viewport can actually reach.

     The behaviour is already in `shared/storefront.js`: `initShell` toggles
     `is-nav-open` on `.shell` from any `[data-sidebar-toggle]`, closes on
     the scrim and on Escape, and locks the body scroll. Nothing new is
     loaded; the pack simply never had the markup or the rules. */
  .side {
    position: fixed; inset: 0 auto 0 0; z-index: 80;
    width: min(var(--sidebar), 84vw); height: 100%;
    transform: translateX(-100%);
    transition: transform .26s cubic-bezier(.22, .8, .3, 1);
    box-shadow: 0 0 0 1px var(--line);
  }
  .shell.is-nav-open .side { transform: none; }
  .shell__scrim { display: block; visibility: hidden; }
  .shell.is-nav-open .shell__scrim { opacity: 1; visibility: visible; }

  .topbar__toggle { display: grid; }
  .content { padding: 16px 16px 84px; }

  .tabbar {
    display: grid; grid-auto-flow: column; position: fixed; inset: auto 0 0 0;
    background: var(--bg); border-top: 1px solid var(--line);
    padding: 8px 4px calc(8px + env(safe-area-inset-bottom));
    z-index: 20;
  }
  /* ⚠ The last entry is a `<button>`, not a link, because it opens the
     drawer rather than going anywhere. Both selectors or it arrives wearing
     the browser's own button and sitting out of line with its five
     neighbours — `.icon-btn` in `shared/base.css` strips the chrome, and
     this is what puts it back in the grid. */
  .tabbar a, .tabbar__more { display: grid; justify-items: center; gap: 3px;
              padding: 6px 4px; text-decoration: none; color: var(--muted);
              font-size: .7rem; font-weight: 600; }
  .tabbar a[aria-current="page"] { color: var(--brand); }
  .tabbar svg { width: 20px; height: 20px; }

  /* Tables become labelled cards rather than a sideways scroll. */
  .table thead { display: none; }
  .table, .table tbody, .table tr, .table td { display: block; width: 100%; }
  .table tr { border: 1px solid var(--line); border-radius: var(--r);
              margin-bottom: 10px; padding: 6px 4px; }
  .table td { border: 0; display: flex; justify-content: space-between; gap: 16px;
              padding: 7px 12px; }
  .table td::before { content: attr(data-label); color: var(--muted);
                      font-size: .8rem; font-weight: 600; }

  /* The two-line cell stops being two lines inside a label/value row: the
     icon and the sub-line would make a 56px tall row out of each of four
     facts. The title alone is what the label is describing.

     ⚠ `.cell-main .cell-sub`, NOT every `.cell-sub`. The orders list uses
     the same class on its "To" column, where it is the only value in the
     row — hiding that one leaves a phone reading "To" with nothing after
     it, on the column that says which number an order went to. It is only
     redundant when it sits under a title inside `.cell-main`. */
  .cell-ico, .cell-main .cell-sub { display: none; }
  .cell-main { display: contents; }
}

/* The signed-out panel is the first thing to go: it is context, and the card
   is the task. ⚠ 844 to 932px is a phone in LANDSCAPE, so this collapses at
   the same 900px the app shell does rather than at a notional tablet width. */
@media (max-width: 900px) {
  .auth { grid-template-columns: minmax(0, 1fr); }
  .auth__aside { display: none; }
  .auth__main { padding: 32px 20px; }
}

/* Somebody who has asked their phone to stop animating has asked for this
   too. The drawer still opens; it simply arrives rather than slides. */
@media (prefers-reduced-motion: reduce) {
  .side, .shell__scrim { transition: none; }
}

/* ── the landing page a visitor sees before signing in ───────────────
   ⚠⚠ THIS IS THE ONLY PAGE A STRANGER JUDGES THE SHOP BY, and it was a
   1.2KB stub: a heading, a tagline and three cards, with no header, no
   footer and nothing saying what the shop sells or why to trust it. The
   demo the buyer chose from is a 28KB page. A shop that goes live looking
   unfinished is the thing the buyer notices first and we notice last.

   ⚠ Benchmark is Moniepoint, Opay and Billpoint, not Western SaaS: familiar
   structure, above-average execution. Differentiation goes into density and
   detail, never into a new visual language, because unfamiliar design costs
   trust and trust is the whole decision when money is involved.

   ⚠ NO GRADIENTS ON THIS PAGE except the photo scrim, which is an overlay
   rather than decoration. No glassmorphism, no emoji, and the brand colour is
   used as a solid here. A page with a violet-to-cyan mesh reads as
   machine-made.

   ⚠ The one exception in this pack is the signed-in balance card and the
   signed-out panel, which carry a tonal ramp of the owner's single colour —
   see the rule at the top of this file. That is one hue going darker, not two
   hues meeting, and it is deliberately NOT extended to the landing page: a
   stranger judging the shop is reading copy, and depth behind copy costs
   legibility for nothing.

   ⚠ `padding-block` and never `padding` on anything carrying `.wrap`: the
   shorthand's zero sides silently wipes `.wrap`'s 24px inline padding, which
   is what put every line of Techsub's hero copy flush against the screen edge
   below 1280px. */

.lander { --lander-ink: #10151b; --lander-soft: #5a6472; --lander-line: #e4e8ee;
          --lander-surface: #f6f8fa; color: var(--lander-ink); }

/* header */
.lhead { position: sticky; top: 0; z-index: 20; background: #fff;
         border-bottom: 1px solid var(--lander-line); }
/* `initLandingNav` sets this once the page has scrolled past 8px. Defined
   here because a script that toggles a class no stylesheet claims is a line
   of code that does nothing — the hook was being set and nothing used it. */
.lhead.is-stuck { box-shadow: 0 1px 12px rgba(16,24,40,.07); }
.lhead__in { display: flex; align-items: center; justify-content: space-between;
             gap: 16px; padding-block: 12px; }
.lhead__nav { display: flex; gap: 22px; align-items: center; }
.lhead__nav a { color: var(--lander-soft); text-decoration: none;
                font-size: .94rem; }
.lhead__nav a:hover { color: var(--lander-ink); }
.lhead__acts { display: flex; gap: 10px; align-items: center; }

/* ⚠ THE PHONE BURGER. `.lhead__nav` is `display: none` below 860px, and
   until now nothing replaced it: on a phone the landing header was a logo
   and two buttons, so Prices — a separate PAGE, not an anchor — was
   reachable only by scrolling the whole page to the footer. Techsub and
   Kobopay both have one; Meridian is the default pack and did not.

   `initLandingNav` in `shared/storefront.js` already drives this: it needs
   `[data-nav-toggle]` and `[data-site-nav]`, swaps the burger icon for a
   close mark, and closes the panel when a link inside it is followed. */
.lhead__burger { display: none; width: 40px; height: 40px; place-items: center;
                 border-radius: var(--r-xs); border: 1px solid var(--lander-line);
                 background: #fff; color: var(--lander-ink); flex: none; }
.lhead__burger svg { width: 20px; height: 20px; }
.lhead__drawer { display: none; }

@media (max-width: 860px) {
  .lhead__burger { display: grid; }
  /* ⚠ The panel is laid out but kept out of the flow until opened, rather
     than rendered conditionally: the script binds to it once at boot. */
  .lhead__drawer { display: grid; gap: 2px;
                   border-top: 1px solid var(--lander-line);
                   padding-block: 8px 12px; }
  .lhead__drawer:not(.is-open) { display: none; }
  .lhead__drawer a { padding: 12px 4px; text-decoration: none;
                     color: var(--lander-ink); font-weight: 600;
                     border-bottom: 1px solid var(--lander-surface); }
  .lhead__drawer a:last-child { border-bottom: 0; }
}

/* hero. ⚠ The scrim is the whole job: unreadable white text on a photograph
   is the most common failure of this pattern, so it is heaviest where the copy
   sits and lighter on the other side so the picture still reads. */
.lhero { position: relative; overflow: hidden; background: var(--t-brand); }
.lhero__media { position: absolute; inset: 0;
                background-image: url("hero-mobile.webp");
                background-size: cover; background-position: center; }
/* ⚠ MEASURED ON THE LIVE PAGE, NOT GUESSED. The first version faded to .34 by
   the right edge and dropped the mid-stop at 46%, so the last words of the
   lede ("result checker and") sat over a bright face and were barely readable
   at 1440. The copy column is 44rem, which is past half the width on a desktop,
   so the dark has to HOLD to about 62% and only then fall away. The photograph
   still reads on the right third, which is the whole point of using one. */
.lhero__media::after { content: ""; position: absolute; inset: 0;
  background: linear-gradient(100deg, rgba(8,12,18,.92) 0%,
              rgba(8,12,18,.86) 38%, rgba(8,12,18,.74) 62%,
              rgba(8,12,18,.42) 86%, rgba(8,12,18,.3) 100%); }
.lhero__in { position: relative; padding-block: 72px 76px; color: #fff;
             max-width: 44rem; }
.lhero h1 { font-family: var(--t-font-display), var(--ui-stack); font-size: clamp(2rem, 5vw, 3.1rem);
            line-height: 1.1; margin: 0 0 14px; }
.lhero p { font-size: clamp(1rem, 2vw, 1.14rem); line-height: 1.6;
           color: rgba(255,255,255,.9); margin: 0 0 26px; }
.lhero__acts { display: flex; flex-wrap: wrap; gap: 12px; }
.lhero__trust { display: flex; flex-wrap: wrap; gap: 18px; margin-top: 30px;
                font-size: .88rem; color: rgba(255,255,255,.88); }
.lhero__trust span { display: inline-flex; align-items: center; gap: 8px; }
.lhero__trust svg { width: 17px; height: 17px; }
.eyebrow { display: inline-flex; align-items: center; gap: 8px;
           padding: 7px 13px; border-radius: 999px; font-size: .8rem;
           font-weight: 600; letter-spacing: .01em; margin-bottom: 20px;
           background: rgba(255,255,255,.14); color: #fff; }
.eyebrow svg { width: 15px; height: 15px; }
.btn--onphoto { background: rgba(255,255,255,.14); color: #fff;
                border: 1px solid rgba(255,255,255,.38); }
.btn--onphoto:hover { background: rgba(255,255,255,.22); }
.btn--lg { padding: 14px 22px; font-size: 1rem; }

/* sections */
.lsec { padding-block: 56px; }
.lsec--surface { background: var(--lander-surface); }
.lsec__head { max-width: 42rem; margin-bottom: 26px; }
.lsec__head h2 { font-family: var(--t-font-display), var(--ui-stack);
                 font-size: clamp(1.5rem, 3vw, 2rem); line-height: 1.2;
                 margin: 0 0 10px; }
.lsec__head p { color: var(--lander-soft); margin: 0; line-height: 1.6; }

/* the service grid: big, obvious, icon-led. The pattern every Nigerian
   payments app opens with, because it is the one people already read. */
.svc { display: block; padding: 20px; background: #fff; text-decoration: none;
       border: 1px solid var(--lander-line);
       border-radius: calc(14px * var(--t-radius-scale, 1));
       color: var(--lander-ink); transition: border-color .15s, transform .15s; }
.svc:hover { border-color: var(--t-brand); transform: translateY(-2px); }
.svc__icon { display: grid; place-items: center; width: 46px; height: 46px;
             border-radius: calc(12px * var(--t-radius-scale, 1));
             background: color-mix(in srgb, var(--t-brand) 12%, #fff);
             color: var(--t-brand); margin-bottom: 14px; }
.svc__icon svg { width: 23px; height: 23px; }
.svc__name { font-weight: 650; margin-bottom: 4px; }
.svc__note { color: var(--lander-soft); font-size: .88rem; line-height: 1.5; }

/* prices: real plans at their real price, because a price list nobody can
   check is the thing a reseller's customer distrusts first. */
.plan { display: flex; align-items: baseline; justify-content: space-between;
        gap: 14px; padding: 15px 18px; background: #fff;
        border: 1px solid var(--lander-line);
        border-radius: calc(12px * var(--t-radius-scale, 1)); }
.plan__name { font-weight: 600; }
.plan__net { color: var(--lander-soft); font-size: .82rem;
             text-transform: uppercase; letter-spacing: .04em; }
.plan__price { font-weight: 700; color: var(--t-brand); white-space: nowrap; }

/* four steps */
.step { position: relative; padding-left: 52px; }
.step__n { position: absolute; left: 0; top: 0; width: 36px; height: 36px;
           display: grid; place-items: center; border-radius: 50%;
           background: var(--t-brand); color: var(--t-brand-ink, #fff);
           font-weight: 700; font-size: .95rem; }
.step__t { font-weight: 650; margin-bottom: 5px; }
.step__d { color: var(--lander-soft); font-size: .92rem; line-height: 1.55; }

/* questions people actually ask before they fund a wallet */
.faq { border: 1px solid var(--lander-line); background: #fff;
       border-radius: calc(12px * var(--t-radius-scale, 1)); padding: 16px 18px; }
.faq + .faq { margin-top: 10px; }
.faq summary { cursor: pointer; font-weight: 600; }
.faq p { color: var(--lander-soft); margin: 10px 0 0; line-height: 1.6; }

/* closing call, then the footer */
.lcta { background: var(--t-brand); color: var(--t-brand-ink, #fff);
        text-align: center; }
.lcta__in { padding-block: 54px; }
.lcta h2 { font-family: var(--t-font-display), var(--ui-stack); margin: 0 0 10px;
           font-size: clamp(1.5rem, 3vw, 2rem); }
.lcta p { margin: 0 auto 24px; max-width: 34rem; line-height: 1.6;
          color: color-mix(in srgb, var(--t-brand-ink, #fff) 82%, transparent); }
.lfoot { border-top: 1px solid var(--lander-line); background: #fff;
         padding-block: 32px; }
.lfoot__in { display: flex; flex-wrap: wrap; gap: 20px;
             justify-content: space-between; align-items: flex-start; }
.lfoot a { color: var(--lander-soft); text-decoration: none; }
.lfoot a:hover { color: var(--lander-ink); }
.lfoot__links { display: flex; flex-wrap: wrap; gap: 18px; font-size: .92rem; }
.lfoot__legal { color: var(--lander-soft); font-size: .84rem; line-height: 1.6; }

/* The price list with nothing in it. A real state, reached by a real tenant on
   its first live day, on the page a stranger reads before registering. It gets
   a composed empty state rather than one grey sentence, because the page still
   has to look like a shop that works. */
.pempty { text-align: center; max-width: 34rem; margin-inline: auto;
          padding-block: 28px 8px; }
.pempty__i { display: grid; place-items: center; width: 56px; height: 56px;
             margin: 0 auto 18px; border-radius: 16px;
             background: var(--lander-surface);
             border: 1px solid var(--lander-line); color: var(--lander-soft); }
.pempty__i svg { width: 26px; height: 26px; }
.pempty h2 { font-size: clamp(1.3rem, 2.6vw, 1.6rem); margin: 0 0 10px; }
.pempty p { color: var(--lander-soft); line-height: 1.65; margin: 0 0 22px; }
.pempty a { color: inherit; }
/* The buttons are a `.row`, which is `align-items:center` and left aligned.
   Centred here so they sit under centred copy rather than against the margin. */
.pempty .row { justify-content: center; }

/* ⚠ A phone is a phone, not a narrow desktop. 844-932px is a phone in
   LANDSCAPE, so nothing here may assume a tablet at those widths. */
@media (min-width: 768px) {
  .lhero__media { background-image: url("hero-tablet.webp"); }
  .lhero__in { padding-block: 104px 110px; }
}
@media (min-width: 1200px) {
  .lhero__media { background-image: url("hero-desktop.webp"); }
}
@media (max-width: 860px) {
  .lhead__nav { display: none; }
}
@media (max-width: 767px) {
  /* ⚠ A near-opaque vertical scrim, because below this width the copy covers
     the whole frame and a diagonal leaves half the words on bare photograph. */
  .lhero__media::after {
    background: linear-gradient(180deg, rgba(8,12,18,.82) 0%,
                rgba(8,12,18,.9) 100%); }
  .lhero__in { padding-block: 56px 60px; }
  .lhero__acts .btn { width: 100%; justify-content: center; }
  .lsec { padding-block: 40px; }
  .lfoot__in { flex-direction: column; }
}

/* ⚠ The header is sticky, so an anchor jump lands UNDER it. Measured on the
   live page: "What happens to money in my wallet?" sat behind the bar after
   following the Questions link in our own header. */
.lsec[id] { scroll-margin-top: 84px; }

/* The closing button sits on a solid brand band, where the translucent
   on-photo style reads as disabled. White solid, which is what every Nigerian
   payments app puts at the bottom of a page. */
.btn--onbrand { background: #fff; color: var(--t-brand); border: 0;
                font-weight: 650; }
.btn--onbrand:hover { background: rgba(255,255,255,.9); }

/* ── matching the demo's depth ───────────────────────────────────────
   ⚠ Benchmarked against the demo the buyer chose from, 15 Oct 2026: it runs
   TWELVE blocks and the live page ran eight. The owner's rule is that the live
   shop may build on the demo and must never fall below it.

   ⚠⚠ WHAT IS NOT COPIED ACROSS, AND WHY. The demo carries three testimonials
   labelled "Sample testimonial", a live-activity panel of invented transfers,
   and figures like "about eight seconds". All of that is honest on a page that
   says "Placeholder brand and sample data" in a ribbon at the bottom. On a real
   business's shop it is fabricated social proof and invented performance
   claims, in their name, to their customers. So the slots are kept and filled
   with things that are TRUE: their own live prices where the sample activity
   was, and what actually happens when an order fails where the testimonials
   were. */

.split { display: grid; gap: 34px; align-items: start; }
@media (min-width: 900px) { .split { grid-template-columns: 1fr 1fr; gap: 48px; } }
.split__copy p { color: var(--lander-soft); line-height: 1.65; margin: 0 0 18px; }

.ticks { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
.ticks li { display: flex; gap: 11px; align-items: flex-start; line-height: 1.5; }
.ticks svg { width: 19px; height: 19px; flex: none; margin-top: 2px;
             color: var(--t-brand); }

/* The panel beside the copy. ⚠ Real rows only — see the note above. */
.panel { background: #fff; border: 1px solid var(--lander-line);
         border-radius: calc(16px * var(--t-radius-scale, 1)); overflow: hidden; }
.panel__head { display: flex; align-items: center; justify-content: space-between;
               padding: 14px 18px; border-bottom: 1px solid var(--lander-line);
               font-weight: 650; font-size: .94rem; }
.panel__tag { font-size: .76rem; font-weight: 600; color: var(--lander-soft);
              text-transform: uppercase; letter-spacing: .05em; }
.panel__row { display: flex; align-items: center; justify-content: space-between;
              gap: 14px; padding: 14px 18px; }
.panel__row + .panel__row { border-top: 1px solid var(--lander-surface); }
.panel__foot { padding: 14px 18px; border-top: 1px solid var(--lander-line);
               background: var(--lander-surface); font-size: .88rem;
               color: var(--lander-soft); }

/* six reasons */
.reason { padding: 22px; background: #fff; border: 1px solid var(--lander-line);
          border-radius: calc(14px * var(--t-radius-scale, 1)); }
.reason__icon { display: grid; place-items: center; width: 40px; height: 40px;
                border-radius: calc(11px * var(--t-radius-scale, 1));
                background: color-mix(in srgb, var(--t-brand) 12%, #fff);
                color: var(--t-brand); margin-bottom: 13px; }
.reason__icon svg { width: 20px; height: 20px; }
.reason__t { font-weight: 650; margin-bottom: 6px; }
.reason__d { color: var(--lander-soft); font-size: .91rem; line-height: 1.55; }

/* what happens when an order fails. ⚠ This slot held testimonials in the demo;
   a real shop cannot ship invented quotes, and the refund is what their best
   sample quote was about anyway. */
.assure { background: var(--lander-ink); color: #fff; }
.assure__in { padding-block: 52px; }
.assure h2 { font-family: var(--t-font-display), var(--ui-stack); margin: 0 0 12px;
             font-size: clamp(1.5rem, 3vw, 2rem); }
.assure p { color: rgba(255,255,255,.82); line-height: 1.65; margin: 0 0 24px;
            max-width: 42rem; }
.assure__grid { display: grid; gap: 18px; }
@media (min-width: 760px) { .assure__grid { grid-template-columns: repeat(3, minmax(0,1fr)); } }
.assure__item { padding: 18px; border-radius: calc(12px * var(--t-radius-scale, 1));
                background: rgba(255,255,255,.06);
                border: 1px solid rgba(255,255,255,.12); }
.assure__t { font-weight: 650; margin-bottom: 6px; }
.assure__d { color: rgba(255,255,255,.74); font-size: .9rem; line-height: 1.55; }

/* ⚠ A tick box is not a text box. `_form.html` renders every other control
   label-above-field; a checkbox is one sentence you tick, so the box sits
   inline with its label and the whole line is the hit target. Before this
   the label floated above a lonely square with nothing under it — seen on
   "Save this number for next time" on the buy page of all three packs. */
.field--check > label {
  display: flex; align-items: center; gap: 10px;
  margin: 0; font-weight: 500; cursor: pointer;
}
.field--check input[type="checkbox"] {
  width: 18px; height: 18px; flex: none; margin: 0;
  accent-color: var(--brand); cursor: pointer;
}
