/* ==========================================================================
   boringesim — landing page
   Monochrome by design: black, white, greys. The only colour on the page is
   the app itself, inside the device. That is the whole art direction.

   House rules, enforced throughout:
   · hover is COLOUR ONLY — nothing lifts, scales or slides
   · nothing overshoots, nothing bounces, nothing travels more than ~18px
   · liquid glass appears only on things that float over another layer
   · the page is white top to bottom; the footer is the only dark surface
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Fonts — bundled, so the page renders identically with the network off
   -------------------------------------------------------------------------- */
@font-face { font-family:"Caveat"; src:url("../fonts/Caveat-Regular.ttf") format("truetype"); font-weight:400; font-style:normal; font-display:swap; }
@font-face { font-family:"Caveat"; src:url("../fonts/Caveat-Bold.ttf") format("truetype");    font-weight:700; font-style:normal; font-display:swap; }
@font-face { font-family:"Aeonik"; src:url("../fonts/Aeonik-Regular.ttf") format("truetype"); font-weight:400; font-style:normal; font-display:swap; }
@font-face { font-family:"Aeonik"; src:url("../fonts/Aeonik-Medium.ttf") format("truetype");  font-weight:500; font-style:normal; font-display:swap; }
@font-face { font-family:"Aeonik"; src:url("../fonts/Aeonik-Bold.ttf") format("truetype");    font-weight:700; font-style:normal; font-display:swap; }

/* The face that stands in for Aeonik until it downloads. Aeonik's cap height is
   0.700em against SF Pro's 0.705, so the two are close enough that no
   size-adjust is needed and the swap does not reflow the page. The old block
   here was tuned to Poppins' metrics and would have shifted every line. */
@font-face {
  font-family:"Aeonik Fallback";
  src:local("SF Pro Text"), local("Helvetica Neue"), local("Segoe UI"), local("Arial");
  ascent-override:96%; descent-override:24%; line-gap-override:0%;
}

/* --------------------------------------------------------------------------
   2. Tokens
   -------------------------------------------------------------------------- */
:root {
  /* light surfaces */
  --ink:#0b0c0f;
  --body:#5b6068;
  --muted:#6b7078;
  --page:#f5f5f6;
  --hairline:#e8e9ec;
  --hairline-strong:#d9dbe0;

  /* dark surfaces */
  --dark:#0b0c0f;
  --on-dark:#ffffff;
  --on-dark-muted:rgba(255,255,255,.64);
  --on-dark-faint:rgba(255,255,255,.58);
  --hairline-dark:rgba(255,255,255,.12);

  --control:#0b0c0f;
  --control-hover:#22242a;

  /* The nav bar writes its own glass literally, in §6 — it is the only glass
     on the page, so there are no glass tokens to share. */

  --sh-card:  0 1px 2px rgba(11,12,15,.04), 0 12px 28px -14px rgba(11,12,15,.12);
  --sh-float: 0 2px 6px rgba(11,12,15,.06), 0 18px 40px -18px rgba(11,12,15,.28);
  --sh-control:0 8px 20px -10px rgba(0,0,0,.5);

  --font:"Aeonik","Aeonik Fallback",-apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,sans-serif;

  /* ONE type ladder. Six sizes, two weights, stepped once at 768px.
     Before this the homepage used 9.5, 11.5, 13, 14, 14.5, 15, 16, 16.5, 17,
     19 and 21px plus eleven separate clamp() curves — four "body" sizes
     within 2px of each other, which reads as sloppiness rather than as
     hierarchy. Pingo runs on nine integer sizes and never lets two sit a
     pixel apart. */
  --t-h2:38px;
  --t-h1:30px;
  --t-lede:18px;
  --t-body:16px;
  --t-label:14px;
  --t-micro:12px;

  --nav-h:72px;
  --wrap:1240px;
  --gutter:clamp(20px, 4vw, 44px);
  /* One rhythm, stepped once at 768 like the type. Pingo uses 80/112 on every
     content section and never makes an exception; the gap at every boundary is
     the same number, so the page has a beat you can count. Ours was five
     different top paddings — 110, 122, 0, 150, 80 — and four bottoms. */
  --section-y:80px;
  --radius-slab:36px;

  --ease:cubic-bezier(.2,.8,.2,1);
  --dur:200ms;
}

/* The one breakpoint that carries the type. Pingo puts 100% of its type change
   at 768px too; a clamp would give a different fractional size at every width,
   which is the thing that made this page feel unsettled. */
@media (min-width:768px) {
  :root { --t-h2:56px; --t-h1:46px; --t-lede:20px; --section-y:112px; }
}

/* --------------------------------------------------------------------------
   3. Base
   -------------------------------------------------------------------------- */
*,*::before,*::after { box-sizing:border-box; }

html {
  -webkit-text-size-adjust:100%;
  scroll-behavior:smooth;
  scroll-padding-top:calc(var(--nav-h) + 32px);
  background:var(--page);
}

body {
  margin:0;
  overflow-x:hidden;
  background:var(--page);
  color:var(--ink);
  font-family:var(--font);
  font-size:var(--t-body);
  line-height:1.62;
  font-weight:400;
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
}

img { display:block; max-width:100%; }
svg { display:block; }
h1,h2,h3,h4,p,ul,figure,hr { margin:0; }
/* Headings inherit. Without this an unclassed <h1> falls through to the UA
   default of bold — which, with Aeonik, is a visibly different typeface beside
   Medium. This is the rule that lets every Pingo heading sit at 400 with no
   weight declared anywhere in their CSS. */
h1,h2,h3,h4,h5,h6 { font-size:inherit; font-weight:inherit; letter-spacing:inherit; }
ul { padding:0; list-style:none; }
hr { border:0; height:1px; background:var(--hairline); }
a { color:inherit; text-decoration:none; transition:color 160ms linear; }

:focus-visible { outline:2px solid var(--ink); outline-offset:3px; }
.footer :focus-visible { outline-color:#fff; }
::selection { background:var(--ink); color:#fff; }

.wrap { width:100%; max-width:var(--wrap); margin-inline:auto; padding-inline:var(--gutter); }
.glyph { width:1em; height:1em; flex:none; }

.sr-only {
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip-path:inset(50%); white-space:nowrap;
}

.skip-link {
  position:absolute; left:50%; top:0; translate:-50% -140%; z-index:200;
  background:#fff; color:var(--ink); padding:12px 20px; border-radius:0 0 14px 14px;
  font-size:var(--t-label); font-weight:500; transition:translate var(--dur) var(--ease);
}
.skip-link:focus-visible { translate:-50% 0; }

/* --------------------------------------------------------------------------
   4. Type
   -------------------------------------------------------------------------- */
.display {
  font-size:var(--t-h1);
  line-height:1.03;
  font-weight:500;
  letter-spacing:-.038em;
  color:var(--ink);
  text-wrap:balance;
  max-width:15ch;
}

.h2 {
  font-size:var(--t-h2);
  line-height:1.08;
  font-weight:500;
  letter-spacing:-.035em;
  color:var(--ink);
  text-wrap:balance;
}

.h3 { font-size:var(--t-lede); line-height:1.3; font-weight:500; letter-spacing:-.02em; color:var(--ink); }

.lede { font-size:var(--t-lede); line-height:1.55; color:var(--body); text-wrap:pretty; }
.lede strong { font-weight:500; color:var(--ink); }

.section-head { display:flex; flex-direction:column; gap:16px; max-width:680px; }
.section-head--center { margin-inline:auto; align-items:center; text-align:center; }
.section-head .lede { max-width:56ch; }

/* --------------------------------------------------------------------------
   5. Controls
   -------------------------------------------------------------------------- */
.btn {
  display:inline-flex; align-items:center; justify-content:center; gap:10px;
  height:52px; padding:0 26px;
  border:1px solid var(--control);
  border-radius:999px;
  background:var(--control);
  color:#fff;
  /* shorthand, so the weight sweep could not see it — this was the last 600
     on the homepage, and 600 resolves to Aeonik Bold */
  font:500 var(--t-body)/1 var(--font);
  letter-spacing:-.01em;
  white-space:nowrap;
  box-shadow:var(--sh-control);
  transition:background-color 160ms linear, border-color 160ms linear, color 160ms linear;
}
.btn:hover { background:var(--control-hover); border-color:var(--control-hover); }
.btn:active { background:#000; }
.btn--sm { height:40px; padding:0 18px; font-size:var(--t-label); box-shadow:none; }

/* Store buttons — drawn, never a downloaded badge asset.
   ONE component, one size, everywhere. It previously rendered at four
   different heights (46 / 52 / 58 / 72) and three radii across the hero,
   the app section, the closing CTA and the footer, which is what made the
   page feel unsettled. 56px matches the hero's own CTA, so every primary
   action on the site is now the same object. */
.stores { display:flex; gap:12px; flex-wrap:wrap; }
.stores--center { justify-content:center; }

/* Measured off pingo.ai and matched: 56px tall, 9999px radius, #1b1b1b (not
   pure black), symmetric 24px padding, 12px gap, 28px icon, no border, no
   shadow. Ours had asymmetric padding, a 10px gap, a 22px icon and a 1px
   border, which is why it read as a near-miss of theirs. */
.store {
  display:inline-flex; align-items:center; gap:12px;
  height:56px; padding:0 24px;
  border-radius:9999px;
  background:#1b1b1b; color:#fff;
  border:0;
  transition:background-color 160ms linear, color 160ms linear;
}
.store:hover { background:#2a2a2a; }
.store__glyph { width:28px; height:28px; flex:none; fill:currentColor; }
.store__glyph--play { fill:none; }   /* the Play mark keeps Google's own colours */
.store__text { display:flex; flex-direction:column; align-items:flex-start; }
.store__kicker {
  /* Pingo sets this in sentence case at 12/400, full white, line-height 1 —
     not uppercase micro-caps at 66% opacity, which is what ours was. */
  display:block; font-size:var(--t-micro); font-weight:400; letter-spacing:normal;
  color:inherit; line-height:1;
}
.store__name { display:block; font-size:var(--t-body); font-weight:400; letter-spacing:normal; line-height:1; }

/* On the dark surfaces the badge used to be #0b0c0f on #0b0c0f — a 1.00:1
   shape held together by a hairline, i.e. invisible. It inverts instead. */
.footer .store,
.takeover .store {
  background:#fff; color:var(--ink);
}
.footer .store:hover,
.takeover .store:hover { background:#e9eaee; }

/* --------------------------------------------------------------------------
   6. Nav — a floating glass pill, never a full-width bar
   -------------------------------------------------------------------------- */
/* The bar. Over the hero it is nothing at all: no pill, no fill, no border,
   only the wordmark, the links and the button set wide across the page's own
   measure, the way Revolut's sits. Once the page has moved it becomes a full
   width bar of light glass, so the links stay readable over whatever passes
   underneath. A bar and not a pill: a pill floating over scrolling content
   reads as a widget, a bar reads as the top of the page. */
.nav {
  position:fixed; inset:0 0 auto; z-index:60;
  isolation:isolate;
}
/* The glass is a layer of its own so that it can fade in. backdrop-filter does
   not interpolate from none, and a fill that snaps on at the first pixel of
   scroll is a flicker, not a transition. */
.nav::before {
  content:"";
  position:absolute; inset:0; z-index:-1;
  background:linear-gradient(180deg, rgba(255,255,255,.86), rgba(255,255,255,.74));
  backdrop-filter:blur(28px) saturate(170%);
  -webkit-backdrop-filter:blur(28px) saturate(170%);
  border-bottom:1px solid rgba(11,12,15,.06);
  box-shadow:0 12px 30px -24px rgba(11,12,15,.30);
  opacity:0;
  transition:opacity 260ms var(--ease);
  pointer-events:none;
}
.nav--scrolled::before { opacity:1; }
@supports not (backdrop-filter:blur(1px)) { .nav::before { background:rgba(255,255,255,.95); } }

/* Three columns, so the links sit on the page's centre line whatever the
   wordmark and the button happen to measure. */
.nav__row {
  display:grid; grid-template-columns:1fr auto 1fr; align-items:center;
  column-gap:clamp(20px, 3vw, 48px);
  height:var(--nav-h);
  width:100%; max-width:var(--wrap);
  margin-inline:auto; padding-inline:var(--gutter);
}

/* both wordmarks stacked so the flip cross-fades instead of popping */
.nav__logo { position:relative; z-index:1; display:block; width:132px; height:24px; justify-self:start; }
.nav__logo img {
  position:absolute; inset:0; width:100%; height:auto;
  transition:opacity 300ms var(--ease);
}
.nav__logo .is-dark { opacity:0; }
.nav--solid .nav__logo .is-light { opacity:0; }
.nav--solid .nav__logo .is-dark { opacity:1; }
.nav__links {
  display:flex; align-items:center; gap:clamp(24px, 3.2vw, 48px);
  position:relative; z-index:1;
  font-size:var(--t-body); font-weight:400;
  color:rgba(255,255,255,.96);
  transition:color 300ms var(--ease);
}
.nav__links a { transition:opacity 160ms linear; }
.nav__links a:hover { opacity:.68; }
.nav--solid .nav__links { color:var(--ink); }
.nav__actions { position:relative; z-index:1; display:flex; align-items:center; justify-self:end; }
.nav__actions .btn { height:44px; padding:0 20px; font-size:var(--t-label); box-shadow:none; }

/* --------------------------------------------------------------------------
   7. Hero — one centred column, the product shot cropped by the fold, and
      ambient light that moves so slowly you only notice it if you wait.
   -------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------
   8. Hero — a full sky, the promise set hard left, and the app floating in a
   pane of glass on the right.

   The reference this follows puts the headline on the left third and lets a
   glass panel break in from the right, overlapping the photograph rather than
   sitting beside it. That asymmetry is the whole effect: a centred hero reads
   as a poster, an offset one reads as a product. The sky is the same
   photograph the page always used; only the composition changed.
   -------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------
   8. Hero — the promise centred on a full sky, and the app rising into it from
   below, cut in half by the section that follows.

   The earlier offset composition put the copy hard left against a phone on the
   right. It read as two designs sharing a screen. Centring the type and
   standing the phone under it gives the page one axis, and cropping the device
   at the fold does the work a drop shadow would otherwise have to: it places
   the phone in the world rather than on top of it.

   The crop is deterministic. The panel carries half the artwork's aspect ratio
   and hides the overflow, so exactly the top half of the phone shows at every
   viewport, on every device, rather than however much happened to fit.
   -------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------
   Hero
   --------------------------------------------------------------------------
   The app's own light mode, on the web. The sky is the Home screen's sky,
   sampled from a screenshot of the running app rather than guessed at, so the
   page and the phone standing on it are the same colour. Ink, muted ink and
   the accent are the app's tokens.

   Country colour appears once, as three soft auras behind the headline that
   cycle through real flag palettes. The app puts a country's own colours
   behind its page; this is the same idea at a whisper, and it is the only
   colour in the composition that is not the sky or the product.
   -------------------------------------------------------------------------- */
.hero {
  /* The app's light sky, used as a bloom behind the device rather than as a
     wash from the top. */
  --sky:#A9EBF0;

  position:relative;
  isolation:isolate;
  /* NOT overflow:hidden. The device fades itself and the bloom fades itself;
     clipping the section turned both of those fades into one hard horizontal
     line across the bottom of the hero - a rectangle sitting behind the phone,
     which is exactly what it looked like. Anything that needs containing is
     contained by .hero__glow instead. */
  text-align:center;
  /* One viewport, exactly. The headline and the button take what they need and
     the phone takes the rest, so the fold falls across the device at every
     size and the next section starts where the screen ends. svh, so a phone
     browser's toolbar does not push the cut below the glass. */
  display:flex; flex-direction:column;
  /* HEIGHT, not min-height. With a minimum the device's intrinsic 836px
     pushed the hero to 1244px on a 844px screen — the fold stopped falling
     across the phone and the next section started a screen and a half down.
     Fixed height makes .hero__device the flex item that absorbs the
     remainder, and it crops itself with its own overflow:hidden. */
  height:100vh; height:100svh;
  padding-top:calc(var(--nav-h) + clamp(18px, 4.2vh, 60px));
  padding-bottom:0;
  background:#fff;
}

/* The bloom. One soft ellipse of the app's own sky, rising from behind the
   phone, with two flag-coloured warmths at the shoulders. Everything here is
   blurred past the point of being a shape: the page has to stay white, and
   the only thing with an edge on it should be the product. */
/* Country colour, in bits. Two of them, at the shoulders, far enough out that
   they read as a temperature rather than as flags. */
@keyframes hero-drift-l { to { transform:translate3d(5%, 6%, 0) scale(1.10); } }
@keyframes hero-drift-r { to { transform:translate3d(-6%, 4%, 0) scale(1.07); } }
@keyframes hero-hue-l {
  0%,22%   { background-color:#E8404C; }   /* Japan */
  28%,47%  { background-color:#C8102E; }   /* Türkiye */
  53%,72%  { background-color:#CE2B37; }   /* Italy */
  78%,100% { background-color:#E8404C; }
}
@keyframes hero-hue-r {
  0%,22%   { background-color:#2B5BD7; }   /* France */
  28%,47%  { background-color:#0A3161; }   /* the UK */
  53%,72%  { background-color:#1584C8; }   /* Greece */
  78%,100% { background-color:#2B5BD7; }
}
@media (prefers-reduced-motion:reduce) {
}

.hero__inner {
  position:relative; z-index:1;
  /* min-height:0 is load-bearing. A flex item defaults to min-height:auto,
     which refuses to shrink below its content — so this box sat at 1321px
     inside a 900px hero and the device below it could never shrink, however
     many times its own min-height was set to 0. */
  flex:1 1 auto; min-height:0;
  width:100%; max-width:var(--wrap);
  margin-inline:auto; padding-inline:var(--gutter);
  display:flex; flex-direction:column; align-items:center;
}

/* The headline. Two lines, the same size, the second one lighter and softer -
   the whole of the reference's structure. The old hero set one tight display
   line and then stacked an aside, a lede and a star row under it; four voices
   above the fold is why it read as a landing page rather than as a product. */
.hero__display {
  margin:0;
  /* Two real numbers stepped once at 768, not a curve. A clamp gives a
     different fractional size at every width, which is the thing that made
     the page feel unsettled — and it is how the headline ended up SMALLER at
     721px than at 430px, because two near-duplicate breakpoints were fighting
     over it. 30/44 also puts the H1 below the section H2 (38/56), which is
     what both references do. */
  font-size:var(--t-h1);
  line-height:1.05;
  letter-spacing:-.025em;
  display:flex; flex-direction:column;
  text-wrap:balance;
}
/* One face for both lines: Aeonik Medium. The first line used to be Bold, and
   Aeonik's Bold is drawn tighter and heavier enough to read as a different
   typeface sitting on top of the second line. The two tones carry the
   hierarchy now, ink over muted, and the weight is shared. */
.hero__line { color:var(--ink); font-weight:500; }

.hero__sub {
  margin:20px 0 0;
  max-width:34ch;
  font-size:var(--t-lede); line-height:1.4; color:var(--body);
  text-wrap:balance;         /* breaks at the sentence, not before "the app." */
}
.hero .stores { margin-top:32px; }
.hero__rating {
  display:flex; align-items:center; justify-content:center; gap:7px;
  margin:16px 0 0;
  font-size:var(--t-label); line-height:1; color:var(--body);
}
.hero__star { width:16px; height:16px; color:#f5a623; flex:none; }
.hero__rating strong { font-weight:500; color:var(--ink); }

@media (min-width:768px) {
  .hero__sub { max-width:576px; }
}

/* The phone.

   THE RENDER CARRIES ITS OWN SHADOW, and that shadow spans the whole canvas
   at a very low alpha. Asking CSS for a drop-shadow on top of that traced the
   CANVAS rather than the device - a soft rectangle with a gradient inside it,
   sitting around the phone in mid-air. There is no filter here now; the
   picture already has the shadow it needs.

   AND THE FILE WAS MOSTLY EMPTY. The device was 560px of a 900px-wide canvas -
   38% of the width was transparent margin - so every CSS width was really
   buying 62% of a phone, which is why it read as small and thin however large
   the number got. assets/img/hero-mockup-tight-v2.webp is the same render cropped
   to the device (plus a little room for its own shadow), so the width here is
   now the width of the phone.

   THE CUT IS THE FOLD. The figure is a window that fills whatever height the
   headline and the button leave, and the phone stands in it from the top,
   wider than the window is tall, so about the top half of the device shows
   and the rest runs off under the fold. The window measures itself (it is a
   size container), and the phone is as wide as it takes for exactly half of
   it to fit, 100cqh * 0.8016 for a 616 by 1537 render. On a short laptop
   screen that would be a small phone, so it may grow to the floor, but only
   as far as 100cqh * 0.954, which is the width at which 42% of the device is
   still in the window: a large phone showing a little under half, never a
   huge one showing only its forehead. The fade
   is the window's, over its last third, so the device dissolves into the
   page at the bottom of the screen and nothing ever ends on a hard line. */
.hero__device {
  /* One elastic term, svh, carries the whole hero on short screens — it is
     what Pingo does with its mark (w-[34svh]) and what this hero was missing.
     flex:1 1 auto with min-height:0 lets it actually shrink, so .hero can
     centre its column and spend the surplus as whitespace instead of
     overflowing. The old container-query formula deliberately sized the phone
     so only half of it fit, and then a mask faded it from 60% on top of that,
     which together left a phone reader with no app screen at all. */
  /* The device takes whatever is left and runs to the bottom edge of the
     hero, so the cut lands ON the fold. Capping it put the cut in the middle
     of the screen with white underneath, which reads as a mistake rather than
     as "this carries on below". */
  flex:1 1 auto; min-height:0;
  width:100%;
  margin:clamp(16px, 2.6vh, 30px) 0 0;
  overflow:hidden;
  display:flex; justify-content:center; align-items:flex-start;
  -webkit-mask-image:linear-gradient(180deg, #000 76%, transparent 100%);
          mask-image:linear-gradient(180deg, #000 76%, transparent 100%);
}
.hero__device img {
  display:block; flex:none;
  width:min(44svh, 80vw, 380px); max-width:none; height:auto;
}

/* --------------------------------------------------------------------------
   9b. The download page, /app. It is what a desktop gets when it follows a
       /app, /get or /download link that a phone would have been redirected
       straight to a store by.

       THIS USED TO BE A <dialog> TAKEOVER and most of what was here was the
       machinery for that: ::backdrop, [open], @starting-style, an
       allow-discrete transition so the CLOSE animated, a close button, and a
       QR code for scanning the page onto a handset. All of it is gone. Every
       download button is now a plain link to a store, so the only thing left
       to style is a dark page with a headline and two badges.
   -------------------------------------------------------------------------- */
.takeover {
  min-height:100dvh;
  background:var(--dark); color:#fff;
}
.takeover__inner {
  min-height:100dvh;
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:clamp(22px, 3vh, 36px);
  padding:clamp(72px, 12vh, 120px) var(--gutter) clamp(40px, 8vh, 72px);
  text-align:center;
}

.takeover__title {
  font-size:var(--t-h2); line-height:1; font-weight:500;
  letter-spacing:-.045em; text-transform:uppercase; color:#fff;
}
.takeover__sub {
  margin-top:-8px;
  font-size:var(--t-lede); font-weight:500; color:rgba(255,255,255,.66);
  letter-spacing:-.01em;
}
.takeover :focus-visible { outline-color:#fff; }

/* a phone held sideways is only ~360px tall */
@media (max-height:560px) {
  .takeover__inner { gap:11px; padding:44px var(--gutter) 14px; }
  .takeover__title { font-size:clamp(22px, 4.4vh, 32px); }
  .takeover__sub { margin-top:-4px; font-size:14px; }
}

/* --------------------------------------------------------------------------
   The countries band. The count is the heading and sits ABOVE two full-bleed
   rails of flags running opposite ways, so the carousel is nothing but flags
   from edge to edge. It used to sit between the rails, which cost the number
   the middle of the screen and left each rail a third of the width to run in.

   The loop works because each track prints its flag list TWICE and animates a
   flat -50%: at the end of the cycle the second copy sits exactly where the
   first began, so the jump back is invisible. Any odd number of copies, or a
   percentage that is not 50, and it visibly snaps.

   ONE PRINTED COPY MUST BE AT LEAST AS WIDE AS THE VIEWPORT. At -50% the
   track has travelled one copy's width, so only the second copy is covering
   the screen; if that copy is narrower than the window, bare background
   trails the last flag. Eight flags was enough when a rail was a third of the
   screen and is not now, which is why each list is 24 long.
   -------------------------------------------------------------------------- */
.countries { padding-block:var(--section-y); overflow:hidden; background:#fff; }

/* two rails, one under the other, each the full width */
.countries__row { display:grid; gap:clamp(16px, 2vw, 28px); }

.countries__count {
  margin:0 0 clamp(26px, 3.4vw, 46px);
  text-align:center; line-height:1; white-space:nowrap;
}
.countries__count strong {
  display:block;
  font-size:var(--t-h2); font-weight:500; letter-spacing:-.025em; color:var(--ink);
}
.countries__count span {
  display:block; margin-top:6px;
  font-size:var(--t-lede); font-weight:400; color:var(--body);
}

/* Now that a rail spans the whole screen, both of its ends ARE outer ends, so
   the fade is symmetric — and tight, 7%, so the flags are sharp everywhere a
   reader is actually looking and only dissolve as they leave the screen. The
   old directional mask existed to keep the edge next to the count crisp;
   there is no count in the middle any more. */
.marquee {
  overflow:hidden; min-width:0;
  -webkit-mask-image:linear-gradient(90deg, transparent 0, #000 7%, #000 93%, transparent 100%);
          mask-image:linear-gradient(90deg, transparent 0, #000 7%, #000 93%, transparent 100%);
}
.marquee__track {
  display:flex; align-items:center; width:max-content;
  gap:clamp(16px, 2vw, 28px);
  will-change:transform;
}
/* 32 flags per copy instead of 8, so the same duration would have run four
   times faster. 48s holds ~0.9 flags a second, a shade quicker than before. */
.marquee--rtl .marquee__track { animation:marquee-rtl 48s linear infinite; }
.marquee--ltr .marquee__track { animation:marquee-ltr 48s linear infinite; }

@keyframes marquee-rtl { from { transform:translate3d(0,0,0); }   to { transform:translate3d(-50%,0,0); } }
@keyframes marquee-ltr { from { transform:translate3d(-50%,0,0); } to { transform:translate3d(0,0,0); } }

.countries .flag {
  width:clamp(56px, 6vw, 84px); aspect-ratio:1; flex:none;
  border-radius:50%;
  box-shadow:inset 0 0 0 1px rgba(11,12,15,.06);
}

@media (prefers-reduced-motion:reduce) {
  .marquee__track { animation:none; }
}

/* --------------------------------------------------------------------------
   10. Sections
   -------------------------------------------------------------------------- */
.section { padding-block:var(--section-y); scroll-margin-top:100px; }
.section--white { background:#fff; }
/* set only the corners each one owns, so .lift and .drop can share an element */
.lift { border-start-start-radius:var(--radius-slab); border-start-end-radius:var(--radius-slab); }
.drop { border-end-start-radius:var(--radius-slab); border-end-end-radius:var(--radius-slab); }
/* No exception here. A zeroed top padding was the one place the rhythm broke,
   and two same-coloured sections still want the same gap between their content
   as any other pair — Pingo runs 112 on both sides of every boundary. */

/* --------------------------------------------------------------------------
   11. The app — a real render of the product, and the case for it alongside.
       The screenshot carries the countries and their prices, so no price on
       this page is ever something the reader could act on.
   -------------------------------------------------------------------------- */


/* --------------------------------------------------------------------------
   12. Steps — three cards, no art. The device row above already showed the app.
   -------------------------------------------------------------------------- */
/* No connector line between the cards: the cards are opaque and sit on top of
   it, so 876px of dash rendered as two stray 20px fragments in the gaps. */
.steps {
  margin-top:clamp(40px, 4.4vw, 56px);
  display:grid; grid-template-columns:repeat(3, minmax(0,1fr)); gap:20px;
}
.step {
  display:flex; flex-direction:column;
  padding:30px;
  background:#fff; border:1px solid var(--hairline); border-radius:22px;
  box-shadow:var(--sh-card);
}
.step__num {
  align-self:flex-start;
  height:26px; padding:0 11px; border-radius:13px;
  display:inline-flex; align-items:center;
  background:var(--ink); color:#fff;
  font-size:var(--t-micro); font-weight:500; letter-spacing:.06em;
}
.step .h3 { margin-top:18px; margin-bottom:6px; }
.step p { font-size:var(--t-body); line-height:1.6; color:var(--body); }

/* --------------------------------------------------------------------------
   13. Value card — one survivor, carrying the question that blocks installs
   -------------------------------------------------------------------------- */
.value {
  padding:22px 24px; background:#fff;
  border:1px solid var(--hairline); border-radius:18px; box-shadow:var(--sh-card);
}
.value__icon { width:22px; height:22px; color:var(--ink); margin-bottom:14px; }
.value p { margin-top:7px; font-size:var(--t-body); line-height:1.6; color:var(--body); }
.honesty .value { grid-column:1 / -1; }
.honesty .value p { max-width:72ch; }   /* full-bleed card, but not a full-bleed line length */

/* --------------------------------------------------------------------------
   14. In-app furniture — the rows and the countdown ring, drawn inside a device
   -------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------
   15. Manifesto lines — now the closing headline, fading down the ladder
   -------------------------------------------------------------------------- */
.manifesto__line {
  display:block;
  font-size:var(--t-h2); line-height:1.06; font-weight:500;
  letter-spacing:-.04em; color:var(--ink);
}
.manifesto__line:nth-child(2) { color:rgba(11,12,15,.7); }
.manifesto__line:nth-child(3) { color:rgba(11,12,15,.52); }

/* --------------------------------------------------------------------------
   16. Honesty
   -------------------------------------------------------------------------- */
.honesty {
  margin-top:clamp(36px, 4vw, 52px);
  display:grid; grid-template-columns:repeat(2, minmax(0,1fr)); gap:14px;
}
.honesty__col { padding:30px; border:1px solid var(--hairline); border-radius:22px; background:#fff; }
.honesty__col--not { background:var(--page); }
.honesty__head {
  font-size:var(--t-micro); font-weight:500; letter-spacing:.18em; text-transform:uppercase;
  color:var(--muted); margin-bottom:22px;
}
.honesty li {
  display:flex; align-items:flex-start; gap:12px;
  padding-block:12px; font-size:var(--t-body); color:var(--ink);
  border-top:1px solid var(--hairline);
}
.honesty li:first-of-type { border-top:0; }
.honesty .glyph { font-size:17px; color:var(--ink); margin-top:3px; }
.honesty__col--not li { color:var(--body); }
.dash { width:16px; height:1.5px; border-radius:1px; background:var(--muted); flex:none; margin-top:12px; }

/* --------------------------------------------------------------------------
   17. FAQ
   -------------------------------------------------------------------------- */
.faq { margin-top:clamp(36px, 4vw, 48px); display:grid; gap:8px; max-width:840px; margin-inline:auto; }
.faq details {
  background:#fff; border:1px solid var(--hairline); border-radius:16px;
  transition:border-color var(--dur) var(--ease);
}
.faq details[open] { border-color:var(--hairline-strong); }
.faq summary {
  display:flex; align-items:center; gap:16px;
  padding:18px 20px; cursor:pointer; list-style:none;
  font-size:var(--t-lede); font-weight:500; letter-spacing:-.02em; color:var(--ink);
}
.faq summary::-webkit-details-marker { display:none; }
.faq summary::after {
  content:""; margin-left:auto; flex:none;
  width:9px; height:9px;
  border-right:1.8px solid var(--muted); border-bottom:1.8px solid var(--muted);
  rotate:45deg; translate:0 -2px;
  transition:rotate var(--dur) var(--ease), translate var(--dur) var(--ease);
}
.faq details[open] summary::after { rotate:-135deg; translate:0 2px; }
.faq p { padding:0 20px 20px; font-size:var(--t-body); line-height:1.6; color:var(--body); max-width:68ch; }

/* --------------------------------------------------------------------------
   18. Closing — the page ends where it opened, in the dark
   -------------------------------------------------------------------------- */
.closing {
  position:relative; overflow:hidden;
  padding-block:var(--section-y);
  background:#fff;
  text-align:center;
  color:var(--ink);
}
.closing::before {
  content:""; position:absolute; inset:0; pointer-events:none;
  background:radial-gradient(760px 460px at 50% 4%, rgba(11,12,15,.05), rgba(11,12,15,0) 70%);
}
.closing__inner { position:relative; z-index:2; display:grid; justify-items:center; gap:20px; }
.closing__stack { display:grid; justify-items:center; }
.closing .lede { color:var(--body); max-width:44ch; }
.closing .stores { margin-top:22px; }

/* --------------------------------------------------------------------------
   19. Footer
   -------------------------------------------------------------------------- */
.footer {
  background:var(--dark); color:var(--on-dark-muted);
  border-top:1px solid var(--hairline-dark);
  padding-block:clamp(56px, 6vw, 80px) 30px;
  font-size:var(--t-label);
}
.footer__grid { display:grid; grid-template-columns:1.7fr repeat(3, 1fr); gap:clamp(24px, 3vw, 48px); }
.footer__brand img { width:140px; height:auto; margin-bottom:18px; }
.footer__brand p { max-width:30ch; color:var(--on-dark-faint); font-size:var(--t-label); line-height:1.6; }
.footer h4 {
  color:var(--on-dark); font-size:var(--t-micro); font-weight:500; letter-spacing:.16em; text-transform:uppercase;
  margin-bottom:16px;
}
.footer li + li { margin-top:10px; }
.footer a:hover { color:var(--on-dark); }
.footer__bottom {
  margin-top:clamp(40px, 5vw, 64px); padding-top:24px;
  border-top:1px solid var(--hairline-dark);
  display:flex; align-items:center; justify-content:space-between; gap:16px; flex-wrap:wrap;
  font-size:var(--t-micro); color:var(--on-dark-faint);
}
.footer__legal { display:flex; gap:20px; }

/* the trust strip: where to get the app, and who takes the money */
.footer__strip {
  margin-top:clamp(36px, 4.5vw, 56px);
  padding-top:clamp(28px, 3.4vw, 40px);
  border-top:1px solid var(--hairline-dark);
  display:flex; align-items:flex-end; justify-content:space-between;
  gap:32px; flex-wrap:wrap;
}
.footer__get { min-width:0; }
.footer__get-label,
.footer__pay-label {
  display:flex; align-items:center; gap:8px;
  font-size:var(--t-micro); font-weight:500; letter-spacing:.16em; text-transform:uppercase;
  color:var(--on-dark-faint); margin-bottom:14px;
}
.footer__pay-label .glyph { font-size:15px; }
.footer__pay { text-align:right; }

.paymarks { display:flex; align-items:center; gap:10px; justify-content:flex-end; }
.paymark {
  display:flex; align-items:center; justify-content:center; gap:3px;
  height:30px; min-width:48px; padding:0 10px;
  border-radius:7px;
  background:rgba(255,255,255,.08);
  border:1px solid var(--hairline-dark);
  color:var(--on-dark);
}
.paymark--type { font-size:var(--t-micro); font-weight:500; letter-spacing:.06em; }
.paymark--pay { font-size:var(--t-micro); font-weight:500; letter-spacing:-.01em; }
.paymark--pay .glyph { font-size:14px; fill:currentColor; }
.paymark svg { width:26px; height:17px; }
.footer__legal li + li { margin-top:0; }   /* the column rule must not stagger this row */

/* --------------------------------------------------------------------------
   19b. Subpage hero, plain ground instead of the sky. These pages are born
        with the nav already solid: there is no photograph to be glass over.
   -------------------------------------------------------------------------- */
.page-hero {
  padding-top:calc(var(--nav-h) + clamp(56px, 7vw, 96px));
  padding-bottom:clamp(10px, 1.6vw, 24px);
}
.page-hero__kicker {
  display:block; margin-bottom:18px;
  font-size:11.5px; font-weight:500; letter-spacing:.18em; text-transform:uppercase;
  color:var(--muted);
}
.page-hero .display { max-width:17ch; }
.page-hero .lede { margin-top:20px; max-width:54ch; }

/* --------------------------------------------------------------------------
   19c. Application form, creators and partners. One card, a handful of
        fields, no account. The reply is an email from a person.
   -------------------------------------------------------------------------- */
.apply {
  margin-top:clamp(36px, 4vw, 52px); margin-inline:auto;
  max-width:840px;
  padding:clamp(24px, 3vw, 40px);
  background:#fff; border:1px solid var(--hairline); border-radius:22px;
  box-shadow:var(--sh-card);
}
.apply__grid { display:grid; grid-template-columns:repeat(2, minmax(0,1fr)); gap:22px 20px; }
.field { min-width:0; }
.field--full { grid-column:1 / -1; }
.field__label {
  display:block; margin-bottom:12px;
  font-size:16px; font-weight:500; letter-spacing:-.02em; color:var(--ink);
}
.field__hint { font-weight:400; color:var(--muted); }
.field__input,
.field__area {
  -webkit-appearance:none; appearance:none;
  width:100%; padding:0 18px;
  border:1px solid var(--hairline-strong); border-radius:14px;
  background:#fff; color:var(--ink);
  font:500 16px/1.45 var(--font); letter-spacing:-.01em;
  transition:border-color var(--dur) var(--ease);
}
.field__input { height:56px; }
.field__area { min-height:140px; padding-block:15px; resize:vertical; }
.field__input::placeholder, .field__area::placeholder { color:var(--muted); font-weight:400; }
.field__input:hover, .field__area:hover,
.field__input:focus, .field__area:focus { border-color:var(--ink); }

.apply__foot { margin-top:26px; display:flex; align-items:center; gap:18px; flex-wrap:wrap; }
.apply__submit:disabled { background:var(--control-hover); border-color:var(--control-hover); cursor:default; }
.apply__note { font-size:14px; color:var(--muted); }

/* monochrome by design, so the error is weight and words rather than red */
.apply__error {
  margin-top:18px; padding:14px 18px;
  border:1px solid var(--hairline-strong); border-radius:14px;
  background:var(--page); color:var(--ink);
  font-size:14.5px; font-weight:500;
}
.apply__error[hidden] { display:none; }

/* what replaces the form once the application lands */
.apply--done { display:flex; flex-direction:column; align-items:flex-start; }
.apply--done[hidden] { display:none; }
.apply__tick {
  width:44px; height:44px; margin-bottom:16px;
  display:grid; place-items:center; border-radius:50%;
  background:var(--ink); color:#fff;
}
.apply__tick svg { width:20px; height:20px; }
.apply--done .h3 { font-size:21px; }
.apply--done p { margin-top:6px; font-size:15px; color:var(--body); }

/* --------------------------------------------------------------------------
   19d. Invite, the referral landing. The code rides in on the URL and leaves
        in the app, this page just holds it up.
   -------------------------------------------------------------------------- */
.invite {
  padding-top:calc(var(--nav-h) + clamp(64px, 8vw, 110px));
  padding-bottom:clamp(76px, 9vw, 130px);
  text-align:center;
}
.invite__inner { display:flex; flex-direction:column; align-items:center; gap:20px; }
/* the group exists to be hidden as one, its children lay out in the column */
.invite__group { display:contents; }
.invite__group[hidden] { display:none; }
.invite .display { max-width:none; }
.invite .lede { max-width:46ch; }

/* the dashed chip, the same shape the app shows the code in */
.invite__chip {
  margin-top:6px;
  display:inline-flex; align-items:center; justify-content:center;
  min-width:min(320px, 80vw);
  padding:18px 36px;
  border:2px dashed rgba(11,12,15,.3); border-radius:20px;
  background:#fff;
  font-size:clamp(30px, 6vw, 46px); line-height:1; font-weight:500;
  letter-spacing:.08em; color:var(--ink);
}

.btn--ghost { background:transparent; color:var(--ink); border-color:var(--hairline-strong); box-shadow:none; }
.btn--ghost:hover { background:transparent; border-color:var(--ink); color:var(--ink); }
.btn--ghost:active { background:var(--page); }

.invite .stores { margin-top:26px; }
/* Google Play is not out yet, so the badge says so and goes nowhere */
.store--soon { cursor:default; opacity:.55; box-shadow:none; }
.store--soon:hover { background:var(--control); border-color:var(--control); }

/* --------------------------------------------------------------------------
   20. Entrance + scroll motion (both fail safe: content is visible by default)
   -------------------------------------------------------------------------- */
@keyframes rise { from { opacity:0; transform:translateY(16px); } to { opacity:1; transform:none; } }
@keyframes fade { from { opacity:0; } to { opacity:1; } }

.rise { animation:rise 700ms var(--ease) both; animation-delay:var(--d, 0ms); }
.rise--fade { animation-name:fade; }

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .reveal {
      animation:rise 700ms var(--ease) both;
      animation-timeline:view();
      animation-range:entry 8% cover 30%;
    }
  }
}

/* --------------------------------------------------------------------------
   21. Responsive
   -------------------------------------------------------------------------- */
@media (max-width:1279px) {
  .footer__grid { grid-template-columns:1.4fr repeat(3, 1fr); }
}

@media (max-width:1023px) {
  .nav__links { display:none; }
  .nav__row { grid-template-columns:1fr auto; }
  .hero { padding-top:calc(var(--nav-h) + clamp(16px, 3.6vh, 44px)); }
  /* three cards never go in two columns — that strands the third on its own
     row. One column below 1024, three above. */
  .steps { grid-template-columns:minmax(0,1fr); }
  .honesty { grid-template-columns:1fr; }
}

@media (max-width:767px) {
  body { font-size:16px; }

  /* the bar has ~270px of usable width here, so the lead-in goes and the
     close button keeps only the room it actually needs */
  /* left:auto, or the base rule's left wins over this right and the button
     lands on top of the first word of the message. */

  :root { --nav-h:64px; }
  .nav__logo { width:120px; height:22px; }
  .nav__actions .btn { height:46px; padding:0 20px; font-size:14.5px; }
  /* stacked and centred at their natural width, the way Pingo does it —
     side by side at this width leaves each badge about 170px, which crushes
     "Download on the / App Store" */
  .stores { flex-direction:column; align-items:center; gap:10px; }
  .stores--center { align-items:center; }
  .steps { grid-template-columns:minmax(0, 1fr); }
  /* one card at a time on a phone, at a readable size rather than a third of it */
  /* controls stay at finger size on a phone rather than shrinking with the
     viewport — this is the one band on the page you are meant to touch */
  .footer__grid { grid-template-columns:1fr 1fr; }
  /* footer links were 20px tall — the padding is what makes them tappable,
     so the row spacing comes off the margin to stop the column doubling */
  .footer li a, .footer__legal a { display:flex; align-items:center; min-height:44px; }
  .footer li + li { margin-top:0; }
  .footer__legal { gap:22px; }
  .footer__bottom { flex-direction:column; align-items:flex-start; }
  .footer__strip { flex-direction:column; align-items:stretch; gap:34px; }
  .footer__pay { text-align:left; }
  .paymarks { justify-content:flex-start; flex-wrap:wrap; }
  /* the application form goes one column, and its button goes full width the
     way the picker's does */
  .apply__grid { grid-template-columns:minmax(0,1fr); }
  .apply__foot { flex-direction:column; align-items:stretch; text-align:center; }
  .invite__chip { min-width:0; width:100%; padding:15px 22px; }
}

@media (max-width:400px) {
  /* ~246px of bar left at 320 — the message sheds its verb rather than ellipsing */
}

@media (max-width:479px) {
  .display { font-size:32px; }
  .footer__grid { grid-template-columns:1fr; }
  .nav__logo { width:104px; height:19px; }
}

/* --------------------------------------------------------------------------
   22. Reduced motion — everything lands on its settled, visible frame
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior:auto; }
  *,*::before,*::after {
    animation:none !important;
    transition-duration:.01ms !important;
  }
}

/* --------------------------------------------------------------------------
   23. Onboarding, creators and partners. One narrow centred column: a big
       friendly heading, the pitch squeezed to three beats, then the form.
       Built for a phone held in one hand, so it is one field per row and
       nothing to tap is under 48px.
   -------------------------------------------------------------------------- */
.onb {
  padding-top:calc(var(--nav-h) + clamp(40px, 6vw, 76px));
  padding-bottom:clamp(72px, 9vw, 120px);
}
.onb__col {
  max-width:440px; margin-inline:auto;
  display:flex; flex-direction:column; align-items:center; text-align:center;
}
.onb__kicker {
  font-size:11.5px; font-weight:600; letter-spacing:.18em; text-transform:uppercase;
  color:var(--muted);
}
.onb__title {
  margin-top:14px;
  font-size:clamp(32px, 8.4vw, 42px); line-height:1.06; font-weight:600;
  letter-spacing:-.035em; color:var(--ink); text-wrap:balance;
}
.onb__lede { margin-top:14px; font-size:16.5px; line-height:1.55; color:var(--body); text-wrap:pretty; }

/* the three step pitch, compressed to one quiet strip so the form itself
   stays close to the fold */
.onb__steps {
  margin-top:28px; width:100%;
  display:grid; grid-template-columns:repeat(3, minmax(0,1fr)); gap:8px;
}
.onb__steps li {
  display:flex; flex-direction:column; align-items:center; gap:8px;
  font-size:12.5px; line-height:1.35; font-weight:500; color:var(--body);
  text-wrap:balance;
}
.onb__step-num {
  width:24px; height:24px; border-radius:50%; flex:none;
  display:grid; place-items:center;
  background:var(--ink); color:#fff;
  font-size:11.5px; font-weight:600;
}

/* the card. One column of fields, no side by side anything. */
.onb__card {
  margin-top:26px; width:100%;
  padding:clamp(22px, 6vw, 30px);
  background:#fff; border:1px solid var(--hairline); border-radius:22px;
  box-shadow:var(--sh-card);
  text-align:left;
}
.onb__card .field + .field { margin-top:18px; }
.onb__card .field__label { margin-bottom:9px; font-size:14.5px; }
.onb__submit { margin-top:22px; width:100%; height:56px; }
.onb__note { margin-top:14px; font-size:13.5px; color:var(--muted); text-align:center; }
.onb__card .apply__error { margin-top:18px; }

/* what replaces the form. For a creator this is the whole point: the code
   is issued while the button is still warm. */
.onb__won { display:flex; flex-direction:column; align-items:center; text-align:center; }
.onb__won .apply__tick { margin-bottom:14px; }
.onb__won-title {
  font-size:clamp(26px, 7vw, 32px); line-height:1.1; font-weight:600;
  letter-spacing:-.03em; color:var(--ink); text-wrap:balance;
}
.onb__won-sub { margin-top:8px; font-size:15px; line-height:1.55; color:var(--body); }

/* the dashed chip, the same shape the app and the invite page use */
.onb__chip {
  margin-top:20px; width:100%;
  display:flex; align-items:center; justify-content:center;
  min-height:74px; padding:16px 20px;
  border:2px dashed rgba(11,12,15,.3); border-radius:18px; background:#fff;
  font-size:clamp(26px, 7vw, 34px); line-height:1; font-weight:700;
  letter-spacing:.08em; color:var(--ink);
  overflow-wrap:anywhere;
}
.onb__copy { margin-top:12px; width:100%; height:52px; }
.onb__share { margin-top:20px; width:100%; display:flex; flex-direction:column; gap:8px; }
.onb__share-label {
  font-size:11.5px; font-weight:600; letter-spacing:.16em; text-transform:uppercase;
  color:var(--muted);
}
/* the link is a button because tapping it copies it, which is the only thing
   anyone actually does with their own referral link */
.onb__share-link {
  width:100%; min-height:48px; padding:13px 16px;
  border:1px solid var(--hairline-strong); border-radius:14px;
  background:var(--page); color:var(--ink); cursor:pointer;
  font:500 14px/1.4 var(--font); letter-spacing:-.01em;
  overflow-wrap:anywhere; text-align:center;
  transition:border-color var(--dur) var(--ease);
}
.onb__share-link:hover { border-color:var(--ink); }
.onb__go { margin-top:20px; width:100%; height:56px; }
.onb__mailed { margin-top:14px; font-size:13.5px; color:var(--muted); }

/* --------------------------------------------------------------------------
   24. Portal, the creator and partner dashboard. Same narrow column, but the
       chrome shrinks to a wordmark: this page is a tool, not a pitch.
   -------------------------------------------------------------------------- */
.portal-top {
  max-width:calc(440px + 2 * var(--gutter)); margin-inline:auto;
  padding:clamp(20px, 4vw, 30px) var(--gutter) 0;
  display:flex; align-items:center; justify-content:space-between; gap:12px;
}
.portal-top__logo { display:flex; align-items:center; min-height:48px; }
.portal-top__logo img { width:122px; height:auto; }
.portal-top__out {
  min-height:48px; padding:0 6px; border:0; background:none; cursor:pointer;
  font:500 14px var(--font); letter-spacing:-.01em; color:var(--muted);
  transition:color 160ms linear;
}
.portal-top__out:hover { color:var(--ink); }

.portal { padding-top:clamp(26px, 5vw, 46px); padding-bottom:clamp(72px, 9vw, 120px); }
.portal__col {
  max-width:440px; margin-inline:auto;
  display:flex; flex-direction:column; align-items:center; text-align:center;
}
.portal__view { width:100%; display:flex; flex-direction:column; align-items:center; }
.portal__title {
  font-size:clamp(30px, 8vw, 38px); line-height:1.08; font-weight:600;
  letter-spacing:-.035em; color:var(--ink); text-wrap:balance;
}
.portal__lede { margin-top:12px; font-size:16px; line-height:1.55; color:var(--body); text-wrap:pretty; }
.portal__lede strong { font-weight:600; color:var(--ink); overflow-wrap:anywhere; }
.portal__quiet { font-size:14px; line-height:1.55; color:var(--muted); }

.portal__card {
  margin-top:22px; width:100%;
  padding:clamp(22px, 6vw, 28px);
  background:#fff; border:1px solid var(--hairline); border-radius:22px;
  box-shadow:var(--sh-card);
  text-align:left;
}
.portal__cardkick {
  font-size:11.5px; font-weight:600; letter-spacing:.16em; text-transform:uppercase;
  color:var(--muted); margin-bottom:16px;
}
.portal__card .onb__chip { margin-top:0; }
.portal__submit { margin-top:20px; width:100%; height:56px; }
.portal__go { margin-top:24px; width:100%; max-width:320px; height:56px; }
.portal__alt {
  margin-top:6px; align-self:center;
  min-height:48px; padding:0 10px; border:0; background:none; cursor:pointer;
  font:500 14px var(--font); color:var(--muted);
  transition:color 160ms linear;
}
.portal__alt:hover { color:var(--ink); }

/* monochrome by design, so errors here are weight and words rather than red */
.portal__error {
  margin-top:16px; padding:13px 16px;
  border:1px solid var(--hairline-strong); border-radius:14px;
  background:var(--page); color:var(--ink);
  font-size:14px; font-weight:500; line-height:1.5;
}

/* six boxes, one invisible input stretched across all of them. The input does
   the typing, pasting and one-time-code autofill; the boxes only display. */
.otp { position:relative; display:flex; gap:8px; justify-content:center; }
.otp__digit {
  flex:1 1 0; min-width:0; height:60px;
  display:grid; place-items:center;
  border:1px solid var(--hairline-strong); border-radius:14px; background:#fff;
  font:600 22px/1 var(--font); color:var(--ink);
  font-variant-numeric:tabular-nums;
  transition:border-color var(--dur) var(--ease);
}
.otp__digit.is-active { border-color:var(--ink); }
.otp__input {
  position:absolute; inset:0; width:100%; height:100%;
  opacity:0; border:0; padding:0; margin:0;
  background:transparent; color:transparent; caret-color:transparent;
  font-size:16px;             /* 16px so iOS does not zoom the page on focus */
}
.otp__input:focus { outline:none; }
.otp:focus-within .otp__digit.is-active { border-width:2px; }

/* stat tiles, two by two */
.tiles {
  margin-top:14px; width:100%;
  display:grid; grid-template-columns:repeat(2, minmax(0,1fr)); gap:10px;
}
.tile {
  padding:16px 18px; text-align:left;
  background:#fff; border:1px solid var(--hairline); border-radius:18px;
}
.tile__label {
  font-size:11px; font-weight:600; letter-spacing:.14em; text-transform:uppercase;
  color:var(--muted);
}
.tile__value {
  margin-top:8px;
  font-size:clamp(20px, 5.6vw, 24px); line-height:1.1; font-weight:600;
  letter-spacing:-.02em; color:var(--ink);
  font-variant-numeric:tabular-nums;
  overflow-wrap:anywhere;
}

/* the road to the first payout */
.meter { width:100%; height:8px; border-radius:4px; background:var(--hairline); overflow:hidden; }
.meter__fill { display:block; height:100%; border-radius:4px; background:var(--ink); transition:width 300ms var(--ease); }
.portal__meterline {
  margin-top:12px;
  display:flex; align-items:baseline; justify-content:space-between; gap:12px;
  font-size:13.5px; font-weight:500; color:var(--body);
}
.portal__meterval { color:var(--muted); font-variant-numeric:tabular-nums; white-space:nowrap; }

/* status chips: paid is settled and solid, requested is open and outlined */
.status {
  display:inline-flex; align-items:center; flex:none;
  height:24px; padding:0 10px; border-radius:12px;
  font-size:11px; font-weight:600; letter-spacing:.05em; text-transform:uppercase;
}
.status--requested { border:1px solid var(--hairline-strong); background:var(--page); color:var(--ink); }
.status--paid { background:var(--ink); color:#fff; }
.status--muted { border:1px solid var(--hairline); background:#fff; color:var(--muted); }
.portal__pending { margin-top:4px; height:32px; padding:0 14px; border-radius:16px; align-self:flex-start; }
.portal__card .portal__quiet { margin-top:12px; }

/* the history rows: what, when, how much, and where it stands */
.ledger { width:100%; }
.ledger li { display:flex; align-items:center; gap:12px; padding-block:13px; border-top:1px solid var(--hairline); }
.ledger li:first-child { border-top:0; }
.ledger__what { min-width:0; }
.ledger__kind { font-size:14.5px; font-weight:600; letter-spacing:-.01em; color:var(--ink); }
.ledger__date { margin-top:2px; font-size:12.5px; color:var(--muted); }
.ledger__amt {
  margin-left:auto; flex:none;
  font-size:14.5px; font-weight:600; color:var(--ink);
  font-variant-numeric:tabular-nums;
}

.portal-foot {
  padding:28px var(--gutter) 44px; text-align:center;
  font-size:12.5px; color:var(--muted);
}

/* several of the blocks above set their own display, which would beat the
   hidden attribute; the attribute must always win */
.onb [hidden], .onb__won[hidden], .portal [hidden], .portal__view[hidden] { display:none !important; }

/* --------------------------------------------------------------------------
   25. Legal, terms and privacy. One readable column and nothing else: these
       pages are meant to be read top to bottom, so the type does all the work.
   -------------------------------------------------------------------------- */
.legal {
  padding-top:calc(var(--nav-h) + clamp(48px, 6.5vw, 88px));
  padding-bottom:clamp(76px, 9vw, 130px);
}
.legal__col { max-width:720px; margin-inline:auto; }
.legal__kicker {
  font-size:11.5px; font-weight:600; letter-spacing:.18em; text-transform:uppercase;
  color:var(--muted);
}
.legal__title {
  margin-top:14px;
  font-size:clamp(32px, 5vw, 46px); line-height:1.06; font-weight:600;
  letter-spacing:-.035em; color:var(--ink); text-wrap:balance;
}
.legal__updated { margin-top:16px; font-size:14px; font-weight:500; color:var(--muted); }
.legal__lede { margin-top:18px; font-size:16.5px; line-height:1.62; color:var(--body); text-wrap:pretty; }

.legal h2 {
  margin-top:clamp(36px, 4.6vw, 52px);
  font-size:20px; line-height:1.3; font-weight:600; letter-spacing:-.02em; color:var(--ink);
}
.legal p { margin-top:13px; font-size:15.5px; line-height:1.72; color:var(--body); }
.legal p strong { font-weight:600; color:var(--ink); }
.legal ul { margin-top:13px; }
.legal li {
  position:relative; padding-left:24px; margin-top:9px;
  font-size:15.5px; line-height:1.72; color:var(--body);
}
/* the same flat dash the honesty list uses, doing marker duty */
.legal li::before {
  content:""; position:absolute; left:2px; top:13px;
  width:12px; height:1.5px; border-radius:1px; background:var(--muted);
}
.legal a {
  color:var(--ink); font-weight:500;
  text-decoration:underline; text-underline-offset:3px;
  text-decoration-color:var(--hairline-strong);
  transition:text-decoration-color 160ms linear;
}
.legal a:hover { text-decoration-color:var(--ink); }

/* the portal's one-line footer carries the legal links too */
.portal-foot a { color:inherit; text-decoration:underline; text-underline-offset:2px; transition:color 160ms linear; }
.portal-foot a:hover { color:var(--ink); }

/* --------------------------------------------------------------------------
   Nav actions over the hero: a quiet text link and one solid pill. White on a
   photograph, because a dark pill in the corner competes with the dark pill
   that is the actual call to action.
   -------------------------------------------------------------------------- */
.nav__open {
  position:relative; z-index:1;
  margin-right:clamp(10px, 1.2vw, 18px);
  font-size:14.5px; color:inherit;
  transition:opacity 160ms linear;
}
.nav__open:hover { opacity:.68; }

.btn--light { background:#fff; color:var(--ink); }
.btn--light:hover { background:rgba(255,255,255,.88); }

/* --------------------------------------------------------------------------
   Join — the one onboarding flow, for creators and for businesses
   --------------------------------------------------------------------------
   A flow, not a page: no announcement bar, no nav links, no footer. Anything
   that is not the question in front of you is a reason to leave, and the two
   pages this replaces spent most of their height explaining a programme the
   reader had already decided to join.

   One question per screen, the same column on every device. The stage is
   centred vertically on a tall screen and top-aligned on a short one, so a
   phone keyboard never pushes the question off the top.
   -------------------------------------------------------------------------- */
.join { min-height:100dvh; display:flex; flex-direction:column; background:var(--page); }
/* `hidden` has to win. Half the things this flow hides are flex or grid
   containers, and a display rule in a stylesheet beats the attribute's UA
   default - so the buttons for step two sat under step one in full view. */
.join [hidden] { display:none !important; }

.join__top {
  padding:22px var(--gutter);
  display:flex; align-items:center; justify-content:space-between; gap:16px;
}
.join__logo { display:inline-flex; align-items:center; }
.join__logo img { height:20px; width:auto; display:block; }
.join__exit { font-size:14px; font-weight:500; color:var(--muted); }
.join__exit:hover { color:var(--ink); }

.join__stage {
  flex:1; display:flex; align-items:center; justify-content:center;
  padding:min(6vh, 48px) var(--gutter) clamp(48px, 10vh, 96px);
}
.join__col { width:100%; max-width:520px; }

/* Where you are. A number and a rule - a row of dots turns into a puzzle
   once there are more than four of them. */
.join__meta {
  display:flex; align-items:baseline; gap:8px;
  font-size:13px; font-weight:600; letter-spacing:-.01em; color:var(--muted);
}
.join__meta b { color:var(--ink); font-weight:600; }
.join__bar {
  margin-top:12px; height:3px; border-radius:99px;
  background:var(--hairline-strong); overflow:hidden;
}
.join__bar i {
  display:block; height:100%; width:0; border-radius:99px;
  background:var(--ink); transition:width 440ms var(--ease);
}

/* One step visible at a time. The outgoing one is removed rather than
   animated out: cross-fading two columns of fields over each other reads as
   a flicker, and the incoming card arriving is the thing worth watching. */
.join__step { display:none; }
.join__step.is-on { display:block; animation:joinFwd 420ms var(--ease) both; }
.join__step.is-on.is-back { animation:joinBack 420ms var(--ease) both; }
@keyframes joinFwd  { from { opacity:0; transform:translate3d(26px,0,0); } to { opacity:1; transform:none; } }
@keyframes joinBack { from { opacity:0; transform:translate3d(-26px,0,0); } to { opacity:1; transform:none; } }

/* The page's one real heading. The step titles below it are h2s: they change
   as the form advances, so none of them names the page, and five of the six
   are display:none at any moment. Kept small deliberately — the form is the
   thing to look at, this is only the label above it. */
.join__h1 {
  margin:0 0 14px;
  font-size:13px; font-weight:600; letter-spacing:-.01em; color:var(--muted);
}

.join__title {
  margin-top:26px;
  font-size:clamp(30px, 7.4vw, 40px); line-height:1.06; font-weight:600;
  letter-spacing:-.035em; color:var(--ink); text-wrap:balance;
}
.join__sub { margin-top:10px; font-size:16px; line-height:1.5; color:var(--body); }

.join__fields { margin-top:26px; display:grid; gap:18px; }
.join__fields .field__label { margin-bottom:9px; font-size:14.5px; }

/* The one choice that changes the rest of the flow. Big targets, because on
   a phone this is the first thing a thumb meets. */
.join__pick { margin-top:26px; display:grid; gap:12px; }
.join__pick-btn {
  width:100%; display:flex; align-items:center; gap:14px; text-align:left;
  padding:20px; border:1px solid var(--hairline-strong); border-radius:18px;
  background:#fff; color:var(--ink); cursor:pointer;
  transition:border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
             transform var(--dur) var(--ease);
}
.join__pick-btn:hover { border-color:var(--ink); box-shadow:var(--sh-card); }
.join__pick-btn:active { transform:scale(.99); }
.join__pick-btn[aria-pressed="true"] { border-color:var(--ink); box-shadow:var(--sh-card); }
.join__pick-icon {
  width:44px; height:44px; flex:none; border-radius:13px;
  display:grid; place-items:center; background:var(--page); color:var(--ink);
}
.join__pick-icon svg { width:21px; height:21px; }
.join__pick-text { min-width:0; }
.join__pick-name { display:block; font-size:17px; font-weight:600; letter-spacing:-.02em; }
.join__pick-what { display:block; margin-top:3px; font-size:14px; line-height:1.4; color:var(--muted); }

.join__nav { margin-top:26px; display:flex; align-items:center; gap:12px; }
.join__next { flex:1; height:56px; }
.join__back {
  height:56px; padding-inline:20px; border-radius:99px; flex:none;
  display:inline-flex; align-items:center; justify-content:center;
  border:1px solid var(--hairline-strong); background:#fff; color:var(--ink);
  font:600 15.5px/1 var(--font); cursor:pointer;
  transition:border-color var(--dur) var(--ease);
}
.join__back:hover { border-color:var(--ink); }
.join__enter { margin-top:14px; text-align:center; font-size:13px; color:var(--muted); }
.join__enter kbd {
  font:inherit; padding:1px 6px; border-radius:6px;
  border:1px solid var(--hairline-strong); background:#fff;
}
/* A keyboard hint is a lie on a touch screen. */
@media (hover:none) { .join__enter { display:none; } }

.join__err { margin-top:16px; font-size:14px; color:#b02318; }

/* The end. Two of them: a code that already works, or a request that is in. */
/* Focused on arrival so a screen reader lands on the outcome, but the ring
   is for keyboard navigation and this is not that: it drew a box around the
   whole result. */
.join__done { text-align:center; }
.join__done:focus { outline:none; }
.join__done .apply__tick { margin-bottom:16px; }
.join__code {
  margin-top:22px; display:inline-block; padding:14px 24px; border-radius:16px;
  background:#fff; border:1px dashed var(--hairline-strong);
  font-size:24px; font-weight:600; letter-spacing:.06em; color:var(--ink);
}
.join__done-actions { margin-top:20px; display:grid; gap:10px; }
.join__share {
  margin-top:18px; font-size:13.5px; color:var(--muted);
  display:flex; flex-direction:column; align-items:center; gap:6px;
}
.join__share button {
  border:0; background:none; padding:0; cursor:pointer;
  font:600 14px/1.4 var(--font); color:var(--ink); text-decoration:underline;
  text-underline-offset:3px; word-break:break-all;
}

@media (prefers-reduced-motion:reduce) {
  .join__step.is-on, .join__step.is-on.is-back { animation:none; }
  .join__bar i { transition:none; }
}

/* --------------------------------------------------------------------------
   Destination guides — /esim and /esim/<country>.

   THE LINK MESH IS IN THE FOOTER ON PURPOSE. These pages only earn their
   keep if a crawler can see them as a family, which needs every page to link
   its siblings; and the site's rule is that inside <main> the only links are
   store buttons. Both hold at once by putting the mesh after </main>. It is
   also where Pingo, the reference for this whole exercise, keeps theirs.

   No prices here and none in the markup: these are guides, not a catalogue.
   -------------------------------------------------------------------------- */
.footer__dest {
  margin-top:clamp(34px, 5vw, 56px);
  padding-top:clamp(26px, 3.4vw, 38px);
  border-top:1px solid rgba(255,255,255,.12);
}
.footer__dest h4 {
  margin:0 0 16px;
  font-size:var(--t-micro); font-weight:500; letter-spacing:.08em;
  text-transform:uppercase; color:rgba(255,255,255,.52);
}
.footer__dest-cols { display:grid; gap:0 clamp(20px, 3vw, 44px); grid-template-columns:repeat(3, minmax(0,1fr)); }
.footer__dest-cols ul { margin:0; padding:0; list-style:none; }
.footer__dest-cols li { margin:0 0 9px; }
.footer__dest-cols a { font-size:14px; color:rgba(255,255,255,.66); }
.footer__dest-cols a:hover { color:#fff; }
@media (max-width:640px) {
  .footer__dest-cols { grid-template-columns:repeat(2, minmax(0,1fr)); }
}

/* The index. Cards, not a price grid — each one carries the country and the
   single thing that makes its page worth opening. */
.dest {
  margin:0; padding:0; list-style:none;
  display:grid; gap:clamp(10px, 1.4vw, 14px);
  grid-template-columns:repeat(auto-fill, minmax(268px, 1fr));
}
.dest a {
  display:flex; flex-direction:column; gap:5px; height:100%;
  padding:18px 20px;
  border:1px solid var(--hairline); border-radius:14px;
  background:#fff;
  transition:border-color 160ms linear, background-color 160ms linear;
}
.dest a:hover { border-color:var(--hairline-strong); background:#fcfcfd; }
.dest__name { font-size:var(--t-body); font-weight:500; color:var(--ink); letter-spacing:-.01em; }
.dest__note { font-size:14px; line-height:1.5; color:var(--muted); text-wrap:pretty; }

/* At twenty destinations the footer could list them all. At 205 it cannot:
   that is 205 links on every one of 214 pages, which dilutes each one and
   bloats the page. The footer carries the twelve most-wanted and a route to
   the index; /esim is the hub that links all of them, so anywhere on the site
   is two hops from any destination. */
.footer__dest-all { margin-top:16px; }
.footer__dest-all a { font-size:14px; color:#fff; border-bottom:1px solid rgba(255,255,255,.3); padding-bottom:2px; }
.footer__dest-all a:hover { border-bottom-color:#fff; }

/* The destination hub. A plain indexed list, not a catalogue of cards: there
   are 205 of them and nothing to say about each one here except its name. */
.destjump { display:flex; flex-wrap:wrap; gap:14px; margin-top:22px; }
.destjump a { font-size:14px; color:var(--muted); border-bottom:1px solid var(--hairline); padding-bottom:2px; }
.destjump a:hover { color:var(--ink); border-bottom-color:var(--hairline-strong); }

.destgrp { margin-top:clamp(34px, 4vw, 52px); }
.destgrp:first-child { margin-top:0; }
.destgrp h2 { display:flex; align-items:baseline; gap:10px; }
.destgrp__n { font-size:var(--t-micro); font-weight:400; color:var(--muted); }
.destlist {
  margin:18px 0 0; padding:0; list-style:none;
  display:grid; gap:2px clamp(18px, 2.4vw, 32px);
  grid-template-columns:repeat(auto-fill, minmax(190px, 1fr));
}
.destlist li { margin:0; }
.destlist a {
  display:block; padding:7px 0;
  font-size:15px; color:var(--body);
  border-bottom:1px solid transparent;
}
.destlist a:hover { color:var(--ink); }
