:root{
  --bg:#061018;
  --bg-deep:#03090e;
  --beam:#07121a;
  --line:rgba(205,226,239,.16);
  --line-soft:rgba(205,226,239,.08);
  --text:#f4f7f9;
  --muted:#b4bec5;
  --dim:#7f8d97;
  --accent:#43bff0;
  --accent-soft:#82d3f3;
  --pad:clamp(22px,5.5vw,88px);
  --header-h:88px;
  --sans:Inter,ui-sans-serif,-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif;
  --mono:ui-monospace,"SF Mono","Cascadia Mono","JetBrains Mono","Roboto Mono",Menlo,Consolas,monospace;
  /* WEB-005B Product palette (tasks/WEB-005B_HOMEPAGE_VISUAL_FIDELITY_PALETTE.md section 5). Defined
     once, here; scripts/validate_site.py pins every value. Brand/UI and non-scientific framing only:
     no analytical value is ever coloured with these. */
  --orb-bg:#030B12;
  --orb-surface:#08131D;
  --orb-panel:#0D1B27;
  --orb-divider:#183245;
  /* WEB-005B R15 tonal hierarchy. Three grounds in ONE family, not three colours: --orb-bg is the
     page ground every section still starts and ends on, --orb-lift is the slightly raised ground a
     reading section rests on, and --orb-deep is the ground the page settles onto as it closes. They
     are only ever reached through a gradient that returns to --orb-bg at both edges, so no boundary
     is ever a colour step. --orb-atmos is the one soft atmospheric tint, used behind the result. */
  --orb-lift:#061420;
  --orb-deep:#020810;
  --orb-atmos:rgba(28,74,104,.30);
  --orb-text-primary:#EAF2F8;
  --orb-text-secondary:#9EB1C1;
  --orb-meta:#6F8597;
  --orb-cyan:#73E7FF;
  --orb-cyan-glow:#8AF1FF;
  --orb-beam-core:#7FEFFF;
  --orb-beam-glow:#3CCBFF;
  --orb-target-frame:#98F5FF;
  /* WEB-005B R11: the homepage story after the hero centres on one measure and keeps the page
     gutter below it, so every act shares exactly one set of edges on a large monitor. */
  --shell:1280px;
  --sec-y:clamp(72px,8.4vw,140px);
}
*{box-sizing:border-box}
html{scroll-behavior:smooth;background:var(--bg);scroll-padding-top:var(--header-h)}
body{margin:0;background:var(--bg);color:var(--text);font-family:var(--sans);-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;overflow-x:hidden}
a{color:inherit;text-decoration:none}
img{display:block;max-width:100%}
button,a{-webkit-tap-highlight-color:transparent}
:focus-visible{outline:2px solid var(--accent);outline-offset:4px}
.skip-link{position:fixed;left:16px;top:16px;z-index:999;transform:translateY(-160%);background:#fff;color:#071018;padding:10px 14px;border-radius:8px;font-size:13px;transition:transform .2s ease}.skip-link:focus{transform:none}

/* Secondary monospace treatment: coordinates, evidence labels, metadata, technical descriptors. */
.mono{font-family:var(--mono);font-variant-ligatures:none}
.kicker{margin:0 0 18px;font-size:10px;letter-spacing:.24em;text-transform:uppercase;color:var(--accent-soft)}

/* ---------- header / navigation ---------- */
.site-header{height:var(--header-h);padding:0 var(--pad);display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid var(--line);background:rgba(4,12,18,.96);position:relative;z-index:40}
/* Padding, not a larger wordmark: WCAG 2.5.8 wants a >=24px activation box and the bare 21px
   line box of the wordmark was short of it. The header centres its children, so the extra box
   height changes nothing visually. */
.brand{display:inline-flex;align-items:center;padding:6px 0}
.brand-wordmark{font-size:24px;font-weight:430;letter-spacing:-.035em;line-height:1}.brand-wordmark span{color:var(--accent)}
.main-nav{display:flex;align-items:center;justify-content:flex-end;gap:clamp(22px,2.8vw,44px);font-size:10px;text-transform:uppercase;letter-spacing:.17em}
.nav-list{display:flex;align-items:center;gap:clamp(24px,3.2vw,52px);list-style:none;margin:0;padding:0}
.nav-list a,.nav-trigger{position:relative;display:inline-flex;align-items:center;gap:9px;padding:6px 0;opacity:.83;transition:opacity .2s ease;color:inherit;background:none;border:0;font:inherit;letter-spacing:inherit;text-transform:inherit;cursor:pointer;white-space:nowrap}
.nav-list a:hover,.nav-trigger:hover,.has-menu.open .nav-trigger{opacity:1}
.nav-list a[aria-current="page"],.nav-trigger[aria-current="page"]{opacity:1}
.nav-list a[aria-current="page"]::after,.nav-trigger[aria-current="page"]::after{content:"";position:absolute;left:0;right:0;bottom:-2px;height:1px;background:var(--accent)}
.chevron{width:5px;height:5px;border-right:1px solid currentColor;border-bottom:1px solid currentColor;transform:translateY(-2px) rotate(45deg);transition:transform .2s ease}
.has-menu.open .chevron{transform:translateY(1px) rotate(225deg)}
.has-menu{position:relative}
.submenu{position:absolute;top:100%;left:-18px;padding-top:22px;display:none;z-index:50}
.has-menu.open .submenu{display:block}
.submenu ul{list-style:none;margin:0;padding:8px 0;min-width:250px;background:#07121a;border:1px solid var(--line);border-radius:6px;box-shadow:0 18px 40px rgba(0,0,0,.45)}
.submenu a{display:block;padding:11px 18px;opacity:.8;transition:opacity .15s ease,background .15s ease;white-space:nowrap}
.submenu a:hover,.submenu a:focus-visible{opacity:1;background:rgba(67,191,240,.08)}
.submenu a:focus-visible{outline-offset:-3px}
.lang-switch{display:flex;align-items:center;gap:8px;padding-left:clamp(20px,2.6vw,40px);border-left:1px solid var(--line)}
/* min-width, not a bigger label: at 10px uppercase the two-letter codes measured 21-22px wide on
   desktop, just under the 24px WCAG 2.5.8 target. The mobile rules below already raise them to 44px. */
.lang-btn{background:none;border:0;padding:6px 5px;min-width:24px;color:var(--dim);font:inherit;letter-spacing:inherit;text-transform:inherit;cursor:pointer;transition:color .2s ease}
.lang-btn:hover{color:var(--text)}
.lang-btn[aria-pressed="true"]{color:var(--accent)}
.lang-sep{color:var(--dim);opacity:.55}
.menu-toggle{display:none;background:none;border:0;padding:10px;margin-right:-10px;cursor:pointer}.menu-toggle span{display:block;width:25px;height:1px;background:#fff;margin:6px}

/* ---------- hero (WEB-005 cinematic acquisition sequence) ---------- */
.image-panel{position:relative;overflow:hidden;background:#0b141a}
.panel-image{width:100%;height:100%;object-fit:cover}
/* WEB-005B R11 section 2: the header plus the approved hero own the first viewport exactly. The
   old clamp(680px,82vh,980px) capped the hero at 980px, so on any window taller than ~1068px the
   next act sat visibly below it at scroll position 0. Small-viewport units (svh) are deliberate:
   dvh would let mobile browser chrome retracting reveal Act 02 mid-scroll, and 100vh on a phone is
   taller than the visible area. Nothing inside the hero changes — only the box it is drawn in. */
.hero{position:relative;overflow:hidden;background:#0b141a;height:calc(100svh - var(--header-h));min-height:560px}
.hero-visual{position:absolute;inset:0}
/* Poster and video occupy the same box and are the same framing, so the crossfade cannot shift
   the composition and there is no layout work when playback starts. The poster stays underneath
   rather than being removed: it is the fallback for every static state, including a mid-visit
   switch to reduced motion. */
.hero-poster,.hero-held,.hero-video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center 46%}
.hero-video{opacity:0;transition:opacity .9s ease;border:0}
/* The held base (the frame the video ends on) covers the startup poster in every static state; the
   drape states register with this frame and no other. */
.hero-held{opacity:0;transition:opacity .35s ease}
.hero-held.is-on{opacity:1}
.hero[data-hero-state="playing"] .hero-video,
.hero[data-hero-state="held"] .hero-video{opacity:1}
@property --hs50{syntax:'<number>';inherits:false;initial-value:.48}@property --hs52{syntax:'<number>';inherits:false;initial-value:.4467}@property --hs54{syntax:'<number>';inherits:false;initial-value:.4133}@property --hs56{syntax:'<number>';inherits:false;initial-value:.38}@property --hs58{syntax:'<number>';inherits:false;initial-value:.3467}@property --hs61{syntax:'<number>';inherits:false;initial-value:.2967}@property --hs74{syntax:'<number>';inherits:false;initial-value:.08}@property --hs100{syntax:'<number>';inherits:false;initial-value:.04}@property --hv24{syntax:'<number>';inherits:false;initial-value:.292}@property --hv30{syntax:'<number>';inherits:false;initial-value:.163}@property --hv32{syntax:'<number>';inherits:false;initial-value:.12}@property --hv33{syntax:'<number>';inherits:false;initial-value:.114}
.hero-shade{position:absolute;inset:0;background:linear-gradient(90deg,rgba(3,9,14,.97) 0%,rgba(3,9,14,.88) 27%,rgba(3,9,14,.5496) 46%,rgba(3,9,14,var(--hs50)) 50%,rgba(3,9,14,var(--hs52)) 52%,rgba(3,9,14,var(--hs54)) 54%,rgba(3,9,14,var(--hs56)) 56%,rgba(3,9,14,var(--hs58)) 58%,rgba(3,9,14,var(--hs61)) 61%,rgba(3,9,14,var(--hs74)) 74%,rgba(3,9,14,var(--hs100)) 100%),linear-gradient(0deg,rgba(3,9,14,.82) 0%,rgba(3,9,14,.55) 12%,rgba(3,9,14,var(--hv24)) 24%,rgba(3,9,14,var(--hv30)) 30%,rgba(3,9,14,var(--hv32)) 32%,rgba(3,9,14,var(--hv33)) 33%,transparent 52%);transition:--hs50 .9s ease,--hs52 .9s ease,--hs54 .9s ease,--hs56 .9s ease,--hs58 .9s ease,--hs61 .9s ease,--hs74 .9s ease,--hs100 .9s ease,--hv24 .9s ease,--hv30 .9s ease,--hv32 .9s ease,--hv33 .9s ease}
.hero-content{position:relative;z-index:2;display:flex;flex-direction:column;justify-content:center;height:100%;padding:30px var(--pad) 56px;width:min(780px,62vw)}

/* The analytical payoff (WEB-005A final production): lossless full-frame drape states on the held
   frame. Same box, same object-fit and same object-position as the poster and the video, so they
   register pixel for pixel with no placement maths; never graded or filtered. No legend, card or
   label lives here (Product decision b9579ef section 4). Desktop layout only. */
.hero-drape{position:absolute;inset:0;pointer-events:none;display:none;isolation:isolate}
.hero-drape-layer{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center 46%;filter:none;opacity:0;transition:opacity .45s ease}
.hero-drape-layer.is-on{opacity:1}
/* The relief rise. script.js drives two successive rendered states at opacities (1 - p) and p;
   plus-lighter makes that an exact linear interpolation of two partly transparent images (a plain
   cross-fade dips in the middle), and the isolated group keeps the sum inside the drape instead of
   adding it to the video underneath. No CSS transition: the script is the clock. */
.hero-drape-rise,.hero-drape.is-rising .hero-drape-layer{transition:none}
.hero-drape-rise,.hero-drape.is-rising .hero-drape-layer[data-layer="terrain"]{mix-blend-mode:plus-lighter}
@media(min-width:981px){
  .hero-drape{display:block}
  .hero-drape[hidden]{display:none}
  /* Analysis-safe shade (Product decision c7c6cb1 section 7). Identical to the resting shade behind
     the copy column (x <= 46%) and in the caption band (y <= 12%), feathered to nothing before the
     settled footprint begins at x = 57.6%. The stops themselves transition, so the copy side never
     lightens on the way. */
  .hero[data-hero-payoff="on"] .hero-shade{--hs50:.40;--hs52:.30;--hs54:.17;--hs56:.07;--hs58:.02;--hs61:0;--hs74:0;--hs100:0;--hv24:.14;--hv30:.03;--hv32:.01;--hv33:0}
}
.eyebrow{font-size:11px;line-height:1.9;text-transform:uppercase;letter-spacing:.28em;color:#b9cbd6;margin:0 0 28px}
.hero h1{font-size:clamp(50px,6.1vw,98px);font-weight:370;letter-spacing:-.045em;line-height:1;margin:0 0 30px;max-width:11ch}
.hero-copy{max-width:600px;color:#c2cbd0;line-height:1.7;font-size:clamp(16px,1.25vw,20px);margin:0 0 38px}
.hero-actions{display:flex;align-items:center;flex-wrap:wrap;gap:clamp(22px,3vw,44px)}
.button{width:max-content;display:inline-flex;align-items:center;gap:34px;border:1px solid rgba(255,255,255,.68);border-radius:11px;padding:15px 21px;font-size:10px;letter-spacing:.15em;text-transform:uppercase;background:rgba(6,16,24,.38);backdrop-filter:blur(8px);transition:background .2s ease,color .2s ease}.button:hover{background:#fff;color:#061018}
.text-link{display:inline-flex;align-items:center;gap:14px;padding:6px 0;font-size:10px;letter-spacing:.15em;text-transform:uppercase;color:#d5dee3;border-bottom:1px solid transparent;transition:color .2s ease,border-color .2s ease;white-space:nowrap}
.text-link:hover{color:#fff;border-bottom-color:rgba(255,255,255,.5)}

/* ---------- scene label: location + coordinates directly on the image ---------- */
.scene-label{position:absolute;right:var(--pad);bottom:22px;z-index:3;margin:0;text-align:right;font-family:var(--mono);font-variant-ligatures:none;font-size:9.5px;line-height:1.8;text-transform:uppercase;letter-spacing:.14em;color:rgba(244,247,249,.94);text-shadow:0 1px 2px rgba(0,0,0,.65),0 0 14px rgba(0,0,0,.5);pointer-events:none}
.scene-label span{display:block}
.scene-label span+span{color:rgba(214,226,233,.82)}
.scene-label .scene-kind{color:rgba(214,226,233,.55)}


/* ---------- WEB-002 product proof ---------- */
/* Scientific rasters and the score colour ramp are published exactly as the accepted GEO-039
   export rendered them. Any saturation, contrast, brightness or opacity change would alter the
   rendered scientific content, so proof imagery is explicitly exempt from the gallery grade that
   the hero still uses. Do not remove this guard. */
[data-visual-status="product-proof"] img{filter:none;opacity:1}

/* The WEB-001 label was tuned for dark satellite photography. The accepted cartographic exports
   are pale over much of the frame, so the same white text vanished on them. Still bare monospace
   text in the same place, with no card, box or band: legibility comes from a tight halo, and the
   tone is chosen per panel from the measured luminance of the region the label sits over. */
[data-label-tone="light"] .scene-label{color:#fbfdfe;
  text-shadow:0 0 1px rgba(2,7,11,1),0 0 2px rgba(2,7,11,1),0 0 3px rgba(2,7,11,1),
              0 0 5px rgba(2,7,11,1),0 0 9px rgba(2,7,11,.95),0 0 18px rgba(2,7,11,.85),
              0 1px 2px rgba(2,7,11,1)}
/* All three lines carry the full tone colour. Hierarchy comes from tracking and content, not
   from opacity: on a mid-luminance backdrop an 0.86 alpha cost the third line up to 1.9:1, and the
   third line is the one that says what the visual actually is. */
[data-label-tone="light"] .scene-label span+span,
[data-label-tone="light"] .scene-label .scene-kind{color:#fbfdfe}
[data-label-tone="light"] .scene-label .scene-kind{letter-spacing:.17em}
/* Dark captions already clear 5:1 against the grounds they sit on, so the halo only needs to be
   local insurance against bright speckle — a tight ring, not the dense glow the light tone needs. */
[data-label-tone="dark"] .scene-label{color:#050d13;
  text-shadow:0 0 1px rgba(255,255,255,.95),0 0 3px rgba(255,255,255,.8),0 1px 2px rgba(255,255,255,.85)}
[data-label-tone="dark"] .scene-label span+span,
[data-label-tone="dark"] .scene-label .scene-kind{color:#050d13}
[data-label-tone="dark"] .scene-label .scene-kind{letter-spacing:.17em}
/* Mandatory scientific warning carried in visible copy next to every proof visual. */
.beam-note{margin:0;max-width:62ch;padding-left:14px;border-left:2px solid rgba(200,169,122,.5);font-size:clamp(12px,.82vw,13px);line-height:1.6;color:#9aa7b0;font-weight:350}

.scale-ends{display:flex;justify-content:space-between;margin-top:5px;font-size:9px;letter-spacing:.1em;color:var(--dim)}

/* ================================================================================
   WEB-005B R11 — the homepage after the hero (accepted final Claude Design).

   R10 sections 3-6: one continuous page ground. Acts 02, 03 and 04, the inspection
   aid, the domains, the method grid, the company block and the contact ending all
   sit on the SAME background token. Nothing separates them by a full-width colour
   change; separation is spacing, type scale, imagery, hairlines and inner stages.
   Section heights are content-driven — only the hero owns a viewport.
   ================================================================================ */
body.home{background:var(--orb-bg)}
.shell{position:relative;z-index:1;width:min(var(--shell),100%);margin-inline:auto}
.sec{position:relative;background:var(--orb-bg);padding:var(--sec-y) var(--pad)}

/* ---------- R15 tonal hierarchy ----------
   The page stays one continuous ground; what changes is how high off it a section sits. Every
   section still STARTS and ENDS on --orb-bg, and the lift or the settle happens in the middle of
   the section, so no boundary is ever a colour step and the page never reads as blocks stacked on
   blocks. Reading sections rise slightly (--orb-lift), the result sinks and gets the one
   atmospheric tint on the page, and the closing sections settle onto --orb-deep, which is also the
   footer's ground, so the page comes to rest instead of stopping. */
.sec-evidence{background:linear-gradient(180deg,var(--orb-bg) 0%,var(--orb-lift) 20%,var(--orb-lift) 80%,var(--orb-bg) 100%)}
.sec-result{background:
  radial-gradient(86% 56% at 50% 44%,var(--orb-atmos) 0%,rgba(28,74,104,.09) 44%,transparent 74%),
  linear-gradient(180deg,var(--orb-bg) 0%,var(--orb-deep) 26%,var(--orb-deep) 76%,var(--orb-bg) 100%)}
.sec-inspect{background:linear-gradient(180deg,var(--orb-bg) 0%,var(--orb-lift) 28%,var(--orb-lift) 76%,var(--orb-bg) 100%)}
.sec-contact{background:linear-gradient(180deg,var(--orb-bg) 0%,var(--orb-deep) 100%)}

/* One hairline per boundary, and it fades out before the page edge instead of cutting the width
   in half — a rule the eye reads as a handoff, not a seam. The first post-hero act deliberately
   has none: the hero already ends on its own bottom shade, and a line there would be exactly the
   hard edge R10 section 4 asks for the absence of. */
.sec-evidence::before,.sec-result::before,.sec-inspect::before,.sec-domains::before,
.sec-contact::before{content:"";position:absolute;
  left:var(--pad);right:var(--pad);top:0;height:1px;pointer-events:none;
  background:linear-gradient(90deg,transparent 0%,var(--line-soft) 14%,var(--line-soft) 86%,transparent 100%)}
.sec-result{padding-top:clamp(52px,5.4vw,88px);padding-bottom:clamp(52px,5.4vw,88px)}
.sec h2{margin:0;color:var(--orb-text-primary)}
.sec .kicker{margin:0;color:var(--orb-cyan)}
.sec-head{display:flex;flex-direction:column;gap:18px;max-width:60ch}
.sec-head h2{font-size:clamp(30px,3.5vw,54px);font-weight:360;letter-spacing:-.035em;line-height:1.08;max-width:16ch}
/* The Solutions headline is a sentence rather than a phrase, so it needs a wider measure than the
   act headings are tuned for. The real limiter is .sec-head's own 60ch, which resolves against the
   inherited 16px body size (~480px) and caps the h2 no matter what the h2 asks for. */
.sec-domains .sec-head{max-width:780px}
.sec-domains .sec-head h2{max-width:none}
.act-statement{margin:0;font-size:clamp(15px,1.15vw,19px);line-height:1.72;color:#c2cbd0;font-weight:350}
/* Deliberately NOT uppercased. These lines carry exact identifiers — the accepted scoring profile
   id `mvp_remote_sensing_priority_v1`, the EPSG code — and a text-transform would publish them in a
   case the authority never used. The monospace face and tracking carry the technical register
   instead. */
.act-meta{margin:0;font-size:10.5px;letter-spacing:.1em;color:var(--orb-meta);line-height:1.8}
.act-note{margin:0}
.act-footnote{margin:clamp(30px,3.4vw,48px) 0 0;max-width:86ch;display:flex;flex-wrap:wrap;align-items:baseline;gap:10px 16px;font-size:13px;line-height:1.7;color:#8d99a2;font-weight:350;border-top:1px solid var(--line-soft);padding-top:20px}
.act-footnote .mono{flex:none;font-size:9px;letter-spacing:.26em;text-transform:uppercase;color:rgba(200,169,122,.9)}
.act-footnote>span:not(.mono){flex:1 1 32ch;min-width:0}

/* Scroll entrance: one quiet rise per visual, once, only when script.js has an observer and motion
   is allowed (it adds .has-reveal). Opacity and translation of the wrapper only — the governed
   pixels themselves are never filtered, and at rest nothing is transformed. */
.has-reveal [data-reveal]{opacity:0;transform:translate3d(0,22px,0);transition:opacity .9s ease,transform 1.1s cubic-bezier(.2,.7,.2,1)}
.has-reveal [data-reveal].is-revealed{opacity:1;transform:none}
.has-reveal .domain-card[data-reveal]:nth-child(2){transition-delay:.1s}
.has-reveal .domain-card[data-reveal]:nth-child(3){transition-delay:.2s}

/* ---------- Act 02 — the place ----------
   The one cinematic moment below the fold: a single contained photograph with the copy inside its
   protected zone. Capped at 1600 CSS px because the native frame is 3200 px, so a 2x display is
   served at, never above, native density. */
.sec-place{padding:0}
/* Two rows: the photograph, then the copy. Below the desktop breakpoint the copy really does sit
   in row 2, on the page ground, where it is readable; from 1101px up it moves into row 1 and
   becomes the design's integrated caption inside the photograph's protected zone. The caption
   stays pinned to the bottom-right of the PHOTOGRAPH in both cases because it lives in row 1
   either way — no absolute offsets that depend on how tall the copy happens to be. */
.context-band{position:relative;margin:0 auto;max-width:1600px;background:#0b141a;
  display:grid;grid-template-columns:minmax(0,1fr);
  --place-pad:max(var(--pad),calc((100% - var(--shell)) / 2))}
/* A phone sees a 4:5 window on the frame, a small tablet 4:3, and anything wider the whole 16:9
   frame. The AOI corner marks are drawn from fractions of the WHOLE frame, so they are only shown
   in the last of those three — the one case where nothing is cropped away horizontally. */
.context-frame{grid-area:1/1;position:relative;overflow:hidden;aspect-ratio:4/5}
.context-frame>.panel-image{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:34% 50%}
/* Protection for the class-A photograph only: readable ground for the copy on the left, and a
   bottom edge that dissolves into the page ground so Act 02 hands to Act 03 without a hard cut
   (R10 section 5). Acts 3 and 4 are governed rasters and no gradient ever touches them. */
/* Below the desktop composition the copy is not on the photograph, so the only protection needed
   is the bottom edge: enough for the caption, and enough that the image dissolves into the page
   ground instead of ending on a hard line (R10 section 5). */
.context-shade{position:absolute;inset:0;z-index:1;pointer-events:none;background:
  linear-gradient(0deg,rgba(3,11,18,.98) 0%,rgba(3,11,18,.72) 8%,rgba(3,11,18,.3) 20%,rgba(3,11,18,.05) 34%,transparent 48%)}
.place-copy{grid-row:2;position:relative;z-index:2;display:flex;flex-direction:column;gap:18px;
  padding:clamp(34px,6vw,56px) var(--pad) clamp(44px,7vw,72px);width:100%}
.place-copy h2{max-width:14ch;font-size:clamp(30px,3.6vw,58px);font-weight:360;letter-spacing:-.04em;line-height:1.05}
.place-copy .act-statement{max-width:46ch;color:#dbe4ea}
.place-copy .beam-note{max-width:56ch}
.place-spec{display:flex;flex-wrap:wrap;gap:6px 28px;margin-top:2px}
.place-spec .act-meta{color:var(--orb-text-secondary)}
/* WEB-005B R14: the AOI corner marks are removed from Act 02. The recorded analysis grid spans
   x 0.169-0.544 of this frame and the copy column covers the left ~49% of it, so the square
   measured 72-100% hidden behind the copy at every desktop width -- and no crop fixes it, because
   pushing the square clear of the copy means cropping its own left edge away. Half a piece of
   governed geometry is worse than none. The geometry is still recorded and is still drawn, to the
   same fractions, by the inspection aid further down the page. */
.context-band .scene-label{grid-area:1/1;position:relative;right:auto;bottom:auto;z-index:2;
  align-self:end;justify-self:end;margin:0 var(--place-pad) 20px 0}

/* ---------- Act 03 — one ground, read through several layers ----------
   One shared geographic frame; only the evidence inside it changes. The radios are the state, so
   the switch works with no JavaScript, with arrow keys inside the group and with touch. Every
   panel is capped at 600 CSS px (native grid 1200), so no display ever upsamples governed pixels. */
.evidence-switch{position:relative;margin-top:clamp(34px,4vw,64px)}
.evidence-radio{position:absolute;left:0;top:0;width:1px;height:1px;margin:0;opacity:0;pointer-events:none}
/* R15 measure. The panel cap is unchanged at 600 — that is exactly the native 1200 px grid at a 2x
   device pixel ratio, and the layout never asks a governed raster for density it does not have.
   What changed is the STAGE. It used to run the full 1280 shell, so a 600 px map sat beside a 634 px
   column holding 330 px of text, and the section had empty ground on the right and under the reading
   column both. The stage is measured to its content now, and the column is stretched to the map's
   height with the subordinate footnote and the frame spec anchored to its foot. */
.evidence-stage{display:grid;grid-template-columns:minmax(0,600px) minmax(240px,394px);gap:clamp(28px,3vw,46px);align-items:stretch;max-width:1040px}
.evidence-main{min-width:0}
.evidence-tabs{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));border:1px solid var(--orb-divider);margin-bottom:clamp(18px,2vw,26px);background:var(--orb-surface)}
.evidence-tab{position:relative;display:flex;flex-direction:column;justify-content:center;gap:6px;min-height:66px;padding:11px clamp(12px,1.2vw,18px);border-right:1px solid var(--orb-divider);cursor:pointer;transition:background .2s ease}
.evidence-tab:last-child{border-right:0}
.evidence-tab-role{font-size:9px;letter-spacing:.22em;color:var(--orb-meta);transition:color .2s ease}
.evidence-tab-name{font-size:15px;font-weight:430;letter-spacing:-.005em;color:var(--orb-text-secondary);transition:color .2s ease}
/* Selection is never colour alone: a 2px underline rule, a brighter label AND a "Shown" marker. */
.evidence-tab-shown{display:none;font-size:8.5px;letter-spacing:.2em;text-transform:uppercase;color:var(--orb-cyan)}
.evidence-tab:hover .evidence-tab-name{color:var(--orb-text-primary)}
.evidence-frame{position:relative;display:grid;width:100%;max-width:600px;aspect-ratio:1/1;border:1px solid var(--orb-divider);background:#0b141a;overflow:hidden}
.evidence-plate{grid-area:1/1;position:relative;margin:0;opacity:0;visibility:hidden;transition:opacity .45s ease,visibility 0s linear .45s}
.evidence-plate>.panel-image{width:100%;height:100%;object-fit:cover}
.evidence-state{display:flex;flex-wrap:wrap;gap:6px 22px;margin:15px 0 0;font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--orb-meta)}
.evidence-side{display:grid;grid-template-columns:minmax(0,1fr);grid-template-rows:max-content 1fr;gap:22px;border-top:1px solid var(--orb-divider);padding-top:19px}
.evidence-read{grid-area:1/1;display:flex;flex-direction:column;gap:13px;opacity:0;visibility:hidden;transition:opacity .35s ease,visibility 0s linear .35s}
.evidence-role{font-size:9px;letter-spacing:.24em;text-transform:uppercase;color:var(--orb-cyan)}
.evidence-label{margin:0;font-size:clamp(15px,1.2vw,19px);font-weight:430;letter-spacing:-.01em;color:var(--orb-text-primary)}
.evidence-body{margin:0;font-size:15px;line-height:1.75;color:var(--orb-text-secondary);max-width:none}
.evidence-note{max-width:none}
/* The foot of the reading column: the subordinate structure/geology gap, the route into the
   method, and the one shared frame spec. Anchored to the bottom so it lands level with the map's
   own foot instead of leaving the column half empty. */
.evidence-foot{grid-row:2;align-self:end;display:flex;flex-direction:column;align-items:flex-start;gap:14px;border-top:1px solid var(--line-soft);padding-top:18px}
.evidence-gap{margin:0;font-size:12.5px;line-height:1.72;color:#8d99a2;font-weight:350}
.evidence-gap .mono{display:block;margin-bottom:7px;font-size:9px;letter-spacing:.26em;text-transform:uppercase;color:rgba(200,169,122,.9)}
.evidence-foot .act-meta{color:var(--orb-meta)}
#ev-terrain:checked~.evidence-stage .evidence-plate[data-layer="terrain"],
#ev-thermal:checked~.evidence-stage .evidence-plate[data-layer="thermal"],
#ev-alteration:checked~.evidence-stage .evidence-plate[data-layer="alteration"]{opacity:1;visibility:visible;transition:opacity .45s ease}
#ev-terrain:checked~.evidence-stage .evidence-read[data-layer="terrain"],
#ev-thermal:checked~.evidence-stage .evidence-read[data-layer="thermal"],
#ev-alteration:checked~.evidence-stage .evidence-read[data-layer="alteration"]{opacity:1;visibility:visible;transition:opacity .35s ease}
#ev-terrain:checked~.evidence-stage [for="ev-terrain"],
#ev-thermal:checked~.evidence-stage [for="ev-thermal"],
#ev-alteration:checked~.evidence-stage [for="ev-alteration"]{background:rgba(115,231,255,.07);box-shadow:inset 0 -2px 0 var(--orb-cyan)}
#ev-terrain:checked~.evidence-stage [for="ev-terrain"] .evidence-tab-name,
#ev-thermal:checked~.evidence-stage [for="ev-thermal"] .evidence-tab-name,
#ev-alteration:checked~.evidence-stage [for="ev-alteration"] .evidence-tab-name{color:var(--orb-text-primary)}
#ev-terrain:checked~.evidence-stage [for="ev-terrain"] .evidence-tab-role,
#ev-thermal:checked~.evidence-stage [for="ev-thermal"] .evidence-tab-role,
#ev-alteration:checked~.evidence-stage [for="ev-alteration"] .evidence-tab-role{color:var(--orb-cyan)}
#ev-terrain:checked~.evidence-stage [for="ev-terrain"] .evidence-tab-shown,
#ev-thermal:checked~.evidence-stage [for="ev-thermal"] .evidence-tab-shown,
#ev-alteration:checked~.evidence-stage [for="ev-alteration"] .evidence-tab-shown{display:block}
/* The focus ring belongs on the tab the keyboard is actually on, not on the whole group. */
#ev-terrain:focus-visible~.evidence-stage [for="ev-terrain"],
#ev-thermal:focus-visible~.evidence-stage [for="ev-thermal"],
#ev-alteration:focus-visible~.evidence-stage [for="ev-alteration"]{outline:2px solid var(--accent);outline-offset:-2px}

/* ---------- Act 04 — the result ----------
   The dominant object on the page, and dominant by scale, centring and the silence around it —
   not by a different background, and not by out-measuring an evidence panel by a few pixels. The
   map is 600 CSS px (native 1200 px grid, so 2x displays are served at exactly native density).
   The cyan corners are the Product target frame carried from the hero's lock; they are not data.
   The legend is the map's own unblended LUT, inside the same figure. */
/* R14 viewport fit: the headline and the map have to be readable together on a laptop. The map is
   sized against the viewport as well as the native-density cap, so a short screen gets a smaller
   map instead of a map that starts below the fold; a tall screen still gets the full 600 px. The
   floor keeps it from collapsing on a very short window. */
.sec-result{--result-map:max(340px,min(600px,calc(100svh - 356px)));--defs-gap:clamp(20px,2.4vw,40px)}
.sec-result .shell{display:flex;flex-direction:column;align-items:center;text-align:center}
/* No 13ch cap: it broke "Where to look first." after "look", which is the wrong place for the one
   headline the whole page is building to. The sentence sets its own measure. */
.sec-result h2{margin:0 0 16px;font-size:clamp(34px,4.1vw,64px);font-weight:370;letter-spacing:-.045em;line-height:1.02;max-width:none;text-wrap:balance}
.result-lead{margin:0 0 clamp(26px,3vw,44px);max-width:54ch;font-size:clamp(15px,1.15vw,19px);line-height:1.68;color:#c2cbd0;font-weight:350}
.priority-stage{--stage-pad:clamp(18px,2vw,30px);position:relative;margin:0;width:min(100%,calc(var(--result-map,600px) + 2 * var(--stage-pad)));max-width:calc(600px + 2 * var(--stage-pad));padding:var(--stage-pad);text-align:left;background:linear-gradient(180deg,var(--orb-surface),#050e16);border:1px solid rgba(24,50,69,.75);border-radius:3px;box-shadow:0 60px 110px -50px rgba(0,0,0,.9)}
.priority-frame{position:relative;width:100%;max-width:600px;aspect-ratio:1/1;background:#0b141a}
.priority-frame>.panel-image{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.target-frame{position:absolute;inset:-10px;pointer-events:none}
.target-frame i{position:absolute;width:22px;height:22px;border:0 solid var(--orb-target-frame);opacity:.9}
.target-frame i:nth-child(1){left:0;top:0;border-left-width:1.5px;border-top-width:1.5px}
.target-frame i:nth-child(2){right:0;top:0;border-right-width:1.5px;border-top-width:1.5px}
.target-frame i:nth-child(3){right:0;bottom:0;border-right-width:1.5px;border-bottom-width:1.5px}
.target-frame i:nth-child(4){left:0;bottom:0;border-left-width:1.5px;border-bottom-width:1.5px}
.priority-legend{margin-top:clamp(16px,1.7vw,24px);width:min(256px,62%)}
/* The ramp is a 256 x 8 image of the exact LUT; `pixelated` keeps each LUT entry a flat step
   instead of letting the browser blend neighbours into colours the map does not use. */
.priority-legend-ramp{display:block;width:100%;height:8px;image-rendering:pixelated;border-radius:1px}
.priority-legend-ends{display:flex;justify-content:space-between;margin-top:7px;font-size:10px;letter-spacing:.1em;color:var(--orb-text-secondary)}
.priority-stage .scene-label{position:static;margin-top:14px;text-align:left;text-shadow:none;color:var(--orb-meta)}
.priority-stage .scene-label span+span,.priority-stage .scene-label .scene-kind{color:var(--orb-meta)}
.priority-stage .scene-label .scene-kind{color:var(--orb-text-secondary);letter-spacing:.13em}
/* Four definitions, ending on what the score is not. The last cell is the mandatory warning.
   R15: the rules used to be a border on the cell itself, so they ran hard against the text on both
   sides and the warning cell added a second rule of its own on top. Now the gutter is real space
   and the rule sits in the MIDDLE of it, inset from the type top and bottom; the warning keeps its
   caution colour on the term, where it does not collide with anything. */
.result-defs{margin:clamp(30px,3.4vw,52px) 0 0;width:100%;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));column-gap:var(--defs-gap);border-top:1px solid var(--orb-divider);text-align:left}
.result-defs>div{position:relative;padding:22px 0 6px}
/* The rule's geometry lives on every cell and only `content` turns it on, so the responsive blocks
   below can move which cells carry one without restating where it sits. */
.result-defs>div::before{content:none;position:absolute;left:calc(var(--defs-gap) / -2);top:24px;bottom:8px;width:1px;background:var(--line-soft)}
.result-defs>div+div::before{content:""}
.result-defs dt{font-size:9px;font-family:var(--mono);letter-spacing:.24em;text-transform:uppercase;color:var(--orb-cyan);margin-bottom:10px}
.result-defs .is-not dt{color:rgba(200,169,122,.9)}
.result-defs dd{margin:0;font-size:13.5px;line-height:1.7;color:#a9b5bd}
.result-defs dd.beam-note{max-width:none;font-size:13.5px;color:#a9b5bd;padding-left:0;border-left:0}
.result-actions{display:flex;flex-wrap:wrap;justify-content:center;align-items:center;gap:clamp(22px,3vw,44px);margin-top:clamp(26px,2.8vw,40px)}

/* ---------- inspection aid ----------
   A way to look, not a published figure. The photograph is scaled and offset by the recorded
   analysis-grid fractions (web_005b.context.frame.aoi_in_frame: x 0.169063-0.544063,
   y 0.166667-0.833333 of the 3200 x 1800 master = exactly 1200 x 1200 at 30 m), so the two sides
   of the wipe are the same 36 x 36 km ground. Presentation scaling only: nothing is re-projected,
   re-coloured or filtered, and both sides are the files Acts 2-4 publish. */
.sec-inspect .shell{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,600px);gap:clamp(28px,4vw,80px);align-items:center}
.inspect-switch{position:relative;justify-self:end;width:100%;max-width:600px}
.inspect-radio{position:absolute;left:0;top:0;width:1px;height:1px;margin:0;opacity:0;pointer-events:none}
.inspect-figure{margin:0;display:flex;flex-direction:column;gap:14px}
.inspect-head{display:flex;flex-wrap:wrap;align-items:baseline;gap:10px 22px}
.inspect-against{font-size:9.5px;letter-spacing:.2em;text-transform:uppercase;color:var(--orb-meta)}
/* No row gap: each pair already carries a 44px activation box, which is the spacing. */
.inspect-pairs{display:flex;flex-wrap:wrap;gap:0 18px}
.inspect-pair{display:inline-flex;align-items:center;min-height:44px;font-size:9.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--orb-meta);cursor:pointer;border-bottom:1px solid transparent;transition:color .2s ease,border-color .2s ease}
.inspect-pair:hover{color:var(--orb-text-primary)}
.inspect-frame{position:relative;width:100%;max-width:600px;aspect-ratio:1/1;overflow:hidden;border:1px solid var(--orb-divider);background:#0b141a;--pos:50%}
.inspect-base{position:absolute;inset:0;overflow:hidden}
.inspect-base>img{position:absolute;left:-45.0835%;top:-25%;width:266.6667%;height:150%;max-width:none;object-fit:cover}
.inspect-layer{position:absolute;left:0;top:0;bottom:0;width:var(--pos);overflow:hidden;opacity:0;visibility:hidden}
.inspect-layer>img{position:absolute;left:0;top:0;height:100%;width:auto;max-width:none}
.inspect-divider{position:absolute;top:0;bottom:0;left:var(--pos);width:1px;background:rgba(255,255,255,.72);pointer-events:none}
.inspect-divider::after{content:"";position:absolute;left:-6px;top:calc(50% - 13px);width:13px;height:26px;border:1px solid rgba(255,255,255,.72);background:rgba(4,12,18,.5)}
.inspect-tags{position:absolute;left:0;right:0;top:0;display:flex;justify-content:space-between;margin:0;padding:9px 11px;font-size:9px;letter-spacing:.14em;text-transform:uppercase;color:#fbfdfe;
  text-shadow:0 0 2px rgba(2,7,11,1),0 0 5px rgba(2,7,11,.95),0 0 12px rgba(2,7,11,.85);pointer-events:none}
/* Hidden until script.js takes the range over: an input nothing listens to is worse than none. */
.inspect-range{position:absolute;inset:0;width:100%;height:100%;margin:0;opacity:0;cursor:ew-resize;display:none}
.inspect-frame.is-live .inspect-range{display:block}
.inspect-range:focus-visible+.inspect-divider{background:var(--orb-cyan);width:2px}
.inspect-note{max-width:none}
#cp-thermal:checked~.inspect-figure .inspect-layer[data-pair="thermal"],
#cp-alteration:checked~.inspect-figure .inspect-layer[data-pair="alteration"],
#cp-priority:checked~.inspect-figure .inspect-layer[data-pair="priority"]{opacity:1;visibility:visible}
#cp-thermal:checked~.inspect-figure [for="cp-thermal"],
#cp-alteration:checked~.inspect-figure [for="cp-alteration"],
#cp-priority:checked~.inspect-figure [for="cp-priority"]{color:var(--orb-text-primary);border-bottom-color:var(--orb-cyan)}
#cp-thermal:focus-visible~.inspect-figure [for="cp-thermal"],
#cp-alteration:focus-visible~.inspect-figure [for="cp-alteration"],
#cp-priority:focus-visible~.inspect-figure [for="cp-priority"]{outline:2px solid var(--accent);outline-offset:3px}

/* ---------- Solutions ----------
   The active application leads at full width; the two in development sit beneath it. One
   composition on all three cards: title, one sentence, status, lower-left, identical padding and
   identical distance from the card's own foot. The photographs are illustrative Landsat scenes of
   other places and the section footnote below the cards is what says so — the per-card captions
   that used to say it were removed at Product's instruction in R14. */
.domains{list-style:none;margin:clamp(34px,4vw,62px) 0 0;padding:0;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:clamp(16px,1.8vw,26px)}
.domain-card{position:relative;overflow:hidden;display:flex;align-items:flex-end;min-height:300px;border:1px solid var(--orb-divider);background:#0b141a;scroll-margin-top:calc(var(--header-h) + 12px)}
.domain-card.is-lead{grid-column:1/-1;min-height:clamp(340px,40vh,460px)}
/* Same height for every card's copy block, so the three titles sit the same distance off their own
   card's foot however tall the card or however long the sentence. Without this the two-line Mining
   and Marine sentences floated at a different height from Geothermal's three-line one. */
.domains{--domain-copy-h:118px}
.domain-card>img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;transition:opacity .25s ease}
.domain-card:hover>img{opacity:.92}
.domain-shade{position:absolute;inset:0;background:linear-gradient(0deg,rgba(3,11,18,.94) 0%,rgba(3,11,18,.6) 34%,rgba(3,11,18,.06) 76%)}
/* R14: one composition on all three cards — title, sentence, status, lower-left, identical
   padding. The asymmetric right gutter and the secondary cards' extra bottom padding both existed
   only to keep the copy clear of the per-card technical caption, and that caption is gone. */
.domain-copy{position:relative;z-index:2;display:flex;flex-direction:column;justify-content:flex-end;
  gap:11px;width:100%;min-height:calc(var(--domain-copy-h) + 2 * clamp(22px,2.6vw,40px));
  padding:clamp(22px,2.6vw,40px)}
.domain-copy h3{margin:0;font-size:clamp(20px,1.9vw,30px);font-weight:370;letter-spacing:-.025em;color:#fff}
.domain-copy p{margin:0;max-width:46ch;font-size:14.5px;line-height:1.7;color:#ccd7dd}
.domain-status{margin:2px 0 0;font-size:9.5px;letter-spacing:.16em;text-transform:uppercase;color:rgba(214,226,233,.82)}
.domain-status.is-active{color:var(--orb-cyan)}
/* WEB-005C R2: each card is a native link to its own /solutions/ row. The anchor wraps the copy
   block and stays STATIC on purpose -- that is what lets its ::after resolve against the card
   instead of the copy block, so one transparent overlay makes the whole card the click target
   while .domain-copy keeps its own position/z-index exactly as accepted. No CTA, no arrow, no
   hover behaviour beyond the image fade the card already had. */
.domain-link{display:block;width:100%;color:inherit;text-decoration:none}
.domain-link::after{content:"";position:absolute;inset:0;z-index:3}
/* The card clips its own overflow, so the focus ring is inset like the other contained
   surfaces on the page (evidence tabs, submenu) rather than the page default outset ring. */
.domain-link:focus-visible{outline:none}
.domain-link:focus-visible::after{outline:2px solid var(--accent);outline-offset:-2px}
.domains-note{margin-top:clamp(22px,2.4vw,34px)}


/* ---------- company mark (the About header) ---------- */
.company-parent{margin:0;font-size:9.5px;letter-spacing:.22em;text-transform:uppercase;color:var(--dim)}

/* ---------- contact: one centred Partner line (MER-240) ---------- */
.sec-contact{padding-top:clamp(44px,5vw,72px);padding-bottom:clamp(52px,6vw,88px)}
.sec-contact .shell{display:flex;justify-content:center}

/* ---------- WEB-003: deep public route pages ---------- */
/* Shared page header: kicker + H1 + intro, used at the top of every deep route.
   Deliberately subordinate in scale to the homepage hero (98px) — these are secondary pages. */
.page-hero{padding:clamp(64px,9vw,140px) var(--pad) clamp(40px,5vw,64px);background:var(--bg);border-bottom:1px solid var(--line)}
.page-hero-inner{max-width:920px}
.page-hero h1{margin:0 0 22px;font-size:clamp(34px,4.2vw,64px);font-weight:370;letter-spacing:-.03em;line-height:1.1;max-width:18ch}
.page-hero-copy{margin:0;max-width:64ch;font-size:clamp(16px,1.2vw,19px);line-height:1.7;color:#c2cbd0;font-weight:350}
.page-hero-copy+.company-parent{margin-top:22px}

/* Single padded wrapper for every deep-page content block; children below carry no padding of
   their own so a page never has to reach for an inline style. */
.page-section{position:relative;padding:clamp(50px,6.5vw,96px) var(--pad);background:var(--bg);border-top:1px solid var(--line)}
.page-section.is-deep{background:#050d13}
.page-section-head{max-width:760px;margin:0 0 clamp(28px,3.5vw,48px)}
.page-section-head h2{margin:0 0 16px;font-size:clamp(22px,2.2vw,32px);font-weight:370;letter-spacing:-.02em;line-height:1.16}

/* A renamed or moved section carries its superseded anchor along with it, so an existing deep
   link (/solutions/#mineral, /solutions/#environment, the old /pilot/#pilot-* fragments) still
   lands on what it always meant. Absolutely positioned at the origin of its container, so it takes
   no part in the layout; it inherits the header offset when it is the scroll target. The container
   (.page-section, .domain-band) must therefore be positioned itself, or the alias
   falls back to the top of the document and the link lands there (scripts/validate_site.py checks). */
.anchor-alias{position:absolute;top:0;left:0;width:0;height:0;overflow:hidden;pointer-events:none;scroll-margin-top:calc(var(--header-h) + 12px)}

/* ---------- MER-240 / Milestone 6: show-first pages ---------- */
/* Tables are show-first elements, not cards: hairline rows, a mono header, no boxes. */
.data-table{width:100%;border-collapse:collapse;border-top:1px solid var(--line)}
.data-table th,.data-table td{padding:18px 24px 18px 0;text-align:left;vertical-align:top;border-bottom:1px solid var(--line)}
.data-table thead th{padding:14px 24px 14px 0;vertical-align:bottom;font-family:var(--mono);font-weight:400;font-size:9.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--dim)}
.data-table tbody th{font-size:14.5px;line-height:1.55;font-weight:430;letter-spacing:-.005em;color:var(--text)}
.data-table td{font-size:14.5px;line-height:1.6;color:#b9c4cb}
.data-table td.mono{font-family:var(--mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase;line-height:2;color:var(--dim)}
.data-table td.is-active{color:var(--orb-cyan)}
.data-table a{color:#d5dee3;border-bottom:1px solid rgba(255,255,255,.3);transition:color .2s ease,border-color .2s ease}
.data-table a:hover{color:#fff;border-bottom-color:rgba(255,255,255,.7)}
.data-table .beam-note{max-width:54ch}
.data-table .cell-note{display:block;margin-top:8px;font-family:var(--mono);font-size:9.5px;font-weight:400;letter-spacing:.14em;text-transform:uppercase;color:rgba(200,169,122,.9)}
.data-table.is-facts tbody th{width:30%;font-family:var(--mono);font-weight:400;font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;line-height:2;color:var(--dim)}
.data-table.is-facts td{color:#e3e9ed}
.table-foot{margin:22px 0 0;max-width:72ch;font-size:13px;line-height:1.6;color:#93a1aa}

/* Solutions hub bands: one photograph per domain at full size. Capped at 1440 CSS px, which a 2x
   display fills from the 2880 px master width, so a wide screen gets a contained band rather than
   an upscaled one (sources.json -> scenes -> web_m6_placement). */
.domain-band{position:relative;overflow:hidden;display:flex;align-items:flex-end;max-width:1440px;margin-inline:auto;min-height:clamp(340px,44vw,620px);background:#0b141a;border-top:1px solid var(--line);scroll-margin-top:calc(var(--header-h) + 12px)}
.domain-band>img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.domain-band-shade{position:absolute;inset:0;background:linear-gradient(180deg,rgba(3,11,18,0) 38%,rgba(3,11,18,.84) 100%)}
.domain-band-copy{position:relative;z-index:2;display:flex;flex-direction:column;align-items:flex-start;gap:12px;padding:0 var(--pad) clamp(28px,3.2vw,48px)}
.domain-band-copy h2{margin:0;font-size:clamp(28px,3vw,46px);font-weight:360;letter-spacing:-.03em;line-height:1.05;color:#fff}
.domain-band-copy .domain-status{margin:0}
.page-note{padding:clamp(28px,3.4vw,44px) var(--pad) clamp(48px,6vw,88px);background:var(--bg)}
.page-note .act-footnote{margin-top:0}

/* The Geothermal locator map (Natural Earth, class A): the header's lead visual. */
.locator-figure{position:relative;max-width:1100px;margin:clamp(34px,4vw,56px) 0 0;border:1px solid var(--line);background:#030b12}
.locator-figure>img{display:block;width:100%;height:auto}
.locator-figure .scene-label{right:18px;bottom:14px}

/* The structure/geology gap: the empty frame at the figures' size, with the statement beside it. */
.gap-split{display:grid;grid-template-columns:minmax(0,600px) minmax(0,1fr);gap:clamp(28px,4vw,64px);align-items:start}
.gap-frame{width:100%;max-width:600px;aspect-ratio:1/1;display:flex;align-items:center;justify-content:center;padding:24px;text-align:center;border:1px dashed rgba(205,226,239,.3);background:repeating-linear-gradient(90deg,rgba(205,226,239,.035) 0 1px,transparent 1px 60px)}
.gap-frame p{margin:0;max-width:26ch;font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;line-height:1.8;color:var(--dim)}
.gap-text{margin:0;max-width:46ch;font-size:clamp(15px,1.1vw,17px);line-height:1.7;color:#c2cbd0}

/* Partner with us: the address, set large. */
.mail-address{margin:0;font-family:var(--mono);font-size:clamp(22px,3vw,40px);letter-spacing:.02em;line-height:1.3;overflow-wrap:anywhere}
.mail-address a{color:var(--text);border-bottom:1px solid rgba(255,255,255,.3);transition:border-color .2s ease}
.mail-address a:hover{border-bottom-color:#fff}

/* One closing link per page. */
.page-closing{padding:clamp(40px,5vw,72px) var(--pad);display:flex;justify-content:center;border-top:1px solid var(--line);background:var(--bg)}
.not-found .page-hero{border-bottom:0;min-height:52svh}
.not-found .text-link{margin-top:30px}

/* ---------- footer ---------- */
.site-footer{min-height:180px;padding:34px var(--pad) 46px;display:flex;justify-content:space-between;align-items:flex-end;gap:60px;background:#050d13;border-top:1px solid var(--line)}
/* The homepage story runs on one ground from Act 02 to the end, and the footer is the end of it. */
body.home .site-footer{background:var(--orb-deep);border-top:1px solid var(--line-soft)}
.footer-brand img{width:230px;height:auto;margin-left:-5px}.footer-brand span{display:block;margin-top:2px;font-size:8.5px;text-transform:uppercase;letter-spacing:.25em;color:#7f8d97}
/* The footer links sit at 8.5px, so their bare line box was only 11px tall — well under the 24px
   WCAG 2.5.8 activation target. Vertical padding gives them a real target without enlarging the
   type or loosening the footer's density; the negative block margin keeps the original spacing. */
.footer-right{max-width:760px;text-align:right}.footer-right nav{display:flex;justify-content:flex-end;gap:30px;font-size:8.5px;text-transform:uppercase;letter-spacing:.16em;margin:-7px 0 11px}.footer-right nav a{opacity:.8;padding:7px 0}.footer-right nav a:hover{opacity:1}.footer-right p{font-size:9px;line-height:1.65;color:#73838d;margin:6px 0}.footer-right .attribution{max-width:690px;margin-left:auto}.footer-right .attribution a{color:#93a1aa;border-bottom:1px solid rgba(147,161,170,.45);transition:color .2s ease,border-color .2s ease}.footer-right .attribution a:hover{color:#d5dee3;border-bottom-color:#d5dee3}

/* ---------- desktop refinements ---------- */
@media(min-width:701px){
  /* The whole 16:9 frame is on screen, so the recorded AOI fractions are true of what is drawn
     and the analysis square can be shown. */
  .context-frame{aspect-ratio:16/9}
  .context-frame>.panel-image{object-position:50% 50%}
  .aoi-mark{display:block}
}
@media(max-width:700px) and (min-width:561px){
  .context-frame{aspect-ratio:4/3}
  .context-frame>.panel-image{object-position:38% 50%}
}
@media(min-width:1101px){
  /* Wide enough for the accepted integrated composition: the copy moves onto the photograph, into
     the zone the shade protects, and the section is one image again. */
  .place-copy{grid-area:1/1;grid-row:1;align-self:end;width:min(700px,56%);
    padding:0 var(--place-pad) clamp(56px,5vw,86px)}
  /* The horizontal ramp is tight to the copy column (which ends around 49% of the band) rather
     than spread across the frame: further right it would dim the analysis square's own corners,
     and the square is Product-owned geometry that has to stay legible. */
  .context-shade{background:
    linear-gradient(0deg,rgba(3,11,18,.98) 0%,rgba(3,11,18,.78) 10%,rgba(3,11,18,.34) 26%,rgba(3,11,18,.06) 46%,transparent 62%),
    linear-gradient(90deg,rgba(3,11,18,.95) 0%,rgba(3,11,18,.88) 26%,rgba(3,11,18,.62) 42%,rgba(3,11,18,.18) 56%,rgba(3,11,18,.02) 72%,transparent 84%)}
}

/* ---------- tablet / mobile ---------- */
/* A laptop is short before it is narrow. Everything above the result map gives up a little height
   so the headline and the map read as one object rather than two scroll positions; the map itself
   is already sized against the viewport by --result-map. Nothing here fires above 1000px tall, so
   the full-size desktop composition is untouched. */
@media(max-height:1000px){
  .sec-result{padding-top:clamp(40px,4.4vw,64px);padding-bottom:clamp(44px,4.6vw,72px)}
  .sec-result h2{font-size:clamp(32px,3.4vw,50px);margin-bottom:14px}
  .result-lead{font-size:16px;line-height:1.62;max-width:66ch;margin-bottom:clamp(20px,2.2vw,30px)}
}
@media(max-width:1180px){
  /* 2 x 2: only the right-hand cell of each row carries a vertical rule, and the first row carries
     the horizontal one. A rule inherited from the 4-column layout would land mid-row. */
  .result-defs{grid-template-columns:repeat(2,minmax(0,1fr));row-gap:2px}
  .result-defs>div+div::before{content:none}
  .result-defs>div:nth-child(even)::before{content:""}
  .result-defs>div:nth-child(-n+2){border-bottom:1px solid var(--line-soft);padding-bottom:22px}
}
@media(max-width:1000px){
  .evidence-stage{grid-template-columns:minmax(0,1fr);gap:26px}
  .evidence-side{border-top:1px solid var(--orb-divider)}
  .sec-inspect .shell{grid-template-columns:minmax(0,1fr);gap:30px}
  .inspect-switch{justify-self:start}
}
@media(max-width:980px){
  :root{--header-h:76px}
  .site-header{height:var(--header-h)}
  .main-nav{display:none;position:absolute;top:var(--header-h);left:0;right:0;padding:26px var(--pad) 30px;background:#061018;border-bottom:1px solid var(--line);flex-direction:column;align-items:stretch;gap:0}.main-nav.open{display:flex}.menu-toggle{display:block}
  .nav-list{flex-direction:column;align-items:stretch;gap:0}
  .nav-list>li{border-bottom:1px solid rgba(205,226,239,.08)}
  .nav-list a,.nav-trigger{width:100%;justify-content:space-between;padding:16px 0;font-size:11px;white-space:normal}
  .nav-list a[aria-current="page"]::after{right:auto;width:22px;bottom:10px}
  .submenu{position:static;padding:0}
  .submenu ul{min-width:0;background:transparent;border:0;border-radius:0;box-shadow:none;padding:0 0 10px 18px}
  .submenu a{padding:12px 0;font-size:10.5px;white-space:normal}.submenu a:hover,.submenu a:focus-visible{background:transparent}.submenu a:focus-visible{outline-offset:2px}
  .lang-switch{border-left:0;padding-left:0;padding-top:16px;gap:16px;margin-left:-10px}
  .lang-btn{display:inline-flex;align-items:center;justify-content:flex-start;min-height:44px;min-width:44px;padding:8px 10px;font-size:11px}
  .hero-content{width:100%;max-width:680px}.hero-shade{background:linear-gradient(90deg,rgba(3,9,14,.94),rgba(3,9,14,.66) 58%,rgba(3,9,14,.16)),linear-gradient(0deg,rgba(3,9,14,.86) 0%,rgba(3,9,14,.62) 14%,rgba(3,9,14,.16) 36%,rgba(3,9,14,0) 56%)}
  .hero h1{max-width:none}
  /* Below the desktop layout the copy spans the frame, so the analytical drape stays off (it is a
     bright surface and would sit behind the copy): the hero ends on the held frame, and Acts 3
     and 4 carry the analysis. A narrow hero crops the 16:9 frame horizontally. The settled
     footprint is centred at x = 0.70, so the crop is biased right to keep its outline whole;
     script.js places nothing by geometry below 981px. */
  .hero-poster,.hero-held,.hero-video{object-position:79% 46%}
  .scene-label{bottom:16px;font-size:8.5px}
  .sec{padding-top:clamp(56px,8vw,92px);padding-bottom:clamp(56px,8vw,92px)}
  .sec-place{padding:0}
  .page-hero{padding-top:44px}
  .site-footer{align-items:flex-start;flex-direction:column}.footer-right{text-align:left}.footer-right nav{justify-content:flex-start;flex-wrap:wrap}.footer-right .attribution{margin-left:0}
}
@media(max-width:860px){
  .gap-split{grid-template-columns:1fr}
  /* Small screens read a table row by row: each row becomes a stacked group, with its header
     cell first. The column headers are kept for assistive technology only. */
  .data-table thead{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
  .data-table,.data-table tbody,.data-table tr,.data-table th,.data-table td{display:block;width:100%}
  .data-table tr{padding:16px 0;border-bottom:1px solid var(--line)}
  .data-table th,.data-table td,.data-table tbody th{padding:3px 0;border:0}
  .data-table.is-facts tbody th{width:100%}
}
@media(max-width:820px){
  .domains{grid-template-columns:1fr}
  .domain-card,.domain-card.is-lead{min-height:clamp(280px,38svh,360px)}
  /* A one-column card is taller, so the heading sits further up the photograph than it does on
     desktop; the shade has to reach it. */
  .domain-shade{background:linear-gradient(0deg,rgba(3,11,18,.96) 0%,rgba(3,11,18,.84) 38%,rgba(3,11,18,.42) 66%,rgba(3,11,18,.06) 90%)}
}
@media(max-width:700px){
  .evidence-tabs{grid-template-columns:1fr}
  .evidence-tab{border-right:0;border-bottom:1px solid var(--orb-divider);min-height:56px;flex-direction:row;align-items:center;justify-content:flex-start;flex-wrap:wrap;gap:6px 14px}
  .evidence-tab:last-child{border-bottom:0}
  /* One column: the separation is horizontal, so every vertical rule goes. */
  .result-defs{grid-template-columns:1fr;row-gap:0}
  .result-defs>div::before,.result-defs>div+div::before,
  .result-defs>div:nth-child(even)::before{content:none}
  .result-defs>div+div{border-top:1px solid var(--line-soft)}
  .result-defs>div:nth-child(-n+2){border-bottom:0;padding-bottom:6px}
  .act-footnote{gap:8px}
  .place-copy{padding-left:var(--pad);padding-right:var(--pad)}
  .context-band{--place-pad:var(--pad)}
  /* The band's caption sits bottom-right; on a phone the name and status stand above it. */
  .domain-band-copy{padding-bottom:92px}
}
@media(max-width:560px){
  .brand-wordmark{font-size:21px}.hero-content{padding-top:40px;padding-bottom:70px}.hero h1{font-size:44px}.hero-copy{font-size:15px}.button{gap:22px}
  .hero-actions{gap:18px}
  .scene-label{bottom:14px;font-size:8px;letter-spacing:.12em}
  .beam-note{font-size:12px}
  .sec-head h2,.place-copy h2{font-size:29px;max-width:none}
  .sec-result h2{font-size:32px}
  .act-statement{font-size:15px}
  .priority-stage{--stage-pad:14px}
  .target-frame{inset:-6px}.target-frame i{width:16px;height:16px}
  .domain-copy h3{font-size:21px}
  .site-footer{min-height:220px}.footer-brand img{width:210px}.footer-right nav{gap:18px}
}
/* Reduced motion: no crossfade, no rise. script.js also refuses to attach a video source at all,
   so this is the belt to that braces — the hero is a still image and the payoff simply exists. */
@media(prefers-reduced-motion:reduce){
  .hero-video{display:none}
}
@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}*{transition:none!important}}
