/* vistoeb2.net — shared LANDING template components.
   Loaded by every landing page after base.css:
     base.css     tokens, reset, header/drawer, .btn, line icons, FAQ, quiz, footer
     landing.css  THIS FILE — the landing composition: sections, hero + hero figure,
                  "Em resumo", TOC, two-stage diagram, tabs, evidence table, timeline,
                  duo cards, contrast columns, cost panel, dark honesty, sources, related
   Page-specific overrides (if any) stay inline in that page's own <style>.

   The approved design is frozen — fix a component HERE and every landing gets it. */

/* The brand container is fluid 90vw; a long-form landing caps it so paragraphs never
   run the full width of a wide monitor (design brief §3).
   The header bar is deliberately NOT capped: it is site chrome, identical on every
   page, and capping it here made the nav sit 70px further in on a landing than on the
   homepage — the same bar in two different places depending on where you were. */
.wrap{max-width:1300px}
.sec{padding:clamp(40px,7vw,110px) 0}
.sec--tint{background:var(--color-surface-2)}
/* Reading column: ~700–780px keeps long PT-BR paragraphs comfortable. */
.read{max-width:760px}
.lead{font-size:1.0625rem;line-height:1.7;color:var(--color-on-surface-muted);margin:0}
/* Vertical rhythm runs on the documented spacing scale (docs/design.md):
   4 / 8 / 16 / 24 / 40 / 64 / 96. The eyebrow is a label belonging TO the heading, so
   it sits one step closer (md) than the heading sits to the body copy (lg). Both were
   18px — a value on no scale, and the same gap above and below the heading, which
   flattened the hierarchy. */
.eyebrow{font-family:var(--font-mono);font-size:.6875rem;font-weight:600;letter-spacing:.14em;text-transform:uppercase;color:var(--color-accent-quiet);margin:0 0 16px}
.sec h2{font-family:var(--font-display);font-weight:700;font-size:clamp(1.75rem,3.4vw,3rem);letter-spacing:-.018em;line-height:1.08;margin:0 0 24px;color:var(--color-on-surface);max-width:20ch}
.sec h3{font-family:var(--font-sans);font-size:1.0625rem;font-weight:700;margin:0;color:var(--color-on-surface)}
/* Jump targets clear both sticky bars: header (100px) + "Neste guia" TOC (42px) + gap. */
.anchor{scroll-margin-top:calc(var(--head-h) + var(--toc-h) + var(--sticky-gap))}

/* ---------- compact hero ---------- */
/* No bottom padding: the mid-shot figure bleeds to the very bottom edge of the hero. */
/* No bottom padding: the mid-shot figure bleeds to the very bottom edge of the hero. */
.lhero{background:var(--color-primary);color:var(--color-on-primary);padding:clamp(28px,4vw,44px) 0 0}
.lhero-grid{display:grid;grid-template-columns:56fr 44fr;gap:clamp(32px,5vw,64px);align-items:end}
/* Section has no bottom padding, so the text column carries its own. */
.lhero-copy{align-self:center;padding-bottom:clamp(32px,6vw,76px)}
.lhero .eyebrow{color:var(--color-accent)}
/* 64–82px desktop per brief; nowrap is deliberately NOT used — this H1 is short
   enough to wrap naturally within two lines at every supported width. */
.lhero h1{font-family:var(--font-display);font-weight:300;font-size:clamp(2.75rem,5vw,5.125rem);line-height:1.04;letter-spacing:-.025em;margin:0 0 24px;max-width:13ch}
.lhero h1 em{font-style:normal;font-weight:500;color:#BCE9AB}
.lhero p.intro{color:#c4cecd;font-size:1.0625rem;line-height:1.65;margin:0 0 40px;max-width:52ch}
.lhero-cta{display:flex;gap:14px;flex-wrap:wrap;align-items:center}
/* Both CTAs share the primary button's height so they read as one size, side-by-side
   and stacked. That height is the design-system primary: circle 34 + padding 28.
   border-box makes min-height the full box height. */
.lhero-cta .btn, .lhero-cta .btn-ghost{min-height:62px}
/* Follows the .btn step-down in base.css. A flat 62px here would win over the smaller
   padding and leave an oversized pill with the text floating inside it. */
@media(max-width:960px){.lhero-cta .btn, .lhero-cta .btn-ghost{min-height:52px}}
@media(max-width:560px){.lhero-cta .btn, .lhero-cta .btn-ghost{min-height:48px}}
.btn-ghost{display:inline-flex;align-items:center;gap:10px;font-size:.9375rem;font-weight:600;letter-spacing:.02em;text-transform:uppercase;border:1px solid #3d6b6b;border-radius:var(--rounded-pill);padding:13px 26px;text-decoration:none;color:#F4F7F5;transition:border-color .25s var(--ease-out),background .25s var(--ease-out)}
.btn-ghost:hover{border-color:#F4F7F5;background:rgba(255,255,255,.06)}
@media(max-width:960px){.btn-ghost{font-size:.875rem;padding:11px 22px}}
@media(max-width:560px){.btn-ghost{font-size:.8125rem;padding:10px 18px}}
.micro{font-size:.8125rem;color:#8fa6a3;margin:16px 0 0}
/* Mid-shot cut-out figure that fills the column and bleeds to the hero's bottom edge.
   The near-black clothing measures only ~1.6:1 against the dark-green hero, so the
   silhouette is lifted with a soft light halo behind the upper body. No frame, no
   grounding shadow — the figure is cropped at the waist by the bottom edge itself. */
.lhero-person{position:relative;align-self:end;display:flex;justify-content:center;align-items:flex-end;min-height:0}
.lhero-person::before{content:"";position:absolute;left:50%;top:4%;transform:translateX(-50%);width:96%;height:78%;border-radius:46% 46% 40% 40%;background:radial-gradient(60% 58% at 50% 42%,rgba(255,255,255,.11),rgba(255,255,255,0) 72%);z-index:0}
.lhero-person img{position:relative;z-index:1;width:100%;max-width:520px;height:auto;display:block}
@media(max-width:900px){
  /* Stacked: text then figure. The flush-bottom bleed is a desktop-only device;
     on mobile the hero gets its bottom padding back so the figure can't collide
     with the "Em resumo" card, and align-self is reset so nothing overlaps the copy. */
  .lhero{padding-bottom:clamp(32px,6vw,48px)}
  .lhero-grid{grid-template-columns:1fr;gap:24px;align-items:stretch}
  .lhero-copy{align-self:auto;padding-bottom:0}
  .lhero h1{max-width:none}
  .lhero-person{align-self:auto;justify-content:center}
  .lhero-person img{width:auto;max-width:min(72vw,340px);margin:0 auto}
}

/* ---------- hero visual: swap photo <-> layered composition ----------
   Toggle on the section: data-hero="composition" (default) or "photo".
   Roll back to the photo by changing that one attribute (and re-enabling the
   <link rel=preload> in <head>). Both variants stay in the DOM. */
.lhero[data-hero="composition"] .lhero-person{display:none}
.lhero[data-hero="photo"] .lhero-figure{display:none}
/* Composition mode needs a balanced bottom padding (photo mode stays flush at 0 so the
   figure bleeds to the edge). The extra ~40px offsets the "Em resumo" panel's negative
   margin, leaving a bottom gap that visually matches the top. */
.lhero[data-hero="composition"]{padding-bottom:clamp(32px,6vw,84px)}

/* ---------- hero dossier (third variant) ----------
   data-hero="dossier": three category cards instead of a photo or the layered composition.
   /visto-eb1/ needs it because that page's whole argument is that EB-1 is not one thing —
   the reader has to see EB-1A / EB-1B / EB-1C as separate routes before reading a word.
   Same translucent-panel language as .hfig-goal, so it belongs to the dark hero instead of
   looking like a light card dropped onto it. Unlike the other two variants these cards
   carry meaning, so they are NOT aria-hidden. */
.lhero[data-hero="dossier"]{padding-bottom:clamp(32px,6vw,84px)}
.dossier{align-self:center;display:grid;gap:14px;width:100%;max-width:460px;margin-inline:auto}
.dcard{border:1px solid rgba(255,255,255,.16);border-radius:20px;background:rgba(255,255,255,.06);padding:20px 22px;display:grid;gap:6px}
.dcard .tag{font-family:var(--font-mono);font-size:.6875rem;font-weight:600;letter-spacing:.14em;color:var(--color-accent)}
.dcard b{font-family:var(--font-display);font-size:1.125rem;font-weight:600;letter-spacing:-.01em;color:var(--color-on-primary)}
.dcard span:last-child{font-size:.8125rem;line-height:1.5;color:var(--color-on-primary-muted)}
@media(max-width:900px){.dossier{max-width:none}}

/* ---------- dated policy update ----------
   A live government measure that changes what the page's own advice is worth. It must be
   impossible to miss and equally impossible to mistake for marketing urgency, so it uses
   the brand's attention colour and a plain white panel — no red, no siren, no countdown.
   The visible verification date is part of the component, not decoration: an undated claim
   about a moving policy is worse than none. */
.update{background:var(--color-surface-2);padding:clamp(32px,4vw,56px) 0}
.update-in{background:#fff;border:1px solid var(--color-border);border-left:4px solid var(--color-accent);border-radius:18px;padding:clamp(24px,3vw,40px);box-shadow:0 12px 28px -18px rgba(6,41,45,.4)}
.update-in h2{font-family:var(--font-display);font-weight:700;font-size:clamp(1.375rem,2.4vw,1.875rem);line-height:1.2;letter-spacing:-.015em;color:var(--color-on-surface);margin:0 0 16px;max-width:28ch}
.update-in p{margin:0 0 14px;font-size:1rem;line-height:1.7;color:var(--color-on-surface-muted);max-width:78ch}
.update-in .eyebrow{margin-bottom:14px}
.update-foot{display:flex;flex-wrap:wrap;align-items:center;gap:12px 24px;margin-top:24px}
/* Not .micro: that one is tuned for the dark hero (#8fa6a3) and drops to 2.4:1 here. */
.update-date{margin:0;font-size:.8125rem;line-height:1.5;color:var(--color-on-surface-muted)}

/* The composition is decorative (aria-hidden); meaning lives in the copy column.
   Built from separate layered elements — connecting lines behind, goal card mid,
   floating profile/data chips in front — not a flat image. cqw units scale it all. */
.lhero-figure{align-self:center;width:100%}
.hfig{position:relative;width:100%;max-width:520px;aspect-ratio:100/94;margin-inline:auto;container-type:inline-size}
.hfig > *{position:absolute}
.hfig-lines{inset:0;width:100%;height:100%;z-index:0;overflow:visible}
.hfig-lines path{fill:none;stroke:var(--color-emerald);stroke-width:1.5;stroke-dasharray:3 5;opacity:.55}
.hfig-lines .dot{fill:var(--color-accent-cyan)}

/* frosted card base */
.hfig-goal,.hfig-chip,.hfig-pill{
  background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.14);
  -webkit-backdrop-filter:blur(9px);backdrop-filter:blur(9px);
  box-shadow:0 12cqw 30cqw -14cqw rgba(0,0,0,.6);color:#F4F7F5}

/* central goal card — the destination (permanent residency) */
.hfig-goal{left:16%;top:31%;width:64cqw;z-index:2;border-radius:6cqw;padding:6cqw 6cqw 6.5cqw;
  transform:rotate(-3deg);
  background:linear-gradient(150deg,rgba(16,164,124,.32),rgba(7,58,62,.5) 60%,rgba(6,41,45,.65)),rgba(255,255,255,.05)}
.hfig-goal .tag{display:flex;justify-content:space-between;align-items:center;font-family:var(--font-mono);font-size:2.7cqw;font-weight:600;letter-spacing:.14em;text-transform:uppercase;color:#BCE9AB}
.hfig-goal .tag .star{color:var(--color-accent);font-size:3.4cqw}
.hfig-goal .big{font-family:var(--font-display);font-weight:600;font-size:8.2cqw;line-height:1;letter-spacing:-.02em;margin:5cqw 0 1.5cqw}
.hfig-goal .sub{font-size:3cqw;color:#c4cecd}
.hfig-goal .strip{display:flex;gap:1.6cqw;margin-top:5.5cqw}
.hfig-goal .strip i{height:2.2cqw;flex:1;border-radius:99px;background:rgba(255,255,255,.16)}
.hfig-goal .strip i:first-child{flex:2;background:var(--color-accent)}

/* applicant profile chips */
.hfig-chip{display:flex;gap:3cqw;align-items:center;border-radius:4.5cqw;padding:3cqw 4cqw 3cqw 3cqw;z-index:3}
.hfig-chip .av{width:10.5cqw;height:10.5cqw;border-radius:50%;flex-shrink:0;overflow:hidden;
  display:grid;place-items:center;
  background:rgba(255,255,255,.12);box-shadow:0 0 0 1px rgba(255,255,255,.18)}
.hfig-chip .av img{width:100%;height:100%;object-fit:cover;object-position:center top;display:block}
/* icon variant of the chip avatar — for pages where face photos would wrongly imply
   real clients (e.g. the requirements page). Same chip shape, no face. */
.hfig-chip .av svg{width:62%;height:62%}
.hfig-chip .av svg .ln{stroke:#9fc4bd}
.hfig-chip .av svg .ac{fill:var(--color-accent)}
/* static chips: labels are facts, not live states — kill the "in progress" pulse */
.hfig--static .hfig-chip .who span::before{animation:none}
.hfig-chip .who{display:flex;flex-direction:column;gap:.6cqw;line-height:1.1}
.hfig-chip .who b{font-size:3.5cqw;font-weight:600}
.hfig-chip .who span{display:flex;align-items:center;gap:1.6cqw;font-size:2.7cqw;color:#9fc4bd}
.hfig-chip .who span::before{content:"";width:1.8cqw;height:1.8cqw;border-radius:50%;background:var(--color-accent);box-shadow:0 0 0 0 rgba(255,237,78,.5);animation:hpulse 2.4s var(--ease-out) infinite}
.hfig-chip--1{top:1%;left:0}
.hfig-chip--2{bottom:3%;right:0}

/* data pills */
.hfig-pill{display:flex;align-items:center;gap:2.4cqw;border-radius:99px;padding:2.6cqw 4cqw;z-index:3;
  font-size:2.9cqw;font-weight:600}
.hfig-pill .k{font-family:var(--font-mono);font-weight:700;letter-spacing:.1em;color:var(--color-accent)}
.hfig-pill--a{top:20%;right:1%}
.hfig-pill--b{bottom:25%;left:3%}

@keyframes hpulse{0%{box-shadow:0 0 0 0 rgba(255,237,78,.45)}70%{box-shadow:0 0 0 2.4cqw rgba(255,237,78,0)}100%{box-shadow:0 0 0 0 rgba(255,237,78,0)}}
@media(prefers-reduced-motion:reduce){.hfig-chip .who span::before{animation:none}}
@media(max-width:900px){.hfig{max-width:380px}}

/* ================= INSTITUTIONAL PAGES =================
   Short institutional pages (/sobre/, and the /como-funciona/, /politica-editorial/,
   /transparencia/, /aviso-legal/, /contato/ pages still to come) are NOT landings.
   They open on a LIGHT hero instead of the dark .lhero, which is the point: the reader
   should see at a glance that this is the project explaining itself, not another guide
   selling a route. Everything below the hero is the ordinary landing kit — the only
   additions here are the light hero, its abstract figure, and the closing CTA band. */

/* The dark hero ends with a colour change, so its edge is self-evident. A light hero
   has no such edge: its bottom padding met the next section's top padding for ~200px
   of unbroken white. The hairline closes the hero the way .g-list, .toc and .marquee
   close their blocks, and lets the bottom padding come down a step now that the rule
   is doing the separating. Top matches .lhero; bottom is the design-system 40/64 step. */
.ihero{background:var(--color-surface);padding:clamp(20px,4vw,44px) 0 clamp(32px,5vw,64px);border-bottom:1px solid var(--color-border)}
/* Trimming only the hero's side left the rule floating with ~65px above and ~145px
   below. The section that follows gets the matching step so the hairline sits centred
   in its own gap. Scoped to this adjacency — .sec keeps its full padding everywhere
   else, including on the landings. */
.ihero + .sec{padding-top:clamp(28px,5vw,64px)}
.ihero-grid{display:grid;grid-template-columns:1.05fr .95fr;gap:clamp(32px,5vw,72px);align-items:center}
/* Identical type scale to .lhero h1 — same clamp, line-height, tracking and margin.
   Only the colour changes, because the ground is light. An earlier version shrank this
   "because an institutional page should open quieter"; that invented a second H1 size
   the design system does not have, and the gap widened to 14px on large screens.
   Page character comes from the light ground and the calmer figure, not from type size. */
.ihero h1{font-family:var(--font-display);font-weight:300;font-size:clamp(2.75rem,5vw,5.125rem);line-height:1.04;letter-spacing:-.025em;margin:0 0 24px;color:var(--color-on-surface);max-width:13ch}
/* Bright emerald is safe here only because this text is huge — at this size it counts
   as WCAG large text (3:1). Never carry it down into the paragraphs. */
.ihero h1 em{font-style:normal;font-weight:500;color:var(--color-emerald)}
/* Same measure and leading as .lhero p.intro — only the colour differs. This hero
   carries two paragraphs, so the first closes tight and the second keeps .lhero's
   30px gap before the buttons. */
.ihero p.intro{font-size:1.0625rem;line-height:1.65;color:var(--color-on-surface-muted);margin:0 0 16px;max-width:52ch}
.ihero p.intro + p.intro{margin-bottom:40px}
.ihero-cta{display:flex;gap:14px;flex-wrap:wrap;align-items:center}
.ihero-cta .btn, .ihero-cta .btn-ghost{min-height:62px}
@media(max-width:960px){.ihero-cta .btn, .ihero-cta .btn-ghost{min-height:52px}}
@media(max-width:560px){.ihero-cta .btn, .ihero-cta .btn-ghost{min-height:48px}}
/* .btn-ghost is tuned for the dark hero (pale text, teal border) and turns invisible
   on a light surface. This is its light-surface sibling. */
.btn-ghost--light{border-color:var(--color-border);color:var(--color-on-surface)}
.btn-ghost--light:hover{border-color:var(--color-on-surface);background:rgba(6,41,45,.04)}
@media(max-width:900px){
  .ihero-grid{grid-template-columns:1fr;gap:36px}
  .ihero h1{max-width:none}
}
/* Single-column variant — for a hero with no figure beside it (the 404). Splitting the
   row and leaving the right half empty would read as a broken layout on a page whose
   whole job is to say something is missing. */
.ihero--solo .ihero-grid{grid-template-columns:1fr}
.ihero--solo .intro{max-width:56ch}

/* Abstract document stack — the institutional counterpart of .hfig. Deliberately
   wordless: no avatars, no data labels, no figures that could be read as a real case.
   Built only from the site's own card, border and line language (brief §5). */
.ifig{position:relative;width:100%;max-width:430px;aspect-ratio:100/90;margin-inline:auto;container-type:inline-size}
.ifig > *{position:absolute}
.ifig-sheet{border:1px solid var(--color-border);border-radius:5cqw;background:var(--color-surface)}
.ifig-sheet--a{left:17%;top:3%;width:68cqw;height:72cqw;transform:rotate(5deg)}
.ifig-sheet--b{left:12%;top:6%;width:70cqw;height:74cqw;transform:rotate(-2.5deg);background:#fff}
.ifig-doc{left:5%;top:12%;width:74cqw;padding:6.5cqw;border:1px solid var(--color-border);border-radius:5cqw;background:#fff;box-shadow:0 16cqw 34cqw -18cqw rgba(6,41,45,.3);display:grid;gap:3.2cqw}
/* The single brand accent in the composition. A graphic bar, never text — yellow
   would fail contrast as type on white. */
.ifig-tag{width:20cqw;height:2.6cqw;border-radius:99px;background:var(--color-accent)}
.ifig-line{height:2.6cqw;border-radius:99px;background:var(--color-border)}
.ifig-line--title{height:4.2cqw;width:84%;background:var(--color-ghost)}
.ifig-line--short{width:58%}
.ifig-rule{height:1px;background:var(--color-border);margin:1.4cqw 0}
.ifig-chk{display:flex;align-items:center;gap:3cqw}
.ifig-chk i{flex:1;height:2.6cqw;border-radius:99px;background:var(--color-border)}
.ifig-chk svg{width:6cqw;height:6cqw;flex-shrink:0;display:block}
/* Dashed tie-line, same stroke language as .hfig-lines on the dark hero. */
.ifig-tie{right:1%;top:5%;width:32cqw;height:38cqw;overflow:visible}
.ifig-tie path{fill:none;stroke:var(--color-emerald);stroke-width:1.5;stroke-dasharray:3 5;opacity:.6}
.ifig-tie circle{fill:var(--color-emerald)}
@media(max-width:900px){.ifig{max-width:330px}}

/* Four-step process figure — the /como-funciona/ hero's counterpart to .ifig.
   Built from the card, hairline, mono-number and dot vocabulary the site already has
   (.duo-card, .tl-step): no new illustration language, no score, no timer. */
.pfig{background:#fff;border:1px solid var(--color-border);border-radius:var(--rounded-xl);padding:clamp(16px,2vw,24px) clamp(20px,2.4vw,30px);max-width:420px;margin-inline:auto;box-shadow:0 18px 40px -26px rgba(6,41,45,.42)}
.pfig-list{list-style:none;margin:0;padding:0}
.pfig-step{position:relative;display:grid;grid-template-columns:auto 1fr;align-items:center;gap:14px;padding:15px 0 15px 26px}
/* One hairline spine threaded through the dots, trimmed at both ends. */
.pfig-step::before{content:"";position:absolute;left:3.5px;top:0;bottom:0;width:1px;background:var(--color-border)}
.pfig-step:first-child::before{top:50%}
.pfig-step:last-child::before{bottom:50%}
.pfig-step::after{content:"";position:absolute;left:0;top:50%;margin-top:-4px;width:8px;height:8px;border-radius:50%;background:var(--color-ghost)}
/* Only the first step is marked: the reader is at the start, not at a scored stage. */
.pfig-step:first-child::after{background:var(--color-accent-quiet)}
.pfig-no{font-family:var(--font-mono);font-size:.625rem;font-weight:600;letter-spacing:.12em;color:var(--color-accent-quiet)}
.pfig-t{font-size:.9375rem;font-weight:600;color:var(--color-on-surface)}

/* A supporting line at the foot of a card ("Por que importa"), separated the way
   .tab-caution separates its note. */
.card-note{margin-top:16px;padding-top:16px;border-top:1px solid var(--color-border)}
.card-note p{margin:0;font-size:.875rem;line-height:1.6;color:var(--color-on-surface-muted)}

/* Bullet list inside the bordered panel — same marker as .duo-card li / .contrast-col li.
   Scoped to an UNCLASSED list on purpose. Written as `.cost li` it also hit any component
   list that happened to sit inside a panel: `.numlist` counters and `.fee-list` amounts
   both inherited this absolutely-positioned grey dash, and the numbered list came out
   with its "01" spilling out of a 7×2px block. A list that brings its own class brings
   its own markers. */
.cost ul:not([class]){margin:16px 0 0;padding:0;list-style:none;display:grid;gap:9px}
.cost ul:not([class]) li{font-size:.9375rem;line-height:1.55;color:var(--color-on-surface-muted);padding-left:18px;position:relative}
.cost ul:not([class]) li::before{content:"";position:absolute;left:0;top:.52em;width:5px;height:5px;border-radius:50%;background:var(--color-ghost)}

/* General contact form. The fields themselves reuse the assessment's vocabulary
   (.qfields/.qfield/.qinput/.qconsent/.qerr/.qbtn/.quiz-done/.hp from base.css) — only
   the panel and the two control types .qinput never covered are declared here.
   Its own panel class rather than .cost: `.cost p` is (0,1,1) and would beat `.qerr`,
   rendering the error message as muted body text instead of red. */
.cform{border:1px solid var(--color-border);border-radius:22px;background:#fff;padding:clamp(24px,3vw,40px)}
.cform .intro{margin:0 0 24px;font-size:.9375rem;line-height:1.7;color:var(--color-on-surface-muted)}
/* .qinput was written for <input>; a select needs its native arrow replaced and a
   textarea needs a usable height. Same box, same focus ring. */
select.qinput{appearance:none;-webkit-appearance:none;cursor:pointer;padding-right:42px;
  background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%237E8A87' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 16px center;background-size:12px 8px}
textarea.qinput{min-height:140px;resize:vertical;line-height:1.6}
.cform-foot{display:flex;align-items:center;gap:16px;flex-wrap:wrap;margin-top:24px}
.cform-foot .qbtn--go{margin-left:0}
/* A submit that is mid-flight must look unavailable, not merely inert. */
.cform .qbtn--go:disabled{opacity:.55;cursor:not-allowed}
.cform .qbtn--go:disabled:hover{background:var(--color-accent)}

/* Closing CTA band. Compact by design: the institutional page sends the reader to the
   assessment, it does not host the form (brief §13). */
.ctaband{background:var(--color-primary);color:var(--color-on-primary);padding:clamp(32px,6vw,84px) 0}
.ctaband .wrap{display:grid;grid-template-columns:1.25fr .75fr;gap:clamp(26px,4vw,64px);align-items:center}
.ctaband .eyebrow{color:var(--color-accent)}
.ctaband h2{font-family:var(--font-display);font-weight:700;font-size:clamp(1.6rem,3vw,2.6rem);letter-spacing:-.018em;line-height:1.1;margin:0 0 16px;color:var(--color-on-primary);max-width:20ch}
.ctaband p{margin:0;color:#c4cecd;font-size:1rem;line-height:1.65;max-width:58ch}
.ctaband-act{display:flex;flex-direction:column;align-items:flex-start;gap:14px}
.ctaband-act .micro{margin:0}
@media(max-width:820px){.ctaband .wrap{grid-template-columns:1fr}}

/* ---------- "Em resumo" answer panel ---------- */
.resumo{background:#fff;border:1px solid var(--color-border);border-radius:22px;padding:clamp(24px,3vw,40px);margin-top:clamp(-40px,-4vw,-28px);position:relative;z-index:2}
/* The panel pulls itself up to overlap the DARK landing hero. Under a light hero there
   is nothing to overlap, and the pull would drag the panel across the hero's closing
   hairline — so this variant sits flat in its own section.
   MUST stay after .resumo: both selectors weigh (0,1,0), so source order decides.
   Declared up in the institutional block, it silently lost and the panel kept its -40px. */
.resumo--flat{margin-top:0}
.resumo-grid{display:grid;grid-template-columns:1.15fr .85fr;gap:clamp(24px,4vw,56px);align-items:start}
.resumo p{margin:0;font-size:1rem;line-height:1.7;color:var(--color-on-surface-muted)}
/* The eyebrow is a <p>, so `.resumo p{margin:0}` above was cancelling its bottom margin
   and the label sat straight on the text. Restore a gap on the design-system scale (lg). */
.resumo .eyebrow{margin-bottom:24px}
/* Facts are labels + direct answers, deliberately not styled as statistics (brief §7). */
.facts{display:grid;grid-template-columns:1fr 1fr;gap:1px;background:var(--color-border);border:1px solid var(--color-border);border-radius:14px;overflow:hidden}
.facts div{background:#fff;padding:16px 18px}
.facts dt{font-family:var(--font-mono);font-size:.625rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--color-on-surface-muted);margin-bottom:8px}
.facts dd{margin:0;font-size:.9375rem;font-weight:600;line-height:1.4;color:var(--color-on-surface)}
.alert{margin-top:24px;padding:16px 18px;border-radius:14px;background:var(--color-surface-2);border-left:3px solid var(--color-accent-quiet);font-size:.9375rem;line-height:1.6;color:var(--color-on-surface)}
@media(max-width:820px){.resumo-grid{grid-template-columns:1fr}.facts{grid-template-columns:1fr}}

/* ---------- table of contents ---------- */
/* Solid white, not --color-surface: this bar is sticky and travels over tinted and dark
   sections alike, so it needs to read as a distinct surface rather than blend into the
   page. Same #fff the cards use against the page's slightly grey ground. */
.toc{margin-top:clamp(24px,5vw,64px);border-top:1px solid var(--color-border);border-bottom:1px solid var(--color-border);background:#fff;position:sticky;top:var(--head-h);z-index:20}
.toc-in{display:flex;align-items:center;gap:20px;padding:12px 0}
.toc-lbl{font-family:var(--font-mono);font-size:.625rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--color-on-surface-muted);flex-shrink:0}
/* ONE ROW, never two. The bar's height is baked into the 154px that `.anchor` compensates
   for via scroll-margin-top, so a list that wraps silently pushes every heading the index
   jumps to under the bar — /visto-eb1/ was off by 45px on all eleven of its entries, and
   nothing about the page looked wrong. A row that scrolls keeps the bar at a fixed 52px
   whatever the entry count, which is what makes the constant safe. */
.toc details{position:relative;flex:1 1 auto;min-width:0}
.toc ul{list-style:none;display:flex;gap:22px;margin:0;padding:0;flex-wrap:nowrap;
  overflow-x:auto;scroll-behavior:smooth;scrollbar-width:none;-ms-overflow-style:none}
.toc ul::-webkit-scrollbar{display:none}
.toc li{flex:0 0 auto}
.toc a{font-size:.8125rem;color:var(--color-on-surface-muted);text-decoration:none;white-space:nowrap;transition:color .2s}
/* The section being read takes the same green as hover; the rest stay muted.
   Weight carries the state as well as colour — colour alone is not a cue everyone
   can see, and this is the only indicator of where you are in the guide. */
.toc a:hover, .toc a.is-current{color:var(--color-accent-quiet)}
.toc a.is-current{font-weight:600}
.toc summary{display:none}

/* Edge fades. An affordance, not decoration: a hard cut reads as "the list ends here".
   `data-sx` is written by app.js — none / start / middle / end — so a fade appears only on
   the side that actually has more to reach, and not at all when everything already fits.
   Without JS the row still scrolls; it just loses the hint. */
.toc details::before, .toc details::after{
  content:"";position:absolute;top:0;bottom:0;width:clamp(32px,6vw,64px);
  pointer-events:none;opacity:0;transition:opacity .25s var(--ease-out);z-index:1}
.toc details::before{left:0;background:linear-gradient(to right,#fff 15%,rgba(255,255,255,0))}
.toc details::after{right:0;background:linear-gradient(to left,#fff 15%,rgba(255,255,255,0))}
.toc[data-sx="start"] details::after,
.toc[data-sx="middle"] details::after,
.toc[data-sx="middle"] details::before,
.toc[data-sx="end"] details::before{opacity:1}

/* The label is the first thing to go when the row gets tight — it is a caption, the links
   are the function. */
@media(max-width:760px){.toc-lbl{display:none}}

/* Phones only. A twelve-entry strip on a 390px screen shows two at a time and reaching the
   last one is a dozen swipes, so below this the list becomes a tap-target accordion.
   Tablets deliberately keep the row — that was the point of the change.
   The breakpoint is mirrored in app.js (it decides where <details> is forced open); moving
   one without the other leaves a closed <details> whose own control is display:none. */
@media(max-width:640px){
  .toc{position:static}
  .toc-in{padding:0}
  .toc details{flex:none;width:100%;position:static}
  .toc summary{display:flex;justify-content:space-between;align-items:center;cursor:pointer;list-style:none;padding:16px 0;font-size:.9375rem;font-weight:600;min-height:44px}
  .toc summary::-webkit-details-marker{display:none}
  /* On <summary>, not <details> — no collision with the fade pseudo-elements above. */
  .toc summary::after{content:"+";color:var(--color-accent-quiet);font-size:1.35rem;transition:transform .3s var(--ease-out)}
  .toc details[open] summary::after{transform:rotate(45deg)}
  .toc ul{flex-direction:column;gap:0;padding-bottom:12px;overflow-x:visible}
  .toc li{border-top:1px solid var(--color-border)}
  .toc ul a{display:flex;align-items:center;min-height:44px;font-size:.9375rem;white-space:normal}
  .toc details::before, .toc details::after{display:none}
}

/* ---------- two-stage diagram ---------- */
.stages{display:grid;grid-template-columns:1fr auto 1fr;gap:clamp(16px,2vw,28px);align-items:stretch;margin-top:clamp(28px,4vw,44px)}
.stage{position:relative;border:1px solid var(--color-border);border-radius:22px;padding:clamp(22px,2.4vw,32px);background:#fff;display:flex;flex-direction:column}
/* ---------- DISPLAY NUMERALS ----------
   `.stage .no` and `.rel--num .no` are the same numeral and must stay SUBORDINATE to the
   section heading beside them at every width.
   That is why they use a clamp rather than breakpoint steps. `.sec h2` scales smoothly
   (clamp 1.75rem..3rem), so a stepped numeral overtook it in between: at 1024px the
   heading was 34.8px while the number sat at 44px, and the decoration outshouted the
   title from 1280px all the way down.
   This clamp tracks the heading's curve at roughly 0.9x, so the order holds everywhere:
   28..48px heading against 24..44px numeral. */
.stage .no{font-family:var(--font-display);font-size:clamp(1.5rem,3vw,2.75rem);font-weight:700;line-height:1;color:var(--color-accent-quiet);margin-bottom:16px}
.stage-ico{position:absolute;top:clamp(22px,2.4vw,30px);right:clamp(22px,2.4vw,30px);width:42px;height:42px}
.stage h3{font-size:1.25rem;margin:0 0 8px;letter-spacing:-.01em}
/* The icon and heading step at the site-wide breakpoints; the number does not — see the
   DISPLAY NUMERALS note below for why it needs a clamp instead. */
@media(max-width:960px){.stage-ico{width:36px;height:36px}}
@media(max-width:560px){
  .stage .no{margin-bottom:8px}
  .stage-ico{width:32px;height:32px}
  .stage h3{font-size:1.125rem}
}
.stage > p{margin:0;font-size:.9375rem;line-height:1.65;color:var(--color-on-surface-muted)}
.subroutes{margin:24px 0 0;padding:0;list-style:none;display:grid;gap:12px}
.subroutes li{border-top:1px solid var(--color-border);padding-top:12px}
.subroutes b{display:block;font-size:.875rem;margin-bottom:4px;color:var(--color-on-surface)}
.subroutes span{font-size:.8125rem;line-height:1.6;color:var(--color-on-surface-muted)}
.stage-link{display:flex;justify-content:center;align-items:center;color:var(--color-ghost)}
.stage-link svg{width:34px;height:34px}
.stage-note{margin-top:clamp(16px,2.4vw,24px);padding:16px 24px;border-radius:14px;background:var(--color-surface-2);font-size:.9375rem;line-height:1.6}
.inline-cta{display:inline-flex;align-items:center;gap:8px;font-weight:600;font-size:.9375rem;color:var(--color-accent-quiet);text-decoration:none;margin-top:16px}
.inline-cta:hover{text-decoration:underline}
/* On a phone this text link is the section's actual CTA, and its natural line box is
   only 24px — well under the 44px minimum touch target. Pad it out there only, so the
   desktop layout keeps the compact text-link rhythm. */
@media(max-width:900px){.inline-cta{min-height:44px}}
@media(max-width:860px){
  .stages{grid-template-columns:1fr}
  .stage-link{transform:rotate(90deg);padding:4px 0}
}

/* ---------- scope tags ---------- */
.tags{display:flex;flex-wrap:wrap;gap:8px;margin:24px 0 0;padding:0;list-style:none}
.tags li{border:1px solid var(--color-border);border-radius:var(--rounded-pill);padding:9px 16px;font-size:.875rem;font-weight:600;color:var(--color-on-surface);background:#fff}
/* `margin-bottom:0` is load-bearing. The class is used on both <p> and <div>, and a <p>
   keeps the browser's 15px bottom margin — so the same component produced a different gap
   depending on the tag it happened to be written on: 31px before an .inline-cta on
   /visto-eb2-niw/ and /visto-eb1/, 16px before the same link on /visto-eb3/. The panel now
   owns no trailing space and whatever follows declares its own. */
.callout{margin-top:24px;margin-bottom:0;padding:16px 24px;border-radius:16px;background:var(--color-surface-2);border-left:3px solid var(--color-accent);font-size:.9375rem;line-height:1.65;color:var(--color-on-surface);max-width:80ch}
/* An .inline-cta is inline-flex, so its margin never collapses with the panel's — without
   this it sat 16px under a full-width panel and read as part of it. 24px matches the
   .cta-row case, which is the same relationship. */
.callout + .inline-cta{margin-top:24px}
/* A callout that follows the section intro is a block after text, not a note attached to a
   component, so it takes the same 44px every other component takes after `.read`. */
.read + .callout{margin-top:clamp(28px,4vw,44px)}
/* a callout may carry a small label + body */
.callout .crit-lbl{margin:0 0 8px}
.callout p{margin:0}
/* caution note — same shape as .callout, emerald edge instead of yellow */
.alert-note{margin-top:24px;padding:16px 24px;border-radius:16px;background:var(--color-surface-2);border-left:3px solid var(--color-accent-quiet);font-size:.9375rem;line-height:1.65;color:var(--color-on-surface);max-width:80ch}
.sec--tint .alert-note{background:var(--color-surface);border:1px solid var(--color-border);border-left:3px solid var(--color-accent-quiet);max-width:none;box-shadow:0 12px 28px -18px rgba(6,41,45,.4)}
/* two notes side by side (e.g. a callout next to its caution note) */
.notes-2{display:grid;grid-template-columns:1fr 1fr;gap:24px;align-items:start;margin-top:24px}
.notes-2 > *{margin-top:0;max-width:none}
@media(max-width:820px){.notes-2{grid-template-columns:1fr;gap:16px}}

/* ---------- numbered list on light surfaces ----------
   Light-theme sibling of .honest-list: common mistakes, checklists, question sets. */
.numlist{list-style:none;margin:clamp(24px,3vw,36px) 0 0;padding:0;counter-reset:n;display:grid;grid-template-columns:1fr 1fr;gap:0 clamp(28px,4vw,64px)}
.numlist li{counter-increment:n;display:flex;gap:16px;padding:16px 0;border-top:1px solid var(--color-border);font-size:.9375rem;line-height:1.55;color:var(--color-on-surface)}
.numlist li::before{content:counter(n,decimal-leading-zero);font-family:var(--font-mono);font-size:.625rem;font-weight:600;letter-spacing:.12em;color:var(--color-accent-quiet);padding-top:4px;flex-shrink:0}
/* No rule above the first row — the list already starts against open space, and a
   leading border reads as the bottom edge of whatever sits above it. In two columns the
   top row is the first TWO items; the single-column cases below put item 2 back. */
.numlist li:nth-child(-n+2){border-top:none}
.numlist--single{grid-template-columns:1fr}
.numlist--single li:nth-child(2){border-top:1px solid var(--color-border)}
/* an item may carry a title plus an explanation (not just a one-liner) */
.numlist li > div{display:grid;gap:4px}
.numlist li b{font-weight:600;color:var(--color-on-surface)}
.numlist li span{font-size:.875rem;color:var(--color-on-surface-muted)}
/* One column: item 2 is no longer on the top row, so it needs its rule back. */
@media(max-width:820px){.numlist{grid-template-columns:1fr}.numlist li:nth-child(2){border-top:1px solid var(--color-border)}}
/* On a tinted (surface-2) section the default surface-2 callout blends in. Flip it to a
   white full-width card with a border + soft shadow so it reads as a distinct block. */
.sec--tint .callout{background:var(--color-surface);border:1px solid var(--color-border);border-left:3px solid var(--color-accent);max-width:none;box-shadow:0 12px 28px -18px rgba(6,41,45,.4)}

/* ---------- image + text split (homepage-style rhythm change) ---------- */
/* Top-aligned, not centred: the text column is always the taller of the two, so centring
   left the image floating with uneven space above and below and nothing lining up with
   the heading beside it. Both columns now start on the same line. */
.lsplit{display:grid;grid-template-columns:.92fr 1.08fr;gap:clamp(28px,5vw,64px);align-items:start;margin-top:clamp(28px,4vw,44px)}
.lsplit-img{border-radius:24px;overflow:hidden;aspect-ratio:3/2;position:relative;background:var(--color-surface-2)}
.lsplit-img img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}
.lsplit h2{margin-top:0}
.lsplit .callout{max-width:none}
@media(max-width:820px){.lsplit{grid-template-columns:1fr;gap:22px}}

/* ---------- criteria as tabs ----------
   Headings list on the left, one detail panel on the right that switches on click
   (and gently auto-advances). All three panels stay in the DOM — inactive ones use
   the `hidden` attribute, which crawlers still index — so nothing is lost for SEO. */
.tabs{display:grid;grid-template-columns:.92fr 1.08fr;gap:clamp(20px,3vw,44px);margin-top:clamp(28px,4vw,44px);align-items:start}
.tabs-nav{display:flex;flex-direction:column;gap:10px}
.tab{position:relative;overflow:hidden;display:flex;gap:14px;align-items:baseline;text-align:left;background:transparent;border:1px solid var(--color-border);border-radius:16px;padding:18px 20px;cursor:pointer;transition:border-color .25s var(--ease-out),background .25s var(--ease-out)}
.tab-no{font-family:var(--font-display);font-weight:700;font-size:1.25rem;line-height:1;color:var(--color-ghost);transition:color .25s;flex-shrink:0}
.tab-t{font-size:1.0625rem;font-weight:600;line-height:1.3;letter-spacing:-.01em;color:var(--color-on-surface-muted);transition:color .25s}
.tab:hover{border-color:var(--color-ghost)}
.tab[aria-selected="true"]{background:#fff;border-color:var(--color-accent)}
.tab[aria-selected="true"] .tab-no{color:var(--color-accent-quiet)}
.tab[aria-selected="true"] .tab-t{color:var(--color-on-surface)}
.tab:focus-visible{outline:2px solid var(--color-accent-quiet);outline-offset:2px}
.tab-panel{border:1px solid var(--color-border);border-radius:22px;background:#fff;padding:clamp(24px,2.6vw,36px);animation:tabin .4s var(--ease-out)}
.tab-panel[hidden]{display:none}
.tab-panel > p{margin:0 0 4px;font-size:.9375rem;line-height:1.65;color:var(--color-on-surface-muted)}
.tab-panel .crit-lbl{margin:16px 0 8px}
.tab-panel ul{margin:0;padding:0 0 0 18px;display:grid;gap:7px}
.tab-panel li{font-size:.875rem;line-height:1.55;color:var(--color-on-surface-muted)}
.tab-panel li::marker{color:var(--color-ghost)}
/* caution area — differentiated by surface + label, never a red X (brief §11/§15) */
.tab-caution{margin-top:24px;padding-top:16px;border-top:1px solid var(--color-border)}
.tab-caution .crit-lbl{margin-top:0}
.tab-caution p{margin:0;font-size:.875rem;line-height:1.6;color:var(--color-on-surface)}
@keyframes tabin{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
/* No translate — used by the stacked variant, where the panel is fused to its tab. */
@keyframes tabfade{from{opacity:0}to{opacity:1}}
@media(prefers-reduced-motion:reduce){.tab-panel{animation:none}}
/* ---- phone/tablet: the panel opens under ITS OWN tab ----
   Stacked, the two-column layout became "every tab, then the content" — with the first
   criterion selected the reader scrolled 210px past two unrelated tabs to reach what they
   had just tapped. Worse the more tabs a group has; the biggest here is six.

   Behaviour is unchanged: exactly one panel open, switching closes the previous one. Only
   the position moves. The tab script needed no edit for this — it finds panels through
   aria-controls and only toggles [hidden], so it never cared where they sat. (It does own
   the scroll-to-top on switch, which is a separate concern.)

   `display:contents` dissolves both wrappers so tabs and panels become siblings that
   `order` can interleave. Pairs are listed to nine — more than the largest group needs, so
   a new group is covered without touching this; extra rules match nothing.
   Roles stay tab/tablist/tabpanel — verified still exposed in the accessibility tree with
   the wrappers dissolved. If a future browser drops them, move the panels with JS instead.

   This is the component's behaviour, not an opt-in: any .tabs group on any page gets it.
   grid-template-columns is gone from here because display is flex below this width. */
@media(max-width:820px){
  /* align-items:stretch is load-bearing — the base `.tabs` sets `start`, which in a COLUMN
     flex container packs each item to its own text width: the tabs came out 408px and
     454px inside a 710px container while the panel filled it, so the stack looked ragged. */
  .tabs{display:flex;flex-direction:column;align-items:stretch;gap:10px}
  .tabs-nav, .tabs-panels{display:contents}
  .tabs .tab:nth-child(1){order:1}  .tabs .tab-panel:nth-child(1){order:2}
  .tabs .tab:nth-child(2){order:3}  .tabs .tab-panel:nth-child(2){order:4}
  .tabs .tab:nth-child(3){order:5}  .tabs .tab-panel:nth-child(3){order:6}
  .tabs .tab:nth-child(4){order:7}  .tabs .tab-panel:nth-child(4){order:8}
  .tabs .tab:nth-child(5){order:9}  .tabs .tab-panel:nth-child(5){order:10}
  .tabs .tab:nth-child(6){order:11} .tabs .tab-panel:nth-child(6){order:12}
  .tabs .tab:nth-child(7){order:13} .tabs .tab-panel:nth-child(7){order:14}
  .tabs .tab:nth-child(8){order:15} .tabs .tab-panel:nth-child(8){order:16}
  .tabs .tab:nth-child(9){order:17} .tabs .tab-panel:nth-child(9){order:18}
  /* Tab and its open panel merge into ONE outlined block. Dropping the two facing borders
     is what removes the yellow seam; without that the tab's bottom border and the panel's
     top border stack into a 2px line straight through the middle of the shape.
     margin-top cancels the flex gap exactly, so the two boxes touch.
     With the seam gone the facing paddings (18 + 24) read as one 52px void, so both are
     pulled in — the pair should look like a heading with its text, not two rooms. */
  .tabs .tab[aria-selected="true"]{
    border-bottom:0;border-bottom-left-radius:0;border-bottom-right-radius:0;padding-bottom:12px}
  .tabs .tab-panel{
    margin-top:-10px;border-top:0;border-top-left-radius:0;border-top-right-radius:0;
    border-color:var(--color-accent);padding-top:14px;
    /* Fade only. The shared `tabin` slides the panel down 8px, which was right when it was
       a separate card — fused to the tab it tears the outline open for the whole 0.4s. */
    animation:tabfade .3s var(--ease-out)}
}

/* ---------- evidence matrix ---------- */
.matrix-wrap{margin-top:clamp(28px,4vw,44px)}
table.matrix{width:100%;border-collapse:collapse;background:#fff;border:1px solid var(--color-border);border-radius:16px;overflow:hidden}
table.matrix th, table.matrix td{text-align:left;padding:18px 20px;border-bottom:1px solid var(--color-border);vertical-align:top;font-size:.9375rem;line-height:1.6}
table.matrix thead th{font-family:var(--font-mono);font-size:.625rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--color-on-surface);background:var(--color-surface-2)}
table.matrix tbody th{font-weight:700;color:var(--color-on-surface);width:22%}
table.matrix td{color:var(--color-on-surface-muted)}
table.matrix tbody tr:last-child th, table.matrix tbody tr:last-child td{border-bottom:none}
/* Mobile: each row becomes a card and repeats its column label — never a horizontal scroll. */
@media(max-width:860px){
  table.matrix, table.matrix tbody, table.matrix tr, table.matrix td, table.matrix th{display:block}
  table.matrix{border:none;background:transparent}
  table.matrix thead{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
  table.matrix tr{background:#fff;border:1px solid var(--color-border);border-radius:16px;margin-bottom:16px;padding:8px 0}
  table.matrix tbody th{width:auto;font-size:1.0625rem;border-bottom:none;padding-bottom:6px}
  table.matrix td{border-bottom:none;padding-top:6px}
  table.matrix td::before{content:attr(data-label);display:block;font-family:var(--font-mono);font-size:.625rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--color-on-surface);margin-bottom:8px}
}

/* ---------- timeline ---------- */
.tl{display:grid;grid-template-columns:repeat(4,1fr);gap:20px;margin-top:clamp(28px,4vw,44px)}
/* Five stages (/visto-eb1/). Five columns at 1440px leave ~250px each, which is still
   wider than the copy needs; below 1100px they drop to a 3+2 grid rather than squeezing. */
.tl--5{grid-template-columns:repeat(5,1fr)}
@media(max-width:1100px){.tl--5{grid-template-columns:repeat(3,1fr);gap:20px 20px}}
/* Seven stages (/visto-eb3/ PERM). Seven across would leave ~180px per column, narrower
   than the copy reads well at, so it wraps 4+3 from the start. Both modifiers are declared
   here, ABOVE the max-width:900px rule that collapses .tl to one column — same weight
   (0,1,0), so the later rule has to win for the mobile stack to survive. */
.tl--7{grid-template-columns:repeat(4,1fr);row-gap:clamp(24px,3vw,36px)}
@media(max-width:1100px){.tl--7{grid-template-columns:repeat(2,1fr)}}
.tl-step{position:relative;padding-top:26px;border-top:2px solid var(--color-border)}
.tl-step::before{content:"";position:absolute;top:-7px;left:0;width:12px;height:12px;border-radius:50%;background:var(--color-accent-quiet)}
.tl-ico{width:34px;height:34px;margin-bottom:16px}
.tl-step .no{font-family:var(--font-mono);font-size:.625rem;font-weight:600;letter-spacing:.12em;color:var(--color-accent-quiet);margin-bottom:8px}
.tl-step h3{font-size:1.0625rem;margin:0 0 8px;letter-spacing:-.01em}
.tl-step p{margin:0;font-size:.875rem;line-height:1.6;color:var(--color-on-surface-muted)}
@media(max-width:900px){
  .tl{grid-template-columns:1fr;gap:0}
  .tl-step{border-top:none;border-left:2px solid var(--color-border);padding:0 0 28px 24px}
  .tl-step:last-child{border-left-color:transparent;padding-bottom:0}
  .tl-step::before{top:2px;left:-7px}
}

/* ---------- Brazil / US cards ---------- */
.duo{display:grid;grid-template-columns:1fr 1fr;gap:20px;margin-top:clamp(28px,4vw,44px)}
/* three equal cards — same card language as .duo, for fact/metric sets */
/* No `align-items:start` — cards in a row share the tallest card's height so the row reads
   as a table instead of a ragged edge. This grid used to be the only one that opted out;
   its siblings .duo, .contrast and .rel never set align-items and so stretch by default.
   Raggedness inside a single row before the fix: 122px on /politica-editorial/, 105px on
   /visto-eb1/, 49px on /visto-eb3/. Only the box stretches — the text stays pinned to the
   top of each card, which is what keeps it a table rather than vertically centred blocks. */
.trio{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;margin-top:clamp(28px,4vw,44px)}
@media(max-width:900px){.trio{grid-template-columns:1fr}}
.duo-card{border:1px solid var(--color-border);border-radius:22px;background:#fff;padding:clamp(22px,2.4vw,32px)}
.duo-card .crit-lbl{margin:0 0 16px}
.duo-card h3{font-size:1.25rem;letter-spacing:-.01em;margin:0 0 8px}
.duo-card p{margin:0;font-size:.9375rem;line-height:1.65;color:var(--color-on-surface-muted)}
/* optional bullet list inside a duo card (same marker language as .contrast-col) */
.duo-card ul{margin:16px 0 0;padding:0;list-style:none;display:grid;gap:9px}
.duo-card li{font-size:.875rem;line-height:1.55;color:var(--color-on-surface-muted);padding-left:18px;position:relative}
.duo-card li::before{content:"";position:absolute;left:0;top:.52em;width:5px;height:5px;border-radius:50%;background:var(--color-ghost)}
.duo-ic{width:44px;height:44px;margin-bottom:16px}
@media(max-width:820px){.duo{grid-template-columns:1fr}}

/* ---------- advantages vs limits ---------- */
/* Both columns are visually identical: limits must not read as hidden fine print. */
.contrast{display:grid;grid-template-columns:1fr 1fr;gap:20px;margin-top:clamp(28px,4vw,44px)}
.contrast-col{border:1px solid var(--color-border);border-radius:22px;background:#fff;padding:clamp(22px,2.4vw,32px)}
.contrast-col h3{font-size:1.125rem;letter-spacing:-.01em;margin:0 0 16px}
.contrast-col ul{margin:0;padding:0;list-style:none;display:grid;gap:12px}
.contrast-col li{font-size:.9375rem;line-height:1.6;color:var(--color-on-surface-muted);padding-left:20px;position:relative}
.contrast-col li::before{content:"";position:absolute;left:0;top:.54em;width:5px;height:5px;border-radius:50%;background:var(--color-ghost)}
/* A column may close with a line of explanation under its list. Without this the
   paragraph falls back to 16px body copy and outweighs the items it is summarising. */
.contrast-col p{margin:16px 0 0;font-size:.875rem;line-height:1.6;color:var(--color-on-surface-muted)}
@media(max-width:820px){.contrast{grid-template-columns:1fr}}

/* ---------- cost preview ---------- */
/* Two columns: intro heading (left) + premium-processing panel (right) — same
   heading-left / content-right rhythm as the FAQ and the honesty block. */
.cost-grid{display:grid;grid-template-columns:.9fr 1.1fr;gap:clamp(28px,4vw,64px);align-items:start}
.cost-grid h2{margin-top:0}
@media(max-width:820px){.cost-grid{grid-template-columns:1fr;gap:22px}}
/* Same top margin every other component carries (.trio, .contrast, .matrix-wrap, .tl,
   .duo) so a panel dropped after a `.read` intro sits on the page's rhythm instead of
   touching the paragraph above it. It used to have none: spacing came either from the
   grid gap or from remembering to add `.cost--stack`, and thirteen panels across
   /visto-eb1/ and /visto-eb3/ ended up glued to the text because nobody remembered.
   Making it the default means the next page cannot repeat that. */
.cost{margin-top:clamp(28px,4vw,44px);border:1px solid var(--color-border);border-radius:22px;background:#fff;padding:clamp(24px,3vw,40px)}
/* In the two-column layout the grid gap owns the spacing. */
.cost-grid .cost{margin-top:0}
.cost h3{font-size:1.125rem;margin:0 0 8px;letter-spacing:-.01em}
.cost p{margin:0 0 16px;font-size:.9375rem;line-height:1.7;color:var(--color-on-surface-muted)}
.cost-note{padding:16px 18px;border-radius:14px;background:var(--color-surface-2);border-left:3px solid var(--color-accent);font-size:.875rem;line-height:1.6;color:var(--color-on-surface)}

/* ---------- dark honesty callout ---------- */
.honest{background:var(--color-primary);color:var(--color-on-primary)}
/* Two columns: heading (top-left) + CTA (pinned bottom-left), all items on the right.
   The list spans both rows so it defines the height; row 1 (1fr) pushes the CTA down. */
.honest .wrap{display:grid;grid-template-columns:.9fr 1.1fr;grid-template-rows:1fr auto;
  grid-template-areas:"head list" "cta list";
  gap:clamp(24px,3vw,40px) clamp(32px,6vw,80px);align-items:start}
.h-head{grid-area:head}
.h-list{grid-area:list}
.h-cta{grid-area:cta;align-self:end}
/* CTA sits right under the heading instead of pinned low — for heads with no
   supporting paragraph, where a bottom-pinned CTA would float far from its title. */
.honest--tight .wrap{grid-template-rows:auto 1fr}
.honest--tight .h-cta{align-self:start}
.honest .eyebrow{color:var(--color-accent)}
.honest h2{font-family:var(--font-display);font-weight:700;font-size:clamp(1.75rem,3.4vw,3rem);letter-spacing:-.018em;line-height:1.08;margin:0 0 24px;color:var(--color-on-primary);max-width:16ch}
.honest .lead{color:#c4cecd;margin:0}
.honest-list{list-style:none;margin:0;padding:0;counter-reset:h;display:grid;gap:0}
.honest-list li{counter-increment:h;display:flex;gap:18px;padding:18px 0;border-top:1px solid var(--color-border-dark);font-size:1rem;line-height:1.6;color:#dbe6e4}
.honest-list li:first-child{border-top:none;padding-top:0}
.honest-list li::before{content:counter(h,decimal-leading-zero);font-family:var(--font-mono);font-size:.625rem;font-weight:600;letter-spacing:.12em;color:var(--color-accent);padding-top:5px;flex-shrink:0}
/* an item may carry a title plus an explanation (not just a one-liner) */
.honest-list li > div{display:grid;gap:5px}
.honest-list li b{font-weight:600;color:var(--color-on-primary)}
.honest-list li span{font-size:.9375rem;color:#9fb5b2}

/* ---- phone layout: number + title on one row, explanation on the next (TRIAL) ----
   Default layout puts the number in its own column and wraps the title beside it, so a
   long title reads as a narrow block squeezed next to a 10px numeral. Here the number
   pairs with the title on the first row and the explanation drops to a second row.

   The explanation stays in column 2 — indented to the title's left edge, exactly as on
   desktop. The number column is a marker gutter, and text does not run under a marker:
   both text blocks share one left edge, so the eye tracks a single vertical line down the
   list instead of two.

   `display:contents` on the wrapper is what makes this possible: it dissolves the <div> so
   <b> and <span> become grid items of the <li> itself. Without it the explanation is
   trapped inside the wrapper and cannot be placed on its own row.

   Items written as a plain one-liner (no <div>/<b>/<span>, as on /visto-eb2-niw/) still
   work — the bare text becomes an anonymous grid item and lands beside the number. */
@media(max-width:560px){
  .honest-list li{display:grid;grid-template-columns:auto 1fr;column-gap:12px;row-gap:5px;align-items:baseline}
  .honest-list li > div{display:contents}
  .honest-list li b{grid-column:2}
  .honest-list li span{grid-column:2}
  /* the 5px nudged the number onto the title's baseline in the flex layout; baseline
     alignment does that job here, and the padding would now push it off. */
  .honest-list li::before{padding-top:0}
}
.honest-close{margin:clamp(16px,3vw,24px) 0 0;font-size:.9375rem;line-height:1.7;color:#8fa6a3;max-width:70ch}
/* A text link inside the dark module. .inline-cta defaults to --color-accent-quiet,
   which is a dark green on a dark green ground — effectively invisible here. */
.honest .inline-cta{color:var(--color-accent)}
@media(max-width:820px){
  .honest .wrap{grid-template-columns:1fr;grid-template-rows:auto;grid-template-areas:"head" "list" "cta"}
  .h-cta{align-self:start}
}

/* ---------- legal document ----------
   A policy reads as one column of prose, not as a stack of landing modules — the privacy
   brief rules out cards, tables and panels for the body. Headings step well down from the
   section scale: thirteen of them in a row at 48px would shout, and a hairline above each
   separates the clauses better than size does. */
.doc{max-width:none}
/* Preamble: no clause number, so it stays a single reading column above the two-column
   run rather than sitting in an empty grid row. */
.doc-intro{max-width:760px}
/* Each clause is heading-left / content-right, the same rhythm the FAQ and the cost
   panel use. It has to be a wrapper per clause: the source is a flat run of
   h2 → p → ul → h2, and in a bare grid every sibling would claim its own cell and the
   columns would step down the page instead of lining up. */
.doc-row{display:grid;grid-template-columns:1fr 1.4fr;gap:clamp(20px,4vw,80px);margin-top:40px;padding-top:32px;border-top:1px solid var(--color-border)}
.doc-row > h2{font-family:var(--font-display);font-weight:700;font-size:clamp(1.25rem,2vw,1.5rem);line-height:1.3;letter-spacing:-.01em;color:var(--color-on-surface);max-width:20ch;margin:0}
/* The hairline separates one clause from the previous one, so the first clause must not
   draw it: on a page with no .doc-intro above it (/aviso-legal/ opens straight on clause
   1) it would read as a stray rule hanging under the section's top padding. */
.doc > .doc-row:first-child{margin-top:0;padding-top:0;border-top:0}
.doc-body > *:last-child{margin-bottom:0}
@media(max-width:820px){
  .doc-row{grid-template-columns:1fr;gap:16px;margin-top:32px;padding-top:24px}
}
.doc p{margin:0 0 16px;font-size:1rem;line-height:1.7;color:var(--color-on-surface-muted)}
.doc ul{margin:0 0 16px;padding:0;list-style:none;display:grid;gap:8px}
.doc li{font-size:1rem;line-height:1.6;color:var(--color-on-surface-muted);padding-left:20px;position:relative}
.doc li::before{content:"";position:absolute;left:0;top:.6em;width:5px;height:5px;border-radius:50%;background:var(--color-ghost)}
.doc a{color:var(--color-accent-quiet);font-weight:600;text-decoration:none}
.doc a:hover{text-decoration:underline}
/* A note inside a clause. Same specificity trap the cards keep hitting: `.doc p` is
   (0,1,1) and a bare `.callout` / `.alert-note` is (0,1,0), so an unscoped note keeps its
   coloured frame but loses its type — it renders as ordinary muted body copy inside a box
   that promises emphasis. Scope it, exactly as `.duo-card .alert-note` does.
   `margin:0 0 16px` replaces the components' `margin-top:24px`: inside a clause the note
   is one more block in the flow, not something set off from a section above it. */
.doc .callout, .doc .alert-note{margin:0 0 16px;max-width:none}
.doc .callout p, .doc .alert-note p{margin:0;font-size:.9375rem;line-height:1.65;color:var(--color-on-surface)}
/* Postal address and long e-mail. `break-word` matters here: at 360px an unbroken
   address or mailto would push the whole page into a horizontal scroll. */
.doc address{font-style:normal;margin:0 0 16px;font-size:1rem;line-height:1.7;color:var(--color-on-surface);overflow-wrap:break-word}
.doc address b{font-weight:600}
.doc .mailto{overflow-wrap:break-word}

/* ---------- sources panel ---------- */
.sources{border:1px solid var(--color-border);border-radius:22px;background:#fff;padding:clamp(24px,3vw,36px)}
.sources p{margin:0 0 16px;font-size:.9375rem;line-height:1.65;color:var(--color-on-surface-muted);max-width:80ch}
.sources ul{margin:0;padding:0;list-style:none;display:grid;gap:10px}
.sources li{font-size:.875rem}
.sources a{color:var(--color-accent-quiet);font-weight:600;text-decoration:none}
.sources a:hover{text-decoration:underline}
.sources .disc{margin:24px 0 0;padding-top:16px;border-top:1px solid var(--color-border);font-size:.8125rem;color:var(--color-on-surface-muted)}

/* ---------- related guides ---------- */
.rel{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;margin-top:clamp(24px,3vw,36px)}
/* `transition` is a shorthand, so this rule REPLACES the one `.stagger > *` sets in
   base.css — anything missing from the list below simply snaps instead of animating.
   These cards were arriving at full opacity in one frame. The entrance rides the
   independent `translate` property so it never collides with the `transform` the hover
   lift uses, and each keeps its own timing: .8s to arrive, .3s to lift.
   (prefers-reduced-motion resets `translate` too — see base.css.) */
.rel-card{border:1px solid var(--color-border);border-radius:22px;background:#fff;padding:clamp(22px,2.4vw,30px);text-decoration:none;display:flex;flex-direction:column;gap:10px;
  transition:opacity .8s var(--ease-out),translate .8s var(--ease-out),border-color .3s var(--ease-out),transform .3s var(--ease-out)}
.stagger > .rel-card{transform:none;translate:0 36px}
.stagger.in > .rel-card{translate:none}
.rel-card:hover{border-color:var(--color-accent);transform:translateY(-4px)}
.rel-card .no{font-family:var(--font-mono);font-size:.625rem;font-weight:600;letter-spacing:.12em;color:var(--color-accent-quiet)}
/* Variant: the big display numbering used by the .stage cards, for a page that opens
   with numbered stages and closes with numbered guides — the two then rhyme.
   Only the number changes; card, hover and layout stay the shared ones.
   6px, not 16px: .rel-card already puts a 10px flex gap between its children, so this
   lands on the same 16px the stage number sits above its heading. */
/* Same numeral, same clamp as `.stage .no` — see DISPLAY NUMERALS above. */
.rel--num .no{font-family:var(--font-display);font-size:clamp(1.5rem,3vw,2.75rem);font-weight:700;line-height:1;letter-spacing:normal;margin-bottom:6px}
.rel-card h3{font-size:1.0625rem;letter-spacing:-.01em}
.rel-card p{margin:0;font-size:.875rem;line-height:1.6;color:var(--color-on-surface-muted)}
.rel-card .go{margin-top:auto;font-size:1.1rem;color:var(--color-on-surface)}
@media(max-width:900px){.rel{grid-template-columns:1fr}}
/* Four cards instead of three. Declared after the rule above so it wins at the same
   specificity — otherwise the 900px breakpoint would collapse this variant to one
   column while there is still room for two. */
.rel--4{grid-template-columns:repeat(4,1fr)}
@media(max-width:1100px){.rel--4{grid-template-columns:repeat(2,1fr)}}
@media(max-width:560px){.rel--4{grid-template-columns:1fr}}

/* ---------- shared micro-elements inside cards ----------
   SPECIFICITY TRAP — read before touching this block.
   Every card component styles its own paragraphs (`.duo-card p`, `.cost p`,
   `.tab-panel > p`), and those selectors are (0,1,1). A bare `.crit-lbl` is (0,1,0),
   so it LOSES: the label silently renders as ordinary body copy. That is exactly what
   was happening — the mono label look was only ever declared under `.tab-panel`, so
   the same class rendered as plain grey text in `.duo-card` and `.cost`.
   These rules are `p.<class>` (0,1,1) and live at the end of the file so they win
   the tie against every card's paragraph rule, in any component. Per-context margin
   overrides above are (0,2,0) and still win — that is intended, only the margin. */

/* Small mono label above a fact or a card's content. */
p.crit-lbl{font-family:var(--font-mono);font-size:.625rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--color-on-surface-muted);margin:16px 0 8px}
/* A stated figure inside a card. A fact, never a rating or a price offer. */
p.fact-v{font-family:var(--font-display);font-weight:700;font-size:clamp(1.6rem,2.8vw,2.25rem);line-height:1;letter-spacing:-.02em;color:var(--color-on-surface);margin:0 0 8px}
/* A note may sit inside a card, where `.duo-card p` would flatten its colour/margin. */
.duo-card .alert-note, .duo-card .callout{margin:16px 0 0;max-width:none;color:var(--color-on-surface)}
/* Bare list of amounts making up an example. Markers would add nothing — the label
   above the list already says what it is. */
ul.fee-list{margin:16px 0 0;padding:0;list-style:none;display:grid;gap:8px}
ul.fee-list li{font-size:.9375rem;line-height:1.6;color:var(--color-on-surface-muted)}
/* TIGHTER than the default `.cost` margin, not a replacement for it: a panel that reads as
   a continuation of the table right above it (the fee tables on /visto-eb2-niw-quanto-custa/
   and the self-assessment on /eb2-niw-requisitos/). Declared after `.cost` so it wins the
   (0,1,0) tie by source order — moving it above `.cost` would silently do nothing. */
.cost--stack{margin-top:clamp(24px,3vw,36px)}
/* Closing note of a cost panel — it follows content, so it leads with a top margin
   (`.cost p` would otherwise give it a trailing one and no separation). */
p.cost-note{margin:16px 0 0}
/* Two inline text CTAs side by side under a section.
   `p.` is load-bearing, same trap as p.cost-note above: inside a panel `.cost p` is
   (0,1,1) and beat a bare `.cta-row`, zeroing its top margin — the links sat flush
   against the list above them on /contato/ and /como-funciona/. */
p.cta-row{display:flex;gap:24px;flex-wrap:wrap;margin-top:24px}
.cta-row{display:flex;gap:24px;flex-wrap:wrap;margin-top:24px}
.cta-row .inline-cta{margin-top:0}
/* A primary action attached directly to a section heading gets the xl step — the same
   heading→CTA distance the dark module uses. At lg a 62px button crowds a 48px heading. */
.sec h2 + .cta-row{margin-top:40px}

/* FAQ uses the homepage's two-column structure (sticky heading left, accordion right)
   straight from base.css. Only the heading weight is matched to the landing's other H2s.
   Sticky top must clear BOTH sticky bars: header (100px) + "Neste guia" TOC (42px) + gap;
   base.css sets 110px (homepage has no TOC), which would let the heading slide under it. */
.faq-sec .faq-grid h2{font-weight:700;font-size:clamp(1.75rem,3.4vw,3rem);letter-spacing:-.018em;top:calc(var(--head-h) + var(--toc-h) + var(--sticky-gap))}
/* No measure cap here: the accordion is already the narrow column of a two-column grid,
   so 66ch left ~96px of the panel unused and the answer looked misaligned with its
   question. The homepage FAQ never had this cap — landings now match it. */
