/* Page-level blocks. Everything here still reads its values from the tokens. */

/* Content boxes narrower than the 1220px page. The gutter goes on the longhands only: a
   `padding` shorthand here loads after base.css and would silently wipe .section,
   .section-tight and .section-end off every page that combines them. */
.narrow { max-width: 940px; margin: 0 auto; padding-left: var(--fx-gutter); padding-right: var(--fx-gutter); width: 100%; }
.wide { max-width: 1060px; margin: 0 auto; padding-left: var(--fx-gutter); padding-right: var(--fx-gutter); width: 100%; }
.checkout { max-width: 560px; margin: 0 auto; padding-left: var(--fx-gutter); padding-right: var(--fx-gutter); width: 100%; }
.faq-section { max-width: 840px; margin: 0 auto; padding: clamp(56px, 6vw, 88px) var(--fx-gutter); width: 100%; }

.section-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 24px;
  margin-bottom: 28px;
}

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

.loading { display: grid; place-items: center; padding: 40px 0; color: var(--fx-ink2); }
.loading .spinner { width: 22px; height: 22px; }

.empty {
  display: grid;
  justify-items: center;
  gap: 12px;
  padding: 24px;
  border: 1px dashed var(--fx-border);
  border-radius: var(--fx-r-card);
}

.avatar {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--fx-cyansoft);
  color: var(--fx-cyanink);
  display: inline-grid;
  place-items: center;
  font-size: 12px;
  font-weight: 600;
  flex-shrink: 0;
}

.avatar.md { width: 36px; height: 36px; font-size: 14px; }
.avatar.big { width: 46px; height: 46px; font-size: 16px; }

.flag { line-height: 1; flex-shrink: 0; }
.region-mark { border-radius: 50%; display: block; flex-shrink: 0; }

/* The inverted panels share one soft cyan wash. Named apart from the button's `.glow`,
   which is a cyan drop shadow — the two used to collide and stretch the header CTA. */
.panel-glow {
  position: absolute;
  inset: 0;
  background-image: radial-gradient(circle at 86% 12%, rgba(8, 181, 209, .24), transparent 55%);
  pointer-events: none;
}

.bullet { display: flex; align-items: flex-start; gap: 9px; }
.bullet-dot { width: 5px; height: 5px; border-radius: 50%; background: var(--fx-cyan); flex-shrink: 0; margin-top: 8px; }
.bullet-dot.ok { background: var(--fx-ok); }
.bullet-dot.warn { background: var(--fx-warn); }
.bullet-dot.err { background: var(--fx-err); }

.steps { display: grid; gap: 16px; }
.steps li { display: flex; gap: 13px; align-items: flex-start; }

.step-badge {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--fx-cyansoft);
  color: var(--fx-cyanink);
  display: grid;
  place-items: center;
  font-size: 12px;
  font-weight: 600;
  flex-shrink: 0;
}

.spec-row { display: flex; align-items: center; justify-content: space-between; gap: 14px; font-size: 14px; }

/* ---------- hero ---------- */

.hero {
  position: relative;
  overflow: hidden;
  background: var(--fx-surface);
  border-bottom: 1px solid var(--fx-border);
}

.hero-grid {
  position: absolute;
  inset: 0;
  background-image: linear-gradient(var(--fx-grid) 1px, transparent 1px), linear-gradient(90deg, var(--fx-grid) 1px, transparent 1px);
  background-size: 64px 64px;
  mask-image: radial-gradient(120% 90% at 60% 10%, #000 20%, transparent 78%);
  -webkit-mask-image: radial-gradient(120% 90% at 60% 10%, #000 20%, transparent 78%);
  pointer-events: none;
  /* --sy is written by hero.js on scroll; the plane drifts up as the page moves. */
  transform: translateY(calc(var(--sy, 0) * -40px));
}

.hero-inner {
  position: relative;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
  gap: clamp(32px, 5vw, 56px);
  align-items: center;
  padding-top: clamp(48px, 7vw, 104px);
  padding-bottom: clamp(56px, 6vw, 88px);
}

/* Pointer parallax. hero.js writes --px/--py (-.5….5 from the hero's centre) and --sy (0…1 from
   scroll) onto .hero, and these are the only readers. Multipliers are the prototype's. */
[data-globe] { transform: translate3d(calc(var(--px, 0) * -12px), calc(var(--py, 0) * -12px), 0); }
.float-card { transition: transform .12s linear; }
.float-stop { transform: translate3d(calc(var(--px, 0) * 34px), calc(var(--py, 0) * 26px - var(--sy, 0) * 30px), 0); }
.float-note { transform: translate3d(calc(var(--px, 0) * 52px), calc(var(--py, 0) * 40px - var(--sy, 0) * 54px), 0); }
.float-live { transform: translate3d(calc(var(--px, 0) * -40px), calc(var(--py, 0) * -30px + var(--sy, 0) * 24px), 0); }
.float-usage { transform: translate3d(calc(var(--px, 0) * -60px), calc(var(--py, 0) * -46px + var(--sy, 0) * 44px), 0); }

/* The sticky header would otherwise cover the heading of whatever we scroll to. */
#popular, #how, #install, #device, #support { scroll-margin-top: calc(var(--fx-header) + 14px); }

.hero-copy { min-width: 0; position: relative; z-index: 2; }
.hero-copy .h1 { margin: 22px 0 18px; text-wrap: balance; }
.hero-sub { font-size: clamp(16px, 1.4vw, 18px); line-height: 1.55; color: var(--fx-ink2); margin-bottom: 30px; max-width: 30em; text-wrap: pretty; }

.hero-search { position: relative; max-width: 520px; }

.search-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  height: 60px;
  padding: 0 8px 0 18px;
  background: var(--fx-surface);
  border: 1px solid var(--fx-border);
  border-radius: 14px;
  box-shadow: var(--fx-shadow);
  transition: border-color var(--fx-fast) ease;
}

.search-bar:focus-within { border-color: var(--fx-cyan); }
.search-bar i { font-size: 20px; color: var(--fx-ink2); }

.search-bar input {
  flex: 1;
  min-width: 0;
  height: 100%;
  border: 0;
  background: none;
  font-size: 16px;
  color: var(--fx-ink);
}

.search-bar input::placeholder { color: var(--fx-ink2); }
.search-bar input::-webkit-search-cancel-button { display: none; }
/* The button is 44px inside a 60px bar, so it has to centre rather than stretch. */
.search-bar .btn { align-self: center; }

.search-results {
  position: absolute;
  top: 68px;
  left: 0;
  right: 0;
  z-index: 30;
  background: var(--fx-surface);
  border: 1px solid var(--fx-border);
  border-radius: 14px;
  box-shadow: var(--fx-shadow-lift);
  overflow: hidden;
  animation: fxUp var(--fx-base) var(--fx-ease-out) both;
}

.search-row {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 12px 16px;
  text-align: left;
}

.search-row + .search-row { border-top: 1px solid var(--fx-border); }
.search-row:hover { background: var(--fx-bg); }

.hero-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; }
.hero-chips .chip { height: 36px; }
.hero-chips .chip:hover { transform: translateY(-1px); }

.hero-globe { min-width: 0; display: grid; justify-items: center; }

/* Stacked hero. `.hero-inner` is auto-fit minmax(340px, 1fr), which drops to one column near
   750px on its own — pinning the column count here means the wrap point and the centring can
   never drift apart if the gap or the track size is ever tuned. */
@media (max-width: 760px) {
  .hero-inner { grid-template-columns: 1fr; }
  .hero-copy { text-align: center; }
  .hero-sub, .hero-search { margin-inline: auto; }
  .hero-chips { justify-content: center; }

  /* The search keeps its own alignment: a centred placeholder next to a leading icon reads as
     a mistake, and the results underneath are a list. */
  .search-bar, .search-results { text-align: left; }
}
.globe-box { position: relative; width: 100%; max-width: 560px; }
.globe-box svg { width: 100%; height: auto; display: block; }

.float-card {
  position: absolute;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 15px;
  background: var(--fx-surface);
  border: 1px solid var(--fx-border);
  border-radius: 14px;
  box-shadow: var(--fx-shadow);
  white-space: nowrap;
}

.float-stop { top: 4%; left: -2%; padding: 13px 16px; box-shadow: var(--fx-shadow-lift); }
.float-note { bottom: 18%; left: 2%; }
.float-live { top: 20%; right: 14%; background: var(--fx-deep); border-color: rgba(255, 255, 255, .08); padding: 13px 16px; box-shadow: var(--fx-shadow-lift); }
.float-usage { bottom: 8%; right: 2%; display: block; }

/* ---------- trust strip ---------- */

.trust { background: var(--fx-surface); border-bottom: 1px solid var(--fx-border); overflow: hidden; }

.trust-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 14px 28px;
  padding-top: 18px;
  padding-bottom: 18px;
}

.trust-item {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 14px;
  font-weight: 500;
  color: var(--fx-ink2);
  white-space: nowrap;
}

.trust-item i { font-size: 18px; color: var(--fx-cyan); }

.trust-marquee { padding: 18px 0; }

.trust-track {
  display: flex;
  width: max-content;
  gap: 28px;
  padding-right: 28px;
  animation: fxMarquee 22s linear infinite;
}

@media (prefers-reduced-motion: reduce) {
  .trust-marquee { overflow-x: auto; }
  .trust-track { animation: none; padding-left: var(--fx-gutter); }
}

/* ---------- destinations ---------- */

.tabs-scroll { overflow-x: auto; padding-bottom: 4px; margin-bottom: 22px; }
.tabs-scroll::-webkit-scrollbar { display: none; }
.tabs-scroll { scrollbar-width: none; }

.dest-grid { gap: var(--fx-gap); }

/* Sits one layout gap under the grid so it reads as the grid's last row. Empty when the
   whole list is already on screen — the host element stays put so a repaint has a target. */
.dest-more { display: grid; justify-items: center; gap: 8px; margin-top: var(--fx-gap); }
.dest-more:empty { display: none; }

.dest-row {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 16px 18px;
  transition: transform var(--fx-base) ease, box-shadow var(--fx-base) ease, border-color var(--fx-base) ease;
  background: var(--fx-surface);
  border: 1px solid var(--fx-border);
  border-radius: var(--fx-r-card);
  color: inherit;
  transition: border-color var(--fx-fast) ease;
}

/* `color: inherit` is load-bearing: base.css's `a:not(.btn):hover` would recolour the whole row. */
.dest-row:hover { transform: translateY(-2px); box-shadow: var(--fx-shadow); border-color: var(--fx-cyan); color: inherit; }
.dest-name { display: block; font-size: 18px; font-weight: 600; font-family: var(--fx-display); letter-spacing: -.02em; text-wrap: pretty; }
.dest-sub { display: block; margin-top: 3px; font-size: 13px; color: var(--fx-ink2); }
/* One 40px slot for the leading mark, so names line up whichever tab is open. The region mark
   is an <img> already sized to 40 by regionMark(); only the flag glyph needs the box. */
.dest-row .flag { width: 40px; height: 40px; display: grid; place-items: center; }

/* ---------- planner ---------- */

.planner {
  position: relative;
  overflow: hidden;
  background: var(--fx-deep);
  border-radius: var(--fx-r-hero);
  padding: clamp(28px, 4vw, 52px);
}

.planner-inner {
  position: relative;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: clamp(28px, 4vw, 56px);
  align-items: start;
}

.planner-steps { display: grid; gap: 8px; }

.planner-step {
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 12px 14px;
  border: 1px solid var(--fx-white-10);
  border-radius: 14px;
  background: rgba(255, 255, 255, .03);
  text-align: left;
  transition: border-color var(--fx-fast) ease;
}

.planner-step:hover,
.planner-step.on { border-color: rgba(8, 181, 209, .5); }

.planner-step-n {
  width: 28px;
  height: 28px;
  border-radius: 9px;
  display: grid;
  place-items: center;
  font-size: 12px;
  font-weight: 600;
  background: var(--fx-white-07);
  color: var(--fx-deepink2);
  flex-shrink: 0;
}

.planner-step-n.on { background: var(--fx-cyan); color: var(--fx-on-cyan); }
.planner-step-n.done { background: var(--fx-cyansoft); color: var(--fx-cyanink); }

.planner-progress { display: block; flex: 1; max-width: 200px; height: 4px; border-radius: 99px; background: var(--fx-white-12); }
.planner-progress span { display: block; height: 100%; border-radius: 99px; background: var(--fx-cyan); transition: width var(--fx-slow) var(--fx-ease); }

.planner-panel { border-radius: 18px; padding: clamp(20px, 2.6vw, 28px); box-shadow: var(--fx-shadow-lift); }

.planner-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 8px; max-height: 330px; overflow-y: auto; }

.planner-dest,
.planner-opt {
  display: flex;
  align-items: center;
  border: 1px solid var(--fx-border);
  border-radius: 13px;
  background: var(--fx-surface);
  transition: border-color var(--fx-fast) ease, background-color var(--fx-fast) ease;
}

/* The two rows share a shell but not a size — the prototype gives each its own. */
.planner-dest { gap: 11px; min-height: 56px; padding: 9px 13px; }
.planner-opt { gap: 12px; padding: 14px 15px; }

.planner-dest:hover,
.planner-opt:hover { border-color: var(--fx-cyan); }
.planner-opt i { font-size: 19px; color: var(--fx-cyanink); }
.planner-data { display: grid; gap: 9px; }

.planner-days { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 10px; }

.planner-day {
  display: grid;
  gap: 4px;
  justify-items: start;
  text-align: left;
  align-content: start;
  min-height: 72px;
  padding: 12px;
  border: 1px solid var(--fx-border);
  border-radius: 13px;
  background: var(--fx-surface);
  transition: border-color var(--fx-fast) ease;
}

.planner-day:hover { border-color: var(--fx-cyan); }

.planner-back {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 44px;
  margin-top: 18px;
  transition: color var(--fx-fast) ease;
}

/* `.muted` on the label would otherwise outrank the colour inherited from the button. */
.planner-back:hover,
.planner-back:hover .muted { color: var(--fx-cyanink); }

/* ---------- planner result ---------- */

/* Identity row and spec grid sit between two hairlines, as in the prototype. */
.planner-id { padding-bottom: 18px; border-bottom: 1px solid var(--fx-border); }
.planner-country { font-size: 22px; letter-spacing: -.02em; }

.planner-specs {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: 14px;
  padding: 18px 0;
  border-bottom: 1px solid var(--fx-border);
}

.planner-spec { display: grid; gap: 4px; }
.planner-spec-v { font-size: 16px; font-weight: 600; color: var(--fx-ink); }

/* The buy button fills the row; "Qaytadan" keeps its own width. */
.planner-result .row .btn { height: 48px; font-size: 15px; }
.planner-result [data-buy] { flex: 1; min-width: 170px; }

/* ---------- global + regions cards ---------- */

.hop {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 38px;
  padding: 0 14px;
  border-radius: var(--fx-r-pill);
  background: var(--fx-cyansoft);
}

.region-card { padding: 20px; }

.region-plan { display: flex; flex-direction: column; padding: 24px; border-radius: 18px; }
.region-price { font-size: 20px; letter-spacing: -.02em; margin: 18px 0; padding-top: 16px; border-top: 1px solid var(--fx-border); }

/* ---------- how it works ---------- */

/* Three cards abreast on a desk. On a phone they become a rail: stacked, each card is nearly a
   screenful, so the third is never reached. Full-bleed — the negative margin cancels the page
   gutter so a card can reach the screen edge, and the padding puts the gutter back inside so
   the first card still lines up with the heading above it. */
@media (max-width: 1023px) {
  .how-rail {
    margin-inline: calc(var(--fx-gutter) * -1);
    padding-inline: var(--fx-gutter);
  }

  .how-steps {
    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: 46%; /* a tablet takes two cards and a peek of the third */
  }
}

@media (max-width: 640px) {
  .how-steps { grid-auto-columns: 78%; } /* a phone takes one and a peek of the next */
}

/* Pinned. how.js gives the section the stage's height plus the cards' travel, and the stage
   sticks under the header for exactly that distance: the reader meets a full screen of cards,
   swipes them across while the page appears to hold still, and only then carries on to what is
   below. `padding-top: 0` is load-bearing — .section's padding would come out of the height the
   section was given and the last card would never arrive. Not a horizontal scroller either: one
   on a phone swallows the touch that was meant for the page. */
@media (max-width: 1023px) and (prefers-reduced-motion: no-preference) {
  .how-pin { padding-top: 0; }

  .how-stage {
    position: sticky;
    top: var(--fx-header);
    /* svh, not dvh: a height that changed as the URL bar collapsed would shift the pin mid-swipe */
    min-height: calc(100svh - var(--fx-header));
    display: grid;
    align-content: center;
  }

  .how-rail { overflow: hidden; }
  .how-steps { transform: translate3d(var(--hx, 0px), 0, 0); }
}

/* Reduced motion gets neither the pin nor the scroll link — how.js leaves the section alone —
   so the rail needs its own way to reach cards two and three. */
@media (max-width: 1023px) and (prefers-reduced-motion: reduce) {
  .how-rail {
    overflow: auto hidden;
    overscroll-behavior-x: contain;
    scroll-snap-type: x proximity;
    scroll-padding-inline: var(--fx-gutter);
    scrollbar-width: none;
  }
  .how-rail::-webkit-scrollbar { display: none; }
  .how-steps > * { scroll-snap-align: start; }
}

.step-card {
  display: grid;
  justify-items: center;
  overflow: hidden;
  padding: 32px 24px 0;
  background: var(--fx-bg);
  border: 1px solid var(--fx-border);
  border-radius: var(--fx-r-hero);
  text-align: center;
}

.phone {
  width: 100%;
  max-width: 280px;
  display: grid;
  justify-items: center;
  padding: 20px 20px 0;
  background: var(--fx-surface);
  border-radius: 22px 22px 0 0;
}

.phone-screen {
  width: 100%;
  max-width: 210px;
  height: 216px;
  overflow: hidden;
  border: 7px solid var(--fx-bezel);
  border-bottom: 0;
  border-radius: 30px 30px 0 0;
  background: var(--fx-surface);
  padding: 14px 10px 0;
  text-align: left;
}

.mock-row { display: flex; align-items: center; gap: 9px; padding: 9px 10px; background: var(--fx-bg); border-radius: 10px; }
.selected-row { background: var(--fx-surface); border: 1px solid var(--fx-cyan); box-shadow: var(--fx-shadow); padding: 11px 10px; }
.mock-bar { display: block; height: 22px; border-radius: 999px; background: var(--fx-bg); }
.mock-qr { width: 62px; height: 62px; border-radius: 50%; background: var(--fx-cyansoft); display: grid; place-items: center; }
.mock-qr i { font-size: 28px; color: var(--fx-cyanink); }
.mock-cta { height: 42px; border-radius: 12px; background: var(--fx-cyan); color: var(--fx-on-cyan); display: grid; place-items: center; font-size: 14px; font-weight: 600; }
.mock-panel { padding: 12px; background: var(--fx-bg); border-radius: 14px; }

/* ---------- reviews ---------- */

/* One wrapping row, not a grid: the prototype gives each card its own flex basis so the wide
   quote can take two shares while the stat column stays narrow. `auto-fit` cannot do that. */
.reviews-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--fx-gap);
  align-items: stretch;
}

.stars { display: inline-flex; gap: 3px; line-height: 1; color: var(--fx-warn); }

.score-card {
  flex: 1 1 300px;
  min-width: 0;
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 24px;
  padding: 26px;
  background: var(--fx-deep);
  border-radius: var(--fx-r-feature);
}

.score-card > *:not(.panel-glow) { position: relative; }

.score-n {
  font-size: clamp(40px, 5vw, 58px);
  letter-spacing: -.04em;
  line-height: 1;
  color: var(--fx-deepink);
}

.score-note {
  margin: 12px 0 0;
  max-width: 22em;
  font-size: 15px;
  line-height: 1.5;
  color: var(--fx-deepink2);
}

.store-pill {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 34px;
  padding: 0 13px;
  border-radius: var(--fx-r-pill);
  background: var(--fx-white-07);
  border: 1px solid var(--fx-white-12);
  font-size: 13px;
  font-weight: 500;
  color: var(--fx-deepink);
}

.store-pill i { font-size: 14px; }

/* The quote cards. `.card card-feature` already carries the surface, border, radius and padding. */
.review {
  flex: 1 1 320px;
  min-width: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.review-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }

.review blockquote {
  margin: 0;
  font-size: 16px;
  line-height: 1.6;
  color: var(--fx-ink);
  text-wrap: pretty;
}

/* `margin-top: auto` pins the attribution to the bottom, so cards of unequal text still line up. */
.review figcaption {
  margin-top: auto;
  display: flex;
  align-items: center;
  gap: 11px;
  padding-top: 16px;
  border-top: 1px solid var(--fx-border);
}

.review-who { flex: 1; min-width: 0; }
.review-name { display: block; font-size: 15px; font-weight: 600; color: var(--fx-ink); }
.review-sub { display: block; font-size: 12px; color: var(--fx-ink2); }

/* The wide closing quote: two shares of the row, a pull-quote glyph instead of a flag. */
.review-lead { flex: 2 1 420px; }
.review-lead blockquote { font-size: clamp(16px, 1.5vw, 19px); line-height: 1.55; max-width: 44em; }
.review-glyph { font-size: 30px; color: var(--fx-cyansoft); }
.review-verified i { color: var(--fx-ok); }

/* The narrow quote shares its column with the stat card, so it drops the caption rule. */
.review-col {
  flex: 1 1 240px;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.review-sm { flex: 1; gap: 14px; padding: 24px; }
.review-sm blockquote { font-size: 15px; }
.review-sm figcaption { gap: 10px; padding-top: 0; border-top: 0; }

.review-stat { padding: 22px; background: var(--fx-cyan); border-radius: var(--fx-r-feature); }

.review-stat-n {
  font-family: var(--fx-display);
  font-weight: 600;
  font-size: 34px;
  letter-spacing: -.03em;
  line-height: 1;
  color: var(--fx-on-cyan);
}

.review-stat-t {
  margin: 8px 0 0;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.4;
  color: var(--fx-on-cyan-muted);
}

/* The dashed card is the row's invitation to act — the only dashed border on the site. */
.review-cta {
  flex: 1 1 240px;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 18px;
  padding: 26px;
  text-align: left;
  background: var(--fx-bg);
  border: 1px dashed var(--fx-border);
  border-radius: var(--fx-r-feature);
  transition: border-color var(--fx-base) ease, background-color var(--fx-base) ease;
}

.review-cta:hover { border-color: var(--fx-cyan); background: var(--fx-cyansoft); }

.review-cta-h {
  font-family: var(--fx-display);
  font-weight: 600;
  font-size: 19px;
  letter-spacing: -.02em;
  color: var(--fx-ink);
  text-wrap: pretty;
}

.review-cta-a {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  font-weight: 600;
  color: var(--fx-cyanink);
}

/* ---------- referral ---------- */

.referral {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  background: var(--fx-bg);
  border: 1px solid var(--fx-border);
  border-radius: var(--fx-r-hero);
  overflow: hidden;
}

.referral-copy { display: grid; align-content: center; gap: 18px; padding: clamp(28px, 4vw, 52px); justify-items: start; }

.referral-photo { position: relative; min-height: clamp(260px, 26vw, 340px); background: var(--fx-cyansoft); }
.referral-photo img { width: 100%; height: 100%; object-fit: cover; display: block; position: absolute; inset: 0; }

.referral-corner {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 32%;
  height: 28%;
  background: var(--fx-cyan);
  border-top-left-radius: 100%;
}

.referral-gift {
  position: absolute;
  top: 18px;
  left: 18px;
  width: 56px;
  height: 56px;
  border-radius: 16px;
  background: var(--fx-deep);
  display: grid;
  place-items: center;
  box-shadow: var(--fx-shadow-lift);
}

.referral-gift i { font-size: 26px; color: var(--fx-cyan); }

/* ---------- country ---------- */

.country-hero {
  background: var(--fx-surface);
  border-bottom: 1px solid var(--fx-border);
  padding-top: clamp(28px, 4vw, 56px);
  padding-bottom: clamp(32px, 4vw, 48px);
}

.crumbs { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--fx-ink2); margin-bottom: 26px; }
.crumbs i { font-size: 13px; }

.price-card { background: var(--fx-bg); border-radius: 18px; padding: 24px; }

.plan-row {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 60px;
  padding: 12px 16px;
  border: 1px solid var(--fx-border);
  border-radius: 14px;
  background: var(--fx-surface);
  text-align: left;
  transition: border-color var(--fx-fast) ease, background-color var(--fx-fast) ease;
}

.plan-row:hover { border-color: var(--fx-cyan); }
.plan-gb { font-size: 16px; letter-spacing: -.015em; min-width: 58px; }
.plan-days { font-size: 14px; color: var(--fx-ink2); min-width: 56px; }
.plan-price { font-size: 16px; letter-spacing: -.015em; }
.plan-sep { width: 1px; height: 20px; background: var(--fx-border); flex-shrink: 0; }
.plan-row .badge { align-self: center; }

.plan-foot { margin-top: 18px; padding-top: 18px; border-top: 1px solid var(--fx-border); }

/* `.row-between` wraps, but only if something makes it. `.grow` is `flex: 1` — basis zero — so
   next to a button that will not shrink it collapsed to a couple of characters and broke the
   plan name one word per line. A real basis makes the row wrap instead of crushing the text. */
.plan-foot > .grow { flex: 1 1 11em; }
.plan-foot > .btn { flex-shrink: 0; }

/* Below the hero the page splits: the cards on the left, the order rail on the right. The rail is
   what keeps the price and the buy button reachable on a page this tall — below 1024 it gives way
   to .plan-foot and the fixed .sticky-cta, so each width has exactly one buy surface. */
.country-body { display: grid; gap: var(--fx-gap); align-items: start; }
.country-main { display: grid; gap: var(--fx-gap); align-content: start; min-width: 0; }

@media (min-width: 1024px) {
  .country-body { grid-template-columns: minmax(0, 1fr) 340px; }
}

/* same idiom as .dash-nav: clear the sticky header, then hold */
.order-rail { position: sticky; top: calc(var(--fx-header) + 24px); }
.order-card { display: grid; gap: 14px; }
.order-total { display: flex; align-items: baseline; gap: 8px; }

.order-meta {
  display: grid;
  gap: 9px;
  padding: 14px 0;
  border-top: 1px solid var(--fx-border);
  border-bottom: 1px solid var(--fx-border);
}

.spec-item { display: flex; align-items: flex-start; gap: 13px; padding: 14px 16px; background: var(--fx-bg); border-radius: 13px; }

.how-head { font-size: 18px; letter-spacing: -.02em; padding: 20px 22px; border-bottom: 1px solid var(--fx-border); }
.how-row { display: flex; align-items: flex-start; gap: 14px; padding: 18px 22px; border-bottom: 1px solid var(--fx-border); }
.how-row:last-child { border-bottom: 0; }
.how-icon { width: 34px; height: 34px; border-radius: 10px; background: var(--fx-cyansoft); display: grid; place-items: center; flex-shrink: 0; }
.how-icon i { font-size: 17px; color: var(--fx-cyanink); }

.sticky-cta {
  position: fixed;
  left: 0;
  right: 0;
  /* Rests on the bottom edge. The bottom nav only exists for a signed-in visitor, so only then
     does the buy bar step up over it — otherwise it would float above a strip of nothing. */
  bottom: env(safe-area-inset-bottom);
  z-index: 65;
  padding: 10px 14px;
  background: linear-gradient(to top, var(--fx-bg) 60%, transparent);
}

[data-session='in'] .sticky-cta { bottom: calc(69px + env(safe-area-inset-bottom)); }

/* ---------- global page ---------- */

.global-hero { position: relative; overflow: hidden; background: var(--fx-deep); padding: clamp(48px, 7vw, 96px) 0; }
.global-hero > .wide { position: relative; }

.global-plan {
  display: grid;
  align-content: start;
  padding: 20px;
  border-radius: var(--fx-r-card);
  background: var(--fx-white-05);
  border: 1px solid var(--fx-white-10);
}

.global-plan.popular { background: rgba(8, 181, 209, .12); border-color: rgba(8, 181, 209, .4); }
.global-kicker { font-size: 12px; font-weight: 600; letter-spacing: .1em; color: var(--fx-deepink2); margin-bottom: 10px; }
.global-plan.popular .global-kicker { color: var(--fx-cyan); }

/* The plans are the choice on this page, so each card is a radio. `.popular` is a label the
   catalogue carries and keeps its faded cyan edge; the checked card takes the solid one, which is
   the same "selected = brand border" rule the plan rows follow on a light ground. */
button.global-plan {
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: border-color var(--fx-fast) ease, background-color var(--fx-fast) ease;
}

.global-plan[aria-checked='true'] { background: var(--fx-white-10); border-color: var(--fx-cyan); }
.global-plan:hover { border-color: var(--fx-cyan); }

/* ---------- how page ---------- */

.step-row { display: flex; gap: 18px; }
.step-n { font-size: 13px; letter-spacing: .1em; color: var(--fx-cyanink); width: 30px; flex-shrink: 0; }

/* ---------- login ---------- */

.login-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: var(--fx-gap); align-items: stretch; }

.login-pitch {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 32px;
  padding: clamp(28px, 4vw, 44px);
  background: var(--fx-deep);
  border-radius: var(--fx-r-hero);
}

.login-pitch > *:not(.panel-glow) { position: relative; }
.login-form { display: grid; align-content: center; padding: clamp(24px, 3vw, 36px); }

.or { display: flex; align-items: center; gap: 14px; margin: 22px 0; font-size: 12px; color: var(--fx-ink2); }
.or span { flex: 1; height: 1px; background: var(--fx-border); }

.phone-input { height: 54px; border-radius: 13px; }
.phone-sep { width: 1px; height: 24px; background: var(--fx-border); }

/* ---------- dashboard ---------- */

.dash { display: grid; grid-template-columns: 236px 1fr; gap: var(--fx-gap); align-items: start; }
.dash-main { min-width: 0; }

.dash-nav { position: sticky; top: calc(var(--fx-header) + 20px); display: grid; gap: 2px; }

.dash-link {
  display: flex;
  align-items: center;
  gap: 11px;
  height: 40px;
  padding: 0 12px;
  border-radius: 10px;
  font-size: 13px;
  font-weight: 500;
  color: var(--fx-ink2);
  text-align: left;
  transition: background-color var(--fx-fast) ease, color var(--fx-fast) ease;
}

.dash-link i { font-size: 17px; }
.dash-link:hover { background: var(--fx-bg); color: var(--fx-ink); }
.dash-link.on { background: var(--fx-cyansoft); color: var(--fx-cyanink); }

.dash-rail { display: flex; gap: 8px; overflow-x: auto; padding-bottom: 6px; margin-bottom: 20px; scrollbar-width: none; }
.dash-rail::-webkit-scrollbar { display: none; }
.dash-rail .chip { height: 38px; flex-shrink: 0; }

.esim-card { display: flex; flex-direction: column; padding: 20px; }

.order-row { display: flex; align-items: center; gap: 12px; padding: 14px 18px; border-bottom: 1px solid var(--fx-border); flex-wrap: wrap; }
.order-row:last-child { border-bottom: 0; }

.usage-chart { display: flex; align-items: flex-end; gap: 10px; height: 160px; }
.usage-col { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 8px; height: 100%; justify-content: flex-end; }
.usage-bar { width: 100%; max-width: 34px; border-radius: 8px 8px 4px 4px; background: var(--fx-cyan); transform-origin: bottom; animation: fxRise var(--fx-slow) var(--fx-ease-out) both; }

.switch {
  width: 46px;
  height: 28px;
  border-radius: 999px;
  background: var(--fx-border);
  padding: 3px;
  display: flex;
  transition: background-color var(--fx-base) ease;
  flex-shrink: 0;
}

.switch span { width: 22px; height: 22px; border-radius: 50%; background: var(--fx-surface); box-shadow: var(--fx-shadow-sm); transition: transform var(--fx-base) var(--fx-ease); }
.switch.on { background: var(--fx-cyan); }
.switch.on span { transform: translateX(18px); }

.warn-card { border-color: var(--fx-warn); background: var(--fx-warnsoft); }

/* ---------- eSIM detail ---------- */

.copy-row { display: flex; align-items: center; gap: 12px; padding: 12px 14px; background: var(--fx-bg); border-radius: 12px; }

.qr-box {
  width: 200px;
  height: 200px;
  padding: 12px;
  background: #fff;
  border: 1px solid var(--fx-border);
  border-radius: 14px;
  display: grid;
  place-items: center;
}

.qr-box img { width: 100%; height: 100%; object-fit: contain; }

/* ---------- checkout / success ---------- */

.checkout-total { margin-top: 18px; padding-top: 18px; border-top: 1px solid var(--fx-border); }
.pay-method { display: flex; align-items: center; gap: 14px; }
.pay-method img { background: #fff; border-radius: 6px; padding: 2px 6px; }

.success-mark {
  width: 58px;
  height: 58px;
  border-radius: 50%;
  background: var(--fx-cyansoft);
  display: grid;
  place-items: center;
  margin: 0 auto 20px;
}

.success-mark i { font-size: 28px; color: var(--fx-cyanink); }

/* The QR is the deliverable but only 200px wide — half of a 1060px row left it floating in an
   empty card, so it gets a fixed column and the receipt and steps take the rest. */
.success-body { display: grid; gap: var(--fx-gap); align-items: start; }

@media (min-width: 1024px) {
  .success-body { grid-template-columns: 380px minmax(0, 1fr); }
}

.account-nudge {
  position: relative;
  overflow: hidden;
  padding: 24px;
  border-radius: 18px;
  background: var(--fx-deep);
}

.account-nudge > *:not(.panel-glow) { position: relative; }

/* ---------- responsive ---------- */

@media (max-width: 1023px) {
  .dash { grid-template-columns: 1fr; gap: 0; }
  .float-card { display: none; }

  /* The pitch panel beside it is .desk-only, and auto-fit hands its track to the form. A phone
     number and a code do not want 900px of it, so the form keeps a readable width and centres. */
  .login-form { max-width: 520px; margin-inline: auto; width: 100%; }
}

@media (max-width: 640px) {
  .plan-row { flex-wrap: wrap; row-gap: 8px; }
  .plan-price { min-width: 90px; }
  .plan-row .badge { order: 9; }
  .referral-copy { padding: 28px 16px; }
  .qr-box { width: 100%; max-width: 200px; }

  /* One horizontal inset on a phone. Containers only — every box that holds page
     content sits 16px from its parent's edge, so nothing steps in or out against
     its neighbour. Vertical rhythm and the controls keep their own values. */
  .empty, .planner, .planner-panel, .region-card, .region-plan, .step-card,
  .score-card, .review-sm, .review-stat, .review-cta, .price-card,
  .how-head, .how-row, .global-plan, .login-pitch, .login-form,
  .esim-card, .order-row, .account-nudge, .dest-row {
    padding-left: 16px;
    padding-right: 16px;
  }
}
