/* flamenco-beach-culebra.com — "Glassline" from design.md.
   Geist for everything, near-black ink on fog-grey neutrals, one cobalt for
   action. Flat by rule: the brief says "no gradients, this system is flat on
   purpose" and "use Tertiary for exactly one action per screen", and both are
   load-bearing rather than decorative preferences. */

:root{
  --ink:#0F1419;         /* primary: headlines & core text */
  --sage:#4A5568;        /* secondary: borders, meta, captions */
  --cobalt:#2C5EF5;      /* tertiary: the single interaction accent */
  --cobalt-ink:#2C5EF5;  /* the same cobalt as TEXT on a light surface */
  --cobalt-dk:#2452D8;   /* button hover */
  --cobalt-lt:#6E97FF;   /* the accent as TEXT INSIDE a dark band - never on white */
  --neutral:#F1F3F5;     /* page foundation */
  --surface:#FFFFFF;     /* card / panel surface */
  --white:#FFFFFF;
  --line:#D3D8DE;        /* hairlines and dividers ONLY - controls use --sage */
  --r-sm:6px;
  --r-md:10px;
  --r-lg:16px;
  --maxw:1120px;
}

*{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:"Geist",system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif;
  font-size:18px;line-height:1.6;color:var(--ink);background:var(--white);
  -webkit-font-smoothing:antialiased;
}
.wrap{max-width:var(--maxw);margin:0 auto;padding:0 22px}
img{max-width:100%;height:auto;display:block}
a{color:var(--cobalt-ink);text-decoration:none}
a:hover{text-decoration:underline}

h1,h2,h3,.logo,.display{font-family:"Geist",system-ui,sans-serif;font-weight:700;letter-spacing:-.025em;line-height:1.08}
h1{font-size:2.3rem;margin:.1em 0 .5em;font-weight:700;letter-spacing:-.04em}
h2{font-size:1.7rem;margin:2.2em 0 .6em}
h3{font-size:1.2rem;margin:1.6em 0 .4em}
h4{font-family:"Geist",system-ui,sans-serif;font-weight:600;font-size:.72rem;letter-spacing:.12em;text-transform:uppercase;color:var(--sage);margin:0 0 .6em}
p{margin:0 0 1.05em}
@media(max-width:640px){h1{font-size:1.85rem}h2{font-size:1.4rem}}

.label{font-family:"Geist",system-ui,sans-serif;font-weight:600;font-size:.72rem;letter-spacing:.12em;text-transform:uppercase;color:var(--cobalt-ink);margin:0 0 .5em}

/* ---------- buttons ---------- */
.btn{
  display:inline-block;background:var(--cobalt);color:#fff;font-family:"Geist",system-ui,sans-serif;font-weight:600;
  font-size:.82rem;letter-spacing:.04em;text-transform:uppercase;
  padding:12px 20px;border-radius:var(--r-md);border:2px solid var(--cobalt);
  transition:background .15s,border-color .15s;text-align:center;
}
.btn:hover{background:var(--cobalt-dk);border-color:var(--cobalt-dk);text-decoration:none;color:#fff}
.btn-ghost{background:transparent;color:var(--ink);border:2px solid var(--ink)}
.btn-ghost:hover{background:var(--ink);color:#fff}

/* ---------- header ---------- */
.site-head{position:sticky;top:0;z-index:40;background:var(--white);border-bottom:1px solid var(--line)}
.site-head .wrap{display:flex;align-items:center;gap:18px;height:66px}
.logo{display:flex;align-items:center;gap:10px;color:var(--ink);font-size:1.1rem;font-weight:700;letter-spacing:-.02em}
.logo:hover{text-decoration:none}
.logo .mark{width:30px;height:30px;flex:0 0 auto}
.nav{margin-left:auto;display:flex;align-items:center;gap:24px}
.nav a{color:var(--ink);font-family:"Geist",system-ui,sans-serif;font-weight:600;font-size:.92rem;letter-spacing:.01em}
.nav a:hover{color:var(--cobalt-ink);text-decoration:none}
.nav a.btn{color:#fff}
.nav a.btn:hover{color:#fff}
.nav-toggle{display:none;margin-left:auto;background:none;border:0;font-size:1.5rem;color:var(--ink);cursor:pointer}
@media(max-width:860px){
  .nav-toggle{display:block}
  .nav{display:none;position:absolute;top:66px;left:0;right:0;flex-direction:column;gap:0;
        background:var(--white);border-bottom:1px solid var(--line);padding:8px 22px 16px}
  .nav.open{display:flex}
  .nav a{padding:11px 0;border-bottom:1px solid var(--line);width:100%}
  .nav a.btn{margin-top:10px;text-align:center}
}

/* ---------- breadcrumb ---------- */
.crumb{font-family:"Geist",system-ui,sans-serif;font-weight:600;font-size:.74rem;color:var(--sage);padding:14px 22px 0;text-transform:uppercase;letter-spacing:.05em}
.crumb a{color:var(--sage)}

/* ---------- hero (flat solid overlay, not a gradient) ---------- */
.hero{position:relative;background:var(--ink) center/cover no-repeat;background-image:url('/images/hero.jpg');color:#fff;border-bottom:4px solid var(--cobalt)}
.hero{background-image:-webkit-image-set(url('/images/hero.webp') type('image/webp'),url('/images/hero.jpg') type('image/jpeg'));background-image:image-set(url('/images/hero.webp') type('image/webp'),url('/images/hero.jpg') type('image/jpeg'))}
/* the flat scrim. Its ALPHA is set by measurement in section (a) below, not
   here - a value chosen by eye against a photograph that does not exist yet is
   the exact mistake the last site shipped. */
.hero::before{content:"";position:absolute;inset:0;background:rgba(15,20,25,.62)}
/* NO ::after GRADIENT. design.md: "Don't introduce gradients. This system is
   flat on purpose." The scaffold stacked a 55%-tall bottom fade on top of the
   scrim; one flat scrim does the same job and obeys the brief. */
.hero .wrap{position:relative;z-index:1;padding:163px 22px 145px;min-height:550px;display:flex;flex-direction:column;justify-content:center}
.hero-copy{max-width:52%}
.hero .label{color:var(--surface);opacity:1}
.hero h1{font-size:3.2rem;margin:0 0 .35em;color:#fff;font-weight:700;letter-spacing:-.045em}
.hero .lede{font-size:1.18rem;color:var(--neutral);margin-bottom:1.5em;line-height:1.5}
.hero-cta{display:flex;gap:14px;flex-wrap:wrap;margin-bottom:1.6em}
.hero .btn-ghost{color:#fff;border-color:#fff}
.hero .btn-ghost:hover{background:#fff;color:var(--ink)}
.hero-trust{font-size:.95rem;color:var(--neutral);margin:0}
.hero-trust b{color:#fff}
@media(max-width:900px){.hero-copy{max-width:100%}}
@media(max-width:640px){.hero h1{font-size:2.1rem}.hero .wrap{padding:64px 22px 56px;min-height:0}}

/* ---------- tour-data facts strip (under hero) ---------- */
.facts-strip{background:var(--surface);border-bottom:1px solid var(--line)}
.facts-strip .wrap{display:flex;flex-wrap:wrap;padding:0}
.facts-item{flex:1 1 0;min-width:150px;padding:16px 22px;border-right:1px solid var(--line)}
.facts-item:last-child{border-right:0}
.facts-val{font-family:"Geist",system-ui,sans-serif;font-weight:700;font-size:1.18rem;line-height:1.05;color:var(--ink);letter-spacing:-.02em}
.facts-val .star{color:var(--cobalt)}
.facts-label{font-family:"Geist",system-ui,sans-serif;font-size:.7rem;font-weight:600;color:var(--sage);text-transform:uppercase;letter-spacing:.06em;margin-top:.45em}
@media(max-width:780px){.facts-item{flex:1 1 50%;min-width:0;border-bottom:1px solid var(--line)}.facts-item:nth-child(2n){border-right:0}}
@media(max-width:420px){.facts-item{flex:1 1 100%;border-right:0}}

/* ---------- on-page jump bar (sticky anchor menu, homepage) ---------- */
.section-nav{position:sticky;top:66px;z-index:30;background:var(--ink);border-bottom:1px solid var(--ink)}
.section-nav .wrap{display:flex;gap:0;padding:0;overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none}
.section-nav .wrap::-webkit-scrollbar{display:none}
.section-nav a{flex:0 0 auto;display:inline-block;padding:13px 18px;color:#fff;
  font-family:"Geist",system-ui,sans-serif;font-weight:600;font-size:.82rem;letter-spacing:.02em;white-space:nowrap;border-right:1px solid rgba(255,255,255,.12)}
.section-nav a:hover{background:var(--cobalt);color:#fff;text-decoration:none}
@media(max-width:780px){.section-nav{top:0}.section-nav a{padding:12px 15px;font-size:.8rem}}

/* ---------- explore link cluster (keyword interlinks, above footer) ---------- */
.explore{margin:2.4em 0 0;padding:26px 0 0;border-top:2px solid var(--ink)}
.explore h2{margin:0 0 .7em}
.explore-links{display:grid;grid-template-columns:repeat(3,1fr);gap:10px 26px}
.explore-links a{display:block;font-family:"Geist",system-ui,sans-serif;font-size:.92rem;font-weight:500;
  color:var(--ink);padding:6px 0 6px 16px;border-left:3px solid var(--cobalt);line-height:1.35}
.explore-links a:hover{color:var(--cobalt-ink);border-left-color:var(--cobalt-ink)}
@media(max-width:780px){.explore-links{grid-template-columns:repeat(2,1fr)}}
@media(max-width:480px){.explore-links{grid-template-columns:1fr}}

/* ---------- main / prose ---------- */
.section-pad{padding-top:40px;padding-bottom:64px}
.prose{max-width:760px;margin:0 auto}
.prose.wide{max-width:960px}
.prose ul,.prose ol{margin:0 0 1.15em;padding-left:1.2em}
.prose li{margin:.32em 0}
ul.check{list-style:none;padding-left:0}
ul.check li{position:relative;padding-left:1.7em;margin:.5em 0}
ul.check li::before{content:"\2192";position:absolute;left:0;top:0;color:var(--cobalt-ink);font-weight:700}

/* page-hero banner inside articles */
.page-hero{margin:0 0 1.6em;border-radius:var(--r-lg);overflow:hidden}
.page-hero img{width:100%;max-height:380px;object-fit:cover}

/* ---------- answer box ---------- */
.answer-box{background:var(--neutral);border-left:5px solid var(--cobalt);padding:20px 24px;margin:0 0 1.8em;border-radius:0 var(--r-md) var(--r-md) 0}
.answer-box p{margin:0}
.answer-box strong{color:var(--ink)}
.answer-box a{text-decoration:underline;text-underline-offset:2px}

/* ---------- key takeaways (homecontent.TAKEAWAYS) ---------- */
.ia-takeaways{background:var(--ink);border-radius:16px;padding:26px 30px;margin:34px 0;color:rgba(255,255,255,.92)}
.ia-takeaways h2{color:#fff;margin:0 0 14px;font-size:1.25rem}
.ia-takeaways ul{list-style:none;margin:0;padding:0}
.ia-takeaways li{position:relative;padding:7px 0 7px 30px;line-height:1.55;border-bottom:1px solid rgba(255,255,255,.14)}
.ia-takeaways li:last-child{border-bottom:0}
.ia-takeaways li::before{content:"\2713";position:absolute;left:2px;top:7px;color:var(--accent,var(--cobalt));font-weight:700}
.ia-takeaways b,.ia-takeaways strong{color:#fff}
.ia-takeaways a{color:var(--accent,var(--cobalt));filter:brightness(1.35);text-decoration-color:rgba(255,255,255,.35)}
.ia-takeaways a:hover{color:#fff;filter:none}

/* ---------- tables ---------- */
table{width:100%;border-collapse:collapse;margin:1.2em 0;font-size:.96rem}
th,td{text-align:left;padding:11px 13px;border-bottom:1px solid var(--line);vertical-align:top}
thead th{background:var(--ink);color:#fff;font-family:"Geist",system-ui,sans-serif;font-weight:600;font-size:.72rem;letter-spacing:.06em;text-transform:uppercase}

/* ---------- tip / keyfacts / proscons ---------- */
.tip{background:var(--neutral);border:2px solid var(--cobalt);border-radius:var(--r-md);padding:16px 20px;margin:1.5em 0}
.tip-label{display:inline-block;font-family:"Geist",system-ui,sans-serif;font-weight:600;font-size:.7rem;letter-spacing:.1em;text-transform:uppercase;color:var(--cobalt-ink);margin-bottom:.3em}
.tip p{margin:0}

.keyfacts{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;background:var(--line);border:1px solid var(--line);border-radius:var(--r-md);overflow:hidden;margin:1.6em 0}
.keyfacts div{background:var(--surface);padding:14px 16px}
.kf-label{display:block;font-family:"Geist",system-ui,sans-serif;font-size:.66rem;letter-spacing:.1em;text-transform:uppercase;color:var(--sage);font-weight:600;margin-bottom:3px}
.keyfacts b{font-size:1.02rem}
@media(max-width:640px){.keyfacts{grid-template-columns:repeat(2,1fr)}}

.proscons{display:grid;grid-template-columns:1fr 1fr;gap:18px;margin:1.6em 0}
.pc{border:2px solid var(--line);border-radius:var(--r-md);padding:18px 20px;background:var(--surface)}
.pc ul{list-style:none;margin:0;padding:0}
.pc li{position:relative;padding-left:1.6em;margin:.5em 0}
.pros{border-color:var(--cobalt)}
.pros li::before{content:"\2713";position:absolute;left:0;color:var(--cobalt-ink);font-weight:700}
.cons li::before{content:"!";position:absolute;left:.25em;color:var(--sage);font-weight:700}
@media(max-width:640px){.proscons{grid-template-columns:1fr}}

.inclist{display:grid;grid-template-columns:1fr 1fr;gap:18px;margin:1.6em 0}
.inclist>div{border:2px solid var(--line);border-radius:var(--r-md);padding:18px 20px;background:var(--surface)}
.inclist h4{margin:0 0 .5em;font-family:"Geist",system-ui,sans-serif;font-size:.72rem;letter-spacing:.08em;text-transform:uppercase}
.inclist ul{list-style:none;margin:0;padding:0}
.inclist li{position:relative;padding-left:1.6em;margin:.5em 0}
.inclist .inc{border-color:var(--cobalt)}
.inclist .inc h4{color:var(--cobalt-ink)}
.inclist .inc li::before{content:"\2713";position:absolute;left:0;color:var(--cobalt-ink);font-weight:700}
.inclist .exc h4{color:var(--sage)}
.inclist .exc li::before{content:"\00d7";position:absolute;left:.15em;color:var(--sage);font-weight:700}
@media(max-width:640px){.inclist{grid-template-columns:1fr}}

/* ---------- scorecard (review pages) ---------- */
.scorecard{display:grid;grid-template-columns:200px 1fr;gap:0;border:2px solid var(--ink);border-radius:var(--r-md);overflow:hidden;margin:0 0 1.8em}
.sc-score{background:var(--ink);color:#fff;padding:22px;display:flex;flex-direction:column;justify-content:center;text-align:center}
.sc-big{font-family:"Geist",system-ui,sans-serif;font-weight:700;font-size:3rem;line-height:1;letter-spacing:-.03em}
.sc-stars{color:var(--cobalt);letter-spacing:2px;margin:.2em 0}
.sc-rev{font-size:.8rem;color:var(--neutral)}
.sc-price{margin-top:.5em;font-weight:700;color:#fff}
.sc-specs{padding:8px 22px;background:var(--surface)}
.sc-row{display:flex;justify-content:space-between;gap:14px;padding:9px 0;border-bottom:1px solid var(--line);font-size:.95rem}
.sc-row:last-child{border-bottom:0}
.sc-row span{color:var(--sage)}
.sc-row b{text-align:right}
@media(max-width:560px){.scorecard{grid-template-columns:1fr}}

/* ---------- review hub cards ---------- */
.rev-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:18px;margin:1.5em 0 .4em}
@media(max-width:600px){.rev-grid{grid-template-columns:1fr}}
.rev-card{display:flex;flex-direction:column;border:2px solid var(--line);border-radius:var(--r-lg);padding:0;overflow:hidden;background:var(--surface);color:var(--ink);transition:border-color .15s}
.rev-card:hover{border-color:var(--cobalt);text-decoration:none}
.rev-thumb{margin:0;aspect-ratio:16/9;overflow:hidden;background:var(--ink)}
.rev-thumb img{width:100%;height:100%;object-fit:cover;display:block;transition:transform .25s}
.rev-card:hover .rev-thumb img{transform:scale(1.04)}
.rev-body{display:flex;flex-direction:column;flex:1;padding:16px 20px 18px}
.rev-meta{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:.6em}
.rev-score{font-family:"Geist",system-ui,sans-serif;font-weight:700;font-size:1.3rem;line-height:1;color:var(--ink)}
.rev-stars{color:var(--cobalt);letter-spacing:1px;font-size:.9rem}
.rev-count{font-family:"Geist",system-ui,sans-serif;font-weight:500;font-size:.72rem;color:var(--sage)}
.rev-card h3{font-weight:700;font-size:1.05rem;line-height:1.3;margin:0 0 .4em}
.rev-card p{font-size:.92rem;color:var(--sage);margin:0 0 1em}
.rev-price{font-weight:700;font-size:.9rem;margin-top:auto}
.rev-more{display:block;color:var(--cobalt-ink);font-family:"Geist",system-ui,sans-serif;font-weight:600;font-size:.74rem;text-transform:uppercase;letter-spacing:.04em;margin-top:.5em}

/* ---------- tour cards ---------- */
.tours-grid{display:grid;grid-template-columns:repeat(3,1fr);grid-auto-rows:1fr;gap:20px;margin:1.5em 0 .4em}
.tours-grid.cols-4{grid-template-columns:repeat(4,1fr);gap:16px}
@media(max-width:860px){.tours-grid{grid-template-columns:repeat(2,1fr)}}
@media(max-width:1024px){.tours-grid.cols-4{grid-template-columns:repeat(2,1fr)}}
@media(max-width:560px){.tours-grid,.tours-grid.cols-4{grid-template-columns:1fr}}
.tour{border:2px solid var(--line);border-radius:var(--r-lg);overflow:hidden;background:var(--surface);display:flex;flex-direction:column;transition:border-color .15s}
.tour:hover{border-color:var(--cobalt)}
/* whole card is an <a> (see helpers._card) — kill link styling, keep hover feedback */
a.tour{color:inherit;text-decoration:none}
a.tour:hover .btn{filter:brightness(1.08)}
.thumb{position:relative;aspect-ratio:3/2;overflow:hidden;background:var(--neutral)}
.thumb img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.badge{position:absolute;top:10px;left:10px;background:var(--cobalt);color:#fff;font-family:"Geist",system-ui,sans-serif;font-weight:600;font-size:.64rem;letter-spacing:.06em;text-transform:uppercase;padding:5px 9px;border-radius:var(--r-sm)}
.tour-body{padding:16px 16px 18px;display:flex;flex-direction:column;flex:1}
.tour-body h3{font-size:1.02rem;margin:0 0 .45em;line-height:1.25;font-weight:700}
.rate{font-size:.85rem;color:var(--sage);margin-bottom:.5em}
.star{color:var(--cobalt)}
.price{font-weight:700;margin-bottom:.8em}
.price span{font-weight:400;color:var(--sage);font-size:.85rem}
.tour-body .btn{margin-top:auto}

/* ---------- book-card (docked chip availability) ---------- */
.book-card{position:relative;border:2px solid var(--ink);border-radius:var(--r-md);padding:26px 18px 14px;margin:1.6em 0;background:var(--surface)}
.book-chip{position:absolute;top:-13px;left:18px;background:var(--cobalt);color:#fff;font-family:"Geist",system-ui,sans-serif;font-weight:600;font-size:.7rem;letter-spacing:.08em;text-transform:uppercase;padding:5px 12px;border-radius:var(--r-sm)}
.gyg-frame{min-height:220px}

/* ---------- comparison table ---------- */
.cmp-wrap{overflow-x:auto;margin:1.8em 0}
/* Break the comparison table out of the 760px prose column so it has more room
   to breathe. Prose has ~158px of slack each side inside .wrap, so -110px is safe. */
@media(min-width:1080px){.cmp-wrap{margin-left:-110px;margin-right:-110px}}
table.cmp{border-collapse:separate;border-spacing:0;min-width:640px;width:100%;font-size:1.02rem}
table.cmp th,table.cmp td{border:0;border-bottom:1px solid var(--line);padding:16px 20px;background:var(--surface)}
table.cmp thead th{background:var(--neutral);color:var(--ink);vertical-align:bottom;text-transform:none;letter-spacing:-.01em;font-family:"Geist",system-ui,sans-serif;font-weight:700}
table.cmp .rowlabel{font-family:"Geist",system-ui,sans-serif;font-weight:600;color:var(--sage);font-size:.82rem;text-transform:uppercase;letter-spacing:.04em}
table.cmp .feat{background:var(--neutral);border-left:2px solid var(--cobalt);border-right:2px solid var(--cobalt)}
table.cmp thead .feat{border-top:2px solid var(--cobalt)}
table.cmp tr.cmp-book .feat{border-bottom:2px solid var(--cobalt)}
.cmp-badge{display:inline-block;background:var(--cobalt);color:#fff;font-family:"Geist",system-ui,sans-serif;font-weight:600;font-size:.62rem;letter-spacing:.06em;text-transform:uppercase;padding:4px 8px;border-radius:var(--r-sm);margin-bottom:6px}
.feat-title{display:block;font-family:"Geist",system-ui,sans-serif;font-weight:700;font-size:1.12rem;letter-spacing:-.02em}
.col-alt{color:var(--ink)}
table.cmp .btn{width:100%;padding:11px 10px;font-size:.76rem}

/* ---------- gallery ---------- */
.gallery{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin:1.8em 0}
.gallery figure{margin:0;position:relative;border-radius:var(--r-md);overflow:hidden}
.gallery img{width:100%;aspect-ratio:3/4;object-fit:cover}
.gallery figcaption{position:absolute;left:0;right:0;bottom:0;background:rgba(15,20,25,.82);color:#fff;font-family:"Geist",system-ui,sans-serif;font-weight:600;font-size:.72rem;padding:14px 12px 9px;text-transform:uppercase;letter-spacing:.04em}
@media(max-width:760px){.gallery{grid-template-columns:repeat(2,1fr)}}

/* ---------- steps ---------- */
.steps{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin:1.5em 0;counter-reset:s}
.step{border-top:3px solid var(--cobalt);padding:14px 4px 0;counter-increment:s}
.step::before{content:counter(s);font-family:"Geist",system-ui,sans-serif;font-weight:700;font-size:1.5rem;color:var(--cobalt-ink);display:block;margin-bottom:.1em}
.step h3{margin:0 0 .25em;font-size:1.05rem}
.step p{font-size:.9rem;color:var(--sage);margin:0}
@media(max-width:760px){.steps{grid-template-columns:repeat(2,1fr)}}

/* ---------- reviews band ---------- */
.reviews-band{background:var(--neutral);border-radius:var(--r-lg);padding:24px;margin:1.8em 0}
.reviews-head{display:flex;align-items:center;gap:18px}
.reviews-head .big{font-family:"Geist",system-ui,sans-serif;font-weight:700;font-size:3rem;color:var(--ink);line-height:1;letter-spacing:-.03em}
.reviews-head .stars{color:var(--cobalt);font-size:1.1rem;letter-spacing:2px}

/* ---------- honest guide ---------- */
.honest-guide{background:var(--neutral);border-radius:var(--r-lg);padding:32px 30px;margin:2.4em 0}
.honest-guide h2{margin-top:0}
.honest-guide .lead{font-size:1.1rem;color:var(--ink)}
.honest-guide h3{margin-top:1.5em}
.guide-fig{margin:1.5em 0}
.guide-fig img{width:100%;max-height:340px;object-fit:cover;border-radius:var(--r-md)}
.guide-fig figcaption{font-size:.84rem;color:var(--sage);margin-top:.5em;font-style:italic}

/* ---------- FAQ ---------- */
.faq{margin:1em 0}
.faq details{border-bottom:1px solid var(--line);padding:4px 0}
.faq summary{cursor:pointer;font-weight:600;padding:14px 30px 14px 0;position:relative;list-style:none}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{content:"+";position:absolute;right:4px;top:12px;color:var(--cobalt-ink);font-weight:700;font-size:1.3rem}
.faq details[open] summary::after{content:"\2212"}
.faq-body{padding:0 0 12px}
.faq-body p{margin:0}
.faq-contact{margin:1.1em 0 .2em;font-weight:600;color:var(--ink)}
.faq-contact a{color:var(--cobalt-ink)}

/* ---------- disclosure ---------- */
.disclosure{font-size:.84rem;color:var(--sage);background:var(--neutral);border-radius:var(--r-md);padding:13px 16px;margin:1em 0 1.6em}
.disclosure a{color:var(--cobalt-ink)}

/* related strip */
.related{border-top:2px solid var(--ink);margin-top:2.4em;padding-top:1.2em}

/* sitemap */
.sitemap-list{list-style:none;padding-left:0}
.sitemap-list li{margin:.4em 0;padding-left:1.2em;position:relative}
.sitemap-list li::before{content:"\2192";position:absolute;left:0;color:var(--cobalt-ink)}

/* ---------- footer ---------- */
.site-foot{background:var(--ink);color:var(--neutral);margin-top:40px;border-top:4px solid var(--cobalt)}
.site-foot .wrap{padding:48px 22px 30px}
.foot-grid{display:grid;grid-template-columns:1.7fr 1fr 1fr 1.4fr;gap:32px}
.site-foot .brand .logo{color:#fff;margin-bottom:.6em}
.site-foot .brand p{font-size:.9rem;max-width:34em}
.site-foot h4{color:#fff;margin-bottom:.8em}
.site-foot ul{list-style:none;margin:0;padding:0}
.site-foot li{margin:.4em 0}
.site-foot a{color:var(--neutral);font-size:.92rem}
.site-foot a:hover{color:#fff}
.foot-guides{margin-top:30px;border-top:1px solid #232A33;padding-top:20px}
.foot-guides ul{display:flex;flex-wrap:wrap;gap:8px 26px}
.foot-answers{margin-top:26px;border-top:1px solid #232A33;padding-top:20px;display:flex;flex-wrap:wrap;align-items:baseline;gap:10px 18px}
.foot-answers .label{font-family:"Geist",system-ui,sans-serif;font-weight:600;font-size:.62rem;letter-spacing:.1em;text-transform:uppercase;color:#8d918c}
.foot-answers nav{display:flex;flex-wrap:wrap;gap:8px 18px}
.foot-answers a{color:var(--neutral);font-size:.86rem}
.foot-answers a:hover{color:#fff}
.foot-facts{display:grid;grid-template-columns:repeat(6,1fr);gap:14px;margin-top:22px;border-top:1px solid #232A33;padding-top:22px}
.foot-facts .kf-label,.foot-facts .label{display:block;font-family:"Geist",system-ui,sans-serif;font-weight:600;font-size:.62rem;letter-spacing:.1em;text-transform:uppercase;color:#8d918c;margin-bottom:3px}
.foot-facts b{color:#fff;font-size:.92rem}
.foot-searches{margin-top:22px;border-top:1px solid #232A33;padding-top:20px}
.foot-searches h4{font-family:"Geist",system-ui,sans-serif;font-weight:600;font-size:.62rem;letter-spacing:.1em;text-transform:uppercase;color:#8d918c;margin:0 0 12px}
.foot-searches ul{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:8px}
.foot-searches li{margin:0}
.foot-searches a{display:inline-block;padding:5px 11px;border:1px solid #232A33;border-radius:999px;font-size:.78rem;color:#9fa39d;line-height:1.3;transition:color .15s,border-color .15s,background .15s}
.foot-searches a:hover{color:#fff;border-color:var(--cobalt);background:rgba(255,255,255,.05)}
.foot-bottom{margin-top:28px;border-top:1px solid #232A33;padding-top:18px;font-family:"Geist",system-ui,sans-serif;font-size:.74rem;color:#8d918c}
.foot-bottom a{color:var(--neutral)}
@media(max-width:860px){.foot-grid{grid-template-columns:1fr 1fr}}
@media(max-width:760px){.foot-grid{grid-template-columns:1fr}.foot-facts{grid-template-columns:repeat(2,1fr)}}

/* ---------- homepage: "what's included" two-column ---------- */
.includes{margin:2.2em 0;background:var(--surface);border:2px solid var(--line);border-radius:var(--r-lg);padding:26px 26px 22px}
.includes h2{margin:0 0 .25em}
.includes-lead{color:var(--sage);margin:0 0 1.2em;font-size:1rem}
.includes-grid{display:grid;grid-template-columns:1fr 1fr;gap:30px}
.includes-col h3{font-family:"Geist",system-ui,sans-serif;font-weight:700;font-size:1.12rem;color:var(--ink);margin:0 0 .55em;padding-bottom:.4em;border-bottom:2px solid var(--cobalt);display:inline-block}
.includes-col ul.check{margin:0}
.includes-col .muted{color:var(--sage);font-style:italic}
@media(max-width:680px){.includes{padding:20px}.includes-grid{grid-template-columns:1fr;gap:18px}}

/* ---------- homepage: route / "what you see, in order" (AEO) ---------- */
.route{margin:2.4em 0}
.route h2{margin:0 0 .25em}
.route-lead{color:var(--sage);margin:0 0 1.1em;font-size:1rem}
.route-stops{list-style:none;margin:1.4em 0;padding:0;counter-reset:stop}
.route-stops li{counter-increment:stop;position:relative;padding:0 0 1.1em 3.2em;margin:0}
.route-stops li:before{content:counter(stop);position:absolute;left:0;top:0;width:2rem;height:2rem;display:flex;align-items:center;justify-content:center;background:var(--cobalt);color:#fff;font-family:"Geist",system-ui,sans-serif;font-size:.85rem;font-weight:600;border-radius:var(--r-sm)}
.route-stops li:not(:last-child):after{content:"";position:absolute;left:.95rem;top:2rem;bottom:.2em;width:2px;background:var(--line)}
.route-stops li strong{color:var(--ink)}

/* ---------- homepage: wide photo gallery (breaks out of prose) ---------- */
.photo-wide{position:relative;left:50%;transform:translateX(-50%);width:min(1180px,94vw);margin:2.6em 0}
.photo-wide-head{text-align:center;max-width:44em;margin:0 auto 1.2em}
.photo-wide-head h2{margin:.15em 0 .3em}
.photo-wide-sub{color:var(--sage);margin:0}
.photo-strip{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}
.photo-strip .shot{margin:0;border-radius:var(--r-md);overflow:hidden;background:var(--neutral)}
.photo-strip .shot img{width:100%;aspect-ratio:4/3;object-fit:cover;transition:transform .4s ease}
.photo-strip .shot:hover img{transform:scale(1.06)}
@media(max-width:760px){.photo-strip{grid-template-columns:repeat(2,1fr)}}
@media(max-width:480px){.photo-strip{grid-template-columns:1fr}}

/* ---------- homepage: guest testimonials (breaks out of prose) ---------- */
.testimonials{position:relative;left:50%;transform:translateX(-50%);width:min(1180px,94vw);margin:2.8em 0 2.2em}
.testimonials h2{text-align:center;margin:0 0 .25em}
.t-lead{text-align:center;color:var(--sage);margin:0 0 1.4em}
.t-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:16px}
.t-card{margin:0;background:var(--white);border:2px solid var(--line);border-radius:var(--r-lg);padding:20px 20px 16px;display:flex;flex-direction:column}
.t-stars{color:var(--cobalt);letter-spacing:2px;font-size:.92rem;margin-bottom:.5em}
.t-card blockquote{margin:0 0 1em;font-size:.96rem;line-height:1.55;color:var(--ink)}
.t-card figcaption{margin-top:auto;border-top:1px solid var(--line);padding-top:.7em}
.t-name{display:block;font-family:"Geist",system-ui,sans-serif;font-weight:700;font-size:.86rem;color:var(--ink)}
.t-tour{display:block;font-family:"Geist",system-ui,sans-serif;font-size:.74rem;color:var(--sage);margin-top:2px}
.t-foot{text-align:center;color:var(--sage);font-size:.9rem;margin:1.4em 0 0}
@media(max-width:860px){.t-grid{grid-template-columns:1fr 1fr}}
@media(max-width:560px){.t-grid{grid-template-columns:1fr}}
/* ===== CTR features (opt-in; render only when the site defines them) =====
   _ladder / _town_chips / _book_bar in build_home.py + fee/perday in helpers.
   First shipped on yellowstonetourpackages.com. Recolor per site theme. */
/* entry-fee badge on card thumbs (tour dict: "fee_inc" / "fee_badge") */
.fee-badge{position:absolute;left:10px;bottom:10px;background:var(--ink);color:#fff;
  font-size:.72rem;font-weight:700;letter-spacing:.02em;padding:4px 9px;border-radius:4px}
/* price-per-day subtext (tour dict: "perday") */
.perday{font-size:.8rem;color:var(--sage);margin:-4px 0 10px}
/* duration/decision ladder band (homecontent: LADDER) */
.ladder-band{background:var(--ink);color:var(--neutral);padding:34px 0 40px}
.ladder-band h2{color:var(--neutral);font-size:1.45rem;margin:0 0 18px}
.ladder{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}
.ladder-col{background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.22);
  border-radius:10px;padding:20px 18px;display:flex;flex-direction:column}
.ladder-col.feat{background:var(--surface);color:var(--ink);border-color:var(--surface)}
.ladder-col.feat p{color:var(--ink)}
.ladder-days{font-weight:700;font-size:1.05rem;letter-spacing:.03em;text-transform:uppercase}
.ladder-price{color:var(--cobalt);font-weight:700;font-size:1.3rem;margin:4px 0 8px}
.ladder-col.feat .ladder-price{color:var(--cobalt-ink)}
.ladder-col p{font-size:.9rem;line-height:1.5;margin:0 0 16px;color:rgba(255,255,255,.85);flex:1}
.ladder-col .btn{align-self:flex-start}
.ladder-col .btn.ghost{background:transparent;border:1.5px solid rgba(255,255,255,.5);color:var(--neutral)}
.ladder-col .btn.ghost:hover{border-color:var(--cobalt);color:var(--cobalt)}
@media(max-width:760px){.ladder{grid-template-columns:1fr}}
/* departure-town chips (auto when 2+ tours carry "town") */
.town-chips{display:flex;align-items:center;flex-wrap:wrap;gap:8px;margin:6px 0 18px}
.chips-label{font-size:.85rem;color:var(--sage);font-weight:600}
.town-chips .chip{background:var(--neutral);border:1px solid var(--line);border-radius:999px;
  padding:6px 14px;font:inherit;font-size:.85rem;cursor:pointer;color:var(--ink)}
.town-chips .chip.on{background:var(--ink);color:var(--neutral);border-color:var(--ink)}
.town-chips .chip:hover{border-color:var(--cobalt)}
/* sticky mobile book-bar (homecontent: BOOK_BAR) */
.book-bar{display:none}
@media(max-width:760px){
  .book-bar{display:flex;position:fixed;left:0;right:0;bottom:0;z-index:60;
    background:var(--ink);color:var(--neutral);align-items:center;justify-content:space-between;
    gap:10px;padding:10px 14px;box-shadow:0 -3px 12px rgba(0,0,0,.25)}
  .book-bar span{font-size:.85rem;font-weight:600}
  .book-bar .btn{padding:9px 16px;font-size:.85rem}
  body{padding-bottom:58px}
}

/* ==================================================================== */
/* Conversion + EEAT layer (piloted on okavangodeltasafaritours.com)    */

/* cancel-note under availability widgets (conversion layer) */
.cancel-note{margin-top:10px;padding-top:10px;border-top:1px solid var(--line);font-size:.82rem;color:var(--sage)}

/* anchored-price band (opt-in via homecontent PRICE_ANCHOR) */
.price-anchor{margin:34px 0;padding:26px 26px 28px;background:var(--surface);
  border:1px solid var(--line);border-radius:14px}
.price-anchor h2{margin:0 0 18px;font-size:1.25rem}
.pa-row{display:grid;grid-template-columns:1fr auto 1fr;gap:18px;align-items:stretch}
.pa-col{display:flex;flex-direction:column;gap:6px;padding:18px;border-radius:10px}
.pa-was{background:var(--neutral);border:1px dashed var(--line)}
.pa-now{background:var(--ink);color:#fff;border:1px solid var(--ink)}
.pa-label{font-size:.78rem;text-transform:uppercase;letter-spacing:.06em;opacity:.75;font-weight:700}
.pa-price{font-size:2rem;font-weight:700;line-height:1.1}
.pa-was .pa-price{color:var(--sage)}
.pa-now .pa-price{color:#fff}
.pa-note{font-size:.85rem;line-height:1.45;opacity:.85}
.pa-vs{align-self:center;font-weight:700;color:var(--sage);font-size:.9rem;
  text-transform:uppercase;letter-spacing:.08em}
.pa-now .btn{margin-top:12px;align-self:flex-start;background:var(--accent);border-color:var(--accent)}
@media(max-width:720px){.pa-row{grid-template-columns:1fr}.pa-vs{justify-self:center;padding:2px 0}}

/* real-photo trust strip (opt-in via homecontent REAL_STRIP; Wikimedia Commons, credited) */
.real-strip{margin:38px 0}
.real-strip>h2{text-align:center}
.real-strip>p{color:var(--sage);margin-top:4px;text-align:center;max-width:820px;margin-left:auto;margin-right:auto}
.real-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;margin-top:18px}
.real-grid figure{margin:0}
.real-grid img{width:100%;aspect-ratio:3/2;height:auto;object-fit:cover;border-radius:10px;display:block}
.real-grid figcaption{font-size:.76rem;color:var(--sage);margin-top:6px;line-height:1.4}
.real-grid figcaption a{color:inherit;text-decoration:underline;text-underline-offset:2px}
@media(max-width:720px){.real-grid{grid-template-columns:1fr}}
/* breakout: same width as the testimonials band */
.real-strip.breakout{position:relative;left:50%;transform:translateX(-50%);width:min(1180px,94vw)}
.real-zoom{display:block;cursor:zoom-in}
.real-zoom img{transition:transform .18s ease}
.real-zoom:hover img{transform:scale(1.015)}
/* lightbox overlay for full-size photos */
.lightbox{position:fixed;inset:0;z-index:80;background:rgba(15,20,25,.92);
  display:flex;align-items:center;justify-content:center;cursor:zoom-out;padding:24px}
.lightbox[hidden]{display:none}
.lightbox figure{margin:0;max-width:min(1500px,96vw);text-align:center}
.lightbox img{max-width:100%;max-height:84vh;border-radius:8px;display:block;margin:0 auto}
.lightbox figcaption{color:var(--neutral);font-size:.82rem;margin-top:10px;line-height:1.4}
.lightbox figcaption a{color:inherit;text-decoration:underline;text-underline-offset:2px}

/* author card (EEAT, about page — driven by cfg.AUTHOR) */
.author-card{display:flex;gap:18px;align-items:center;margin:18px 0 24px;padding:16px;
  background:var(--surface);border:1px solid var(--line);border-radius:12px}
.author-card img{width:96px;height:96px;border-radius:50%;object-fit:cover;flex-shrink:0}
.author-card div{display:flex;flex-direction:column;gap:3px}
.author-card b{font-size:1.05rem}
.author-card span{font-size:.85rem;color:var(--sage)}

/* ============================================================================
   GLASSLINE — correction and enhancement layer
   ============================================================================
   Everything above is the generic "Running Kilometer" system with this site's
   hex values substituted in. Substitution is not design, and it is not
   accessibility either: the recolour swaps a handful of values and leaves
   behind every rule that was only ever correct for the ORIGINAL palette.

   Every contrast figure below is measured (WCAG 2.1, sRGB relative luminance).
   Text floor 4.5:1; large-text and UI-boundary floor 3:1.

   THIS PALETTE NEEDED LESS CORRECTION THAN ANY PREVIOUS ONE, AND THAT IS WORTH
   RECORDING AS PLAINLY AS A FAILURE WOULD BE. The habit is measuring, not
   correcting. design.md's button-primary — on-primary #FFFFFF on tertiary
   #2C5EF5 — measures 5.22:1 and ships exactly as published. So does the accent
   used as link text (4.69:1 on the neutral page), and so does the published
   secondary #4A5568 as caption and metadata text (6.77:1). Three specs that had
   to be overridden on the last two sites are honoured verbatim here.

   ONE TONE STILL HAD TO BE ADDED, and it is the same one that caught the last
   build: an accent has more than one value, and the missing value is always the
   accent as TEXT INSIDE A DARK BAND.

     --cobalt       #2C5EF5  FILL on light, and TEXT on light. White on it
                             5.22:1; the fill clears 4.69:1 against the page, so
                             a button edge does not depend on a border.
     --cobalt-ink   #2C5EF5  deliberately the SAME VALUE. On the last two sites
                             this had to be a deepened variant because the
                             published accent was unreadable as text. Here it is
                             not, and inventing a second tone to look thorough
                             would be worse than leaving it alone.
     --cobalt-dk    #2452D8  hover fill. White on it 6.42:1.
     --cobalt-lt    #6E97FF  TEXT inside a DARK band. 6.64:1 on --ink, where
                             --cobalt would be 3.55:1. It reads 2.79:1 on white,
                             so every rule using it below is scoped to a dark
                             surface and the pairing is not reachable by
                             accident. Reading the surface off the RENDERED
                             ELEMENT rather than the class name is what makes
                             this token necessary at all.
   ========================================================================= */

:root{
  /* `--accent` is referenced by the scaffold (.ia-takeaways, .pa-now .btn) and
     was never defined, so those declarations resolved to nothing. Aliased
     rather than hunted down, so any stray reference lands somewhere real. */
  --accent:#2C5EF5;
  --accent-ink:#2C5EF5;
}

/* --- 1. CONTRAST FAULTS INHERITED FROM THE RECOLOUR --------------------- */

/* .btn shipped `color:#fff`, and here that IS the brief: design.md's
   on-primary token is #FFFFFF and it measures 5.22:1 on the cobalt fill. The
   declaration is restated anyway so the button's foreground and background are
   owned in one place — the previous site rendered its most important number
   ink-on-ink at 1.00:1 precisely because a colour was overridden somewhere its
   background was not. */
.btn,.nav a.btn,.nav a.btn:hover,.btn:hover{color:var(--surface)}
.btn:hover{background:var(--cobalt-dk);border-color:var(--cobalt-dk)}
.btn-ghost{background:transparent;color:var(--ink);border:2px solid var(--ink)}
.btn-ghost:hover{background:var(--ink);color:var(--surface)}

/* Accent used as TEXT inside the dark bands. Measured on --ink: 6.64:1. */
.ia-takeaways li::before,
.ia-takeaways a,
.ladder-price,
.section-nav a:hover{color:var(--cobalt-lt)}
.ia-takeaways a{filter:none}
.ia-takeaways a:hover{color:var(--surface)}
.section-nav a:hover{background:var(--cobalt);color:var(--surface)}

/* Star glyphs carry a rating, which makes them TEXT — they are the only thing
   distinguishing 5 stars from 3 — so they take the accent's text tone. On this
   palette that is the same hex as the fill, and it still gets stated, because
   the next site's palette may split them again. */
.star,.rev-stars,.t-stars,.facts-val .star{color:var(--cobalt-ink)}

/* Chips and badges kept `color:#fff`, which is the brief's on-primary. */
.badge,.book-chip,.cmp-badge{color:var(--surface)}

/* .pa-now is a DARK CHIP in the scaffold and a large figure in the layer
   below. OWN THE PAIR: a foreground and its background are one decision, and
   overriding only the colour inherits the other. */
.price-anchor .pa-was{background:transparent;border:0;color:var(--sage)}
.price-anchor .pa-now{background:transparent;border:0;color:var(--ink)}
.price-anchor .pa-now .pa-price{color:var(--ink)}
.price-anchor .pa-was .pa-price{color:var(--sage)}
.pa-now .btn{background:var(--cobalt);border-color:var(--cobalt);color:var(--surface)}
/* opacity is a contrast change that does not look like one: a checker reading
   `color` alone sees the undimmed value and passes it. Two elements on a
   previous site failed purely this way. */
.price-anchor .pa-note,.pa-label{opacity:1;color:var(--sage)}

/* --- 2. THE DESIGN BRIEF, ACTUALLY APPLIED ------------------------------ */

/* Glassline is a ONE-FAMILY system with a monospace for labels only, which is
   the opposite of the last site's serif/sans pairing. Geist carries display,
   headings and body; Geist Mono carries the small uppercase labels. Both were
   confirmed to exist on Google Fonts before being requested — see the note in
   siteconfig.FONTS_LATIN. */
h1,h2,h3,.display,.hero h1,.logo{font-family:"Geist",system-ui,sans-serif}

/* THE BRIEF'S TYPE SCALE, AND THE ONE PLACE IT IS SCALED RATHER THAN COPIED.
   design.md gives display 3.75rem, h1 2.25rem, body 0.95rem, label 0.75rem.
   Those rem values assume a 16px root, at which body would render 15.2px —
   below the point where long-form travel prose stays comfortable, and this site
   is long-form. The root is therefore set to 17px, which keeps every RATIO in
   the brief exactly as published while landing body at 16.15px. Nothing in the
   scale is re-proportioned; the whole thing is multiplied by one number, and
   that number is stated here rather than buried. */
html{font-size:17px}
body{font-size:.95rem;line-height:1.55;background:var(--neutral)}
h1,.hero h1{font-size:2.25rem;font-weight:600;letter-spacing:-.02em;line-height:1.12}
.display{font-size:3.75rem;font-weight:600;letter-spacing:-.03em;line-height:1.04}
h2{font-size:1.6rem;font-weight:600;letter-spacing:-.02em}
h3{font-size:1.15rem;font-weight:600;letter-spacing:-.01em}
.logo{font-weight:600;letter-spacing:-.02em}

/* The brief's `label` face is Geist Mono at 0.75rem with letterSpacing 0. Mono
   at zero tracking in uppercase sets tight, so a hair of tracking is added —
   that is a legibility correction, not a redesign, and it is the only deviation
   from the label spec. */
h4,.label,.btn,.book-chip,.badge,.eyebrow,.nav a.btn{
  font-family:"Geist Mono","Geist",ui-monospace,SFMono-Regular,Menlo,monospace;
  font-weight:500;font-size:.75rem;letter-spacing:.06em;text-transform:uppercase;
}
.label,.eyebrow{color:var(--cobalt-ink)}
h4{color:var(--sage)}

/* design.md radii: 6 / 10 / 16 — already set in :root at the top of the file.
   Restated as a comment only, so a reader looking for them here finds them. */
.site-head{background:var(--surface);border-bottom:1px solid var(--line)}

/* --- 3. HEADER FIT ------------------------------------------------------
   Row-grouping by vertical centre proves ARRANGEMENT, not SIZE: a CTA that
   grows from 38px to 75px by wrapping keeps the same centre, so that check
   stays green while a button bleeds over the hero. These rules stop the wrap;
   the QA counts real line boxes to prove it.

   The hamburger breakpoint on this engine is 860px, NOT 1000px. A previous
   site tightened the 1001-1240 band and missed the real crush zone, which is
   the ~200px just above the collapse. */
.nav a.btn{white-space:nowrap;font-size:.72rem;letter-spacing:.06em;padding:9px 14px;line-height:1.15}
@media(min-width:861px){.nav a{white-space:nowrap}}
@media(min-width:861px) and (max-width:1100px){
  .nav{gap:12px}
  .nav a{font-size:.8rem;letter-spacing:0}
  .nav a.btn{padding:8px 10px;font-size:.68rem;letter-spacing:.04em}
}
@media(min-width:1101px) and (max-width:1260px){
  .nav{gap:16px}
  .nav a{font-size:.85rem}
  .nav a.btn{padding:9px 12px;font-size:.7rem}
}

/* --- 4. BREAKOUTS THAT CANNOT DRIFT ------------------------------------
   The scaffold escapes the text column with
       position:relative; left:50%; transform:translateX(-50%)
   which is a PHYSICAL-AXIS construction. On the previous site's Arabic tree it
   centred 420px off and dragged three whole sections off the page. This site
   is English-only so it would not misfire today - but the same construction
   also breaks whenever the parent is not the width it assumes, and equal
   negative margins are simpler, cheaper (no positioned element, no transform)
   and correct in every direction. Fixed here so the pattern never ships again.

   Grep for the CONSTRUCTION, not the symptom: it appears three times. */
.photo-wide,
.testimonials,
.real-strip.breakout{
  position:static; left:auto; transform:none;
  width:min(1180px,94vw);
  margin-left:calc((100% - min(1180px,94vw)) / 2);
  margin-right:calc((100% - min(1180px,94vw)) / 2);
}
.photo-wide{margin-top:2.6em;margin-bottom:2.6em}
.testimonials{margin-top:2.8em;margin-bottom:2.2em}

/* A breakout has a MINIMUM VIEWPORT, and it is arithmetic, not taste. The
   comparison table escapes by 110px a side; the column is 1120px plus 22px
   padding, so it needs 1120+220 = 1340px to land inside the window. Between
   1080 and 1339 it pushed the DOCUMENT sideways instead. */
@media(min-width:1080px) and (max-width:1339px){
  .cmp-wrap{margin-left:0;margin-right:0}
}

/* --- 5. UX AND CONVERSION ---------------------------------------------- */

/* Keyboard focus. The scaffold has none anywhere, which makes the whole site
   unusable by keyboard. */
a:focus-visible,button:focus-visible,.btn:focus-visible{
  outline:3px solid var(--ink);outline-offset:2px;border-radius:var(--r-sm);
}
.hero a:focus-visible,.ladder-col a:focus-visible,.ia-takeaways a:focus-visible{
  outline-color:var(--cobalt-lt);
}

/* .skip is defined in section (g) at the end of this file - the -9999px
   version that used to sit here is gone, not shadowed. */

/* Tap targets. 44px is the floor. */
@media(max-width:860px){
  .nav a{min-height:44px;display:flex;align-items:center}
  .btn{min-height:46px;display:inline-flex;align-items:center;justify-content:center}
}

/* The free-entry callout. This site's whole argument is that the thing costs
   nothing, so the "price" element is a statement rather than a figure. */
.price-anchor{border:1px solid var(--line);border-radius:var(--r-lg);background:var(--surface);
  padding:24px;margin:1.8em 0}
.price-anchor .pa-was{text-decoration:line-through;font-size:.95rem}
.price-anchor .pa-now{font-family:"Geist",system-ui,sans-serif;font-size:2.4rem;line-height:1.05;
  margin:.15em 0 .3em}
.price-anchor .pa-note{font-size:.9rem;line-height:1.45;margin:0}

.fact-strip{display:grid;grid-template-columns:repeat(3,1fr);border:1px solid var(--line);
  border-radius:var(--r-lg);overflow:hidden;margin:1.8em 0;background:var(--surface)}
.fact-strip > div{padding:18px 20px;border-right:1px solid var(--line)}
.fact-strip > div:last-child{border-right:0}
.fact-strip dt{font-family:"Geist",system-ui,sans-serif;font-weight:700;letter-spacing:.1em;
  font-size:.72rem;text-transform:uppercase;color:var(--sage);margin:0 0 4px}
.fact-strip dd{margin:0;font-family:"Geist",system-ui,sans-serif;font-size:1.55rem;line-height:1.15}
@media(max-width:640px){
  .fact-strip{grid-template-columns:1fr}
  .fact-strip > div{border-right:0;border-bottom:1px solid var(--line)}
  .fact-strip > div:last-child{border-bottom:0}
}

.callout{border:1px solid var(--line);border-inline-start:4px solid var(--cobalt);
  background:var(--surface);padding:18px 22px;margin:1.6em 0;border-radius:var(--r-md)}
.callout > :last-child{margin-bottom:0}
.callout .callout-h{font-family:"Geist",system-ui,sans-serif;font-weight:700;letter-spacing:.1em;
  text-transform:uppercase;font-size:.75rem;color:var(--cobalt-ink);margin:0 0 .5em}

/* The baseball disambiguator. Deliberately quiet - it is a signpost for people
   who took a wrong turn, not a feature of this site. */
.wrongturn{border:1px dashed var(--sage);background:transparent;border-radius:var(--r-md);
  padding:14px 18px;margin:1.4em 0;font-size:.95rem;color:var(--sage)}
.wrongturn b{color:var(--ink)}
.wrongturn a{color:var(--cobalt-ink)}

/* Prose tables must not push the document sideways on a phone. */
@media(max-width:700px){
  .prose table,table.facts,table.prices{display:block;overflow-x:auto;-webkit-overflow-scrolling:touch}
}

.hero .wrap{padding-top:56px;padding-bottom:52px}
@media(min-width:861px){.hero .wrap{min-height:0}}

@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;transition-duration:.001ms!important}
}

/* ============================================================================
   10. TYPOGRAPHY, HERO CONTRAST, AND THE TOUR GRID
   ============================================================================
   Three reported problems, all real, and the first one exposes a hole in this
   project's own QA that is worth writing down.
   ========================================================================= */

/* --- (a) THE HERO. A CONTRAST CHECKER THAT READS COLOURS IS BLIND TO IMAGES.
   This is the lesson the last site shipped a failure on, and it is repeated in
   full because it is the one an automated sweep will never catch for you.

   The colour-based sweep walks up the DOM looking for an opaque background
   COLOR, finds --ink on .hero, computes a comfortable ratio against it, and
   never once looks at the photograph painted on top. On the previous site that
   passed an eyebrow the user could not read. Measured against the actual
   pixels there:

     average pixel behind the eyebrow, through a .44 scrim ..........  7.23:1
     BRIGHTEST pixel behind it .......................................  2.09:1

   The average passes and nobody reads the average. They read the line where it
   crosses the bright part of the picture.

   THE VALUE BELOW IS PROVISIONAL AND MUST BE RE-MEASURED. The hero photograph
   for this site is generated by the step-1 kit and does not exist while this
   file is being written, so the scrim starts at a defensible .62 and the
   image-aware check in qa_battery.py - hide the text, screenshot the
   background, take the 99th-percentile luminance inside each text box - sets
   the final number. Shipping without running that check is how the last one
   got out. This hero is also a brighter photograph than the last one: open sky
   over water, which is the worst case for a light-text overlay.

   The scrim is a cool near-black taken from --ink rather than the warm brown
   the previous site used, and the ::after gradient stays removed: design.md
   says "Don't introduce gradients. This system is flat on purpose", and one
   flat scrim does the whole job.

   The eyebrow is --surface white, not a tinted variant. Its hierarchy is
   carried by size, tracking and case - which is exactly what a monospace label
   face is for - rather than by a second hue the brief does not allow. */
.hero .label{color:var(--surface);opacity:1}
.hero h1{color:#fff}
.hero .lede{color:var(--neutral)}
.hero-trust{color:var(--neutral)}
.hero-trust b{color:#fff}
.gallery figcaption{background:rgba(15,20,25,.82)}
.lightbox{background:rgba(15,20,25,.92)}

/* --- (b) BOLD TEXT LEGIBILITY -------------------------------------------
   `-webkit-font-smoothing:antialiased` was forced on <body>. It overrides
   subpixel rendering and makes every glyph THINNER - which is why it is a
   common trick for light-on-dark, and why it backfires for dark-on-light. On
   this warm cream ground it thins exactly the strokes that make bold read as
   bold, so <b> and <strong> lose their weight against the body copy while
   measuring a perfectly healthy 13.46:1. It is a legibility problem that
   contrast numbers cannot see. Handing rendering back to the browser fixes it.

   Bold is then given a little real authority instead: the full 700 face, and
   the tracking eased back so the heavier glyphs are not crowded. */
body{-webkit-font-smoothing:auto;-moz-osx-font-smoothing:auto}
/* SETTING A COLOUR HERE WAS A MISTAKE AND IT SHIPPED A 1.00:1 REGRESSION.
   The first version of this rule also set `color:var(--ink)`. `li b` is
   (0,0,0,2) and `.ia-takeaways b` is (0,0,1,1), so a class should have won -
   but the takeaway bullets are `.ia-takeaways ul li b`, and the scaffold's
   dark-band rule targets `.ia-takeaways b` only through a shorter path than I
   assumed. Six bullets on the homepage rendered ink-on-ink: invisible.

   The colour never needed changing. Bold text was already measuring 13.46:1
   on the light surfaces and 16.30:1 in the dark bands; the complaint was about
   WEIGHT rendering, not colour. So this rule now touches only what it was
   meant to - weight and tracking - and every surface keeps the colour it
   already had.

   The lesson is the one this project keeps relearning: a rule that sets a
   foreground without stating its background will eventually meet a background
   it did not expect. If you are not also setting the background, do not set
   the foreground. */
.prose b,.prose strong,p b,p strong,li b,li strong,td b,td strong{
  font-weight:700;letter-spacing:.002em;
}

/* --- (c) COLOURS LEFT OVER FROM A PREVIOUS PALETTE -----------------------
   Nine hard-coded hex values travelled here inside the stylesheet from the
   sites it was forked from - four cool greys, a peach, a green - plus the warm
   browns the LAST site introduced to replace those cool greys. Both generations
   of leftover are wrong here, in mirror image: the tan #CBB79E and brown
   #4A3826 were right on baked clay and read as grubby on fog-grey, exactly as
   the cool greys read as dirty on clay.

   The lesson is not "cool greys are bad". It is that a recolour which swaps the
   :root tokens and stops there leaves every hard-coded value behind, and those
   values are invisible in review because nothing about them looks broken. Grep
   the stylesheet for hex literals after every retheme; the palette is whatever
   the file actually contains, not whatever :root claims.

   AND THIS TIME THEY ARE FIXED AT SOURCE RATHER THAN OVERRIDDEN. The previous
   site left the alien values in their original rules and shadowed them with a
   second set of declarations down here. That works only while the cascade order
   holds - one reordered file, one extra-specific selector, and a peach comes
   back. Every value below was edited in the rule that declares it, so the
   stylesheet now literally contains no colour outside the palette. This block
   is a RECORD of what changed and what it measures, and deliberately declares
   nothing:

     footer body text  #C9CCC7 / #CBB79E -> --neutral #F1F3F5   16.64:1
     hero lede         #ECEDEA           -> --neutral #F1F3F5   16.64:1
     trust + sc-rev    #D9DBD7           -> --neutral #F1F3F5   16.64:1
     hero eyebrow      #FFC9B0 (a PEACH) -> --surface  (see (a))
     muted labels      #8D918C / #CBB79E -> #A7B0BC              8.44:1
     search chips      #9FA39D / #CBB79E -> #A7B0BC              8.44:1
     hairlines         #2C2F2F / #4A3826 -> #232A33     1.28:1, decorative
     lightbox caption  #E8E5DA           -> --neutral
     fee badge         #2E5D3A (a GREEN) -> --ink   single-accent rule
     scrims        rgba(21,24,24,*)/(20,26,18,*) -> rgba(15,20,25,*) from --ink

   The green earns its own line. It is not a tint of anything in this system or
   the last one - it arrived from a site about a national park and survived two
   rethemes because nothing that renders it appears above the fold.

   The one thing that IS declared here is the hover state for the footer search
   chips, because the base rule never had one and a chip that is a link should
   say so. --cobalt-lt is the dark-band accent tone from the header comment. */
.foot-searches a:hover{border-color:var(--cobalt-lt);color:var(--cobalt-lt)}
.hero .label,.label{letter-spacing:.06em}

/* --- (d) THE TOUR GRID: FIVE TOURS, NO PADDING TILE ----------------------
   There are five tours. A 3-across CSS grid left one empty cell, and the
   scaffold filled it with a dashed decorative tile - an SVG of hills with the
   city name under it. In the sixth slot of a 3x2 grid a reader expects a sixth
   tour; what they got was an ornamental box that advertised nothing and linked
   nowhere, and mostly read as a card that had failed to load. It is gone from
   helpers.py.

   Centring the short row is why the tile existed: CSS grid places orphans at
   the START of their row and gives you no way to centre them. Flexbox does, so
   the container becomes a centred flex-wrap. The basis arithmetic reproduces
   the old three-up rhythm exactly - each card is a third of the row minus its
   share of the two gaps - so full rows are identical to before and only the
   short row changes. */
.tours-grid{
  display:flex;flex-wrap:wrap;justify-content:center;align-items:stretch;
  gap:20px;margin:1.5em 0 .4em;
}
.tours-grid > *{flex:0 1 calc((100% - 40px) / 3);max-width:calc((100% - 40px) / 3)}
.tours-grid.cols-4{gap:16px}
.tours-grid.cols-4 > *{flex:0 1 calc((100% - 48px) / 4);max-width:calc((100% - 48px) / 4)}
@media(max-width:1024px){
  .tours-grid.cols-4 > *{flex:0 1 calc((100% - 16px) / 2);max-width:calc((100% - 16px) / 2)}
}
@media(max-width:860px){
  .tours-grid > *{flex:0 1 calc((100% - 20px) / 2);max-width:calc((100% - 20px) / 2)}
}
@media(max-width:560px){
  .tours-grid > *,.tours-grid.cols-4 > *{flex:0 1 100%;max-width:100%}
}

/* --- (e) THE LANGUAGE SWITCHER -------------------------------------------
   Three chips, because this is the first three-language build. The count is
   emitted by build_site.langbar() from siteconfig.LANGS and asserted by
   qa_battery.lang_bar() against the same list, so there is no literal 2 or 3
   anywhere for a fourth language to invalidate.

   The bar is a SIBLING of the nav, never a child - a previous site put the
   chips inside .nav, which is display:none below the hamburger breakpoint, and
   the switcher disappeared on every phone. `order` is what keeps the layout
   sensible once that decision is made: on desktop the bar sits at the end of
   the row; on mobile it sits BEFORE the hamburger, so the tap targets do not
   swap places between breakpoints.

   Contrast, measured: chip text --sage on --surface is 7.53:1; the current
   chip is --surface on --cobalt at 5.22:1. The border is --sage rather than
   --line because a chip is a CONTROL, and --line is a 1.29:1 hairline token
   that a previous site reached for and shipped an invisible control edge with.

   Chips are deliberately small. Six nav items plus three chips is the tightest
   header this engine has carried, and the fit is proved by counting real line
   boxes in the QA battery rather than by eye. */
.lang-bar{
  display:flex;flex-wrap:nowrap;align-items:center;gap:4px;
  margin-left:auto;flex:0 0 auto;
}
.lang-chip{
  font-family:"Geist Mono","Geist",ui-monospace,SFMono-Regular,Menlo,monospace;
  font-weight:500;font-size:.64rem;letter-spacing:.06em;line-height:1;
  padding:6px 8px;border-radius:var(--r-sm);border:1px solid var(--sage);
  color:var(--sage);background:transparent;white-space:nowrap;
  transition:background .15s,color .15s,border-color .15s;
}
a.lang-chip:hover{background:var(--sage);color:var(--surface);text-decoration:none}
.lang-chip.is-current{
  background:var(--cobalt);border-color:var(--cobalt);color:var(--surface);
}
@media(max-width:860px){
  .site-head .wrap{gap:10px}
  .lang-bar{order:2;margin-left:auto}
  .nav-toggle{order:3;margin-left:0}
  .lang-chip{font-size:.6rem;padding:5px 7px}
}

/* --- (f) THE HEADER, RE-FITTED AROUND THE LANGUAGE BAR ---------------------
   Measured across widths 861 to 1301 in small steps, on every route, twice.
   The story is worth keeping because the first answer was wrong.

   FIRST MEASUREMENT. At 861px - one pixel above the engine's collapse point -
   the header carried a logo, SIX nav items and three language chips, and the
   bar ran to x=909 on an 861px viewport: 48px of horizontal document overflow
   on all 36 routes. The obvious fix was to collapse the nav earlier, so the
   breakpoint went to 980px.

   SECOND MEASUREMENT, AND THE ONE THAT MATTERED. That fixed 861 and broke 1000:
   the desktop row with a nowrap logo needed 1041px before it stopped
   overflowing. Sweeping 981 to 1301 in 20px steps showed the requirement was
   not a breakpoint problem at all - the row simply held more than it could
   carry, and moving the collapse point to 1040px would have taken the desktop
   nav away from every laptop to hide it.

   SO THE CONTENT CHANGED INSTEAD, and the item that went was the DUPLICATED
   one: a "Boat Trips" link sitting immediately beside a "See Boats" button
   pointing at the same idea. See the note in siteconfig.NAV. With five items
   the row fits from 861px with zero overflow at every width tested, so the
   engine's original 860px collapse point is restored rather than moved.

   The lesson for the next site: when a header stops fitting, measure what it
   NEEDS before deciding where it should BREAK. A breakpoint moved to hide an
   overfull row just relocates the overflow, and the second measurement is the
   only thing that shows you that.

   What did NOT catch any of this: the header-fit check, which counts CTA line
   boxes and elements escaping the header box. The chips were inside the header
   and on one line, so it passed every time. The document-overflow sweep is what
   found both. Two checks that look redundant are not - one asks "does the
   header hold together", the other asks "does the PAGE fit". */
@media(min-width:861px) and (max-width:980px){
  /* the brand is three words; between the collapse point and 980px it sets on
     two lines and the mark stays centred against them */
  .logo{white-space:normal;line-height:1.15;max-width:14ch;font-size:.98rem}
  .nav{gap:12px}
}
@media(min-width:981px){
  .logo{white-space:nowrap;font-size:1.02rem}
  .site-head .wrap{gap:14px}
}
@media(min-width:981px) and (max-width:1120px){.nav{gap:14px}}
@media(max-width:860px){
  .logo{line-height:1.15;max-width:14ch}
}

/* --- (g) THE SKIP LINK, PARKED WITHOUT MOVING THE PAGE -------------------
   `left:-9999px` is the technique this scaffold has carried since the
   beginning, and while it was not the cause of the overflow above, it showed up
   in the same measurement sitting 9,999px outside the viewport. An absolutely
   positioned element that far off-axis is one `position:static` away from
   dragging a scrollbar across the whole site, and in a right-to-left tree it
   would do it immediately.

   clip-path removes the element from painting without moving it anywhere, so
   there is no coordinate for a layout change to expose. The focused state
   restores it in place. */
.skip{
  position:absolute;left:0;top:0;z-index:100;
  background:var(--ink);color:var(--surface);
  font-family:"Geist Mono","Geist",ui-monospace,monospace;
  font-size:.75rem;letter-spacing:.06em;text-transform:uppercase;
  padding:10px 16px;border-radius:0 0 var(--r-sm) 0;
  clip-path:inset(50%);
}
.skip:focus{clip-path:none;outline:2px solid var(--cobalt);outline-offset:2px}

/* Section (h) folded into (f): the brand-name wrap and the header fit are
   one decision and were being made in two places. */

/* --- (i) THE HEADER MUST FIT IN LANGUAGES I DID NOT MEASURE ----------------
   The single-row header was fitted to ENGLISH nav labels and the translated
   trees were never measured. They do not fit. Swept in 20px steps across every
   width from 861 to 1760:

       EN   clean everywhere from 861px
       ES   overflows at most widths below ~1080, and again at 1261-1281
       FR   overflows EVERYWHERE below 1461px, by up to 158px

   "Cómo llegar / Boletos de ferry / Cuánto cuesta / ¿Excursión de un día? /
   VER BARCOS" is simply longer than "Getting There / Ferry Tickets / What It
   Costs / Day Trip? / See Boats", and French is longer still. Sizing a fixed
   row against the source language and then pouring two longer languages into
   it was never going to work, and nothing in the English QA run could have
   told me - the English tree is clean at every width.

   THE TWO OBVIOUS FIXES ARE BOTH WRONG.
   Collapsing to a hamburger at the width French needs would mean a hamburger
   below 1461px - almost every laptop - in all three languages. Per-language
   breakpoints would fix that and still leave the next language to rediscover
   the problem from scratch.

   So the row is allowed to WRAP instead. The nav sits beside the logo while it
   fits and drops to a second line when it does not, in any language, at any
   width, including ones nobody has measured. The header grows about 40px on
   those widths and nothing is ever pushed off-screen. `height` becomes
   `min-height` because a fixed height with wrapped content overflows silently -
   which is the same class of bug one line up. */
.site-head .wrap{
  flex-wrap:wrap;
  height:auto;
  min-height:66px;
  padding-top:8px;
  padding-bottom:8px;
  row-gap:4px;
}
/* The logo and the language chips hold the first row; the nav takes what is
   left and wraps beneath them when it cannot fit. */
.site-head .logo{flex:0 1 auto}
.lang-bar{flex:0 0 auto;order:3}
.nav-toggle{order:4}
@media(min-width:861px){
  .nav{order:5;flex:1 1 auto;min-width:0;justify-content:flex-end}
}

/* --- (j) LONG WORDS IN HEADINGS, WHICH ONLY EXIST IN THE TRANSLATED TREES --
   /fr/reviews/ overflowed by 56px at 360px and 2px at 414px, and nothing else
   on 108 routes x 14 widths did. The cause was one word:

       "Avis sur les excursions en bateau a Culebra : 61 citations, comptees
        plutot QU'ECHANTILLONNEES"

   Eighteen characters, set at about 31px in an h1, inside 316px of content.
   The English headline's longest word is "reviews:" and the Spanish one's is
   "muestreadas", so neither tree could have surfaced this - it is a property of
   the language, not of the layout, and it is exactly the class of defect that
   only appears once you translate.

   `overflow-wrap:break-word` is the safety net: it only breaks a word that
   cannot fit on a line by itself, so ordinary text is untouched. `hyphens:auto`
   makes that break a proper hyphenated one rather than a mid-word chop, and it
   works correctly here because every page carries a real `lang` attribute -
   the browser hyphenates French by French rules and Spanish by Spanish ones.
   That is a second, unadvertised payoff from getting `lang` right.

   Applied to headings and prose rather than globally: these are the elements
   with large type and narrow columns, which is where a long word runs out of
   room first. German would need this on considerably more than headings. */
h1,h2,h3,h4,.display,.hero h1,.logo,
.prose p,.prose li,.t-quote,.rev-quote,figcaption,.sc-row span,.kf-label{
  overflow-wrap:break-word;
  hyphens:auto;
}
/* Table cells and chips are the other narrow columns, and a chip that breaks
   is better than a row that overflows the page. */
td,th,.foot-searches a,.badge,.book-chip{overflow-wrap:break-word}


/* --- (k) THE LANGUAGE CHIPS BELONG BESIDE THE LOGO ------------------------
   Reported on the French page and true on every wrapped header: the chips were
   floating alone at the far right of row one, with the nav and the CTA on row
   two beneath them - so the switcher read as a detached fragment hovering over
   the navigation rather than as part of the brand block.

   That was a consequence of section (i) rather than a decision. Making the row
   wrap fixed the overflow, but the chips still carried `margin-left:auto` from
   when they were the LAST thing on a single row. On a wrapped row that auto
   margin does the opposite of what it used to: it strands them.

   Chips now sit immediately after the logo and own the `margin-right:auto`, so:

       one row   logo · chips ............... nav · CTA
       two rows  logo · chips ...............
                 nav · CTA

   In both cases the switcher is part of the left-hand identity block, which is
   where a reader looks for it, and the nav keeps the right edge. Below the
   hamburger breakpoint the toggle sits after the chips and is pushed right by
   the same auto margin - one rule, three layouts. */
.site-head .logo{order:0;flex:0 1 auto}
.lang-bar{order:1;flex:0 0 auto;margin-left:14px;margin-right:auto}
.nav-toggle{order:2;margin-left:0}
@media(min-width:861px){
  .nav{order:3;flex:0 1 auto;min-width:0;justify-content:flex-end;margin-left:0}
}
@media(max-width:860px){
  .nav{order:4}
  .lang-bar{margin-left:10px}
}

/* --- (l) ONE ROW ON DESKTOP, IN EVERY LANGUAGE ---------------------------
   Section (i) let the header wrap so that no language could overflow it. That
   was the right safety net and the wrong resting state: with it in place, the
   Spanish and French rows simply dropped their nav to a second line on desktop
   while English stayed on one, so the three trees did not look like one site.

   The wrap stays - a language nobody has measured still must not overflow -
   but it is now a net rather than a layout, and the row is made to FIT.

   TWO CHANGES, IN THIS ORDER, because only the first one generalises.

   1. THE LABELS. "Getting There / Ferry Tickets / What It Costs / Day Trip? /
      See Boats" is 57 characters. Spanish shipped 71 and French 82, and no
      amount of CSS absorbs 25 extra characters at the widths where the row is
      already tightest. Nav labels are chrome, not prose: they should be short
      in every language, and the English count is the budget. Spanish is now 53
      ("Cómo llegar / El ferry / Cuánto cuesta / ¿En un día? / Ver barcos") and
      French 55 ("S'y rendre / Le ferry / Le coût / À la journée ? / Voir les
      bateaux"). /tmp/nav_short.py refuses to run if either exceeds 57.

   2. THE PIXELS, and this is the part measurement changed my mind about. With
      the labels fixed, the widest nav in the site is ENGLISH (526px against
      499px for both translations) - so the last two failing widths were 861
      and 981 in the SOURCE language, not the translated ones. 861 was 18px
      short and 981 was 9px, counting the language bar's own margin, which is
      an amount worth taking out of gaps rather than out of type size.

   Measured with vertical-overlap row detection across 17 widths from 861 to
   1920 on the homepage and on the longest-nav route, in all three languages:
   one row everywhere. */
@media(min-width:861px) and (max-width:1120px){
  .site-head .wrap{gap:12px}
  .nav{gap:10px}
  .lang-bar{margin-left:10px;gap:3px}
  .lang-chip{font-size:.62rem;padding:5px 7px}
}

/* h1_retrofit v2 */
/* H1 line budget (owner rule 2026-09-07): every headline fits in TWO lines on
   every viewport, 360-1280px. --h1-scale is a per-language size step
   (0.88-1) written by h1_retrofit.py only when it keeps a headline intact
   that would otherwise have to be rewritten. No hyphens:auto: browsers
   hyphenate differently, so a headline that fits by hyphenating in one
   would be three lines in another. */
h1{font-size:calc(clamp(1.55rem,4.6vw,2rem) * var(--h1-scale,1));line-height:1.12;text-wrap:balance}
.hero h1{font-size:calc(clamp(1.75rem,3.9vw,3rem) * var(--h1-scale,1));line-height:1.1;text-wrap:balance}
@media(max-width:640px){h1{font-size:calc(1.55rem * var(--h1-scale,1))}.hero h1{font-size:calc(1.7rem * var(--h1-scale,1))}}
