/* =============================================================
   São Tomé Surf Travel — folha de estilos / stylesheet
   ============================================================= */

/* ---------- Tipo de letra dos títulos / title typeface ----------
   Gilda Display (SIL Open Font License), servida daqui e não do Google, como
   as outras letras do site: menos um servidor de fora no caminho e nada que
   dependa de terceiros para a página abrir.

   Dois subconjuntos, latin e latin-ext, cada um com o seu unicode-range: o
   navegador só descarrega o segundo se a página precisar de um sinal que o
   primeiro não tenha. Ao contrário da Salt Water, esta tem minúsculas a sério,
   por isso os títulos passam a sair como estão escritos e não em caixa alta.

   Gilda Display (SIL Open Font License), served from here rather than from
   Google, like the site's other faces: one less outside server in the path and
   nothing third-party standing between the page and opening.

   Two subsets, latin and latin-ext, each with its own unicode-range: the
   browser only fetches the second if the page needs a character the first does
   not carry. Unlike Salt Water, this one has real lowercase, so headings now
   come out as written instead of in caps. */
@font-face {
  font-family: "Gilda Display";
  src: url("../fonts/gilda-display-latin.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Gilda Display";
  src: url("../fonts/gilda-display-latin-ext.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ---------- Design tokens ---------- */
:root {
  /* Cores — paleta construída a partir da cor da marca #ad6145 (terracota)
     Palette built from the brand colour #ad6145 (terracotta) */
  --brand: #ad6145;        /* principal: botões, marcadores, estados activos */
  --brand-deep: #7d4330;   /* escuro: links, fundos seleccionados */
  --brand-mid: #99563d;    /* rótulos e texto pequeno de destaque */
  --brand-soft: #e3b39c;   /* destaque sobre fundos escuros */
  --accent: #d9a04e;       /* ocre: brilhos, estrelas, época alta */
  --deep: #32201a;         /* fundo das secções escuras */
  --ink: #2b1c16;
  --ink-soft: #4d382e;
  --muted: #7a655a;
  --sand: #f4e6db;
  --cream: #fdf8f4;
  --paper: #ffffff;
  --line: rgba(43, 28, 22, 0.14);
  --line-soft: rgba(43, 28, 22, 0.08);

  /* Tipografia */
  /* A Gilda Display à frente, com serifas de sistema atrás para o caso de a
     letra não chegar. Ao contrário da anterior, esta traz o conjunto latino
     completo, por isso não é preciso guardar-lhe as costas para os sinais.
     Gilda Display first, with system serifs behind in case the face never
     arrives. Unlike the previous one, this carries the full Latin set, so
     nothing has to cover for it on punctuation. */
  --font-display: "Gilda Display", "Iowan Old Style", "Palatino Linotype", Georgia, serif;
  --font-body: "Outfit", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;

  /* Espaço & forma */
  --r-sm: 10px;
  --r-md: 18px;
  --r-lg: 28px;
  --r-xl: 40px;
  --pad: clamp(1.1rem, 4vw, 2rem);
  --maxw: 1200px;
  --shadow-sm: 0 2px 10px rgba(43, 28, 22, 0.07);
  --shadow: 0 12px 34px -14px rgba(43, 28, 22, 0.26);
  --shadow-lg: 0 30px 70px -30px rgba(43, 28, 22, 0.42);
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
}

/* ---------- Reset ---------- */
*,
*::before,
*::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  font-family: var(--font-body);
  font-size: clamp(1rem, 0.97rem + 0.18vw, 1.08rem);
  line-height: 1.65;
  color: var(--ink);
  background: var(--cream);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img, svg, video { max-width: 100%; display: block; }
a { color: inherit; }
button { font: inherit; color: inherit; }

h1, h2, h3, h4 {
  font-family: var(--font-display);
  /* A Gilda Display também só tem um peso. Sem font-synthesis: none o browser
     engorda-a à força onde o HTML pede negrito, e uma serifa fina desenhada a
     um só peso fica borrada quando isso acontece.
     Gilda Display also ships a single weight. Without font-synthesis: none the
     browser fattens it by force wherever the HTML asks for bold, and a fine
     serif drawn at one weight goes muddy when that happens. */
  font-weight: 400;
  font-synthesis: none;
  /* A anterior era unicase, sem descendentes nenhuns, e por isso aguentava
     1.08 de entrelinha e um bocadinho de tracking. Esta tem minúsculas com
     hastes e caudas: apertada assim, os p e os g da linha de cima tocavam nas
     maiúsculas da linha de baixo. E uma serifa desenhada para títulos já tem o
     espaçamento certo de origem, por isso o tracking volta a zero.
     The previous face was unicase, with no descenders at all, so it tolerated
     1.08 leading and a touch of tracking. This one has lowercase with stems and
     tails: held that tight, the p's and g's of one line met the capitals of the
     next. And a serif drawn for display already carries the right fit, so the
     tracking goes back to zero. */
  line-height: 1.16;
  letter-spacing: 0;
  margin: 0 0 0.5em;
  text-wrap: balance;
}
h1 { font-size: clamp(2.3rem, 1.5rem + 3.6vw, 4.4rem); }
h2 { font-size: clamp(1.8rem, 1.3rem + 2.1vw, 2.9rem); }
h3 { font-size: clamp(1.2rem, 1.05rem + 0.7vw, 1.5rem); }
p { margin: 0 0 1em; text-wrap: pretty; }
p:last-child { margin-bottom: 0; }

:focus-visible {
  outline: 3px solid var(--brand-mid);
  outline-offset: 3px;
  border-radius: 4px;
}

::selection { background: var(--brand-soft); color: var(--deep); }

/* ---------- Layout helpers ---------- */
.wrap {
  width: min(100% - 2 * var(--pad), var(--maxw));
  margin-inline: auto;
}
.wrap--narrow { width: min(100% - 2 * var(--pad), 820px); margin-inline: auto; }

.section { padding: clamp(3.5rem, 8vw, 7rem) 0; }
.section--tight { padding: clamp(2.5rem, 5vw, 4rem) 0; }
.section--sand { background: var(--sand); }
.section--paper { background: var(--paper); }
.section--deep {
  background: var(--deep);
  color: var(--sand);
}
.section--deep h2, .section--deep h3 { color: #fff; }
.section--deep .kicker { color: var(--brand-soft); }

.kicker {
  display: inline-flex;
  align-items: center;
  gap: 0.55em;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--brand-mid);
  margin: 0 0 0.9rem;
}
.kicker::before {
  content: "";
  width: 26px;
  height: 2px;
  background: currentColor;
  border-radius: 2px;
}

.lead {
  font-size: clamp(1.05rem, 1rem + 0.45vw, 1.3rem);
  color: var(--muted);
  max-width: 62ch;
}
.section--deep .lead { color: rgba(255, 255, 255, 0.78); }

.head { max-width: 68ch; margin-bottom: clamp(2rem, 4vw, 3rem); }
.head--center { margin-inline: auto; text-align: center; }
.head--center .kicker { justify-content: center; }
.head--center .lead { margin-inline: auto; }

.grid { display: grid; gap: clamp(1rem, 2.2vw, 1.6rem); }
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr)); }
.grid--3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr)); }
.grid--4 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr)); }

/* ---------- Buttons ---------- */
.btn {
  --btn-bg: var(--brand);
  --btn-fg: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.55em;
  padding: 0.85em 1.5em;
  background: var(--btn-bg);
  color: var(--btn-fg);
  border: 1px solid transparent;
  border-radius: 999px;
  font-weight: 600;
  font-size: 0.98rem;
  letter-spacing: 0.01em;
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.25s var(--ease), box-shadow 0.25s var(--ease),
    background 0.25s var(--ease), color 0.25s var(--ease);
  box-shadow: 0 10px 24px -12px rgba(173, 97, 69, 0.55);
}
.btn:hover { transform: translateY(-2px); box-shadow: 0 16px 30px -14px rgba(173, 97, 69, 0.6); }
.btn:active { transform: translateY(0); }

.btn--ghost {
  --btn-bg: transparent;
  --btn-fg: var(--ink);
  border-color: var(--line);
  box-shadow: none;
}
.btn--ghost:hover { background: var(--ink); color: #fff; border-color: var(--ink); box-shadow: none; }

.btn--light {
  --btn-bg: rgba(255, 255, 255, 0.12);
  --btn-fg: #fff;
  border-color: rgba(255, 255, 255, 0.34);
  box-shadow: none;
  backdrop-filter: blur(6px);
}
.btn--light:hover { background: #fff; color: var(--deep); box-shadow: none; }

.btn--wa { --btn-bg: #21ba5a; box-shadow: 0 10px 24px -12px rgba(33, 186, 90, 0.9); }
.btn--wa:hover { box-shadow: 0 16px 30px -14px rgba(33, 186, 90, 0.95); }

.btn--sm { padding: 0.6em 1.1em; font-size: 0.88rem; }
.btn-row { display: flex; flex-wrap: wrap; gap: 0.75rem; }

.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  font-weight: 600;
  color: var(--brand-deep);
  text-decoration: none;
  border-bottom: 1.5px solid transparent;
  transition: border-color 0.2s, gap 0.2s var(--ease);
}
.link-arrow:hover { border-color: currentColor; gap: 0.75em; }
.link-arrow::after { content: "→"; }

/* ---------- Skip link ---------- */
.skip {
  position: absolute;
  left: 50%;
  top: -100px;
  transform: translateX(-50%);
  background: var(--ink);
  color: #fff;
  padding: 0.7em 1.2em;
  border-radius: 0 0 12px 12px;
  z-index: 200;
  text-decoration: none;
  transition: top 0.2s;
}
.skip:focus { top: 0; }

/* ---------- Header ---------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(253, 248, 244, 0.85);
  backdrop-filter: blur(14px) saturate(1.4);
  border-bottom: 1px solid transparent;
  transition: border-color 0.3s, background 0.3s, box-shadow 0.3s;
}
.site-header.is-stuck {
  border-color: var(--line-soft);
  box-shadow: 0 6px 24px -18px rgba(43, 28, 22, 0.55);
}
.header-inner {
  display: flex;
  align-items: center;
  gap: 1rem;
  min-height: 72px;
  padding-block: 0.6rem;
}

/* A marca é apenas o logótipo — o próprio logótipo já contém o nome. */
.brand {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  margin-right: auto;
  flex-shrink: 0;
}
.brand .mark {
  height: 56px;
  width: auto;
  flex: none;
  object-fit: contain;
  transition: transform 0.3s var(--ease);
}
.brand:hover .mark { transform: scale(1.04); }
/* Todo o desenho a branco puro. brightness(0) achata tudo o que é opaco a
   preto e invert(1) levanta-o a branco, seja qual for a cor de origem: o
   castanho do disco, o preto do lettering, tudo sai igual. O canal alfa não é
   tocado, por isso as palmeiras, o surfista e a onda continuam vazados e
   deixam passar o castanho escuro do rodapé.
   The whole drawing in pure white. brightness(0) flattens everything opaque to
   black and invert(1) lifts it to white, whatever colour it started as: the
   brown of the disc, the black of the lettering, all come out the same. The
   alpha channel is untouched, so the palms, the surfer and the wave stay
   knocked out and let the footer's dark brown through. */
.site-footer .brand .mark {
  filter: brightness(0) invert(1);
  opacity: 1;
  /* Este logótipo é mais alto e traz o lettering em arco à volta do disco, que
     a 64px não se lia de todo. É preciso dar-lhe altura para o nome se ler.
     This logo is taller and carries the lettering arced around the disc, which
     at 64px could not be read at all. It needs height for the name to read. */
  height: clamp(96px, 9vw, 124px);
}
@media (max-width: 480px) { .brand .mark { height: 48px; } }
@media (prefers-reduced-motion: reduce) { .brand:hover .mark { transform: none; } }

.nav { display: flex; align-items: center; gap: 0.15rem; }
.nav a {
  position: relative;
  padding: 0.5rem 0.7rem;
  border-radius: 999px;
  text-decoration: none;
  font-size: 0.92rem;
  font-weight: 500;
  color: var(--ink-soft);
  white-space: nowrap;
  transition: color 0.2s, background 0.2s;
}
.nav a:hover { color: var(--ink); background: rgba(173, 97, 69, 0.09); }
.nav a[aria-current="page"] { color: var(--brand-deep); font-weight: 600; }
.nav a[aria-current="page"]::after {
  content: "";
  position: absolute;
  left: 0.7rem;
  right: 0.7rem;
  bottom: 0.18rem;
  height: 2px;
  border-radius: 2px;
  background: var(--brand);
}

.header-actions { display: flex; align-items: center; gap: 0.5rem; flex-shrink: 0; }

.nav [data-mobile-cta] { display: none; }

.lang {
  display: inline-flex;
  align-items: center;
  padding: 3px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.7);
}
/* O trocador passou de botões a ligações, para ser navegável e rastreável.
     O aspecto é o mesmo: os dois selectores partilham as regras.
     The switcher went from buttons to links, so it can be navigated and
     crawled. It looks the same: both selectors share the rules. */
.lang a,
.lang button {
  display: inline-block;
  text-decoration: none;
  border: 0;
  background: none;
  padding: 0.3em 0.72em;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--muted);
  cursor: pointer;
  transition: background 0.2s, color 0.2s;
}
.lang a[aria-current="page"],
.lang button[aria-pressed="true"] { background: var(--ink); color: #fff; }

.burger {
  display: none;
  width: 44px;
  height: 44px;
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.7);
  border-radius: 14px;
  cursor: pointer;
  place-items: center;
}
.burger span {
  display: block;
  width: 19px;
  height: 2px;
  background: var(--ink);
  border-radius: 2px;
  position: relative;
  transition: transform 0.3s var(--ease), background 0.2s;
}
.burger span::before,
.burger span::after {
  content: "";
  position: absolute;
  left: 0;
  width: 19px;
  height: 2px;
  background: var(--ink);
  border-radius: 2px;
  transition: transform 0.3s var(--ease), top 0.2s;
}
.burger span::before { top: -6px; }
.burger span::after { top: 6px; }
body.menu-open .burger span { background: transparent; }
body.menu-open .burger span::before { top: 0; transform: rotate(45deg); }
body.menu-open .burger span::after { top: 0; transform: rotate(-45deg); }

@media (max-width: 1140px) {
  .burger { display: grid; }
  .nav {
    position: fixed;
    inset: 72px 0 auto;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    background: var(--cream);
    border-bottom: 1px solid var(--line);
    padding: 0.6rem var(--pad) 1.4rem;
    max-height: calc(100dvh - 72px);
    overflow-y: auto;
    transform: translateY(-8px);
    opacity: 0;
    pointer-events: none;
    visibility: hidden;
    transition: opacity 0.25s, transform 0.25s var(--ease), visibility 0.25s;
    box-shadow: var(--shadow);
  }
  body.menu-open .nav {
    opacity: 1;
    transform: none;
    pointer-events: auto;
    visibility: visible;
  }
  .nav a { padding: 0.85rem 0.8rem; font-size: 1.05rem; border-radius: var(--r-sm); }
  .nav a[aria-current="page"]::after { display: none; }
  .nav a[aria-current="page"] { background: rgba(173, 97, 69, 0.12); }
  .header-cta { display: none; }
  .nav [data-mobile-cta] { display: inline-flex; }
}

/* ---------- Hero ---------- */
.hero {
  position: relative;
  isolation: isolate;
  color: #fff;
  /* Sem degradê castanho: a fotografia é o fundo. Este tom neutro só aparece
     enquanto não existir assets/img/hero.jpg.
     No brown gradient: the photograph is the background. This neutral tone
     only shows while assets/img/hero.jpg does not exist. */
  background: linear-gradient(165deg, #101820 0%, #17242e 55%, #1d3038 100%);
  /* Espaçamento em vh (não vw): encolhe com a altura do ecrã, para o herói
     caber acima da dobra em portáteis.
     Padding in vh (not vw): shrinks with screen height so the hero fits above
     the fold on laptops. */
  padding: clamp(1.75rem, 5vh, 3.5rem) 0 clamp(2rem, 6vh, 4rem);
  overflow: hidden;
  /* O herói ocupa o que sobra do ecrã depois do cabeçalho e da tira a rolar,
     para a tira ficar encostada ao fundo da janela. O --fold é medido pelo
     site.js; o valor de reserva serve enquanto o JS não corre.
     The hero takes whatever the screen has left after the header and the
     scrolling tape, so the tape sits flush with the bottom of the window.
     --fold is measured by site.js; the fallback covers the moment before the
     JS runs. */
  min-height: calc(100vh - var(--fold, 150px));
  min-height: calc(100svh - var(--fold, 150px));
  display: flex;
  align-items: center;
}
/* Numa janela muito baixa, deixar de forçar altura: mais vale rolar do que
   espremer o texto. On a very short window, stop forcing the height: better to
   scroll than to squash the text. */
@media (max-height: 520px) {
  .hero { min-height: 0; display: block; }
}
/* Véu neutro sobre a foto: dá profundidade sem lhe roubar a cor.
   Neutral scrim over the photo: adds depth without draining its colour. */
.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(
    180deg,
    rgba(8, 12, 18, 0.34) 0%,
    rgba(8, 12, 18, 0.12) 45%,
    rgba(8, 12, 18, 0.48) 100%
  );
}
/* A foto a 100%: era o opacity 0.32 + mix-blend-mode que a deixava lavada.
   The photo at full strength: opacity 0.32 + mix-blend-mode was what washed it out. */
.hero__media {
  position: absolute;
  inset: 0;
  z-index: -2;
  object-fit: cover;
  width: 100%;
  height: 100%;
}
/* Painel "liquid glass": desfoca a foto por trás do texto, para o texto ficar
   legível sem cobrir a fotografia com um degradê opaco.
   "Liquid glass" panel: blurs the photo behind the text, so the copy stays
   readable without burying the photograph under an opaque gradient. */
.hero__inner {
  position: relative;
  max-width: 56ch;
  padding: clamp(1.25rem, 3vw, 2.1rem);
  border-radius: var(--r-lg);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.20) 0%, rgba(255, 255, 255, 0) 42%),
    rgba(16, 22, 30, 0.34);
  border: 1px solid rgba(255, 255, 255, 0.22);
  backdrop-filter: blur(20px) saturate(150%);
  -webkit-backdrop-filter: blur(20px) saturate(150%);
  box-shadow:
    0 28px 64px -32px rgba(0, 0, 0, 0.62),
    inset 0 1px 0 rgba(255, 255, 255, 0.34);
}
/* Sem backdrop-filter (browsers antigos) o vidro passa a ser opaco.
   Without backdrop-filter (older browsers) the glass falls back to solid. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .hero__inner { background: rgba(16, 22, 30, 0.72); }
}
/* Quem pediu menos transparência no sistema recebe um painel sólido.
   Anyone who asked the OS for less transparency gets a solid panel. */
@media (prefers-reduced-transparency: reduce) {
  .hero__inner {
    background: rgba(16, 22, 30, 0.86);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
}
/* Título um pouco mais contido que o h1 global, para o bloco caber no ecrã.
   Slightly more restrained than the global h1, so the block fits on screen. */
.hero h1 {
  color: #fff;
  font-size: clamp(1.95rem, 1.35rem + 2.4vw, 3.4rem);
  margin-bottom: 0.3em;
}
.hero h1 em {
  font-style: normal;
  display: block;
  color: var(--accent);
}
.hero .kicker { color: var(--brand-soft); margin-bottom: 0.7rem; }
.hero .lead { color: rgba(255, 255, 255, 0.92); font-size: clamp(1rem, 0.96rem + 0.4vw, 1.18rem); }
.hero .btn-row { margin-top: 1.5rem; }

.hero-badges {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
  padding: 0;
  margin: 1.4rem 0 0;
}
.hero-badges li {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  font-size: 0.83rem;
  padding: 0.42em 0.9em;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.28);
  background: rgba(255, 255, 255, 0.09);
  backdrop-filter: blur(4px);
}
.hero-badges li::before { content: "✦"; color: var(--accent); }

/* Ecrãs baixos (portáteis de 13"/14"): aperta mais um pouco para o herói
   caber inteiro sem scroll.
   Short screens (13"/14" laptops): tighten a little further so the whole hero
   fits without scrolling. */
@media (max-height: 800px) and (min-width: 700px) {
  .hero h1 { font-size: clamp(1.85rem, 1.2rem + 1.9vw, 2.8rem); }
  .hero .lead { font-size: 1.02rem; }
  .hero .btn-row { margin-top: 1.2rem; }
  .hero-badges { margin-top: 1.1rem; }
}

/* page hero (inner pages) */
.pagehero {
  position: relative;
  isolation: isolate;
  color: #fff;
  background: linear-gradient(140deg, var(--deep), #6a3a29 60%, #8d4d38);
  padding: clamp(2.6rem, 7vw, 5rem) 0 clamp(2.8rem, 7vw, 5rem);
  overflow: hidden;
}
.pagehero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: radial-gradient(55% 60% at 85% 20%, rgba(217, 160, 78, 0.32), transparent 70%);
}
/* Faixa com fotografia: a imagem entra por baixo de tudo e leva um véu
   escuro por cima, para o título continuar legível seja qual for a foto.
   Banner with a photograph: the image sits beneath everything and takes a dark
   veil on top, so the heading stays readable whatever the photo. */
.pagehero__media {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.pagehero--photo { padding: clamp(3.5rem, 9vw, 6.5rem) 0 clamp(3.5rem, 9vw, 6.5rem); }
/* A foto encosta à direita: é desse lado que fica à vista, enquanto o texto
   ocupa a esquerda. The photo anchors right: that is the side left on show,
   while the text takes the left. */
.pagehero--photo .pagehero__media { object-position: right center; }
/* Véu que abre da esquerda para a direita: sólido por baixo do texto, a
   desaparecer até deixar a fotografia limpa na margem direita.
   A veil opening from left to right: solid under the text, fading away until
   the photograph is left clean at the right-hand edge. */
.pagehero--photo::before {
  background: linear-gradient(
    90deg,
    var(--deep) 0%,
    rgba(50, 32, 26, 0.94) 26%,
    rgba(50, 32, 26, 0.72) 46%,
    rgba(50, 32, 26, 0.36) 66%,
    rgba(50, 32, 26, 0.08) 85%,
    rgba(50, 32, 26, 0) 100%
  );
}
/* O texto fica do lado escuro, sem invadir a parte limpa da foto.
   The text stays on the dark side, without straying into the clean part of
   the photograph. */
@media (min-width: 760px) {
  .pagehero--photo .wrap > * { max-width: min(56%, 60ch); }
}
/* Em ecrã estreito o texto ocupa a largura toda, por isso o véu passa a
   descer de cima para baixo. On a narrow screen the text spans the full width,
   so the veil runs top to bottom instead. */
@media (max-width: 759px) {
  .pagehero--photo::before {
    background: linear-gradient(
      180deg,
      rgba(50, 32, 26, 0.62) 0%,
      rgba(50, 32, 26, 0.5) 45%,
      rgba(50, 32, 26, 0.78) 100%
    );
  }
}

.pagehero h1 { color: #fff; }
.pagehero .lead { color: rgba(255, 255, 255, 0.84); }
.pagehero .kicker { color: var(--brand-soft); }

.breadcrumb {
  display: flex;
  gap: 0.5rem;
  font-size: 0.82rem;
  color: rgba(255, 255, 255, 0.62);
  margin-bottom: 1.2rem;
}
.breadcrumb a { text-decoration: none; }
.breadcrumb a:hover { color: #fff; text-decoration: underline; }

/* ---------- Cards ---------- */
.card {
  background: var(--paper);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-lg);
  padding: clamp(1.3rem, 2.5vw, 1.9rem);
  box-shadow: var(--shadow-sm);
  transition: transform 0.35s var(--ease), box-shadow 0.35s var(--ease),
    border-color 0.35s var(--ease);
}
.card--hover:hover {
  transform: translateY(-5px);
  box-shadow: var(--shadow);
  border-color: rgba(173, 97, 69, 0.35);
}
.card__icon {
  font-size: 1.9rem;
  line-height: 1;
  display: grid;
  place-items: center;
  width: 58px;
  height: 58px;
  border-radius: 18px;
  background: linear-gradient(150deg, rgba(173, 97, 69, 0.13), rgba(217, 160, 78, 0.2));
  margin-bottom: 1rem;
}
.card h3 { margin-bottom: 0.4em; }
.card p { color: var(--muted); font-size: 0.98rem; }

.chips { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 1rem; padding: 0; list-style: none; }
.chip {
  font-size: 0.76rem;
  font-weight: 500;
  padding: 0.32em 0.75em;
  border-radius: 999px;
  background: rgba(173, 97, 69, 0.09);
  color: var(--brand-deep);
  border: 1px solid rgba(173, 97, 69, 0.2);
}

/* quick start tiles */
.tiles { display: grid; gap: 0.9rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); }
.tile {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  padding: 1.1rem 1.25rem;
  border-radius: var(--r-md);
  background: var(--paper);
  border: 1px solid var(--line-soft);
  text-decoration: none;
  font-weight: 600;
  box-shadow: var(--shadow-sm);
  transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease), background 0.3s;
}
.tile:hover { transform: translateY(-4px); box-shadow: var(--shadow); }
.tile em { font-style: normal; font-size: 1.6rem; line-height: 1; }
.tile::after { content: "→"; margin-left: auto; color: var(--brand-mid); transition: transform 0.25s var(--ease); }
.tile:hover::after { transform: translateX(4px); }

/* why list */
.why { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.85rem; }
.why li {
  display: flex;
  gap: 0.85rem;
  align-items: flex-start;
  padding: 0.95rem 1.1rem;
  border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.12);
}
.why li em { font-style: normal; font-size: 1.25rem; line-height: 1.3; }

/* stat facts */
.facts { list-style: none; padding: 0; margin: 0; display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 150px), 1fr)); }
.facts li {
  padding: 1.2rem;
  border-radius: var(--r-md);
  background: var(--paper);
  border: 1px solid var(--line-soft);
  text-align: center;
}
.facts strong {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 1.2rem + 1.2vw, 2.2rem);
  color: var(--brand-deep);
  line-height: 1.1;
}
.facts span { font-size: 0.85rem; color: var(--muted); }

/* ---------- Experience cards ---------- */
.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 2rem;
}
.filter {
  border: 1px solid var(--line);
  background: var(--paper);
  border-radius: 999px;
  padding: 0.5em 1.05em;
  font-size: 0.9rem;
  font-weight: 500;
  cursor: pointer;
  transition: background 0.2s, color 0.2s, border-color 0.2s, transform 0.2s;
}
.filter:hover { transform: translateY(-1px); border-color: var(--brand-mid); }
.filter[aria-pressed="true"] { background: var(--ink); color: #fff; border-color: var(--ink); }

/* Os filtros só servem para alguma coisa com javascript: sem ele seriam
   botões que não fazem nada. A lista completa das experiências está sempre
   na página, gerada de origem — filtrar é só uma comodidade por cima.
   The filters only do anything with JavaScript: without it they would be
   buttons that lead nowhere. The full list of experiences is always on the
   page, generated at build time — filtering is only a convenience on top. */
.filters { display: none; }
.js .filters { display: flex; }

/* A fila da ilha encosta-se à do tipo: são dois filtros, não duas secções. */
.filters--island { margin-top: -1.25rem; }
.filters--island .filter { font-size: 0.85rem; }

/* ---------- Ilha da experiência ---------- */
/* O tipo e a ilha na mesma linha, por baixo da foto e por cima do título.
   A etiqueta é discreta de propósito: diz onde é, sem competir com o nome da
   experiência nem com a fotografia.
   Type and island on one line, below the photo and above the title. The tag is
   deliberately quiet: it says where, without competing with the experience's
   name or with the photograph. */
.slide__meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.4rem 0.85rem;
  margin-bottom: 0.9rem;
}
.slide__meta .kicker { margin: 0; }
.island-tag {
  margin: 0;
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.25em 0.7em;
  white-space: nowrap;
}
.island-tag::before {
  content: "";
  width: 0.42em;
  height: 0.42em;
  border-radius: 50%;
  background: var(--brand-soft);
  flex: none;
}
.island-tag[data-island="principe"]::before { background: var(--brand); }
.island-tag[data-island="ambas"]::before {
  background: linear-gradient(90deg, var(--brand-soft) 50%, var(--brand) 50%);
}

/* No telemóvel a linha parte-se em duas em vez de espremer a etiqueta. */
@media (max-width: 520px) {
  .slide__meta { gap: 0.35rem 0.6rem; }
  .island-tag { font-size: 0.65rem; padding: 0.22em 0.6em; }
  /* Com a fila do tipo partida em várias linhas, a da ilha precisa de mais
     ar para não parecer só mais uma linha do mesmo grupo.
     With the type row broken over several lines, the island row needs more
     air so it does not read as just one more line of the same group. */
  .filters--island { margin-top: -0.75rem; }
}

/* ---------- Fotografia de experiência ---------- */
/* Enquanto o ficheiro .jpg não existir mostra-se o ícone sobre um degradê.
   Until the .jpg exists, the icon sits on a gradient instead. */
.shot {
  position: relative;
  border-radius: var(--r-md);
  overflow: hidden;
  aspect-ratio: 4 / 3;
  background: linear-gradient(150deg, var(--brand-deep), var(--brand-mid));
}
.shot img { width: 100%; height: 100%; object-fit: cover; }
.shot__ph {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: clamp(2.4rem, 6vw, 4rem);
  opacity: 0.55;
}

/* ---------- Carrossel de experiências ---------- */
.carousel { position: relative; }
.carousel__track {
  display: flex;
  gap: 1.2rem;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scroll-padding: 0;
  padding: 0.4rem 0.3rem 1.2rem;
  margin: 0 -0.3rem;
  scrollbar-width: none;
}
.carousel__track::-webkit-scrollbar { display: none; }
.carousel__track:focus-visible { outline: 3px solid var(--brand-mid); outline-offset: 4px; border-radius: var(--r-lg); }

.slide {
  flex: 0 0 100%;
  scroll-snap-align: center;
  scroll-margin-top: 100px;
  display: grid;
  gap: clamp(1.2rem, 3vw, 2.2rem);
  align-items: center;
  background: var(--paper);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-lg);
  padding: clamp(1.1rem, 2.4vw, 1.8rem);
  box-shadow: var(--shadow-sm);
  opacity: 0.55;
  transition: opacity 0.4s var(--ease), box-shadow 0.4s var(--ease), border-color 0.4s var(--ease);
}
.slide.is-current { opacity: 1; box-shadow: var(--shadow); border-color: rgba(173, 97, 69, 0.3); }
.slide.is-hidden { display: none; }
.slide__media { min-width: 0; }
.slide__media .shot { aspect-ratio: 4 / 3; box-shadow: var(--shadow); }
.slide__text { min-width: 0; }
.slide__text h3 { margin-bottom: 0.35em; }
.slide__short { font-size: 1.05rem; color: var(--ink-soft); font-weight: 500; }
.slide__body { color: var(--muted); font-size: 0.97rem; }
.slide__body p + p { margin-top: 0.8em; }
.slide .btn-row { margin-top: 1.2rem; }

@media (min-width: 860px) {
  .slide { grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr); }
  .slide__media .shot { aspect-ratio: 3 / 4; }
}
/* Deixamos espreitar a lâmina seguinte: percebe-se logo que há mais para ver.
   We let the next slide peek through: it reads instantly as "there is more". */
@media (min-width: 1100px) {
  .slide { flex-basis: calc(100% - 84px); }
}

.carousel__nav {
  position: absolute;
  top: calc(50% - 0.6rem);
  transform: translateY(-50%);
  z-index: 3;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.94);
  backdrop-filter: blur(6px);
  box-shadow: var(--shadow);
  font-size: 1.7rem;
  line-height: 1;
  padding-bottom: 4px;
  color: var(--brand-deep);
  cursor: pointer;
  transition: transform 0.2s var(--ease), opacity 0.2s, background 0.2s;
}
.carousel__nav:hover:not(:disabled) { transform: translateY(-50%) scale(1.08); background: #fff; }
.carousel__nav:disabled { opacity: 0.3; cursor: default; }
.carousel__nav--prev { left: -10px; }
.carousel__nav--next { right: -10px; }
@media (min-width: 1300px) {
  .carousel__nav--prev { left: -26px; }
  .carousel__nav--next { right: -26px; }
}

.carousel__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 0.4rem;
}
.dots { display: flex; flex-wrap: wrap; gap: 0.45rem; }
.dot {
  width: 10px;
  height: 10px;
  padding: 0;
  border-radius: 50%;
  border: 1px solid rgba(173, 97, 69, 0.45);
  background: transparent;
  cursor: pointer;
  transition: background 0.2s, transform 0.2s, width 0.25s var(--ease);
}
.dot:hover { background: var(--brand-soft); }
.dot[aria-current="true"] { background: var(--brand); border-color: var(--brand); width: 26px; border-radius: 999px; }
.dot.is-hidden { display: none; }
.carousel__count { margin: 0; color: var(--muted); font-size: 0.9rem; font-variant-numeric: tabular-nums; }
.carousel__count strong { color: var(--ink); }
.carousel__hint { margin: 0.7rem 0 0; color: var(--muted); font-size: 0.88rem; }

@keyframes fadeIn { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }

/* SEPARADORES ------------------------------------------------------------
   Um carril de rótulos com um sublinhado a marcar o activo. Substitui os
   botões em pastilha, que pesavam tanto como as caixas que vieram substituir.
   TABS. A rail of labels with an underline marking the active one. It replaces
   the pill buttons, which weighed as much as the boxes they replaced. */
.tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 0 clamp(1rem, 2.5vw, 1.7rem);
  margin: 0.6rem 0 1.5rem;
  border-bottom: 1px solid var(--line-soft);
}
.tab {
  border: 0;
  background: none;
  padding: 0.65rem 0;
  margin-bottom: -1px;
  border-bottom: 2px solid transparent;
  font: inherit;
  font-size: 0.9rem;
  color: var(--muted);
  cursor: pointer;
  transition: color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.tab:hover { color: var(--brand-deep); }
.tab[aria-selected="true"] { color: var(--ink); border-bottom-color: var(--brand); }

.panel { display: none; }
.panel[hidden] { display: none; }
.panel.is-active { display: block; animation: fadeIn 0.35s var(--ease); }
/* Os painéis têm alturas muito diferentes (de 20 a 140 palavras). Sem um piso,
   trocar de separador fazia a página saltar meio ecrã. O piso apanha cinco dos
   seis; só o mais longo é que cresce.
   The panels differ a lot in height (20 to 140 words). With no floor, changing
   tab made the page jump half a screen. The floor covers five of the six; only
   the longest one grows past it. */
@media (min-width: 940px) { .panel.is-active { min-height: 16rem; } }

/* ---------- Season chart ---------- */
/* Água a sério com uma escala a sério por cima: a linha de água de cada mês
   está à altura do valor desse mês, e a grelha, os pontos e os números usam
   exactamente a mesma escala.
   Real water with a real scale on top: each month's waterline sits at the
   height of that month's value, and the gridlines, dots and numbers all use
   exactly the same scale. */
.season { margin: 1.5rem 0 0; }
.season__stage { position: relative; }
.season__sea,
.season__chart {
  display: block;
  width: 100%;
  aspect-ratio: 1200 / 300;
  border-radius: var(--r-md);
}
.season__sea { display: none; }
.season__stage.has-sea .season__sea { display: block; }
.season__stage.has-sea .season__chart { display: none; }
@media (max-width: 680px) {
  .season__sea,
  .season__chart { aspect-ratio: 1200 / 430; }
  /* Doze números num ecrã estreito: mais pequenos, e a palavra "agora" sai —
     o mês em destaque por baixo já o diz.
     Twelve numbers on a narrow screen: smaller, and the word "now" goes — the
     highlighted month underneath already says it. */
  /* Doze palavras não cabem lado a lado num ecrã estreito, por isso as de
     meses alternados sobem um degrau. Cada uma continua sobre o seu ponto.
     Twelve words will not sit side by side on a narrow screen, so alternate
     months step up a line. Each one still sits over its own dot. */
  .ax__pt b { font-size: 0.5rem; bottom: 8px; }
  .ax__pt.is-odd b { bottom: 20px; }
  .ax__pt i { width: 5px; height: 5px; }
  .ax__now span { display: none; }
}

/* ---- a camada que se lê / the layer you read ---- */
.ax { position: absolute; inset: 0; pointer-events: none; }

/* faixa da época mais consistente / the most consistent season */
.ax__band {
  position: absolute;
  top: 0;
  bottom: 0;
  background: rgba(255, 255, 255, 0.07);
  border-left: 1px solid rgba(255, 255, 255, 0.16);
  border-right: 1px solid rgba(255, 255, 255, 0.16);
}

/* grelha e escala / gridlines and scale */
.ax__grid {
  position: absolute;
  left: 0;
  right: 0;
  border-top: 1px dashed rgba(255, 255, 255, 0.16);
}
.ax__grid.is-base { border-top-style: solid; border-top-color: rgba(255, 255, 255, 0.3); }
/* a linha do dado, em degraus — um patamar por mês
   the data line, stepped — one tread per month */
.ax__line {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.ax__line path {
  fill: none;
  stroke: rgba(255, 255, 255, 0.92);
  stroke-width: 2;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

/* ponto e número de cada mês / each month's dot and number */
.ax__pt { position: absolute; transform: translate(-50%, -50%); }
.ax__pt i {
  display: block;
  width: 7px;
  height: 7px;
  margin: 0 auto;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.6);
}
.ax__pt.is-hi i { background: #fff; box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.16); }
.ax__pt b {
  position: absolute;
  left: 50%;
  bottom: 11px;
  transform: translateX(-50%);
  display: inline-flex;
  align-items: center;
  gap: 0.32em;
  white-space: nowrap;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: rgba(255, 255, 255, 0.6);
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.6);
}
.ax__pt b em { font-style: normal; font-size: 1.15em; line-height: 1; }
.ax__pt.is-hi b { color: #fff; }
.ax__pt.is-now b { color: var(--accent); }
.ax__pt.is-now i { background: var(--accent); box-shadow: 0 0 0 3px rgba(217, 160, 78, 0.25); }

/* o mês corrente / the current month */
.ax__now {
  position: absolute;
  top: 0;
  bottom: 0;
  border-left: 1px dashed rgba(217, 160, 78, 0.6);
}
.ax__now span {
  position: absolute;
  top: 2px;
  left: 4px;
  font-size: 0.6rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent);
}

.season__unit {
  margin: 0 0 0.5rem;
  font-size: 0.66rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.45);
}

/* os meses, alinhados com as colunas / the months, aligned to the columns */
.season__months {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  margin-top: 0.55rem;
}
.season__months span {
  text-align: center;
  font-size: clamp(0.58rem, 1.5vw, 0.74rem);
  color: rgba(255, 255, 255, 0.55);
}
.season__months span.is-hi { color: rgba(255, 255, 255, 0.85); }
.season__months span.is-now { color: var(--accent); font-weight: 600; }

.season-legend { display: flex; flex-wrap: wrap; gap: 1.2rem; margin-top: 1.3rem; font-size: 0.88rem; }
.season-legend span { display: inline-flex; align-items: center; gap: 0.5em; }
.season-legend i { width: 12px; height: 12px; border-radius: 50%; display: inline-block; }
.season-legend .hi { background: #fff; }
.season-legend .lo { background: rgba(255, 255, 255, 0.42); }

/* ---------- Accordion ---------- */
.acc { border-top: 1px solid var(--line); }
.acc__item { border-bottom: 1px solid var(--line); }
.acc__item.is-hidden { display: none; }
.acc__btn {
  width: 100%;
  display: flex;
  gap: 1rem;
  align-items: flex-start;
  justify-content: space-between;
  padding: 1.15rem 0.2rem;
  background: none;
  border: 0;
  text-align: left;
  cursor: pointer;
  font-size: 1.03rem;
  font-weight: 500;
  transition: color 0.2s;
}
.acc__btn:hover { color: var(--brand-deep); }
.acc__btn::after {
  content: "";
  flex: none;
  width: 12px;
  height: 12px;
  margin-top: 0.42em;
  border-right: 2px solid var(--brand-mid);
  border-bottom: 2px solid var(--brand-mid);
  transform: rotate(45deg);
  transition: transform 0.3s var(--ease);
}
.acc__item.is-open .acc__btn { color: var(--brand-deep); font-weight: 600; }
.acc__item.is-open .acc__btn::after { transform: rotate(-135deg); }
.acc__panel {
  display: none;
  padding: 0 0 1.35rem;
  color: var(--muted);
  max-width: 78ch;
}
.acc__item.is-open .acc__panel { display: block; animation: fadeIn 0.3s var(--ease); }

.search {
  position: relative;
  margin-bottom: 1.8rem;
  max-width: 520px;
}
.search input {
  width: 100%;
  font: inherit;
  padding: 0.9em 1.1em 0.9em 2.9em;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--paper);
  transition: border-color 0.2s, box-shadow 0.2s;
}
.search input:focus { outline: none; border-color: var(--brand-mid); box-shadow: 0 0 0 4px rgba(173, 97, 69, 0.13); }
.search::before {
  content: "🔍";
  position: absolute;
  left: 1.05em;
  top: 50%;
  transform: translateY(-50%);
  font-size: 0.95rem;
  opacity: 0.6;
}

.faq-group { margin-bottom: 2.6rem; }
.faq-group > h3 {
  font-family: var(--font-body);
  font-size: 0.78rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--brand-mid);
  margin-bottom: 0.4rem;
}
.faq-group.is-hidden { display: none; }

/* ---------- Steps ---------- */
.steps { list-style: none; padding: 0; margin: 0; display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 230px), 1fr)); counter-reset: s; }
.steps li {
  position: relative;
  padding: 1.5rem 1.3rem 1.3rem;
  background: var(--paper);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-sm);
}
.steps li strong { display: block; margin-bottom: 0.35rem; font-size: 1.02rem; }
.steps li p { font-size: 0.93rem; color: var(--muted); }
.steps li b {
  position: absolute;
  top: -14px;
  left: 1.3rem;
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--brand);
  color: #fff;
  font-size: 0.9rem;
}

/* ---------- Prose blocks ---------- */
.prose { max-width: 72ch; }
.prose p { color: var(--ink-soft); }
.prose ul { padding-left: 1.15rem; color: var(--ink-soft); }
.prose li { margin-bottom: 0.4rem; }

/* Sobre fundo escuro o texto tem de clarear — inclui os filhos de .prose,
   que de outro modo herdariam a cor escura definida acima.
   On dark backgrounds text must lighten — including .prose children, which
   would otherwise keep the dark colour set above. */
.section--deep .prose,
.section--deep .prose p,
.section--deep .prose ul,
.section--deep .prose li,
.section--deep p {
  color: rgba(255, 255, 255, 0.82);
}
.section--deep strong { color: #fff; }

.note {
  display: flex;
  gap: 0.9rem;
  padding: 1.1rem 1.3rem;
  border-radius: var(--r-md);
  background: rgba(217, 160, 78, 0.15);
  border: 1px solid rgba(217, 160, 78, 0.35);
  font-size: 0.95rem;
}
.note::before { content: "ℹ️"; flex: none; }

.copybox {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.8rem;
  justify-content: space-between;
  padding: 1rem 1.15rem;
  border-radius: var(--r-md);
  border: 1px dashed var(--line);
  background: var(--paper);
  margin-bottom: 0.8rem;
}
.copybox small { display: block; font-size: 0.72rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); }
.copybox code { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 0.95rem; word-break: break-all; }

/* section side-nav */
.subnav {
  position: sticky;
  top: 84px;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  padding: 0.55rem;
  background: rgba(253, 248, 244, 0.92);
  backdrop-filter: blur(10px);
  border: 1px solid var(--line-soft);
  border-radius: 999px;
  z-index: 40;
  margin-bottom: 2.5rem;
  box-shadow: var(--shadow-sm);
}
.subnav a {
  padding: 0.42em 0.95em;
  border-radius: 999px;
  font-size: 0.87rem;
  font-weight: 500;
  text-decoration: none;
  color: var(--ink-soft);
  white-space: nowrap;
  transition: background 0.2s, color 0.2s;
}
.subnav a:hover, .subnav a.is-active { background: var(--ink); color: #fff; }

.block { scroll-margin-top: 150px; margin-bottom: clamp(2.5rem, 5vw, 4rem); }
.block__head { display: flex; align-items: center; gap: 0.85rem; margin-bottom: 1.1rem; }
.block__head em {
  font-style: normal;
  font-size: 1.5rem;
  display: grid;
  place-items: center;
  width: 50px;
  height: 50px;
  flex: none;
  border-radius: 16px;
  background: linear-gradient(150deg, rgba(173, 97, 69, 0.14), rgba(217, 160, 78, 0.22));
}
.block__head h2, .block__head h3 { margin: 0; }

/* ---------- Mosaico de fotografias / photo collage ----------
   Colunas em vez de grelha: cada fotografia mantém a sua própria altura, por
   isso nenhuma é cortada. É o object-fit: cover que corta, e aqui não há
   nenhum — as imagens são width:100% e height:auto, a forma que têm.
   Columns rather than a grid: each photograph keeps its own height, so none is
   cropped. Cropping comes from object-fit: cover, and there is none here —
   images are width:100% and height:auto, the shape they actually are. */
.collage-wrap {
  width: min(100% - 2 * var(--pad), 1440px);
  margin-inline: auto;
}
.collage {
  columns: 3;
  column-gap: clamp(0.5rem, 1vw, 0.9rem);
}
@media (max-width: 1000px) { .collage { columns: 2; } }
@media (max-width: 560px)  { .collage { columns: 1; } }

.collage__item {
  /* Uma fotografia nunca se parte entre duas colunas.
     A photograph never splits across two columns. */
  break-inside: avoid;
  -webkit-column-break-inside: avoid;
  page-break-inside: avoid;
  margin: 0 0 clamp(0.5rem, 1vw, 0.9rem);
}
.collage .zoom {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: linear-gradient(150deg, var(--brand-deep), var(--brand-mid));
  border-radius: var(--r-md);
  overflow: hidden;
  cursor: zoom-in;
  box-shadow: var(--shadow-sm);
  transition: transform 0.4s var(--ease), box-shadow 0.4s var(--ease);
}
.collage .zoom:hover { transform: translateY(-3px); box-shadow: var(--shadow); }
.collage .zoom img {
  width: 100%;
  height: auto;      /* a proporção verdadeira / the true proportion */
  display: block;
}
@media (prefers-reduced-motion: reduce) {
  .collage .zoom, .collage .zoom:hover { transition: none; transform: none; }
}

/* MOMENTOS: UMAS EM PÉ, OUTRAS DEITADAS ------------------------------------
   As seis fotografias saíram todas da máquina em 3:2 deitado, e seis
   rectângulos iguais dão sempre uma grelha morta. Antes tentei salvá-la com
   desníveis verticais, mas isso só afastava as fotografias umas das outras e
   abria espaços a mais.

   A variedade vem agora da forma: três ficam em pé, recortadas na grelha, e
   três mantêm-se deitadas. Em pé ficam aquelas em que há uma pessoa de corpo
   inteiro, que é uma figura vertical e agradece o formato; deitadas ficam as
   paisagens largas, que um corte vertical destruiria. Cada recorte é
   ancorado no --fx da fotografia, o ponto onde a pessoa está, para nunca a
   cortar. A fotografia inteira abre na caixa de luz.

   MOMENTS: SOME STANDING, SOME LYING DOWN. All six came off the camera as 3:2
   landscape, and six identical rectangles always make a dead grid. I first
   tried to rescue it with vertical offsets, but that only pushed the photos
   apart and opened too much space.

   The variety now comes from shape: three stand up, cropped in the grid, and
   three stay landscape. Standing are the ones with a full-length person, a
   vertical subject that suits the format; landscape are the wide scenes, which
   a vertical crop would destroy. Each crop is anchored to the photo's own --fx,
   the point where the person is, so it never cuts them out. The whole photo
   opens in the lightbox. */
.collage--moments {
  columns: initial;
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: clamp(0.6rem, 1.4vw, 1.1rem);
  align-items: start;
}
.collage--moments .collage__item { margin: 0; }

/* Em pé: 3 por 4. O recorte segura-se no ponto --fx de cada fotografia.
   Standing: 3 by 4. The crop holds on to each photo's own --fx point. */
.collage--moments .is-tall .zoom { aspect-ratio: 3 / 4; }
.collage--moments .is-tall .zoom img {
  height: 100%;
  object-fit: cover;
  object-position: var(--fx, 50%) center;
}

/* Uma em pé e uma deitada por fila, trocando de lado. Com 4 e 8 colunas as
   duas dão quase exactamente a mesma altura, por isso as filas assentam
   direitas sem precisar de desnível nenhum.
   One standing and one lying down per row, swapping sides. At 4 and 8 columns
   the two come out almost exactly the same height, so the rows sit level with
   no offset needed. */
@media (min-width: 620px) {
  .collage--moments .collage__item:nth-child(1) { grid-column: span 4; }
  .collage--moments .collage__item:nth-child(2) { grid-column: span 8; }
  .collage--moments .collage__item:nth-child(3) { grid-column: span 8; }
  .collage--moments .collage__item:nth-child(4) { grid-column: span 4; }
  .collage--moments .collage__item:nth-child(5) { grid-column: span 4; }
  .collage--moments .collage__item:nth-child(6) { grid-column: span 8; }
}

/* Ecrã estreito: uma coluna. As em pé continuam em pé, que num telemóvel é
   precisamente o formato que sobra.
   Narrow screen: one column. The standing ones stay standing, which on a phone
   is exactly the shape there is room for. */
@media (max-width: 619px) {
  .collage--moments .collage__item { grid-column: 1 / -1; }
}

/* ---------- A foto em grande / the photo, large ---------- */
.no-scroll { overflow: hidden; }
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  place-items: center;
  padding: clamp(1rem, 4vw, 3rem);
  background: rgba(12, 9, 8, 0.92);
  backdrop-filter: blur(6px);
}
.lightbox[hidden] { display: none; }
.lightbox__frame { margin: 0; display: grid; gap: 0.8rem; justify-items: center; }
.lightbox__frame img {
  /* contain, nunca cover: a foto inteira cabe no ecrã, sem cortes.
     contain, never cover: the whole photo fits the screen, uncropped. */
  max-width: min(94vw, 1600px);
  max-height: 82vh;
  width: auto;
  height: auto;
  object-fit: contain;
  border-radius: var(--r-md);
  box-shadow: 0 40px 90px -30px rgba(0, 0, 0, 0.8);
}
.lightbox__frame figcaption {
  color: rgba(255, 255, 255, 0.6);
  font-size: 0.78rem;
  letter-spacing: 0.14em;
  text-align: center;
}
/* Uma foto só: não há contagem, não há linha vazia a ocupar espaço.
   A single photo: no count, and no empty line taking up space. */
.lightbox__frame figcaption:empty { display: none; }
.lightbox__close, .lightbox__nav {
  position: absolute;
  border: 1px solid rgba(255, 255, 255, 0.25);
  background: rgba(255, 255, 255, 0.1);
  color: #fff;
  border-radius: 999px;
  cursor: pointer;
  display: grid;
  place-items: center;
  transition: background 0.2s;
}
.lightbox__close:hover, .lightbox__nav:hover { background: rgba(255, 255, 255, 0.22); }
.lightbox__close {
  top: clamp(0.7rem, 2vw, 1.4rem);
  right: clamp(0.7rem, 2vw, 1.4rem);
  width: 2.6rem; height: 2.6rem;
  font-size: 1.6rem; line-height: 1;
}
.lightbox__nav {
  top: 50%;
  transform: translateY(-50%);
  width: 3rem; height: 3rem;
  font-size: 2rem; line-height: 1;
}
.lightbox__nav--prev { left: clamp(0.5rem, 2vw, 1.6rem); }
.lightbox__nav--next { right: clamp(0.5rem, 2vw, 1.6rem); }
.lightbox.is-solo .lightbox__nav { display: none; }

/* ---------- Explorar: a viagem / the Explore journey ----------
   Uma tela fixa que fica quieta enquanto os capítulos passam por cima. A
   pista é alta (um ecrã por capítulo) e é essa altura que dá o "scroll".
   A fixed canvas that stays put while the chapters travel over it. The track
   is tall (one screen per chapter) and that height is what gives the scroll
   something to work with. */
/* Fundo de noite, não o castanho das outras secções: à volta de um globo, o
   terracota lia-se como um erro. O degradê põe o globo num halo.
   A night ground rather than the brown of the other sections: around a globe,
   the terracotta read as a mistake. The gradient sets the globe in a halo. */
/* O mesmo creme do resto do site, e texto escuro por cima. A secção deixou de
   ser um bloco nocturno à parte: é a mesma página, com um globo lá dentro.
   The same cream as the rest of the site, with dark text over it. The section
   is no longer a nocturnal block of its own: it is the same page, with a globe
   inside it. */
.journey {
  position: relative;
  color: var(--ink);
  background: var(--cream);
  /* Uma só definição do verde: o ponto no globo, o fio e a etiqueta lêem todos
     daqui, por isso não podem divergir.
     A single definition of the green: the dot on the globe, the thread and the
     label all read from here, so they cannot drift apart. */
  --globe-mark: #24d67a;
}
.journey__stage {
  position: sticky;
  top: 0;
  /* Uma unidade só, e a mesma que as margens negativas usam: misturar svh com
     vh desalinhava a tela do texto que a cobre.
     One unit only, the same one the negative margins use: mixing svh with vh
     knocked the canvas out of line with the text laid over it. */
  height: 100vh;
  z-index: 0;
}
.journey__canvas { width: 100%; height: 100%; display: block; }
.journey__labels { position: absolute; inset: 0; pointer-events: none; }
.globe__label {
  position: absolute;
  top: 0;
  left: 0;
  white-space: nowrap;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  /* A etiqueta veste a cor do ponto a que está presa. O fundo escuro fica, para
     o verde se ler por cima do creme e dos pontos castanhos.
     The label wears the colour of the dot it is tied to. The dark ground stays,
     so the green reads over the cream and the brown dots. */
  color: var(--globe-mark, #24d67a);
  background: var(--ink);
  border: 1px solid var(--globe-mark, #24d67a);
  border-radius: 999px;
  padding: 0.25em 0.7em;
  opacity: 0;
  transition: opacity 0.45s var(--ease);
}
/* O fio que liga o ponto aceso à etiqueta. Um pixel, e da mesma cor do ponto.
   The thread tying the lit dot to its label. One pixel, the colour of the dot. */
.globe__leader {
  position: absolute;
  top: 0;
  left: 0;
  width: 1px;
  transform-origin: top left;
  background: var(--globe-mark, #24d67a);
  opacity: 0;
  transition: opacity 0.45s var(--ease);
}
.globe__leader.is-on { opacity: 0.85; }
.globe__label.is-on { opacity: 1; }

.journey__intro {
  position: relative;
  z-index: 1;
  margin-top: -100vh;
  padding: clamp(3rem, 12vh, 7rem) 0 0;
  text-align: center;
}
/* O texto assenta em cima do globo; um halo claro, da cor do fundo, chega para
   o descolar dos pontos sem parecer sombra.
   The text sits over the globe; a pale halo the colour of the background is
   enough to lift it off the dots without looking like a shadow. */
.journey__intro h2,
.journey__intro .kicker,
.journey__hint { text-shadow: 0 0 14px var(--cream), 0 0 7px var(--cream), 0 0 3px var(--cream); }
.journey__intro h2 { color: var(--ink); }
.journey__intro .kicker { color: var(--brand-mid); justify-content: center; display: inline-flex; }
.journey__hint {
  /* Era o cinzento --muted, que sobre o globo claro quase desaparecia.
     It used to be --muted grey, which all but vanished over the pale globe. */
  color: var(--brand-mid);
  font-weight: 600;
  font-size: 0.85rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.journey__hint::after { content: " ↓"; }

/* Só a introdução é puxada para cima da tela. A pista arranca logo a seguir
   e passa por cima da tela, que fica colada.
   Only the intro is pulled over the canvas. The track starts right after it
   and travels over the canvas, which stays stuck. */
.journey__track { position: relative; z-index: 1; }
.chapter {
  min-height: 100vh;
  display: grid;
  align-content: center;
  padding: 0 var(--pad);
  /* A profundidade que faz o texto rodar como a folha de um rolodex, em vez de
     simplesmente esmorecer. Depth is what makes the text turn like a rolodex
     leaf rather than merely dimming. */
  perspective: 1200px;
  perspective-origin: 50% 50%;
}
/* Sem caixa: o texto assenta directamente na página e roda com o scroll. As
   três variáveis são escritas pelo site.js a cada scroll, o que dá um
   movimento contínuo em vez de um estado ligado/desligado.
   No box: the text sits straight on the page and turns as you scroll. The three
   variables are written by site.js on every scroll, which gives continuous
   movement rather than an on/off state. */
.chapter__card {
  width: min(100%, 34rem);
  margin-left: clamp(0rem, 6vw, 6rem);
  transform-origin: 50% 50%;
  transform:
    translateY(var(--ty, 0rem))
    rotateX(var(--rx, 0deg))
    scale(var(--sc, 1));
  opacity: var(--op, 1);
  will-change: transform, opacity;
  backface-visibility: hidden;
}
.chapter__card h3 {
  color: var(--ink);
  font-size: clamp(1.7rem, 1.2rem + 1.9vw, 2.9rem);
  margin-bottom: 0.4em;
  /* O biselado: um realce claro por baixo da letra e uma sombra curta por
     cima, como se estivesse gravada no creme.
     The bevel: a pale highlight under the letter and a short shadow above, as
     though it were struck into the cream. */
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.95), 0 2px 4px rgba(43, 28, 22, 0.16);
}
.chapter__card p {
  color: var(--ink-soft);
  margin: 0;
  font-size: clamp(1.02rem, 0.98rem + 0.4vw, 1.18rem);
  max-width: 34ch;
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.8);
}
.chapter__card .kicker { color: var(--brand-mid); }
/* Sem pastilhas: uma linha corrida, separada por traços finos, para não voltar
   a haver caixas. No pills: one running line separated by thin rules, so no
   boxes creep back in. */
.chapter__list {
  list-style: none;
  padding: 0;
  margin: 1.2rem 0 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.2rem 0.9rem;
  font-size: 0.86rem;
  color: var(--muted);
}
.chapter__list li { display: inline-flex; align-items: center; gap: 0.9rem; }
.chapter__list li + li::before {
  content: "";
  width: 14px;
  height: 1px;
  background: var(--brand-soft);
}

/* Sem globo: a tela sai da frente e os capítulos passam a uma coluna normal.
   No globe: the canvas steps aside and the chapters become an ordinary
   column. */
.journey--flat .journey__stage { display: none; }
.journey--flat .journey__intro { margin-top: 0; }
.journey--flat .chapter { min-height: 0; padding-block: clamp(1.5rem, 4vw, 2.5rem); }
.journey--flat .chapter__card {
  opacity: 1;
  transform: none;
  margin-inline: auto;
  width: min(100%, 44rem);
}
.journey--flat .journey__hint { display: none; }
/* A mesma condição que o JS usa para não carregar o globo, para que a tela
   nunca chegue a ocupar espaço em ecrãs onde não vai ser desenhada, nem sequer
   no instante antes do JS correr.
   The same condition the JS uses to skip the globe, so the canvas never takes
   up space on screens where it will not be drawn, not even in the instant
   before the JS runs. */
@media (max-width: 760px), (hover: none), (pointer: coarse) {
  .journey__stage { display: none; }
  .journey__intro { margin-top: 0; }
  .journey__hint { display: none; }
  .chapter { min-height: 0; padding-block: clamp(1.2rem, 4vw, 2rem); }
  .chapter__card { opacity: 1; transform: none; margin-inline: auto; }
}
@media (prefers-reduced-motion: reduce) {
  .chapter__card { opacity: 1; transform: none; transition: none; }
}

/* O detalhe completo, dobrado: fica cá, mas não à frente.
   The full detail, folded away: still here, just not in the way. */
.deep { margin-top: 1rem; }
.deep > summary {
  cursor: pointer;
  font-family: var(--font-display);
  font-size: clamp(1.05rem, 1rem + 0.4vw, 1.3rem);
  padding: 0.9rem 1.2rem;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--paper);
  list-style: none;
}
.deep > summary::-webkit-details-marker { display: none; }
.deep > summary::after { content: " +"; color: var(--brand); font-weight: 700; }
.deep[open] > summary::after { content: " −"; }
.deep > summary:hover { border-color: var(--brand-mid); }

/* ==========================================================================
   Peças partilhadas pelas páginas de Serviços, Reservas e pelo detalhe do
   Explorar. Todas seguem a mesma ideia: pôr à vista o que se lê num relance
   — um ícone, um título, meia dúzia de factos — e guardar a letra miudinha
   atrás de um clique, sem a deitar fora.

   Pieces shared by the Services and Booking pages and by the Explore detail.
   All follow one idea: show what can be read at a glance — an icon, a title,
   half a dozen facts — and put the small print behind a click without
   throwing it away.
   ========================================================================== */

/* ---------- Cartão de serviço / service card ---------- */
/* SERVIÇOS, EM LINHAS ------------------------------------------------------
   Cada serviço ocupa a largura toda: à esquerda o número e o nome em grande,
   à direita a explicação. Eram cartões lado a lado, que obrigavam a ler três
   colunas ao mesmo tempo; assim lê-se um de cada vez, de cima a baixo.
   SERVICES, AS ROWS. Each service takes the full width: number and name large
   on the left, the explanation on the right. They used to be cards side by
   side, which meant reading three columns at once; this way you read one at a
   time, top to bottom. */
.stack { margin-top: clamp(1.8rem, 4vw, 2.8rem); }
.stack__row {
  display: grid;
  gap: clamp(0.7rem, 2vw, 2.6rem);
  padding: clamp(1.5rem, 3.5vw, 2.4rem) 0;
  border-top: 1px solid var(--line-soft);
}
@media (min-width: 820px) {
  .stack__row { grid-template-columns: minmax(0, 1fr) minmax(0, 1.5fr); align-items: start; }
}
.stack__n {
  display: block;
  margin-bottom: 0.45rem;
  font-family: var(--font-display);
  font-size: 0.95rem;
  color: var(--brand);
  opacity: 0.55;
  font-variant-numeric: tabular-nums;
}
.stack__side h3 {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(1.45rem, 1rem + 1.7vw, 2.1rem);
  line-height: 1.02;
  letter-spacing: -0.01em;
  color: var(--ink);
}
/* As etiquetas separadas por uma barra fina, não por pastilhas.
   The labels split by a thin bar rather than set in pills. */
.stack__tags { display: flex; flex-wrap: wrap; margin: 0.9rem 0 0; }
.stack__tags span {
  font-size: 0.75rem;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--brand-mid);
}
.stack__tags span:not(:last-child)::after {
  content: "/";
  margin: 0 0.7em;
  color: var(--line);
}
.stack__body p { margin: 0 0 0.85rem; color: var(--muted); font-size: 0.98rem; line-height: 1.7; }
.stack__body p:last-child { margin-bottom: 0; }

/* UM SERVIÇO COM CONDIÇÕES -------------------------------------------------
   Coluna da esquerda fixa enquanto a da direita corre: a ficha técnica fica
   à vista enquanto se lê a condição que se escolheu.
   ONE SERVICE WITH TERMS. The left column stays put while the right one
   scrolls: the spec sheet stays in view while you read the term you picked. */
.feature { display: grid; gap: clamp(1.6rem, 4vw, 3rem); }
@media (min-width: 940px) {
  .feature { grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr); align-items: start; }
  .feature__intro { position: sticky; top: 100px; }
}
.feature__intro h2 { margin: 0.2rem 0 0.6rem; }
.feature__intro .lead { margin-bottom: 1.4rem; }

/* TRÊS COISAS PARA SABER ---------------------------------------------------
   O número que interessa em grande à esquerda, a explicação à direita. Não há
   nada dobrado: se é preciso saber antes de viajar, tem de estar à vista.
   THREE THINGS TO KNOW. The figure that matters set large on the left, the
   explanation on the right. Nothing is folded: if you need to know it before
   travelling, it has to be in plain sight. */
.knows { margin-top: clamp(1.8rem, 4vw, 2.8rem); }
.know {
  display: grid;
  gap: clamp(0.8rem, 2vw, 2.6rem);
  padding: clamp(1.5rem, 3.5vw, 2.4rem) 0;
  border-top: 1px solid var(--line-soft);
}
@media (min-width: 820px) {
  .know { grid-template-columns: minmax(0, 0.62fr) minmax(0, 1.38fr); align-items: start; }
}
.know__fig b {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(2.1rem, 1.2rem + 3.2vw, 3.3rem);
  line-height: 0.98;
  letter-spacing: -0.02em;
  color: var(--brand-deep);
}
.know__fig small {
  display: block;
  margin-top: 0.5rem;
  max-width: 24ch;
  font-size: 0.74rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--muted);
  line-height: 1.5;
}
.know__body h3 {
  margin: 0 0 0.5rem;
  font-family: var(--font-body);
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--ink);
}
.know__body p { margin: 0 0 1.1rem; max-width: 62ch; color: var(--muted); font-size: 0.98rem; line-height: 1.7; }
.know__body .know__label {
  margin-bottom: 0.55rem;
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--brand-mid);
  font-weight: 600;
}
/* Um traço curto em vez de uma pastilha: marca o item sem lhe desenhar
   uma caixa à volta. A short rule instead of a pill: it marks the item
   without drawing a box around it. */
.ticks { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.4rem; }
.ticks li { position: relative; padding-left: 1.3rem; font-size: 0.95rem; color: var(--ink-soft); line-height: 1.55; }
.ticks li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.72em;
  width: 12px;
  height: 1px;
  background: var(--brand);
  opacity: 0.6;
}
.know__body .know__note {
  margin: 1.1rem 0 0;
  padding-left: 0.9rem;
  border-left: 2px solid var(--brand-soft);
  font-size: 0.9rem;
  color: var(--muted);
}

/* AS DUAS ILHAS -----------------------------------------------------------
   Sem cartões: só tipografia e o canal a separá-las. Em ecrã largo são duas
   colunas com um tracejado vertical ao meio; em ecrã estreito empilham e o
   tracejado deita-se, que é a leitura certa em ambos os casos.
   THE TWO ISLANDS. No cards: just type, and the channel between them. On a
   wide screen it is two columns with a vertical dashed rule down the middle;
   on a narrow one they stack and the rule lies down, which is the right
   reading either way. */
.twin { display: grid; gap: clamp(1.6rem, 4vw, 2.4rem); margin-top: clamp(1.8rem, 4vw, 2.8rem); }
@media (min-width: 900px) {
  .twin {
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    gap: clamp(1.8rem, 4vw, 3.2rem);
    align-items: start;
  }
}
.twin__name {
  font-family: var(--font-display);
  font-size: clamp(2.1rem, 6vw, 3.4rem);
  line-height: 0.98;
  letter-spacing: -0.015em;
  color: var(--ink);
  margin: 0;
}
.twin__count {
  margin: 0.55rem 0 0;
  font-size: 0.74rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--brand-mid);
}
.twin__count b { font-size: 1.05rem; letter-spacing: 0.02em; }
.twin__note {
  margin: 0.9rem 0 0;
  max-width: 42ch;
  color: var(--ink-soft);
  font-size: 0.98rem;
  line-height: 1.6;
}

/* A constelação: os nomes correm como texto, separados por um ponto da cor
   da marca. É a mesma gramática dos pontos do globo, e lê-se como território
   e não como uma lista de coisas a fazer.
   The constellation: the names run as text, split by a dot in the brand
   colour. Same grammar as the globe's dots, and it reads as territory rather
   than as a list of things to do. */
.twin__places {
  margin: 1.15rem 0 0;
  padding-top: 1.15rem;
  border-top: 1px solid var(--line-soft);
  line-height: 2.05;
  font-size: 0.95rem;
}
/* Cada lugar leva o seu próprio ponto à frente: é a mesma marca que o globo
   usa para desenhar a ilha, e assim nenhum separador fica pendurado no fim
   de uma linha, como acontecia com um ponto entre nomes.
   Every place carries its own dot in front: the same mark the globe uses to
   draw the island, and this way no separator is left dangling at the end of a
   line, the way a dot between names would be. */
.twin__places span {
  display: inline-block;
  margin-right: 1.05em;
  color: var(--ink-soft);
  white-space: nowrap;
  transition: color 0.2s var(--ease);
}
.twin__places span::before {
  content: "";
  display: inline-block;
  width: 4px;
  height: 4px;
  margin-right: 0.55em;
  border-radius: 50%;
  background: var(--brand);
  opacity: 0.5;
  vertical-align: 0.18em;
  transition: opacity 0.2s var(--ease), transform 0.2s var(--ease);
}
.twin__places span:hover { color: var(--brand-deep); }
.twin__places span:hover::before { opacity: 1; transform: scale(1.5); }

/* O canal. A distância é a medida real de costa a costa entre as duas ilhas.
   The channel. The distance is the real coast-to-coast measurement between
   the two islands. */
.twin__sea {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.9rem;
  color: var(--muted);
  font-size: 0.7rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  white-space: nowrap;
}
.twin__sea::before,
.twin__sea::after {
  content: "";
  flex: 1 1 auto;
  border-top: 1px dashed var(--line);
}
@media (min-width: 900px) {
  .twin__sea {
    flex-direction: column;
    align-self: stretch;
    padding: 0.4rem 0;
  }
  .twin__sea span { writing-mode: vertical-rl; }
  .twin__sea::before,
  .twin__sea::after { border-top: 0; border-left: 1px dashed var(--line); width: 0; }
}

/* O QUE ORGANIZAMOS -------------------------------------------------------
   Uma lista numerada, separada por fios. O número faz o trabalho que a caixa
   fazia antes: dá ritmo à leitura sem fechar nada.
   WHAT WE RUN. A numbered list split by hairlines. The number does the work
   the box used to do: it paces the reading without boxing anything in. */
.runs { margin-top: clamp(2.6rem, 6vw, 4rem); }
.runs__title {
  margin: 0 0 0.4rem;
  font-family: var(--font-body);
  font-size: 0.74rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--brand-mid);
}
.runs__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0;
}
@media (min-width: 760px) {
  .runs__list { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: clamp(2rem, 5vw, 3.6rem); }
}
.run {
  display: flex;
  align-items: baseline;
  gap: clamp(0.9rem, 2vw, 1.3rem);
  padding: 1.1rem 0;
  border-top: 1px solid var(--line-soft);
}
.run__n {
  flex: none;
  font-family: var(--font-display);
  font-size: 1.05rem;
  color: var(--brand);
  opacity: 0.55;
  font-variant-numeric: tabular-nums;
}
.run__body { min-width: 0; }
.run__body h4 {
  margin: 0 0 0.25rem;
  font-family: var(--font-body);
  font-size: 1rem;
  font-weight: 600;
  color: var(--ink);
}
.run__body p { margin: 0; color: var(--muted); font-size: 0.93rem; line-height: 1.6; }

/* A frase que fecha. Era uma caixa de aviso; agora é o remate da secção.
   The closing line. It used to be a notice box; now it is the section's
   sign-off. */
.reach__close {
  margin: clamp(2.4rem, 5vw, 3.4rem) auto 0;
  max-width: 66ch;
  text-align: center;
  color: var(--ink-soft);
  font-size: 1.02rem;
  line-height: 1.7;
  padding-top: clamp(1.6rem, 4vw, 2.2rem);
  border-top: 1px solid var(--line-soft);
}
.reach__close b {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.18em;
  color: var(--ink);
}

/* Ficha técnica: rótulo à esquerda, valor à direita, uma linha por facto.
   A spec sheet: label left, value right, one line per fact. */
.spec { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; }
.spec li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.55rem 0;
  border-top: 1px solid var(--line-soft);
  font-size: 0.92rem;
}
.spec li:first-child { border-top: 0; }
.spec b { font-weight: 600; color: var(--ink); }
.spec span { color: var(--muted); text-align: right; }

/* ---------- Detalhe dobrado / folded detail ---------- */
.fold { margin-top: auto; }
.fold > summary {
  cursor: pointer;
  list-style: none;
  font-size: 0.86rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--brand-deep);
  padding-top: 0.9rem;
  border-top: 1px solid var(--line-soft);
}
.fold > summary::-webkit-details-marker { display: none; }
.fold > summary::after { content: " +"; }
.fold[open] > summary::after { content: " −"; }
.fold > summary:hover { color: var(--brand); }
.fold .prose { margin-top: 0.8rem; font-size: 0.94rem; }
.fold .prose p { color: var(--muted); }

/* ---------- Carril numerado / numbered rail ----------
   Os passos deixam de ser uma lista para passarem a ser um caminho, com a
   linha a ligá-los. The steps stop being a list and become a path, with the
   line joining them up. */
.rail { list-style: none; margin: 0; padding: 0; display: grid; gap: 1.4rem; position: relative; }
@media (min-width: 820px) {
  .rail { grid-template-columns: repeat(4, 1fr); gap: 1rem; }
  .rail::before {
    content: "";
    position: absolute;
    left: 1.4rem;
    right: 1.4rem;
    top: 1.35rem;
    height: 2px;
    background: repeating-linear-gradient(90deg, var(--brand-soft) 0 8px, transparent 8px 16px);
  }
}
.rail li { position: relative; display: grid; gap: 0.5rem; align-content: start; }
.rail b {
  width: 2.7rem;
  height: 2.7rem;
  border-radius: 999px;
  display: grid;
  place-items: center;
  background: var(--brand);
  color: #fff;
  font-family: var(--font-display);
  font-size: 1.15rem;
  box-shadow: 0 0 0 6px var(--cream);
}
.rail strong { font-size: 1.02rem; }
.rail p { margin: 0; font-size: 0.93rem; color: var(--muted); }

/* ---------- Facto em destaque / headline fact ---------- */
/* ---------- Índice de lugares / index of places ----------
   Os lugares passam a etiquetas em vez de marcas de lista: lê-se de relance
   quantos são e quais. Places become tags rather than bullets: at a glance you
   see how many there are and which. */
.tagset__label {
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--brand-mid);
  font-weight: 600;
  margin: 1.1rem 0 0;
}

/* ---------- Contact form ---------- */
.form { display: grid; gap: 1.1rem; }
.field { display: grid; gap: 0.4rem; }
.field label { font-size: 0.86rem; font-weight: 600; letter-spacing: 0.01em; }
.field input, .field textarea, .field select {
  font: inherit;
  padding: 0.8em 1em;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--paper);
  color: inherit;
  transition: border-color 0.2s, box-shadow 0.2s;
}
.field textarea { min-height: 140px; resize: vertical; }
.field input:focus, .field textarea:focus {
  outline: none;
  border-color: var(--brand-mid);
  box-shadow: 0 0 0 4px rgba(173, 97, 69, 0.13);
}
.field-row { display: grid; gap: 1.1rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); }

/* O mesmo aspecto de um <label>, para campos cujo rótulo não aponta para uma
   caixa só. Same look as a <label>, for fields whose caption does not point at
   a single box. */
.field-label { font-size: 0.86rem; font-weight: 600; letter-spacing: 0.01em; }

/* ---------- Contador de pessoas / people stepper ---------- */
.stepper {
  display: grid;
  grid-template-columns: 3rem minmax(0, 1fr) 3rem;
  align-items: stretch;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--paper);
  overflow: hidden;
}
.stepper button {
  border: 0;
  background: transparent;
  cursor: pointer;
  font-size: 1.25rem;
  line-height: 1;
  color: var(--brand-deep);
  transition: background 0.2s, color 0.2s;
}
.stepper button:hover { background: rgba(173, 97, 69, 0.1); }
.stepper button:active { background: rgba(173, 97, 69, 0.18); }
.stepper input {
  border: 0;
  border-inline: 1px solid var(--line);
  border-radius: 0;
  text-align: center;
  font-weight: 600;
  padding: 0.8em 0.4em;
  background: transparent;
  /* Fora com as setinhas do browser: os botões já fazem esse trabalho.
     Away with the browser's own arrows: the buttons already do that job. */
  -moz-appearance: textfield;
  appearance: textfield;
}
.stepper input::-webkit-outer-spin-button,
.stepper input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.stepper:focus-within { border-color: var(--brand-mid); box-shadow: 0 0 0 4px rgba(173, 97, 69, 0.13); }

/* ---------- Calendário de datas / date range calendar ---------- */
.daterange { position: relative; }
.daterange__field {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 0.7rem;
  font: inherit;
  text-align: left;
  padding: 0.8em 1em;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--paper);
  color: var(--muted);
  cursor: pointer;
  transition: border-color 0.2s, box-shadow 0.2s, color 0.2s;
}
.daterange.is-set .daterange__field { color: var(--ink); font-weight: 500; }
.daterange__field:hover { border-color: var(--brand-mid); }
.daterange__field[aria-expanded="true"] {
  border-color: var(--brand-mid);
  box-shadow: 0 0 0 4px rgba(173, 97, 69, 0.13);
}
.daterange__icon { flex: none; }
.daterange__text { flex: 1; min-width: 0; }
.daterange__nights {
  flex: none;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--brand-deep);
  background: rgba(173, 97, 69, 0.12);
  padding: 0.2em 0.7em;
  border-radius: 999px;
}
.daterange__nights:empty { display: none; }

.daterange__pop {
  position: absolute;
  z-index: 80;
  top: calc(100% + 0.5rem);
  left: 0;
  padding: 1rem;
  border-radius: var(--r-md);
  background: var(--paper);
  border: 1px solid var(--line-soft);
  box-shadow: var(--shadow-lg);
}
.daterange__pop[hidden] { display: none; }
.cal__nav { display: flex; justify-content: space-between; margin-bottom: 0.2rem; }
.cal__nav button {
  border: 1px solid var(--line);
  background: var(--paper);
  border-radius: 999px;
  width: 2rem;
  height: 2rem;
  cursor: pointer;
  font-size: 1.1rem;
  line-height: 1;
  color: var(--ink);
}
.cal__nav button:disabled { opacity: 0.35; cursor: default; }
.cal__months { display: flex; gap: 1.4rem; }
/* Dois meses lado a lado só quando há largura para isso; abaixo disso, um.
   Two months side by side only when there is room; below that, one. */
@media (max-width: 700px) {
  .cal__months > .cal:last-child { display: none; }
  .daterange__pop { left: 50%; transform: translateX(-50%); }
}
.cal { width: 15.5rem; }
.cal__title {
  font-family: var(--font-display);
  font-size: 1rem;
  text-align: center;
  margin-bottom: 0.5rem;
}
.cal__wd, .cal__grid { display: grid; grid-template-columns: repeat(7, 1fr); }
.cal__wd span {
  text-align: center;
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  padding-bottom: 0.3rem;
}
.cal__grid { gap: 2px 0; }
.cal__day {
  border: 0;
  background: transparent;
  font: inherit;
  font-size: 0.85rem;
  aspect-ratio: 1;
  cursor: pointer;
  border-radius: 999px;
  color: var(--ink-soft);
  transition: background 0.15s, color 0.15s;
}
.cal__day:hover:not(:disabled) { background: rgba(173, 97, 69, 0.14); }
.cal__day:disabled { color: rgba(122, 101, 90, 0.38); cursor: default; }
.cal__day.is-today { font-weight: 700; color: var(--brand-deep); }
/* O miolo do intervalo fica quadrado, para as noites lerem como uma barra
   contínua. The middle of the range stays square, so the nights read as one
   continuous bar. */
.cal__day.is-between { background: rgba(173, 97, 69, 0.14); border-radius: 0; }
.cal__day.is-edge {
  background: var(--brand);
  color: #fff;
  font-weight: 600;
}
.cal__foot { margin-top: 0.6rem; text-align: right; }
.cal__clear {
  border: 0;
  background: transparent;
  cursor: pointer;
  font: inherit;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--brand-deep);
  text-decoration: underline;
}

.checks { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.checks label {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  padding: 0.45em 0.9em;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 0.87rem;
  font-weight: 500;
  cursor: pointer;
  background: var(--paper);
  transition: background 0.2s, border-color 0.2s, color 0.2s;
}
.checks input { accent-color: var(--brand-mid); margin: 0; }
.checks label:has(input:checked) { background: var(--ink); color: #fff; border-color: var(--ink); }

/* ---------- Catálogo de locais e experiências ---------- */
/* Seis grupos, três colunas: dão duas filas cheias, sem a fila órfã que o
   auto-fit deixava. Os cartões esticam todos à altura da fila (align-items
   fica em stretch, o valor por omissão), para os fundos ficarem alinhados.
   Six groups, three columns: two full rows, without the orphan row auto-fit
   was leaving behind. Cards all stretch to the row height (align-items stays
   at its default, stretch), so their bottoms line up. */
.cat-grid {
  display: grid;
  gap: clamp(1rem, 2vw, 1.4rem);
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
@media (max-width: 1000px) {
  .cat-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 620px) {
  .cat-grid { grid-template-columns: 1fr; }
}
.cat-grid .card { display: flex; flex-direction: column; }
/* Altura fixa do cabeçalho: com títulos de uma ou de duas linhas, as listas
   passam a começar todas à mesma altura.
   Fixed header height: with one-line and two-line titles alike, every list
   now starts at the same height. */
.cat-grid .block__head {
  min-height: 3.6rem;
  align-items: center;
  margin-bottom: 0;
  padding-bottom: 1rem;
  border-bottom: 1px solid var(--line-soft);
}
.cat-grid .block__head h3 {
  font-size: clamp(1.05rem, 1rem + 0.35vw, 1.25rem);
  line-height: 1.12;
}
/* A lista encosta ao topo em vez de se espalhar pelo cartão esticado.
   The list sits at the top instead of spreading through the stretched card. */
.cat-grid .cat-list { align-content: start; margin-top: 1rem; }
.cat-list { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.5rem; }
.cat-list li {
  display: grid;
  grid-template-columns: 1.1em minmax(0, 1fr);
  gap: 0.5rem;
  font-size: 0.95rem;
  line-height: 1.4;
  color: var(--ink-soft);
}
.cat-list li::before {
  content: "✓";
  color: var(--brand);
  font-weight: 700;
  line-height: 1.4;
}

/* Opções agrupadas no formulário / grouped options in the form */
/* ---------- Pré-visualização ao passar o rato nas opções ---------- */
.peek-hint { margin: 0 0 0.9rem; color: var(--muted); font-size: 0.85rem; }
.peek {
  position: fixed;
  z-index: 90;
  width: min(340px, calc(100vw - 24px));
  padding: 0.75rem;
  border-radius: var(--r-md);
  border: 1px solid var(--line-soft);
  background: var(--paper);
  box-shadow: var(--shadow-lg);
  pointer-events: none;
  opacity: 0;
  transform: translateY(6px) scale(0.98);
  transition: opacity 0.18s var(--ease), transform 0.18s var(--ease);
}
.peek.is-in { opacity: 1; transform: none; }
.peek__media .shot { aspect-ratio: 16 / 10; border-radius: var(--r-sm); }
.peek__text { padding: 0.7rem 0.35rem 0.2rem; }
.peek__text .kicker { margin: 0 0 0.3rem; }
.peek__text h4 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.08rem;
  line-height: 1.15;
  margin: 0 0 0.4rem;
}
.peek__text p { margin: 0; color: var(--muted); font-size: 0.9rem; line-height: 1.5; }
.peek .chips { margin-top: 0.6rem; }
.peek .chip { font-size: 0.7rem; }
@media (prefers-reduced-motion: reduce) {
  .peek { transition: opacity 0.01s; transform: none; }
}

/* Cada opção do catálogo salta para a experiência no carrossel. */
.cat-link {
  border: 0;
  background: none;
  padding: 0;
  text-align: left;
  cursor: pointer;
  color: inherit;
  font: inherit;
  border-bottom: 1px dashed transparent;
  transition: color 0.2s, border-color 0.2s;
}
.cat-link:hover { color: var(--brand-deep); border-bottom-color: var(--brand-soft); }

/* A ilha manda na lista: um cabeçalho por ilha, com os temas por baixo.
   The island heads the list: one heading per island, themes underneath. */
.check-island + .check-island { margin-top: clamp(1.8rem, 4vw, 2.6rem); }
.check-island__name {
  margin: 0 0 0.9rem;
  font-family: var(--font-display);
  font-size: clamp(1.3rem, 1rem + 1.2vw, 1.7rem);
  color: var(--ink);
}
.check-island__name::after {
  content: "";
  display: block;
  margin-top: 0.55rem;
  width: 2.2rem;
  height: 2px;
  background: var(--brand);
  opacity: 0.55;
}

.check-group { border: 0; padding: 0; margin: 0 0 1.15rem; min-width: 0; }
.check-group:last-of-type { margin-bottom: 0; }
.check-group legend {
  padding: 0;
  margin-bottom: 0.5rem;
  font-size: 0.76rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--brand-mid);
}

.contact-cards { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 265px), 1fr)); }
.contact-card {
  display: flex;
  gap: 0.9rem;
  align-items: center;
  padding: 1.2rem 1.3rem;
  border-radius: var(--r-md);
  background: var(--paper);
  border: 1px solid var(--line-soft);
  text-decoration: none;
  box-shadow: var(--shadow-sm);
  transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease);
}
.contact-card:hover { transform: translateY(-4px); box-shadow: var(--shadow); }
.contact-card em { font-style: normal; font-size: 1.6rem; flex: none; }
.contact-card small { display: block; font-size: 0.74rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); }
/* Um e-mail é uma palavra só e não quebra sozinho. Sem min-width:0 o item flex
   recusa encolher e o texto sai fora do cartão.
   An email is a single unbreakable word. Without min-width:0 the flex item
   refuses to shrink and the text spills outside the card. */
.contact-card > span { min-width: 0; flex: 1; }
.contact-card strong {
  font-weight: 600;
  display: block;
  font-size: 0.95rem;
  /* O <wbr> antes do @ trata do caso normal; isto é a rede de segurança para
     ecrãs muito estreitos. The <wbr> before the @ handles the normal case; this
     is the safety net for very narrow screens. */
  overflow-wrap: anywhere;
  line-height: 1.35;
}

/* ---------- Testimonials ---------- */
.review-links { display: flex; flex-wrap: wrap; gap: 0.8rem; }
.review-link {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.9rem 1.3rem;
  border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.2);
  text-decoration: none;
  font-weight: 600;
  transition: background 0.25s, transform 0.25s var(--ease);
}
.review-link:hover { background: rgba(255, 255, 255, 0.16); transform: translateY(-3px); }
.stars { color: var(--accent); letter-spacing: 0.1em; }

/* Variante para fundos claros (era style inline no site.js).
   Light-background variant (used to be an inline style in site.js). */
.review-link--light {
  background: rgba(8, 34, 43, 0.04);
  border-color: var(--line);
  color: var(--ink);
}
.review-link--light:hover { background: rgba(8, 34, 43, 0.08); }
.g-mark { width: 20px; height: 20px; flex: none; }

/* ---------- Carrossel automático de avaliações / auto-scrolling reviews ----------
   A fila é duplicada no site.js; o track desliza -50% e volta ao início, pelo
   que o ciclo não tem costura visível.
   The row is duplicated in site.js; the track slides -50% and restarts, so the
   loop has no visible seam. */
.reviews {
  overflow: hidden;
  margin-block: clamp(1.5rem, 4vw, 2.5rem);
  /* Esbate as pontas em vez de as cortar a direito.
     Fades the ends instead of cutting them off square. */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.reviews__track {
  display: flex;
  width: max-content;
  animation: reviews-slide var(--rv-dur, 40s) linear infinite;
}
/* Pausa ao passar o rato ou ao focar com o teclado, para se poder ler.
   Pauses on hover or keyboard focus, so a review can actually be read. */
.reviews:hover .reviews__track,
.reviews:focus-within .reviews__track { animation-play-state: paused; }
.reviews__row { display: flex; gap: 1rem; padding-right: 1rem; }
@keyframes reviews-slide {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

.review-card {
  flex: 0 0 min(88vw, 360px);
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  margin: 0;
  padding: 1.5rem;
  border-radius: var(--r-md);
  background: var(--cream);
  border: 1px solid var(--line-soft);
  box-shadow: var(--shadow-sm);
}
.review-card blockquote {
  margin: 0;
  font-size: 0.98rem;
  line-height: 1.6;
  color: var(--ink-soft);
}
.review-card blockquote::before { content: "“"; }
.review-card blockquote::after { content: "”"; }
.review-card figcaption {
  margin-top: auto;
  font-weight: 600;
  font-size: 0.92rem;
  color: var(--ink);
}
/* O aviso de tradução: presente, mas mais leve do que o nome de quem
   escreveu. The translation note: present, but lighter than the name of the
   person who wrote it. */
.review-card__tr {
  display: block;
  margin-top: 0.35rem;
  font-weight: 400;
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  opacity: 0.75;
}

.review-card figcaption small {
  display: block;
  font-weight: 400;
  font-size: 0.8rem;
  color: var(--muted);
}

/* Sem animação para quem pede menos movimento — passa a poder arrastar-se.
   No animation for anyone asking for less motion — becomes swipeable instead. */
@media (prefers-reduced-motion: reduce) {
  .reviews { overflow-x: auto; }
  .reviews__track { animation: none; }
  .reviews__row:last-child { display: none; }
}

/* ---------- CTA band ---------- */
.cta {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  border-radius: var(--r-xl);
  padding: clamp(2.2rem, 5vw, 3.8rem);
  background: linear-gradient(135deg, var(--brand-deep), var(--brand-mid) 80%);
  color: #fff;
  text-align: center;
}
.cta::after {
  content: "";
  position: absolute;
  z-index: -1;
  inset: -40% -10% auto auto;
  width: 420px;
  height: 420px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(217, 160, 78, 0.42), transparent 65%);
}
.cta h2 { color: #fff; }
.cta p { color: rgba(255, 255, 255, 0.92); max-width: 55ch; margin-inline: auto; }
.cta .btn-row { justify-content: center; margin-top: 1.8rem; }

/* ---------- Marquee ---------- */
.marquee {
  overflow: hidden;
  border-block: 1px solid var(--line-soft);
  background: var(--sand);
  padding: 0.85rem 0;
  white-space: nowrap;
}
.marquee__track { display: inline-flex; gap: 2.5rem; animation: slide 34s linear infinite; }
.marquee span {
  font-family: var(--font-display);
  font-size: 1.05rem;
  color: var(--brand-deep);
  opacity: 0.75;
  display: inline-flex;
  gap: 2.5rem;
  align-items: center;
}
.marquee span::after { content: "•"; color: var(--brand); }
@keyframes slide { from { transform: translateX(0); } to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) { .marquee__track { animation: none; } }

/* ---------- Footer ---------- */
.site-footer {
  background: var(--deep);
  color: rgba(255, 255, 255, 0.72);
  padding: clamp(3rem, 6vw, 4.5rem) 0 2rem;
}
.footer-grid {
  display: grid;
  gap: clamp(1.6rem, 4vw, 3rem);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr));
}
.site-footer h4 {
  font-family: var(--font-body);
  font-size: 0.76rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--brand-soft);
  margin-bottom: 1rem;
}
.site-footer ul { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.55rem; }
.site-footer a { text-decoration: none; transition: color 0.2s; overflow-wrap: anywhere; }
.site-footer a:hover { color: #fff; text-decoration: underline; }
.site-footer .brand { color: #fff; margin: 0 0 0.9rem; }
.footer-bottom {
  margin-top: 3rem;
  padding-top: 1.4rem;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  display: flex;
  flex-wrap: wrap;
  gap: 0.8rem;
  justify-content: space-between;
  font-size: 0.83rem;
}

/* ---------- Floating WhatsApp ---------- */
.fab {
  position: fixed;
  right: max(1rem, env(safe-area-inset-right));
  bottom: max(1rem, env(safe-area-inset-bottom));
  z-index: 90;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.55rem;
  padding: 0.8rem 1.15rem;
  border-radius: 999px;
  background: #21ba5a;
  color: #fff;
  font-weight: 600;
  font-size: 0.92rem;
  text-decoration: none;
  /* Brilho centrado no botão (sem deslocamento vertical, que o fazia escorrer
     para baixo e ficar cortado no fundo do ecrã) + sombra de apoio subtil.
     Glow centred on the button (no vertical offset, which made it pool below
     and get clipped at the bottom of the screen) + a subtle grounding shadow. */
  box-shadow:
    0 0 18px rgba(33, 186, 90, 0.45),
    0 0 36px rgba(33, 186, 90, 0.22),
    0 6px 16px -8px rgba(0, 0, 0, 0.4);
  transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease);
}
.fab:hover {
  transform: translateY(-3px) scale(1.02);
  box-shadow:
    0 0 22px rgba(33, 186, 90, 0.6),
    0 0 44px rgba(33, 186, 90, 0.3),
    0 10px 20px -10px rgba(0, 0, 0, 0.45);
}
.fab svg { width: 20px; height: 20px; fill: currentColor; display: block; flex: none; }
@media (max-width: 560px) {
  .fab span { display: none; }
  /* Ícone-só: círculo perfeito com o ícone ao centro.
     Icon-only: a perfect circle with the icon centred. */
  .fab { gap: 0; padding: 0; width: 52px; height: 52px; }
}

/* ---------- Reveal on scroll ----------
   O estado escondido está preso a .js, uma classe que só existe se o
   JavaScript correr. Sem JavaScript nunca chega a haver opacity: 0, e o texto
   que veio no HTML lê-se na mesma: a animação é um extra, não a condição para
   o conteúdo aparecer. Antes disto, o HTML estava lá mas invisível.
   A classe é posta no <head>, antes do primeiro desenho, senão via-se o
   conteúdo aparecer e desaparecer outra vez.

   The hidden state is tied to .js, a class that only exists if JavaScript
   runs. With no JavaScript there is never an opacity: 0, and the text that
   came down in the HTML reads just the same: the animation is an extra, not
   the condition for the content to exist. Before this, the HTML was there but
   invisible. The class is set in the <head>, before the first paint, or the
   content would be seen appearing and then vanishing again. */
.js .reveal { opacity: 0; transform: translateY(18px); transition: opacity 0.7s var(--ease), transform 0.7s var(--ease); }
.js .reveal.is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .js .reveal { opacity: 1; transform: none; transition: none; }
}

/* ---------- Split media block ---------- */
.split {
  display: grid;
  gap: clamp(1.5rem, 4vw, 3.5rem);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
  align-items: center;
}
.frame {
  position: relative;
  border-radius: var(--r-lg);
  overflow: hidden;
  aspect-ratio: 4 / 3;
  background: linear-gradient(150deg, var(--brand-deep), var(--brand-mid));
  box-shadow: var(--shadow-lg);
}
.frame img { width: 100%; height: 100%; object-fit: cover; }
.frame--tall { aspect-ratio: 3 / 4; }

/* A sobre.jpg é 3:2 e o "Quem Somos" corta-a a 3:4, ficando só com a metade
   central: os três rapazes caíam a 34% da largura, encostados à esquerda.
   Deslocar o recorte para a esquerda empurra-os para o meio do quadro.
   Só aqui: a mesma foto na página inicial usa um corte 4:3, onde já está
   centrada, e o retrato do Fundador partilha a classe .frame--tall.

   sobre.jpg is 3:2 and the About page crops it to 3:4, keeping only the middle
   half: the three lads landed at 34% across, hard against the left. Moving the
   crop window left pushes them into the centre of the frame.
   Scoped here on purpose: the same photo on the home page uses a 4:3 crop,
   where it is already centred, and the Founder portrait shares .frame--tall. */
body[data-page="about"] .aside-sticky .frame img { object-position: 35% center; }

/* Texto longo ao lado de uma imagem: coluna de leitura mais larga, topos
   alinhados e a imagem acompanha o scroll em vez de flutuar ao centro. */
.split--start { align-items: start; }
@media (min-width: 900px) {
  .split--reading { grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr); }
}
.aside-sticky { display: grid; gap: 1rem; align-content: start; }
@media (min-width: 900px) {
  .aside-sticky { position: sticky; top: 104px; }
}

/* ---------- Fundador ---------- */
.founder-role {
  margin: 0.9rem 0 0;
  font-size: 0.86rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--brand-mid);
  text-align: center;
}
.pull-quote {
  margin: 1.8rem 0 0;
  padding: 0 0 0 1.4rem;
  border-left: 4px solid var(--accent);
  font-family: var(--font-display);
  font-size: clamp(1.15rem, 1rem + 0.7vw, 1.55rem);
  line-height: 1.35;
  color: var(--brand-deep);
}

/* Saudação destacada / pull-quote */
.welcome {
  margin: 1.6rem 0 0;
  padding: 1.15rem 1.4rem;
  border-radius: var(--r-md);
  border-left: 4px solid var(--brand);
  background: linear-gradient(135deg, rgba(173, 97, 69, 0.09), rgba(217, 160, 78, 0.14));
  font-family: var(--font-display);
  font-size: clamp(1.05rem, 1rem + 0.35vw, 1.25rem);
  line-height: 1.4;
  color: var(--brand-deep);
}
.welcome p { color: inherit; margin: 0; }
.welcome p + p { margin-top: 0.25em; }

/* Lista "o que fazemos": grelha de cartões com o emoji numa coluna própria,
   para que todos os textos comecem no mesmo ponto e as linhas quebradas alinhem.
   "What we do" grid: the emoji sits in its own fixed column so every label starts
   at the same x-position and wrapped lines align under the text, not the icon. */
.do-title {
  font-family: var(--font-body);
  font-size: 0.78rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--brand-mid);
  margin: 0 0 1.1rem;
}
.do-grid {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 0.8rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
}
.do-grid li {
  display: grid;
  grid-template-columns: 46px minmax(0, 1fr);
  align-items: center;
  gap: 0.9rem;
  padding: 0.9rem 1.1rem;
  background: var(--paper);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-sm);
  font-size: 0.96rem;
  line-height: 1.4;
  transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease);
}
.do-grid li:hover { transform: translateY(-3px); box-shadow: var(--shadow); }
.do-ico {
  width: 46px;
  height: 46px;
  display: grid;
  place-items: center;
  border-radius: 14px;
  font-size: 1.3rem;
  line-height: 1;
  background: linear-gradient(150deg, rgba(173, 97, 69, 0.13), rgba(217, 160, 78, 0.2));
}

.hidden { display: none !important; }
