/* Drone Scope Mapping — marketing site.

   Palette is the documented brand system from DSM-Strategy v2 p.5, adapted to a
   dark ground: Slate carries the page, Amber is the 10% accent and never body
   text, Fog is the text colour rather than a background. The dark ground is a
   deliberate choice — the hero slot is meant to hold a live point cloud, which
   renders on black and looks pasted-in on white. See notes/reference-sites.md.

   No build step. One stylesheet, one small script, self-hosted fonts. */

:root {
  /* Brand, verbatim from the strategy doc */
  --amber:#F2B01E;
  --slate:#1E262E;
  --steel:#4A5560;
  --fog:#EDEFF2;
  --ink:#12161A;

  /* Derived for the dark ground. Steel is too dark to read as body text on
     Slate, so muted text is a lighter tint of it rather than Steel itself. */
  --bg:var(--slate);
  --bg-deep:var(--ink);
  --panel:#243039;
  --panel-2:#2A3844;
  --border:#38444F;
  --text:var(--fog);
  --muted:#9FADB8;

  /* Header height is a token because two other things depend on it: the sticky
     offset on the portal card, and the mobile nav that drops from underneath. */
  --header-h:100px;

  --page-max:1240px;
  --pad:clamp(20px, 5vw, 56px);
  --r:10px;

  --f-display:"Poppins", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --f-body:"Poppins", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

/* All four weights the Brand Guide specifies, self-hosted as woff2, latin
   subset. 30.8 KB for the set — the two .ttf files this replaced were 316 KB
   between them for half the weights.

   Latin subset only: the copy is English. The one glyph outside it is the ↗ in
   the demo button (U+2197), which falls back to the system sans and always did.
   If a page ever needs accented characters, pull the latin-ext subset too —
   the fetch is in notes/, and Google serves them per-weight.

   Weight assignments follow the guide:
     800 ExtraBold  document titles and headlines
     700 Bold       section heads, table headers, emphasis, key labels
     600 SemiBold   sub-heads and lead-in lines within a block
     400 Regular    body text, captions, everything else */
@font-face {
  font-family:"Poppins"; font-style:normal; font-weight:400; font-display:swap;
  src:url("../fonts/poppins-400.woff2") format("woff2");
}
@font-face {
  font-family:"Poppins"; font-style:normal; font-weight:600; font-display:swap;
  src:url("../fonts/poppins-600.woff2") format("woff2");
}
@font-face {
  font-family:"Poppins"; font-style:normal; font-weight:700; font-display:swap;
  src:url("../fonts/poppins-700.woff2") format("woff2");
}
@font-face {
  font-family:"Poppins"; font-style:normal; font-weight:800; font-display:swap;
  src:url("../fonts/poppins-800.woff2") format("woff2");
}

*, *::before, *::after { box-sizing:border-box; }

html { scroll-behavior:smooth; }
@media (prefers-reduced-motion:reduce) { html { scroll-behavior:auto; } }

body {
  margin:0;
  background:var(--bg);
  color:var(--text);
  font:400 16px/1.65 var(--f-body);
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}

img { max-width:100%; height:auto; display:block; }
a { color:inherit; }

.wrap { max-width:var(--page-max); margin-inline:auto; padding-inline:var(--pad); }

/* ---------- type ---------- */
/* Display type is uppercase with tight leading — the same treatment the AEC and
   Venue capability sheets already use, so the site and the collateral read as
   one system. 700 is the base; .h-xl and .h-lg override to 800. */
h1, h2, h3 { font-family:var(--f-display); font-weight:700; margin:0; }

/* ExtraBold, per the guide: "document titles and headlines, set uppercase with
   tight leading". These two carry every headline on the page. */
.h-xl { font-weight:800; font-size:clamp(2.1rem, 6vw, 4.1rem); line-height:1.02;
        letter-spacing:-0.015em; text-transform:uppercase; }
.h-lg { font-weight:800; font-size:clamp(1.7rem, 3.6vw, 2.7rem); line-height:1.08;
        letter-spacing:-0.01em; text-transform:uppercase; }
.h-md { font-size:1.06rem; line-height:1.3; text-transform:uppercase;
        letter-spacing:0.01em; }

/* One word of a heading in amber. Cheap, and it is the accent mechanic the
   brand palette specifies — rules and keylines, never body text. */
.accent { color:var(--amber); }

/* Eyebrow label with a short rule, sitting above a heading. */
.eyebrow {
  display:flex; align-items:center; gap:12px;
  font-size:0.72rem; font-weight:700; letter-spacing:0.18em;
  text-transform:uppercase; color:var(--amber); margin-bottom:16px;
}
.eyebrow::before { content:""; width:34px; height:2px; background:var(--amber); flex:none; }

.lede { font-size:clamp(1rem, 1.5vw, 1.14rem); color:var(--muted); max-width:62ch; }
p { margin:0 0 1.1em; }
p:last-child { margin-bottom:0; }

section { padding-block:clamp(56px, 8vw, 104px); }
.section-head { max-width:66ch; margin-bottom:clamp(32px, 4vw, 52px); }
.section-head p { margin-top:16px; }

/* ---------- header ---------- */
.site-header {
  position:sticky; top:0; z-index:50;
  background:rgba(18,22,26,0.82);
  backdrop-filter:blur(10px);
  border-bottom:1px solid var(--border);
}
.site-header .wrap { display:flex; align-items:center; gap:24px; min-height:var(--header-h); }
.brand { display:flex; align-items:center; gap:12px; text-decoration:none; flex:none; }

/* THE FULL LOCKUP, not the wordmark. The Brand Guide assigns the lockup to a
   website header and the wordmark to "wide, short spaces" — banners, video
   lower thirds. It also solves a legibility problem: the wordmark sets "SCOPE"
   as an OUTLINE between two solid words, and below about 190px wide that
   hairline closes up and the middle word reads as a grey smudge. In the lockup
   all three words are solid.
   Aspect is 2.065:1, so width drives height — 148px wide is 72px tall inside a
   100px bar, which leaves 14px of air above and below. */
.brand img { width:148px; height:auto; }
.nav { margin-left:auto; display:flex; align-items:center; gap:28px; }
.nav a {
  text-decoration:none; font-size:0.82rem; font-weight:700; letter-spacing:0.09em;
  text-transform:uppercase; color:var(--text); padding-block:6px;
  border-bottom:2px solid transparent;
}
.nav a:hover { border-bottom-color:var(--amber); }
.nav .tel { color:var(--muted); letter-spacing:0.04em; }

.btn {
  display:inline-block; text-decoration:none; font-family:var(--f-display);
  font-weight:700; font-size:0.8rem; letter-spacing:0.1em; text-transform:uppercase;
  padding:13px 22px; border-radius:6px; border:2px solid transparent;
  transition:background .15s ease, color .15s ease, border-color .15s ease;
}
.btn-primary { background:var(--amber); color:var(--ink); border-color:var(--amber); }
.btn-primary:hover { background:#FFC245; border-color:#FFC245; }
.btn-ghost { border-color:var(--border); color:var(--text); }
.btn-ghost:hover { border-color:var(--amber); color:var(--amber); }

.nav-toggle { display:none; background:none; border:1px solid var(--border);
  border-radius:6px; color:var(--text); padding:9px 11px; cursor:pointer; }

@media (max-width:900px) {
  :root { --header-h:84px; }
  .brand img { width:124px; }
  .nav-toggle { display:block; margin-left:auto; }
  .nav {
    position:absolute; inset:100% 0 auto; margin:0;
    flex-direction:column; align-items:stretch; gap:0;
    background:var(--bg-deep); border-bottom:1px solid var(--border);
    padding:8px var(--pad) 20px;
  }
  .nav[hidden] { display:none; }
  .nav a { padding:14px 0; border-bottom:1px solid var(--border); }
  .nav .btn { text-align:center; margin-top:14px; border-bottom:none; }
}

/* ---------- hero ---------- */
/* THE MEDIA LAYER IS A SLOT. Today it holds a still frame; it is sized and
   layered so a live point cloud canvas can replace the <img> without the copy
   above it moving. Keep the scrim — white text over a lit theatre interior
   fails contrast without it. */
.hero { position:relative; background:var(--bg-deep); overflow:hidden;
        min-height:min(88vh, 780px); display:flex; align-items:flex-end; }
.hero-media { position:absolute; inset:0; z-index:0; }
.hero-media img { width:100%; height:100%; object-fit:cover; object-position:center 42%; }
.hero-scrim {
  position:absolute; inset:0; z-index:1;
  background:
    linear-gradient(to right, rgba(18,22,26,0.94) 0%, rgba(18,22,26,0.78) 46%, rgba(18,22,26,0.35) 100%),
    linear-gradient(to top, rgba(18,22,26,0.96) 0%, rgba(18,22,26,0.10) 55%);
}
/* On a narrow screen the copy runs the full width and crosses the lit part of
   the image rather than sitting in the dark left third, so the horizontal
   gradient stops doing any work. Measured over the auditorium seating: body
   text lands on mid-tone red. Flatten the scrim instead. */
@media (max-width:760px) {
  .hero-scrim {
    background:linear-gradient(to top, rgba(18,22,26,0.97) 12%, rgba(18,22,26,0.86) 62%, rgba(18,22,26,0.55) 100%);
  }
}

.hero .wrap { position:relative; z-index:2; padding-block:clamp(48px, 9vw, 96px); width:100%; }
.hero-copy { max-width:20ch; }
.hero .lede { margin-top:22px; max-width:52ch; }
.hero-actions { display:flex; flex-wrap:wrap; gap:14px; margin-top:32px; }

/* The line that names the customer's situation, sitting under the headline.
   SemiBold: the guide's weight for a lead-in line within a block. */
.hero-hook {
  margin-top:20px; font-family:var(--f-display); font-weight:600;
  font-size:clamp(0.95rem, 1.5vw, 1.1rem); letter-spacing:0.02em;
  text-transform:uppercase; color:var(--amber);
}

/* ---------- markets strip ---------- */
/* Stands in for the client logo wall the reference sites open with. Real logos
   need written permission first — see notes/source-material-review.md. */
.strip { background:var(--bg-deep); border-block:1px solid var(--border);
         padding-block:26px; }
.strip .wrap { display:flex; flex-wrap:wrap; align-items:center;
               gap:14px 30px; justify-content:center; }
.strip span { font-family:var(--f-display); font-weight:700; font-size:0.76rem;
              letter-spacing:0.14em; text-transform:uppercase; color:var(--muted); }
.strip span.sep { color:var(--amber); }

/* ---------- split ---------- */
.split { display:grid; grid-template-columns:1fr 1fr; gap:clamp(28px, 5vw, 64px);
         align-items:center; }
.split.narrow-first { grid-template-columns:0.9fr 1.1fr; }
.split img { border-radius:var(--r); border:1px solid var(--border); }
@media (max-width:860px) {
  .split, .split.narrow-first { grid-template-columns:1fr; }
  .split.flip > :first-child { order:2; }
}

/* ---------- proof tiles ---------- */
/* Deliberately NOT the six-tile volume grid the reference sites use. DSM is two
   people; small numbers in that layout invite a comparison DSM loses. These
   report depth — one very large dataset, owned instruments — not throughput. */
.tiles { display:grid; grid-template-columns:repeat(auto-fit, minmax(220px, 1fr)); gap:16px; }
.tile { background:var(--panel); border:1px solid var(--border);
        border-top:3px solid var(--amber); border-radius:var(--r); padding:26px 24px; }
.tile b { display:block; font-family:var(--f-display); font-weight:800;
          font-size:clamp(2rem, 3.4vw, 2.7rem); line-height:1; letter-spacing:-0.02em; }
.tile .t-label { display:block; margin-top:12px; font-weight:700; font-size:0.94rem; }
.tile .t-note { display:block; margin-top:6px; font-size:0.84rem; color:var(--muted); line-height:1.5; }

/* ---------- service cards ---------- */
.cards { display:grid; grid-template-columns:repeat(auto-fit, minmax(290px, 1fr)); gap:20px; }
.card { background:var(--panel); border:1px solid var(--border); border-radius:var(--r);
        overflow:hidden; display:flex; flex-direction:column; }
.card-media { position:relative; aspect-ratio:16/10; background:var(--bg-deep); }
/* ABSOLUTE, not height:100%. In flow, an image whose height resolves against an
   aspect-ratio box falls back to its own intrinsic ratio and the box grows to
   fit — measured at 383px against 239px for the two landscape cards, which
   knocked the third card's body out of alignment. Taking the image out of flow
   leaves the container's ratio as the only thing setting the height. */
.card-media img { position:absolute; inset:0; width:100%; height:100%; object-fit:cover; }
.card-media .tag {
  position:absolute; left:14px; top:14px;
  background:rgba(18,22,26,0.86); border:1px solid var(--amber); color:var(--amber);
  font-family:var(--f-display); font-weight:700; font-size:0.66rem;
  letter-spacing:0.14em; text-transform:uppercase; padding:5px 10px; border-radius:4px;
}
.card-body { padding:24px; display:flex; flex-direction:column; flex:1; }
.card-body h3 { margin-bottom:10px; }
/* The one-line description under each card title is a lead-in to the list
   below it — SemiBold, per the guide, so it separates from the bullets. */
.card-body > p { color:var(--muted); font-size:0.94rem; font-weight:600; }
.card ul { list-style:none; margin:16px 0 0; padding:0; }
.card li { position:relative; padding-left:20px; font-size:0.92rem; margin-bottom:9px; }
.card li::before { content:""; position:absolute; left:0; top:0.55em;
  width:7px; height:7px; background:var(--amber); border-radius:1px; }
.card .card-foot { margin-top:auto; padding-top:20px; font-size:0.84rem; color:var(--muted); }

/* ---------- before / after ---------- */
/* The strongest thing DSM can show: the captured cloud beside the drawing that
   came out of it. Two static frames rather than a slider — a slider hides half
   the evidence at any moment, and both halves are the point. */
.ba { display:grid; grid-template-columns:1fr 1fr; gap:18px; }
.ba figure { margin:0; }
.ba img { border-radius:var(--r); border:1px solid var(--border); width:100%; }
.ba figcaption { margin-top:12px; font-family:var(--f-display); font-weight:700;
  font-size:0.74rem; letter-spacing:0.14em; text-transform:uppercase; color:var(--muted); }
.ba figcaption em { font-style:normal; color:var(--amber); }
@media (max-width:700px) { .ba { grid-template-columns:1fr; } }

/* ---------- band ---------- */
/* A full-container-width photograph used as a section image rather than beside
   copy. Same frame treatment as the split images so it reads as one system. */
.band { margin:0 0 clamp(28px, 4vw, 44px); }
.band img {
  width:100%; border-radius:var(--r); border:1px solid var(--border);
}

/* ---------- platform slider ---------- */
/* CSS-FIRST, and it has to stay that way: with JS off this is a horizontally
   scrollable strip with snap points, so every photo is still reachable by
   swipe or trackpad and nothing is stranded. site.js adds the buttons, the
   dots and the auto-advance on top; the controls are hidden until the .js
   class is set, the same bargain .reveal makes. */
.slider { position:relative; }
.slider-viewport {
  overflow-x:auto; overflow-y:hidden;
  scroll-snap-type:x mandatory; scroll-behavior:smooth;
  border-radius:var(--r); border:1px solid var(--border);
  -webkit-overflow-scrolling:touch;
  scrollbar-width:none;
}
.slider-viewport::-webkit-scrollbar { display:none; }
.slider-viewport:focus-visible { outline:2px solid var(--amber); outline-offset:3px; }
.slider-track { display:flex; margin:0; padding:0; list-style:none; }
.slider-track > li { flex:0 0 100%; min-width:0; scroll-snap-align:center; }
/* The frame moved to the viewport, so the images inside must not carry their
   own. Two classes deep on purpose — .band img would otherwise tie on
   specificity and leave this depending on rule order. */
.slider .slider-track img { display:block; width:100%; border:0; border-radius:0; }

.slider-nav {
  position:absolute; top:50%; transform:translateY(-50%);
  width:42px; height:42px; border-radius:50%;
  display:grid; place-items:center; cursor:pointer;
  background:rgba(18,22,26,0.72); border:1px solid var(--border);
  color:#fff; padding:0;
}
.slider-nav:hover { background:rgba(18,22,26,0.92); border-color:var(--amber); }
.slider-nav:focus-visible { outline:2px solid var(--amber); outline-offset:2px; }
.slider-nav.prev { left:14px; }
.slider-nav.next { right:14px; }

.slider-dots {
  position:absolute; left:50%; bottom:14px; transform:translateX(-50%);
  display:flex; gap:8px; margin:0; padding:7px 10px; list-style:none;
  background:rgba(18,22,26,0.72); border:1px solid var(--border);
  border-radius:999px;
}
.slider-dot {
  display:block; width:8px; height:8px; padding:0; border-radius:50%;
  background:rgba(255,255,255,0.42); border:0; cursor:pointer;
}
.slider-dot[aria-current="true"] { background:var(--amber); }
.slider-dot:focus-visible { outline:2px solid var(--amber); outline-offset:3px; }

/* No JS: the controls would do nothing, so they are not shown at all. */
html:not(.js) .slider-nav,
html:not(.js) .slider-dots { display:none; }

/* Room is tight on a phone: drop the arrows and let the strip be swiped, which
   is the native gesture there anyway. The dots stay as the position readout. */
@media (max-width:700px) {
  .slider-nav { display:none; }
}

@media (prefers-reduced-motion:reduce) {
  .slider-viewport { scroll-behavior:auto; }
}

/* ---------- portal ---------- */
/* Sticky so it stays beside the three explanatory blocks as they scroll past —
   the call to action is the point of the section, and it should not scroll away
   while the reader is still being told what it does. Falls back harmlessly to a
   static box on short viewports and on browsers without position:sticky. */
.portal-cta {
  background:var(--panel); border:1px solid var(--border);
  border-top:3px solid var(--amber); border-radius:var(--r);
  padding:clamp(24px, 3vw, 34px);
  position:sticky; top:calc(var(--header-h) + 24px);
}
.portal-note {
  margin-top:18px; padding-top:16px; border-top:1px solid var(--border);
  font-size:0.82rem; color:var(--muted);
}
@media (max-width:860px) { .portal-cta { position:static; } }

/* ---------- roles ---------- */
.roles { display:grid; gap:0; border-top:1px solid var(--border); }
.role { display:grid; grid-template-columns:minmax(0,260px) 1fr; gap:clamp(16px,4vw,48px);
        padding-block:30px; border-bottom:1px solid var(--border); align-items:start; }
.role h3 { color:var(--text); }
.role p { color:var(--muted); margin:0; }
@media (max-width:760px) { .role { grid-template-columns:1fr; gap:12px; } }

/* ---------- platform ---------- */
.kit { display:grid; grid-template-columns:repeat(auto-fit, minmax(255px,1fr)); gap:18px; }
.kit-item { background:var(--panel); border:1px solid var(--border);
            border-left:3px solid var(--amber); border-radius:var(--r); padding:22px 24px; }
.kit-item .k-role { font-family:var(--f-display); font-weight:700; font-size:0.68rem;
  letter-spacing:0.16em; text-transform:uppercase; color:var(--amber); }
.kit-item h3 { margin:8px 0 10px; font-size:1.02rem; text-transform:none; letter-spacing:0; }
.kit-item p { font-size:0.9rem; color:var(--muted); margin:0; }

/* ---------- scope note ---------- */
/* The disclaimer ships at the point of the claim, not in the footer. It is the
   same position as the contract and the deliverable title blocks — this is the
   third surface, and the one a stranger actually reads. Styled to be read, not
   to be hidden: amber keyline, full contrast body. */
.scope { background:var(--panel); border:1px solid var(--border);
         border-left:3px solid var(--amber); border-radius:var(--r);
         padding:clamp(24px, 3vw, 34px); }
.scope h2 { font-size:1rem; text-transform:uppercase; letter-spacing:0.04em; margin-bottom:14px; }
.scope p { font-size:0.94rem; color:var(--muted); }
.scope strong { color:var(--text); font-weight:700; }

/* ---------- faq ---------- */
.faq { border-top:1px solid var(--border); }
.faq details { border-bottom:1px solid var(--border); }
.faq summary {
  cursor:pointer; list-style:none; padding:22px 40px 22px 0; position:relative;
  font-family:var(--f-display); font-weight:700; font-size:1rem;
}
.faq summary::-webkit-details-marker { display:none; }
.faq summary::after {
  content:"+"; position:absolute; right:6px; top:50%; transform:translateY(-50%);
  color:var(--amber); font-size:1.5rem; line-height:1; font-weight:400;
}
.faq details[open] summary::after { content:"–"; }
.faq details p { padding:0 0 24px; color:var(--muted); max-width:74ch; }

/* ---------- cta ---------- */
.cta { background:var(--bg-deep); border-top:1px solid var(--border); text-align:center; }
.cta .wrap { max-width:760px; }
.cta .lede { margin-inline:auto; margin-top:18px; }
.cta-actions { display:flex; flex-wrap:wrap; gap:14px; justify-content:center; margin-top:32px; }

/* ---------- footer ---------- */
.site-footer { background:var(--bg-deep); border-top:1px solid var(--border);
               padding-block:48px 36px; font-size:0.9rem; }
.foot-grid { display:grid; grid-template-columns:1.4fr 1fr 1fr; gap:36px; }
.site-footer img { width:186px; height:auto; margin-bottom:16px; }
.site-footer h3 { font-size:0.72rem; letter-spacing:0.16em; text-transform:uppercase;
  color:var(--amber); margin-bottom:14px; }
.site-footer ul { list-style:none; margin:0; padding:0; }
.site-footer li { margin-bottom:9px; color:var(--muted); }
.site-footer a { color:var(--muted); text-decoration:none; }
.site-footer a:hover { color:var(--amber); }
.foot-base { margin-top:38px; padding-top:22px; border-top:1px solid var(--border);
  display:flex; flex-wrap:wrap; gap:12px 24px; justify-content:space-between;
  color:var(--steel); font-size:0.8rem; }
.foot-base .muted { color:var(--muted); }
@media (max-width:760px) { .foot-grid { grid-template-columns:1fr; gap:28px; } }

/* ---------- reveal ---------- */
/* Progressive enhancement only: without JS everything is visible, because the
   class is added by script. Disabled entirely under reduced-motion. */
.js .reveal { opacity:0; transform:translateY(14px); }
.js .reveal.in { opacity:1; transform:none; transition:opacity .5s ease, transform .5s ease; }
@media (prefers-reduced-motion:reduce) {
  .js .reveal { opacity:1; transform:none; }
  .js .reveal.in { transition:none; }
}

:focus-visible { outline:2px solid var(--amber); outline-offset:3px; }

.skip {
  position:absolute; left:-9999px; top:0; background:var(--amber); color:var(--ink);
  padding:12px 18px; font-weight:700; z-index:100;
}
.skip:focus { left:0; }
