
/* Guide resource component — SINGLE SOURCE (2026-09-08, owner brief). tools/build-guide-pdfs.py writes this into every
   region that renders guides. Two parts, one design:
     .grs-frame  — GuideCollectionFrame: the ONE outer holding frame (the approved featured-panel language: pale surface,
                   hairline border, 18px radius, content width) around a guide set. Count variants: --single (one guide
                   or the route finder, the wide 240px-cover geometry), --pair (two equal entries side by side, one quiet
                   vertical rule), --grid (four entries as a 2 × 2 grid with shared internal rules). Entries never carry
                   a card of their own — the frame is the card; entries are columns divided by rules.
     .grc        — GuideResourceItem: cover (real first page, whole, contain, in a pale media field) · title · summary ·
                   metadata · action. Never a mockup, never cropped, never a thumbnail.
   Action variants change the CTA only: --primary (dark pill, download), --route (tracked text link, live tool).
   Tokens only; both themes. The stacked / .grs-list vertical-stack variants are retired (2026-09-08). */
.grs { padding: 96px 0; border-top: 1px solid var(--line-soft); }
/* featured-guide heading measure (2026-09-07): the wrap falls after "before" — "they file" stays together; no <br>, no nbsp */
/* No 36rem cap: it broke "The free-zone decision, in one guide" across two lines with the last three
   words orphaned (owner, 2026-09-10). The wrap is the constraint; the heading wraps naturally on narrow
   viewports. `balance` keeps a genuinely long heading from leaving one short trailing line. */
.grs--featured .sec-head h2 { max-inline-size: none; text-wrap: balance; }
.grs .sec-head { margin-bottom: 28px; }
/* ---- GuideCollectionPanel (.grs-panel, 2026-09-09 owner brief) ----
   Every TWO-guide set renders inside ONE outer holding panel that carries the section's own heading and lede and then
   the pair frame — the composition the owner approved on uae-dubai ("Get clear on your options"). The copy is page-
   specific (guide-cards.json › pages[page].heading / lede); the structure is not. Hairline, 16px radius, a 3% lift
   from the control-surface token in both themes; the heading measure and type match the page section heads. */
.grs-panel { box-sizing: border-box; padding: 40px; border: 1px solid var(--line-soft); border-radius: 16px; background: var(--control-surface); }
.grs-panel .sec-head { max-width: 720px; margin: 0 0 28px; }
.grs-panel .sec-head h2 { margin: 0 0 12px; font-size: clamp(26px, 3vw, 34px); line-height: 1.15; letter-spacing: -.02em; font-weight: 500; color: var(--text); }
.grs-panel .sec-head p { margin: 0; font-size: 15px; line-height: 1.6; color: var(--muted); }
@media (max-width: 720px) { .grs-panel { padding: 24px 20px; border-radius: 14px; } .grs-panel .sec-head { margin-bottom: 22px; } }
/* ---- GuideCollectionFrame ---- */
.grs-frame { box-sizing: border-box; border: 1px solid var(--line); border-radius: 18px; background: var(--surface); transition: border-color .2s, transform .2s; }
.grs-frame:has(> .grc:hover) { border-color: var(--line-strong); }
.grs-frame--single { padding: 32px 40px; }
/* The frame does NOT move on hover (owner, 2026-09-10: "on mouse over makes the whole section move").
   A 2px lift on a full-width panel reads as the section jumping; the border tightening above is the
   affordance, and the CTA keeps its own micro-shift. */
/* scale (owner brief 2026-09-08, second pass): the pair is a "paired library shelf" — 46 × 44 padding, 180 × 260 media; the
   four-guide grid has its own collection density — 40px frame padding, 32px cell padding, 150 × 220 media, 260px row minimum */
.grs-frame--pair, .grs-frame--grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); grid-auto-rows: auto; row-gap: 0; --grs-rule-gap: 28px; --grs-row-gap: 32px; }
.grs-frame--pair { padding: 54px 46px; --grs-rule-gap: 46px; }   /* +8–10% (2026-09-08 third pass): document presence, not type scale */
.grs-frame--grid { padding: 32px; --grs-rule-gap: 28px; --grs-row-gap: 28px; }
/* one shared row system (2026-09-08 refinement): every entry spans the same four rows — title · summary · metadata ·
   action — through subgrid, so the pair (and each row of the 2 × 2 grid) aligns exactly, never two independently
   flowing columns. The divider is the frame's own line, running the full height of the shared rows. */
.grs-frame--pair > .grc, .grs-frame--grid > .grc { grid-row: span 4; grid-template-rows: subgrid; row-gap: 0; }
.grs-frame--pair .grc__body, .grs-frame--grid .grc__body { display: contents; }
.grs-frame--pair .grc__cover, .grs-frame--grid .grc__cover { grid-column: 1; grid-row: 1 / span 4; align-self: start; }   /* top-anchored with the title (2026-09-15, owner: uneven spacing on vn/index.html) */
.grs-frame--pair .grc__title, .grs-frame--grid .grc__title { grid-column: 2; grid-row: 1; align-self: start; padding-bottom: 12px; text-wrap: balance; }   /* start, not end: with shared subgrid rows an end-aligned title drops below its neighbour whenever one title wraps (Vietnam Corporate Income Tax vs Vietnam Zone Selection, 2026-09-15) */
.grs-frame--grid .grc__title { font-size: 24px; min-height: 0; padding-bottom: 8px; }
.grs-frame--pair .grc__desc, .grs-frame--grid .grc__desc { grid-column: 2; grid-row: 2; align-self: start; padding-bottom: 18px; }
.grs-frame--pair .grc__meta, .grs-frame--grid .grc__meta { grid-column: 2; grid-row: 3; align-self: start; padding-bottom: 10px; }
.grs-frame--pair .grc__action, .grs-frame--grid .grc__action { grid-column: 2; grid-row: 4; align-self: start; justify-self: start; margin-top: 12px; }
.grs-frame--grid > .grc { min-height: 0; }   /* content-led (2026-09-09): the enlarged cover sets the row, no reserved height */
.grs-frame--grid .grc__desc { font-size: 15px; line-height: 1.5; max-width: 36ch; min-height: 0; padding-bottom: 14px; }
.grs-frame--grid .grc__meta { font-size: 13px; line-height: 1.45; min-height: 0; padding-bottom: 16px; }
.grs-frame--grid .grc__action { margin-top: 0; }
/* the compact two-line metadata (pair/grid): "N pages · PDF" over "Last verified …" */
.grc__meta > span { display: block; }
.grc__meta > span + span { margin-top: 3px; }
.grs-frame--pair .grc__action--primary, .grs-frame--grid .grc__action--primary { min-width: 172px; justify-content: center; }
/* internal rules: the column gap is the divider's breathing room, not an inter-card gap */
.grs-frame--pair > .grc:nth-child(odd), .grs-frame--grid > .grc:nth-child(odd) { padding-inline-end: var(--grs-rule-gap); }
.grs-frame--pair > .grc:nth-child(even), .grs-frame--grid > .grc:nth-child(even) { padding-inline-start: var(--grs-rule-gap); border-inline-start: 1px solid var(--line); }
.grs-frame--grid > .grc:nth-child(-n+2) { padding-bottom: var(--grs-row-gap); }
.grs-frame--grid > .grc:nth-child(n+3) { padding-top: var(--grs-row-gap); border-top: 1px solid var(--line); }
/* ---- GuideResourceItem ---- */
.grc { display: grid; grid-template-columns: 198px minmax(0, 1fr); column-gap: 32px; align-items: center; min-width: 0; text-decoration: none; color: inherit; border-radius: 12px; }
.grs-frame--grid .grc { grid-template-columns: 160px minmax(0, 1fr); column-gap: 26px; --grc-frame-h: 212px; --grc-frame-pad: 8px; }   /* 2026-09-09 owner brief: the cover is a visual anchor (~30 % of the card), not a thumbnail — A4 at 212px tall = 150px wide inside a 160px field */
.grc:focus-visible { outline: 2px solid var(--focus-ring, var(--mineral)); outline-offset: 6px; }
/* inner media frame: a quiet stone presentation field around the cover — compact (148 × 200, the cover 128 wide with 10px of
   surround) in a pair/grid, wide (310) alone. Reduced 2026-09-08: excess beige removed, the cover itself unchanged. */
.grc { --grc-frame-h: 285px; --grc-frame-pad: 14px; }
.grc__cover { margin: 0; box-sizing: border-box; height: var(--grc-frame-h); padding: var(--grc-frame-pad); display: flex; align-items: center; justify-content: center; background: var(--surface-tinted); border: 1px solid var(--line-soft); border-radius: 12px; }
.grc__cover-img, .grc__cover-sheet { display: block; height: 100%; width: auto; max-width: 100%; aspect-ratio: 210 / 297; background: #F5F2EA; border-radius: 3px 5px 5px 3px; box-shadow: 0 0 0 1px var(--line-strong), 0 4px 12px rgba(0,0,0,.16); }
:root[data-theme="light"] .grc__cover-img, :root[data-theme="light"] .grc__cover-sheet { box-shadow: 0 0 0 1px var(--line), 0 4px 12px rgba(20,24,27,.10); }
.grc__cover-img { object-fit: contain; object-position: center; filter: none; }
.grc__cover-sheet { box-sizing: border-box; display: flex; flex-direction: column; justify-content: flex-end; padding: 8% 7%; color: #2F2A20; }   /* typographic sheet: stands in only while a resource has no cover file */
.grc__cover-mark { font-family: var(--mono, 'JetBrains Mono', monospace); font-size: 9.5px; letter-spacing: .16em; text-transform: uppercase; color: #6B655A; }
.grc__cover-title { margin-top: 8px; font-size: 17px; font-weight: 500; line-height: 1.2; letter-spacing: -.01em; }
.grc__body { display: flex; flex-direction: column; min-width: 0; gap: 10px; }
.grc__title { margin: 0; font-size: 26px; font-weight: 500; letter-spacing: -.02em; color: var(--text); line-height: 1.2; min-height: 2.4em; display: flex; align-items: flex-end; }   /* reserves two lines so both entries start the summary on the same line */
.grc__desc { margin: 0; font-size: 16.5px; color: var(--muted); line-height: 1.55; max-width: 44ch; min-height: 3.1em; }   /* two summary lines reserved */
.grc__meta { margin: 0; font-size: 13.5px; line-height: 1.5; color: var(--muted); min-height: 0; }   /* one line since 2026-09-09: "N pages · PDF · date" */
.grc__action { margin-top: 8px; align-self: flex-start; display: inline-flex; align-items: center; gap: 8px; text-decoration: none; }
.grc__action svg { width: 14px; height: 14px; flex: none; }
/* the single-guide entry keeps the wide featured geometry — the graphical source of truth */
.grs-frame--single > .grc { grid-template-columns: 220px minmax(0, 1fr); column-gap: 48px; min-height: 320px; --grc-frame-h: 292px; --grc-frame-pad: 14px; }   /* fourth pass (2026-09-08 advisor geometry): 220 × 292 field, 14px surround — the cover fills ~90% of its field; text 48px away, no right-hand desert */
/* Feature card footer (owner, 2026-09-11): metadata left, download CTA right, on ONE row. Only this
   variant — the --pair and --grid frames keep the CTA beneath their own metadata so the repeated
   cards stay symmetrical, and they set `display: contents` on the body so none of this reaches them.
   Grid areas rather than reordered markup: the DOM stays title → description → metadata → CTA, so
   reading order and tab order are unchanged. */
.grs-frame--single .grc__body {
  max-width: 560px;
  display: grid;
  /* Two content-width columns with a trailing spacer: the CTA sits directly AFTER the metadata
     rather than being pushed to the card's right edge, where it read as belonging to the empty half
     of the card instead of to the guide (owner, 2026-09-11). The 1fr absorbs what is left. */
  grid-template-columns: max-content max-content 1fr;
  grid-template-areas: "title title title" "desc desc desc" "meta cta .";
  align-items: center;
  row-gap: 14px;
  column-gap: clamp(28px, 2.5vw, 40px);
}
.grs-frame--single .grc__title { grid-area: title; font-size: clamp(24px, 2.4vw, 30px); line-height: 1.25; min-height: 0; display: block; }
.grs-frame--single .grc__desc { grid-area: desc; font-size: 16px; max-width: 52ch; line-height: 1.55; min-height: 0; }
.grs-frame--single .grc__meta { grid-area: meta; margin-top: 0; min-height: 0; min-width: 0; }
.grs-frame--single .grc__action { grid-area: cta; margin-top: 0; justify-self: start; align-self: center; }

/* Below the width where the row starts squeezing the metadata, stack deliberately — never shrink the
   CTA or truncate the date to keep one line. */
@media (max-width: 700px) {
  .grs-frame--single .grc__body { grid-template-columns: minmax(0, 1fr); grid-template-areas: "title" "desc" "meta" "cta"; row-gap: 12px; }
}
/* action variants */
.grc__action--primary { padding: 12px 22px; border-radius: 999px; background: var(--text); color: var(--bg); font-family: 'Inter Tight', 'Inter', sans-serif; font-size: 14px; font-weight: 500; transition: box-shadow .2s, transform .2s; }
.grc:hover .grc__action--primary { box-shadow: var(--shadow-action-hover, 0 6px 16px rgba(20,24,27,.18)); transform: translateX(2px); }
.grc__action--route { font-family: var(--mono, 'JetBrains Mono', monospace); font-size: 11.5px; letter-spacing: .14em; text-transform: uppercase; color: var(--mineral, #8FA4AC); }
.grc__action--route svg { transition: transform .2s; }
.grc:hover .grc__action--route svg { transform: translateX(4px); }
/* tablet: keep the shared frame and the side-by-side entries; tighten before changing layout */
@media (max-width: 1024px) { .grs-frame--pair, .grs-frame--grid { padding: 32px; --grs-rule-gap: 22px; --grs-row-gap: 26px; } .grc, .grs-frame--grid .grc { grid-template-columns: 150px minmax(0, 1fr); column-gap: 20px; --grc-frame-h: 215px; --grc-frame-pad: 11px; } .grs-frame--grid > .grc { min-height: 0; } .grc__title { font-size: 23px; } .grc__desc { font-size: 15.5px; } }
@media (max-width: 900px) { .grs-frame--single { padding: 28px; } .grs-frame--single > .grc { grid-template-columns: 200px minmax(0, 1fr); column-gap: 36px; --grc-frame-h: 266px; --grc-frame-pad: 12px; } }
/* mobile: ONE frame around every guide; entries stack inside it under a single horizontal rule each */
@media (max-width: 900px) {   /* 2026-09-09: the 2 × 2 collection stacks at tablet — two ~316px cells could not hold the enlarged cover
                                   and the copy without the grid overflowing; mirrors the 720px stack below (same :nth-child(n) reset the
                                   component already relies on to outrank its desktop column/row rules), keeping the 150px tablet cover */
  .grs-frame--grid { grid-template-columns: minmax(0, 1fr); row-gap: 0; padding: 28px; --grs-row-gap: 26px; }
  .grs-frame--grid > .grc { grid-row: auto; grid-template-rows: auto; }
  .grs-frame--grid .grc__body { display: flex; flex-direction: column; gap: 10px; }
  .grs-frame--grid .grc__cover { grid-row: auto; }
  .grs-frame--grid .grc__title, .grs-frame--grid .grc__desc, .grs-frame--grid .grc__meta { min-height: 0; padding-bottom: 0; align-self: stretch; }
  .grs-frame--grid .grc__title { display: block; }
  .grs-frame--grid .grc__action { margin-top: 8px; align-self: flex-start; }
  .grs-frame--grid > .grc:nth-child(n) { padding: 0; border: 0; }
  .grs-frame--grid > .grc:nth-child(n+2) { padding-top: var(--grs-row-gap); border-top: 1px solid var(--line-soft); }
  .grs-frame--grid > .grc:not(:last-child) { padding-bottom: var(--grs-row-gap); }
}
@media (max-width: 720px) {
  .grs { padding: 72px 0; }
  .grs-frame--single { padding: 24px; }
  .grs-frame--single > .grc { grid-template-columns: 1fr; row-gap: 22px; min-height: 0; --grc-frame-h: 226px; --grc-frame-pad: 10px; }
  .grs-frame--single .grc__cover { width: 170px; justify-self: start; }
  .grs-frame--single .grc__title { font-size: 24px; } .grs-frame--single .grc__desc { font-size: 15.5px; }
  .grs-frame--pair, .grs-frame--grid { grid-template-columns: minmax(0, 1fr); row-gap: 0; padding: 24px; --grs-row-gap: 24px; }
  .grs-frame--pair > .grc, .grs-frame--grid > .grc { grid-row: auto; grid-template-rows: auto; }
  .grs-frame--pair .grc__body, .grs-frame--grid .grc__body { display: flex; flex-direction: column; gap: 10px; }
  .grs-frame--pair .grc__cover, .grs-frame--grid .grc__cover { grid-row: auto; }
  .grs-frame--pair .grc__title, .grs-frame--grid .grc__title, .grs-frame--pair .grc__desc, .grs-frame--grid .grc__desc, .grs-frame--pair .grc__meta, .grs-frame--grid .grc__meta { min-height: 0; padding-bottom: 0; align-self: stretch; }
  .grs-frame--pair .grc__title, .grs-frame--grid .grc__title { display: block; }
  .grs-frame--pair .grc__action, .grs-frame--grid .grc__action { margin-top: 8px; align-self: flex-start; }
  .grs-frame--pair > .grc:nth-child(n), .grs-frame--grid > .grc:nth-child(n) { padding: 0; border: 0; }   /* :nth-child(n) outranks the desktop column/row rules */
  .grs-frame--pair > .grc:nth-child(n+2), .grs-frame--grid > .grc:nth-child(n+2) { padding-top: var(--grs-row-gap); border-top: 1px solid var(--line-soft); }
  .grs-frame--pair > .grc:not(:last-child), .grs-frame--grid > .grc:not(:last-child) { padding-bottom: var(--grs-row-gap); }
  .grc, .grs-frame--grid .grc { grid-template-columns: 112px minmax(0, 1fr); column-gap: 18px; --grc-frame-h: 150px; --grc-frame-pad: 7px; }
}
@media (max-width: 480px) { .grc, .grs-frame--grid .grc { grid-template-columns: 1fr; row-gap: 16px; --grc-frame-h: 192px; --grc-frame-pad: 8px; } .grc__cover { width: 144px; } }
@media (prefers-reduced-motion: reduce) { .grs-frame, .grc__action--primary, .grc__action--route svg { transition: none; } }

/* GuideRequestModal (.grm) — the shared guide-request dialog opened by every guide CTA (2026-09-08,
   owner brief). One instance, built by _shared/guide-gate.js from the clicked card's data. Calm
   paper surface, one title, guide metadata, minimal form (email required, first name optional),
   one action. Truthful preview behavior: a valid submit starts the PDF download and says so. */
.grm-overlay { position: fixed; inset: 0; z-index: 200; display: grid; place-items: center; padding: 20px; background: rgba(8,10,12,.62); }
.grm-overlay[hidden] { display: none; }   /* 2026-09-09 defect: display:grid beat the hidden attribute, so a closed dialog left an invisible full-screen layer over the page (nothing clickable, the next tap re-hit the scrim) */
.grm { position: relative; box-sizing: border-box; width: min(100%, 520px); max-height: calc(100vh - 40px); overflow: auto; padding: 30px 32px 26px; border: 1px solid var(--line); border-radius: 16px; background: var(--surface); color: var(--text); }
.grm-close { position: absolute; top: 14px; right: 14px; width: 36px; height: 36px; display: grid; place-items: center; border: 1px solid transparent; border-radius: 10px; background: transparent; color: var(--muted); cursor: pointer; }
.grm-close:hover { background: var(--control-surface); color: var(--text); }
.grm-close:focus-visible { outline: 2px solid var(--focus-ring, var(--mineral)); outline-offset: 2px; }
.grm-close svg { width: 16px; height: 16px; }
.grm-title { margin: 0 26px 8px 0; font-size: 21px; line-height: 1.25; letter-spacing: -.015em; font-weight: 500; }
.grm-meta { margin: 0 0 14px; font-family: var(--mono); font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--faint); }
.grm-desc { margin: 0 0 18px; font-size: 14.5px; line-height: 1.6; color: var(--muted); }
/* Intake order, 2026-09-10 (owner standard): the first-name/last-name pair is the ONLY side-by-side
   row; every other control is full width, and the pair stacks under 520px. Children default to the
   full row so the submit and the fine print need no rule of their own. */
.grm-form { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
/* Same defect as .grm-overlay above, missed on the form: `display: grid` beats the UA rule for the
   hidden attribute, so guide-gate.js setting f.hidden = true on submit did NOT hide it. The reader
   saw the filled form, "Your download has started" and the desk's error all at once (2026-09-11).
   Any class here that a script toggles with .hidden needs this guard — .grm-fld and .grm-close are
   included because they carry display rules too and are one refactor away from the same bug. */
.grm-form[hidden], .grm-fld[hidden], .grm-close[hidden] { display: none; }
.grm-form > * { grid-column: 1 / -1; }
.grm-form > .grm-fld--half { grid-column: span 1; }
@media (max-width: 520px) { .grm-form > .grm-fld--half { grid-column: 1 / -1; } }
.grm-fld { display: grid; gap: 6px; }
.grm-fld > span { font-size: 12.5px; color: var(--muted); }
.grm-fld input { box-sizing: border-box; width: 100%; padding: 11px 13px; border: 1px solid var(--line); border-radius: 10px; background: var(--control-surface, transparent); color: var(--text); font: inherit; font-size: 14.5px; }
.grm-fld input:focus-visible { outline: 2px solid var(--focus-ring, var(--mineral)); outline-offset: 1px; }
.grm-submit { justify-self: start; margin-top: 4px; }
.grm-fine { margin: 4px 0 0; font-size: 12px; line-height: 1.55; color: var(--faint); }
.grm-done h3 { margin: 0 0 8px; font-size: 17px; font-weight: 500; }
.grm-done p { margin: 0 0 10px; font-size: 14px; line-height: 1.6; color: var(--muted); }
.grm-done a { color: var(--text); }
@media (max-width: 480px) { .grm { padding: 24px 20px 20px; } }
@media (prefers-reduced-motion: no-preference) { .grm { animation: grm-in .18s ease; } @keyframes grm-in { from { opacity: 0; transform: translateY(6px) scale(.985); } } }

/* The landings' "Download our guides" section shell (.resources) — owned here since 2026-09-16: vn/index.html carried a
   page-local rule that no longer applied (computed padding 0, the heading sat on the section edge — owner screenshot),
   while ae/index.html carried its own copy. One shared rhythm, same as .grs: 96px above, 88px below, 40px under the head. */
.resources { padding: 96px 0 88px; border-top: 1px solid var(--line-soft); }
.resources .sec-head { max-width: 720px; margin-bottom: 40px; }
        