/*
 * One skin for the whole of Lempart Flex on the web.
 *
 * The marketing pages, the tariff tables, the account area and the checkout all load this
 * file, so the site looks like one company rather than three. The brand's own colour,
 * corner radius and typeface arrive as CSS variables — written by the server into the page
 * for the static parts, and by app.js from the design document for the dynamic ones — so
 * changing the accent in the Studio changes the website too.
 *
 * A website is not a phone. There is no tab bar and no phone-shaped column here: the
 * layout is wide where a browser is wide, and narrows to one comfortable column on a
 * phone. The shop front has room for the big banner a shop front needs, and the thing a
 * visitor came for — a destination, and what it costs — is a tap away from every page.
 */
/* One theme, on purpose (owner, 23 Sep 2026)
   ------------------------------------------
   A night version was built and it was a mess to read: five greens within a few percent
   of each other, then a lime that shouted. The shop now shows the same warm ivory to
   everybody, whatever their phone is set to, which is also what every screenshot, every
   store listing and every reviewer will see. `color-scheme: light` keeps the browser's
   own furniture — form fields, select menus, scrollbars — light with it. */
:root {
  color-scheme: light;
  /* The Flex brand kit (17 Sep 2026): warm ivory, forest, lime. */
  --accent: #073D31;
  --on-accent: #F6F4EC;
  /*
   * The accent when it is ink rather than paint.
   *
   * `--accent` is written over by the Studio's theme — app.js sets it as an inline style on
   * :root, and every server-rendered page repeats it in a <style> after this file — so a
   * dark-mode `--accent` declared here would never survive to the screen. The forest that
   * reads beautifully as a button under a light page is 1.41:1 against the dark page's own
   * background: on a dark screen every link, eyebrow, pill and ghost button was a
   * near-black shape on near-black. So the accent-as-text has its own token. In the light
   * it is the brand's accent, whatever the Studio says it is; in the dark it is the brand's
   * lime, 14.8:1 on the forest background, because nothing else in the kit can be read
   * there.
   */
  --accent-text: var(--accent);
  --secondary: #073D31;
  --lime: #D9FC57;
  --forest: #073D31;
  --radius: 16px;
  /*
   ONE GUTTER FOR THE PICKER (owner, 24 Sep 2026)
   ==============================================
   "Can you make so all these buttons and lines have some space away from edge like the
   7 days button." On /usa-esim at 390 the fold's controls each stood a different distance
   from the screen: the segment, the day chips and the shelf of sizes sat hard against the
   card that held them (17px in, 1px of which was the card's own line), while everything in
   the pinned bar — the switches, the Covers chips, Total, Buy now — sat 11px from the edge
   of the phone. Five widths in one column.

   This is the number the chips already had: the space between the words on a day button
   and the button's own edge. It is the shelf row's padding, the bar's padding and the
   page's own gutter on a phone as well, so everything in that column now begins and ends
   on the same two lines. Change it here and it moves everywhere at once, which is the
   point — pickerGutter.test.ts keeps them from drifting apart again.
  */
  --gutter: 16px;
  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  --ink: #082C29;
  --muted: #55645F;
  --bg: #F6F4EC;
  --card: #FFFFFF;
  --line: #D6DACF;
  --wash: color-mix(in srgb, var(--accent) 9%, transparent);

  /* ONE COLUMN FOR THE WHOLE SITE (23 Sep 2026).
     `.wrap` was 1120 and `.wrap.shop` 1160, so walking from /how-it-works to a destination
     page stepped the whole site sideways by 20px a side — the largest possible failure of
     "everything has to be aligned". The shop's is the measured one and the one nearer the
     reference's 1184, so the informational pages come up to meet it rather than the shop
     coming down: that way the home page's banner, which must not move, is not touched at
     any width. Measured: the shop and the home page render identically before and after;
     the `.wrap` pages gain 40px of column at 1440 and are unchanged at 375. */
  --page: 1160px;
  --shadow-1: 0 1px 2px rgba(16, 24, 40, .05);
  --shadow-2: 0 1px 2px rgba(16, 24, 40, .05), 0 10px 26px rgba(16, 24, 40, .07);
  --shadow-3: 0 20px 50px rgba(16, 24, 40, .14);
  --shadow: var(--shadow-2);
}

* { box-sizing: border-box; }

/*
 * THE LOGO, AND ONLY THE LOGO, WHILE THE SITE OPENS (owner, 27 Sep 2026)
 * ---------------------------------------------------------------------
 * The layer the first page of a visit opens under: the site's ivory, and the app icon in
 * the middle with the breathing the shop's own splash has (index.html). `lf-splash` is put
 * on <html> by the script in every page's head (SPLASH_HEAD in apps/api/src/site.ts), which
 * also takes it off again — `lf-splash-out` is its 180 ms fade. Two pseudo-elements and no
 * words: everything on the page stays in the page, for a crawler and a screen reader alike.
 */
html.lf-splash::before, html.lf-splash::after {
  content: ""; position: fixed; z-index: 2147483647;
  transition: opacity .18s ease-out, visibility 0s linear .18s;
}
html.lf-splash::before { top: 0; right: 0; bottom: 0; left: 0; background: #F6F4EC; }
html.lf-splash::after {
  top: 50%; left: 50%; width: 88px; height: 88px; margin: -44px 0 0 -44px; border-radius: 20px;
  background: url(/icon-192.png) 50% 50% / 88px 88px no-repeat;
  animation: lf-breathe 1.6s ease-in-out infinite;
}
html.lf-splash-out::before, html.lf-splash-out::after { opacity: 0; visibility: hidden; pointer-events: none; animation: none; }
@keyframes lf-breathe { 50% { opacity: .55; transform: scale(.96); } }
@media (prefers-reduced-motion: reduce) {
  html.lf-splash::before, html.lf-splash::after { animation: none; transition: none; }
}

body {
  margin: 0;
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.5;
  color: var(--ink);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  padding-bottom: env(safe-area-inset-bottom);
}

.boot { padding: 90px 20px; text-align: center; color: var(--muted); }

::selection { background: color-mix(in srgb, var(--accent) 28%, transparent); }

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

.shell { max-width: var(--page); margin: 0 auto; padding: 0 20px 72px; }
.wrap { max-width: var(--page); margin: 0 auto; padding: 0 22px 72px; }

a { color: var(--accent-text); }

/*
 * A link inside a sentence is underlined.
 *
 * Colour was the only thing telling a link from the words around it, and the colour was
 * 1.23:1 against the body text in the light and 1.06:1 in the dark - a difference nobody
 * with any degree of colour blindness can see, and most people without one would miss in a
 * paragraph. WCAG 1.4.1 asks for something besides the hue; a rule under the word is the
 * oldest answer there is.
 *
 * Prose only: a sentence, a list item, the body of a legal document. The navigation, the
 * buttons, the chips and the rows where the whole card is the link are shapes already, and
 * a page of them ruled would be a page of noise - so the ones that live inside a paragraph
 * are excepted back out.
 */
p a, li a, dd a, figcaption a {
  text-decoration: underline;
  text-underline-offset: .16em;
  text-decoration-thickness: max(1px, .06em);
}
p a.cta, li a.cta, p a.btn, li a.btn, p a.banner, li a.banner,
p a.chip, li a.chip, p a.pill, li a.pill, p a.row, li a.row, p a.dest, li a.dest,
footer p a { text-decoration: none; }

/* The header is the same on the marketing pages and inside the shop (app.js builds it). */
header {
  position: sticky; top: 0; z-index: 30;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  /* --scrollbar is set by the page (app.js / the site shell): 100vw counts the scrollbar,
     so without it the header was 8px wider than the window and the page scrolled sideways. */
  margin: 0 calc(50% - 50vw + var(--scrollbar, 0px) / 2) 4px; padding: 12px max(22px, calc(50vw - var(--scrollbar, 0px) / 2 - (var(--page) / 2) + 22px));
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: saturate(1.6) blur(14px);
  -webkit-backdrop-filter: saturate(1.6) blur(14px);
  border-bottom: 1px solid color-mix(in srgb, var(--line) 70%, transparent);
}
.logo { display: flex; align-items: center; gap: 10px; font-weight: 700; font-size: 18px; letter-spacing: -.02em; text-decoration: none; color: var(--ink); }

.logo span {
  display: inline-grid; place-items: center; width: 32px; height: 32px; border-radius: 10px;
  background: linear-gradient(135deg, var(--accent), color-mix(in srgb, var(--secondary) 70%, #000 30%));
  color: var(--on-accent); font-weight: 800; font-size: 16px;
  box-shadow: 0 4px 12px color-mix(in srgb, var(--accent) 40%, transparent);
}
nav { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; justify-content: flex-end; }
nav a {
  font-size: 14px; font-weight: 600; color: var(--muted); text-decoration: none;
  padding: 8px 11px; border-radius: 999px;
}
nav a:hover { color: var(--ink); background: color-mix(in srgb, var(--ink) 6%, transparent); }
nav a.here { color: var(--on-accent); background: var(--accent); }
/* The one place the site asks instead of deciding.

   Shown only when the address could not be placed and the browser asked for nothing we
   carry - the reader behind a VPN, on Tor, or with a browser that sends no preference. It
   carries no sentence on purpose: a sentence would have to be in some language, and the
   whole reason this is on screen is that we do not know which one. Names in their own
   scripts need no translating. */
.langbar {
  display: flex; align-items: center; gap: 4px; flex-wrap: wrap;
  margin: 0 0 18px; padding: 8px 10px; border-radius: 14px;
  background: var(--wash); border: 1px solid var(--line);
}
.langbar svg { width: 17px; height: 17px; color: var(--muted); margin: 0 4px; flex: none; }
.langbar a {
  font-size: 13px; font-weight: 600; color: var(--muted); text-decoration: none;
  padding: 5px 10px; border-radius: 999px;
}
.langbar a:hover { color: var(--ink); background: color-mix(in srgb, var(--ink) 6%, transparent); }
.langbar a.on { color: var(--on-accent); background: var(--accent); }

/* The language control sits in the nav and has to look like it belongs there, not like a
   form control somebody forgot to style. */
select.lang {
  font: inherit; font-size: 14px; font-weight: 600; color: var(--muted);
  padding: 7px 10px; border-radius: 999px; cursor: pointer;
  background: color-mix(in srgb, var(--ink) 5%, transparent);
  border: 1px solid color-mix(in srgb, var(--line) 70%, transparent);
}
select.lang:hover { color: var(--ink); }

/* What a bundle carries beyond the base, on the line somebody is choosing from. Four flags
   are read at a glance; the sentence they replaced had to be parsed. */
/* Two zones that flow: they share a line when both fit and take a line each when they do
   not, so a plus is never stranded at the end of a line with its flags wrapped under it. */
.extras { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 3px; line-height: 1; align-items: flex-start; }
/* The faintest wash behind what a bundle is missing and what it adds — on the zone, never
   on the flags, which have their own colours and are the thing being read. */
.extras .zone { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 4px; padding: 3px 7px; border-radius: 8px; }
.extras .zone.out { background: color-mix(in srgb, #d24b4b 11%, transparent); }
.extras .zone.in { background: color-mix(in srgb, #1f9d55 12%, transparent); }
/* The base the flags are added to, in words, INSIDE the green field with them — "EU + EFTA
   + 🇬🇧🇹🇷🇺🇦" (owner, 27 Sep 2026: "not grey but green", then "in the same field with
   flags so it's obvious what it shows"). Green ink, darker than the wash, to read at this size. */
.extras .zone .base { font-weight: 700; font-size: 12.5px; color: #16793c; margin-right: 1px; }

.extras .f { font-size: 15px; }
.extras .sign { font-weight: 800; font-size: 13px; color: var(--muted); margin-left: 2px; }
.extras .sign.out { color: #c0392b; margin-left: 0; }
/* A country the plan does NOT have. The RED FIELD behind it says so — the flag itself
   keeps its colours, because a grey flag is not a flag: nobody can tell Chad from Romania
   in greyscale, which defeated the whole point of printing the flag. */
.extras .f.out { opacity: 1; filter: none; }
/* The marketing pages draw flags as little pictures rather than emoji, because Windows
   renders an emoji flag as two grey letters. Same row, same size. */
.extras img.flag { width: 20px; height: 15px; border-radius: 2px; margin: 0; box-shadow: none; }
/* Full colour here too, with a thin dark edge so a pale flag still reads on the red. */
.extras img.flag.out { opacity: 1; filter: none; box-shadow: 0 0 0 1px rgba(0,0,0,.14); }
.countries .country img.flag { width: 20px; height: 15px; border-radius: 2px; box-shadow: none; }
.chip img.flag { width: 18px; height: 14px; border-radius: 2px; box-shadow: none; display: inline-block; vertical-align: -2px; }


.topbar {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; gap: 12px;
  padding: 12px 16px;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: saturate(1.4) blur(12px);
  border-bottom: 1px solid var(--line);
}
.topbar .brand { font-weight: 650; letter-spacing: -.01em; display: flex; align-items: center; gap: 8px; color: inherit; text-decoration: none; }
.topbar .brand .mark { width: 26px; height: 26px; border-radius: 8px; background: var(--accent); color: var(--on-accent); display: grid; place-items: center; font-size: 14px; font-weight: 700; }
.topbar .spacer { flex: 1; }
.topbar a.plain { color: var(--muted); text-decoration: none; font-size: 14px; font-weight: 600; }

footer {
  margin-top: 72px; padding-top: 22px; border-top: 1px solid var(--line);
  color: var(--muted); font-size: 13.5px; display: flex; flex-wrap: wrap; gap: 10px 20px; align-items: center;
}
footer a { color: var(--muted); text-decoration: none; }
footer a:hover { color: var(--ink); }
/* Who is selling, where they are and how to write to them: its own line above the row of
   links, because it is a statement rather than another place to click. */
footer .trader { flex: 1 0 100%; color: var(--muted); }
footer .trader b { color: var(--ink); font-weight: 650; }
footer .trader a { text-decoration: underline; text-underline-offset: .16em; }

/* --- type -------------------------------------------------------------------------- */

h1 { letter-spacing: -.03em; }
h2 { font-size: clamp(21px, 2.4vw, 27px); margin: 0 0 12px; letter-spacing: -.02em; }
h3 { letter-spacing: -.01em; }
section { margin-top: 52px; }
section > p { color: var(--muted); margin: 8px 0; max-width: 68ch; }

.eyebrow {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 12.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--accent-text); background: var(--wash);
  padding: 6px 12px; border-radius: 999px; margin-bottom: 16px;
}
.lede { font-size: clamp(16.5px, 1.5vw, 19px); color: var(--muted); max-width: 60ch; }
.sub { color: var(--muted); }
.small { font-size: 13px; }
.muted { color: var(--muted); }
.caption { font-size: 12.5px; color: var(--muted); }

/* --- the shop front ---------------------------------------------------------------- */

.hero { position: relative; padding: 60px 0 26px; }
.hero.lead::before {
  content: ""; position: absolute; z-index: -1;
  top: -160px; bottom: 20px; left: calc(50% - 50vw + var(--scrollbar, 0px) / 2); right: calc(50% - 50vw + var(--scrollbar, 0px) / 2);
  background:
    radial-gradient(46% 60% at 22% 30%, color-mix(in srgb, var(--accent) 22%, transparent), transparent 70%),
    radial-gradient(40% 55% at 78% 12%, color-mix(in srgb, var(--secondary) 16%, transparent), transparent 72%);
  filter: blur(4px);
  pointer-events: none;
}
.hero h1 { font-size: clamp(34px, 5.4vw, 58px); line-height: 1.03; margin: 0 0 16px; max-width: 16ch; }
.hero p { font-size: clamp(16.5px, 1.5vw, 19px); color: var(--muted); margin: 0 0 24px; max-width: 60ch; }
.hero .actions { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }

.facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; margin: 30px 0 4px; }
.fact { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 15px 17px; box-shadow: var(--shadow-1); }
.fact b { display: block; font-size: 25px; letter-spacing: -.02em; line-height: 1.15; }
.fact small { color: var(--muted); }

.cta {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  background: var(--accent); color: var(--on-accent); text-decoration: none;
  padding: 14px 22px; border-radius: 999px; font-weight: 650; font-size: 15.5px;
  border: 1px solid transparent;
  box-shadow: 0 8px 22px color-mix(in srgb, var(--accent) 32%, transparent);
  transition: transform .12s ease, box-shadow .12s ease;
}
.cta:hover { transform: translateY(-1px); box-shadow: 0 12px 28px color-mix(in srgb, var(--accent) 38%, transparent); }
.cta.soon { background: color-mix(in srgb, var(--ink) 10%, transparent); color: var(--muted); box-shadow: none; cursor: default; }
/* The store buttons: Apple's badge at the height of a .cta, the Android pill beside it. */
.store-buttons { display: inline-flex; flex-wrap: wrap; gap: 10px; align-items: center; }
/* Under the "next steps" rows: on the rows' own text line (the gutter), a little air above,
   not jammed against the box (owner, 25 Sep 2026: "align … make lines more near and stylish"). */
.card > .store-buttons { display: flex; margin-top: 12px; padding: 0 var(--gutter); }
/* After a paragraph on the long pages: on the text's own line, with a paragraph's air. */
.band > .store-buttons, .ed-section > .store-buttons, section > .store-buttons { display: flex; margin-top: 14px; }
.store-badge { display: inline-flex; line-height: 0; border-radius: 8px; }
.store-badge img { height: 50px; width: 150px; display: block; }
/* The band under "Where are you going?": the field's own width (720px on a wide screen,
   the column on a phone), one row — a label, Apple's badge, the Android pill. */
.store-band { display: flex; justify-content: center; max-width: 720px; margin: 10px auto 0; }
/* Centred line by line: where the two do not fit side by side and the Android pill drops
   under the badge, it stays under the field's middle instead of hanging off its left edge. */
.store-band .store-buttons { gap: 10px; justify-content: center; }
/* The band sits 14px above the banner, not a section's worth of air (owner, 25 Sep 2026). */
.store-band + .block { margin-top: 14px !important; }
/* The Android button before there is an Android app: the rounded, shaded pill it always
   was (`.cta.soon`), the badge's size — 150 × 50, not twice its length (owner,
   25 Sep 2026) — so its words sit on two centred lines.

   NEVER CUT SHORT (owner, 27 Sep 2026). 150 was a fixed width with an ellipsis, and in
   Ukrainian it read "Застосунок для А… незабаром"; Russian and Polish lost letters too.
   150 × 50 is now the SMALLEST it gets: a longer line widens the pill to fit (Ukrainian and
   Russian come out 20–30px wider, still one badge high), and on a column too narrow even
   for that the words wrap onto another line and the pill grows taller. Nothing is ever
   hidden. */
.store-soon { display: inline-flex; flex-direction: column; align-items: center; justify-content: center; box-sizing: border-box; min-width: 150px; max-width: 100%; min-height: 50px; padding: 4px 10px; border-radius: 999px; background: color-mix(in srgb, var(--ink) 10%, transparent); color: var(--muted); font-weight: 650; font-size: 12.5px; line-height: 1.2; text-align: center; }
.store-soon .s1, .store-soon .s2 { display: block; max-width: 100%; overflow-wrap: break-word; }
.cta.quiet { background: var(--card); color: var(--ink); border-color: var(--line); box-shadow: var(--shadow-1); }

/* Destination cards — the same two hues the phone draws for a place, so the shop and the
   app never disagree about what colour Japan is. */
/*
 * `hidden` has to win.
 *
 * The browser's own rule for [hidden] is `display: none` at the weakest possible strength,
 * so ANY rule that sets a display — and every card, row and chip here sets one — silently
 * beats it. The country search on /plans set `hidden` on 197 of 198 cards and every one of
 * them stayed on the screen: the filter was working perfectly and the stylesheet was
 * throwing the answer away. Found on 11 September 2026 by typing "viet" and watching
 * Afghanistan stay put.
 */
[hidden] { display: none !important; }

.destgrid { display: grid; gap: 14px; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); }
.destgrid.wide { grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); }
.dest {
  position: relative; display: flex; flex-direction: column; justify-content: flex-end;
  min-height: 132px; padding: 16px; border-radius: var(--radius); overflow: hidden;
  text-decoration: none; color: #fff; isolation: isolate;
  box-shadow: var(--shadow-2);
  transition: transform .14s ease, box-shadow .14s ease;
}
.dest::after { content: ""; position: absolute; inset: 0; z-index: -1; background: linear-gradient(158deg, rgba(255,255,255,.16), rgba(255,255,255,0) 46%, rgba(0,0,0,.34)); }
.dest:hover { transform: translateY(-3px); box-shadow: var(--shadow-3); }
.dest .flag { position: absolute; top: 13px; left: 15px; font-size: 30px; line-height: 1; filter: drop-shadow(0 2px 5px rgba(0,0,0,.3)); }
.dest .name { font-weight: 680; font-size: 17px; letter-spacing: -.01em; text-shadow: 0 1px 6px rgba(0,0,0,.3); }
.dest .from { font-size: 13.5px; opacity: .92; text-shadow: 0 1px 6px rgba(0,0,0,.3); }
.dest.plain { color: var(--ink); background: var(--card); border: 1px solid var(--line); min-height: 96px; }
.dest.plain::after { display: none; }
.dest.plain .name, .dest.plain .from { text-shadow: none; }
.dest.plain .from { color: var(--muted); }

/* The big promotion, and the smaller ones under it. */
.billboard {
  position: relative; overflow: hidden;
  border-radius: calc(var(--radius) + 8px);
  padding: clamp(26px, 4vw, 44px);
  color: var(--on-accent);
  background: linear-gradient(135deg, var(--accent), color-mix(in srgb, var(--secondary) 55%, #101828 45%));
  display: grid; gap: 10px;
  box-shadow: var(--shadow-3);
}
.billboard::before {
  content: ""; position: absolute; inset: -50% -20% auto auto; width: 60%; aspect-ratio: 1;
  background: radial-gradient(circle, rgba(255,255,255,.22), transparent 62%);
  pointer-events: none;
}
.billboard h2 { margin: 0; font-size: clamp(24px, 3.6vw, 38px); color: inherit; letter-spacing: -.025em; max-width: 18ch; }
.billboard p { margin: 0; color: inherit; opacity: .93; font-size: clamp(15.5px, 1.5vw, 18px); max-width: 54ch; }
.billboard .cta { background: var(--on-accent); color: var(--accent); margin-top: 12px; justify-self: start; box-shadow: 0 10px 26px rgba(0,0,0,.22); }

.promos { display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); }
.promo {
  display: block; border-radius: var(--radius); padding: 22px; background: var(--card); border: 1px solid var(--line);
  box-shadow: var(--shadow-1); color: inherit; text-decoration: none;
  transition: transform .14s ease, box-shadow .14s ease;
}
a.promo:hover { transform: translateY(-2px); box-shadow: var(--shadow-2); }
.promo h3 { color: var(--ink); }
.promo .glyph { font-size: 24px; line-height: 1; display: block; margin-bottom: 10px; }
.promo h3 { margin: 0 0 6px; font-size: 17px; }
.promo p { margin: 0; color: var(--muted); font-size: 15px; }

/* ------------------------------------------------------------------ signing in
   Two buttons the size of buttons, side by side, not two full-width slabs. The colours
   are the ones Apple and Google's own guidelines describe for their buttons — black for
   Apple, white with a hairline for Google — which is a convention, not their artwork:
   the marks themselves are their files in /app/brand/ and the button prints correctly
   without them. */
.idps { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 6px; }
.idp {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  padding: 11px 18px; min-height: 44px; border-radius: 10px;
  font: inherit; font-size: 15px; font-weight: 600; cursor: pointer;
  border: 1px solid var(--line); background: var(--card); color: var(--ink);
  transition: transform .12s ease, border-color .12s ease;
}
.idp:hover { transform: translateY(-1px); border-color: color-mix(in srgb, var(--ink) 28%, var(--line)); }
.idp .idp-mark { width: 18px; height: 18px; display: block; }
/* Apple's button is black on light and white on dark; Google's is the reverse of neither
   — it stays white with a hairline, which is what their guidelines ask for. */
.idp-apple { background: #000; color: #fff; border-color: #000; }
.idp-google { background: #fff; color: #1f1f1f; border-color: #dadce0; }
/* Apple's own button picture, once it has loaded: the capsule steps out of the way and
   the picture is the button — 44px tall, Apple's mark and words, our width. */
.idp .idp-face { display: none; height: 44px; width: auto; max-width: 100%; }
.idp-apple.has-face { padding: 0; background: transparent; border-color: transparent; }
.idp-apple.has-face .idp-face { display: block; }
.idp-apple.has-face .idp-words { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }

/* ======================================================================= the account
   A rail of sections and one panel at a time, instead of a single column that ended in
   three links. Below 860px the rail becomes a scrolling strip of chips across the top,
   because a phone has no side to put a sidebar on. */
/* Your name on the left, the way out on the right - the two things you look for first. */
.acct-head { display: flex; align-items: flex-start; gap: 12px; flex-wrap: wrap; margin: 18px 0 16px; }
.acct-head h1 { margin: 0 0 2px; }
.acct-head p { margin: 0; }
.acct-head .acct-out { flex: none; margin-top: 4px; }

/* At the foot of the rail, set apart: a way out is not another room. */
.acct-leave {
  width: 100%; margin-top: 10px; padding-top: 14px; border: 0; background: none; cursor: pointer;
  border-top: 1px solid var(--line); border-radius: 0; color: var(--muted); font: inherit; text-align: start;
}
.acct-leave:hover { color: var(--ink); background: none; }

.acct { display: grid; gap: 18px; align-items: start; }
@media (min-width: 860px) { .acct { grid-template-columns: 232px minmax(0, 1fr); gap: 26px; } }

/* The rail is a <nav>, and the shop's generic `nav` rule is flex-end, centred, with its
   own link styling at a higher specificity than a single class. Everything here is written
   under `.acct-nav` so it wins, rather than fighting the header's navigation with !important. */
.acct-nav { display: flex; gap: 6px; overflow-x: auto; padding-bottom: 4px; scrollbar-width: none; justify-content: flex-start; align-items: stretch; }
.acct-nav::-webkit-scrollbar { display: none; }
@media (min-width: 860px) {
  .acct-nav { position: sticky; top: 84px; flex-direction: column; overflow: visible; padding: 0; }
}
/* On a phone the rail is a wrapped strip of chips: everything visible in two or three
   rows, rather than a sideways scroll that hides half the account behind an edge. */
@media (max-width: 859px) {
  .acct-nav { flex-wrap: wrap; gap: 6px; }
  .acct-nav .acct-tab { padding: 7px 11px; font-size: 13.5px; background: var(--card); border-color: var(--line); }
  .acct-nav .acct-tab.on { background: var(--wash); border-color: color-mix(in srgb, var(--accent) 35%, var(--line)); }
}
.acct-nav .acct-tab {
  display: flex; align-items: center; justify-content: flex-start; text-align: start;
  gap: 8px; white-space: nowrap; width: auto;
  padding: 9px 13px; border-radius: 10px;
  font-size: 14.5px; font-weight: 500; color: var(--muted); text-decoration: none;
  border: 1px solid transparent; background: none;
  transition: background .14s ease, color .14s ease;
}
.acct-nav .acct-tab:hover { background: color-mix(in srgb, var(--accent) 6%, transparent); color: var(--ink); }
.acct-nav .acct-tab.on { background: var(--wash); color: var(--accent-text); font-weight: 600; }
.acct-nav .acct-tab .grow { flex: 1; text-align: start; }
.acct-nav .acct-note {
  font-size: 11.5px; font-weight: 650; padding: 1px 7px; border-radius: 999px;
  background: color-mix(in srgb, var(--accent) 14%, transparent); color: var(--accent-text);
}
.acct-nav .acct-tab.on .acct-note { background: color-mix(in srgb, var(--accent) 22%, transparent); }

.acct-pane { min-width: 0; }
.acct-pane > div > h2 { margin: 0 0 4px; }
.acct-pane > div > h2 + p { margin: 0 0 4px; }

/* The four numbers at the top of the overview. */
.acct-tiles { display: grid; gap: 10px; grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (min-width: 620px) { .acct-tiles { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.acct-tile { background: var(--card); border: 1px solid var(--line); border-radius: 12px; padding: 14px 16px; }
.acct-tile-v { font-size: 22px; font-weight: 700; letter-spacing: -.02em; color: var(--ink); line-height: 1.15; }
.acct-tile-k { font-size: 12.5px; color: var(--muted); margin-top: 2px; }

/* Three real doors out of the account, at the weight of a secondary action — the shop's
   own `.btn.ghost` is a bare word, which reads as a link rather than a button in a row. */
.acct-quick { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
.acct-quick .btn { padding: 10px 16px; font-size: 14.5px; font-weight: 600; }
.acct-figure { font-size: 30px; font-weight: 700; letter-spacing: -.025em; color: var(--ink); margin: 6px 0 8px; }

.acct-empty {
  margin-top: 14px; padding: 26px 22px; text-align: center;
  border: 1px dashed var(--line); border-radius: 14px; color: var(--muted);
}
.acct-empty p { margin: 0 0 12px; font-size: 14.5px; }
.acct-empty p:last-child { margin-bottom: 0; }

.acct-field { padding: 14px 0; border-top: 1px solid var(--line); }
.acct-field:first-of-type { border-top: 0; }
.acct-label { font-size: 11.5px; font-weight: 650; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); margin-bottom: 5px; }
.acct-field p { margin: 6px 0 0; }
.acct-input {
  font: inherit; font-size: 15px; color: inherit;
  background: var(--card); border: 1px solid var(--line); border-radius: 10px;
  padding: 9px 12px; min-width: 0; flex: 1 1 180px; outline: none;
}
.acct-input:focus { border-color: var(--accent-text); }
.acct-claim { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--line); }
.acct-danger { display: grid; gap: 10px; justify-items: start; }

/* ==================================================================== the front page
   The sections added on 14 September: the shelf, the argument, the comparison and the
   questions. Every colour here is a token this file already defined — the accent, its
   wash, the line, the card, the two shadows. Nothing new was introduced and nothing that
   was already on the page was touched.

   The rule the second pass was written to: weight comes from rhythm, not from fill. A
   hairline and a small capital do the work a tinted panel was doing, in a fifth of the
   height, and the page reads as one surface instead of a stack of slabs. */

/* A section's own label, small and quiet, above its heading. */
.eyebrow + h2 { margin-top: 4px; }
.lede { margin: 0 0 18px; color: var(--muted); font-size: 15.5px; line-height: 1.6; max-width: 58ch; }

/* The mark: one glyph, sized to sit beside a heading rather than announce itself. */
.mark {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; flex: 0 0 30px;
  border-radius: 9px; background: var(--wash);
}
.mark svg { width: 17px; height: 17px; color: var(--accent-text); display: block; }

/* ------------------------------------------------------------------------- the shelf
   Six ways to buy. Equal-height cards on a tight grid, the price pinned to the bottom so
   the six numbers line up across the row instead of floating wherever the copy ended. */
/* Six cards want three columns and two full rows, not four and a gap-toothed second. */
.ways { display: grid; gap: 12px; grid-template-columns: 1fr; }
@media (min-width: 620px) { .ways { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 940px) { .ways { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.way {
  position: relative; display: flex; flex-direction: column; gap: 7px;
  padding: 18px 18px 16px; border-radius: 14px;
  background: var(--card); border: 1px solid var(--line);
  color: inherit; text-decoration: none;
  transition: border-color .15s ease, transform .15s ease;
}
.way:hover { border-color: color-mix(in srgb, var(--accent) 45%, var(--line)); transform: translateY(-1px); }
.way h3 { margin: 2px 0 0; font-size: 15.5px; letter-spacing: -.01em; color: var(--ink); }
.way p { margin: 0; font-size: 13.5px; line-height: 1.55; color: var(--muted); }
.way .from {
  margin-top: auto; padding-top: 10px;
  font-size: 13px; font-weight: 600; color: var(--accent-text);
}
.way .badge {
  position: absolute; top: 16px; inset-inline-end: 16px;
  padding: 2px 8px; border-radius: 999px;
  font-size: 10.5px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
  background: var(--wash); color: var(--accent-text);
}

/* --------------------------------------------------------------------- the argument
   Two columns, the first argument across both. Five full-width slabs were five screens
   of scrolling with an empty right half on every one of them; a column sets the measure
   at something readable without a max-width fighting the card it sits in. */
.reasons { display: grid; gap: 12px; grid-template-columns: 1fr; }
@media (min-width: 860px) {
  .reasons { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .reasons > .reason:first-child { grid-column: 1 / -1; }
  .reasons > .reason:first-child .said { max-width: 74ch; }
}
.reason {
  background: var(--card); border: 1px solid var(--line); border-radius: 14px;
  overflow: hidden; box-shadow: none;
}
.reason .said { padding: 20px 22px; display: block; }
.reason .said > .mark { margin-bottom: 12px; }
.reason h3 {
  margin: 0 0 8px; font-size: 18.5px; line-height: 1.25; letter-spacing: -.02em; color: var(--ink);
}
.reason p { margin: 0; color: var(--muted); font-size: 14.5px; line-height: 1.62; max-width: none; }

/* The stakes: a hairline and a small capital, not a filled panel. */
.reason .matters {
  margin-top: 14px; padding: 0 0 0 14px;
  border-inline-start: 2px solid color-mix(in srgb, var(--accent) 55%, transparent);
  color: var(--ink); font-size: 13.5px; line-height: 1.6;
}
.reason .matters b {
  display: block; margin-bottom: 2px;
  font-size: 10.5px; font-weight: 650; letter-spacing: .1em; text-transform: uppercase;
  color: color-mix(in srgb, var(--accent-text) 85%, var(--ink));
}

/* The photograph, when the five of them exist: across the top of a narrow card. */
.reason .shot { background-size: cover; background-position: center; aspect-ratio: 16 / 9; }
@media (min-width: 860px) {
  .reasons > .reason.pictured:first-child { display: grid; grid-template-columns: minmax(0, 38%) minmax(0, 1fr); }
  .reasons > .reason.pictured:first-child .shot { aspect-ratio: auto; height: 100%; }
}

/* ------------------------------------------------------------------- the comparison
   Our column is tinted; the other two are described rather than mocked. Tight rows, one
   size down, because six short rows should read as a glance and not as a spreadsheet. */
table.versus { min-width: 600px; font-size: 14px; }
table.versus th, table.versus td { padding: 11px 14px; vertical-align: middle; }
table.versus th[scope="row"] {
  text-align: start; font-weight: 500; font-size: 14px; color: var(--ink);
  text-transform: none; letter-spacing: normal; width: 34%;
}
table.versus td { color: var(--muted); font-weight: 400; }
table.versus td:last-child, table.versus th:last-child { text-align: start; white-space: normal; font-weight: 400; }
table.versus .mine { background: var(--wash); }
table.versus td.mine { text-align: center; }
table.versus thead th { white-space: normal; font-size: 11px; letter-spacing: .06em; }
table.versus thead th.mine { color: var(--accent-text); }
table.versus tbody tr:hover { background: transparent; }
table.versus tbody tr:hover .mine { background: var(--wash); }
.tick, .cross { font-size: 14px; font-weight: 700; line-height: 1; }
.tick { color: var(--accent-text); }
.cross { color: var(--muted); opacity: .55; }

/* --------------------------------------------------------------------- the questions
   ONE CARD, OPEN OR SHUT (owner, 24 September 2026)
   ---------------------------------------------------
   "Make these lines more defined, neat, and have some shade." He was on /how-it-works on
   his phone: four white slabs with a hairline round them, each one 86px tall to hold a
   single 22px line, the question pressed flat against the left edge, and a stray capital
   L where the chevron belongs.

   All of it was one fault. These questions are written once and printed in two places —
   /about puts them in `.asks`, the rebuilt /how-it-works puts the same `details.ask` in a
   `.faq-list` — and `.faq-list > details` had been given a second, flat-row treatment of
   its own for the destination pages. The two sets of rules score the same specificity, so
   the browser was taking half of each: `padding: 17px 0` from one (hence 86px tall and no
   inset left the question anywhere to sit) and `border-radius: 12px` from the other.

   The L was the same accident in the marker. This block drew its chevron out of two
   borders on a box turned with `rotate: 45deg`; the faq-list drew its own out of the
   site's `--chev-down` mask and turned it with `transform`. `rotate` and `transform` are
   different properties, so neither overwrote the other — the mask chevron was painted and
   then rotated 45 degrees, and a chevron on its corner is a letter L. Open, the two
   turns cancelled to the same 45 degrees, which is why all four wore one.

   So the questions are a single component now, with one chevron — the site's own
   `--chev-down`, the mark `.text-link` and the destination folds already use — sitting in
   the summary as a flex item rather than pinned by absolute coordinates, so it moves to
   the left of the card by itself in Arabic. It is the page's `--gutter` in from the edge
   on both sides, which is the same distance every other control on a phone now stands
   from the screen, and the answer shares that inset with its question. It takes the
   card radius and the resting shadow the facts and the columns take, and opening one
   lifts the shadow rather than changing its shape: nothing moves but the chevron.
   The flat-row treatment stays where it was earned, on the destination FAQs, and now says
   `:not(.ask)` so it cannot reach in here again. asksMarker.test.ts holds the line. */
.asks { display: grid; gap: 10px; }
details.ask {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-1);
  padding: 0 var(--gutter);
  transition: border-color .15s ease, box-shadow .15s ease;
}
details.ask:hover { border-color: color-mix(in srgb, var(--accent) 30%, var(--line)); }
details.ask[open] {
  border-color: color-mix(in srgb, var(--accent) 42%, var(--line));
  box-shadow: var(--shadow-2);
}
details.ask > summary {
  list-style: none; cursor: pointer;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 14px 0;
  font-weight: 600; font-size: 15px; line-height: 1.45; color: var(--ink);
}
details.ask > summary::-webkit-details-marker { display: none; }
details.ask > summary:hover { color: var(--accent-text); }
/* The mark, not a letter: the site's chevron, masked so it takes its colour from here. */
details.ask > summary::after {
  content: ""; flex: none; width: 17px; height: 17px;
  background: var(--muted);
  -webkit-mask: var(--chev-down) center / contain no-repeat;
  mask: var(--chev-down) center / contain no-repeat;
  transition: transform .18s ease, background-color .15s ease;
}
details.ask[open] > summary::after { transform: rotate(180deg); background: var(--accent-text); }
details.ask > p {
  margin: 0; padding: 0 0 16px; max-width: 74ch;
  color: var(--muted); font-size: 14.5px; line-height: 1.65;
}
/* `.asks` is a grid and spaces them itself; in a `.faq-list` the cards sit beside rows
   that are not cards, so the space belongs to the card. */
.faq-list > details.ask + details.ask { margin-top: 10px; }

/* The four new sections keep one rhythm between them. */
#ways, #why, #compare, #questions { margin-top: 46px; }

.cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 14px; }
.cols.three { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.cols.two { grid-template-columns: repeat(auto-fit, minmax(290px, 1fr)); gap: 16px 22px; }
.cols .col h3 { margin: 0 0 6px; font-size: 16.5px; font-weight: 700; letter-spacing: -.01em; }
.cols .col p { margin: 0; color: var(--muted); font-size: 14.5px; line-height: 1.6; }

/* A form that belongs to the page it is on
   ----------------------------------------
   The support form carried its colours inline — a grey hairline that stayed grey on a dark
   page and a red button from no part of this brand. Tokens now, like everything else. */
.ask-form { display: grid; gap: 14px; max-width: 560px; }
.ask-form label { display: grid; gap: 6px; font-weight: 600; font-size: 14.5px; }
.ask-form input, .ask-form select, .ask-form textarea {
  width: 100%; padding: 11px 13px; border-radius: 12px; font: inherit; font-weight: 500;
  color: var(--ink); background: var(--card); border: 1px solid var(--line);
}
.ask-form textarea { resize: vertical; min-height: 120px; }
.ask-form input:focus, .ask-form select:focus, .ask-form textarea:focus {
  outline: 2px solid var(--accent-text); outline-offset: 1px; border-color: transparent;
}
.ask-form small { color: var(--muted); font-weight: 400; }
.ask-form .cta { justify-self: start; }

/* The foot of every page
   ----------------------
   It was one long line of fifteen links, which is a list nobody reads and a shape that
   says the site ended by accident. Four columns with names over them, the wordmark under
   them at a size you can actually see, and the legal line last (owner, 23 Sep 2026). */
footer.sitefoot { display: block; margin-top: 56px; padding: 34px 0 10px; border-top: 1px solid var(--line); }
.footcols { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 26px 20px; }
.footcol h3 { margin: 0 0 10px; font-size: 13px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.footcol a { display: block; padding: 5px 0; color: var(--ink); text-decoration: none; font-size: 14.5px; }
.footcol a:hover { text-decoration: underline; }
.footmark { margin: 34px 0 18px; }
.footmark .wordmark {
  display: block; height: 60px; width: auto; aspect-ratio: 574 / 264; background: var(--ink); opacity: .9;
  -webkit-mask: url(/app/brand-wordmark.png) left center / contain no-repeat;
  mask: url(/app/brand-wordmark.png) left center / contain no-repeat;
}
.footline { display: flex; flex-wrap: wrap; gap: 6px 16px; align-items: center; color: var(--muted); font-size: 13px; padding-bottom: 20px; }
.footline a { color: var(--muted); }
@media (max-width: 620px) {
  footer.sitefoot { margin-top: 40px; padding-top: 26px; }
  /* "I think these can be two columns" (owner, 24 September 2026)
     ----------------------------------------------------------
     He was looking at the foot of the page on his iPhone: the four group names running
     down the left in one column with the entire right half of the screen empty. Measured,
     the rule above was doing this: `auto-fit` with a 170px minimum, which at 390 has
     358px to spend and needs 356 for two tracks. Two pixels. It fitted in Chromium and
     it does not fit at 375 or at 360, and it is not a layout — it is an accident that
     happened to come out right on one width. So the phone says two columns and means it,
     with `minmax(0, 1fr)` so a long Russian label widens nothing and a track can never
     push the page sideways.

     Four groups into two columns, in the order they are written, is also the pairing he
     circled: Our eSIMs beside About eSIMs, Get help beside Legal. That is not a
     coincidence of reading order, it is the best balance available — the groups are 3, 3,
     4 and 8 links deep, and of every way of dealing two columns without breaking a group
     open this one leaves the shortest tall column (281px against 408px here). The only
     partition that comes out lower puts three groups on the left and Legal alone on the
     right, two pixels better and much worse to look at, which is what CSS columns would
     have chosen on its own. So: a grid, not `columns`.

     What is left over is Legal being eight links against Get help's four, and `start`
     is where it goes — the shorter column simply ends earlier, so the leftover air
     collects at the bottom left, right above the wordmark, and reads as space before the
     sign-off instead of a hole inside a list. Nothing is stretched to meet a row.

     The column gap is the page's own `--gutter`, so the space between the two halves is
     the space between the words and the edge of the screen. */
  .footcols { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px var(--gutter); align-items: start; }
  /* A label longer than half a phone is broken rather than allowed to overrun the track:
     the Russian and Polish document titles are the long ones. */
  .footcol a { overflow-wrap: break-word; }
  .footmark .wordmark { height: 46px; }
}

/* THE BIG FOOTER MARK, TRIED AND TAKEN BACK OUT (owner, 24 Sep 2026: "make the logo at
   the bottom of each page small again")
   ----------------------------------------------------------------------------------------
   It was here, width-driven and capped at 880px, which gave 405px on a laptop and filled
   the column on a phone — Airalo's treatment, where the name at the foot of the page is a
   graphic rather than a logo. He has now seen it on every page and wants a logo back, and
   he is the one looking at it.

   So there is no override: the foot of every page, shop and site alike, is the `.footmark`
   size above — 60px, dropping to 46px below 620. No middle size was invented, because the
   scale has no gap to fill: the header mark is 54px at this width, so 60px already reads
   as the sign-off rather than as a repeat of the header. The margins went with it; they
   were sized for a 405px mark and 52px of air over a 60px logo reads as an accident. */

/* A band: one idea, room around it
   --------------------------------
   The destination pages had every section touching the one above it, which is what makes
   a page read as a wall rather than a sequence (owner, 23 Sep 2026). A band is a heading,
   one line under it, and the thing itself — with air at the top and nothing competing. */
.band { margin-top: 42px; }
.band > h2 { margin: 0 0 6px; font-size: clamp(21px, 2.4vw, 27px); letter-spacing: -.02em; }
.band > .lede { margin: 0 0 16px; color: var(--muted); font-size: 15px; max-width: 62ch; }
.band > .cols { margin-top: 18px; }
.band .rows { border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; background: var(--card); }
@media (max-width: 620px) { .band { margin-top: 32px; } }

/* The three commissioned illustrations on /how-it-works.

   They sit ON the page rather than in a box. Each one already carries its own background
   — two of the three are within a shade of the page's own paper — so a border would draw
   a frame around a picture that is trying to breathe, and a shadow would lift a drawing
   off the page as though it were a card you could press. Neither belongs here: the card
   chrome on this site marks the things a reader can act on, and art is not one of them.

   The corners are rounded to the same radius as every other block, because "your first
   day" is a dark green rectangle edge to edge, and a hard corner against warm paper reads
   as a pasted screenshot instead of a drawing.

   Nothing here fights the `width` and `height` attributes that reserve the space before
   the file lands: the height stays automatic, so the 16:9 the artist drew is the 16:9 on
   the page at every width, uncropped and unstretched. */
.band-art {
  display: block; width: 100%; height: auto; max-width: 100%;
  margin: clamp(22px, 2.6vw, 34px) 0;
  border-radius: var(--radius);
}

/* The trail at the top of a destination page: where you are, and the way back up. */
.trail { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-start; gap: 8px; margin: 2px 0 14px; font-size: 13.5px; color: var(--muted); }
.trail a { color: var(--muted); text-decoration: none; }
.trail a:hover { color: var(--ink); text-decoration: underline; }
.trail span[aria-hidden] { opacity: .6; }
.trail [aria-current] { color: var(--ink); font-weight: 600; }
.col { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 20px 22px; box-shadow: var(--shadow-1); }
.col h3 { margin: 0 0 6px; font-size: 16.5px; }
.col p { margin: 0; font-size: 15px; color: var(--muted); }

/* Numbered steps as cards, not a bulleted list. */
ol.steps { list-style: none; counter-reset: step; margin: 0; padding: 0; display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); }
ol.steps li {
  counter-increment: step; position: relative;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 46px 20px 20px; color: var(--muted); font-size: 15px; box-shadow: var(--shadow-1);
}
ol.steps li::before {
  content: counter(step); position: absolute; top: 18px; left: 20px;
  width: 26px; height: 26px; border-radius: 9px; display: grid; place-items: center;
  background: var(--wash); color: var(--accent-text); font-weight: 700; font-size: 14px;
}

article {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  padding: clamp(20px, 3vw, 32px); white-space: pre-wrap; box-shadow: var(--shadow-1);
  max-width: 78ch;
}

/* A tariff table that stays readable on a phone. */
.tablewrap { overflow-x: auto; border-radius: var(--radius); box-shadow: var(--shadow-1); }
table { width: 100%; border-collapse: collapse; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
th, td { text-align: left; padding: 13px 16px; border-top: 1px solid var(--line); font-size: 15px; }
th { border-top: 0; color: var(--muted); font-weight: 600; font-size: 12.5px; letter-spacing: .04em; text-transform: uppercase; }
td:last-child, th:last-child { text-align: right; white-space: nowrap; }
td:last-child { font-weight: 650; }
tbody tr:hover { background: color-mix(in srgb, var(--accent) 5%, transparent); }

/* The destination filter on /plans. */
.filter { display: flex; align-items: center; gap: 10px; background: var(--card); border: 1px solid var(--line); border-radius: 999px; padding: 12px 20px; box-shadow: var(--shadow-1); max-width: 460px; }
.filter input { flex: 1; border: 0; background: none; font: inherit; font-size: 16px; color: inherit; outline: none; }

/* --- blocks (the shop inside the browser) ------------------------------------------- */

/* Room to breathe between the shop's blocks: 16 points put a banner, a shelf and a rail
   close enough to read as one slab of stuff (owner, 23 Sep 2026: "make it breathable"). */
.block { margin: 22px 0; }
.block > h2.b { margin-bottom: 12px; }
.block:first-child { margin-top: 20px; }

h1.b { font-size: clamp(26px, 3.4vw, 34px); line-height: 1.15; margin: 0 0 6px; letter-spacing: -.025em; }
h2.b { font-size: 20px; line-height: 1.25; margin: 0 0 6px; letter-spacing: -.015em; }
p.b { margin: 0; }

.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 18px;
  box-shadow: var(--shadow-2);
}
.card.flat { box-shadow: none; }
.card > h2.b { margin-bottom: 10px; }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 13px 20px; border-radius: 999px;
  border: 1px solid transparent; cursor: pointer;
  font: inherit; font-weight: 650; text-decoration: none;
  background: var(--accent); color: var(--on-accent);
  box-shadow: 0 8px 20px color-mix(in srgb, var(--accent) 28%, transparent);
  transition: transform .12s ease;
}
.btn:hover { transform: translateY(-1px); }
.btn.wide { width: 100%; }
/* Two fields and a button, stacked — the shape of every "type this in" card on the site. */
.stack { display: grid; gap: 10px; }
.stack input { font: inherit; padding: 12px 14px; border-radius: 12px; border: 1px solid var(--line); background: var(--bg); color: var(--ink); }
.stack input:focus { outline: 2px solid color-mix(in srgb, var(--accent-text) 55%, transparent); outline-offset: 1px; }
.cta.wide { width: 100%; justify-content: center; }
/* An order number is read aloud and typed back in. Proportional digits make that harder. */
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; letter-spacing: .02em; }
.btn.quiet { background: var(--card); color: var(--ink); border-color: var(--line); box-shadow: var(--shadow-1); }
.btn.ghost { background: none; color: var(--accent-text); padding: 8px 0; box-shadow: none; }
.btn:disabled { opacity: .5; cursor: default; transform: none; }

.notice { border-radius: var(--radius); padding: 13px 16px; background: var(--wash); }
.notice.warn { background: color-mix(in srgb, #e08a1e 18%, transparent); }
.notice.bad, .notice.danger { background: color-mix(in srgb, #d24b4b 16%, transparent); }

.banner {
  border-radius: var(--radius); padding: 20px;
  background: linear-gradient(135deg, var(--accent), color-mix(in srgb, var(--secondary) 60%, #101828 40%));
  color: var(--on-accent);
  box-shadow: var(--shadow-2);
}
.banner h2 { margin: 0 0 4px; font-size: clamp(19px, 2vw, 23px); color: inherit; }
a.banner { color: var(--on-accent); text-decoration: none; display: block; }
a.banner:hover { transform: translateY(-1px); }
.banner p { margin: 0; opacity: .92; }
/* A BANNER WITH A PHOTOGRAPH IS A WHITE CARD WITH THE PHOTOGRAPH ON TOP (owner, 24 Sep 2026)
   =========================================================================================
   "I want the ENTIRE home page to be light … consistent, the entire style." These were the
   last dark shapes on the page: the photograph as the card's background, two washes over it
   and ivory words on top. The picture is a picture now — in its own frame at the top of the
   card, 16:10, cropped never stretched — and the words stand under it in the page's ink on
   white, the shape the help centre's topic tiles and the destination tiles already take.
   No wash, no text-shadow: nothing is written over the photograph any more. */
.banner.pictured {
  padding: 0; overflow: hidden; display: flex; flex-direction: column;
  background: var(--card); color: var(--ink);
  border: 1px solid var(--line); box-shadow: var(--shadow-1);
  text-shadow: none; min-height: 0;
  transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease;
}
.banner.pictured:hover { transform: translateY(-3px); box-shadow: var(--shadow-2); border-color: color-mix(in srgb, var(--forest) 28%, var(--line)); }
.banner-art { aspect-ratio: 16 / 10; background: var(--panel-sage) center / cover no-repeat; flex: none; }
.banner-words { padding: 16px 18px 18px; display: flex; flex-direction: column; gap: 6px; }
.banner.pictured h2 { margin: 0; font-size: 17px; line-height: 1.25; letter-spacing: -.02em; color: var(--ink); }
.banner.pictured p { margin: 0; opacity: 1; color: var(--muted); font-size: 13.5px; line-height: 1.5; }

/* THE PLAIN BANNERS ARE LIGHT TOO (owner, 24 Sep 2026)
   ====================================================
   "I want the ENTIRE home page to be light. As all other pages, like countries in Pro
   Store, light and beautiful ... it has to be consistent, the entire style."

   With the banner above them turned light, four cards under it were the only dark shapes
   left on the page that are not photographs: the three steps and the question card, solid
   forest-to-near-black rectangles with ivory on them. They are the white card the rest of
   this site is made of now — the same paper, the same soft shade, a forest heading and the
   muted body. Nothing new is invented and nothing is added.

   A banner WITH a picture keeps every rule it has. The picture is the point of it, the two
   washes over it are what make the words readable on it, and the destination pages lead
   with a picture as well — so the photographs are already the family, and stripping them
   would be the change he did not ask for.

   `:not(.pictured)` reaches ONLY the home screen. Measured on /plans, /usa-esim,
   /how-it-works and the unlimited store: not one of them draws a `.banner` at all, so the
   Pro Store and the unlimited store are untouched, exactly as he said to leave them. */
.banner:not(.pictured) {
  background: var(--card);
  color: var(--ink);
  box-shadow: var(--shadow-1);
  border: 1px solid color-mix(in srgb, var(--line) 70%, transparent);
}
.banner:not(.pictured) h2 { color: var(--forest); }
.banner:not(.pictured) p { color: var(--muted); opacity: 1; }
a.banner:not(.pictured) { color: var(--ink); }
a.banner:not(.pictured):hover { border-color: color-mix(in srgb, var(--forest) 28%, transparent); }

.dest-hero {
  border-radius: calc(var(--radius) + 4px); overflow: hidden; position: relative;
  min-height: 200px; display: flex; align-items: flex-end;
  padding: 22px; color: #fff;
  background: linear-gradient(135deg, var(--accent), var(--secondary));
  box-shadow: var(--shadow-2);
}
/* Two washes, not one. The diagonal is what gives the picture its depth; the vertical
   one under it is what makes the words legible, because a photograph is bright exactly
   where it wants to be and the sentence under the place name kept landing on a pale sky.
   The wash is tied to the bottom of the card rather than to the text, so it holds however
   long the sentence runs. */
.dest-hero::after {
  content: ""; position: absolute; inset: 0;
  background:
    linear-gradient(to top, rgba(0,0,0,.62) 0, rgba(0,0,0,.42) 38%, rgba(0,0,0,0) 72%),
    linear-gradient(158deg, rgba(255,255,255,.14), rgba(255,255,255,0) 45%, rgba(0,0,0,.28));
}
.dest-hero .words { position: relative; z-index: 1; text-shadow: 0 1px 3px rgba(0,0,0,.45); }
.dest-hero .flag { font-size: 40px; line-height: 1; display: block; margin-bottom: 8px; filter: drop-shadow(0 2px 6px rgba(0,0,0,.35)); }
.dest-hero h1 { margin: 0; font-size: clamp(26px, 4vw, 38px); }
.dest-hero p { margin: 6px 0 0; opacity: .95; max-width: 60ch; line-height: 1.45; }

.grid { display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); }
.tile {
  position: relative; overflow: hidden; isolation: isolate;
  border: 0; border-radius: var(--radius);
  padding: 16px; cursor: pointer; text-align: left; font: inherit; color: #fff;
  display: flex; flex-direction: column; justify-content: flex-end; gap: 3px; min-height: 118px;
  background: linear-gradient(135deg, var(--accent), var(--secondary));
  box-shadow: var(--shadow-2);
  transition: transform .14s ease, box-shadow .14s ease;
}
.tile::after { content: ""; position: absolute; inset: 0; z-index: -1; background: linear-gradient(158deg, rgba(255,255,255,.16), rgba(255,255,255,0) 46%, rgba(0,0,0,.34)); }
.tile:hover { transform: translateY(-3px); box-shadow: var(--shadow-3); }
.tile .flag { position: absolute; top: 13px; left: 15px; font-size: 28px; line-height: 1; filter: drop-shadow(0 2px 5px rgba(0,0,0,.3)); }
.tile .name { font-weight: 660; font-size: 16px; text-shadow: 0 1px 6px rgba(0,0,0,.3); }
.tile .from { font-size: 13px; opacity: .92; text-shadow: 0 1px 6px rgba(0,0,0,.3); }

.rail { display: flex; gap: 12px; overflow-x: auto; padding: 2px 2px 10px; scroll-snap-type: x mandatory; scrollbar-width: thin; }
.rail > * { flex: 0 0 auto; scroll-snap-align: start; }

.rows { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-2); }
/* The length a group of lines belongs to, as a heading inside the card rather than a
   bold word floating above it. */
.rows .grouphead {
  display: flex; align-items: baseline; gap: 10px; margin: 0;
  padding: 12px 16px 10px; border-top: 1px solid var(--line);
  background: color-mix(in srgb, var(--ink) 3%, transparent);
  font-size: 13px; font-weight: 750; letter-spacing: .04em; text-transform: uppercase; color: var(--muted);
}
.rows .grouphead:first-child { border-top: 0; }
.rows .grouphead .note { text-transform: none; letter-spacing: 0; font-weight: 600; font-size: 12.5px; }
/* One line of the shelf.
   Every line is the same height whatever it carries: a price with a "from" in front of it
   used to stack two lines and make its row taller than its neighbours, so a column of
   them came out ragged. The price sits in a column of its own, right-aligned, so the
   amounts line up down the page instead of drifting with the length of the word beside
   them. */
.row {
  display: flex; align-items: center; gap: 12px; min-height: 56px;
  padding: 12px var(--gutter); width: 100%; background: none; border: 0;
  border-top: 1px solid var(--line); font: inherit; color: inherit; text-align: left; cursor: pointer;
  transition: background .14s ease, box-shadow .14s ease;
}
.row:first-child { border-top: 0; }
.row:hover:not(.static) { background: color-mix(in srgb, var(--accent) 6%, transparent); }
.row:active:not(.static) { background: color-mix(in srgb, var(--accent) 10%, transparent); }
.row:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
/* The price column: one line, right-aligned, wide enough that the longest amount on the
   page does not push the shorter ones out of line. */
.row .amount { margin-left: auto; display: flex; align-items: baseline; gap: 6px; white-space: nowrap; }
.row .amount .fromword { color: var(--muted); font-size: 12.5px; font-weight: 600; }
.row .amount .price { font-variant-numeric: tabular-nums; }
.row .grow { flex: 1 1 auto; min-width: 0; }
.row .title { font-weight: 620; }
/* The value on the right of a row never wraps; the one UNDER a title (how much runs at
   full speed, say) must, or it runs across the price beside it. */
.row .value { color: var(--muted); font-size: 14px; white-space: nowrap; }
.row .grow .value { white-space: normal; }
/* A plan's facts (Data, Valid for, Works in): the value on the right can be a whole sentence
   ("Unlimited · 1 GB/day at full speed, then 1 Mbps"). On a phone it wraps under itself,
   right-aligned, and the label keeps its width (29 Sep 2026: at 390px the label was squeezed
   to nothing and the two ran together as "DataUnlimited · 1 GB/day…"). */
.rows.plan-facts .row .grow { flex: 0 0 auto; min-width: min-content; }
.rows.plan-facts .row .value { white-space: normal; min-width: 0; flex: 1 1 auto; text-align: right; text-wrap: balance; }
.row .grow { padding-right: 10px; }
.row .chev { color: var(--muted); }
.row.static { cursor: default; }
a.row { text-decoration: none; color: inherit; }
/* The shelf on a destination page is a form of buttons, because a plan is chosen and no
   longer has a page of its own to link to. The form is a wrapper and not a box: `contents`
   takes it out of the layout so the card's border, its rounded corners and the first row's
   missing top border are the same as when the rows were anchors. */
.rows > form { display: contents; }
.row .title { display: block; }

/* A length that is sold in two sizes opens out of its own line. */
details.shelf > summary { list-style: none; }
details.shelf > summary::-webkit-details-marker { display: none; }
details.shelf > summary .chev { transition: transform .15s ease; }
details.shelf[open] > summary .chev { transform: rotate(180deg); }
.rows > details:first-child > summary.row { border-top: 0; }

/* The plan picker
   ================
   The same shape as the app's: choose a length, then a daily amount, then what happens
   after it. Everything else — whether days can be added, which IP variant — is a switch
   beside the total, because a customer wants the same answer to both whatever row they
   land on. As a flat list this was a hundred near-identical lines. */
.chips { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 14px; }
.chips button {
  padding: 9px var(--gutter); border-radius: 999px; border: 1px solid var(--line); background: var(--card);
  font: inherit; font-weight: 620; font-size: 14px; color: var(--ink); cursor: pointer; box-shadow: var(--shadow-1);
}
.chips button:hover:not(.on):not(:disabled) { border-color: color-mix(in srgb, var(--accent) 45%, var(--line)); }
.chips button.on { background: var(--accent); border-color: var(--accent); color: var(--on-accent); box-shadow: 0 4px 12px color-mix(in srgb, var(--accent) 35%, transparent); }
.chips button:disabled { cursor: default; }
.chips.small button { padding: 6px 13px; font-size: 13px; font-weight: 600; }

/* The line you chose. A wash alone was too quiet to find again after scrolling, so it
   also carries the accent down its left edge. */
.row.picked {
  background: color-mix(in srgb, var(--accent) 9%, transparent);
  box-shadow: inset 3px 0 0 var(--accent);
}
.row.picked .title { font-weight: 700; }
.row .mark { width: 22px; height: 22px; border-radius: 50%; border: 2px solid color-mix(in srgb, var(--ink) 22%, transparent); display: inline-grid; place-items: center; flex: 0 0 auto; }
.row.picked .mark { border-color: var(--accent-text); }
.row.picked .mark::after { content: ''; width: 11px; height: 11px; border-radius: 50%; background: var(--accent); }
/* The panel that opens under a chosen line, and the one in the buy bar.
   It used to be a full-bleed grey slab with square corners sitting inside a rounded card,
   which is the one shape in the shop that looked unfinished. It is now inset and rounded
   like everything else, with a hairline instead of an edge. */
.rowchoice {
  padding: 12px 14px; margin: 0 10px 10px; border-radius: 14px;
  background: var(--wash); border: 1px solid color-mix(in srgb, var(--line) 70%, transparent);
}
.rowchoice + .rowchoice { margin-top: -4px; }
/* Air between a chosen line and the panel it opened (owner, 22 Sep 2026). They shared an
   edge, so the question that appeared looked like part of the row above it rather than an
   answer to it. */
.rows .row + .rowchoice { margin-top: 8px; }
.buybar .rowchoice { margin: 0 0 12px; }
.rowchoice .label { color: var(--muted); font-size: 13px; margin: 0 0 8px; }
.rowchoice .chips { margin: 0; align-items: center; }
/* "IP:" sits on the line with the country it names, not on a line of its own. */
.rowchoice .chips .label { margin: 0; }
.rowchoice .label.net { margin: 8px 0 0; }
/* A mark the size of a full stop, sitting in the label. Somebody who knows what 512 kbps
   is should see nothing at all; somebody who does not gets one sentence when they tap. */
.infopoint {
  border: 0; background: none; padding: 0; cursor: pointer; vertical-align: baseline;
  font: inherit; font-size: 13px; line-height: 1; color: var(--accent-text);
}
.infopoint:hover { opacity: .75; }
.speeduse { margin: 0 0 10px; font-size: 12.5px; line-height: 1.5; color: var(--muted); max-width: 62ch; }

.buybar {
  position: sticky; bottom: 12px; z-index: 5; margin-top: 18px; padding: 14px var(--gutter);
  background: color-mix(in srgb, var(--card) 92%, transparent); backdrop-filter: blur(14px);
  border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow-2);
}
.buybar .switches { display: flex; flex-wrap: wrap; gap: 10px 22px; margin-bottom: 12px; }
.buybar .total { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.buybar .total .amount { font-size: 26px; font-weight: 760; letter-spacing: -.03em; }
.buybar .total .what { color: var(--muted); font-size: 13.5px; }
.buybar .cta { margin-left: auto; }

/* THE CHOICE STAYS ON THE SCREEN (owner, 24 Sep 2026) -----------------------------------
   "When you push any line, like 500 megabytes a day… that field with extra countries, with
   IP… can you make it so it's actually appears at the bottom of the screen? No matter where
   you scroll it. Like in app, visible at every spot."

   `position: sticky` only holds while the picker's own box is on screen, and the picker is
   one section of a long page: with a line open the bar was measured sitting at y=2870 on a
   page 8461 tall, so it was never seen unless somebody happened to scroll past it, and it
   left again immediately. The phone does not do that. CountryView hangs the same panel off
   `.safeAreaInset(edge: .bottom)`, which pins it to the bottom of the screen for as long as
   the list is open AND insets the scrolling content by its height so the last row of the
   page is never underneath it. These three rules are that inset, in CSS.

   Only ever with a plan chosen. The empty bar ("Pick how much data a day.") is a line of
   help rather than a control, and a bar pinned over a page somebody is reading is furniture
   the phone does not have either — its bottom bar belongs to the plans screen and nowhere
   else. A tap outside puts the choice down and the bar goes back into the page, which is
   `putDownTheChoice()` in CountryView.swift and `putDown` in app.js.

   `--dock-left` and `--dock-width` are written by app.js from the space the bar itself left
   behind, which is the only honest source for them: the picker sits in a different container
   on the shop's own screens than it does inside the fold of a destination page, and a column
   width guessed at here would be wrong on one of the two. */
.buybar.afloat {
  position: fixed; z-index: 20;
  left: var(--dock-left, 0px); width: var(--dock-width, 100%);
  /* The home indicator, which is what the phone's bottom inset is mostly made of. */
  bottom: calc(12px + env(safe-area-inset-bottom));
  /* Never the whole window: the shop it is a choice in has to stay readable behind it. */
  max-height: 72vh; overflow-y: auto; overscroll-behavior: contain;
}
/* The space the bar came out of, kept to the pixel, so nothing under the picker jumps up
   the moment a line is pressed. app.js sets the height, measured from the bar. */
.buydock { display: block; }
/* …and room at the foot of the page, so a pinned bar can never cover the last row of it.
   Only while there is one: every other page on the site is untouched by this. */
body:has(.buybar.afloat) {
  padding-bottom: calc(env(safe-area-inset-bottom) + var(--buybar-h, 240px) + 20px);
}

.sw { display: inline-flex; align-items: center; gap: 9px; font-size: 13.5px; color: var(--ink); cursor: pointer; position: relative; }
.sw input { position: absolute; opacity: 0; width: 42px; height: 25px; margin: 0; cursor: pointer; }
.sw .track { width: 42px; height: 25px; border-radius: 999px; background: color-mix(in srgb, var(--ink) 18%, transparent); position: relative; transition: background .15s ease; flex: 0 0 auto; }
.sw .track::after { content: ''; position: absolute; top: 3px; left: 3px; width: 19px; height: 19px; border-radius: 50%; background: #fff; box-shadow: var(--shadow-1); transition: transform .15s ease; }
.sw input:checked + .track { background: var(--accent); }
.sw input:checked + .track::after { transform: translateX(17px); }
.sw input:focus-visible + .track { outline: 2px solid var(--accent); outline-offset: 2px; }
/* A switch with only one answer for this destination is still drawn — it is how the plan
   is read — but it cannot be moved. */
.sw.fixed { opacity: .55; cursor: default; color: var(--muted); }
.sw.fixed input { cursor: default; }

/* The buy sheet on a phone -------------------------------------------------------------
   At 390 points it stood 446 pixels tall on a 760-pixel screen: three lines of coverage
   chips, two switches with desktop-sized toggles, and a total whose button wrapped onto a
   line of its own. The sheet is what somebody is buying, and it was covering the thing
   they were buying.

   Half the height, the same controls and the same words. Nothing is dropped, nothing goes
   below a tappable size: the panels tighten, the coverage chips scroll sideways the way
   the row of lengths above them already does, and Total, the price and Buy now share one
   line with the plan named small underneath. */
@media (max-width: 620px) {
  .buybar { bottom: 8px; padding: 9px var(--gutter); }
  /* Flush with the bottom edge and the whole width of the phone, which is what the app's
     bar is: at 390 the floating card left the coverage chips 356px to scroll inside and
     this leaves them 368, and the corners stay rounded where they are still seen. */
  .buybar.afloat {
    left: 0; width: 100%; bottom: 0; max-height: 80vh;
    border-radius: 18px 18px 0 0; border-left: 0; border-right: 0; border-bottom: 0;
    padding-bottom: calc(9px + env(safe-area-inset-bottom));
  }
  .buybar .switches { gap: 6px 14px; margin-bottom: 8px; }
  .buybar .rowchoice {
    display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px;
    padding: 6px 10px; margin: 0 0 5px;
  }
  /* The switches now sit in a panel of their own, so the margin they carried is the
     panel's job and would otherwise be counted twice. */
  .buybar .rowchoice > .switches { margin-bottom: 0; }
  .buybar .rowchoice > .label { font-size: 12px; margin: 0; }
  .buybar .rowchoice > .switches { margin-bottom: 0; }
  /* Sideways rather than down, and faded at the edge so it is clear there is more. */
  .buybar .rowchoice .chips {
    flex: 1 1 180px; min-width: 0; gap: 6px;
    flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none;
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 18px), transparent);
    mask-image: linear-gradient(to right, #000 calc(100% - 18px), transparent);
  }
  .buybar .rowchoice .chips::-webkit-scrollbar { display: none; }
  .buybar .rowchoice .chips > * { flex: 0 0 auto; }
  .buybar .chips.small button { padding: 5px 11px; font-size: 12.5px; }
  .buybar .sw { font-size: 12.5px; gap: 7px; }
  .buybar .sw input, .buybar .sw .track { width: 36px; height: 21px; }
  .buybar .sw .track::after { top: 3px; left: 3px; width: 15px; height: 15px; }
  .buybar .sw input:checked + .track::after { transform: translateX(15px); }
  .buybar .total { gap: 5px 10px; margin-top: 1px; }
  .buybar .total .totalword { font-size: 15px; }
  .buybar .total .amount { font-size: 22px; }
  /* The plan's name under the money instead of beside it, so the button keeps the line. */
  .buybar .total .what { order: 3; flex: 1 0 100%; font-size: 12px; margin: 0; }
  .buybar .cta { order: 2; padding: 10px 16px; font-size: 14px; }
}

/* "Best deal" ---------------------------------------------------------------------------
   Earned, not written down: the page works out which bundles on a shelf are the fastest
   after the daily amount and the cheapest week among those (bestWeek in site.ts), and
   only those wear it. Quiet — the accent at a tenth strength, small caps-weight type
   beside the name — because a shelf where one row shouts reads as an advertisement
   rather than a shop. The dot under the shelf says, in one sentence, what it means. */
.row .deal {
  /* A clear step away from the name rather than crowding it (owner, 22 Sep 2026). */
  display: inline-flex; align-items: center; margin-left: 14px; padding: 2px 8px; border-radius: 999px;
  background: color-mix(in srgb, var(--accent) 13%, transparent);
  color: var(--accent-text); font-size: 11.5px; font-weight: 760; letter-spacing: .01em;
  white-space: nowrap; vertical-align: 1px;
}
/* The dot that explains the badge, on the badge. Its own tap target, its own hover, and
   it never looks like part of the words it follows. */
.row .deal .dealtip {
  display: inline-flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; margin-left: 5px; margin-right: -2px;
  border-radius: 50%; font-size: 12px; font-weight: 600; line-height: 1;
  color: var(--accent-text); opacity: .72; cursor: pointer; vertical-align: -1px;
}
.row .deal .dealtip:hover, .row .deal .dealtip:focus-visible { opacity: 1; }
.row .deal .dealtip:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* The cloud the dot opens: over the page, never in it.

   The explanation used to be a paragraph under the shelf, which on a phone put the answer
   somewhere below the fold and pushed every row down when it appeared. This floats where
   it was asked for, closes on a tap anywhere outside, and moves nothing (owner, 22 Sep). */
.dealcloud {
  position: fixed; z-index: 70; padding: 11px 13px; border-radius: 14px;
  background: var(--card); color: var(--ink); border: 1px solid var(--line);
  box-shadow: 0 14px 38px color-mix(in srgb, #000 22%, transparent);
  font-size: 12.5px; line-height: 1.5;
}
/* On a phone the name and the badge share about 180 points, so the badge is cut to what
   it needs and not a pixel more — it stays beside the name, which is where he asked for
   it twice. */
@media (max-width: 620px) {
  .row .deal { margin-left: 8px; font-size: 10px; padding: 2px 6px; letter-spacing: 0; }
  .row .deal .dealtip { width: 13px; height: 13px; margin-left: 3px; font-size: 10.5px; }
}

.photo-credit { margin: 8px 0 0; color: var(--muted); }
.photo-credit a { color: var(--muted); }
table.credits { border-collapse: collapse; width: 100%; font-size: 14px; }
table.credits th, table.credits td { text-align: left; padding: 9px 12px; border-bottom: 1px solid var(--line); vertical-align: top; }
table.credits th { color: var(--muted); font-weight: 620; white-space: nowrap; }
table.credits td:first-child { white-space: nowrap; font-weight: 600; }

.search { display: flex; align-items: center; gap: 8px; background: var(--card); border: 1px solid var(--line); border-radius: 999px; padding: 12px 18px; box-shadow: var(--shadow-2); }
.search input { flex: 1; border: 0; background: none; font: inherit; color: inherit; outline: none; }

.seg { display: inline-flex; gap: 4px; padding: 4px; border-radius: 999px; background: color-mix(in srgb, var(--ink) 6%, transparent); }
.seg button { flex: 1; padding: 10px 18px; border-radius: 999px; border: 0; background: none; font: inherit; font-weight: 620; font-size: 14.5px; color: var(--muted); cursor: pointer; white-space: nowrap; }
/* Three tabs whose words never wrap, in a pill that is as wide as they are: at 320 points
   "Mga bansa · Mga rehiyon · Global" ran seven pixels past the screen and the whole page
   scrolled sideways. The pill fills the width it has and the words inside it give way
   first, which is what it should have done at every width. */
@media (max-width: 620px) {
  .seg { display: flex; max-width: 100%; }
  .seg button { min-width: 0; padding: 9px 10px; font-size: 13.5px; overflow: hidden; text-overflow: ellipsis; }
}
.seg button.on { background: var(--card); color: var(--ink); box-shadow: var(--shadow-1); }
/* One kind on sale: the same control with its one answer across the whole of it — as wide as
   the pair would be, and nothing to press (owner, 27 Sep 2026). */
.seg.only { min-width: 204px; }
.seg.only button { cursor: default; }
.faq details { border-top: 1px solid var(--line); padding: 14px 0; }
.faq details:first-of-type { border-top: 0; }
.faq summary { cursor: pointer; font-weight: 620; }
.faq p { margin: 8px 0 0; color: var(--muted); }

.feature { display: flex; gap: 12px; padding: 11px 0; border-top: 1px solid var(--line); }
.feature:first-child { border-top: 0; }
.feature .glyph { width: 26px; text-align: center; }

.price { font-weight: 700; letter-spacing: -.02em; }
.state { padding: 40px 10px; text-align: center; color: var(--muted); }
.err { color: #d24b4b; }

.back { background: none; border: 0; color: var(--accent-text); font: inherit; font-weight: 600; padding: 10px 0; cursor: pointer; }

.pill { display: inline-block; padding: 4px 10px; border-radius: 999px; font-size: 12px; font-weight: 650; background: var(--wash); color: var(--accent-text); }
/* A finished plan is a record, not an alarm: the row reads one step quieter. */
.row.quiet .title { color: var(--muted); font-weight: 550; }
.row.quiet .pill { background: color-mix(in srgb, var(--ink) 7%, transparent); color: var(--muted); }

.pill.good { background: color-mix(in srgb, #1f9d55 16%, transparent); color: #1f9d55; }
.pill.warn, .pill.warning { background: color-mix(in srgb, #e08a1e 18%, transparent); color: #b06f12; }
.pill.bad, .pill.danger { background: color-mix(in srgb, #d24b4b 16%, transparent); color: #d24b4b; }

.field { display: block; margin: 14px 0; }
.field span { display: block; font-size: 13px; font-weight: 620; margin-bottom: 6px; }
.field input, .field select, .field textarea, article input, article select, article textarea {
  width: 100%; padding: 12px 14px; border-radius: 12px; border: 1px solid var(--line);
  background: var(--card); font: inherit; color: inherit;
}
/* `.acct-input` sets `outline: none` and puts the accent on its border instead. A border
   colour is not a focus ring — it is one pixel, it is the same pixel the field already had,
   and on a dark screen it was the invisible accent. It joins the fields that get a real
   ring, which is what a keyboard tells "where am I" from. */
.field input:focus, .field select:focus, article input:focus, article textarea:focus, article select:focus,
.search input:focus, .filter input:focus, .acct-input:focus { outline: 2px solid color-mix(in srgb, var(--accent-text) 45%, transparent); outline-offset: 1px; }

.stack-h { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.horizontal { display: flex; gap: 10px; flex-wrap: wrap; }

/* --- phones ------------------------------------------------------------------------- */

/* The activation code as a picture. Always drawn on white, whatever the page's colours are
   doing: a scanner reads contrast, and a dark-mode QR on a dark card is a code nobody can
   scan. The frame is the quiet zone the standard asks for, made visible. */
.qr { display: flex; flex-direction: column; align-items: center; gap: 8px; margin: 14px 0 4px; text-align: center; }
.qr-frame { background: #ffffff; border: 1px solid var(--line); border-radius: 14px; padding: 10px; line-height: 0; box-shadow: var(--shadow-1); }
.qr-frame svg { display: block; width: 208px; height: 208px; max-width: 60vw; }
.qr p { margin: 0; max-width: 34ch; }

@media (max-width: 720px) {
  .wrap { padding: 0 var(--gutter) 56px; }
  header { margin: 0 calc(50% - 50vw + var(--scrollbar, 0px) / 2) 4px; padding: 10px 16px; gap: 8px; }
  nav a { padding: 7px 9px; font-size: 13.5px; }
  .hero { padding: 34px 0 14px; }
  .hero h1 { max-width: none; }
  .hero .actions .cta { flex: 1 1 100%; }
  section { margin-top: 38px; }
  .destgrid, .destgrid.wide { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; }
  .dest { min-height: 116px; padding: 13px; }
  .dest .flag { font-size: 26px; top: 11px; left: 13px; }
  .dest .name { font-size: 15.5px; }
  .facts { grid-template-columns: repeat(2, 1fr); gap: 10px; }
  th, td { padding: 11px 12px; font-size: 14px; }
  footer { margin-top: 48px; }
}

@media (max-width: 420px) {
  nav { gap: 0; }
  nav a { padding: 6px 7px; font-size: 13px; }
  .facts { grid-template-columns: 1fr 1fr; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
  .cta:hover, .btn:hover, .dest:hover, .tile:hover { transform: none; }
}

/* The circle a row wears — a flag, or the globe a bundle wears. The same 40pt emblem the
   phone puts on every row, so a region on the site is the same object as in the app. */
.row .emblem {
  flex: 0 0 auto; width: 40px; height: 40px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 24px; line-height: 1;
  background: color-mix(in srgb, var(--accent) 8%, transparent);
}

/* "39 countries", on the banner, opening the list underneath. */
.pill {
  margin-top: 10px; border: 0; cursor: pointer; font: inherit; font-size: 13px; font-weight: 620;
  color: #fff; background: rgba(0, 0, 0, .3); backdrop-filter: blur(6px);
  padding: 7px 13px; border-radius: 999px;
  /* Three words, never folded into two lines inside a capsule built for one. */
  white-space: nowrap;
}
.pill:hover { background: rgba(0, 0, 0, .42); }

/* The list itself: a flag and a name, wrapping, never a column a page long. */
.countries { display: flex; flex-wrap: wrap; gap: 8px 14px; margin: 10px 0 6px; }
.countries .country { display: inline-flex; align-items: center; gap: 6px; font-size: 14px; }
.countries .country .f { font-size: 17px; line-height: 1; }

/* A value in a row that opens something. */
.linkish { border: 0; background: none; font: inherit; font-size: 14px; font-weight: 620; color: var(--accent-text); cursor: pointer; padding: 0; }
.linkish:disabled { opacity: .5; cursor: default; }

/* "Have a code?" under the checkout's email (owner, 27 Sep 2026): a quiet text button; then
   one row, the code and Apply; then "✓ Code added · ESIMDB" and Remove. Secondary on purpose
   — most people have no code, and the Pay button below does not wait for one. */
.partner-code { margin-top: -4px; }
.partner-code > .linkish { font-size: 13.5px; padding: 6px 0; }
.partner-code-entry { display: flex; gap: 8px; align-items: stretch; }
.partner-code-entry input {
  flex: 1 1 auto; min-width: 0; padding: 11px 14px; border-radius: 12px; border: 1px solid var(--line);
  background: var(--card); font: inherit; color: inherit; text-transform: uppercase; letter-spacing: .04em;
}
.partner-code-entry input::placeholder { text-transform: none; letter-spacing: normal; }
.partner-code-entry input:focus { outline: 2px solid color-mix(in srgb, var(--accent-text) 45%, transparent); outline-offset: 1px; }
.partner-code-entry .btn { flex: none; padding: 10px 18px; }
.partner-code .said { margin: 6px 0 0; }
.partner-code .added { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; margin: 0; padding: 6px 0; font-size: 13.5px; font-weight: 620; }
.partner-code .added .tick { color: #1f9d55; }
.partner-code .added .linkish { font-size: 13.5px; }

/* A plan's own banner, the same shape as a destination's. */
.plan-hero {
  border-radius: calc(var(--radius) + 4px); overflow: hidden; position: relative;
  min-height: 150px; display: flex; align-items: flex-end;
  padding: 22px; color: #fff;
  background: linear-gradient(135deg, var(--accent), var(--secondary));
  box-shadow: var(--shadow-2);
}
.plan-hero::after { content: ""; position: absolute; inset: 0; background: linear-gradient(158deg, rgba(255,255,255,.14), rgba(255,255,255,0) 45%, rgba(0,0,0,.38)); }
.plan-hero .words { position: relative; z-index: 1; }
.plan-hero .flag { font-size: 34px; line-height: 1; display: block; margin-bottom: 8px; filter: drop-shadow(0 2px 6px rgba(0,0,0,.35)); }
.plan-hero h1 { margin: 0; font-size: clamp(24px, 3.6vw, 34px); }
.plan-hero p { margin: 4px 0 0; opacity: .93; }

/* Real flags, the same artwork the phone ships.
   An emoji flag is not a picture: Windows draws it as the two letters of the country code,
   so the site wore a wall of grey letter pairs while the app showed flags. These rules size
   the <img> in each place a flag appears; the span rules above still apply wherever a code
   has no picture and the emoji is used instead. */
img.flag { display: block; height: auto; border-radius: 3px; box-shadow: 0 1px 4px rgba(0,0,0,.35); object-fit: cover; }
.dest img.flag { width: 34px; }
.tile img.flag { width: 32px; }
.dest-hero img.flag { width: 56px; border-radius: 4px; }
.plan-hero img.flag { width: 48px; border-radius: 4px; }
@media (max-width: 620px) {
  .dest img.flag { width: 29px; }
  .dest-hero img.flag { width: 46px; }
  .plan-hero img.flag { width: 40px; }
}

/* A tile wearing a photograph needs its words to stay readable over it: the picture is
   layered above the gradient with its own dark wash (see backgroundWith in site.ts), and
   the text keeps the shadow it always had. Nothing here applies to a place we ship no
   picture for — that tile is still the plain gradient. */
.dest, .tile { background-position: center; background-size: cover; }
.dest-hero { background-position: center; background-size: cover; }

/* The one line that says what the two tabs mean. "Unlimited" over a list of data sizes is
   a contradiction until somebody explains it, and the explanation is short: By Data stops,
   Unlimited slows. Small and grey and marked with a quiet ⓘ — information, not a control,
   and it must never look like something to click. */
.kind-note { display: flex; gap: 6px; align-items: flex-start; margin: -4px 0 14px; color: var(--muted); font-size: 12.5px; line-height: 1.45; max-width: 62ch; }
.kind-note span[aria-hidden] { opacity: .7; }

/* The regions tab is a list of full-width rows at every screen size. Its pieces — the
   "where are you going" box, the matches it finds, the shelves themselves — stack. */
#shelf-regions > * + *, #shelf-global > * + * { margin-top: 14px; }
#shelf-regions .row .price, #shelf-global .row .price { white-space: nowrap; }
/* The name on one line, what it adds on the next. A row is read left to right: name,
   price, chevron — never a name broken into three words down a narrow column. */
#shelf-regions .row .title, #shelf-global .row .title { display: block; }
/* A row that wears "Best Deal!" ------------------------------------------------------
   Name first, badge to the RIGHT of it, at every width and in every language — he said
   so three times, and a badge stacked under the name on phones was still the wrong
   answer. So the line is a flex row: the badge holds its width (it is cut down to about
   80 points on a phone, above) and the name beside it wraps at whole words.

   No min-width:0 on the name: flexbox's automatic minimum is then the longest WORD,
   which is what stops a squeezed column from breaking "Центральная" a letter at a time. */
#shelf-regions .row .title.hasdeal, #shelf-global .row .title.hasdeal { display: flex; align-items: center; min-width: 0; }
/* …and the shop's own shelves (app.js regionRow), where the badge rides the same line. */
.grow > .title.hasdeal { display: flex; align-items: center; min-width: 0; }
.row .title.hasdeal .deal { flex: 0 0 auto; }
/* And the room to do it in: on a phone the indent under a shelf head and the gap between
   the name and the price are what the badge is borrowing from. */
@media (max-width: 620px) {
  #shelf-regions .row, #shelf-global .row { gap: 8px; }
  #shelf-regions details.shelf .row[style], #shelf-global details.shelf .row[style] { padding-left: 16px !important; }
  #shelf-regions .row .title, #shelf-global .row .title { font-size: 14.5px; }
}

/* A place on the regions shelf: its best bundle, and the others folded behind it. */
.regiongroup { display: contents; }
.regiongroup > details.shelf { grid-column: 1 / -1; margin: 2px 0 10px; }
.regiongroup > details.shelf > summary { padding: 10px 12px; }

/* The total, said as a total: the word first and heavier, the money beside it. */
.buybar .total .totalword { font-size: 17px; font-weight: 800; letter-spacing: -.01em; }

/* The search, and the panel that answers it ------------------------------------------
   The panel floats under the field rather than pushing the page down: a shop that jumps
   while somebody is typing loses whatever they were looking at. */
.search-host { position: relative; }
.search-clear { border: 0; background: none; font: inherit; color: var(--muted); cursor: pointer; padding: 0 2px; line-height: 1; }
.search-panel { position: absolute; left: 0; right: 0; top: calc(100% + 6px); z-index: 40; max-height: 340px; overflow-y: auto; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow-2); }
.search-panel .row { width: 100%; }
.search-also { padding: 10px 16px; font-size: 13px; font-weight: 620; color: var(--muted); background: color-mix(in srgb, var(--ink) 4%, transparent); }

/* Together — the page before anybody has joined it ------------------------------------ */
.tg-hero { border-radius: var(--radius); padding: 26px 22px; color: #fff; background: linear-gradient(135deg, var(--accent), color-mix(in srgb, var(--accent) 55%, #6b5bd6)); }
.tg-hero .mark { font-size: 30px; line-height: 1; }
.tg-hero h1 { margin: 10px 0 6px; font-size: 26px; letter-spacing: -.02em; }
.tg-hero p { margin: 0; opacity: .92; }
.tg-save { margin-top: 12px; padding: 14px 16px; border-radius: var(--radius); font-weight: 620; background: color-mix(in srgb, var(--accent) 12%, transparent); }
.tg-feature { display: flex; gap: 12px; align-items: flex-start; padding: 14px 16px; margin-top: 10px; border-radius: var(--radius); background: var(--card); box-shadow: var(--shadow-1); }
.tg-feature .glyph { width: 34px; height: 34px; display: grid; place-items: center; border-radius: 999px; background: color-mix(in srgb, var(--accent) 14%, transparent); }
.tg-step { display: flex; gap: 10px; align-items: center; padding: 6px 0; }
.tg-step .n { width: 26px; height: 26px; display: grid; place-items: center; border-radius: 999px; background: var(--accent); color: var(--on-accent); font-weight: 700; font-size: 13px; }

/* ------------------------------------------------------------------------------------- *
   The shop, as the web version of the app
   ---------------------------------------
   Everything below this line exists so that lempart.app/app and the phone show the same
   first page: one column, the logo at the top, the greeting under it, and the unlimited
   banner leading. Widened to the marketing pages' 1120px the shop laid six destination
   tiles across a desktop and read as a directory rather than a shop.
 * ------------------------------------------------------------------------------------- */
/* The shop is a 620px column, and the header has to know that.

   The header bleeds the full width of the window and pads itself back to the page's own
   column with `--page`, which is 1120 for the marketing pages. Inside the shop, whose
   column is 620, that put the wordmark a couple of hundred pixels to the LEFT of every
   card under it on a laptop — the thing he kept pointing at (owner, 22 Sep 2026). The
   column width is declared here once and the header's own arithmetic does the rest. */
.wrap.shop { max-width: 620px; --page: 620px; }

/* The real wordmark, tinted by the text colour the way the apps tint theirs, so it stays
   legible whichever theme the Studio publishes. The lettered green square it replaced was
   a second logo standing where the first one goes. */
/* Sized by its HEIGHT, at the artwork's own 574:264.

   It used to be a 116x33 BOX with the picture fitted inside it: the lockup is two words
   stacked, so `contain` fitted the height and painted 72 pixels of logo in a 116-pixel
   box — a third of the header's left side was empty, and every attempt to make the logo
   bigger by widening the box changed nothing at all (owner, 22 Sep 2026: "you just
   continue making the field smaller"). Height is the dimension that governs, so height is
   what is set here, and the width follows the artwork. */
.logo .wordmark {
  /* Sized by height, at the artwork's own 574:264, and nothing else. The lockup's F starts
     at the very first column of the file — checked, pixel by pixel — so the box's left edge
     IS the letter's left edge, and the header's padding does the aligning. */
  display: block; height: 46px; width: auto; aspect-ratio: 574 / 264; background: var(--ink);
  -webkit-mask: url(/app/brand-wordmark.png) left center / contain no-repeat;
  mask: url(/app/brand-wordmark.png) left center / contain no-repeat;
  border-radius: 0; box-shadow: none;
}
.greet { margin: 2px 0 10px; color: var(--muted); font-size: 15px; }

/* THE BANNER IS LIGHT, LIKE EVERY OTHER PAGE (owner, 24 Sep 2026)
   ===============================================================
   "I want the entire home page to be light. As all other pages, like countries in Pro
   Store, light and beautiful ... it has to be consistent, the entire style."

   It was a deep-green card on a cream page: the one surface on this site that argued with
   the rest of it, and the first thing anybody sees.

   NOT A CARD EITHER (owner, later the same day). A first pass put the words on a white
   card, and he sent it back: "it doesn't have to be on the white background — like in
   countries it's not a white background … page already exists, do like that page." So this
   is `.hero.ed-hero` — the country pages' own opening — to the letter: the words and the
   picture stand straight on the cream page with no card, no shadow and no frame around them,
   the same padding above, the same two equal columns and the same gap between them, the
   headline at `.ed-hero h1`'s size in the page's ink, the lede at `.lede`'s size in the
   muted grey, the picture in `.ed-hero-art`'s sage panel with one generous corner, and the
   dark pill button. Not one value below is new: every colour, every size and every corner
   is a token or a number `.ed-hero` already carries, which is the whole of "consistent".

   THE RULES BELOW ARE REPOINTED, NEVER DELETED. Each declaration that used to name an ivory
   or a lime for the green ground now names the light one instead, in the same rule, with the
   same selector -- so no class the markup carries is left without a rule behind it, which is
   how the fair-use line once ended up reading as a second headline. */
.unlimited-hero {
  /* `clip`, not `hidden`: the infinity mark behind the words overhangs the column's edge
     and must not widen the page, and `clip` cuts it without making the banner a scroll
     container of its own. The vertical stays open so the button's shadow is not cut. */
  position: relative; overflow-x: clip; overflow-y: visible;
  border-radius: 0; padding: clamp(18px, 2.4vw, 34px) 0 6px;
  background: none;
  box-shadow: none;
  color: var(--ink);
}
.unlimited-hero .capsule {
  display: inline-block; padding: 5px 11px; border-radius: 999px;
  background: var(--accent); color: var(--on-accent);
  font-size: 12px; font-weight: 800; letter-spacing: .02em; text-transform: uppercase;
}
/* The destination pages' headline, to the letter: `.ed-hero h1`'s size, leading, tracking
   and measure, in the page's own ink the way theirs is. It was 38px of ivory on the green. */
.unlimited-hero h1, .unlimited-hero h2 { margin: 14px 0 0; max-width: 13ch; font-size: clamp(34px, 4.4vw, 56px); line-height: 1.05; letter-spacing: -.03em; color: var(--ink); }
/* The named offers under the headline (launch report, 21 Sep 2026). */
.unlimited-hero .proof { margin: 18px 0 0; display: grid; gap: 8px; max-width: 460px; }
.unlimited-hero .proof-row { display: grid; gap: 2px; padding: 10px 14px; border-radius: 14px; background: var(--panel-sage); color: inherit; text-decoration: none; }
.unlimited-hero a.proof-row:hover { background: color-mix(in srgb, var(--forest) 12%, var(--bg)); }
.unlimited-hero .proof-row .where { font-weight: 650; }
.unlimited-hero .proof-row .prices { font-weight: 750; font-variant-numeric: tabular-nums; }
a.tile { text-decoration: none; }
/* `.ed-hero .lede`, value for value: the same distance under the headline, the same measure
   and the same size at every width. */
.unlimited-hero .sub { margin: 18px 0 0; max-width: 38ch; color: var(--muted); opacity: 1; font-size: clamp(15.5px, 1.3vw, 18px); }
.unlimited-hero .from { margin: 18px 0 0; }
.unlimited-hero .from .label { color: var(--muted); opacity: 1; font-size: 14.5px; }
.unlimited-hero .from .amount { display: flex; align-items: flex-end; gap: 8px; }
.unlimited-hero .from .money { font-size: 46px; font-weight: 800; line-height: 1; letter-spacing: -.03em; color: var(--forest); }
.unlimited-hero .from .per { color: var(--muted); opacity: 1; font-size: 16px; padding-bottom: 5px; }
.unlimited-hero .btn.cta {
  margin-top: 18px; background: var(--accent); color: var(--on-accent); border: 0; font-weight: 700;
}

/* The chips scroll rather than share the width equally: three equal columns cut "Belgium"
   to "Belgiu…", a country reduced to a stump on the first screen anybody sees. */
.dest-chips { display: flex; gap: 8px; overflow-x: auto; padding: 2px 0 6px; scrollbar-width: none; }
.dest-chips::-webkit-scrollbar { display: none; }
.dest-chips .chip {
  flex: 0 0 auto; padding: 10px 14px; border-radius: 14px; cursor: pointer;
  background: var(--card); border: 1px solid var(--line); color: var(--ink);
  font-size: 14.5px; font-weight: 600; white-space: nowrap;
}
.dest-chips .chip.on { background: var(--accent); color: var(--on-accent); border-color: transparent; }

.unlimited-plan .find {
  width: 100%; margin: 0 0 12px; padding: 13px 16px; border-radius: 14px;
  background: var(--card); border: 1px solid var(--line); color: var(--ink); font-size: 15px;
}
.unlimited-plan .countries { margin: 4px 0 12px; }
.unlimited-plan .countries summary {
  display: inline-block; cursor: pointer; list-style: none;
  padding: 8px 14px; border-radius: 999px; background: var(--card); border: 1px solid var(--line);
  font-size: 14.5px; font-weight: 600;
}
.unlimited-plan .countries summary::-webkit-details-marker { display: none; }
.unlimited-plan .countries .grid {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px 16px;
  margin-top: 10px; font-size: 14.5px; color: var(--muted);
}
.plan-face .price { font-size: 40px; font-weight: 800; letter-spacing: -.03em; line-height: 1; }
/* One fact per line. The stylesheet lays other lists out in a row, which put "Unlimited
   data · Can be extended · Data only" across the card as though they were tabs. */
.plan-face .facts { display: block; margin: 14px 0; padding-left: 18px; color: var(--muted); font-size: 14.5px; }
.plan-face .facts li { display: list-item; margin: 4px 0; }
.plan-face .switch-row { display: flex; align-items: center; gap: 10px; font-weight: 600; margin-top: 6px; }
.plan-face .switch-row .sw { width: 42px; height: 24px; accent-color: var(--accent); }
.row.link { display: flex; align-items: center; gap: 12px; padding: 14px 16px; border-radius: 16px; background: var(--card); border: 1px solid var(--line); }
.row.link .chev { color: var(--muted); font-size: 20px; }


/* ------------------------------------------------------------------------------------- *
   The shop is the website now (19 Sep 2026): lempart.app opens it.
   A phone keeps the one comfortable column. A laptop gets a page that fills the screen the
   way a shop front should: a wider column, a bigger banner, more tiles to a row, and the
   rails' cards grown with it — the same blocks in the same order, only larger.
 * ------------------------------------------------------------------------------------- */
@media (min-width: 760px) {
  /* The column and the header's idea of the column move together, or the wordmark drifts
     away from the cards under it. */
  .wrap.shop { max-width: 900px; --page: 900px; }
  .wrap.shop .grid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; }
  .wrap.shop .tile { min-height: 150px; }
}
@media (min-width: 1100px) {
  .wrap.shop { max-width: 1160px; --page: 1160px; }
  /* The informational sections moved into `#shop-sections` (23 Sep 2026), so the shelf's
     own blocks and the sections inside that box are both one selector's work: without the
     second half the seven cards below the shelf fall back to the 22px phone rhythm on a
     wide screen, a step out of time with the shelf above them. */
  /* THE HOME PAGE'S OWN SECTIONS BREATHE LIKE THE COUNTRY PAGES' (owner, 24 Sep 2026): the
     Studio's blocks under the banner take the editorial section's air and its heading
     size, so the top half of the page and the served sections under it read as one page. */
  .wrap.shop > .block, .wrap.shop > #shop-sections > .block { margin: clamp(34px, 3.6vw, 56px) 0; }
  .wrap.shop .block > h2.b { font-size: clamp(26px, 3.1vw, 41px); line-height: 1.12; letter-spacing: -.028em; margin-bottom: clamp(16px, 2vw, 26px); }
  /* No card to pad and no card to round: the banner keeps `.hero.ed-hero`'s own padding at
     every width, which is what the country pages open with on the same screen. */
  .wrap.shop .unlimited-hero { padding: clamp(18px, 2.4vw, 34px) 0 6px; border-radius: 0; min-height: 0; }
  /* The eyebrow is the country pages' eyebrow at every width — 11.5px, no padding — so the
     laptop rule that used to grow the filled pill now says the same thing the base does. */
  .wrap.shop .unlimited-hero .capsule { font-size: 11.5px; padding: 0; }
  /* 60px was the card's own headline; `.ed-hero h1` tops out at 56px, and so does this. */
  .wrap.shop .unlimited-hero h2 { font-size: clamp(34px, 4.4vw, 56px); max-width: 13ch; }
  .wrap.shop .unlimited-hero .sub { font-size: clamp(15.5px, 1.3vw, 18px); }
  .wrap.shop .unlimited-hero .from .money { font-size: 64px; }
  .wrap.shop .unlimited-hero .from .per { font-size: 19px; padding-bottom: 8px; }
  /* The button is the country pages' "See unlimited plans": as wide as its own words, not
     a 340px bar. */
  .wrap.shop .unlimited-hero .btn.cta { margin-left: 0; margin-right: 0; width: auto; min-width: 0; min-height: 56px; padding: 0 30px; font-size: 16px; }
  .wrap.shop .grid { gap: 16px; }
  .wrap.shop .tile { min-height: 190px; }
  .wrap.shop .tile .name { font-size: 19px; }
  .wrap.shop .tile .from { font-size: 14.5px; }
  .wrap.shop .rail { gap: 16px; }
  .wrap.shop .rail > .block.banner { width: 360px !important; }
  .wrap.shop .btn.wide { max-width: 520px; margin-left: auto; margin-right: auto; display: flex; justify-content: center; }
  .wrap.shop .search-host { max-width: 720px; margin-left: auto; margin-right: auto; }
}

/* The eyebrow, the button, and nothing painted behind the words (owner, 24 Sep 2026)
   -----------------------------------------------------------------------------------
   `.capsule` was a filled lime pill, which is a shape the light pages do not have. The
   destination pages open with an eyebrow instead — forest small caps with a lime dot in
   front of them — and that is what this is, down to the 11.5px and the .14em. Same
   element, same class, same word from the design document: only the paint changes.

   The button is the dark pill those pages press with ("See unlimited plans"), forest on
   the white card, which is also the one place the eye should land.

   The lime infinity mark that used to sit under the words is gone. It was drawn to be
   read through a deep green; over white it is either invisible or a smudge, and the
   destination pages carry no watermark at all. A third look is exactly what was asked
   for NOT to happen. */
.unlimited-hero .capsule {
  display: inline-flex; align-items: center; gap: 9px;
  background: none; padding: 0; border-radius: 0;
  color: var(--forest); font-size: 11.5px; letter-spacing: .14em;
}
.unlimited-hero .capsule::before {
  content: ""; width: 7px; height: 7px; border-radius: 50%; flex: none;
  background: color-mix(in srgb, var(--lime) 62%, var(--forest));
}
.unlimited-hero .btn.cta {
  background: var(--forest); color: var(--on-band);
  /* `.cta`'s own metrics and its soft shadow, and `.ed-actions`' 30px of air above it —
     the country pages' button, not a bar across the column. */
  margin-top: 30px; width: auto; padding: 14px 22px; border-radius: 999px;
  font-size: 15.5px; font-weight: 650;
  box-shadow: 0 8px 22px color-mix(in srgb, var(--forest) 32%, transparent);
}
.unlimited-hero .btn.cta:hover { background: color-mix(in srgb, var(--forest) 88%, #000); }
.unlimited-hero > * { position: relative; z-index: 1; }
/* THE INFINITY MARK IS BACK, IN THE PAGE'S OWN SHADE (owner, 24 Sep 2026)
   ---------------------------------------------------------------------
   "Add some infinite sign in background like it was in the old banner, but in a shade
   that matches the new style." The mark, its size and where it sits are the old banner's,
   character for character; only the paint changes. It was the kit's lime at 14% through a
   deep green. On the cream page it is the forest at 8% — the same faint sage the panel
   behind the picture is mixed from — so it reads as a watermark under the words and never
   as a third colour. The words, the offer and the button all stand above it (`z-index: 1`
   on the children).

   BOTTOM RIGHT, LIKE THE OLD ONE, AND FADED RATHER THAN CUT (owner, 24 Sep 2026: "the
   infinity sign can be moved a bit to the right bottom — to create some effect like in the
   old banner"). The old card cropped the mark at its bottom-right corner, and the crop was
   the effect: a mark running off under the frame. There is no frame now — the banner's
   edge is an invisible line on the cream — so a hard crop would read as a mark cut with
   scissors. So it sits at the bottom right OF THE WORDS, overhanging their box a little on
   the right, and it fades out towards its own far edges through a mask instead of stopping
   at them: the same running-off, without the scissors. It belongs to `.unl-words` rather
   than to the banner so that on a phone, where the picture stands UNDER the words, the
   mark stays behind the words and never lands on the picture. `.unl-words` is already a
   positioned layer (`.unlimited-hero > *`), so a `z-index: -1` here paints under the
   headline, the price and the button and above nothing but the cream. */
.unlimited-hero .unl-words::after {
  content: ""; position: absolute; z-index: -1; pointer-events: none;
  right: -8%; bottom: -6%; width: 64%; aspect-ratio: 2 / 1; opacity: .09;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 240 120'%3E%3Cpath d='M60 22C29 22 8 40 8 60s21 38 52 38c42 0 78-76 120-76 31 0 52 18 52 38s-21 38-52 38c-42 0-78-76-120-76Z' fill='none' stroke='%23073D31' stroke-width='16' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat;
  -webkit-mask-image: radial-gradient(farthest-side at 38% 42%, #000 46%, transparent 100%);
  mask-image: radial-gradient(farthest-side at 38% 42%, #000 46%, transparent 100%);
}
/* In Arabic the grid mirrors and the words stand on the left, so the mark follows them. */
[dir="rtl"] .unlimited-hero .unl-words::after { right: auto; left: -8%; }
/* On a phone the words are the whole width: the mark is larger against them and overhangs
   the screen's edge a little, which the page's own gutter absorbs — measured, no sideways
   scroll at 320, 375, 390 or 414. */
@media (max-width: 760px) {
  .unlimited-hero .unl-words::after { width: 78%; right: -10%; bottom: -4%; }
  [dir="rtl"] .unlimited-hero .unl-words::after { right: auto; left: -10%; }
}

/* The wordmark a size up on a laptop, where 92px read as a footnote beside the menu. */
@media (min-width: 1100px) { .logo .wordmark { height: 54px; } }

/*
 * The fair-use line under the unlimited hero.
 *
 * `class="sub fair"` was in the markup with no rule behind it, so the qualifier - the one
 * sentence that stops "Unlimited" being a promise we do not keep - was set exactly like
 * the subtitle above it and read as a second headline.
 *
 * It is made quieter by size and measure alone, not by fading it. `.sub` is already at .85
 * on the hero's gradient (6.0:1 at the gradient's lightest stop) and is `--muted` anywhere
 * else (5.7:1 on the light page, 8.4:1 on the dark); knocking it back another notch would
 * put the light-page case at 3.5:1, and a legal qualifier nobody can read is the failure
 * this line exists to prevent. The desktop selector carries `.wrap.shop` so it outranks the
 * wide-screen rule that sets `.unlimited-hero .sub` to 20px.
 */
.sub.fair { margin-top: 6px; max-width: 48ch; font-weight: 500; }
.sub.fair, .wrap.shop .unlimited-hero .sub.fair { font-size: 13.5px; line-height: 1.45; }


/* The offer page
   ==============
   One length of one country, with its total price as the largest thing on the screen.
   Everything here is a variant of something the shop already has — the card, the chips,
   the table — so an offer page looks like the shop rather than like a landing page
   somebody bolted on. */
/* The line above the place name: small, uppercase, the shop's own eyebrow treatment.
   It carries the words a search engine needs without taking the headline off the thing
   the reader came for. */
.dest-hero .kicker {
  display: block; margin: 0 0 2px; font-size: 12px; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase; opacity: .9;
}
.offercard { padding: 22px; }
.offerprice { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; margin-bottom: 10px; }
.offerprice .amount { font-size: clamp(38px, 6vw, 54px); font-weight: 780; letter-spacing: -.035em; line-height: 1; }
.offerprice .what { color: var(--muted); font-size: 15.5px; }
.offercard p { margin: 10px 0 0; }
.offercard .cta { margin-top: 4px; }
.offercard .muted { color: var(--muted); font-size: 13.5px; }

/* The destination page's two headline offers: a week and a month, side by side, each
   with its total as the largest thing in the card and its own buy button. A person who
   arrived from a search for "unlimited USA eSIM" came for one of these two numbers, so
   they are the page rather than something under it. */
.offergrid { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }
.offergrid .offercard { margin: 0; }
ul.offerpoints { margin: 12px 0 16px; padding-left: 18px; color: var(--muted); font-size: 14.5px; }
ul.offerpoints li { margin: 4px 0; }
ul.offerpoints li::marker { color: color-mix(in srgb, var(--accent) 60%, transparent); }

/* The whole catalogue, folded away.

   Every daily amount at every length is over sixty rows, and printing them above the
   price somebody searched for buried the offer in its own stock list. It is still here,
   one click down, drawn exactly as it was. */
details.everything { border: 1px solid var(--line); border-radius: 16px; background: var(--card); box-shadow: var(--shadow-1); }
details.everything > summary {
  list-style: none; cursor: pointer; padding: 16px 18px; display: flex; flex-direction: column; gap: 2px;
}
details.everything > summary::-webkit-details-marker { display: none; }
details.everything > summary::after {
  content: "\203a"; position: absolute; right: 20px; transform: rotate(90deg);
  color: var(--muted); font-size: 20px; line-height: 1;
}
details.everything > summary { position: relative; }
details.everything[open] > summary::after { transform: rotate(-90deg); }
details.everything > summary .title { font-weight: 680; font-size: 15.5px; }
details.everything > summary .value { color: var(--muted); font-size: 13.5px; }
details.everything > summary:hover { border-color: color-mix(in srgb, var(--accent) 45%, var(--line)); }
details.everything .inside { padding: 0 18px 18px; }

.chips-inline { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
a.chip-link {
  display: inline-block; padding: 7px 14px; border-radius: 999px; text-decoration: none;
  background: var(--card); border: 1px solid var(--line); color: var(--ink);
  font-size: 14px; font-weight: 620; box-shadow: var(--shadow-1);
}
a.chip-link:hover { border-color: color-mix(in srgb, var(--accent) 45%, var(--line)); }

/* The conditions, as a plain two-column table: the label the reader is scanning for on
   the left, the plan's own words on the right.

   Both columns are laid out by the table, not by their contents (owner, 23 Sep 2026).
   The general tariff rule below sets the last cell right-aligned and `nowrap`, which is
   right for a price and ruinous for a sentence: it pushed this table to 883px inside a
   288px phone, so every value sat off-screen and each label was squeezed into three
   lines. Fixed layout gives the label a column of its own and lets the value wrap;
   22.5em of it holds the longest label we print on one line. (A fixed table ignores a
   min() width, so this is a plain length.) */
table.terms { width: 100%; max-width: 100%; table-layout: fixed; border-collapse: collapse; font-size: 14.5px; }
table.terms th[scope="row"] {
  text-align: start; vertical-align: top; white-space: normal; font-weight: 650;
  padding: 11px 16px 11px 0; width: 22.5em; color: var(--ink);
  overflow-wrap: break-word;
}
table.terms td {
  vertical-align: top; padding: 11px 16px 11px 0; color: var(--muted);
  text-align: start; white-space: normal; overflow-wrap: break-word;
}
table.terms tr + tr th, table.terms tr + tr td { border-top: 1px solid var(--line); }
@media (max-width: 620px) {
  /* On a phone there is no room for two columns that both hold words: the label goes
     above the value, and the value keeps the full width of the card to wrap in. */
  table.terms, table.terms > tbody, table.terms tr, table.terms th[scope="row"], table.terms td { display: block; width: auto; }
  table.terms th[scope="row"] { padding: 12px 0 3px; }
  table.terms td { padding: 0 16px 12px 0; }
  table.terms tr + tr th { border-top: 1px solid var(--line); }
  table.terms tr + tr td { border-top: 0; }
}

/* The banner's offers, one at a time (owner, 21 Sep 2026)
   The look of the original banner — "from", one big price, the days beside it — with the
   place, the tier and "Unlimited data" named above the price and the month smaller below.
   The offers share one grid cell, so the card is as tall as the tallest and never jumps
   when they turn; the hidden one fades out rather than leaving the page. */
.unlimited-hero .offers { display: grid; margin: 18px 0 0; }
.unlimited-hero .offer {
  grid-area: 1 / 1; display: block; color: inherit; text-decoration: none;
  opacity: 0; visibility: hidden; transition: opacity .6s ease, visibility 0s linear .6s;
  border-radius: 16px; margin: -6px; padding: 6px;
}
.unlimited-hero .offer.on { opacity: 1; visibility: visible; transition: opacity .6s ease; }
.unlimited-hero a.offer:hover .money, .unlimited-hero a.offer:focus-visible .money { text-decoration: underline; text-decoration-thickness: 3px; text-underline-offset: 6px; }
.unlimited-hero a.offer:focus-visible { outline: 2px solid var(--forest); outline-offset: 2px; }
.unlimited-hero .offer .where { display: block; font-weight: 700; font-size: 15.5px; letter-spacing: .005em; }
.unlimited-hero .offer .from { margin: 10px 0 0; }
.unlimited-hero .offer .money { font-size: clamp(46px, 12vw, 64px); }
.unlimited-hero .offer .per { font-size: 18px; padding-bottom: 7px; }
.unlimited-hero .offer .then { display: block; margin-top: 8px; font-size: 16px; font-weight: 600; color: var(--muted); opacity: 1; font-variant-numeric: tabular-nums; }
.unlimited-hero .offer-dots { display: flex; gap: 8px; margin: 16px 0 0; }
.unlimited-hero .offer-dots .dot {
  width: 9px; height: 9px; padding: 0; border: 0; border-radius: 999px; cursor: pointer;
  background: color-mix(in srgb, var(--ink) 16%, transparent); transition: width .3s ease, background .3s ease;
}
.unlimited-hero .offer-dots .dot[aria-current="true"] { width: 26px; background: var(--forest); }
.unlimited-hero .sub.fair, .wrap.shop .unlimited-hero .sub.fair { font-size: 15.5px; max-width: none; margin-top: 2px; font-weight: 400; color: var(--muted); }
@media (prefers-reduced-motion: reduce) { .unlimited-hero .offer, .unlimited-hero .offer.on { transition: none; } }

/* The banner in two columns, the way the destination pages are built (owner, 24 Sep 2026)
   =======================================================================================
   "Now the first banner we have now, you can put that design, that lady on the left and on
   the right, you have some text … Everything put to the right side of that field."

   So this is `.hero.ed-hero`'s rule wearing the banner's own colours: the illustration is a
   COLUMN, not a band across the top, and it keeps its own 3:2 — nothing is stretched and
   nothing is cropped, which is the whole of the "huge ass picture takes entire page"
   complaint. The words keep every rule they already had, because all of them reach through
   `.unlimited-hero` and none of them cares how deep the words sit.

   The picture is placed in column 1 and the words in column 2 EXPLICITLY, so the document
   can keep the words first — which is what puts the price and the button above the fold on
   a phone, and what makes a screen reader read the offer before the decoration. In Arabic
   the grid mirrors itself with the page, so the lady stands on the reader's starting side
   there too, without a rule of her own.

   TWO EQUAL COLUMNS AND THE COUNTRY PAGES' GAP (owner, 24 Sep 2026, second pass). The
   first pass gave the words the wider column and a tighter gap, and the words ended up
   pressed against the middle of the page with the picture floating in a card beside them.
   `.hero.ed-hero` is `1fr 1fr` with `clamp(26px, 3.6vw, 60px)` between, and so is this: the
   picture fills its column to the page's left edge exactly as the country pages' picture
   fills its column to the right edge.

   THE WORDS STAND A LITTLE IN FROM THE GAP. "Move that text a little bit to the right so
   it's kind of more balanced." The picture is one solid block and the words are a ragged
   left edge, so the two do not weigh the same at the same distance from the middle; the
   words take an extra inset of their own — nothing at phone widths, 44px on a laptop —
   which puts the column of type roughly as far from the picture as its right edge is from
   the page's. Set with the logical property so it stays on the picture's side in Arabic. */
.unlimited-hero.unl-split {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: center; gap: clamp(26px, 3.6vw, 60px);
}
.unlimited-hero.unl-split > .unl-words { grid-column: 2; grid-row: 1; min-width: 0; padding-inline-start: clamp(0px, 3vw, 44px); }
.unlimited-hero.unl-split > .unl-art {
  grid-column: 1; grid-row: 1; min-width: 0; overflow: hidden;
  /* `.ed-hero-art`'s own frame, value for value: the sage panel and one generous corner
     turned towards the words. It was a 6% white lift, which was the only thing that could
     be seen against the deep green and is nothing at all against the white card.

     The corner is set with the LOGICAL property, so in Arabic — where the grid mirrors and
     the picture stands on the right — the generous corner turns and still faces the words,
     without a rule of its own. */
  border-radius: var(--radius-lg);
  border-start-end-radius: clamp(28px, 5vw, 76px);
  background: var(--panel-sage);
}
/* `.band-art` carries a standing vertical margin for the pages where it sits between
   paragraphs. Inside a frame that shows as a rim, so the frame spaces it — the same
   exception `.ed-hero-art .band-art` already makes. */
.unlimited-hero .unl-art .band-art { display: block; width: 100%; height: auto; margin: 0; border-radius: 0; }
/* One column on a phone, and the picture AFTER the words: the button and the price are
   what the screen is for, and the illustration follows them rather than pushing them off. */
@media (max-width: 760px) {
  .unlimited-hero.unl-split { grid-template-columns: minmax(0, 1fr); gap: 26px; }
  .unlimited-hero.unl-split > .unl-words { grid-column: 1; grid-row: 1; padding-inline-start: 0; }
  .unlimited-hero.unl-split > .unl-art { grid-column: 1; grid-row: 2; }
  /* THE WORDS ARE AS WIDE AS THE PICTURE UNDER THEM (owner, 24 Sep 2026)
     "The text on banner stretches on the width of the picture below." The measures the
     laptop needs — 13ch on the headline, 38ch on the lede, 460px on the proof — are what
     kept the words in a narrower column than the picture on a phone. One column, one width. */
  .unlimited-hero h1, .unlimited-hero h2, .unlimited-hero .sub, .unlimited-hero .proof,
  .wrap.shop .unlimited-hero h2 { max-width: none; }
}

/* A destination's prices right under its heading (price-advantage brief, 21 Sep 2026):
   "Basic 7 days: $5.99 · 30 days: $22.99", then the benefit in one line. */
.dest-hero .price-strip { margin: 10px 0 0; font-size: clamp(19px, 3.2vw, 24px); font-weight: 750; font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
.dest-hero .price-strip .tier { display: inline-block; vertical-align: middle; margin-right: 6px; padding: 3px 9px; border-radius: 999px; background: #D9FC57; color: #073D31; font-size: 12px; font-weight: 800; letter-spacing: .02em; text-transform: uppercase; }
.dest-hero .benefit { margin: 6px 0 0; font-weight: 600; }

/* The analytics question (consent.js). Bottom of the screen, never over the page's buttons
   for long: one sentence, two equal buttons, Decline as easy as Accept. */
.consent { position: fixed; left: 12px; right: 12px; bottom: 12px; z-index: 1000; max-width: 560px; margin: 0 auto; padding: 14px 16px; border-radius: 16px; background: var(--card, #fff); color: var(--ink, #10231d); box-shadow: 0 10px 30px rgba(0,0,0,.18); border: 1px solid var(--line, rgba(0,0,0,.08)); font-size: 14px; line-height: 1.45; }
.consent p { margin: 0 0 10px; }
.consent a { color: inherit; text-decoration: underline; }
.consent-actions { display: flex; gap: 8px; justify-content: flex-end; }
.consent .btn { min-width: 110px; padding: 9px 14px; border-radius: 999px; border: 1px solid #073D31; background: #073D31; color: #fff; font: inherit; font-weight: 700; cursor: pointer; }
.consent .btn.ghost { background: transparent; color: inherit; border-color: currentColor; }

/* …and it stands ON the pinned buy bar, never over it and never over the page -------------
   The bar a chosen plan opens is fixed to the foot of the window, and this question is fixed
   12px off the same edge with a z-index of 1000, so until somebody answered it the question
   covered the total and the Buy button underneath it. Both have to be usable: the question is
   there for a legal reason and cannot be hidden or deferred, and the bar is what the visitor
   is buying with.

   THE QUESTION STAYS AT THE EDGE, AND THE BAR KEEPS ROOM FOR IT (owner, 24 Sep 2026)
   It was the question that moved: it lifted off the edge by the whole height of the bar, and
   the bar is 312px of a 900px window. So the card stopped being a bar at the bottom of the
   screen and became an opaque card parked in the MIDDLE of the page — measured on
   /usa-esim with a plan chosen, it sat at y=443..564 at 1440x900, y=343..464 at 1280x800 and
   y=311..432 at 1024x768 — over whatever the page had there, swallowing the presses meant for
   it. At 1024 it landed exactly on the row of day lengths, so pressing "30 days" pressed
   Decline on the cookie question instead. Only 390 escaped, by arithmetic: the phone's stack
   is 79px shorter and its window 56px taller, which put the card 44px below the chips.

   So the card goes back where a cookie question belongs — against the bottom edge, exactly
   where it sits on every other page of this site — and the BAR leaves room for it at its own
   foot instead. `--consent-h` is the card's own height, measured and published by consent.js,
   which is the file that puts the card there and takes it away; the room is inside the bar's
   box, so `--buybar-h` and the dock already include it and the foot of the page still clears
   both. The total and the Buy button are above the card, the card is over the bar's padding,
   and nothing is fixed over the middle of the page.

   The phone's bar is flush with the bottom edge and carries the home indicator's inset in its
   own padding; the card sits 12px off that edge either way, so the room is the card and that
   12px on top of whatever padding the bar already had. */
body:has(.consent) .buybar.afloat {
  padding-bottom: calc(14px + var(--consent-h, 0px) + 12px);
  /* A bar allowed 72% of a short window would push the question off the top of it, and the
     two of them allowed half the window would meet the middle of the screen — which is where
     a reader scrolls the control they are reaching for. Together they keep the bottom 45% and
     nothing more, so the middle of the window always belongs to the page: at 1440x900 the top
     of the stack is y=483 against chips ending at y=471, and at 1024x768 y=410 against y=405.
     What will not fit in the bar is reached by scrolling inside it, which it already does,
     and answering the question gives the bar all 72% back. The phone is untouched — its own
     stack is 378px of an 844px window, which is under this ceiling already. */
  max-height: 45vh;
}
@media (max-width: 620px) {
  body:has(.consent) .buybar.afloat {
    padding-bottom: calc(9px + env(safe-area-inset-bottom) + var(--consent-h, 0px) + 12px);
  }
}

/* The destination on each banner offer, big enough to see while it turns. */
.unlimited-hero .offer .place { display: flex; align-items: center; gap: 10px; }
/* The place was set in the kit's lime, which is 1.5:1 on the white card — a word nobody
   could read. It is the forest the destination pages set their own headings in. */
.unlimited-hero .offer .place .name { font-size: clamp(24px, 5.4vw, 30px); font-weight: 800; letter-spacing: -.015em; line-height: 1.1; color: var(--forest); }
.unlimited-hero .offer .place .emblem, .unlimited-hero .offer .place img { width: 34px; height: 25px; border-radius: 5px; object-fit: cover; flex: none; font-size: 26px; line-height: 25px; box-shadow: 0 0 0 1px rgba(16, 24, 40, .14); }
.unlimited-hero .offer .place span.emblem { box-shadow: none; width: auto; }
.unlimited-hero .offer .where { margin-top: 6px; font-size: 14.5px; font-weight: 600; color: var(--muted); opacity: 1; }

/* The chooser's price card names its destination beside the price, and wraps under it on
   a narrow phone rather than squeezing either. */
.plan-face .face-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px 14px; flex-wrap: wrap; }
.plan-face .dest-pill { display: inline-flex; align-items: center; gap: 8px; max-width: 100%; padding: 6px 12px 6px 8px; border-radius: 999px; background: color-mix(in srgb, var(--accent, #D9FC57) 22%, transparent); font-weight: 700; font-size: 15px; }
.plan-face .dest-pill .flag, .plan-face .dest-pill img { width: 26px; height: 19px; border-radius: 4px; object-fit: cover; flex: none; font-size: 18px; line-height: 19px; }
.plan-face .dest-pill .name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* The destination page, drawn like the shop's destination screen (owner, 21 Sep 2026)
   ==================================================================================
   The public /<country>-esim page wears the SPA's own pieces — `.back`, `.dest-hero`,
   `.seg`, `.chips`, `.rows .row` — plus the front page's green `.unlimited-hero` for the
   one featured offer. Everything else the page says is folded into `.dest-more`. */
.dest-page { max-width: 760px; margin: 0 auto; }
.dest-page > * + * { margin-top: 16px; }
.dest-page a.back { display: inline-block; text-decoration: none; margin-top: 8px; }
.dest-page > .dest-hero { margin-top: 4px; min-height: 220px; }
.dest-page .dest-hero h1 { line-height: 1.12; }
.dest-page .dest-hero .from-line { margin: 6px 0 0; font-size: 17px; font-weight: 650; }
.dest-page > .photo-credit { margin-top: 6px; }

.dest-page .dest-feature { padding: 22px; }
.dest-page .dest-feature .where { display: block; margin-top: 12px; font-weight: 700; font-size: 15.5px; }
.dest-page .dest-feature .from { margin: 8px 0 0; }
.dest-page .dest-feature .from .money { font-size: clamp(44px, 11vw, 56px); font-variant-numeric: tabular-nums; }
.dest-page .dest-feature .from .per { font-size: 18px; padding-bottom: 6px; }
.dest-page .dest-feature a.then { display: inline-block; margin-top: 8px; color: inherit; text-decoration: none; font-size: 16px; font-weight: 600; opacity: .9; font-variant-numeric: tabular-nums; }
.dest-page .dest-feature a.then:hover, .dest-page .dest-feature a.enh:hover { text-decoration: underline; opacity: 1; }
.dest-page .dest-feature .btn.cta { display: flex; width: 100%; min-height: 52px; font-size: 16.5px; box-shadow: 0 8px 22px rgba(0,0,0,.18); }
.dest-page .dest-feature a.enh { display: block; margin-top: 14px; color: #D9FC57; text-decoration: none; font-size: 14.5px; font-weight: 650; font-variant-numeric: tabular-nums; }

.dest-page .dest-chooser { margin-top: 26px; }
.dest-page .dest-chooser .seg { display: flex; width: 100%; margin: 0 0 14px; }
.dest-page .dest-chooser .chips { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; padding: 2px 2px 6px; margin: 0 -2px 8px; }
.dest-page .dest-chooser .chips::-webkit-scrollbar { display: none; }
.dest-page .dest-chooser .chips button { flex: 0 0 auto; white-space: nowrap; }
.dest-page .dest-chooser .row { min-height: 60px; }
.dest-page .dest-chooser .row .value { display: block; font-size: 13.5px; margin-top: 2px; }
.dest-page .dest-chooser .row .price { font-size: 16.5px; }
.dest-page .dest-chooser .row .chev { font-size: 20px; line-height: 1; margin-left: 2px; }
/* With the script, one length at a time under its chip; without it, every length is
   listed under its own heading and the controls that could not work are not drawn. */
.dest-page .dest-chooser:not(.js) .seg, .dest-page .dest-chooser:not(.js) .chips { display: none; }
.dest-page .dest-chooser.js .grouphead { display: none; }
.dest-page .dest-chooser .rows + .rows, .dest-page .dest-chooser .kind + .kind { margin-top: 12px; }
.dest-page .dest-chooser [hidden] { display: none; }

.dest-page .dest-more { margin-top: 30px; }
.dest-page .dest-more > summary { padding: 16px 44px 16px 18px; }
.dest-page .dest-more .inside > p, .dest-page .dest-more .inside section > p { color: var(--muted); font-size: 14.5px; line-height: 1.55; }
.dest-page .dest-more .inside h2 { font-size: 17px; margin: 20px 0 8px; }
.dest-page .dest-more .inside section { margin-top: 18px !important; }
.dest-page .dest-more details.everything { box-shadow: none; }
@media (max-width: 480px) {
  .dest-page > .dest-hero { min-height: 190px; padding: 18px; }
  .dest-page .dest-feature { padding: 18px; }
}
/* The questions under the page sit in the same column as the page above them. */
.dest-page ~ * { max-width: 760px; margin-left: auto; margin-right: auto; }

/* "33 countries ⓘ": small print; the list floats over the page and closes on any tap. */
.cover-wrap { position: relative; margin: 2px 0 10px; }
.cover-info { border: 0; background: none; padding: 2px 0; font: inherit; font-size: 13px; font-weight: 600; color: var(--muted); cursor: pointer; text-decoration: underline dotted; text-underline-offset: 3px; }
.cover-pop { position: absolute; z-index: 30; top: calc(100% + 6px); left: 0; width: min(520px, calc(100vw - 32px)); max-height: 300px; overflow: auto; padding: 12px 14px; border-radius: 14px; background: var(--card, #fff); border: 1px solid var(--line, rgba(0,0,0,.08)); box-shadow: 0 12px 30px rgba(0,0,0,.16); }
.cover-pop[hidden] { display: none; }
.cover-pop .grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: 6px 12px; font-size: 14px; }

/* The unlimited store's headline as a promotion banner, in the front page's colours. */
.store-intro.promo { position: relative; overflow: hidden; margin: 6px 0 18px; padding: 18px 20px; border-radius: var(--radius-lg, 22px); background: linear-gradient(135deg, #145845, #0b4436 55%, #052f27); color: #f6f4ec; }
.store-intro.promo .capsule { display: inline-block; padding: 4px 10px; border-radius: 999px; background: #D9FC57; color: #073D31; font-size: 11.5px; font-weight: 800; letter-spacing: .02em; text-transform: uppercase; }
.store-intro.promo h1 { margin: 10px 0 0; font-size: clamp(22px, 5vw, 30px); line-height: 1.12; letter-spacing: -.015em; color: #D9FC57; }

/* The header on a phone: two lines beside the logo, everything at its normal size and the
   language named in full (owner, 21 Sep 2026) — "Pro Store · How it works" above,
   "Log in · Help · English" below. An empty flex item forces the break. */
.lang-wrap { position: relative; display: inline-flex; }
/* The language control is as wide as the language you are reading in
   ------------------------------------------------------------------
   A <select> takes the width of its LONGEST option, so on a laptop "Español" sat in a
   pill built for "Português (Brasil)" with a hand's width of nothing after it (owner,
   23 Sep 2026). The pill below shows the current language and is sized by that word; the
   real <select> is laid over it, invisible, so a tap still opens the system's own list
   with every language in it. What was a phone-only trick is now how it works everywhere.
   A name longer than the pill allows — "Français (Canada)" — is the one that gets an
   ellipsis, which is the trade he asked for. */
.lang-code {
  display: inline-flex; align-items: center; gap: 6px; max-width: 168px;
  padding: 7px 13px; border-radius: 999px; font-weight: 600; font-size: 14px;
  color: var(--muted); background: color-mix(in srgb, var(--ink) 5%, transparent);
  border: 1px solid color-mix(in srgb, var(--line) 70%, transparent); white-space: nowrap;
}
.lang-code .name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.lang-code::after {
  content: ""; flex: none; width: 6px; height: 6px; border-right: 1.6px solid currentColor;
  border-bottom: 1.6px solid currentColor; transform: translateY(-2px) rotate(45deg);
}
.lang-wrap select.lang { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; padding: 0; font-size: 16px; }
.lang-wrap:hover .lang-code { color: var(--ink); border-color: color-mix(in srgb, var(--ink) 22%, transparent); }
.lang-wrap:focus-within .lang-code { outline: 2px solid var(--accent-text); outline-offset: 1px; }
header nav a { white-space: nowrap; }
/* And the same header, tightened (owner, 22 Sep 2026)
   ---------------------------------------------------
   Measured on the page rather than guessed at: at 320 points — an iPhone SE, a small
   Android — the header stood 170 pixels tall and took FOUR lines, and it is sticky, so it
   ate half the screen on every scroll. At 390 it was 96. It is 72 now, in two clean lines
   at every width from 320 up, in every language including Polish and Arabic, with nothing
   overflowing sideways.

   Only sizes change: the same links, the same order, the language still named in full the
   way he asked for on 21 September. Nothing is hidden behind a menu, because a shop whose
   navigation is a hamburger has hidden Pro Store from the person most likely to want it. */
@media (max-width: 620px) {
  header { padding-top: 5px; padding-bottom: 5px; gap: 10px; margin-bottom: 2px; }
  /* As big as the line will carry with the two nav lines beside it. */
  header .logo .wordmark { height: 40px; }
  /* The page's own line-height is 1.6 — right for a paragraph, and eight wasted pixels on
     a one-word link. A nav line is a line, not prose. */
  header nav a { font-size: 12px; padding: 4px 5px; line-height: 1.2; }
  /* One pixel more than the links' padding, because the pill carries a border and they do
     not: without it the language sat two pixels above the words beside it. */
  .lang-code { font-size: 12px; padding: 4px 8px; gap: 5px; line-height: 1.2; }
  /* The country in brackets goes: "Français", not "Français (Canada)". */
  .lang-code .qualifier { display: none; }
  /* Never trimmed. "Bahasa Melayu" is the name of the language somebody reads in, and
     "Bahasa Mel…" is not (owner, 22 Sep 2026). It has the room now: it shares the first
     line with the wordmark instead of a line with four links. */
  .lang-code .name { white-space: nowrap; }
  .lang-code::after { flex: none; }
}
/* The narrow end, where the wordmark and the nav are competing for the same line. */
@media (max-width: 380px) {
  /* The same 16 the column uses, so the wordmark starts where the cards start. */
  header { padding-left: 16px; padding-right: 16px; gap: 6px; }
  header .logo .wordmark { height: 34px; }
  header nav a { font-size: 12px; padding: 4px 5px; }
  .lang-code { font-size: 12px; padding: 3px 6px; }
}
/* The narrowest screens still sold, and the longest navigation we have: Malay says "Cara
   ia berfungsi" where English says "How it works", and at 320 points that was the last
   language taking a third line. */
@media (max-width: 340px) {
  header .logo .wordmark { height: 29px; }
  /* Malay is the longest navigation we have — "Cara ia berfungsi" for "How it works" —
     and at 320 points it was the one language taking a third line. */
  header nav a { font-size: 11px; padding: 4px 3px; }
  .lang-code { font-size: 11px; padding: 3px 5px; gap: 4px; }
}

@media (max-width: 560px) {
  /* Two pixels between the rows, deliberately: with none, a link on the top row and the
     one under it share an edge, and a thumb aiming for Help lands on How it works. The
     row only happens now where a language is too long for one line of four buttons.

     THE FORCED BREAK IS GONE (owner, 24 Sep 2026). `header nav::after` broke the row after
     the second item and `:nth-child(n+3)` sent the rest below it, which is what gave the
     phone its two tidy lines while the LANGUAGE was the nav's fifth item. The language
     stands on its own line beside the wordmark now and the navigation has the whole width
     of the phone to itself, so the break would only cost a third line: measured in Russian
     at 390, keeping it made the header three lines where it had always been two. */
  header nav { row-gap: 2px; column-gap: 0; }
  .lang-code { margin-left: 2px; max-width: 132px; }
}

/* THE NAVIGATION IS FIVE BUTTONS (About joined on 26 Sep 2026), STANDING IN THE MIDDLE (owner, 24 Sep 2026)
   ===========================================================================
   "I wouldn't mind that home page looks like how ChatGPT offers it … Maybe you can put
   that pro store, how it works, log in, help in all these buttons. Even in the middle of
   the screen as it's in ChatGPT."

   NOTHING IS ADDED AND NOTHING IS MOVED. These are the same four links, in the same order,
   in the same <nav> the server and the shop have both written for weeks; they are given the
   shape this site already gives a thing you press — the chip the duration control wears,
   the pill the language wears at the end of this very row. Four grey words that read as
   small print are four buttons now. A second copy of them in the middle of the page would
   be the clutter he has objected to twice ("Destinations & prices" and "Shop" side by
   side), so the row itself is what moves to the middle.

   And it is the middle of the WINDOW, not the middle of what is left over beside the logo:
   the header becomes three columns, the wordmark keeps the left one, the buttons take the
   centre one and the LANGUAGE takes the right one. `1fr auto 1fr` is what makes those two
   agree.

   THE TWO OUTER EDGES ARE THE BANNER'S OWN (owner, 24 Sep 2026): "make so that the English
   button is to the right, also aligned to the right side of the banner as logo is aligned
   to the left side of the banner." The language used to be the fifth item inside the
   navigation, which centred the pill and the buttons TOGETHER and so pushed the buttons
   left of the middle by half a pill — measured at 1440, their midpoint sat at 670 against a
   window midpoint of 720. Nothing needs a number: the header pads itself back to `--page`,
   which IS the column the banner is drawn in, so `justify-self: start` and `justify-self:
   end` land on the banner's own two edges.

   Below 761 points nothing moves. The phone header was measured into two tight lines at
   every width from 320 up, in eighteen languages, and centring it there would buy nothing
   and cost a line. The buttons only take the air a border and a fill need, which is a few
   pixels of padding and a gap where `column-gap: 0` used to be safe for bare words. */
header nav a {
  border: 1px solid color-mix(in srgb, var(--ink) 13%, transparent);
  background: color-mix(in srgb, var(--card) 92%, transparent);
  color: var(--ink); font-weight: 650;
}
header nav a:hover {
  background: color-mix(in srgb, var(--ink) 7%, transparent);
  border-color: color-mix(in srgb, var(--ink) 28%, transparent);
}
/* The page you are on keeps the accent it already had, now as a filled button among
   outlined ones rather than the one coloured word in a line of grey. */
/* The page you are on is FOREST on every page (owner, 24 Sep 2026: "consistent, the entire
   style"). `--accent` is whatever the Studio's theme is set to — coral today on the shop's
   own pages — so the same button was forest on the home page and coral on the Pro Store. */
header nav a.here, header nav a.here:hover {
  background: var(--forest); border-color: var(--forest); color: #FFF;
}
@media (min-width: 761px) {
  header { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); }
  header > .logo { grid-column: 1; justify-self: start; }
  header > nav { grid-column: 2; justify-self: center; gap: 8px; flex-wrap: nowrap; }
  header > .lang-wrap { grid-column: 3; justify-self: end; }
  header nav a { padding: 9px 15px; }
}
/* ONE LINE WHEREVER THE THREE FIT (owner, 24 Sep 2026: "these four buttons have to be
   BETWEEN logo and English button"). Between 600 and 760 points the three zones keep to
   one line with the buttons made compact — measured in the longest languages we publish
   (Punjabi, Russian, Malay) at 600: wordmark, four buttons and the language all on the
   line with room to spare. Below 600 nothing can hold them on one line and the header
   takes two, never more (the rule after this one). */
@media (min-width: 600px) and (max-width: 760px) {
  header { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; column-gap: 10px; align-items: center; }
  header > .logo { grid-column: 1; justify-self: start; }
  /* Five buttons (About joined them, 26 Sep 2026): they wrap into a second centred row in the
     longest languages rather than being cut off at the edge. */
  header > nav { grid-column: 2; justify-self: stretch; justify-content: center; flex-wrap: wrap; gap: 5px; min-width: 0; }
  header > nav::-webkit-scrollbar { display: none; }
  header > .lang-wrap { grid-column: 3; justify-self: end; }
  header nav a { font-size: 12.5px; padding: 6px 10px; line-height: 1.2; }
  .lang-code { font-size: 12.5px; padding: 6px 10px; }
  .lang-code .qualifier { display: none; }
}
/* THE PHONE KEEPS TWO LINES, AND GETS THE SAME THREE ZONES (owner, 24 Sep 2026)
   =============================================================================
   A phone has no room for a wordmark, four buttons and a language on one line, so the
   three zones become two rows rather than three columns: the wordmark on the left of the
   first line and the language hard right on the same line — his two edges — and the four
   buttons on the line under them, in the middle. Same three things, same three places,
   stacked because the window is 390 points wide.

   It is the same two lines the header has had since 22 September, and it had to be
   rebuilt to stay that way. With the language moved out of the navigation and standing
   beside it, the navigation lost a language's width off its FIRST line: measured in
   Russian at 390, "Pro Store · Как это работает" no longer fitted and the header went to
   three lines. Given the whole width of the phone, the four buttons fit on one line in
   every language we publish. */
@media (max-width: 599px) {
  /* ONE LEVEL, ALWAYS (owner, 24 Sep 2026: "these buttons are ALWAYS on the same level as on
     the bigger screen. If it doesn't fit — make two lines of these 4 buttons — but still on
     the same level between logo and English button"). So the header is the same three zones
     on a phone as on a laptop — wordmark, buttons, language, side by side on one line — and
     the middle zone folds its four buttons into two lines of two when the line cannot hold
     them in a row, with the wordmark and the language centred beside the pair of lines.
     Nothing ever drops under the wordmark. The two-row header that stood here was sent back. */
  header {
    display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center; column-gap: 8px; row-gap: 0;
  }
  header > .logo { grid-column: 1; grid-row: 1; }
  /* FIVE BUTTONS since About joined them (owner, 26 Sep 2026), so the middle zone flows them
     into centred rows — as many to a row as the words allow — instead of a fixed grid of
     two, which would stack five into three rows everywhere. */
  header > nav {
    grid-column: 2; grid-row: 1; min-width: 0;
    display: flex; flex-wrap: wrap; justify-content: center;
    column-gap: 5px; row-gap: 5px;
  }
  header > nav > a { min-width: 0; text-align: center; overflow: hidden; text-overflow: ellipsis; }
  header > .lang-wrap { grid-column: 3; grid-row: 1; justify-self: end; }
  /* The middle zone needs every pixel on a phone: a smaller wordmark and a tighter language
     pill give the four buttons the room to keep their whole words. */
  header { column-gap: 6px; }
  header .logo .wordmark { height: 34px; }
  .lang-code { padding: 4px 7px; }
}
/* Smaller words before shorter words: the sizes step down with the screen so that every
   language we publish keeps its whole labels — measured: English, Russian and Filipino
   whole at 390, English and Russian whole at 320. */
@media (max-width: 430px) { header nav a { font-size: 11px; padding: 4px 6px; } .lang-code { font-size: 11.5px; padding: 4px 6px; } }
@media (max-width: 360px) { header nav a { font-size: 10.5px; padding: 4px 5px; } .lang-code { font-size: 11px; padding: 3px 5px; } header { column-gap: 5px; } }
@media (max-width: 340px) { header .logo .wordmark { height: 30px; } header nav { column-gap: 4px; } }
/* The phone header, with the air the borders ask for and no more — tighter since the row
   became five buttons (About, 26 Sep 2026), so that most languages still fold into two
   rows at 390 points. */
@media (max-width: 620px) {
  header nav { column-gap: 5px; row-gap: 4px; }
  header nav a { padding: 4px 8px; }
}
@media (max-width: 430px) { header nav { column-gap: 4px; } header nav a { padding: 4px 6px; } }
@media (max-width: 380px) { header nav { column-gap: 4px; } header nav a { padding: 3px 5px; } }
@media (max-width: 340px) { header nav { column-gap: 3px; } header nav a { padding: 3px 4px; font-size: 10px; } }

/* =========================================================================================
   THE DESTINATION PAGE, REDESIGNED (owner's package, 23 September 2026)
   =========================================================================================
   The server now writes the editorial vocabulary — hero split, plan cards, the forest
   benefit band, the split sections — with a base class first and an `ed-` hook second, so
   the page works before any of this loads and gets its shape from here. Everything below
   is additive: no existing selector changes meaning, and nothing here can reach the home
   page's `.unlimited-hero` banner, which keeps the look and the behaviour it has.
   ========================================================================================= */

:root {
  /* The reference draws its cards at 28px. Ours is 16 and is worn by every row, chip,
     input and sheet in the application, so it stays where it is and the generous corner
     gets its own token, used only on the editorial surfaces below. */
  --radius-lg: 28px;

  /* THE DEEP-FOREST BAND.
     The kit had a forest and a lime but no surface that flips the text to ivory, which is
     the one thing the benefit band needs. `--accent` cannot do it: the Studio overwrites
     that per theme (it is coral today), and a band that changes colour with the theme
     cannot promise contrast. These are fixed, and measured: ivory on forest is 13.9:1,
     lime on forest 11.4:1, soft ivory on forest 8.6:1. */
  --band: var(--forest);
  --on-band: #F4F2E8;
  --on-band-soft: #C3D2C6;
  --on-band-rule: rgba(244, 242, 232, .22);

  /* The price chip. `.pill` is washed with the accent, so on a coral theme the price sat
     in a pink capsule; the shelf's own chip is the brand's lime over the page's paper. */
  --chip-lime: color-mix(in srgb, var(--lime) 40%, var(--bg));
  --panel-sage: color-mix(in srgb, var(--forest) 7%, var(--bg));
}

/* Every picture in these sections is bound by its column. This is deliberately NOT the
   global `img { width: 100% }` the reference uses: that stylesheet dresses six pictures,
   this one dresses an application — flags, QR codes, store badges, avatars and screenshots
   all size themselves today, and a global rule would resize them all at once with no way
   to measure the blast radius in one pass. The markup already carries `band-art` on every
   editorial image; this is the belt to that pair of braces. */
.ed-hero img, .ed-section img { max-width: 100%; height: auto; }
/* `.band-art` carries the standing vertical margin it needs on /how-it-works, where the
   art sits between paragraphs. Inside a frame it would show as a sage rim, so it is the
   frame that spaces these, not the picture. */
.ed-hero-art .band-art, .coverage-art .band-art, .story-art .band-art,
.setup-art .band-art, .benefit-band .band-art { margin: 0; }

/* The eyebrow is a filled capsule in the accent the Studio happens to be set to — coral
   today — which fights the forest-and-lime system these sections are built from. Here it
   is what the reference draws: a quiet forest line with a dot, and no dependence on a
   token that changes with the theme. */
.ed-hero .eyebrow, .ed-section .eyebrow {
  background: none; padding: 0; color: var(--forest);
  font-size: 11.5px; letter-spacing: .14em; gap: 9px;
}
.ed-hero .eyebrow::before, .ed-section .eyebrow::before {
  content: ""; width: 7px; height: 7px; border-radius: 50%; flex: none;
  background: color-mix(in srgb, var(--lime) 62%, var(--forest));
}

/* The arrow-suffixed inline action. The arrow is a mask rather than a character so that it
   tints with the text, never lands in the accessibility tree, and cannot be read aloud as
   "north east arrow" in the middle of a sentence. */
.text-link {
  display: inline-flex; align-items: center; gap: 9px;
  font-weight: 650; font-size: 14.5px; color: var(--ink); text-decoration: none;
  border-bottom: 1px solid currentColor; padding-bottom: 3px;
}
.text-link::after {
  content: ""; width: 15px; height: 15px; flex: none; background: currentColor;
  -webkit-mask: var(--arrow-ne) center / contain no-repeat;
  mask: var(--arrow-ne) center / contain no-repeat;
}
.text-link:hover { color: var(--accent-text); }
:root {
  --arrow-ne: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 17 17 7M8 7h9v9'/%3E%3C/svg%3E");
  --chev-down: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
}

/* --- the hero: words on the left, the picture beside them ------------------------------
   The complaint this answers, in the owner's words: "huge ass picture takes entire page"
   and "if you stretch the page and pictures stretch the text also has to stretch and
   everything has to be aligned". The picture is now a column, not a band: it shares the
   grid with the words, both start at the same line, and it keeps its own 16:9 — nothing is
   stretched and nothing is cropped. */
.hero.ed-hero {
  display: grid; grid-template-columns: 1fr 1fr;
  align-items: center; gap: clamp(26px, 3.6vw, 60px);
  padding: clamp(18px, 2.4vw, 34px) 0 6px;
}
.ed-hero-words { min-width: 0; }
.ed-hero .eyebrow { margin-bottom: 14px; }
.ed-hero h1 {
  margin: 0; max-width: 13ch;
  font-size: clamp(34px, 4.4vw, 56px); line-height: 1.05; letter-spacing: -.03em;
}
.ed-hero .lede { margin: 18px 0 0; max-width: 38ch; font-size: clamp(15.5px, 1.3vw, 18px); }
.ed-hero .pill.price-pill {
  display: inline-block; margin-top: 20px; padding: 8px 14px; font-size: 13px;
  background: var(--chip-lime); color: var(--forest); border: 0;
}
/* THE ACTIONS SIT IN THE MIDDLE OF THEIR OWN SPACE (owner, 24 Sep 2026) ------------------
   "It's too close to the top button… the button and new to eSIM precisely in the middle."
   The block above it is the lime price pill; below it, where the destination has operators,
   the kicker ("Verizon · AT&T · 5G"). It was 24px above and 10px below, so the button and
   the link were pressed up under the pill and stuck to the operators line.

   The two gaps are NOT set to the same number, because the two edges do not weigh the same.
   Above the block there are two solid filled shapes facing each other — the pill's lime
   rectangle and the button's dark one — and a filled edge reads as pushing into the gap, so
   it needs more clearance to look clear. Below it the neighbour is small grey text, which
   carries its own leading inside its line box (4px at this size, measured) and reads lighter
   than any edge. 30px above and 22px below measure unequal and look equal, which is what he
   asked for; the block is centred to the eye, not to the ruler.

   The space below lives on the kicker rather than as a margin under the block, because 187
   destinations have no operators line: there the block is the last thing in the column and
   a bottom margin would only make the column taller for nothing. */
.ed-hero .actions.ed-actions { margin-top: 30px; gap: 18px; row-gap: 12px; }
.ed-hero-note { margin: 15px 0 0; font-size: 12px; color: var(--muted); }
.ed-hero .kicker { display: block; margin-top: 22px; }
.ed-hero-art {
  min-width: 0; overflow: hidden; background: var(--panel-sage);
  border-radius: clamp(28px, 5vw, 76px) var(--radius-lg) var(--radius-lg) var(--radius-lg);
}
.ed-hero-art img { display: block; width: 100%; height: auto; }
.ed-hero-art.photo img { aspect-ratio: 16 / 10; object-fit: cover; }

/* The three things the shelf promises, between two rules. */
p.trust-row {
  display: flex; flex-wrap: wrap; justify-content: center; gap: 12px clamp(20px, 3.4vw, 50px);
  margin: clamp(28px, 3.4vw, 46px) 0 0; padding: 20px 0;
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
  font-size: 13px; color: var(--muted); text-align: center;
}
p.trust-row span { display: inline-flex; align-items: center; gap: 8px; }

/* --- section rhythm -------------------------------------------------------------------- */
.ed-section { margin-top: clamp(46px, 5.4vw, 84px); }
.ed-section-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: clamp(18px, 2.4vw, 32px); margin-bottom: clamp(20px, 2.2vw, 30px); flex-wrap: wrap;
}
.ed-section-head > div { min-width: 0; }
.ed-section-head h2 {
  margin: 0; font-size: clamp(26px, 3.1vw, 41px); line-height: 1.12; letter-spacing: -.028em;
}
.ed-section-head .lede { margin: 12px 0 0; font-size: clamp(14.5px, 1.2vw, 16.5px); }
.ed-section-head .text-link { margin-bottom: 4px; }

/* The duration control: one chip per length, each a button that switches the two cards in
   place (app.js, planSwitch). They were links to a page per length until 29 Sep 2026; those
   pages are gone. `.seg` cannot dress it — a capsule of eight would have to scroll sideways
   on a phone — so these are chips that wrap. The group stands where the <nav> it replaced
   stood (centred on its line, at the end of the heading), and a chip looks exactly as the
   link did, the grey wash of the header's links on hover included. */
.duration-links { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; justify-content: flex-end; }
.duration-links button {
  display: inline-flex; align-items: center; margin: 0; padding: 9px 16px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--card); color: var(--ink);
  font: inherit; font-size: 13.5px; font-weight: 600; line-height: inherit; white-space: nowrap; cursor: pointer;
}
.duration-links button:hover { border-color: color-mix(in srgb, var(--forest) 45%, var(--line)); background: color-mix(in srgb, var(--ink) 6%, transparent); }
.duration-links button.on, .duration-links button[aria-pressed="true"] {
  background: var(--forest); border-color: var(--forest); color: #FFF;
}
/* "All plans" after the last length (owner, 30 Sep 2026: "one more identical button … it has to
   be obvious, has to be visible"). The chip's own shape and size, so it reads as one more choice
   in the row; the lime wash and the arrow are what say it opens more than a length does. */
.duration-links a.all-plans {
  display: inline-flex; align-items: center; gap: 6px; margin: 0; padding: 9px 16px; border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--forest) 55%, var(--line)); background: var(--chip-lime); color: var(--forest);
  font-size: 13.5px; font-weight: 700; line-height: inherit; white-space: nowrap; text-decoration: none;
}
.duration-links a.all-plans:hover { background: color-mix(in srgb, var(--chip-lime) 80%, var(--forest)); }
.duration-links a.all-plans .chev { font-size: 12px; line-height: 1; }

/* --- the shelf ------------------------------------------------------------------------- */
.cols.two.plans-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(16px, 1.6vw, 23px); }
/* "Make these a bit smaller, maybe like 2/3 of their height so it looks better on smaller
   screens too" — the owner, 24 Sep 2026, about the two tier cards. Every sentence and every
   element stays; the height comes off the padding, the gaps, the headline and the button,
   in that order. The price is the one thing that does not shrink — he asked for prices to
   be bigger, and the card reads better when the number is the largest thing in it. */
.card.plan-card {
  border-radius: var(--radius-lg); padding: clamp(15px, 1.4vw, 20px);
  border: 1px solid color-mix(in srgb, var(--forest) 22%, var(--line));
  box-shadow: none; display: flex; flex-direction: column;
}
.card.plan-card.featured { border: 2px solid var(--forest); padding: clamp(14px, 1.4vw, 19px); }
/* The eyebrow pill never breaks its line, so in a language with long words the title row
   was the widest thing on the page and pushed the whole card past a 390px screen. Wrapping
   the row lets the pill drop under the title instead of widening the card. */
.plan-card-top { display: flex; align-items: center; justify-content: space-between; gap: 6px 12px; flex-wrap: wrap; margin-bottom: clamp(8px, .8vw, 11px); }
.plan-card-top h3 { margin: 0; min-width: 0; font-size: clamp(17.5px, 1.5vw, 21px); line-height: 1.2; letter-spacing: -.02em; }
.plan-label {
  display: inline-block; padding: 5px 10px; border-radius: 999px; white-space: nowrap;
  background: var(--chip-lime); color: var(--forest);
  font-size: 10px; line-height: 1.2; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
}
.plan-claim { margin: 0; font-size: clamp(20px, 1.6vw, 22.5px); font-weight: 650; letter-spacing: -.035em; line-height: 1.1; }
.plan-what { margin: 7px 0 0; font-size: 13.5px; line-height: 1.45; color: var(--muted); max-width: 44ch; }
.price-line { display: flex; align-items: baseline; gap: 8px; margin: clamp(10px, 1vw, 14px) 0 3px; flex-wrap: wrap; }
.price-line .price { font-size: clamp(34px, 3.3vw, 45px); font-weight: 650; letter-spacing: -.045em; line-height: 1.02; }
.price-line .price-term { font-size: 14px; color: var(--muted); }
.price-detail { margin: 0; font-size: 11.5px; line-height: 1.6; color: var(--muted); }
/* The speed conditions are the offer, not a footnote: they sit under their own rule, at
   reading size, in the card the price is in. The brief forbids hiding them. */
.speed-terms {
  margin-top: 8px; padding: 9px 0 10px; border-top: 1px solid var(--line);
  display: grid; gap: 2px; font-size: 12px; line-height: 1.4;
}
.speed-terms strong { font-weight: 700; color: var(--ink); }
.speed-terms span { color: var(--muted); }
.plan-card .cta { width: 100%; margin-top: auto; padding: 10px 18px; min-height: 44px; font-size: 15px; }
.plan-foot { margin: 7px 0 0; font-size: 10.5px; line-height: 1.45; color: var(--muted); text-align: center; }
/* The foot is three quiet links now — Package details, the FCC label, the phone check — in the
   foot's own size and colour, underlined only on hover (owner, 30 Sep 2026: "don't highlight
   these three buttons, make them the same font as they are now"). */
/* Beats `.ed-section a:not(…)`, which dresses every other link in these sections in forest green. */
.ed-section .plan-card .plan-foot a:not(.cta):not(.text-link):not(.row) { color: var(--muted); text-decoration: none; font-weight: 400; }
.ed-section .plan-card .plan-foot a:not(.cta):not(.text-link):not(.row):hover,
.ed-section .plan-card .plan-foot a:not(.cta):not(.text-link):not(.row):focus-visible { text-decoration: underline; color: var(--ink); }

/* THE SMALL FACTS BESIDE THE CARD'S OWN LINES (owner, 30 Sep 2026)
   "Using the space that we have" — each goes into the empty right-hand side of a line the card
   already had, in the size of the foot's small print, so the cards are no taller than they were:
   Hotspot included and Data only beside "Unlimited data", the networks beside the price, the IP
   beside the speed terms. On a phone the columns keep their places and only wrap their words. */
.plan-claim-row, .price-row, .speed-row { display: flex; justify-content: space-between; gap: 4px 12px; }
.plan-claim-row { align-items: flex-start; }
.plan-claim-row .plan-claim { flex: 1 1 auto; min-width: 0; }
.plan-points {
  list-style: none; margin: 1px 0 0; padding: 0; flex: none; max-width: 55%;
  display: grid; gap: 2px; justify-items: end; text-align: end;
  font-size: 11px; line-height: 1.3; color: var(--muted);
}
.plan-points li { display: flex; align-items: baseline; gap: 5px; }
.plan-points li[hidden] { display: none; }
.plan-points .pt-hotspot { color: var(--ink); font-weight: 600; }
.plan-points .pt-hotspot::before { content: "\2713"; color: var(--forest); font-weight: 800; }
.price-row { align-items: center; margin: clamp(10px, 1vw, 14px) 0 3px; }
.price-row .price-line { margin: 0; min-width: 0; }
.plan-net {
  flex: none; max-width: 50%; display: grid; gap: 1px; justify-items: end; text-align: end;
  font-size: 11px; line-height: 1.3; color: var(--muted);
}
.plan-net[hidden] { display: none; }
.plan-net span { overflow-wrap: anywhere; }
.plan-net span:first-child::before {
  content: ""; display: inline-block; width: 11px; height: 9px; margin-inline-end: 5px; vertical-align: -1px;
  background: linear-gradient(to top, currentColor 0 100%) 0 100% / 2px 35% no-repeat,
              linear-gradient(to top, currentColor 0 100%) 3px 100% / 2px 60% no-repeat,
              linear-gradient(to top, currentColor 0 100%) 6px 100% / 2px 80% no-repeat,
              linear-gradient(to top, currentColor 0 100%) 9px 100% / 2px 100% no-repeat;
  opacity: .8;
}
.speed-row { align-items: center; margin-top: 8px; border-top: 1px solid var(--line); }
.speed-row .speed-terms { margin-top: 0; border-top: 0; flex: 1 1 auto; min-width: 0; }
/* The IP keeps its line; the speed sentence beside it is what wraps. */
.plan-ip { flex: none; max-width: 60%; }
.card-ip { display: flex; flex-direction: column; align-items: flex-end; gap: 5px; }
.card-ip .chips { display: flex; align-items: center; justify-content: flex-end; flex-wrap: wrap; gap: 4px; }
.card-ip .chips .label { white-space: nowrap; }
.card-ip .chips .label { font-size: 11px; font-weight: 700; color: var(--muted); margin-inline-end: 2px; }
.card-ip .chips button, .card-ip .ipchip {
  display: inline-flex; align-items: center; margin: 0; padding: 3px 10px; min-height: 24px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--card); color: var(--ink);
  font: inherit; font-size: 11.5px; font-weight: 700; line-height: 1.2; cursor: pointer;
}
.card-ip .chips button:hover:not(:disabled) { border-color: color-mix(in srgb, var(--forest) 45%, var(--line)); }
.card-ip .chips button.on, .card-ip .ipchip.on { background: var(--forest); border-color: var(--forest); color: #FFF; }
.card-ip .chips button:disabled { cursor: default; }
@media (max-width: 520px) {
  .card-ip .chips { gap: 3px; }
  .card-ip .chips button, .card-ip .ipchip { padding: 3px 8px; }
}
.card-ip .sw { gap: 6px; font-size: 11.5px; font-weight: 700; white-space: nowrap; }
.card-ip .sw input, .card-ip .sw .track { width: 32px; height: 19px; }
.card-ip .sw .track::after { top: 2px; left: 2px; width: 15px; height: 15px; }
.card-ip .sw input:checked + .track { background: var(--forest); }
.card-ip .sw input:checked + .track::after { transform: translateX(13px); }
/* A switch with nothing to switch to still says the plan's IP — readable, not greyed out. */
.card-ip .sw.fixed { opacity: .8; color: var(--ink); }
.selection-note { margin: 16px 0 0; font-size: 12.5px; color: var(--muted); max-width: none; }

.every-plan { margin-top: 18px; }
/* "See All Plans" scrolls here: clear of the sticky header. */
#every-plan { scroll-margin-top: 84px; }
/* "ALL 114 USA PLANS" IS SEEN NOW (owner, 30 Sep 2026: "keep it as it is, just make it bigger
   or highlighted … because it's same color, you might miss it"). The same words, as a panel of
   their own: the lime of the chips' own "All plans", a larger title, and a round mark that
   turns when the fold opens, so it reads as the door to the rest of the shelf it is. */
.every-plan > summary {
  list-style: none; cursor: pointer; margin: 16px 0; padding: 16px 64px 16px 18px; position: relative;
  /* 18px, not the cards' 28: a bar this long with the cards' corner reads as a pill. */
  display: flex; flex-direction: column; gap: 4px;
  border-radius: 18px; background: var(--chip-lime);
  border: 1px solid color-mix(in srgb, var(--forest) 30%, transparent);
}
.every-plan > summary:hover { background: color-mix(in srgb, var(--chip-lime) 85%, var(--forest)); }
.every-plan > summary::-webkit-details-marker { display: none; }
.every-plan > summary .title { font-weight: 750; font-size: clamp(18px, 1.7vw, 21px); letter-spacing: -.02em; color: var(--forest); }
.every-plan > summary .title .count { font-variant-numeric: tabular-nums; }
.every-plan > summary .value { color: color-mix(in srgb, var(--forest) 75%, var(--muted)); font-size: 13.5px; }
.every-plan > summary .fold-mark {
  position: absolute; inset-inline-end: 16px; top: 50%; width: 34px; height: 34px; margin-top: -17px;
  border-radius: 50%; background: var(--forest); transition: transform .2s ease;
}
.every-plan > summary .fold-mark::after {
  content: ""; position: absolute; left: 50%; top: 45%; width: 9px; height: 9px;
  border: solid #FFF; border-width: 0 2.5px 2.5px 0; transform: translate(-50%, -50%) rotate(45deg);
}
.every-plan[open] > summary .fold-mark { transform: rotate(180deg); }
#plans { scroll-margin-top: 84px; }
.every-plan > .rows { margin: 0 0 18px; }
/* …and stops being a card once the shop has made it the picker.
   The server draws a shelf of links here and that shelf is a card. app.js re-parents those
   rows into `.rows-static` and builds the picker in their place — a segment, a strip of day
   chips, a card of sizes, the buy bar — so the card was left holding three more cards, each
   of them touching its inside edge. That is what put the controls hard against the line and
   made one column read as several widths. With the picker in it this is the column, not a
   surface: its children take the page's own gutter, exactly as the same picker does on the
   shop's own screens, where its host has never been anything but a plain div.
   `.rows-static` is the tell, and it exists only once the script has run: a page with no
   script keeps the card and the shelf of links inside it. */
.every-plan > .rows:has(> .rows-static) {
  background: none; border: 0; border-radius: 0; box-shadow: none; overflow: visible;
}

.card.pro-store {
  margin-top: 22px; border: 0; box-shadow: none; border-radius: var(--radius-lg);
  background: var(--panel-sage); padding: clamp(20px, 2vw, 26px);
  display: flex; align-items: center; justify-content: space-between; gap: 22px; flex-wrap: wrap;
}
.pro-store strong { font-size: 16px; }
.pro-store p { margin: 5px 0 0; font-size: 13.5px; color: var(--muted); }
.pro-store .cta { flex: none; }

/* --- the asymmetric splits -------------------------------------------------------------
   `.cols.two` is an equal grid; these three are not equal, and the artwork bleeds to the
   edge of its own column. Each ratio is the reference's. */
.ed-split { display: grid; align-items: center; gap: clamp(26px, 3.4vw, 64px); }
.ed-split > * { min-width: 0; }
.ed-split.coverage { grid-template-columns: .82fr 1.18fr; }
.ed-split.story { grid-template-columns: 1.05fr .95fr; }
.ed-split.faq-layout { grid-template-columns: .74fr 1.26fr; align-items: start; }
.ed-split h2 { margin: 0; font-size: clamp(26px, 3.1vw, 41px); line-height: 1.12; letter-spacing: -.028em; }
.ed-split .lede, .ed-split > div > p { margin: 16px 0 0; }
.ed-split .text-link { margin-top: 22px; }

.coverage-art, .story-art, .setup-art {
  overflow: hidden; border-radius: var(--radius-lg); background: var(--panel-sage);
}
.coverage-art img, .story-art img, .setup-art img { display: block; width: 100%; height: auto; }
.coverage-art .rows { border: 0; border-radius: 0; box-shadow: none; }

/* --- the forest band --------------------------------------------------------------------
   The section the owner pointed at when he said ours reads like a dissertation. Four white
   cards in a white box became four columns on one dark surface, each under its own rule,
   with the art beside the heading rather than over any text. */
.ed-section.benefit-band {
  background: var(--band); color: var(--on-band);
  border-radius: clamp(24px, 2.6vw, 32px);
  padding: clamp(26px, 3.2vw, 46px) clamp(22px, 3vw, 44px) clamp(28px, 3vw, 41px);
}
.benefit-head { display: flex; align-items: center; justify-content: space-between; gap: clamp(24px, 3.2vw, 45px); margin-bottom: clamp(26px, 3vw, 39px); }
.benefit-head > div { min-width: 0; }
.benefit-head h2 { margin: 0; color: var(--on-band); font-size: clamp(28px, 3.4vw, 46px); line-height: 1.08; letter-spacing: -.035em; max-width: 14ch; }
.benefit-head .lede { margin: 14px 0 0; color: var(--lime); font-size: clamp(16px, 1.5vw, 20px); max-width: 30ch; }
.benefit-band .benefit-art {
  flex: none; width: clamp(190px, 22vw, 270px); height: auto;
  border-radius: 24px; margin: 0;
}
.benefit-band .cols.two.benefit-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: clamp(20px, 2.2vw, 30px); }
.benefit-band .col.benefit {
  background: none; border: 0; border-top: 1px solid var(--on-band-rule);
  border-radius: 0; box-shadow: none; padding: clamp(16px, 1.7vw, 23px) 0 0;
}
.benefit-band .benefit h3 { margin: 0; color: var(--on-band); font-size: clamp(16px, 1.3vw, 18px); font-weight: 650; letter-spacing: -.012em; }
.benefit-band .benefit p { margin: 10px 0 0; color: var(--on-band-soft); font-size: 13px; line-height: 1.65; }

/* --- setup ------------------------------------------------------------------------------ */
/* The only picture on the page that is cropped, and deliberately: the three-phone drawing
   is 16:9 with a great deal of empty cream above and below it, which at this width is 628
   pixels of nothing — "banners that is like more empty white space than text". The band
   keeps the drawing's middle and loses the emptiness; nothing of the subject is cut. */
.setup-art img { aspect-ratio: 2.6; object-fit: cover; object-position: center; }
/* The markup keeps `steps` so the page reads as an ordered list before this file lands;
   that rule draws each step as a card with its own counter chip, which here would print a
   second number beside the one the server wrote. Inside the grid the card comes off and
   the counter with it. */
ol.steps.steps-grid > li.step { background: none; border: 0; border-radius: 0; box-shadow: none; padding: 0; color: inherit; font-size: inherit; }
ol.steps.steps-grid > li.step::before { content: none; }
ol.steps-grid { list-style: none; margin: clamp(20px, 2.2vw, 28px) 0 0; padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(20px, 2.6vw, 37px); }
.steps-grid .step { margin: 0; }
.step-number {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: 50%; margin-bottom: 13px;
  border: 1px solid color-mix(in srgb, var(--forest) 30%, var(--line));
  font-size: 11.5px; font-weight: 650;
}
.steps-grid .step h3 { margin: 0; font-size: clamp(17px, 1.5vw, 20px); letter-spacing: -.018em; }
.steps-grid .step p { margin: 9px 0 0; font-size: 13.5px; line-height: 1.65; color: var(--muted); max-width: 32ch; }
.steps-grid .step > a { display: inline-block; margin-top: 12px; font-size: 12.5px; font-weight: 600; text-underline-offset: 4px; }

/* --- questions -------------------------------------------------------------------------- */
.faq-intro .lede { margin: 16px 0 0; font-size: 14.5px; }
.faq-intro .text-link { margin-top: 20px; }
/* The destination FAQs are flat rows between rules, and they stay that way. `:not(.ask)`
   is what keeps them off the question cards above, which are printed from the same page
   builder into a `.faq-list` on /how-it-works: without it the two treatments tied on
   specificity and the browser took half of each. */
.faq-list > details:not(.ask) { border-bottom: 1px solid var(--line); padding: 17px 0; }
.faq-list > details:not(.ask):first-child { padding-top: 2px; }
.faq-list > details:not(.ask) > summary {
  list-style: none; cursor: pointer; display: flex; align-items: center; justify-content: space-between;
  gap: 15px; font-size: 15.5px; font-weight: 600; line-height: 1.45;
}
.faq-list > details:not(.ask) > summary::-webkit-details-marker { display: none; }
.faq-list > details:not(.ask) > summary::after {
  content: ""; width: 18px; height: 18px; flex: none; background: currentColor;
  -webkit-mask: var(--chev-down) center / contain no-repeat;
  mask: var(--chev-down) center / contain no-repeat;
  transition: transform .2s ease;
}
.faq-list > details:not(.ask)[open] > summary::after { transform: rotate(180deg); }
/* The editorial sections do not borrow the theme accent for their links. `--accent` is
   whatever the Studio is set to — coral today, 3.04:1 on this paper, which is under AA for
   text this size — and these sections are built out of the forest and the lime, which are
   fixed. 11.6:1. */
.ed-section a:not(.cta):not(.text-link):not(.row):not(.learn-card),
.ed-hero a:not(.cta):not(.text-link) { color: var(--forest); }
.faq-list > details:not(.ask) > p { margin: 13px 0 0; padding-right: 28px; font-size: 13.5px; line-height: 1.75; color: var(--muted); }

/* --- learn and close --------------------------------------------------------------------
   Flat, between rules, the way the reference draws them: four fifths of a white card here
   was empty, which is the "banners that is like more empty white space than text" the
   owner objected to. */
.ed-section.cols.two.learn-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(16px, 2vw, 25px); }
.card.learn-card {
  background: none; border: 0; box-shadow: none; border-radius: 0;
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
  padding: clamp(20px, 2.2vw, 27px) 0; padding-right: 44px; position: relative;
  display: block; text-decoration: none; color: inherit;
}
.learn-card .small-label { display: block; font-size: 10px; text-transform: uppercase; letter-spacing: .12em; color: var(--muted); margin-bottom: 9px; }
.learn-card h3 { margin: 0; font-size: clamp(18px, 1.7vw, 22px); letter-spacing: -.02em; }
.learn-card p { margin: 8px 0 0; font-size: 13px; color: var(--muted); }
.learn-card::after {
  content: ""; position: absolute; right: 4px; top: 50%; margin-top: -13px;
  width: 26px; height: 26px; background: currentColor;
  -webkit-mask: var(--arrow-ne) center / contain no-repeat;
  mask: var(--arrow-ne) center / contain no-repeat;
  transition: transform .2s ease;
}
.learn-card:hover::after { transform: translate(4px, -4px); }

/* The brand's lime at full strength is right for a chip and an icon and wrong for a band
   this size — it is the "acid color" the owner objected to. Softened toward the page's own
   paper it keeps the hue and stops shouting; forest on it measures 11.9:1. */
.ed-section.closing {
  background: color-mix(in srgb, var(--lime) 70%, var(--bg)); color: var(--forest); border-radius: var(--radius-lg);
  padding: clamp(26px, 3vw, 42px) clamp(24px, 3vw, 44px);
  display: flex; align-items: center; justify-content: space-between; gap: clamp(22px, 2.6vw, 35px); flex-wrap: wrap;
}
.closing h2 { margin: 0; color: var(--forest); font-size: clamp(25px, 2.8vw, 37px); line-height: 1.12; letter-spacing: -.03em; }
.closing .lede { margin: 11px 0 0; color: color-mix(in srgb, var(--forest) 78%, transparent); font-size: 14px; }
/* On lime, the themed accent button vibrates and its own label loses contrast; the
   reference puts the forest button here and so do we. */
.closing .cta { flex: none; background: var(--forest); color: #FFF; box-shadow: none; }
.closing .cta:hover { box-shadow: 0 12px 28px rgba(7, 61, 49, .32); }

/* --- narrower than a laptop --------------------------------------------------------------- */
@media (max-width: 900px) {
  .hero.ed-hero { grid-template-columns: 1fr; gap: 26px; }
  .ed-hero h1 { max-width: 16ch; }
  .ed-hero .lede { max-width: 46ch; }
  .ed-split.coverage, .ed-split.story, .ed-split.faq-layout { grid-template-columns: 1fr; }
  .ed-split.story .story-art { order: -1; }
  .benefit-head { flex-direction: column; align-items: flex-start; }
  .benefit-band .benefit-art { width: 100%; }
  .benefit-band .cols.two.benefit-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ed-section.cols.two.learn-grid { grid-template-columns: 1fr; gap: 0; }
  .card.learn-card { border-bottom: 0; }
  .card.learn-card:last-child { border-bottom: 1px solid var(--line); }
}
@media (max-width: 760px) {
  .cols.two.plans-grid { grid-template-columns: 1fr; }
  ol.steps-grid { grid-template-columns: 1fr; gap: 22px; }
  .steps-grid .step p { max-width: none; }
  .ed-section-head { align-items: flex-start; }
  .card.pro-store, .ed-section.closing { flex-direction: column; align-items: flex-start; }
  /* A full-width button sits exactly on the panel's content box, left edge to right edge,
     which reads as falling out of the field rather than sitting in it. The owner asked for
     the line "slightly brought inside of that white field" (24 Sep 2026), so it stretches
     and then steps back from both edges. Wide screens keep the button at its own width. */
  .card.pro-store > .cta, .ed-section.closing > .cta {
    width: auto; align-self: stretch; margin-inline: clamp(8px, 3vw, 16px);
  }
}
@media (max-width: 520px) {
  .benefit-band .cols.two.benefit-grid { grid-template-columns: 1fr; gap: 18px; }
  p.trust-row { justify-content: flex-start; gap: 10px 22px; font-size: 12.5px; }
}

/* --- the pieces the rebuilt How it works, About and home pages asked for ------------------
   Same vocabulary, five blocks that had no rules yet. */

/* "these banners don't have design" — the owner, about exactly this block. A heading and a
   sentence on the page's own paper is a paragraph; this is a panel: its own sage surface,
   the generous corner, and a mark beside the words so the eye knows it is an aside and not
   the next section. The mark is a mask, so it tints with the text and is never announced. */
:root {
  --check-circle: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='m8.5 12.2 2.4 2.4 4.6-4.9'/%3E%3C/svg%3E");
}
.ed-section.intro-band {
  display: flex; align-items: center; gap: clamp(18px, 2.2vw, 28px); flex-wrap: wrap;
  background: var(--panel-sage); border-radius: var(--radius-lg);
  padding: clamp(22px, 2.4vw, 32px) clamp(22px, 2.6vw, 36px);
}
.intro-band::before {
  content: ""; flex: none; width: clamp(30px, 3vw, 40px); height: clamp(30px, 3vw, 40px);
  background: var(--forest);
  -webkit-mask: var(--check-circle) center / contain no-repeat;
  mask: var(--check-circle) center / contain no-repeat;
}
.intro-band > div { flex: 1 1 320px; min-width: 0; }
.intro-band h2 { margin: 0; font-size: clamp(19px, 1.8vw, 23px); line-height: 1.2; letter-spacing: -.02em; }
.intro-band .lede { margin: 9px 0 0; font-size: 14px; max-width: 62ch; }
.intro-band .text-link { flex: none; }

/* A split with no modifier still has two columns to make. The named ones below override. */
.ed-split { grid-template-columns: .8fr 1.2fr; }
/* Every split starts at the top. Centred, a short heading floats in the middle of whatever
   the other column happens to be — on the home page's coverage that was 400px of nothing
   above "A whole region on one eSIM", which is "more empty white space than text" in
   miniature. The one exception is the story, where the words are meant to sit against the
   middle of the picture. */
.ed-split { align-items: start; }
.ed-split.story { align-items: center; }

/* The reference's support block: no card, two rules, the actions opposite the words. */
.ed-section.ed-split.support-block {
  display: flex; align-items: center; justify-content: space-between;
  gap: clamp(22px, 3vw, 40px); flex-wrap: wrap;
  padding: clamp(26px, 3vw, 38px) 0;
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
}
.support-block > div:first-child { flex: 1 1 320px; min-width: 0; }
.support-block h2 { margin: 0; font-size: clamp(24px, 2.6vw, 34px); line-height: 1.14; letter-spacing: -.028em; }
.support-block .lede { margin: 12px 0 0; font-size: 14px; }
.support-block .actions { display: flex; align-items: center; flex-wrap: wrap; gap: 14px 20px; }

/* Long-form argument: a short heading holding the left column, the prose set larger than
   body copy in the right, the way the reference reads. */
.ed-section.ed-split.editorial-copy { grid-template-columns: .8fr 1.2fr; align-items: start; gap: clamp(26px, 4vw, 80px); }
.editorial-copy h2 { margin: 0; }
.editorial-copy p { margin: 0; font-size: clamp(16px, 1.4vw, 19px); line-height: 1.65; color: var(--muted); max-width: 64ch; }
.editorial-copy p + p { margin-top: 18px; }
.editorial-copy .text-link { margin-top: 24px; }

/* A two-up that stays two-up. `.cols.two` is auto-fit, which is right for a pair and wrong
   for a quartet: at 1076px four values came out three across with one stranded underneath.
   `two-up` is the explicit variant for the markup to carry; the `:has` rule gives any
   `.cols.two` holding exactly four children the same 2x2 today, without waiting for it. The
   benefit band keeps its four columns — that rule is more specific. */
.cols.two.two-up,
.cols.two:has(> :last-child:nth-child(4)) { grid-template-columns: repeat(2, minmax(0, 1fr)); }

@media (max-width: 900px) {
  .ed-split { grid-template-columns: 1fr; }
  .ed-section.ed-split.editorial-copy { grid-template-columns: 1fr; }
}
@media (max-width: 760px) {
  .cols.two.two-up, .cols.two:has(> :last-child:nth-child(4)) { grid-template-columns: 1fr; }
  .ed-section.intro-band { align-items: flex-start; }
  .ed-section.ed-split.support-block { align-items: flex-start; }
}

/* --- the help centre, in the country pages' family (owner, 24 Sep 2026) -------------------
   "Overall help page is not bad. Just add more visuals. And make it so categories like
   'INSTALLING YOUR ESIM · 20 answers' is a line that only after you push on it, it sends you
   to page with those 20 questions. And when you tap any of those questions, the field
   unfolds with info, not just new page. And all back buttons and breadcrumbs. All logical
   and consistent." The pages are built from the editorial vocabulary above — `.hero.ed-hero`,
   `.ed-section`, `.eyebrow`, `details.ask`, `.support-block` — and these are the five pieces
   that had no rule yet: the search box, the topic tiles, the unfolded answer's body, the
   answer on its own page, and the way back. */

/* The search box: the page's own input and the dark pill, on one line where there is room. */
.help-search { display: flex; gap: 10px; margin-top: 26px; max-width: 560px; }
.help-search input {
  flex: 1 1 auto; min-width: 0; padding: 13px 18px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--card); color: var(--ink);
  font: inherit; font-size: 15.5px; box-shadow: var(--shadow-1);
}
.help-search input::placeholder { color: var(--muted); }
.help-search input:focus { outline: 2px solid var(--forest); outline-offset: 1px; }
.help-search .cta { flex: none; padding: 13px 22px; }
.help-search-hero { grid-template-columns: 1fr; }
.help-search-hero .ed-hero-words { max-width: 720px; }
.help-nothing { max-width: 60ch; }

/* The topics as tiles: the drawing on top, the name, the blurb, and the one line that opens
   the topic — "All 20 answers". Four to a row on a laptop, two on a tablet, one on a phone.
   Pressing anywhere on the tile opens the topic; nothing inside it unfolds. */
.help-topics { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: clamp(14px, 1.6vw, 22px); }
.help-topic {
  display: flex; flex-direction: column; min-width: 0; text-decoration: none; color: inherit;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-1); overflow: hidden;
  transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease;
}
.help-topic:hover { transform: translateY(-3px); box-shadow: var(--shadow-2); border-color: color-mix(in srgb, var(--forest) 28%, var(--line)); }
.help-topic-art { aspect-ratio: 16 / 10; background: var(--panel-sage); overflow: hidden; }
.help-topic-art img { display: block; width: 100%; height: 100%; object-fit: cover; margin: 0; }
.help-topic-words { display: flex; flex-direction: column; gap: 6px; flex: 1 1 auto; padding: 16px 18px 18px; }
.help-topic h3 { margin: 0; font-size: 17px; line-height: 1.25; letter-spacing: -.02em; }
.help-topic p { margin: 0; font-size: 13.5px; line-height: 1.5; color: var(--muted); }
.help-topic-count {
  margin-top: auto; padding-top: 12px; display: inline-flex; align-items: center; gap: 8px;
  font-size: 13px; font-weight: 650; color: var(--forest);
}
.help-topic-count::after {
  content: ""; width: 14px; height: 14px; flex: none; background: currentColor;
  -webkit-mask: var(--chev-down) center / contain no-repeat; mask: var(--chev-down) center / contain no-repeat;
  transform: rotate(-90deg); transition: transform .15s ease;
}
[dir="rtl"] .help-topic-count::after { transform: rotate(90deg); }
.help-topic:hover .help-topic-count::after { transform: rotate(-90deg) translateY(3px); }
[dir="rtl"] .help-topic:hover .help-topic-count::after { transform: rotate(90deg) translateY(3px); }

/* The unfolded answer: the card's own paragraphs, then the link to the answer's own page. */
details.ask .ask-body { padding: 0 0 16px; }
details.ask .ask-body p { margin: 0; max-width: 74ch; color: var(--muted); font-size: 14.5px; line-height: 1.65; }
details.ask .ask-body p + p { margin-top: 12px; }
details.ask .ask-body p.ask-own { margin-top: 14px; }
details.ask .ask-body .text-link { font-size: 13.5px; }

/* The answer on its own page: one white card of prose, at reading width, at reading size. */
.help-answer-section { margin-top: clamp(26px, 3vw, 40px); }
.help-answer {
  max-width: 76ch; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-1); padding: clamp(22px, 2.6vw, 36px) clamp(20px, 2.8vw, 40px);
}
.help-answer p { margin: 0; font-size: clamp(15.5px, 1.25vw, 17px); line-height: 1.7; color: var(--ink); }
.help-answer p + p { margin-top: 16px; }
.help-question-hero .ed-hero-words { align-self: center; }
.help-question-hero h1 { max-width: 20ch; font-size: clamp(28px, 3.4vw, 44px); }

/* The way back, one step up, at the foot of every page — a text link with the chevron the
   way back is drawn with everywhere else on the site. */
.help-back { margin: clamp(26px, 3vw, 40px) 0 0; }
.help-back-row { display: flex; flex-wrap: wrap; gap: 8px 28px; }
.help-back-row .help-back { margin-bottom: 0; }
.text-link.back::after { display: none; }
.text-link.back::before {
  content: ""; width: 15px; height: 15px; flex: none; background: currentColor;
  -webkit-mask: var(--chev-down) center / contain no-repeat; mask: var(--chev-down) center / contain no-repeat;
  transform: rotate(90deg);
}
[dir="rtl"] .text-link.back::before { transform: rotate(-90deg); }
/* The support block is the last thing on the page; the way back sits just above it. */
.help-back + .support-block, .help-back-row + .support-block { margin-top: clamp(30px, 3.4vw, 50px); }

@media (max-width: 900px) {
  .help-topics { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 480px) {
  .help-topics { grid-template-columns: 1fr; }
  .help-search { flex-direction: column; }
  .help-search .cta { align-self: stretch; }
}
/* The topic's name above a question is a way back to the topic — an eyebrow that happens to
   be a link, not a link dressed as an eyebrow. */
.help-question-hero .eyebrow a { color: inherit; text-decoration: none; }
.help-question-hero .eyebrow a:hover { text-decoration: underline; text-underline-offset: 3px; }

/* --- the account, and the two places a person agrees to the terms (owner, 24 Sep 2026) ----- */
/* "The licence-agree button gets the proper button treatment." A button with a class of
   `cta` still wore the browser's own button font and cursor; and the "I have read and agree"
   row on the sign-in screen was a bare checkbox beside grey text, which read as small print
   rather than the one thing the screen is waiting for. */
button.cta, button.btn { font: inherit; cursor: pointer; }
.terms-gate .cta { width: 100%; min-height: 52px; font-size: 16px; font-weight: 700; }
.terms-gate .ghost { margin-top: 10px; }
label.block.agree {
  align-items: center; padding: 14px 16px; border-radius: var(--radius);
  background: var(--card); border: 1px solid color-mix(in srgb, var(--forest) 24%, var(--line));
  box-shadow: var(--shadow-1); font-weight: 600; font-size: 15px; line-height: 1.4; cursor: pointer;
}
label.block.agree:has(input:checked) { border-color: var(--forest); background: color-mix(in srgb, var(--forest) 6%, var(--card)); }
label.block.agree input[type="checkbox"] { width: 22px; height: 22px; flex: none; accent-color: var(--forest); margin: 0; }
/* "See the plans" became two buttons, each to its own store. */
.acct-two { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 10px; }
.acct-two .btn { flex: 1 1 160px; justify-content: center; text-align: center; }
/* The way back stands above the account's head, where it stands on every other screen. */
.acct-head { margin-top: 6px; }
/* The drawing under the questions' introduction on the home page (24 Sep 2026). */
.faq-intro .faq-art { margin-top: 26px; border-radius: var(--radius-lg); overflow: hidden; background: var(--panel-sage); }
.faq-intro .faq-art img { display: block; width: 100%; height: auto; margin: 0; }
/* "Send this eSIM by email" on the order page (owner, 24 Sep 2026): one field, one button. */
.email-esim-row { display: flex; gap: 10px; margin-top: 12px; }
.email-esim-row .acct-input { flex: 1 1 auto; min-width: 0; }
.email-esim-row .cta { flex: none; }
@media (max-width: 480px) { .email-esim-row { flex-direction: column; } .email-esim-row .cta { align-self: stretch; } }

/* --- the buy bar's small facts and the sheets they open (owner, 30 Sep 2026) ------------------
   Under the total, as the phones have them under theirs: Hotspot included, then Package details
   and — for a plan sold into the United States — the FCC broadband label. Quiet links in the
   bar's small print; each opens a panel over the page (openSheet in app.js). */
.buybar .bar-facts {
  flex: 1 0 100%; margin: 8px 0 0; display: flex; flex-wrap: wrap; align-items: center; gap: 4px 16px;
  font-size: 12.5px; color: var(--muted);
}
.buybar .bar-facts .pt-hotspot { color: var(--ink); font-weight: 600; }
.buybar .bar-facts .pt-hotspot::before { content: "\2713"; color: var(--forest); font-weight: 800; margin-inline-end: 5px; }
.buybar .bar-facts a { color: var(--accent-text); font-weight: 600; text-decoration: none; }
.buybar .bar-facts a:hover { text-decoration: underline; }
@media (max-width: 760px) { .buybar .bar-facts { margin-top: 5px; gap: 3px 14px; font-size: 12px; } }

html.sheet-open { overflow: hidden; }
.sheet {
  position: fixed; inset: 0; z-index: 60; display: flex; align-items: center; justify-content: center;
  padding: 24px 16px; background: rgba(4, 26, 18, .45);
}
.sheet-panel {
  width: min(560px, 100%); max-height: min(86vh, 900px); display: flex; flex-direction: column;
  background: var(--card); color: var(--ink); border-radius: var(--radius-lg); box-shadow: 0 24px 60px rgba(0,0,0,.28); overflow: hidden;
}
.sheet-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 16px 18px 12px; border-bottom: 1px solid var(--line); }
.sheet-head h2 { margin: 0; font-size: 18px; letter-spacing: -.01em; }
.sheet-x {
  flex: none; width: 34px; height: 34px; border-radius: 50%; border: 0; cursor: pointer;
  background: color-mix(in srgb, var(--ink) 8%, transparent); color: var(--ink); font: inherit; font-size: 15px;
}
.sheet-body { padding: 6px 18px 18px; overflow-y: auto; -webkit-overflow-scrolling: touch; }
.sheet-body > .block { margin: 0; }
.sheet-row { padding: 12px 0; border-bottom: 1px solid var(--line); }
.sheet-row:last-child { border-bottom: 0; }
.sheet-row h3 { margin: 0 0 4px; font-size: 14px; }
.sheet-row p { margin: 0; font-size: 13.5px; line-height: 1.5; color: var(--muted); }
.fcc-label { margin: 14px 0 0; padding: 14px; border: 2px solid var(--ink); border-radius: 12px; }
.fcc-label > h3 { margin: 0; font-size: 16px; }
.fcc-label > p { margin: 3px 0 8px; }
.fcc-label .label-line { display: flex; justify-content: space-between; gap: 12px; padding: 7px 0; border-top: 1px solid var(--line); font-size: 13.5px; }
.fcc-label .label-line span:first-child { color: var(--muted); }
.fcc-label .label-line span:last-child { text-align: end; }
.fcc-label .label-line.strong span:last-child { font-weight: 750; }
.fcc-label .sheet-row h3 { font-size: 13px; }
.fcc-label .sheet-row p { font-size: 12.5px; }
.sheet-page-title { margin: 12px 0 4px; }
@media (max-width: 560px) {
  .sheet { align-items: flex-end; padding: 0; }
  .sheet-panel { width: 100%; max-height: 90vh; border-radius: var(--radius-lg) var(--radius-lg) 0 0; padding-bottom: env(safe-area-inset-bottom); }
}
