/* On Route Scout — stylesheet.

   The look: white stationery, deep ink, airmail blue and stamp red, and the
   photographs doing the colour. Photos are never written over — every hero
   and card shows its picture clean, with the words beside or beneath it.
   Bricolage Grotesque carries the headings and the big figures; body text is
   the reader's own system face. The typewriter face (Special Elite) is kept
   for the two real "documents" on the site, the boarding pass and the
   passport stamps, and nowhere else.

   Contents: tokens · base · header · buttons and fields · heroes · cards ·
   home · city guide · country · comparisons · rankings · passport · footer ·
   motion. */

/* ---------- Tokens ---------- */
:root {
  color-scheme: light;
  --page: #ffffff;
  --surface: #ffffff;
  --wash: #f2f5fc;           /* tinted band behind tools and callouts */
  --ink: #0f1b3d;
  --ink-2: #3c4868;
  --muted: #626c88;          /* 5.3:1 on white, 4.9:1 on --wash */
  --hairline: #e3e8f2;
  --border: rgba(15, 27, 61, 0.14);
  --accent: #2247e6;         /* airmail blue; 6.7:1 on white */
  --accent-text: #1d3ed0;
  --accent-soft: #e4eaff;
  --accent-2: #0b8f83;
  --red: #e5372b;            /* stamp red — fills and large type only (4.3:1) */
  --red-text: #c2281d;       /* the same red as small text, 6:1 on white */
  --good: #157a37;
  --sun: #ffc53d;
  --card: var(--surface);
  --shadow: 0 18px 40px -18px rgba(15, 27, 61, 0.28);
  --airmail: repeating-linear-gradient(-45deg,
    var(--red) 0 12px, transparent 12px 20px, var(--accent) 20px 32px, transparent 32px 40px);
  --display: "Bricolage Grotesque", system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: "Special Elite", "Courier New", monospace;
  --r-photo: 20px;
  --r-box: 14px;
  --r-field: 10px;
  --stamp-a: #2a4d8f;
  --stamp-b: #b3382b;
  --stamp-c: #2c6e49;
  --stamp-d: #64508d;
}
@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme="light"])) {
    color-scheme: dark;
    --page: #0b1020;
    --surface: #131a2e;
    --wash: #121930;
    --ink: #f2f5ff;
    --ink-2: #c5cde2;
    --muted: #949eb9;
    --hairline: #232c47;
    --border: rgba(200, 212, 255, 0.16);
    --accent: #8ea5ff;
    --accent-text: #9db1ff;
    --accent-soft: #1d2a5c;
    --accent-2: #45c9bc;
    --red: #ff6f5e;
    --red-text: #ff8576;
    --good: #3ecf6a;
    --shadow: 0 18px 40px -18px rgba(0, 0, 0, 0.7);
    --stamp-a: #85a8e8;
    --stamp-b: #f0907f;
    --stamp-c: #86c8a2;
    --stamp-d: #b3a0dd;
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --page: #0b1020;
  --surface: #131a2e;
  --wash: #121930;
  --ink: #f2f5ff;
  --ink-2: #c5cde2;
  --muted: #949eb9;
  --hairline: #232c47;
  --border: rgba(200, 212, 255, 0.16);
  --accent: #8ea5ff;
  --accent-text: #9db1ff;
  --accent-soft: #1d2a5c;
  --accent-2: #45c9bc;
  --red: #ff6f5e;
  --red-text: #ff8576;
  --good: #3ecf6a;
  --shadow: 0 18px 40px -18px rgba(0, 0, 0, 0.7);
  --stamp-a: #85a8e8;
  --stamp-b: #f0907f;
  --stamp-c: #86c8a2;
  --stamp-d: #b3a0dd;
}

/* ---------- Fonts ----------
   Self-hosted subsets (font-src 'self'), cut by scripts/build-fonts.js to
   the characters each face draws. Bricolage Grotesque 700 (OFL) keeps its
   optical-size axis, so an 18px h3 and an 80px headline come from one file.

   optional, not swap: a headline that swapped faces mid-load re-wrapped, so
   the hero changed height and the content below shifted (CLS 0.027 on
   several country pages under the old serif). With optional the browser uses
   the face only if it's there almost at once — always from cache after the
   first visit — and otherwise keeps the system face for that page view.
   Preloading it instead slowed mobile LCP by 0.1–0.3 s. */
@font-face {
  font-family: "Bricolage Grotesque";
  src: url("fonts/bricolage-700-latin.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: optional;
}
@font-face {
  font-family: "Special Elite";
  src: url("fonts/special-elite-latin.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* ---------- Base ---------- */
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--page);
  color: var(--ink);
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-size: 16.5px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3 {
  font-family: var(--display);
  font-weight: 700;
  font-optical-sizing: auto;
  text-wrap: balance;
  margin: 0;
}
h1 { font-size: clamp(38px, 5.4vw, 66px); line-height: 1.02; letter-spacing: -0.03em; }
h2 { font-size: clamp(25px, 2.7vw, 34px); line-height: 1.1; letter-spacing: -0.022em; }
h3 { font-size: 18.5px; line-height: 1.25; letter-spacing: -0.01em; }
p { margin: 0 0 12px; }
a { color: var(--accent-text); text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 3px; }
/* A link inside running text needs more than colour to stand out from the
   words around it (WCAG 1.4.1). */
p a:not([class]), li a:not([class]), dd a:not([class]) {
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: from-font;
}
img { max-width: 100%; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
::selection { background: var(--accent-soft); }

.wrap { max-width: 1168px; margin: 0 auto; padding: 0 24px; }
/* Keeps the footer off the middle of the screen on a short page. */
.site-header + .wrap { min-height: 58vh; }
.sub { color: var(--muted); font-size: 14px; margin: 0 0 14px; }
.lede { font-size: 18px; line-height: 1.55; color: var(--ink-2); margin: 0; max-width: 70ch; }
.muted { color: var(--ink-2); }
/* Visually hidden, read by screen readers. */
.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;
}
.btn-label-short { display: none; }
.error-box { margin: 80px auto; text-align: center; }
.error-box h1 { margin-bottom: 16px; }

/* ---------- Header ----------
   One row on a wide screen: brand, the four destinations, then the tools.
   On a phone it's two: brand and tools, then the links — the search field
   folds to a round button that opens over the row when focused, which is
   what lets everything else stay on one line. */
.site-header { border-bottom: 1px solid var(--hairline); }
.header-in {
  display: flex;
  align-items: center;
  gap: 8px 22px;
  min-height: 68px;
}
.brand {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-family: var(--display);
  font-weight: 700;
  font-size: 19px;
  letter-spacing: -0.02em;
  color: var(--ink);
  white-space: nowrap;
}
.brand:hover { text-decoration: none; color: var(--accent-text); }
.brand-mark { width: 26px; height: 26px; flex: none; }
.site-nav { display: flex; gap: 4px; margin-right: auto; }
.site-nav a {
  padding: 8px 11px;
  border-radius: 999px;
  color: var(--ink-2);
  font-size: 14.5px;
  font-weight: 600;
  white-space: nowrap;
}
.site-nav a:hover { background: var(--wash); color: var(--ink); text-decoration: none; }
.header-tools { display: flex; align-items: center; gap: 8px; }

.currency-select,
.theme-btn,
.auth-btn {
  height: 38px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink-2);
  font: inherit;
  font-size: 13.5px;
  font-weight: 600;
  cursor: pointer;
}
.currency-select { padding: 0 10px; }
.theme-btn { width: 38px; padding: 0; font-size: 16px; line-height: 1; }
.theme-btn .btn-label-full { display: none; }
.theme-btn .btn-label-short { display: inline; }
.auth-btn { padding: 0 16px; color: var(--ink); white-space: nowrap; }
.currency-select:hover,
.theme-btn:hover,
.auth-btn:hover { border-color: var(--ink); color: var(--ink); }
/* The sign-in button arrives after the page has painted (auth.js waits for
   the hero). The slot holds its width from the start, so the controls beside
   it don't step sideways when it does. */
.auth-slot { display: flex; align-items: center; justify-content: flex-end; min-width: 164px; }
.auth-user { display: flex; align-items: center; gap: 8px; }
.auth-user .avatar { width: 28px; height: 28px; border-radius: 50%; }
.auth-user .auth-name {
  font-size: 13.5px;
  color: var(--ink-2);
  max-width: 120px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* City search. The results panel is absolutely positioned off the wrap so it
   overlays the page rather than reflowing it. */
.search-wrap { position: relative; width: 220px; }
.site-search {
  width: 100%;
  height: 38px;
  padding: 0 14px 0 38px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--wash) url("search.svg") 13px 50% / 16px no-repeat;
  color: var(--ink);
  font: inherit;
  font-size: 14px;
}
.site-search::placeholder { color: var(--muted); }
.site-search:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
  background-color: var(--surface);
}
.search-results {
  position: absolute;
  z-index: 60;
  top: calc(100% + 8px);
  right: 0;
  width: max(100%, 300px);
  margin: 0;
  padding: 6px;
  list-style: none;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 16px;
  box-shadow: var(--shadow);
  max-height: 60vh;
  overflow-y: auto;
}
.search-opt a {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-areas: "flag name" "flag meta";
  column-gap: 10px;
  align-items: center;
  padding: 8px 10px;
  border-radius: 10px;
  color: var(--ink);
  text-decoration: none;
}
.search-flag { grid-area: flag; font-size: 20px; }
.search-name { grid-area: name; font-weight: 600; font-size: 14.5px; }
.search-meta { grid-area: meta; font-size: 12.5px; color: var(--muted); }
.search-opt.is-active a,
.search-opt a:hover { background: var(--wash); text-decoration: none; }
.search-empty { padding: 10px 12px; font-size: 13.5px; color: var(--muted); }

@media (max-width: 1040px) {
  .search-wrap { width: 170px; }
  .site-nav a { padding: 8px 8px; }
  .auth-btn .btn-label-full { display: none; }
  .auth-btn .btn-label-short { display: inline; }
  .auth-slot { min-width: 82px; }
}
@media (max-width: 860px) {
  /* .header-tools dissolves (display: contents) so its four controls can
     sit in the grid themselves: search, theme and sign-in beside the brand,
     the currency at the end of the links row, where there is room for it. */
  .header-in {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto auto auto;
    grid-template-areas: "brand search theme auth" "nav nav nav cur";
    gap: 0 6px;
    padding-top: 10px;
    position: relative;
  }
  .brand { grid-area: brand; font-size: 17.5px; overflow: hidden; text-overflow: ellipsis; }
  .header-tools { display: contents; }
  .search-wrap { grid-area: search; }
  .theme-btn { grid-area: theme; }
  .auth-slot { grid-area: auth; min-width: 74px; }
  .currency-select { grid-area: cur; align-self: center; margin-top: 6px; height: 34px; }
  .site-nav {
    grid-area: nav;
    margin: 6px 0 0 -8px;
    gap: 0;
    overflow-x: auto;
    scrollbar-width: none;
  }
  .site-nav::-webkit-scrollbar { display: none; }
  .site-nav a { padding: 10px 7px; font-size: 14px; }
  .site-nav .btn-label-full { display: none; }
  .site-nav .btn-label-short { display: inline; }
  /* Signed in, the slot is avatar + name + "Sign out" — the avatar already
     says who, so the name goes. */
  .auth-user .auth-name { display: none; }
  .auth-btn { padding: 0 12px; }
  /* The folded search: a 38px round button showing only the magnifier. On
     focus it opens across the whole row, over the brand. */
  .search-wrap { position: static; width: 38px; }
  .site-search { padding: 0; color: transparent; background-position: 50% 50%; cursor: pointer; }
  .site-search::placeholder { color: transparent; }
  .search-wrap:focus-within .site-search {
    position: absolute;
    z-index: 61;
    left: 24px;
    right: 24px;
    top: 10px;
    width: auto;
    padding: 0 14px 0 38px;
    color: var(--ink);
    background-position: 13px 50%;
    cursor: text;
  }
  .search-wrap:focus-within .site-search::placeholder { color: var(--muted); }
  .search-results { left: 24px; right: 24px; top: 56px; width: auto; }
}
@media (max-width: 640px) {
  .hero-photo { aspect-ratio: 3 / 2; }
  .home-hero .hero-photo { aspect-ratio: 4 / 3; }
}
@media (max-width: 420px) {
  .wrap { padding: 0 16px; }
  .search-wrap:focus-within .site-search,
  .search-results { left: 16px; right: 16px; }
  .currency-select { padding: 0 6px; }
}

/* ---------- Buttons and fields ---------- */
.btn,
.save-btn,
.vs-picker-go,
.download-btn,
.view-more-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 46px;
  padding: 0 22px;
  border: 1.5px solid var(--accent);
  border-radius: 999px;
  background: var(--accent);
  color: #fff;
  font: inherit;
  font-size: 15px;
  font-weight: 700;
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition: transform 140ms ease, background 140ms ease, border-color 140ms ease;
}
:root[data-theme="dark"] :is(.btn, .save-btn, .vs-picker-go, .download-btn, .view-more-btn) { color: #0b1020; }
@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme="light"])) :is(.btn, .save-btn, .vs-picker-go, .download-btn, .view-more-btn) { color: #0b1020; }
}
.btn:hover,
.save-btn:hover,
.vs-picker-go:hover,
.download-btn:hover,
.view-more-btn:hover { text-decoration: none; transform: translateY(-1px); filter: brightness(1.08); }
.btn:active,
.save-btn:active,
.vs-picker-go:active { transform: translateY(0) scale(0.98); }

/* Quiet buttons: outlined, same height family. */
.btn-quiet,
.stamp-btn,
.bf-more,
.share-btn,
.itin-tab,
.calc-tier-btn,
.pc-btn,
.scam-btn,
.to-top,
.nf-city,
.hh-shuffle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 40px;
  padding: 0 16px;
  border: 1.5px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition: border-color 140ms ease, background 140ms ease, color 140ms ease;
}
.btn-quiet:hover,
.stamp-btn:hover,
.bf-more:hover,
.share-btn:hover,
.itin-tab:hover,
.calc-tier-btn:hover,
.pc-btn:hover,
.scam-btn:hover,
.to-top:hover,
.nf-city:hover,
.hh-shuffle:hover { border-color: var(--ink); text-decoration: none; }
.share-btn[hidden] { display: none; }

select,
input[type="text"],
input[type="number"],
input[type="email"],
textarea {
  font: inherit;
  color: var(--ink);
}
.field,
.pk-field select,
.country-select,
.vs-picker-row select,
.city-combo-input,
.calc-field input[type="number"],
.calc-field select,
.request-input,
.passport-link-row input,
.pc-paid input {
  min-height: 46px;
  padding: 0 14px;
  border: 1.5px solid var(--border);
  border-radius: var(--r-field);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: 15px;
}
.field:focus,
.pk-field select:focus-visible,
.country-select:focus-visible,
.vs-picker-row select:focus-visible,
.city-combo-input:focus,
.calc-field input:focus,
.calc-field select:focus,
.request-input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
select { cursor: pointer; }
textarea.request-input { padding: 12px 14px; min-height: 120px; width: 100%; }
.request-input { width: 100%; }
#request-form .auth-btn { margin-top: 12px; }
#request-form .sub { margin: 8px 0 0; }

/* The budget slider. The filled part of the track is painted from --fill,
   which app.js keeps in step with the value. */
input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 44px;
  margin: 0;
  background: transparent;
  cursor: pointer;
  --fill: 50%;
}
input[type="range"]::-webkit-slider-runnable-track {
  height: 8px;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--accent) var(--fill), var(--hairline) var(--fill));
}
input[type="range"]::-moz-range-track {
  height: 8px;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--accent) var(--fill), var(--hairline) var(--fill));
}
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 30px;
  height: 30px;
  margin-top: -11px;
  border: 3px solid var(--accent);
  border-radius: 50%;
  background: var(--surface);
  box-shadow: 0 4px 12px -2px rgba(15, 27, 61, 0.35);
  transition: transform 120ms ease;
}
input[type="range"]::-moz-range-thumb {
  width: 24px;
  height: 24px;
  border: 3px solid var(--accent);
  border-radius: 50%;
  background: var(--surface);
  box-shadow: 0 4px 12px -2px rgba(15, 27, 61, 0.35);
}
input[type="range"]:hover::-webkit-slider-thumb,
input[type="range"]:active::-webkit-slider-thumb { transform: scale(1.12); }
input[type="range"]:focus-visible { outline: none; }
input[type="range"]:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 5px var(--accent-soft); }
input[type="range"]:focus-visible::-moz-range-thumb { box-shadow: 0 0 0 5px var(--accent-soft); }

/* ---------- Photos ----------
   Every hero and card photo is an <img class="cover-img"> inside a frame
   that sets the shape. The frame's own background is the city's gradient
   (set inline by app.js), so a slow or failed photo leaves a coloured box
   rather than a hole. */
.cover-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Photos ease in on load instead of popping. Scoped under .img-fade-root,
   which only app.js ever adds — the prerendered first paint and no-JS
   readers see images plainly. */
.img-fade-root .fade-img { opacity: 0; transition: opacity 0.4s ease; }
.img-fade-root .fade-img.is-loaded { opacity: 1; }
.photo-credit {
  position: absolute;
  right: 10px;
  bottom: 10px;
  padding: 3px 9px;
  border-radius: 999px;
  background: rgba(10, 16, 32, 0.55);
  color: #fff;
  font-size: 11.5px;
  font-weight: 500;
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}
.photo-credit:hover { color: #fff; background: rgba(10, 16, 32, 0.8); text-decoration: none; }

/* ---------- Heroes ----------
   Words on the left, the photograph on the right, both at full strength. On
   a phone the photo leads on guide pages and follows the question on the
   home page, where the headline is the thing to act on. */
.hero { padding: 36px 0 12px; }
.hero-in {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
  gap: 48px;
  align-items: center;
}
.hero-photo {
  position: relative;
  margin: 0;
  aspect-ratio: 4 / 3;
  border-radius: var(--r-photo);
  overflow: hidden;
  background: var(--wash);
}
.hero .crumb { font-size: 14px; color: var(--muted); margin-bottom: 18px; }
.hero .crumb a { color: var(--ink-2); font-weight: 600; position: relative; }
/* Breadcrumb links are 20px tall; the overlay grows the tap target without
   moving anything. */
.hero .crumb a::before { content: ""; position: absolute; inset: -12px -4px; }
.hero h1 .flag { display: block; font-size: 0.5em; line-height: 1; margin-bottom: 14px; }
.hero-long h1 { font-size: clamp(32px, 3.9vw, 50px); line-height: 1.06; letter-spacing: -0.025em; }
.hero .tagline { margin: 18px 0 0; max-width: 46ch; font-size: 18px; line-height: 1.55; color: var(--ink-2); }
.hero-fact { display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 10px; margin: 22px 0 0; }
.hero-fact-val {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(28px, 3.2vw, 40px);
  line-height: 1;
  letter-spacing: -0.02em;
}
.hero-fact-lbl { font-size: 14.5px; color: var(--muted); }
.hero-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-top: 24px; }
.hero .country-select { margin-top: 24px; }

.save-btn.is-saved { background: var(--sun); border-color: var(--sun); color: #2b2118; }
.stamp-row { display: flex; flex-wrap: wrap; gap: 8px; }
.stamp-btn { min-height: 46px; }
.stamp-btn.is-on { background: var(--ink); border-color: var(--ink); color: var(--page); }
.save-count { display: block; margin-top: 10px; font-size: 13.5px; color: var(--muted); }
.save-count:empty { display: none; }
.save-count + .save-count { margin-top: 2px; }

/* Visit details under the hero stamps */
.visit-details { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 14px; }
.visit-details[hidden] { display: none; }
.visit-q { font-size: 13.5px; font-weight: 600; color: var(--ink-2); }
.visit-details select {
  height: 36px;
  padding: 0 10px;
  border: 1.5px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  font-size: 13.5px;
  font-weight: 600;
}

@media (max-width: 860px) {
  .hero { padding: 16px 0 4px; }
  .hero-in { grid-template-columns: 1fr; gap: 22px; }
  /* 16:9 on a tablet, where 3:2 across the full width would be most of the
     screen; phones get the taller crop back below. */
  .hero-photo { order: -1; aspect-ratio: 16 / 9; }
  .hero .crumb { margin-bottom: 12px; }
  .hero .tagline { font-size: 17px; margin-top: 14px; }
}

/* ---------- Home: the question ----------
   "Where does $100 a day take you?" — the figure is the slider's value, and
   the photo is the answer. */
.home-hero { padding: 44px 0 28px; }
.home-hero h1 { font-size: clamp(44px, 6.3vw, 86px); line-height: 0.98; letter-spacing: -0.035em; }
.hh-amt {
  display: inline-block;
  color: var(--accent-text);
  /* Reserved so the headline doesn't re-wrap as the number changes length
     while dragging — "$25" and "$200+" must take the same room. */
  min-width: 2.6ch;
  font-variant-numeric: tabular-nums;
}
.hh-sub { margin: 20px 0 0; max-width: 44ch; font-size: 18px; line-height: 1.5; color: var(--ink-2); }
.hh-controls { margin-top: 26px; max-width: 520px; }
.hh-scale {
  display: flex;
  justify-content: space-between;
  margin-top: -4px;
  font-size: 13px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.pk-controls { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 18px; }
/* min-width:0 because a <select> is as wide as its widest option, and a flex
   item won't shrink below its content by default — "Türkiye & the Middle
   East" would otherwise force each field onto its own row. */
.pk-field { display: flex; flex-direction: column; gap: 6px; flex: 1 1 160px; min-width: 0; }
.pk-field > label { color: var(--ink-2); font-size: 13.5px; font-weight: 600; }
.pk-field select { width: 100%; min-width: 0; padding-right: 30px; }
.hh-count { margin: 22px 0 0; font-size: 15.5px; }
.hh-count a { font-weight: 700; }

.home-hero .hero-photo { aspect-ratio: 5 / 4; box-shadow: var(--shadow); }
.hh-card { position: absolute; inset: 0; display: block; color: inherit; }
.hh-card .cover-img { position: absolute; inset: 0; transition: transform 600ms cubic-bezier(0.2, 0.7, 0.2, 1); }
.hh-card:hover .cover-img { transform: scale(1.03); }
/* The incoming photo sits over the old one and fades up; app.js removes the
   old one when the fade ends. */
.hh-card .cover-img.is-next { opacity: 0; transition: opacity 420ms ease; }
.hh-card .cover-img.is-next.is-in { opacity: 1; }
/* The luggage tag: which city this is and what a day there costs. */
.hh-tag {
  position: absolute;
  left: 16px;
  bottom: 16px;
  max-width: calc(100% - 32px);
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 12px 18px 12px 16px;
  border-radius: 16px;
  background: var(--surface);
  color: var(--ink);
  box-shadow: 0 10px 30px -10px rgba(10, 16, 32, 0.5);
}
.hh-tag-name { font-family: var(--display); font-weight: 700; font-size: 24px; line-height: 1.15; letter-spacing: -0.02em; }
.hh-tag-meta { font-size: 14px; color: var(--ink-2); }
.hh-tag-go { font-size: 14px; font-weight: 700; color: var(--accent-text); margin-top: 4px; }
.hh-card:hover { text-decoration: none; }
.hh-card:hover .hh-tag-go { text-decoration: underline; text-underline-offset: 3px; }
.hh-shuffle {
  position: absolute;
  top: 14px;
  right: 14px;
  border-color: transparent;
  box-shadow: 0 6px 18px -6px rgba(10, 16, 32, 0.5);
}
@media (max-width: 860px) {
  .home-hero { padding: 26px 0 20px; }
  /* The question first on a phone, then the photo that answers it. */
  .home-hero .hero-photo { order: 0; aspect-ratio: 16 / 9; }
  .hh-sub { font-size: 16.5px; margin-top: 14px; }
  .hh-controls { margin-top: 18px; max-width: none; }
  .hh-tag-name { font-size: 20px; }
}

/* ---------- Page sections ---------- */
.block { margin: 72px 0; }
.block-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px 24px;
  margin-bottom: 24px;
}
.block-head p { margin: 8px 0 0; color: var(--ink-2); max-width: 60ch; }
.block-head .sub { margin: 8px 0 0; font-size: 15px; }
@media (max-width: 640px) { .block { margin: 52px 0; } }

/* A tinted band for tools. */
.panel {
  background: var(--wash);
  border-radius: 24px;
  padding: 32px;
  margin: 56px 0;
}
.panel > h2 { margin-bottom: 8px; }
.panel .sub { font-size: 15px; color: var(--ink-2); margin: 0 0 18px; max-width: 64ch; }
.panel p:last-child { margin-bottom: 0; }
@media (max-width: 640px) { .panel { padding: 22px 18px; border-radius: 18px; margin: 40px 0; } }

/* Plain page title block (rankings, passport, packing and the like). */
.intro { margin: 44px 0 28px; }
.intro h1 { margin-bottom: 14px; }
.intro p { color: var(--ink-2); max-width: 64ch; font-size: 18px; margin: 0; }
.intro-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 20px; flex-wrap: wrap; }
.page-jump { display: flex; justify-content: flex-end; margin: 14px 0 0; }

/* ---------- Cards ----------
   Photo, then the name with its price opposite, then a line or two. No
   boxes: the photo is the card. */
.city-grid,
.bf-results {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 36px 24px;
}
.city-card,
.country-card { display: flex; flex-direction: column; color: inherit; min-width: 0; }
.city-card:hover { text-decoration: none; }
.card-photo {
  position: relative;
  display: block;
  aspect-ratio: 4 / 3;
  border-radius: var(--r-photo);
  overflow: hidden;
  background: var(--wash);
}
.card-photo .cover-img { transition: transform 500ms cubic-bezier(0.2, 0.7, 0.2, 1); }
.city-card:hover .card-photo .cover-img,
.country-card .card-photo:hover .cover-img,
.vs-side:hover .card-photo .cover-img { transform: scale(1.05); }
.card-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-top: 14px;
}
.card-name { font-size: 20px; letter-spacing: -0.015em; }
.city-card:hover .card-name { text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 4px; }
.card-price { flex: none; font-weight: 700; font-size: 15.5px; font-variant-numeric: tabular-nums; }
.card-price small { font-weight: 400; font-size: 12.5px; color: var(--muted); }
.card-meta { display: block; font-size: 13.5px; color: var(--muted); margin-top: 2px; }
.card-hook {
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--ink-2);
  margin-top: 8px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.bf-more { grid-column: 1 / -1; justify-self: center; min-height: 46px; padding: 0 24px; }
.bf-empty { grid-column: 1 / -1; color: var(--ink-2); font-size: 16px; margin: 0; }
.bf-count { color: var(--ink-2); margin: 8px 0 0; }

/* Country cards: the same card, with the three most-read guides linked
   beneath it. */
.country-card .card-photo:hover { text-decoration: none; }
.country-card .card-name a { color: inherit; }
.country-card .tagline { color: var(--ink-2); font-size: 14.5px; margin: 8px 0 0; }
.country-cities {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 0;
  margin-top: 10px;
  font-size: 14px;
}
.country-cities a { position: relative; color: var(--ink); font-weight: 600; }
.country-cities a::before { content: ""; position: absolute; inset: -10px 0; }
.country-cities a:not(:last-child)::after { content: "·"; color: var(--muted); font-weight: 400; margin: 0 7px; }
.country-cities .bud { display: none; }
@media (max-width: 640px) {
  .city-grid,
  .bf-results { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 26px 14px; }
  .card-photo { border-radius: 14px; }
  .card-top { flex-direction: column; gap: 0; margin-top: 10px; }
  .card-name { font-size: 17px; }
  .card-price { font-size: 14px; }
  .card-hook { display: none; }
  .country-card .tagline { display: none; }
  .country-cities { display: none; }
}

/* ---------- Home: map of what fits ----------
   The frame has the map's own proportions (300 degrees by 116, see FIT_MAP
   in app.js), so a dot placed by percentage lands on its coastline. The
   stage inside is what zooms; each dot divides its size by --k, the zoom,
   so it stays a dot. --k is registered as a number so it can ease along
   with the transform instead of jumping ahead of it. */
@property --k { syntax: "<number>"; inherits: true; initial-value: 1; }
.picker.block { margin-top: 40px; }
.fit-map {
  position: relative;
  margin: 0 0 44px;
  border-radius: 24px;
  background: var(--wash);
  overflow: hidden;
  aspect-ratio: 300 / 116;
}
.fit-map.has-hot { cursor: pointer; }
.fit-map-stage {
  position: absolute;
  inset: 0;
  transform-origin: 0 0;
  transition: transform 800ms cubic-bezier(0.3, 0.7, 0.2, 1), --k 800ms cubic-bezier(0.3, 0.7, 0.2, 1);
}
.fit-map-land {
  position: absolute;
  inset: 0;
  background: var(--ink);
  opacity: 0.13;
  -webkit-mask: url("world.svg") 0 0 / 100% 100% no-repeat;
  mask: url("world.svg") 0 0 / 100% 100% no-repeat;
}
.fit-dot {
  position: absolute;
  width: 11px;
  height: 11px;
  margin: -5.5px 0 0 -5.5px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 2px var(--wash);
  transform: scale(calc(1 / var(--k, 1)));
  transition: opacity 300ms ease, background 300ms ease, width 300ms ease, height 300ms ease, margin 300ms ease;
  pointer-events: none;
}
.fit-dot.is-out { width: 5px; height: 5px; margin: -2.5px 0 0 -2.5px; background: var(--muted); opacity: 0.4; box-shadow: none; }
.fit-dot.is-hot { z-index: 2; width: 17px; height: 17px; margin: -8.5px 0 0 -8.5px; background: var(--red); }
.fit-dot.is-new { animation: fit-new 700ms ease-out; }
@keyframes fit-new {
  from { box-shadow: 0 0 0 0 var(--accent); }
  to { box-shadow: 0 0 0 16px transparent; }
}
.fit-tip {
  position: absolute;
  z-index: 5;
  display: grid;
  grid-template-columns: 64px auto;
  gap: 2px 12px;
  align-items: center;
  width: max-content;
  max-width: min(300px, calc(100% - 16px));
  padding: 8px 16px 8px 8px;
  border-radius: 16px;
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--shadow);
  transform: translate(-50%, calc(-100% - 18px));
}
.fit-tip.is-below { transform: translate(-50%, 18px); }
.fit-tip[hidden] { display: none; }
.fit-tip:hover { text-decoration: none; }
.fit-tip img, .fit-tip > span:first-child:empty { grid-row: 1 / 3; width: 64px; height: 64px; border-radius: 10px; object-fit: cover; background: var(--wash); }
.fit-tip-name { font-family: var(--display); font-weight: 700; font-size: 17px; line-height: 1.2; align-self: end; }
.fit-tip-meta { font-size: 13px; color: var(--ink-2); align-self: start; }
.fit-map-note { position: absolute; left: 18px; bottom: 12px; margin: 0; font-size: 12.5px; color: var(--muted); pointer-events: none; }
@media (max-width: 640px) {
  .fit-map { border-radius: 16px; margin-bottom: 28px; }
  .fit-dot { width: 8px; height: 8px; margin: -4px 0 0 -4px; box-shadow: 0 0 0 1.5px var(--wash); }
  .fit-dot.is-out { width: 4px; height: 4px; margin: -2px 0 0 -2px; }
  .fit-map-note { display: none; }
}
@media (hover: none) { .fit-map-note { display: none; } }

/* ---------- Home: compare two ---------- */
.vs-picker-row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.vs-picker-row select { flex: 1 1 200px; min-width: 0; }
.vs-picker-vs { font-family: var(--display); font-weight: 700; font-size: 17px; color: var(--muted); }
.vs-picker-note { min-height: 0; margin: 10px 0 0; }
.vs-picker-note:empty { display: none; }

/* Searchable city picker (enhanceCityPicker in app.js) — sized and styled
   like the <select> it stands in for. */
.city-combo { position: relative; flex: 1 1 200px; min-width: 0; }
.city-combo-input { width: 100%; }
.city-combo-list {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  z-index: 30;
  max-height: 300px;
  overflow-y: auto;
  margin: 0;
  padding: 6px;
  list-style: none;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: var(--shadow);
}
.city-combo-list[hidden] { display: none; }
.city-combo-list li {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 12px;
  border-radius: 9px;
  font-size: 15px;
  cursor: pointer;
}
.city-combo-list li[aria-selected="true"],
.city-combo-list li[data-i]:hover { background: var(--wash); }
.city-combo-country { color: var(--muted); font-size: 13px; white-space: nowrap; }
.city-combo-list .city-combo-empty { color: var(--muted); cursor: default; }
.home-vs-preview:empty { display: none; }
.home-vs-preview { margin-top: 22px; padding: 22px; border-radius: 18px; background: var(--surface); }
.home-vs-verdict { margin: 0 0 14px; font-size: 16.5px; line-height: 1.6; }
.home-vs-months { display: grid; gap: 12px; margin-top: 16px; }
.home-vs-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 20px; }
.home-vs-chips .sub { margin: 0 4px 0 0; font-size: 14px; }
.home-vs-chip,
.vs-more a,
.vs-inline a,
.region-nav a,
.region-nav .is-current {
  display: inline-flex;
  align-items: center;
  min-height: 38px;
  padding: 0 15px;
  border: 1.5px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink);
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
}
.home-vs-chip span { color: var(--muted); font-weight: 500; margin: 0 5px; }
.home-vs-chip:hover,
.vs-more a:hover,
.vs-inline a:hover,
.region-nav a:hover { border-color: var(--ink); text-decoration: none; }
.vs-more, .vs-inline, .region-nav { display: flex; flex-wrap: wrap; gap: 8px; }
.region-nav { margin: 0 0 8px; }
.region-nav .is-current { background: var(--ink); border-color: var(--ink); color: var(--page); }
@media (max-width: 560px) {
  .vs-picker-row select, .vs-picker-row .city-combo, .vs-picker-go { flex: 1 1 100%; }
  .vs-picker-vs { display: none; }
}

/* ---------- Home: pitch in ---------- */
.community-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
.community-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 22px;
  border-radius: 18px;
  background: var(--surface);
  color: var(--ink);
  transition: transform 160ms ease;
}
.community-card:hover { text-decoration: none; transform: translateY(-3px); }
.community-card strong { font-family: var(--display); font-size: 19px; letter-spacing: -0.01em; }
.community-card span { font-size: 14.5px; color: var(--ink-2); line-height: 1.5; }
.community-card .community-go { margin-top: auto; padding-top: 10px; font-weight: 700; color: var(--accent-text); }
.community-card:hover .community-go { text-decoration: underline; text-underline-offset: 3px; }
.community-foot { margin: 18px 0 0; font-size: 14px; }
@media (max-width: 760px) { .community-grid { grid-template-columns: 1fr; } }

/* Most-saved strip. Filled from Firestore after paint, so it can appear a
   beat late; it sits low on the page so nothing being read moves. */
.top-saved { counter-reset: tsc; }
.top-saved-strip { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 10px; }
.top-saved-card {
  counter-increment: tsc;
  position: relative;
  display: block;
  padding: 16px;
  border-radius: 16px;
  background: var(--surface);
  color: var(--ink);
  text-decoration: none;
  transition: transform 160ms ease;
}
.top-saved-card:hover { transform: translateY(-3px); text-decoration: none; }
.tsc-rank::before {
  content: counter(tsc);
  position: absolute;
  top: 12px;
  right: 14px;
  font-family: var(--display);
  font-size: 17px;
  color: var(--muted);
}
.tsc-name { display: block; font-weight: 700; font-size: 15px; padding-right: 20px; }
.tsc-sub { display: block; font-size: 13px; color: var(--muted); margin-top: 1px; }
.tsc-count { display: block; font-size: 13px; font-weight: 600; color: var(--accent-text); margin-top: 8px; }

/* ---------- Tables ---------- */
table { width: 100%; border-collapse: collapse; font-size: 15px; }
th {
  text-align: left;
  font-size: 13px;
  color: var(--muted);
  font-weight: 600;
  padding: 8px 12px 8px 0;
  border-bottom: 1px solid var(--border);
  vertical-align: bottom;
}
td { padding: 11px 12px 11px 0; border-bottom: 1px solid var(--hairline); vertical-align: top; }
th:last-child, td:last-child { padding-right: 0; }
tr:last-child td { border-bottom: none; }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
td.num { font-weight: 600; }
td.muted { color: var(--ink-2); font-size: 14.5px; }
tbody th[scope="row"] { color: var(--ink); font-size: 15px; font-weight: 600; border-bottom: 1px solid var(--hairline); vertical-align: top; padding-top: 11px; padding-bottom: 11px; }
tr:last-child th[scope="row"] { border-bottom: none; }
.table-scroll { overflow-x: auto; }
/* Sticky column headers for the long comparison tables. position:sticky
   binds to the nearest scrolling ancestor, and overflow-x:auto silently makes
   .table-scroll one — so the overflow is dropped at widths where the table
   fits, which makes the viewport the container again. Headers may wrap
   (figures keep their nowrap) so the table fits its column. */
.table-scroll th.num { white-space: normal; }
.table-scroll thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--page);
  border-bottom: none;
  box-shadow: inset 0 -1px 0 var(--border);
}
.panel .table-scroll thead th { background: var(--wash); }
.home-vs-preview .table-scroll thead th { background: var(--surface); }
@media (min-width: 980px) { .table-scroll { overflow-x: visible; } }

/* ---------- City guide: at a glance ----------
   The five headline figures, dressed as the document every trip starts
   with. The .val prices stay $-anchored text so the currency converter
   reformats them like every other figure on the page. */
.bpass {
  position: relative;
  display: flex;
  margin: 0 0 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 20px;
  overflow: hidden;
  scroll-margin-top: 24px;
}
/* The airmail edge. */
.bpass::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 7px;
  background: var(--airmail);
}
.bpass-main { flex: 1; min-width: 0; padding: 27px 24px 16px; }
.bpass-head {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}
.bpass-route { display: flex; align-items: center; gap: 18px; margin: 14px 0 4px; }
.bpass-ap { min-width: 0; }
.bpass-code { display: block; font-family: var(--mono); font-size: 38px; line-height: 1.05; }
.bpass-place {
  display: block;
  font-size: 12.5px;
  color: var(--muted);
  margin-top: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.bpass-ap-to { text-align: right; }
/* The dashed flight line, plane riding it on a surface-coloured pad so it
   reads as sitting on the line rather than skewered by it. */
.bpass-dots { flex: 1; min-width: 36px; border-top: 2px dashed var(--border); position: relative; }
.bpass-dots::after {
  content: "✈";
  position: absolute;
  left: 50%;
  top: -0.72em;
  transform: translateX(-50%);
  padding: 0 8px;
  background: var(--surface);
  color: var(--accent);
  font-size: 17px;
  line-height: 1.4;
}
.bpass-cells {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 12px 16px;
  margin-top: 16px;
  border-top: 1px solid var(--hairline);
  padding-top: 14px;
}
.bpass-cell .lbl {
  font-family: var(--mono);
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
}
.bpass-cell .val { font-family: var(--display); font-size: 21px; font-weight: 700; letter-spacing: -0.015em; margin-top: 3px; line-height: 1.15; }
.bpass-cell .note { font-size: 12px; color: var(--ink-2); margin-top: 2px; }
.bpass-fine { margin: 12px 0 0; font-size: 12px; color: var(--muted); }
/* Tear-off stub. The dashed rule is the perforation; the notches are
   page-coloured discs hanging half off the card edge, as if punched. */
.bpass-stub {
  flex: 0 0 150px;
  position: relative;
  border-left: 2px dashed var(--border);
  padding: 27px 14px 14px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  text-align: center;
}
.bpass-stub-code { font-family: var(--mono); font-size: 32px; line-height: 1; margin-top: 6px; }
.bpass-stub-seat { font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.14em; color: var(--muted); text-transform: uppercase; }
/* Two stripe periods laid over each other; where they interfere the bars
   come out in the mixed thick-thin runs of a real barcode. */
.bpass-barcode {
  width: 100%;
  height: 34px;
  opacity: 0.8;
  background:
    repeating-linear-gradient(90deg, var(--ink) 0 2px, transparent 2px 5px),
    repeating-linear-gradient(90deg, var(--ink) 0 1px, transparent 1px 8px);
}
@media (max-width: 1160px) { .bpass-cells { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 640px) {
  .bpass { flex-direction: column; }
  .bpass-main { padding: 23px 16px 14px; }
  .bpass-head { font-size: 9.5px; letter-spacing: 0.04em; }
  .bpass-code, .bpass-stub-code { font-size: 28px; }
  .bpass-cells { grid-template-columns: repeat(2, 1fr); }
  .bpass-cells > .bpass-cell:last-child:nth-child(odd) { grid-column: 1 / -1; }
  .bpass-stub {
    flex: none;
    border-left: none;
    border-top: 2px dashed var(--border);
    flex-direction: row;
    justify-content: space-between;
    padding: 12px 16px;
  }
  .bpass-barcode { width: 96px; height: 26px; }
  .bpass-stub-code { margin-top: 0; }
}

/* Daily budget by travel style: three columns, the researched one tinted. */
.tier-band { margin: 0 0 16px; border: 1px solid var(--border); border-radius: 20px; padding: 6px; }
.tier-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.tier { padding: 16px 14px 14px; border-radius: 15px; text-align: center; }
.tier.is-mid { background: var(--wash); }
.tier-label { font-size: 13.5px; font-weight: 600; color: var(--muted); }
.tier.is-mid .tier-label { color: var(--accent-text); }
.tier-val { font-family: var(--display); font-weight: 700; font-size: 27px; letter-spacing: -0.02em; line-height: 1.15; margin: 4px 0 2px; }
.tier-per { font-family: system-ui, sans-serif; font-weight: 400; font-size: 13px; letter-spacing: 0; color: var(--muted); margin-left: 2px; }
.tier.is-mid .tier-per { color: var(--ink-2); }
.tier-sub { font-size: 13px; color: var(--ink-2); }
.tier-note { margin: 4px 10px 8px; padding-top: 8px; font-size: 13px; color: var(--muted); text-align: center; }
.tier-note a { color: var(--ink-2); text-decoration: underline; text-underline-offset: 3px; }
@media (max-width: 560px) {
  .tier { padding: 12px 4px 10px; }
  .tier-val { font-size: 19px; }
  .tier-per { display: block; margin: 0; }
  .tier-sub { font-size: 11.5px; }
}

/* Getting there: the route the pass draws, priced. */
.flight-band { margin: 0 0 16px; padding: 18px 24px 16px; border: 1px solid var(--border); border-radius: 20px; }
.flight-head { font-family: var(--display); font-weight: 700; font-size: 18.5px; letter-spacing: -0.01em; margin-bottom: 8px; }
.flight-sub { font-family: system-ui, sans-serif; font-weight: 400; font-size: 13.5px; letter-spacing: 0; color: var(--muted); margin-left: 8px; }
.flight-row { display: flex; align-items: baseline; gap: 10px; padding: 6px 0; }
.flight-origin { font-size: 15px; color: var(--ink-2); white-space: nowrap; }
.flight-dots { flex: 1; border-bottom: 2px dotted var(--border); transform: translateY(-4px); }
.flight-fare { font-family: var(--display); font-weight: 700; font-size: 18px; white-space: nowrap; }
.flight-note { margin: 10px 0 0; padding-top: 10px; border-top: 1px solid var(--hairline); font-size: 13px; color: var(--muted); }
@media (max-width: 560px) {
  .flight-band { padding: 14px 16px 12px; }
  .flight-origin { font-size: 14px; white-space: normal; }
  .flight-fare { font-size: 16px; }
}
.freshness { margin: 0 0 8px; font-size: 13.5px; color: var(--muted); }
.freshness time { font-weight: 600; color: var(--ink-2); }

/* ---------- City guide: layout ----------
   A contents list down the left that follows the reader, and the guide in a
   column narrow enough to read. Under 1000px the list becomes a strip of
   chips pinned to the top of the screen. */
.guide {
  display: grid;
  grid-template-columns: 190px minmax(0, 1fr);
  gap: 64px;
  align-items: start;
  margin-top: 36px;
}
.guide-body { min-width: 0; max-width: 800px; }
.jump-nav {
  position: sticky;
  top: 24px;
  display: flex;
  flex-direction: column;
  gap: 1px;
  max-height: calc(100vh - 48px);
  overflow-y: auto;
  scrollbar-width: none;
}
.jump-nav::-webkit-scrollbar { display: none; }
.jump-nav a {
  padding: 7px 14px;
  border-left: 2px solid var(--hairline);
  color: var(--muted);
  font-size: 14.5px;
  font-weight: 600;
  white-space: nowrap;
}
.jump-nav a:hover { color: var(--ink); text-decoration: none; }
/* Scroll-spy: the entry for the section under the reading line. */
.jump-nav a.active { color: var(--ink); border-left-color: var(--accent); }
@media (max-width: 1000px) {
  .guide { display: block; margin-top: 20px; }
  .guide-body { max-width: none; }
  .jump-nav {
    top: 0;
    z-index: 40;
    flex-direction: row;
    gap: 6px;
    max-height: none;
    overflow-x: auto;
    overflow-y: hidden;
    margin: 0 -24px 22px;
    padding: 10px 24px;
    background: var(--page);
    border-bottom: 1px solid var(--hairline);
  }
  .jump-nav a {
    flex: 0 0 auto;
    padding: 8px 14px;
    border: 1.5px solid var(--border);
    border-radius: 999px;
    color: var(--ink-2);
    font-size: 13.5px;
  }
  .jump-nav a.active { background: var(--ink); border-color: var(--ink); color: var(--page); }
}
@media (max-width: 420px) { .jump-nav { margin: 0 -16px 20px; padding: 10px 16px; } }

/* ---------- Sections ---------- */
/* scroll-margin clears the pinned chip strip on narrow screens and gives a
   little air above the heading on wide ones. */
.section { margin: 56px 0; }
.section, .flight-band { scroll-margin-top: 76px; }
.guide-body > .section:first-child { margin-top: 0; }
.section > h2 { margin: 0 0 16px; }
.section > h3 { margin: 30px 0 10px; }
.section p { color: var(--ink-2); margin: 10px 0; }
.section p strong, .section li strong { color: var(--ink); }
.section ul { margin: 10px 0; padding-left: 22px; color: var(--ink-2); }
.section li { margin: 7px 0; }
.section li::marker { color: var(--accent); }
.section .sub { color: var(--muted); }
.h3-icon { margin-right: 8px; }
@media (max-width: 640px) { .section { margin: 44px 0; } }

.callout {
  background: var(--wash);
  border-radius: var(--r-box);
  padding: 16px 20px;
  margin: 16px 0;
  color: var(--ink-2);
  font-size: 15.5px;
}
.callout strong { color: var(--ink); }

.fact-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 0 28px; }
.fact { border-top: 1px solid var(--hairline); padding: 14px 0 16px; }
.fact .lbl { font-size: 13px; font-weight: 600; color: var(--muted); }
.fact .val { font-size: 15.5px; margin-top: 3px; }
/* The season tile takes the whole row: it carries the 12-month strip under
   its prose, and both need more than one grid cell's width. */
.fact-wide { grid-column: 1 / -1; }
.fact .mo-strip { margin-top: 12px; max-width: 480px; }

/* Full-width photo, dealt between the long text sections of a guide. */
.photo-break { margin: 48px 0; }
.photo-break img {
  display: block;
  width: 100%;
  aspect-ratio: 2 / 1;
  object-fit: cover;
  border-radius: var(--r-photo);
  background: var(--wash);
}
.photo-break figcaption {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 10px;
  font-size: 13.5px;
  color: var(--ink-2);
  margin-top: 10px;
}
.photo-break .credit { color: var(--muted); font-size: 12.5px; white-space: nowrap; }
@media (max-width: 640px) {
  .photo-break { margin: 36px 0; }
  .photo-break img { aspect-ratio: 3 / 2; border-radius: 14px; }
}

.map-embed { border-radius: var(--r-photo); overflow: hidden; background: var(--wash); }
.map-embed iframe { display: block; width: 100%; height: 380px; border: 0; }
.map-links { font-size: 14px; color: var(--ink-2); margin: 10px 0 0; }
@media (max-width: 640px) { .map-embed iframe { height: 280px; } }

/* Entry & visa */
.visa-card { padding: 20px 22px; border-radius: var(--r-box); background: var(--wash); }
.visa-answer { margin: 0; font-size: 16.5px; line-height: 1.6; color: var(--ink) !important; }
.visa-caveat { margin: 14px 0 0 !important; padding-top: 14px; border-top: 1px solid var(--border); font-size: 13.5px; color: var(--muted) !important; }

/* Trip cost calculator */
.calc-controls { display: flex; flex-wrap: wrap; gap: 16px; align-items: flex-end; margin: 4px 0 18px; }
.calc-field { display: flex; flex-direction: column; gap: 6px; }
.calc-field label { font-size: 13.5px; font-weight: 600; color: var(--ink-2); }
.calc-field input[type="number"] { width: 96px; }
.calc-tier-btns { display: flex; gap: 6px; }
.calc-tier-btn { min-height: 46px; }
.calc-tier-btn.active,
.itin-tab.active { background: var(--ink); border-color: var(--ink); color: var(--page); }
.calc-results { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 10px; }
.calc-card { background: var(--wash); border-radius: var(--r-box); padding: 16px 18px; }
.calc-card[hidden] { display: none; }
.calc-card .lbl { font-size: 13.5px; color: var(--ink-2); }
.calc-card .val { font-family: var(--display); font-size: 25px; font-weight: 700; letter-spacing: -0.02em; margin-top: 2px; }
.calc-card-total { background: var(--ink); color: var(--page); }
.calc-card-total .lbl { color: inherit; opacity: 0.8; }
.calc-note { font-size: 14px; color: var(--ink-2); margin: 12px 0 2px; }
.calc-disclaimer { font-size: 13px; color: var(--muted) !important; margin: 6px 0 0; }
@media (max-width: 640px) {
  .calc-controls { flex-direction: column; align-items: stretch; }
  .calc-field input[type="number"], .calc-field select { width: 100%; }
}

/* Price check-ins */
.price-check[hidden] { display: none; }
.pc-rows { display: grid; gap: 10px; margin-top: 14px; }
.pc-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 8px 16px;
  align-items: center;
  padding: 14px 18px;
  border-radius: var(--r-box);
  background: var(--wash);
}
.pc-what { display: flex; flex-direction: column; gap: 2px; }
.pc-label { font-size: 13.5px; color: var(--ink-2); }
.pc-price { font-family: var(--display); font-size: 19px; font-weight: 700; font-variant-numeric: tabular-nums; }
.pc-btns { display: flex; flex-wrap: wrap; gap: 6px; justify-content: flex-end; }
.pc-btn.is-on,
.scam-btn.is-on { background: var(--accent); border-color: var(--accent); color: #fff; }
.pc-status, .pc-paid { grid-column: 1 / -1; margin: 0; }
.pc-paid { display: flex; flex-wrap: wrap; align-items: end; gap: 8px; }
.pc-paid label { display: flex; flex-direction: column; gap: 4px; font-size: 13.5px; }
.pc-paid input { width: 200px; }
@media (max-width: 640px) {
  .pc-row { grid-template-columns: 1fr; }
  .pc-btns { justify-content: flex-start; }
}

/* Things to do */
.activity-group { margin: 0 0 6px; }
.activity-item { display: flex; align-items: center; gap: 16px; padding: 12px 0; border-bottom: 1px solid var(--hairline); }
.activity-item:last-child { border-bottom: none; }
.activity-photo { flex: none; width: 96px; height: 96px; object-fit: cover; border-radius: 12px; background: var(--wash); }
.activity-body { flex: 1; display: flex; justify-content: space-between; align-items: baseline; gap: 12px; min-width: 0; }
/* The whole name + note block is the link to the venue search. min-height
   carries picks with no note up to a 44px target. */
.activity-main { flex: 1; min-width: 0; display: flex; flex-direction: column; justify-content: center; min-height: 44px; color: inherit; }
.activity-main:hover { text-decoration: none; }
.activity-name { font-weight: 700; font-size: 16px; color: var(--ink); }
.activity-main:hover .activity-name { text-decoration: underline; text-underline-offset: 3px; }
.activity-note { color: var(--ink-2); font-size: 14.5px; margin-top: 2px; }
.price-tag {
  flex: none;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-2);
  background: var(--wash);
  border-radius: 999px;
  padding: 3px 11px;
}
@media (max-width: 560px) { .activity-photo { width: 72px; height: 72px; } }

/* Definition-style lists (getting around, where to stay) */
dl { margin: 0; }
.dl-row { display: grid; grid-template-columns: 190px 1fr; gap: 16px; padding: 14px 0; border-bottom: 1px solid var(--hairline); }
.dl-row:last-child { border-bottom: none; }
.dl-row dt { font-weight: 700; font-size: 15.5px; margin: 0; }
.dl-row dd { margin: 0; color: var(--ink-2); font-size: 15.5px; }
@media (max-width: 560px) { .dl-row { grid-template-columns: 1fr; gap: 3px; } }

/* Itineraries */
.itin-tabs { display: flex; flex-wrap: wrap; gap: 6px; margin: 16px 0 18px; }
.itin-plan[hidden] { display: none; }
.itin-plan > p { margin: 0 0 16px; }
.itin-days { margin: 0 !important; padding: 0 !important; list-style: none; display: grid; gap: 0; }
.itin-days li {
  position: relative;
  margin: 0;
  padding: 0 0 22px 26px;
  border-left: 2px solid var(--hairline);
  font-size: 15.5px;
  line-height: 1.6;
}
.itin-days li:last-child { padding-bottom: 0; border-left-color: transparent; }
.itin-days li::before {
  content: "";
  position: absolute;
  left: -7px;
  top: 5px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--page);
  border: 3px solid var(--accent);
}
.itin-when { display: block; font-weight: 700; color: var(--ink); margin-bottom: 2px; }

/* Scam reports */
.scam-list li { margin-bottom: 12px; }
.scam-report { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 8px; }
.scam-btn { min-height: 34px; padding: 0 12px; font-size: 13px; }
.scam-count:empty { display: none; }

/* FAQs: ruled rows, not boxes. */
details { border-bottom: 1px solid var(--hairline); padding: 4px 0; }
details:first-of-type { border-top: 1px solid var(--hairline); }
details summary {
  position: relative;
  cursor: pointer;
  list-style: none;
  padding: 14px 40px 14px 0;
  font-weight: 700;
  font-size: 16.5px;
  color: var(--ink);
}
details summary::-webkit-details-marker { display: none; }
details summary::after {
  content: "+";
  position: absolute;
  right: 4px;
  top: 8px;
  font-family: var(--display);
  font-size: 26px;
  line-height: 1.2;
  color: var(--accent);
  transition: transform 200ms ease;
}
details[open] summary::after { transform: rotate(45deg); }
details p { margin: 0 0 16px !important; color: var(--ink-2); max-width: 68ch; }

.see-also { margin: 0; padding-left: 22px; }
.see-also li { margin: 7px 0; }

.to-top { position: fixed; right: 18px; bottom: 18px; z-index: 50; box-shadow: var(--shadow); }

/* ---------- Sharing ---------- */
.share-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 24px 0 8px; }
.share-lbl { font-size: 14px; font-weight: 600; color: var(--ink-2); margin-right: 4px; }
.share-btn { min-height: 38px; padding: 0 14px; font-size: 13.5px; }
@media (max-width: 640px) { .share-lbl { flex: 0 0 100%; margin: 0 0 2px; } }

/* ---------- Country page ---------- */
.country-cost-table th[scope="row"] a,
.cost-index-table th[scope="row"] a { color: var(--accent-text); }
.sort-btn { all: unset; cursor: pointer; display: inline-flex; align-items: center; gap: 4px; font: inherit; color: inherit; }
.sort-btn::after { content: "↕"; font-size: 11px; color: var(--muted); }
th[aria-sort="ascending"] .sort-btn::after { content: "↑"; color: var(--accent-text); }
th[aria-sort="descending"] .sort-btn::after { content: "↓"; color: var(--accent-text); }
.sort-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
.calc-tier-set { border: 0; padding: 0; margin: 0 0 16px; display: flex; flex-wrap: wrap; gap: 8px 18px; }
.calc-tier-set legend { font-size: 13.5px; font-weight: 600; color: var(--ink-2); padding: 0; margin-bottom: 8px; width: 100%; }
.calc-radio { display: inline-flex; align-items: center; gap: 7px; font-size: 15px; cursor: pointer; }
.calc-radio input { accent-color: var(--accent); width: 18px; height: 18px; }
.country-calc-cities { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; }
.country-calc-cities .calc-field input[type="number"] { width: 100%; }
.country-calc-out { font-size: 17px; margin: 16px 0 0; }

/* ---------- Rankings and the cost index ---------- */
.rank-country { font-size: 13px; color: var(--muted); margin-top: 1px; }
.rank-name { font-weight: 700; }
/* Relative-cost bar under each daily-budget figure, scaled to the priciest
   city in the current view. */
.cost-bar { height: 5px; min-width: 90px; margin-top: 6px; border-radius: 3px; background: var(--hairline); overflow: hidden; }
.cost-bar span { display: block; height: 100%; border-radius: 3px; background: var(--accent); }
.cost-index-actions { margin: 0 0 8px; }
.download-btn { margin: 0 10px 10px 0; }
.cost-index-filters { display: flex; flex-wrap: wrap; gap: 12px 16px; align-items: flex-end; margin: 0 0 14px; }
.cost-index-filters[hidden] { display: none; }
.cost-index-count { font-size: 14px; color: var(--ink-2); margin: 0 0 10px; }
.cite-text { margin: 12px 0; padding: 16px 20px; background: var(--wash); border-radius: var(--r-box); font-size: 15px; }
.cite-text p { margin: 0; }

/* Under 640px the ranked table becomes a stack of cards: seven columns on a
   phone meant four of them lived behind a horizontal scroll nobody found.
   Each row is a grid — rank and city name across the top, then each figure
   as its own labelled line, the label drawn from the cell's data-label. */
@media (max-width: 640px) {
  .rank-table thead { display: none; }
  .rank-table, .rank-table tbody { display: block; }
  .rank-table tr {
    display: grid;
    grid-template-columns: auto 1fr;
    column-gap: 10px;
    align-items: center;
    border-radius: var(--r-box);
    background: var(--wash);
    padding: 14px 16px;
    margin-bottom: 10px;
  }
  .rank-table td { display: block; border-bottom: none; padding: 2px 0; }
  .rank-table td.rank-num { font-size: 13px; font-weight: 700; color: var(--muted); }
  .rank-table td.rank-num::before { content: "#"; }
  .rank-table td.num {
    grid-column: 1 / -1;
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
    padding: 4px 0;
  }
  .rank-table td.num::before {
    content: attr(data-label);
    font-size: 13px;
    font-weight: 400;
    color: var(--muted);
    font-variant-numeric: normal;
    white-space: nowrap;
  }
  .rank-table td.rank-city { padding-bottom: 6px; }
  .rank-table td.rank-city + td.num { border-top: 1px solid var(--border); margin-top: 4px; padding-top: 8px; }
  .rank-table .cost-bar { display: none; }
}

/* ---------- Head-to-head pages ---------- */
.vs-crumb { margin: 32px 0 14px; font-size: 14px; color: var(--muted); }
.vs-crumb a { color: var(--ink-2); font-weight: 600; }
.vs-title { margin: 0 0 28px; }
/* The joiner stays visually subordinate — the two city names are the
   heading. */
.vs-title span { color: var(--red); margin: 0 0.12em; }
.vs-hero { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 8px; }
.vs-side { display: flex; flex-direction: column; color: var(--ink); min-width: 0; }
.vs-side:hover { text-decoration: none; }
.vs-side .card-photo { aspect-ratio: 3 / 2; margin-bottom: 14px; }
.vs-side .flag { font-size: 22px; line-height: 1; margin-bottom: 4px; }
.vs-side h2 { font-size: clamp(22px, 3vw, 34px); }
.vs-side:hover h2 { text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 4px; }
.vs-budget { font-size: 16px; color: var(--ink-2); margin-top: 4px; }
.vs-verdict p { margin: 0; font-size: 17px; line-height: 1.6; }

/* A comparison is a long read of a dozen sections. Only the verdict keeps
   the tinted band; the rest sit on the page, ruled apart. */
.vs-page .panel { background: none; border-radius: 0; padding: 0; margin: 64px 0; }
.vs-page .panel.vs-verdict,
.vs-page .panel.vs-poll,
.vs-page .panel.vs-picker { background: var(--wash); border-radius: 24px; padding: 28px 32px; margin: 32px 0; }
.vs-page .panel .mo { background: var(--wash); }
.vs-page .panel .mo.on { background: var(--accent); }
.vs-page .panel .mo.off { background: transparent; }
.vs-page .panel .table-scroll thead th { background: var(--page); }
.vs-page .panel > p, .vs-page .panel > ul { max-width: 80ch; }
@media (max-width: 640px) {
  .vs-page .panel { margin: 44px 0; }
  .vs-page .panel.vs-verdict, .vs-page .panel.vs-poll { padding: 20px 18px; border-radius: 18px; }
}

/* The winning cell is marked by weight and a small word, never by colour
   alone. */
.vs-table th[scope="row"] { font-size: 14.5px; color: var(--ink-2); }
.vs-table th[scope="row"] .vs-note { display: block; font-size: 12.5px; font-weight: 400; color: var(--muted); }
.vs-table td { font-weight: 400; }
.vs-table td.vs-win { font-weight: 700; color: var(--ink); }
.vs-win-tag { display: block; font-size: 11.5px; font-weight: 700; color: var(--good); }

/* /vs/ poll */
.vs-poll-btns { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.vs-poll-btn {
  min-height: 56px;
  border: 1.5px solid var(--border);
  background: var(--surface);
  color: var(--ink);
  border-radius: var(--r-box);
  padding: 12px 10px;
  font: inherit;
  font-size: 16px;
  font-weight: 700;
  cursor: pointer;
  transition: border-color 140ms ease, transform 140ms ease;
}
.vs-poll-btn:hover { border-color: var(--ink); transform: translateY(-1px); }
.vs-poll-btn.is-on { border-color: var(--accent); background: var(--accent); color: #fff; }
.vs-poll-pct { font-variant-numeric: tabular-nums; opacity: 0.85; }
.vs-poll-bar { height: 8px; margin-top: 14px; border-radius: 999px; background: var(--border); overflow: hidden; }
.vs-poll-bar[hidden] { display: none; }
.vs-poll-bar span { display: block; height: 100%; background: var(--accent); transition: width 400ms ease; }
.vs-poll-note { margin: 12px 0 0; }

/* Month strips */
.vs-months { margin-bottom: 16px; }
.vs-months:last-child { margin-bottom: 0; }
.vs-months-city { font-size: 15px; font-weight: 700; margin-bottom: 6px; }
.mo-strip { display: flex; gap: 3px; }
.mo {
  flex: 1 1 0;
  text-align: center;
  font-size: 11.5px;
  line-height: 26px;
  height: 26px;
  border-radius: 7px;
  color: var(--muted);
  background: var(--wash);
}
.panel .mo, .calc-card .mo { background: var(--surface); }
.mo.on { background: var(--accent); color: #fff; font-weight: 700; }
/* Dashed rather than a second colour: "avoid" is the absence of a
   recommendation, and reads better as an outline than as a rival fill. */
.mo.off { background: transparent; box-shadow: inset 0 0 0 1px var(--border); opacity: 0.7; }
.vs-months-label { font-size: 13px; color: var(--ink-2); margin-top: 5px; }

.vs-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 32px; }
.vs-cols h3 { margin: 0 0 8px; }
.vs-tagline { font-size: 15px; color: var(--ink-2); line-height: 1.55; margin: 0 0 12px; }
.vs-picks { margin: 0 0 12px !important; padding: 0 !important; list-style: none; font-size: 15px; }
.vs-picks li {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  gap: 0 8px;
  margin: 0;
  padding: 8px 0;
  border-bottom: 1px solid var(--hairline);
}
.vs-picks li:last-child { border-bottom: none; }
.vs-price { color: var(--ink-2); font-size: 13.5px; font-weight: 600; }
.vs-cat { grid-column: 1 / -1; font-size: 13px; color: var(--muted); }
.vs-guide-link { font-size: 15px; font-weight: 700; }
.vs-same-intro { margin: 16px 0 10px; }
.vs-same { display: grid; grid-template-columns: minmax(110px, max-content) 1fr; gap: 8px 18px; margin: 0; font-size: 15px; }
.vs-same dt { color: var(--muted); font-size: 14px; }
.vs-same dd { margin: 0; color: var(--ink-2); }

/* Comparison deep-dive (allowlisted pairs) */
.vs-deep p { line-height: 1.65; }
.vs-deep ul { margin: 8px 0 0; padding-left: 22px; }
.vs-deep li { margin-bottom: 6px; line-height: 1.6; }
.vs-direct { font-size: 19px; font-weight: 700; color: var(--ink) !important; margin: 4px 0 12px; }
.vs-month-table { margin-top: 20px; }
.vs-month-table caption { caption-side: top; text-align: left; font-weight: 700; font-size: 15px; padding: 0 0 8px; }
.vs-month-table td { font-size: 14px; font-weight: 600; }
.vs-month-table .mo-good { color: var(--good); }
.vs-month-table .mo-avoid { color: var(--muted); }
.vs-month-table .mo-mid { color: var(--ink-2); font-weight: 500; }
.vs-faq h3 { margin: 22px 0 6px; }
.vs-faq h3:first-of-type { margin-top: 6px; }
.vs-faq p { margin: 0; }
.home-vs .vs-picker-row { margin-top: 6px; }

@media (max-width: 640px) {
  /* The two photos stay side by side even on a phone — seeing both at once
     is the whole point of the page. */
  .vs-hero { gap: 12px; }
  .vs-budget { font-size: 14px; }
  .vs-cols { grid-template-columns: 1fr; gap: 22px; }
  .mo { font-size: 10px; }
  .vs-same { grid-template-columns: 1fr; gap: 2px 0; }
  .vs-same dd { margin-bottom: 8px; }
}

/* ---------- Passport ----------
   Each saved city is an entry stamp: cycling ink colours, each pressed a
   little crooked, every fifth-ish one oval because border posts don't buy
   their kit from one supplier. Markup is a plain link grid in renderSaved();
   everything stampy is CSS. */
.passport-meta {
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-2);
  margin: 2px 0 22px;
}
.stamp-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 26px 20px; margin: 0 0 36px; }
.stamp {
  --ink-s: var(--stamp-a);
  position: relative;
  display: block;
  color: var(--ink-s);
  border: 2px solid var(--ink-s);
  border-radius: 12px;
  padding: 16px 14px 12px;
  text-align: center;
  transform: rotate(-2.4deg);
  transition: transform 0.15s ease;
}
.stamp::before {
  content: "";
  position: absolute;
  inset: 3px;
  border: 1px solid var(--ink-s);
  border-radius: 9px;
  opacity: 0.7;
  pointer-events: none;
}
.stamp:hover { text-decoration: none; transform: rotate(0deg) scale(1.03); }
.stamp:nth-child(4n+2) { --ink-s: var(--stamp-b); transform: rotate(1.9deg); }
.stamp:nth-child(4n+3) { --ink-s: var(--stamp-c); transform: rotate(-1.1deg); }
.stamp:nth-child(4n+4) { --ink-s: var(--stamp-d); transform: rotate(2.7deg); }
.stamp:nth-child(4n+2):hover,
.stamp:nth-child(4n+3):hover,
.stamp:nth-child(4n+4):hover { transform: rotate(0deg) scale(1.03); }
.stamp:nth-child(5n+3) { border-radius: 50% / 44%; padding: 22px 20px 16px; }
.stamp:nth-child(5n+3)::before { border-radius: 50% / 44%; inset: 4px; }
.stamp.is-visited { border-style: double; border-width: 4px; }
.stamp-top { display: block; font-family: var(--mono); font-size: 10px; letter-spacing: 0.3em; text-transform: uppercase; opacity: 0.75; }
.stamp-name { display: block; font-family: var(--mono); font-size: 20px; letter-spacing: 0.06em; text-transform: uppercase; margin: 4px 0 2px; }
.stamp-sub { display: block; font-size: 12.5px; opacity: 0.9; }
.stamp-no {
  display: block;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  opacity: 0.7;
  margin-top: 9px;
  padding-top: 7px;
  border-top: 1px dashed var(--ink-s);
}
.passport-share { margin-top: 28px; }
.passport-link-row { display: flex; flex-wrap: wrap; gap: 8px; margin: 10px 0; }
.passport-link-row input { flex: 1 1 260px; min-width: 0; font-size: 14px; }
.passport-cta { margin-top: 24px; }
.passport-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-top: 10px; }
.passport-img-note { font-size: 13px; }

/* ---------- 404 ---------- */
.nf-links { display: flex; flex-wrap: wrap; gap: 10px; margin: 20px 0 6px; }

/* ---------- Footer ---------- */
.site-footer {
  position: relative;
  margin-top: 96px;
  padding: 51px 0 44px;
  background: var(--wash);
  color: var(--ink-2);
  font-size: 14.5px;
}
.site-footer::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 7px;
  background: var(--airmail);
}
.footer-in { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 28px 64px; align-items: start; }
.footer-line { margin: 10px 0 0; max-width: 40ch; color: var(--ink-2); }
.footer-nav { display: grid; grid-template-columns: repeat(2, auto); gap: 8px 40px; }
.footer-nav a { color: var(--ink); font-weight: 600; }
.footer-note { grid-column: 1 / -1; margin: 0; padding-top: 22px; border-top: 1px solid var(--border); color: var(--muted); font-size: 13.5px; max-width: none; }
@media (max-width: 640px) {
  .site-footer { margin-top: 64px; }
  .footer-in { grid-template-columns: 1fr; }
}

/* ---------- Motion ----------
   Page to page, the browser cross-fades; a photo that was clicked travels
   into the hero of the page it opens (app.js names the pair). */
@view-transition { navigation: auto; }
.hero-photo .cover-img { view-transition-name: hero-photo; }
::view-transition-group(hero-photo) { animation-duration: 420ms; animation-timing-function: cubic-bezier(0.3, 0.7, 0.2, 1); }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: 220ms; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  @view-transition { navigation: none; }
  *, *::before, *::after { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
  .img-fade-root .fade-img { opacity: 1; }
}
