/*
 * 35-pages.css — page-level compositions. ElNidoGuide-Migration.md §6.
 *
 * 30-components.css holds things reused everywhere (buttons, tags, the blueprint
 * frame). This file holds the arrangements that belong to specific pages — the
 * home hero, the tour grid, the ranked provider list — so neither file becomes a
 * dumping ground.
 *
 * Everything here composes the tokens and components already defined; no colour
 * literals, no new type sizes that are not in §2.2.
 */

/* ==========================================================================
   §6.1 Home — hero
   ========================================================================== */

.eng-hero{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(320px,1fr));
  gap:var(--space-8);
  align-items:start;
  padding:var(--space-6) var(--space-4) var(--space-8);
}

/* §2.2 — H1 hero is the one heading at line-height 1; the two-line lockup
   ("El Nido, / end to end.") depends on it closing up. */
.eng-hero__title{
  font-size:var(--type-h1-hero);
  line-height:1;
  margin:var(--space-3) 0;
}
.eng-hero__dek{ font-size:19px; line-height:1.5; max-width:52ch; }

/* §6.1 — stat row: 26px numbers over muted labels. */
.eng-stats{
  display:flex;
  flex-wrap:wrap;
  gap:var(--space-6);
  margin-top:var(--space-6);
}
.eng-stat__num{
  display:block;
  font-family:var(--font-heading);
  font-size:26px;
  font-weight:600;
  line-height:1;
}
.eng-stat__label{
  display:block;
  font-size:12px;
  color:var(--color-muted);
  margin-top:4px;
}

/* §6.1 — trip planner card. A blueprint object, so it stays transparent; the
   only filled thing inside it is the primary button. */
.eng-planner{ padding:var(--space-4); display:grid; gap:var(--space-3); }
.eng-planner__legend{ font-size:13px; color:var(--color-muted); }

/* The planner card rendered by [eng_planner_card] (2026-09-02). Same object as the home
   card; these are the parts that card does not have today: a title and one line of
   feedback (both contexts; the home page's GenerateBlocks card gets the status line from
   eng-app.js only when a build fails), plus the pace segment and the in-card "start over"
   confirm that only context="plan" renders. */
.eng-planner__title{
  font-family:var(--font-heading);
  font-size:var(--type-h3-card);
  font-weight:600;
  line-height:1.15;
  margin:0;
}
.eng-planner__pace{ display:flex; }
.eng-planner__pace .eng-btn{ flex:1 1 0; min-height:44px; border:0; border-right:1px solid var(--color-divider); }
.eng-planner__pace .eng-btn:last-child{ border-right:0; }
/* Pressed state from aria-pressed, the attribute the JS actually toggles. */
.eng-planner__pace .eng-btn[aria-pressed="true"]{ background:var(--color-accent-100); color:var(--color-accent-900); }
.eng-planner .eng-btn--block{ min-height:44px; }
.eng-planner__status{ font-size:13px; color:var(--color-muted); margin:0; min-height:1.4em; }
.eng-planner__status--error{ color:var(--color-danger); }
.eng-planner__reset{ display:grid; gap:var(--space-2); }
.eng-planner__reset .eng-btn{ min-height:44px; }
.eng-planner__confirm{ font-size:14px; margin:0; }
.eng-planner__confirm-actions{ display:flex; flex-wrap:wrap; gap:var(--space-2); }
.eng-planner__confirm-actions .eng-btn{ flex:1 1 140px; min-height:44px; }

/* The optional "how are you getting here" disclosure (2026-09-04). A <details>, so it
   needs its marker suppressed and a 44px summary the same as any other control here. */
.eng-planner__travel{ border-top:1px solid var(--color-divider); padding-top:var(--space-3); }
.eng-planner__travel-summary{
  display:flex;
  align-items:center;
  min-height:44px;
  font-family:var(--font-heading);
  font-size:15px;
  font-weight:600;
  color:var(--color-accent-800);
  cursor:pointer;
  list-style:none;
}
.eng-planner__travel-summary::-webkit-details-marker{ display:none; }
.eng-planner__travel-summary::marker{ content:""; }
.eng-planner__travel-summary::after{ content:"+"; margin-left:auto; font-size:18px; line-height:1; }
.eng-planner__travel[open] .eng-planner__travel-summary::after{ content:"–"; }
.eng-planner__travel-body{ display:grid; gap:var(--space-3); padding-top:var(--space-2); }
.eng-planner__hint{ font-size:13px; color:var(--color-muted); margin:0; }
.eng-2up{ display:grid; gap:var(--space-2); grid-template-columns:1fr 1fr; }
@media (max-width:520px){
  .eng-2up{ grid-template-columns:1fr; }
}

/* Interest chips: square checkboxes that read as tags. */
.eng-chips{ display:flex; flex-wrap:wrap; gap:var(--space-2); }
.eng-chips label{
  display:inline-flex;
  align-items:center;
  gap:8px;
  font-size:13px;
  /* These are the planner's primary input and they measured 28px tall — the smallest
     targets on the page, on the one control a phone visitor has to hit eight times.
     Padding plus the 44px floor, and the checkbox given a real size to match: a 13px
     box beside 13px text is a target you aim at rather than tap. */
  padding:8px 12px;
  min-height:44px;
  border:1px solid var(--color-divider);
  cursor:pointer;
}
.eng-chips input{ width:18px; height:18px; accent-color:var(--color-accent-700); }

/* §6.1 — Arrival / Departure / Travellers, 3-up, collapsing on narrow cards. */
.eng-3up{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  gap:var(--space-3);
}
/*
 * min-width:0 on the cells, because a grid item's automatic minimum size is its
 * MIN-CONTENT width, and `width:100%` cannot shrink it below that. A date or time input
 * and a select carry a browser-decided intrinsic width — around 180px in Chrome — so in
 * a 156px track they rendered 180px wide and spilled past the card's right edge, which
 * is what the owner photographed on 2026-09-04. The cells may now be narrower than their
 * contents want, which is the whole point of a fluid track.
 */
.eng-3up > *,
.eng-2up > *{ min-width:0; }
.eng-3up .eng-input,
.eng-2up .eng-input{ min-width:0; }

/* ==========================================================================
   §6.1 Full-bleed duotone band
   ========================================================================== */

.eng-band{ padding:0 var(--space-4) var(--space-8); }
.eng-band .eng-figure{ aspect-ratio:21/8; }

/* ==========================================================================
   §6.1 — 01 Read before you book
   ========================================================================== */

/* Featured post spans two columns; four text-only teasers stack beside it. */
.eng-editorial{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(300px,1fr));
  gap:var(--space-6);
}
.eng-editorial__feature{ grid-column:span 2; }
.eng-editorial__feature .eng-figure{ aspect-ratio:16/9; }
.eng-editorial__title{ font-size:clamp(22px,2.6vw,28px); margin:var(--space-2) 0; }

.eng-teasers{ display:grid; gap:0; }
.eng-teaser{ padding:var(--space-3) 0; border-bottom:1px solid var(--color-divider); }
.eng-teaser:last-child{ border-bottom:0; }
.eng-teaser__title{ font-size:17px; margin:2px 0 4px; }

/* ==========================================================================
   §6.1 — 02 Island-hopping tours
   ========================================================================== */

.eng-tours{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(230px,1fr));
  gap:var(--space-4);
}
/* §3.3 — 4/5 for tour cards. */
.eng-tourcard .eng-figure{ aspect-ratio:4/5; }
.eng-tourcard__name{ font-size:var(--type-h3-card); margin:2px 0 4px; }
.eng-tourcard__price{ font-size:14px; margin:var(--space-2) 0; }
.eng-tourcard__actions{ display:flex; flex-wrap:wrap; gap:var(--space-2); }

/* ==========================================================================
   §6.1 — 03 Local experts (ranked rows)
   ========================================================================== */

.eng-rank{
  display:grid;
  grid-template-columns:auto 1fr auto;
  gap:var(--space-4);
  align-items:start;
  padding:var(--space-3) 0;
  border-bottom:1px solid var(--color-divider);
}
.eng-rank:last-child{ border-bottom:0; }
.eng-rank__num{
  font-family:var(--font-heading);
  font-size:22px;
  font-weight:600;
  /* accent-700, not accent: at 22px this is body text (WCAG large starts at 24px),
     and --color-accent measures only 3.52:1 on --color-bg. accent-700 is 6.14:1.
     The 38px section numbers keep --color-accent — large text needs only 3:1. */
  color:var(--color-accent-700);
  line-height:1.2;
  min-width:2ch;
}
.eng-rank__name{ font-size:17px; }
.eng-rank__meta{ font-size:12px; color:var(--color-muted); }
.eng-rank__blurb{ font-size:14px; margin-top:4px; }
.eng-rank__side{ text-align:right; font-size:13px; white-space:nowrap; }
.eng-rank__score{ font-size:20px; font-family:var(--font-heading); font-weight:600; }

/* ==========================================================================
   §6.1 — 04 Where the boats go
   ========================================================================== */

.eng-dests{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(210px,1fr));
  gap:var(--space-4);
}
/* §3.3 — 1/1 for destination cards. */
.eng-destcard .eng-figure{ aspect-ratio:1/1; }
.eng-destcard__name{ font-size:17px; margin:var(--space-2) 0 2px; }

/* ==========================================================================
   §6.1 — 05 Traveller questions
   ========================================================================== */

.eng-faqcols{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(260px,1fr));
  gap:var(--space-6);
}
.eng-faqcols__head{
  font-size:12px;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--color-accent-700);
  margin-bottom:var(--space-2);
}
.eng-faq__answer{ font-size:14px; padding:0 0 var(--space-3); color:var(--color-muted); }

.eng-closing{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:var(--space-4);
  border-top:1px solid var(--color-divider);
  margin-top:var(--space-6);
  padding-top:var(--space-4);
}

/* On mobile the featured post cannot span two columns of a single-column grid. */
@media (max-width:767px){
  .eng-editorial__feature{ grid-column:auto; }
  .eng-rank{ grid-template-columns:auto 1fr; }
  .eng-rank__side{ grid-column:2; text-align:left; }
}

/* ==========================================================================
   §6.2 Guides hub
   ========================================================================== */

.eng-guidesec{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(280px,1fr));
  gap:var(--space-6);
  border-top:2px solid var(--color-text);
  padding-top:var(--space-4);
  margin-top:var(--space-6);
}
.eng-guidesec__body{ grid-column:span 2; }
.eng-guiderow{ padding:var(--space-3) 0; border-bottom:1px solid var(--color-divider); }
.eng-guiderow:last-child{ border-bottom:0; }
.eng-guiderow__title{ font-size:23px; margin:2px 0 4px; }

/* ==========================================================================
   §6.3 Single post
   ========================================================================== */

.eng-post{ padding:var(--space-6) var(--space-4) var(--space-8); }
.eng-post__crumb{ font-size:12px; color:var(--color-muted); }
.eng-post__title{
  font-size:var(--type-h1-article);
  line-height:1.02;
  max-width:26ch;
  margin:var(--space-3) 0;
}

/* Byline bar: text rule above, divider below (§6.3). */
.eng-byline{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:var(--space-4);
  border-top:1px solid var(--color-text);
  border-bottom:1px solid var(--color-divider);
  padding:var(--space-3) 0;
  font-size:13px;
  color:var(--color-muted);
  margin-bottom:var(--space-6);
}
.eng-byline__share{ margin-left:auto; display:flex; gap:var(--space-3); }

.eng-post__hero{ aspect-ratio:21/9; margin-bottom:var(--space-2); }

/* In-article styles (§6.3). */
.eng-article h2{ font-size:var(--type-h2-article); margin:var(--space-6) 0 var(--space-2); }
.eng-article h3{ font-size:20px; margin:var(--space-4) 0 var(--space-2); }
.eng-article p{ margin:0 0 var(--space-3); }
.eng-article ul,
.eng-article ol{ margin:0 0 var(--space-3); padding-left:1.3em; }
.eng-article img{ height:auto; }
.eng-article figure{ margin:var(--space-4) 0; }
.eng-article blockquote{
  border-left:3px solid var(--color-accent);
  margin:var(--space-4) 0;
  padding-left:var(--space-4);
  font-size:22px;
  line-height:1.4;
}
.eng-article a{ text-decoration:underline; }

/* Sticky right rail: TOC + blueprint CTA card. */
.eng-toc{ font-size:14px; }
.eng-toc__head{
  font-size:12px;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--color-accent-700);
  margin-bottom:var(--space-2);
}
.eng-toc ul{ list-style:none; margin:0; padding:0; display:grid; gap:6px; }
.eng-ctacard{ padding:var(--space-4); margin-top:var(--space-6); display:grid; gap:var(--space-2); }

/* Footer band (§6.3). */
.eng-postfoot{
  border-top:2px solid var(--color-text);
  margin-top:var(--space-8);
  padding-top:var(--space-4);
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(280px,1fr));
  gap:var(--space-6);
}

/* ==========================================================================
   §6.4 Category archive
   ========================================================================== */

.eng-archive__head{ padding:var(--space-6) var(--space-4) var(--space-4); }
.eng-archive__count{ font-size:13px; color:var(--color-muted); }
.eng-tagrow{ display:flex; flex-wrap:wrap; gap:var(--space-2); margin-top:var(--space-3); }

.eng-postrow{
  display:grid;
  grid-template-columns:1fr 200px;
  gap:var(--space-4);
  align-items:start;
  padding:var(--space-4) 0;
  border-bottom:1px solid var(--color-divider);
}
.eng-postrow__title{ font-size:27px; margin:4px 0 6px; }
.eng-postrow .eng-figure{ aspect-ratio:3/2; }
.eng-pagination{ display:flex; gap:var(--space-2); margin-top:var(--space-6); }

/* ==========================================================================
   §6.5 Destination single
   ========================================================================== */

.eng-dest__hero{ aspect-ratio:24/9; }
.eng-facts{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  gap:var(--space-4);
  margin:var(--space-6) 0;
}
.eng-fact__label{
  font-size:11px;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--color-accent-700);
}
.eng-fact__value{ font-size:16px; margin-top:4px; }

/*
 * Destination gallery (Task 4, P2-F) — curated or auto-matched, both render through
 * the same markup. .eng-figure alone carries no border (the hairline + corner marks
 * were removed from photographs by client direction, see 30-components.css), so the
 * hairline border required for this grid is added here, scoped to the gallery only —
 * it does not touch .eng-figure's photograph-wide default.
 *
 * min-width:0 on the item: a grid child, even one holding only an <img>, can still
 * be blown wider than its track without it once object-fit/aspect-ratio is in play.
 */
.eng-destgallery{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(140px,1fr));
  gap:var(--space-3);
  margin:var(--space-6) 0;
}
.eng-destgallery__item{
  /*
   * display:block is load-bearing. The item is a <span>, which is inline by default, so
   * the aspect-ratio box had no block formatting context and the child image's
   * height:100% (from .eng-figure > img) had nothing to resolve against — every
   * thumbnail sat short inside its frame with a white band beneath it.
   */
  display:block;
  aspect-ratio:4/3;
  overflow:hidden;
  border:1px solid var(--color-divider);
  min-width:0;
}
.eng-destgallery__item img{
  width:100%;
  height:100%;
  object-fit:cover;
  display:block;
}

/* "On the ground" tips (Task 4, P2-F) — a plain list, no card treatment. */
.eng-desttips{
  display:grid;
  gap:var(--space-2);
  margin:var(--space-4) 0;
  padding-left:var(--space-4);
}
.eng-desttips li{ font-size:15px; line-height:1.5; }

/* ==========================================================================
   §6.16 Tips · §6.17 Featured places
   ========================================================================== */

.eng-tipgrid{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(300px,1fr));
  gap:var(--space-4);
}
.eng-tipcard{ padding:var(--space-4); display:grid; gap:var(--space-2); align-content:start; }
.eng-tipcard__tags{ display:flex; flex-wrap:wrap; gap:var(--space-2); }
.eng-tipcard__text{ font-size:17px; line-height:1.45; }
.eng-tipcard__by{ font-size:12px; color:var(--color-muted); }
.eng-tipcard__actions{ display:flex; flex-wrap:wrap; gap:var(--space-2); margin-top:var(--space-2); }

.eng-featgrid{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(280px,1fr));
  gap:var(--space-4);
}
.eng-featcard .eng-figure{ aspect-ratio:4/3; }
.eng-featcard__name{ font-size:24px; margin:var(--space-2) 0 4px; }

/* Filter row (§6.6, §6.16) — active option carries a 5px accent dot. */
.eng-filters{ display:flex; flex-wrap:wrap; gap:var(--space-2); margin:var(--space-3) 0 var(--space-4); }
.eng-filters .eng-btn.is-active::before{
  content:"";
  width:5px;
  height:5px;
  background:var(--color-accent);
  display:inline-block;
}

/* ==========================================================================
   §6.15 Trip planner (static, Phase 1) · §6.18 Saved (empty state)
   ========================================================================== */

.eng-day{ padding:var(--space-4); margin-bottom:var(--space-4); display:grid; gap:var(--space-3); }
.eng-day__head{ display:flex; flex-wrap:wrap; align-items:baseline; gap:var(--space-3); }
.eng-day__num{
  font-family:var(--font-heading);
  font-size:26px;
  font-weight:600;
  color:var(--color-accent-700);
}
.eng-day__item{
  display:grid;
  grid-template-columns:auto 1fr auto;
  gap:var(--space-3);
  padding:var(--space-2) 0;
  border-top:1px solid var(--color-divider);
  font-size:14px;
}
.eng-day__slot{ font-size:11px; letter-spacing:.14em; text-transform:uppercase; color:var(--color-accent-700); }

.eng-empty{
  border:1px solid var(--color-divider);
  padding:var(--space-8) var(--space-4);
  text-align:center;
  display:grid;
  gap:var(--space-3);
  justify-items:center;
}
.eng-empty__title{ font-size:var(--type-h2-section); }

@media (max-width:767px){
  .eng-guidesec__body{ grid-column:auto; }
  .eng-postrow{ grid-template-columns:1fr; }
  .eng-day__item{ grid-template-columns:1fr; }
}

/* Tip cards now carry a linked title (they surface guide posts, not standalone tips). */
.eng-tipcard__title{ font-size:19px; margin:2px 0 4px; }
.eng-tipcard__title a{ text-decoration:none; }
.eng-tipcard__title a:hover{ text-decoration:underline; }

/* ==========================================================================
   §6.12 Order confirmation (thank-you)
   ========================================================================== */

.eng-thanks{ padding:var(--space-6) var(--space-4) var(--space-8); }
.eng-thanks__title{ font-size:var(--type-h1-page); line-height:1.02; margin:var(--space-3) 0; }
.eng-thanks__actions{ display:flex; flex-wrap:wrap; gap:var(--space-2); margin:var(--space-4) 0; }
.eng-thanks__summary{ padding:var(--space-4); margin-top:var(--space-6); }
.eng-tipsgrid-4{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(230px,1fr));
  gap:var(--space-4);
  margin-top:var(--space-6);
}

/* ==========================================================================
   §6.18 Saved · §6.15 planner (the draft dialog retired 2026-09-02)
   ========================================================================== */

.eng-draft-note{ font-size:13px; }

/* ==========================================================================
   §6.8 Provider signup — three tracks
   /become-a-provider/  (markup: inc/providers.php)

   Three doors, not ten cards. The cards are blueprint objects like every other
   card in the system: transparent, hairline, square, registration marks.
   ========================================================================== */

.eng-tracks{ margin:var(--space-6) 0; }
.eng-tracks__title{ margin:0 0 var(--space-2); }
.eng-tracks__lede{ margin:0 0 var(--space-6); color:var(--color-muted); }

.eng-tracks__grid{
  display:grid;
  grid-template-columns:repeat(3, 1fr);
  gap:var(--space-4);
}

/*
 * The whole card is the link.
 *
 * A card with a separate "Sign up" link inside it gives keyboard users two tab stops to
 * the same place and gives pointer users a large dead zone that looks clickable. Making
 * the <a> the card itself is one target, one tab stop, one focus ring — and the arrow is
 * aria-hidden decoration rather than a second control.
 */
.eng-track{
  display:flex;
  flex-direction:column;
  gap:var(--space-3);
  padding:var(--space-4);
  text-decoration:none;
  color:var(--color-text);
  /* min-width:0 so a long category name cannot push the grid track wider than 1fr. */
  min-width:0;
}
.eng-track:hover{ background:var(--color-accent-100); }
.eng-track__title{ margin:0; font-size:22px; }
.eng-track__lede{ margin:0; color:var(--color-muted); font-size:15px; }

.eng-track__covers{
  margin:0;
  padding:0;
  list-style:none;
  display:grid;
  gap:4px;
  font-size:13px;
  color:var(--color-text);
  /* Pushes the "Sign up →" to the bottom so all three cards align regardless of how
     many categories each track covers. */
  margin-bottom:auto;
}
.eng-track__covers li{ padding-left:14px; position:relative; }
.eng-track__covers li::before{
  content:"";
  position:absolute;
  left:0;
  top:8px;
  width:5px;
  height:5px;
  background:var(--color-accent);
}

.eng-track__go{
  font-family:var(--font-body);
  font-weight:600;
  font-size:15px;
  color:var(--color-accent-800);
}
.eng-track:hover .eng-track__go{ color:var(--color-accent-900); }

.eng-tracks__login{ margin-top:var(--space-6); color:var(--color-muted); }

/* --- the chosen track's intro, above the signup form --------------------- */
.eng-track-intro__title{ margin:0 0 var(--space-2); }
.eng-track-intro__lede{ margin:0 0 var(--space-3); color:var(--color-muted); max-width:62ch; }
.eng-track-intro__back{ margin:0 0 var(--space-6); font-size:14px; }

@media (max-width:900px){
  .eng-tracks__grid{ grid-template-columns:1fr; gap:var(--space-4); }
}

/* ==========================================================================
   §6.13 Accommodations — editorial stay cards
   /accommodations/  (markup: inc/stays.php)

   Editorial cards, not booking inventory: these are the guide's own write-ups of
   real places. Three up on desktop, two at tablet, one on mobile.

   The card's children are FLAT — media, kicker, title, dek — rather than a media
   element plus a wrapping body div. Flat is what lets subgrid below align the four
   bands across a whole row, so every headline in a row shares a baseline whatever
   the length of the dek above it.
   ========================================================================== */

.eng-stays{
  display:grid;
  grid-template-columns:repeat(3, 1fr);
  gap:var(--space-6) var(--space-4);
  margin:var(--space-6) 0;
}

.eng-stay{
  display:grid;
  /* Six rows: media, kicker, title, dek, meta, actions. If a child is added here the
     `grid-row: span` below must change to match, or the subgrid stops aligning. */
  grid-template-rows:auto auto auto 1fr auto auto;
  gap:var(--space-2);
  /* min-width:0 — without it a long unbroken hotel name blows the 1fr track out and
     the whole grid loses its columns. */
  min-width:0;
}

/*
 * Align the six bands across each row.
 *
 * Without subgrid each card is its own grid and only the card's top edge is shared, so
 * a two-line headline in one card pushes its dek out of step with its neighbours'.
 * `grid-row: span 6` hands the card's six children to the parent's row track, and
 * every card in the row then measures against the same six bands.
 *
 * @supports-gated because subgrid is the one part of Grid with meaningful legacy gaps.
 * Without it the cards still stack correctly — they just align on their top edge only,
 * which is the ordinary card-grid look rather than a broken one.
 */
@supports (grid-template-rows: subgrid){
  .eng-stay{
    grid-row:span 6;
    grid-template-rows:subgrid;
  }
}

.eng-stay__media{
  display:block;
  aspect-ratio:4 / 3;
  overflow:hidden;
  background:var(--color-surface);
}
.eng-stay__img{
  width:100%;
  height:100%;
  object-fit:cover;
  display:block;
}

/* No photograph on this post yet. The brand mark at low contrast, so the slot reads as
   deliberate rather than as an image that failed to load. */
.eng-stay__media--empty{
  background:var(--color-surface);
  border:1px solid var(--color-divider);
  display:flex;
  align-items:center;
  justify-content:center;
}
.eng-stay__mark{ opacity:.28; }

.eng-stay__kicker{ margin:0; }
.eng-stay__title{ margin:0; font-size:19px; line-height:1.25; }
.eng-stay__title a{ text-decoration:none; }
.eng-stay__title a:hover{ text-decoration:underline; }
.eng-stay__dek{ margin:0; color:var(--color-muted); font-size:14px; }

/* The card's two commercial facts on one line: what a room costs, and what booking
   through us is worth. Emitted even when both are absent — see eng_sc_stays(). */
.eng-stay__meta{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:var(--space-2);
  min-height:0;
}
.eng-stay__rate{ font-size:14px; font-weight:600; }
/* Outlined, not filled. The primary button is the one filled object in this design, and a
   grid of ten cards each shouting a percentage in solid accent would out-shout the thing
   the card is actually for. */
.eng-stay__badge{
  font-size:12px;
  line-height:1;
  padding:6px 10px;
  color:var(--color-accent-800);
  border:1px solid var(--color-accent-400);
  white-space:nowrap;
  /* Pushed right by the badge itself rather than by space-between on the row: most cards
     carry a badge and no rate yet, and space-between left-aligns a lone child. That put
     the pill on the left of some cards and the right of others across the same row. */
  margin-left:auto;
}
@media (max-width:480px){
  /* Stacked and left-aligned — nothing to align to across a single-column grid. */
  .eng-stay__badge{ margin-left:0; }
}

@media (max-width:1023px){
  .eng-stays{ grid-template-columns:repeat(2, 1fr); }
}
@media (max-width:767px){
  .eng-stays{ grid-template-columns:1fr; gap:var(--space-6); }
}

/* ==========================================================================
   §6.18 Save controls
   (markup: inc/saved.php, behaviour: assets/js/eng-app.js)

   One control, four surfaces — Place, Tour, Guide, Tip. It is a <button> with
   aria-pressed, not a link: it toggles in place and navigates nowhere.
   ========================================================================== */

/* Two controls side by side: "View rooms" and "Add to plan". They had no gap rule at all
   and sat against each other at whatever height their text gave them. */
.eng-stay__actions{
  margin-top:var(--space-2);
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:var(--space-2);
}
.eng-stay__actions > .eng-btn{ min-height:44px; }
@media (max-width:480px){
  /* Full width and stacked. Two-up at this size leaves "Add to plan" wrapping onto two
     lines inside a button barely wider than its own text. */
  .eng-stay__actions > .eng-btn{ flex:1 1 100%; }
}
.eng-featcard__save{ margin-top:var(--space-3); }

/* ==========================================================================
   Task 5 (P0-B) — Add to plan controls
   /plan/  (markup: inc/plan-add.php, inc/product.php, inc/stays.php;
   behaviour: assets/js/eng-app.js)

   Save's counterpart: a distinct control (data-eng-plan-add) and a distinct
   localStorage key (eng_plan_v1) feeding the "Added to your plan" section
   below, appended into /plan/ by inc/planner.php's eng_planner_wrap().
   ========================================================================== */

.eng-plan-add{
  /* Same fixed-width rationale as .eng-save: "Add to plan" and "In your plan"
     differ enough in length that without a floor the row reflows on toggle. */
  min-width:120px;
  justify-content:center;
}

/* Pressed state, styled from aria-pressed for the same reason as .eng-save
   above it — the attribute is the source of truth eng-app.js sets. */
[data-eng-plan-add][aria-pressed="true"]{
  background:var(--color-accent-100);
  color:var(--color-accent-900);
  border-color:var(--color-accent-600);
}

.eng-plan-added{
  margin:var(--space-6) 0 0;
  padding-top:var(--space-6);
  border-top:1px solid var(--color-text);
}
.eng-plan-added__h{ margin:0 0 var(--space-4); }

.eng-plan-row{
  display:grid;
  grid-template-columns:1fr auto;
  gap:var(--space-4);
  align-items:center;
  padding:var(--space-3) 0;
  border-bottom:1px solid var(--color-divider);
}
.eng-plan-row:last-child{ border-bottom:0; }
.eng-plan-row__title{ font-size:17px; margin:0 0 2px; }
.eng-plan-row__title a{ text-decoration:none; }
.eng-plan-row__note{ font-size:14px; color:var(--color-text); margin-top:2px; }

@media (max-width:767px){
  .eng-plan-row{ grid-template-columns:1fr; }
}

/*
 * Task 2 (Planner v3) §2f — every plan row's remove control, wherever it renders
 * (renderPlanAdded()'s rows above and renderItinerary()'s itinerary days,
 * eng-app.js). Icon-only, so the button itself needs an explicit floor rather than
 * relying on .eng-btn's own padding: measured at 39px on desktop, same shortfall
 * already called out for .eng-itinerary__actions .eng-btn above. Sized at every
 * width, not only mobile — the shared .eng-btn mobile-only rule in
 * 50-responsive.css does not reach desktop.
 */
.eng-plan-remove{
  min-width:44px;
  min-height:44px;
  padding:0;
  font-size:18px;
  line-height:1;
}

/* ==========================================================================
   Task 6 (P0-A) — plan durability: account-sync note + email-resume form
   /plan/  (markup: inc/plan-sync.php; behaviour: assets/js/eng-app.js)
   ========================================================================== */

.eng-plan-sync{
  margin:var(--space-6) 0 0;
  padding-top:var(--space-6);
  border-top:1px solid var(--color-divider);
}

.eng-plan-resume{ max-width:420px; }
.eng-plan-resume__note{ font-size:13px; }
.eng-plan-resume__error{
  font-size:13px;
  color:var(--color-danger);
  margin:0;
}
.eng-plan-resume__status{
  font-size:13px;
  color:var(--color-success);
  margin:0;
}
.eng-plan-resume input[aria-invalid="true"]{ border-color:var(--color-danger); }

/* 44px hit target, independent of .eng-btn's own (smaller) padding. */
.eng-plan-resume button[type="submit"]{
  min-height:44px;
  margin-top:var(--space-2);
}

/*
 * The FIELD needs the 44px floor too, not just the button.
 *
 * The submit button got it above; the email input inherited the site's default field
 * padding and measured 41px at every width. A text field is a tap target like any other,
 * and 41px is the size that makes a thumb miss it on a phone.
 */
.eng-plan-resume input[type="email"]{
  min-height:44px;
  width:100%;
}

/* ==========================================================================
   §6.15 Trip planner — offline note
   /plan/  (markup: inc/planner.php)

   Task 1 — the retired Planning / On-the-ground toggle and its on-the-ground
   panel (.eng-planner-modes, .eng-planner__planning, .eng-planner__onground,
   .eng-og*) are gone; the plain-paragraph note that used to close the
   retired panel now closes the single planner view instead.
   ========================================================================== */

.eng-planner__offline{ margin:var(--space-6) 0 0; }

/* ==========================================================================
   404 and search
   (template: 404.php)

   The search form is styled here rather than in a 404-only block: the same
   markup appears in the 404, on search results and in any search widget, and
   GeneratePress ships it with a filled submit button in its own accent — which
   rendered as an off-brand red square next to every search field on the site.
   ========================================================================== */

.eng-404{ padding-bottom:var(--space-8); }
.eng-404__search{ margin:var(--space-6) 0; max-width:520px; }

.eng-404__links{
  display:grid;
  grid-template-columns:repeat(3, 1fr);
  gap:var(--space-4);
  border-top:2px solid var(--color-text);
  padding-top:var(--space-6);
}
.eng-404__link{
  display:block;
  padding:var(--space-4);
  border:1px solid var(--color-divider);
  text-decoration:none;
  color:var(--color-text);
  min-width:0;
}
.eng-404__link:hover{ background:var(--color-accent-100); border-color:var(--color-accent-600); }
.eng-404__link-title{ margin:0 0 4px; font-size:19px; }
.eng-404__link p{ margin:0; font-size:14px; }

/* --- the search form, everywhere it appears ------------------------------- */
.search-form,
.wp-block-search__inside-wrapper{
  display:flex;
  gap:0;
  align-items:stretch;
}
.search-form input[type="search"],
.wp-block-search__input{
  flex:1 1 auto;
  min-width:0;
  border-radius:0;
  border:1px solid var(--color-divider);
  border-right:0;
  background:transparent;
  padding:12px var(--space-3);
  min-height:44px;      /* §9 hit target */
  font-family:var(--font-body);
  font-size:15px;
  color:var(--color-text);
  box-shadow:none;
}
.search-form button,
.search-form input[type="submit"],
.wp-block-search__button{
  flex:0 0 auto;
  border-radius:0;
  margin:0;
  padding:12px var(--space-4);
  min-height:44px;
  background:var(--color-accent-600);
  color:#fff;
  border:1px solid var(--color-accent-600);
  font-family:var(--font-body);
  font-weight:600;
  font-size:15px;
  box-shadow:none;
  cursor:pointer;
}
.search-form button:hover,
.search-form input[type="submit"]:hover,
.wp-block-search__button:hover{
  background:var(--color-accent-800);
  border-color:var(--color-accent-800);
  color:#fff;
}
/* GP's button carries an SVG magnifier; keep it on the accent, not black. */
.search-form button svg,
.wp-block-search__button svg{ fill:currentColor; }

@media (max-width:767px){
  .eng-404__links{ grid-template-columns:1fr; }
}

/* ==========================================================================
   §6.1 Home — the three live sections
   (markup: inc/home.php)
   ========================================================================== */

.eng-homeguides{ display:grid; gap:0; }
.eng-homeguide{
  display:grid;
  gap:4px;
  padding:var(--space-4) 0;
  border-bottom:1px solid var(--color-divider);
  min-width:0;
}
.eng-homeguide:last-child{ border-bottom:0; }
.eng-homeguide__title{ margin:0; font-size:23px; line-height:1.2; }
.eng-homeguide__title a{ text-decoration:none; }
.eng-homeguide__title a:hover{ text-decoration:underline; }
.eng-homeguide__dek{ margin:0; color:var(--color-muted); font-size:15px; }

.eng-destgrid{
  display:grid;
  grid-template-columns:repeat(4, 1fr);
  gap:var(--space-4);
}
.eng-destcard{ display:grid; gap:var(--space-2); text-decoration:none; color:var(--color-text); min-width:0; }
.eng-destcard__media{
  display:block;
  /* 1/1 for destinations, per §3.3's aspect-ratio table. */
  aspect-ratio:1 / 1;
  overflow:hidden;
  background:var(--color-surface);
}
.eng-destcard__img,
.eng-destcard__media img{ width:100%; height:100%; object-fit:cover; display:block; }
.eng-destcard__name{ font-family:var(--font-heading); font-weight:600; font-size:19px; }
.eng-destcard:hover .eng-destcard__name{ text-decoration:underline; }

/* §6.1 section 03 — ranked operator rows, matching the directory's row treatment
   rather than a card grid: this is a leaderboard, not a gallery. */
.eng-homeexperts{ display:grid; gap:0; }
.eng-homeexpert{
  display:grid;
  grid-template-columns:auto minmax(0, 1fr) auto;
  align-items:baseline;
  gap:var(--space-4);
  padding:var(--space-4) 0;
  border-bottom:1px solid var(--color-divider);
  text-decoration:none;
  color:var(--color-text);
}
.eng-homeexpert:last-child{ border-bottom:0; }
.eng-homeexpert:hover{ background:var(--color-accent-100); }

/* accent-700, not accent — body-sized text has to clear 4.5:1 (audit-contrast.mjs). */
.eng-homeexpert__rank{
  font-family:var(--font-heading);
  font-weight:600;
  font-size:18px;
  color:var(--color-accent-700);
}
.eng-homeexpert__body{ display:grid; gap:2px; min-width:0; }
.eng-homeexpert__name{ font-family:var(--font-heading); font-weight:600; font-size:19px; }
.eng-homeexpert__meta{ font-size:14px; }
.eng-homeexpert__stats{ text-align:right; font-size:14px; white-space:nowrap; }
.eng-homeexpert__rating{ font-weight:600; }

@media (max-width:1023px){
  .eng-destgrid{ grid-template-columns:repeat(2, 1fr); }
}
@media (max-width:600px){
  .eng-destgrid{ grid-template-columns:1fr; }
  /* The rank column costs width a phone does not have; the number moves inline. */
  .eng-homeexpert{ grid-template-columns:auto minmax(0, 1fr); }
  .eng-homeexpert__stats{ grid-column:2; text-align:left; }
}


/* The visitor's own itinerary, rendered by renderItinerary() in eng-app.js into the
   [data-eng-itinerary] shell that inc/planner.php prints. This replaced the four static
   days that used to be baked into the page record — see eng_plan_itinerary_panel(). */
.eng-itinerary__title{
  font-family:var(--font-heading);
  font-size:22px;
  line-height:1.2;
  margin:0 0 var(--space-2);
}
.eng-itinerary__days{
  margin:var(--space-4) 0;
  border-top:1px solid var(--color-divider);
}
.eng-itinerary__days .eng-day__item{
  border-bottom:1px solid var(--color-divider);
}
/*
 * Task 3 (Planner v3) — a day's title becomes a real link once inc/plan-book.php
 * resolves a bookable category or product for it. Element-qualified
 * (a.eng-day__link, not .eng-day__link): GeneratePress emits `.inside-article a {
 * color: … }` at 0-1-1 and silently beats a bare class here, as it has elsewhere on
 * this project. accent-700 measures 4.5:1+ on the cream ground; accent-600 (used for
 * icon accents elsewhere) does not and is not used for text.
 */
a.eng-day__link{
  color:var(--color-accent-700);
  text-decoration:underline;
  /* The day title IS the booking link, and it measured 17px tall — a line of text,
     not a target. inline-flex + min-height gives it a 44px touch area without
     changing where the text sits or how the row reads. */
  display:inline-flex;
  align-items:center;
  min-height:44px;
}
a.eng-day__link:hover,
a.eng-day__link:focus{
  color:var(--color-accent-900);
}
/*
 * Task 2 (Planner v3) §2f — a fourth column for the remove control, on a modifier class
 * rather than on `.eng-day__item` itself: the same base class also renders the §7
 * dialog's read-only preview rows (renderDialog() in eng-app.js), which carry no remove
 * button and must keep their existing three columns.
 */
.eng-day__item--plan{ grid-template-columns:auto 1fr auto auto; }
@media (max-width:767px){
  /*
   * A single-class selector, same specificity as the general `.eng-day__item{
   * grid-template-columns:1fr; }` mobile collapse below — declared after it here so it
   * still wins for these rows once both apply.
   *
   * TWO columns on a phone, not one (2026-09-04). Collapsing all four cells into one
   * column stacked them in source order — day label, title, price, remove — which put
   * the remove control on a line of its own, centred, under the price: a bare × floating
   * in the middle of the row with nothing to attach it to. It also made every row 195px
   * to 271px tall, so a five-day itinerary took four screens to scroll past.
   *
   * The second column exists only for the remove control, pinned to the row's first line
   * where the eye already is. Everything else runs down the first column at full width,
   * and the empty price cell a transfer row carries is removed rather than left to add a
   * gap for a number that does not exist.
   */
  .eng-day__item--plan{
    grid-template-columns:1fr auto auto;
    align-items:center;
    row-gap:2px;
    column-gap:var(--space-2);
  }
  /* The day, its price and the remove control share the first line: three short things
     that belong together, and the line the eye lands on first. The title then gets the
     full width beneath them instead of competing with a number for it. */
  .eng-day__item--plan > .eng-day__slot{ grid-column:1; grid-row:1; }
  .eng-day__item--plan > span:not(.eng-day__slot){ grid-column:2; grid-row:1; justify-self:end; }
  .eng-day__item--plan > [data-eng-plan-remove]{ grid-column:3; grid-row:1; }
  .eng-day__item--plan > div:not(.eng-day__actions){ grid-column:1 / -1; grid-row:2; }
  .eng-day__item--plan > .eng-day__actions{ grid-column:1 / -1; grid-row:3; }
}
/*
 * Planner booking (2026-09-01) — the action strip under a bookable row: an optional
 * product dropdown plus Book now, or the in-cart badge plus View cart. A full-width
 * grid row (grid-column:1/-1) under the existing columns, so rows without a button
 * keep their exact current shape and the modifier only adds the strip.
 *
 * The select is a real control at the 44px floor. Its border uses the divider token
 * (a control edge, not an emphasis), its focus ring the accent — themed, per the
 * craft floor, rather than shipping the browser default on the one control this
 * page asks the visitor to operate.
 */
.eng-day__item--actions{ row-gap:var(--space-2); }
.eng-day__actions{
  grid-column:1 / -1;
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:var(--space-2);
  /* min-width:0 on both the grid item and the select below: a flex/grid item's
     default min-width:auto refuses to shrink below its content, and one long
     product title then pushed the whole strip past a 430px viewport — measured
     on staging, Day 3's "Happiness El Nido Deluxe…" select. 0 lets the select
     shrink and ellipsize inside the row instead. */
  min-width:0;
}
.eng-day__select{
  min-height:44px;
  padding:0 var(--space-2);
  border:1px solid var(--color-divider);
  background:#fff;
  color:var(--color-text);
  font-family:var(--font-body);
  font-size:14px;
  max-width:100%;
  flex:1 1 220px;
  min-width:0;
  text-overflow:ellipsis;
}
.eng-day__select:focus{
  outline:2px solid var(--color-accent-600);
  outline-offset:1px;
  border-color:var(--color-accent-600);
}
/* a.-qualified for the same 0-1-1 reason as a.eng-day__link above; the shared
   .eng-btn variants carry the palette, this only holds the target height. */
a.eng-day__book{ min-height:44px; }
.eng-day__incart{
  color:var(--color-accent-700);
  font-weight:600;
  font-size:14px;
}
@media (max-width:767px){
  /* One control per line on phones: the select and the button each take the full
     width rather than wrapping into a cramped pair. */
  .eng-day__select{ flex-basis:100%; }
  a.eng-day__book{ flex:1 1 100%; }
}
/*
 * Task 4 (Planner v3) — the seeded accommodation recommendation. Always carries
 * `.eng-day__item--plan` too (eng-app.js's stayRowHtml()), so it keeps that class's
 * 4-column grid and remove control — same list, removable the same way as a day, per
 * the brief. This modifier only adds what makes it read as NOT a numbered day: an
 * accent rule plus a tinted background, standing in for the "Day N" slot text that
 * stayRowHtml() replaces with a fixed "Where to stay" label instead.
 */
.eng-day__item--stay{
  background:var(--color-surface);
  border-left:3px solid var(--color-accent-700);
  padding-left:var(--space-3);
}
/* A transfer row is information, not an offer (2026-09-04): a quieter ground and a
   left rule, so the eye reads it as the frame around the day rather than a thing to
   book. No price cell content, no booking control — see renderItinerary(). */
.eng-day__item--transfer{
  background:var(--color-surface);
  border-left:3px solid var(--color-accent-600);
  /* Matches --stay above: a 3px rule with no padding sits the text flush against it. */
  padding-left:var(--space-3);
}
.eng-day__item--transfer .eng-day__slot{ color:var(--color-accent-800); }
.eng-itinerary__actions{
  display:flex;
  flex-wrap:wrap;
  gap:var(--space-2);
  margin-top:var(--space-4);
}
/* The secondary button's own padding lands it at 39px on desktop; the mobile rules
   already bump it past 44. Stated here so the target holds at EVERY width, not just the
   one where another rule happens to save it. Measured, not assumed — build/audit-draft-handoff.mjs. */
.eng-itinerary__actions .eng-btn{ min-height:44px; }
/* The empty state carries the page on a first visit, so it is a panel rather than a line
   of muted text: a visitor who lands here before building anything needs an obvious way
   in, not an apology. */
.eng-itinerary__empty{
  padding:var(--space-6) var(--space-4);
  background:var(--color-surface);
  text-align:center;
}
.eng-itinerary__empty p{
  margin:0 auto var(--space-4);
  max-width:46ch;
  color:var(--color-text);
}

/*
 * Task 5 (Planner v3 ADDENDUM) — the trip total. Rendered by tripTotalHtml() as part of
 * renderItinerary()'s own output (eng-app.js), so it has no PHP shell of its own — see
 * that function's docblock for why. Styled like .eng-day__item--stay just above it in
 * this file: a tinted panel with an accent rule, so it reads as a closing summary of the
 * list above it rather than another row within it.
 */
.eng-trip-total{
  margin:var(--space-4) 0;
  padding:var(--space-4);
  background:var(--color-surface);
  border-left:3px solid var(--color-accent-700);
}
.eng-trip-total__amount{
  font-family:var(--font-heading);
  font-size:22px;
  line-height:1.2;
  margin:0 0 var(--space-2);
  color:var(--color-text);
}
.eng-trip-total__label{
  display:block;
  font-family:var(--font-body);
  font-size:var(--type-meta);
  text-transform:uppercase;
  letter-spacing:.08em;
  color:var(--color-muted);
  margin-bottom:2px;
}
.eng-trip-total__party,
.eng-trip-total__note{ margin:0 0 var(--space-1); }
/*
 * The addendum's "say how many rows are uncounted" line — warning, not danger: this is a
 * disclosure about the total's own coverage, not a failure. --color-warning measures
 * 5.01:1 on --color-bg and 4.59:1 on --color-surface (this block's own background), so
 * it clears 4.5:1 either way the total is placed.
 */
.eng-trip-total__partial{ margin:var(--space-1) 0 0; color:var(--color-warning); }

/*
 * Plan B (Task 3) — the owner-authored itineraries that fit this trip. Rendered by
 * renderSuggestions() (eng-app.js) into the [data-eng-suggestions] shell that
 * inc/planner.php's eng_planner_wrap() prints on /plan/.
 *
 * The SECTION itself carries no padding, border or margin of its own, deliberately: it is
 * empty whenever nothing matched, and a styled wrapper would leave a visible gap standing
 * in for a section that is not there. Every rule below is on the heading or a card, so an
 * empty section occupies nothing.
 */
.eng-suggestions__h{
  font-family:var(--font-heading);
  font-size:22px;
  line-height:1.2;
  margin:var(--space-6) 0 var(--space-4);
}
/* A bordered block, not a card — the design has no elevation model (§12), so a suggestion
   is separated from the page by one hairline and its own padding, nothing else. */
.eng-suggest{
  border:1px solid var(--color-divider);
  padding:var(--space-4);
  margin:0 0 var(--space-4);
}
.eng-suggest:last-child{ margin-bottom:0; }
/* The owner uploads whatever image they have. A fixed ratio keeps three suggestions from
   stepping down the page at three different heights. */
.eng-suggest__thumb{
  display:block;
  width:100%;
  aspect-ratio:16/9;
  object-fit:cover;
  margin:0 0 var(--space-3);
  background:var(--color-surface);
}
.eng-suggest__title{
  font-family:var(--font-heading);
  font-size:19px;
  line-height:1.25;
  margin:0 0 var(--space-2);
}
.eng-suggest__summary{ margin:0 0 var(--space-2); max-width:60ch; }
/* var(--type-meta) is the 13px the brief asks for, taken from the token rather than typed,
   so this line tracks every other meta line on the site. */
.eng-suggest__meta{ font-size:var(--type-meta); color:var(--color-muted); margin:0 0 var(--space-3); }
/* Follows .eng-planner__confirm-actions at the top of this file: a wrapping flex row whose
   buttons carry the 44px floor at EVERY width, not only where 50-responsive.css happens to
   supply it. */
.eng-suggest__actions{ display:flex; flex-wrap:wrap; gap:var(--space-2); }
.eng-suggest__actions .eng-btn{ min-height:44px; }
/* The preview is a plain list under a rule, never a second card inside the first: it shows
   the same days the itinerary above would, shown early. */
.eng-suggest__days{
  margin-top:var(--space-3);
  padding-top:var(--space-3);
  border-top:1px solid var(--color-divider);
}
.eng-suggest__day{ margin:0 0 var(--space-2); font-size:15px; }
.eng-suggest__day:last-child{ margin-bottom:0; }
.eng-suggest__slot{
  display:block;
  font-size:var(--type-meta);
  text-transform:uppercase;
  letter-spacing:.08em;
  color:var(--color-muted);
}
/* The owner's Note for this day. .eng-muted already carries the size and colour the
   transfer row's note uses; this only makes it its own line, because it sits inside the
   day's <p> alongside the item rather than in a block of its own. */
.eng-suggest__note{ display:block; margin-top:var(--space-1); }
@media (max-width:767px){
  /* Stacked and full-width: neither action should be the narrower half of a row that is
     already only a thumb wide. */
  .eng-suggest__actions{ flex-direction:column; }
  .eng-suggest__actions .eng-btn{ width:100%; }
}

/*
 * Homepage real-estate section (2026-09-01) — [eng_home_realestate], inc/home.php.
 * Same card grammar as the module's own listing cards, in theme tokens: square
 * corners, one accent, no shadows; the two title-status badges reuse the exact
 * colour pairs the listing archive already established.
 */
.eng-homere{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:var(--space-4);margin:0 0 var(--space-4)}
.eng-homere__card{background:#fff;border:1px solid var(--color-divider);display:flex;flex-direction:column}
.eng-homere__media{display:block;aspect-ratio:4/3;overflow:hidden;background:var(--color-surface)}
.eng-homere__media img{width:100%;height:100%;object-fit:cover;display:block}
.eng-homere__body{padding:var(--space-3) var(--space-4) var(--space-4);display:flex;flex-direction:column;gap:var(--space-2);flex:1}
.eng-homere__title{margin:0;font-size:1.02rem;line-height:1.35}
a.eng-homere__title a,.eng-homere__title a{color:var(--color-text);text-decoration:none}
.eng-homere__title a:hover,.eng-homere__title a:focus{color:var(--color-accent-800);text-decoration:underline}
.eng-homere__badge{align-self:flex-start;font-size:.7rem;font-weight:700;padding:3px 9px;letter-spacing:.02em}
/* Outline badges on the card's white ground: --color-success measures under
   4.5:1 on --color-success-bg at this size (caught by audit-contrast), but
   clears it on #fff — so the fill goes, the border carries the semantics. */
.eng-homere__badge--titled{background:#fff;color:var(--color-success);border:1px solid var(--color-success)}
.eng-homere__badge--tax{background:#fff;color:var(--color-warning);border:1px solid var(--color-warning)}
.eng-homere__price{font-weight:700;color:var(--color-accent-800);margin-top:auto}
.eng-homere__cta{display:flex;gap:var(--space-2);flex-wrap:wrap}
.eng-homere__cta .eng-btn{min-height:44px}

/* ==========================================================================
   §6.1 — the reel band (2026-09-01, replacing the static photo band).

   A portrait Facebook reel cannot fill the old 21/8 cinematic strip, so the
   band becomes a split moment: editorial copy on the left, the reel in a true
   9:16 frame on the right. Mobile stacks copy over a centred, near-full-width
   reel. The frame keeps the site's grammar — square corners, one hairline
   border, no shadow.
   ========================================================================== */
.eng-reelband{
  display:grid;
  grid-template-columns:1fr minmax(280px,380px);
  gap:var(--space-6);
  align-items:center;
  padding:0 var(--space-4) var(--space-8);
}
.eng-reelband__copy{ max-width:52ch; }
.eng-reelband__title{ font-size:clamp(22px,2.6vw,28px); margin:0 0 var(--space-2); }
.eng-reelband__dek{ font-size:15px; color:var(--color-muted); margin:0 0 var(--space-3); }
/* a.-qualified: GP's .inside-article a (0-1-1) beats a bare class. */
a.eng-reelband__link{ color:var(--color-accent-700); font-size:14px; font-weight:600; text-decoration:underline; text-underline-offset:3px; min-height:44px; display:inline-flex; align-items:center; }
a.eng-reelband__link:hover,
a.eng-reelband__link:focus{ color:var(--color-accent-900); }
.eng-reelframe{
  aspect-ratio:9/16;
  width:100%;
  /* When the height cap bites, the width must shrink with it or aspect-ratio
     silently loses to the grid track and the reel turns square — measured on
     staging (380×390). 0.5625 = 9/16. */
  max-height:78vh;
  max-width:calc(78vh * 0.5625);
  margin:0 0 0 auto;
  border:1px solid var(--color-divider);
  background:var(--color-surface);
  overflow:hidden;
}
.eng-reelframe iframe{ width:100%; height:100%; display:block; border:0; }
@media (max-width:767px){
  .eng-reelband{ grid-template-columns:1fr; gap:var(--space-4); }
  .eng-reelframe{ max-width:min(420px,92vw); margin:0 auto; }
}

/* ==========================================================================
   §6.19 The rooms showcase
   (markup + data: inc/cloudbeds.php, appended to partner write-ups)

   One card per room type: the property's own photograph, then the name, the
   description, the facts and the nightly rate underneath it. Nothing is drawn
   over the photograph and nothing framed around it, per the standing direction
   of 2026-08-21.

   EVERY SELECTOR HERE IS SCOPED UNDER .eng-rooms, and that is not style — it is
   required. This section is appended inside the_content, so it renders inside
   `.entry-content`, whose element rules (`.entry-content p`, `.entry-content h3`
   — specificity 0,1,1) outrank a lone class (0,1,0). Written unscoped, every
   `margin:0` below lost: each element kept a 12-16px bottom margin on top of the
   grid gap, the room name rendered 20px against a 22px section heading, and the
   card rhythm came out of the theme rather than out of this file.
   ========================================================================== */

.eng-rooms{
  margin-top:var(--space-8);
  /* Bottom margin as well as top: this block sits INSIDE the article now, at the tail of
     the write-up's own rooms section, so the heading that follows it needs the same air
     the block was given above. */
  margin-bottom:var(--space-8);
  padding-top:var(--space-6);
  border-top:1px solid var(--color-divider);
  /* The hub's "View rooms" button links straight to #eng-rooms. Same offset convention as
     .eng-splithero__anchor, so the heading clears the sticky rail instead of landing
     underneath it. */
  scroll-margin-top:calc(var(--rail-top) + var(--space-4));
}
.eng-rooms .eng-rooms__title{ margin:0 0 var(--space-2); }
.eng-rooms .eng-rooms__note{
  margin:0 0 var(--space-6);
  color:var(--color-muted);
  font-size:14px;
  max-width:60ch;
}
.eng-rooms__grid{
  display:grid;
  grid-template-columns:repeat(auto-fill, minmax(260px, 1fr));
  gap:var(--space-6);
}

.eng-room{
  display:grid;
  /* SIX slots: media, name, description, facts, rate, button. Every one is emitted
     even when empty (see eng_cb_sc_rooms) — a room with no rate would otherwise put
     its button on its neighbour's rate line and pull the whole row crooked. */
  grid-template-rows:auto auto auto auto auto auto;
  gap:var(--space-2);
  align-content:start;
}
@supports (grid-template-rows:subgrid){
  .eng-rooms__grid{ grid-auto-rows:auto; }
  .eng-room{ grid-row:span 6; grid-template-rows:subgrid; }
}

.eng-rooms .eng-room__media{
  /* A crop box, not a frame: no border, no radius, no shadow. The ratio keeps a row
     of rooms even when the property's photographs are not all one shape. */
  aspect-ratio:4 / 3;
  overflow:hidden;
  background:var(--color-surface);
}
.eng-rooms .eng-room__media--empty{
  display:flex;
  align-items:center;
  justify-content:center;
}
.eng-rooms .eng-room__mark{ opacity:.28; }
.eng-rooms .eng-room__img{
  width:100%;
  height:100%;
  object-fit:cover;
  display:block;
}
.eng-rooms .eng-room__name{
  margin:0;
  font-size:18px;
  line-height:1.2;
}
.eng-rooms .eng-room__desc{
  margin:0;
  color:var(--color-muted);
  font-size:14px;
}
.eng-rooms .eng-room__facts{
  margin:0;
  color:var(--color-muted);
  font-size:13px;
}
.eng-rooms .eng-room__rate{
  margin:0;
  font-size:16px;
  font-weight:600;
}
/* A room with no bookable base rate on the sampled dates. Muted and lighter than a
   real figure, so a scan down the column never mistakes it for a price. */
.eng-rooms .eng-room__rate-none{
  color:var(--color-muted);
  font-weight:400;
  font-size:14px;
}
.eng-rooms .eng-room__cta{ margin:0; }
.eng-rooms .eng-room__cta > .eng-btn{
  min-height:44px;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  /* `.entry-content a` underlines every link in the prose, which is right for prose and
     wrong for a filled button — it rendered "Check availability" underlined inside its
     own solid block. A button is not a link in a sentence. */
  text-decoration:none;
}

@media (max-width:480px){
  /* One room at a time, and a full-width target: at this width a two-up grid leaves
     each photograph too small to judge a room by. */
  .eng-rooms__grid{ grid-template-columns:1fr; }
  .eng-rooms .eng-room__cta > .eng-btn{ width:100%; }
}

/* ==========================================================================
   §6.21 Legacy pages — the pages built before the design system
   (page list + body class: inc/legacy-pages.php · folds: assets/js/eng-legacy.js)

   WHAT THIS SECTION IS FOR. Eight pages predate the current theme and were
   hand-built in GenerateBlocks, with alignment, type and spacing typed in per
   block. Explore is the extreme case, and every number below was measured on it
   at 390px before anything here existed:

     · 28,005px tall — 33.2 screens of scrolling
     · six section headings, all centred, all `text-transform:capitalize`
     · 27 nodes at 13px, set with !important by the small-font-size preset
     · 17 paragraphs and list items centred on mobile by per-block rules
     · `.gbp-section` padding of 7rem (112px) desktop, 4rem (64px) mobile
     · `.gb-card-modern` — the class on all nineteen cards — with ZERO rules
       anywhere in the build, so the "cards" were undecorated divs

   The palette was already right: theme.json's --palm-green and --tropical-teal
   are #0A6572 (= --color-accent-700), --island-navy is #084F59 (= -800) and
   --coral-orange is #0C7C89 (= -600). Nothing here recolours anything. The
   defects are structural — alignment, scale, rhythm, and the sheer height.

   NOTHING HERE TOUCHES CONTENT. Every rule is a presentation override on markup
   the owner wrote, reached through the `eng-legacy` body class. The two folds
   are DOM moves in eng-legacy.js, never rewrites. The page keeps its 32
   headings, its 53 links (21 of them 12go.asia affiliate urls, four carrying
   the tracking id) and all 34 images whether or not any of this loads.

   SPECIFICITY IS THE POINT, NOT AN ACCIDENT. GenerateBlocks writes per-block
   rules as single hashed classes — `.gb-text-2f653f54`, `.gb-element-d8aae077`
   — at 0,1,0, some inside `@media` blocks. Scoping under
   `.eng-legacy .entry-content` puts every rule below at 0,2,1 or higher, which
   beats them regardless of source order or media query. Drop either half of
   that prefix and the block silently loses.
   ========================================================================== */

/* --- Section rhythm ------------------------------------------------------ */

/* 112px of padding above and below each band is a landing-page gesture on a
   3,825-word guide; at six bands it was over a thousand pixels of nothing. The
   horizontal 40px went too — `.site-content` already owns the gutter, so it was
   being paid twice and pinching the measure. */
.eng-legacy .entry-content .gbp-section{ padding:var(--space-8) 0; }

.eng-legacy .entry-content .gbp-section__inner{
  column-gap:var(--space-6);
  row-gap:var(--space-6);
  margin-bottom:var(--space-4);
}

/* The day-card grid. GenerateBlocks pins these at three or four fixed columns
   and drops to ONE at 1024px, so a tablet showed fifteen full-width cards in a
   column. auto-fit tracks the width instead: four across at 1200px, two on a
   tablet, one on a phone, with no breakpoint list to keep in sync.

   :has() is load-bearing here — it is what tells a grid of cards apart from the
   heading-and-intro row above it without naming a hashed class that changes
   whenever the block is re-saved. Where :has() is unsupported the GenerateBlocks
   layout stands, which is the layout that ships today. */
.eng-legacy .entry-content .gbp-section__inner:has(> .gb-card-modern){
  grid-template-columns:repeat(auto-fit, minmax(240px, 1fr));
  margin-bottom:0;
}

/* --- Cards --------------------------------------------------------------- */

/* `.gb-card-modern` had no rules at all, in any stylesheet. Nineteen "cards"
   were bare divs, which is why the page read as one undifferentiated column.
   Same treatment as every other card in this theme: tinted ground, hairline,
   square corners, no shadow. */
.eng-legacy .entry-content .gb-card-modern{
  display:flex;
  flex-direction:column;
  background:var(--color-surface);
  border:1px solid var(--color-divider);
}
.eng-legacy .entry-content .gb-card-modern > div{ padding:var(--space-4); }

/* The card photograph. GenerateBlocks left these at `width:auto`, so a 320px
   source sat in a wider card with a ragged strip of ground beside it, and the
   2rem below each one was 32px of air fifteen times over. A fixed ratio makes a
   row of cards line up even though the source images are not one shape. */
.eng-legacy .entry-content .gb-card-modern > img{
  display:block;
  width:100%;
  aspect-ratio:4 / 3;
  object-fit:cover;
  margin-bottom:0;
}

/* --- Type ---------------------------------------------------------------- */

/* Centred and capitalised is the house style of a template, not of this site.
   `capitalize` also mangles the copy it is given — "Getting To El Nido". */
.eng-legacy .entry-content h2,
.eng-legacy .entry-content h3,
.eng-legacy .entry-content h4{
  text-align:left;
  text-transform:none;
}
/*
 * Body copy, same argument. Seventeen nodes were centred on a phone and thirteen on
 * a 1400px screen — including the BULLETS inside the day cards, which inherit
 * `text-align:center` from a wrapper. Centred body copy gives every line a different
 * left edge, and that edge is the thing an eye uses to find the next line; on a
 * bulleted list it also detaches each item from its own marker.
 *
 * This was briefly scoped to `@media (max-width:767px)`, which fixed the phone and
 * left the desktop bullets centred. It is not a mobile problem.
 *
 * Anything the author centred DELIBERATELY carries `has-text-align-center` — two
 * paragraphs on Explore do — and is left exactly as written.
 */
.eng-legacy .entry-content p:not(.has-text-align-center),
.eng-legacy .entry-content li,
.eng-legacy .entry-content ul,
.eng-legacy .entry-content ol{ text-align:left; }

.eng-legacy .entry-content h2{ font-size:var(--type-h2-section); }
.eng-legacy .entry-content h3{ font-size:var(--type-h3-card); }
.eng-legacy .entry-content h4{ font-size:18px; }

/* 13px, set by the small-font-size preset with !important, across 27 nodes —
   most of them the itinerary bullets, which are the part people read most
   closely. Matching that !important is the only way past it; a plain
   declaration loses at any specificity. */
.eng-legacy .entry-content .has-small-font-size{ font-size:15px !important; }

/*
 * Measure. This page carries GeneratePress's `full-width-content` layout, chosen
 * per-page by the owner, so prose inherits the whole viewport: measured at 1400px,
 * 45 separate paragraphs and lists were running 1,308-1,340px wide — 160 characters
 * a line, about double what an eye tracks back from without losing its place.
 *
 * Capped everywhere, then released inside the two places a column already does the
 * job: cards, which are 378px wide, and media-text, whose text sits in its own half.
 * Capping those as well would gain nothing and could leave a short card marooned
 * beside its neighbour. Prose in a narrow left column beside full-width images and
 * card grids is what a magazine page does; it is not an unfinished one.
 *
 * An earlier version of this rule used the child combinator and was inert — every
 * paragraph on the page is nested at least two levels down, so `> p` matched nothing
 * at all and the 160-character lines survived it untouched.
 */
.eng-legacy .entry-content p,
.eng-legacy .entry-content ul,
.eng-legacy .entry-content ol{ max-width:72ch; }

.eng-legacy .entry-content .gb-card-modern p,
.eng-legacy .entry-content .gb-card-modern ul,
.eng-legacy .entry-content .gb-card-modern ol,
.eng-legacy .entry-content .wp-block-media-text p,
.eng-legacy .entry-content .wp-block-media-text ul,
.eng-legacy .entry-content .wp-block-media-text ol{ max-width:none; }

/* --- Separators, buttons, figures ---------------------------------------- */

.eng-legacy .entry-content hr.wp-block-separator{
  border:0;
  border-top:1px solid var(--color-divider);
  margin:var(--space-8) 0;
  opacity:1;
}

.eng-legacy .entry-content .eng-btn{
  min-height:44px;
  justify-content:center;
  /* `.entry-content a` underlines every link, which is right in prose and wrong
     inside a filled button. */
  text-decoration:none;
}

/* The tour cards carry two buttons side by side and the blocks were authored with
   nothing between them: two solid accent rectangles touching edge to edge read as one
   wide button with a line of text wrapped inside it, and on a phone — where they are
   full width and stacked — even more so. */
.eng-legacy .entry-content .eng-btn + .eng-btn{ margin-left:var(--space-2); }

.eng-legacy .entry-content figure.wp-block-image{ margin:var(--space-4) 0; }
.eng-legacy .entry-content figure.wp-block-image img{
  display:block;
  width:100%;
  height:auto;
}

/* Two galleries in "Private/Custom Island Tours and Expeditions" sit directly above
   a paragraph with nothing between them: the wrapping div has no padding, the
   gallery's own margin-bottom is 0, and the paragraph's margin-top is 0 — measured
   gap 0px, gallery butting straight into its own caption text. WordPress's
   `.wp-block-gallery.has-nested-images figure.wp-block-image{ margin:0 }` governs
   the gallery's internals, so the fix goes on the paragraph that follows it rather
   than on the gallery, which would fight that rule for no gain. Scoped to `p` (not
   the GenerateBlocks `.gb-text` class) because .gb-text applies to all block types
   including headings and buttons, making it unreliable as a text-only signal; a
   plain `<p>` is immune to scope creep if galleries appear before other block types
   elsewhere. The sibling combinator is what keeps this safe: the other four galleries
   on the page sit inside `.gb-card-modern` cards, already spaced by the card's own
   16px padding (measured gap 20px), and none of them has a text sibling immediately
   after it — so this can never add a second gap there. */
.eng-legacy .entry-content .wp-block-gallery + p{ margin-top:var(--space-4); }

/* --- The disclosures ----------------------------------------------------- */

/*
 * Two of them, both built by eng-legacy.js, both native <details> so that the
 * keyboard, the screen reader and Ctrl+F all work without a line of code:
 *
 *   .eng-legacy__fold        the hour-by-hour schedule inside a tour card
 *   .eng-legacy__fold--plan  a whole multi-day plan's grid of day cards
 *
 * Same marker convention as .eng-planner__travel-summary above, so a disclosure
 * on this page opens the way one on /plan/ does.
 */
.eng-legacy__fold{
  margin-top:var(--space-3);
  border-top:1px solid var(--color-divider);
}

/* The plan fold sits directly under its own heading and intro, which are its
   header already; a second rule there would read as a divider between two
   things rather than a lid on one. */
.eng-legacy__fold--plan{
  margin-top:0;
  border-top:0;
}

.eng-legacy__summary{
  display:flex;
  align-items:center;
  min-height:44px;
  /* The paragraph this can sit inside is centred on mobile by a per-block rule;
     a control that drifts to the middle of the card is harder to hit and harder
     to find twice. */
  text-align:left;
  font-family:var(--font-heading);
  font-size:15px;
  font-weight:600;
  color:var(--color-accent-800);
  cursor:pointer;
  list-style:none;
}
.eng-legacy__summary::-webkit-details-marker{ display:none; }
.eng-legacy__summary::marker{ content:""; }
.eng-legacy__summary::after{
  content:"+";
  margin-left:auto;
  padding-left:var(--space-3);
  font-size:18px;
  line-height:1;
}
.eng-legacy__fold[open] > .eng-legacy__summary::after{ content:"–"; }

.eng-legacy__foldbody{ padding-bottom:var(--space-2); }


/* --- Media-text bands ---------------------------------------------------- */

/*
 * The five mainland sections are `wp-block-media-text`, and at 390px they were the
 * tallest thing left on the page — 5,311px between them. WordPress pads the text
 * column by 8% a side, which inside an already-narrow column left a 278px measure:
 * about 38 characters, or half of what a line wants. Trading that padding for the
 * article's own gutter widens the measure and shortens the block at the same time.
 */
.eng-legacy .entry-content .wp-block-media-text__content{ padding:var(--space-4) 0; }

/*
 * Removing that 8% padding deleted the ONLY gutter between image and text, because
 * `.wp-block-media-text` is a grid with `column-gap: normal` (0px) — measured at
 * 1400px on all five blocks (three image-left, two `.has-media-on-the-right`):
 * `grid-template-columns: 670px 670px`, gap 0px, the text starting on the pixel the
 * photo ends. The gutter belongs on the grid, not on the child's padding, so it goes
 * back there as `column-gap`, which a flip of `has-media-on-the-right` cannot break —
 * gap applies to the tracks, not to which block occupies which one, so both
 * directions get the same 32px. WordPress sizes the columns `50% 1fr`, so the `1fr`
 * (content) track absorbs it without the block overflowing.
 *
 * `row-gap` rides the same declaration and does different work: at
 * `is-stacked-on-mobile` widths the block becomes one column and two rows, so
 * `column-gap` goes inert there and `row-gap` becomes the photo-to-heading gap
 * instead. That gap measured 16px — the content box's own top padding above, with
 * nothing ahead of it — which is tight between a photograph and the heading under
 * it. 16px of `row-gap` plus the existing 16px of content padding totals 32px,
 * without doubling either token or touching the 330px stacked measure the 8%
 * removal was for.
 */
.eng-legacy .entry-content .wp-block-media-text{ gap:var(--space-4) var(--space-6); }

/* --- Tables -------------------------------------------------------------- */

/*
 * The comparison table declared `is-style-stripes` and rendered without any: every
 * cell measured transparent with a transparent border, so it read as loose columns
 * of text. Hairlines and a tinted band, in the same idiom as every other table in
 * the theme — and a scroll container, because a multi-column table cannot be made to
 * fit 390px without either shrinking the type or lying about the layout.
 */
.eng-legacy .entry-content figure.wp-block-table{ overflow-x:auto; }
.eng-legacy .entry-content table{ width:100%; border-collapse:collapse; }
.eng-legacy .entry-content th,
.eng-legacy .entry-content td{
  border:1px solid var(--color-divider);
  padding:var(--space-2) var(--space-3);
  text-align:left;
  font-size:15px;
  vertical-align:top;
}
.eng-legacy .entry-content thead th{
  background:var(--color-surface);
  font-family:var(--font-heading);
  font-weight:600;
}
.eng-legacy .entry-content .is-style-stripes tbody tr:nth-child(odd) td{
  background:var(--color-surface);
}

/* --- Third party: the 12go.asia search widget ---------------------------- */

/*
 * Two of these sit in the "Getting to El Nido" section. They are injected by 12go's
 * script AFTER load — which is why a scan of the served HTML finds nothing and only
 * a live measurement does — and they arrive dressed in someone else's design system:
 *
 *   header and submit  rgb(48, 171, 224)   a blue that appears nowhere else here
 *   inputs and buttons 5px radius, an inset shadow, a 34px hit target
 *   wrapper            background:#FFFFFF written as an inline style attribute
 *
 * They are also affiliate forms carrying the tracking id, so they get repainted, not
 * removed. Everything below is a presentation override on markup this site does not
 * own: no script is patched and no url is touched.
 *
 * WHY SO MANY !important. Specificity alone was not enough, and that was measured
 * rather than assumed: after a pass without them, `height` had gone from 34px to 44px
 * while `background`, `border`, `border-radius` and `box-shadow` on the SAME elements
 * had not moved at all. One selector winning for one property and losing for four
 * means the loss is not specificity — 12go's own stylesheet marks its colour and
 * shape !important, and !important is the only thing that answers it. The wrapper is
 * a separate case again: its white ground is an inline style attribute, which nothing
 * but !important outranks. Everything unmarked below won on specificity and is left
 * unmarked, so the file still says which battles were real.
 */
.eng-legacy .entry-content .one2go{
  background:var(--color-surface) !important;
  border:1px solid var(--color-divider);
}
.eng-legacy .entry-content .one2go .one2goheader{
  background:var(--color-accent-800) !important;
}
.eng-legacy .entry-content .one2go .o2gcaption{
  font-family:var(--font-heading);
  font-weight:600;
  color:#fff;
}

/* 34px is below the 44px minimum this theme holds every control to, and `height` is
   set outright rather than as a minimum — so it has to be answered in kind. */
.eng-legacy .entry-content .one2go .o2gform-control,
.eng-legacy .entry-content .one2go .o2gbtn{
  height:44px;
  min-height:44px;
  border:1px solid var(--color-divider) !important;
  border-radius:0 !important;
  box-shadow:none !important;
  background:#fff !important;
  color:var(--color-text);
  font-family:var(--font-body);
  font-size:15px;
}
.eng-legacy .entry-content .one2go .o2ggo{
  height:44px;
  min-height:44px;
  border-radius:0 !important;
  background:var(--color-accent) !important;
  color:#fff;
  font-family:var(--font-heading);
  font-weight:600;
}
.eng-legacy .entry-content .one2go .o2ggo:is(:hover,:focus){
  background:var(--color-accent-800) !important;
}

/* --- Mobile -------------------------------------------------------------- */

@media (max-width:767px){
  .eng-legacy .entry-content .gbp-section{ padding:var(--space-6) 0; }

  /* A phone shows one card at a time whatever the track maths says. */
  .eng-legacy .entry-content .gbp-section__inner:has(> .gb-card-modern){
    grid-template-columns:1fr;
  }

  .eng-legacy .entry-content .eng-btn{ width:100%; }
  .eng-legacy .entry-content .eng-btn + .eng-btn{
    margin-left:0;
    margin-top:var(--space-2);
  }
}

/* ==========================================================================
   §6.22 Contact — /contact-us/
   (markup + mail: inc/contact.php · enhancement: assets/js/eng-contact.js)

   WHAT IS ADDED HERE, AND WHY SO LITTLE. inc/contact.php already builds every control
   with `.eng-field` markup (assets/css/30-components.css §3.4), which is where the
   uppercase-tracked label, the hairline-bordered input and the 44px floor all come from —
   none of that is repeated below. What is genuinely missing is: a two-column arrangement
   for the form to sit beside the page's existing "Get in touch" details (the email address
   and Facebook link already on /contact-us/, which this task does not touch), the
   honeypot's off-screen hiding, and the success/error banner's colouring — using the
   status tokens the design system already defines rather than inventing a second red and
   a second green.
   ========================================================================== */

/*
 * Two columns, but ONLY when `.eng-contact` actually holds two children. inc/contact.php's
 * own shortcode output is always a single child (the form) — the existing "Get in touch"
 * details live in the page's own content, outside this file's reach, and whoever places
 * both side by side (a Columns block, or a container carrying this class) supplies the
 * second child. Without the :has() guard a lone form would still be laid out as column 1
 * of a two-column grid, leaving an empty, invisible-but-space-consuming column 2 — the
 * form rendering at half width for no reason. Same technique as
 * `.gbp-section__inner:has(> .gb-card-modern)` above (§6.21).
 */
.eng-contact:has(> :nth-child(2)){
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:var(--space-8);
  align-items:start;
}

.eng-contact-form{
  display:flex;
  flex-direction:column;
  gap:var(--space-4);
  max-width:520px;
}

.eng-contact-form button[type="submit"]{
  align-self:flex-start;
  min-height:44px;
}

/* .eng-hp (the honeypot wrapper inc/contact.php renders) is already defined in
   assets/css/55-integrations.css — position:absolute; left:-9999px; height:0;
   overflow:hidden. Do not re-add a rule for it here: stylesheets enqueue alphabetically,
   so 55-integrations.css loads AFTER this file and would silently win/override anyway. */

/* The shared live region eng-contact.js writes into, and that inc/contact.php's own
   redirect fills on a no-JS submit. Coloured only via the status tokens the design system
   already defines — no new colour is introduced here. */
.eng-contact__result{
  padding:var(--space-3) var(--space-4);
  border:1px solid var(--color-divider);
  font-size:14px;
}
.eng-contact__result--success{
  background:var(--color-success-bg);
  border-color:var(--color-success);
  color:var(--color-success);
}
.eng-contact__result--error{
  background:var(--color-danger-bg);
  border-color:var(--color-danger-border);
  color:var(--color-danger);
}

/* A field the last submission flagged. Matches .eng-plan-resume's own rule
   (this file, Task 6) so an invalid control reads the same way everywhere in the theme. */
.eng-contact-form [aria-invalid="true"]{ border-color:var(--color-danger); }

/*
 * The page-level two-column wrapper: form beside the contact details.
 *
 * A SEPARATE class from `.eng-contact` above, deliberately. The shortcode already emits
 * `.eng-contact` around the form, so reusing that class on the page wrapper would nest
 * `.eng-contact` inside `.eng-contact` with two different meanings — the outer one a
 * layout grid, the inner one a form container — and the next person to read either rule
 * would have to work out which was which. One class, one job.
 *
 * No :has() guard is needed here because this class is only ever written by
 * deploy/contact-rebuild.php onto a wrapper that holds exactly two children. If a third
 * is ever added the grid simply gains a row, which is the sane outcome.
 */
.eng-contact-page{
  display:grid;
  /* Capped, not full-bleed. The page runs `full-width-content`, so an uncapped grid gave
     the form column 1000px to hold a 520px form — 480px of dead ground between the fields
     and the details card, measured on staging. 1000px total puts the form column at 632px,
     which is a comfortable width to type into and leaves the card beside it, not adrift. */
  max-width:1000px;
  grid-template-columns:minmax(0,1fr) minmax(0,320px);
  gap:var(--space-8);
  align-items:start;
}

/* Inside the two-column page the column already provides the measure, so the form's own
   520px cap would only reintroduce the gap it was meant to prevent. It still applies
   wherever the shortcode is used on its own. */
.eng-contact-page .eng-contact-form{ max-width:none; }

/* The details column: email, Facebook, and what to expect after sending. Same card idiom
   as every other card in the theme — tinted ground, hairline, square corners. */
.eng-contact-details{
  background:var(--color-surface);
  border:1px solid var(--color-divider);
  padding:var(--space-4);
}
.eng-contact-details h2{ margin-top:0; font-size:var(--type-h3-card); }
.eng-contact-details p{ margin:0 0 var(--space-3); font-size:15px; }
.eng-contact-details p:last-child{ margin-bottom:0; }
.eng-contact-details__label{
  display:block;
  font-size:12px;
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--color-muted);
}

/* The hero. A solid accent band rather than text over the banner photograph: this page's
   sibling /about-us/ shipped white type over a background that failed to load, leaving the
   heading invisible on cream, and the same failure mode is available here. A band cannot
   fail that way. The banner image is kept, below the band, where it is decoration rather
   than a contrast dependency. */
.eng-contact-hero{
  background:var(--color-accent-800);
  color:#fff;
  padding:var(--space-8) var(--space-6);
  margin-bottom:var(--space-6);
}
.eng-contact-hero h1{ margin:0 0 var(--space-3); color:#fff; }
.eng-contact-hero p{ margin:0; max-width:60ch; color:#fff; opacity:.92; }
/* A band, not a wall. At its natural 1640x924 this photograph rendered 771px tall on a
   1400px screen and pushed the form entirely below the fold — the one thing the page exists
   to show. Cropping to 16:5 keeps it as the decoration it is. */
.eng-contact-banner{
  display:block;
  width:100%;
  aspect-ratio:16 / 5;
  object-fit:cover;
  margin-bottom:var(--space-8);
}

@media (max-width:767px){
  .eng-contact:has(> :nth-child(2)){ grid-template-columns:1fr; }
  .eng-contact-page{ grid-template-columns:1fr; gap:var(--space-6); }
  .eng-contact-hero{ padding:var(--space-6) var(--space-4); }
}

/* ==========================================================================
   §6.23 About — /about-us/
   (content: deploy/about-rebuild.php · page id 122)

   WHY THIS PAGE HAS A REBUILD SECTION INSTEAD OF A RESTYLE. Measured live at 1400px
   before this shipped: the <h1> "Discover El Nido" was inline white text on the cream
   page background with no image behind it — invisible; the subtitle sat at x = 0,
   outside the page gutter; the lead image carried an inline border-radius; the two
   feature icons were an inline off-palette green. All four were per-block
   GenerateBlocks settings baked into that page's own post_content, not anything this
   stylesheet could reach — a CSS override can only mask an inline style, never remove
   it. deploy/about-rebuild.php replaces the block markup with the plain
   `eng-about__*` HTML below, keeping every heading, image and word verbatim.

   Every colour, spacing and type value below is a token from 00-tokens.css; no
   border-radius, box-shadow or gradient appears anywhere in this section.
   ========================================================================== */

.eng-about{
  display:flex;
  flex-direction:column;
  gap:var(--space-8);
}

/* --- Hero ------------------------------------------------------------ */

/*
 * A solid --color-accent-800 band behind "Discover El Nido", not the hero photo
 * behind the words. That is the exact failure being fixed — the old page's heading
 * was already meant to sit on something, and nothing was ever there. Putting the
 * photo in its own column instead of behind the text removes the possibility of a
 * repeat: a photo can be re-cropped or swapped later without ever touching contrast.
 *
 * white (#fff) on --color-accent-800 (#084F59) measures 9.25:1 by the WCAG relative-
 * luminance formula — clears AA (4.5:1) and AAA (7:1) for any text size with margin.
 */
.eng-about__hero{
  display:grid;
  grid-template-columns:1fr;
  background:var(--color-accent-800);
}
.eng-about__hero-copy{
  padding:var(--space-6) var(--space-4);
  color:#fff;
}
.eng-about__h1{
  margin:0 0 var(--space-2);
  font-family:var(--font-heading);
  font-size:var(--type-h1-page);
  line-height:1.1;
  color:#fff;
}
.eng-about__subtitle{
  margin:0;
  font-family:var(--font-body);
  font-weight:400;
  font-size:var(--type-h2-section);
  line-height:1.3;
  color:#fff;
}
.eng-about__hero-img{
  display:block;
  width:100%;
  height:100%;
  aspect-ratio:4 / 3;
  object-fit:cover;
}

@media (min-width:768px){
  .eng-about__hero{ grid-template-columns:1fr 1fr; align-items:stretch; }
  .eng-about__hero-copy{
    display:flex;
    flex-direction:column;
    justify-content:center;
    padding:var(--space-8);
  }
}

/* --- Body gutter ------------------------------------------------------ */

/* One gutter declaration for every section after the full-bleed hero band, rather
   than repeating `padding:0 var(--space-4)` on each of the five sections it holds.
   Same reasoning as .engx in 55-integrations.css: .site-content already owns the
   outer container, this only keeps content off its edge on phones. */
.eng-about__body{
  display:flex;
  flex-direction:column;
  gap:var(--space-8);
  padding:0 var(--space-4);
}

/* --- Prose blocks (About Us / Our Mission / About El Nido / Guide / Welcome) --- */

.eng-about__block{
  display:flex;
  flex-direction:column;
  gap:var(--space-3);
  padding-bottom:var(--space-6);
  border-bottom:1px solid var(--color-divider);
}
.eng-about__block:last-child{ border-bottom:0; padding-bottom:0; }

.eng-about__intro{
  display:flex;
  flex-direction:column;
  gap:var(--space-4);
}
.eng-about__label{
  margin:0 0 var(--space-1);
  font-family:var(--font-heading);
  font-size:var(--type-h3-card);
  color:var(--color-text);
}
.eng-about__block p,
.eng-about__intro p{
  margin:0;
  font-size:var(--type-body);
  color:var(--color-text);
}
.eng-about__cta a{
  color:var(--color-accent-700);
}
.eng-about__cta a:hover{ color:var(--color-accent-800); }

.eng-about__h2{
  margin:0 0 var(--space-2);
  font-family:var(--font-heading);
  font-size:var(--type-h2-section);
  color:var(--color-text);
}
.eng-about__tagline{
  margin:0 0 var(--space-4);
  font-family:var(--font-heading);
  font-size:var(--type-h3-card);
  font-weight:600;
  color:var(--color-muted);
}

/* Every supporting photograph in the body. The crop matches §6.21's card images exactly
   — block, full width, 4:3, object-fit:cover — so a photograph reads the same on either
   page. The hairline is NOT the same arrangement, and the difference is deliberate: §6.21
   borders the card CONTAINER and leaves its image unbordered, because there the frame
   belongs to the card. These photographs stand on their own with no card around them, so
   the hairline has to sit on the image itself or there is none at all. */
.eng-about__figure{ margin:0; }
.eng-about__img{
  display:block;
  width:100%;
  aspect-ratio:4 / 3;
  object-fit:cover;
  border:1px solid var(--color-divider);
}
.eng-about__figure--closing{ max-width:640px; margin:0 auto; }

/* --- Experience Paradise cards ----------------------------------------- */

/* Mobile-first: one column at 390px, two once a phone has the width to spare, four
   once there is room for the whole row — same tinted-surface, hairline-border card
   as .eng-stay (§6.13) and .gb-card-modern (§6.21). */
.eng-about__cards{
  display:grid;
  grid-template-columns:1fr;
  gap:var(--space-4);
  margin-top:var(--space-4);
}
.eng-about__card{
  background:var(--color-surface);
  border:1px solid var(--color-divider);
  padding:var(--space-4);
}
.eng-about__card-title{
  margin:0 0 var(--space-2);
  font-family:var(--font-heading);
  font-size:var(--type-h3-card);
  color:var(--color-text);
}
.eng-about__list{
  margin:0;
  padding-left:var(--space-4);
  font-size:var(--type-body);
  color:var(--color-muted);
}
.eng-about__list li + li{ margin-top:var(--space-1); }

.eng-about__experience-media{
  display:grid;
  grid-template-columns:1fr;
  gap:var(--space-4);
  margin-top:var(--space-6);
}

@media (min-width:480px){
  .eng-about__cards{ grid-template-columns:repeat(2, 1fr); }
}
@media (min-width:768px){
  .eng-about__cards{ grid-template-columns:repeat(4, 1fr); }
  .eng-about__experience-media{ grid-template-columns:1fr 1fr; }
}

/* --- Discover — closing band --------------------------------------------- */

.eng-about__closing{
  display:flex;
  flex-direction:column;
  gap:var(--space-4);
  text-align:center;
}
.eng-about__closing .eng-about__h2{ text-align:center; }
