/* ============================================================
   SkyShield Technology — shared stylesheet
   Single dark theme, deliberately: the product's own world (the
   ground station, the ops room) is dark. Every colour is painted
   explicitly so nothing depends on a host background.
   ============================================================ */
/* Dusk, not midnight: the ground is a blue-hour sky rather than flat black, and it lifts
   toward the right the way the last light does. Surfaces are translucent over it so that
   gradient stays visible through the whole page instead of being covered by opaque bands. */
:root{
  --ink:#0b1a2b;
  --panel:#102438;
  --panel-2:#16304a;
  --line:#22456a;
  --line-soft:#193754;
  --accent:#3fb4f2;
  --accent-dim:#2585c2;
  --amber:#f5b055;
  --text:#eef4fa;
  --muted:#9db3c9;
  /* Lifted from #7290ac: against the lightest part of the dusk gradient that measured 3.61
     contrast, under the 4.5 AA threshold for the small uppercase labels this colour is
     used on. This clears it. */
  --muted-2:#93aec7;

  --surface:rgba(10,22,37,.55);
  --surface-alt:rgba(14,30,48,.55);

  --display:"Saira Condensed",-apple-system,"Segoe UI",sans-serif;
  --body:"Archivo",-apple-system,"Segoe UI",Roboto,sans-serif;
  --mono:"IBM Plex Mono",ui-monospace,"SFMono-Regular",Consolas,monospace;

  /* Wide content column with a slim gutter: at 1240px the page left a couple of hundred
     pixels of dead space each side on a large display, which also made the content look
     detached from the full-bleed header. This keeps it close to the header's own inset. */
  --wrap:1680px;
  --pad:clamp(16px,2vw,34px);
}
*{box-sizing:border-box}
html{scroll-behavior:smooth}
/* The header is sticky and 70px tall, so without this every in-page jump -- #contact,
   #connect, the partner form -- lands with its heading tucked underneath it. */
html{scroll-padding-top:84px}
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.001ms!important;transition-duration:.001ms!important}
}
body{
  margin:0;background:var(--ink);color:var(--text);
  font-family:var(--body);font-size:16px;line-height:1.62;
  -webkit-font-smoothing:antialiased;
}
/* The dusk sky itself. On a fixed pseudo-element rather than background-attachment:fixed,
   which janks badly on mobile. Light sits top-right and falls away to the left, with a
   thin warm band low on the right where the sun has just gone. */
body::before{
  content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;
  background:
    radial-gradient(1250px 820px at 97% 6%,rgba(125,180,230,.24),transparent 62%),
    radial-gradient(950px 640px at 104% 46%,rgba(247,178,124,.10),transparent 60%),
    linear-gradient(103deg,#08131f 0%,#0b1c2e 36%,#122843 68%,#1a3856 100%);
}
img{max-width:100%;display:block}
a{color:inherit}
:focus-visible{outline:2px solid var(--accent);outline-offset:3px}
.wrap{max-width:var(--wrap);margin:0 auto;padding-inline:var(--pad)}

/* ---------- type ---------- */
.eyebrow{
  font-family:var(--mono);font-size:12.5px;letter-spacing:.18em;
  text-transform:uppercase;color:var(--accent);margin:0 0 14px;
}
.eyebrow.amber{color:var(--amber)}
h1,h2,h3,h4{font-family:var(--display);font-weight:700;text-wrap:balance;margin:0;line-height:1.04}
h2.h2{font-size:clamp(30px,4.4vw,54px);letter-spacing:-.005em}
h3{font-size:clamp(19px,2vw,23px);line-height:1.2;letter-spacing:.01em}
p{margin:0 0 16px}
.lede{font-size:clamp(16px,1.35vw,18.5px);color:var(--muted);max-width:60ch}
.sub{color:var(--muted);max-width:62ch}

/* ---------- header ---------- */
header{
  position:sticky;top:0;z-index:60;
  background:rgba(9,20,33,.78);backdrop-filter:blur(16px);
  border-bottom:1px solid var(--line-soft);
}
/* Full-bleed bar rather than the centred content column, so the mark sits hard against
   the left edge on any screen width instead of drifting inward as the viewport grows. */
.navbar{
  max-width:none;margin:0;padding-inline:clamp(14px,1.6vw,26px);
  height:70px;display:flex;align-items:center;gap:26px;
}
.brand{display:flex;align-items:center;gap:11px;text-decoration:none;flex-shrink:0}
.brand img{width:42px;height:42px;object-fit:contain}
.brand-name{display:flex;flex-direction:column;line-height:1}
.brand-name b{
  font-family:var(--display);font-weight:700;font-size:25px;
  letter-spacing:.045em;text-transform:uppercase;color:var(--text);
}
/* One colour. Splitting SKY and SHIELD across two colours read as two words rather than
   one company name, and the logo beside it already carries the accent. */
.brand-name b i{font-style:normal;color:inherit}
.brand-name span{
  font-family:var(--mono);font-size:10px;letter-spacing:.26em;
  text-transform:uppercase;color:var(--muted-2);margin-top:5px;
}
nav.links{margin-left:auto;display:flex;gap:26px}
nav.links a,.nav-contact{
  font-family:var(--mono);font-size:12px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--muted);text-decoration:none;padding:6px 0;
  border-bottom:1px solid transparent;transition:color .18s,border-color .18s;
}
nav.links a:hover,nav.links a:focus-visible,
.nav-contact:hover,.nav-contact:focus-visible{color:var(--text);border-bottom-color:var(--accent)}
nav.links a[aria-current="page"]{color:var(--text);border-bottom-color:var(--accent)}
/* Its own element rather than a fifth item inside nav.links, on purpose: nav.links
   disappears below 940px (next rule), and this is what has to stay reachable on a phone
   -- same job it did back when this was styled as a standalone button. margin-left:auto
   with the sibling override at 0 is the same pairing nav.links itself uses, so the two
   sit as one right-aligned cluster on desktop, and this alone remains on mobile. */
.nav-contact{margin-left:auto}
nav.links ~ .nav-contact{margin-left:0}
/* ---------- mobile menu ----------
   Below 940px the five links no longer fit beside the mark. They used to simply vanish,
   which left a phone with no route to Ravin, the GCS, the rental page or the partner form
   except through links buried inside the pages. They now fold behind a menu button.

   The collapsed version is gated on .js, which an inline script in each page's <head>
   sets before first paint. Without JS the button would be dead, so the links fall back to
   a wrapped row under the mark instead -- always reachable, just not folded away. Setting
   the flag that early, rather than from site.js at the end of the body, is what stops
   that fallback row flashing up and then collapsing on every page load. */
.nav-toggle{display:none}
@media (max-width:940px){
  .navbar{flex-wrap:wrap;height:auto;min-height:70px}
  nav.links{order:3;flex-basis:100%;margin-left:0;flex-wrap:wrap;gap:2px 18px;padding-bottom:8px}
  /* Pushes Contact to the right edge. The desktop pairing (nav.links carrying the auto
     margin, this one zeroed) stops working once the links leave the row, and Contact was
     left sitting hard against the mark. */
  nav.links ~ .nav-contact{margin-left:auto}

  .js .navbar{flex-wrap:nowrap;height:70px}
  /* Solid, unlike the header's translucent tint: the page's headline showed through behind
     the links. top clears the header's 1px border, which then reads as the divider. */
  .js nav.links{
    display:none;position:absolute;left:0;right:0;top:calc(100% + 1px);
    flex-direction:column;gap:0;padding:4px clamp(14px,1.6vw,26px) 10px;
    background:var(--ink);border-bottom:1px solid var(--line-soft);
    box-shadow:0 18px 30px rgba(0,0,0,.35);
  }
  .js header.nav-open nav.links{display:flex}
  .js nav.links a{padding:15px 0;font-size:13px;border-bottom:1px solid var(--line-soft)}
  .js nav.links a:last-child{border-bottom:0}
  .js nav.links a[aria-current="page"]{color:var(--accent);border-bottom-color:var(--line-soft)}

  .js .nav-toggle{
    display:flex;flex-direction:column;justify-content:center;align-items:center;gap:5px;
    width:44px;height:44px;margin-right:-10px;padding:0;
    background:transparent;border:0;cursor:pointer;color:var(--text);
  }
  .nav-toggle span{display:block;width:22px;height:2px;background:currentColor;transition:transform .2s,opacity .2s}
  header.nav-open .nav-toggle span:nth-child(1){transform:translateY(7px) rotate(45deg)}
  header.nav-open .nav-toggle span:nth-child(2){opacity:0}
  header.nav-open .nav-toggle span:nth-child(3){transform:translateY(-7px) rotate(-45deg)}

  /* The two header controls that stay on screen, brought up to a 44px tap height. */
  .nav-contact{padding:13px 4px}
  .brand{padding-block:5px}
}
@media (max-width:560px){
  .navbar{gap:12px}
  .brand img{width:34px;height:34px}
  .brand-name b{font-size:20px}
  .brand-name span{font-size:9.5px;letter-spacing:.22em;margin-top:4px}
}

/* ---------- buttons ---------- */
.btn{
  font-family:var(--mono);font-size:12.5px;letter-spacing:.1em;text-transform:uppercase;
  text-decoration:none;padding:13px 22px;border-radius:2px;font-weight:500;
  display:inline-block;transition:background .18s,border-color .18s,color .18s;
}
.btn-primary{background:var(--accent);color:var(--ink)}
.btn-primary:hover{background:#4dbcf9}
.btn-ghost{border:1px solid var(--line);color:var(--text)}
.btn-ghost:hover{border-color:var(--accent);color:var(--accent)}
.actions{display:flex;flex-wrap:wrap;gap:12px}

/* ---------- hero ---------- */
.hero{
  position:relative;border-bottom:1px solid var(--line-soft);
  background:radial-gradient(1000px 520px at 68% 6%,rgba(63,180,242,.13),transparent 64%);
  overflow:hidden;
}
.hero::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background-image:linear-gradient(var(--line-soft) 1px,transparent 1px),
                   linear-gradient(90deg,var(--line-soft) 1px,transparent 1px);
  background-size:76px 76px;
  -webkit-mask-image:radial-gradient(820px 500px at 55% 10%,#000 20%,transparent 76%);
  mask-image:radial-gradient(820px 500px at 55% 10%,#000 20%,transparent 76%);
  opacity:.45;
}
.hero-inner{
  position:relative;z-index:1;max-width:var(--wrap);margin:0 auto;
  padding:clamp(46px,6vw,78px) var(--pad) clamp(40px,5vw,64px);
  display:grid;grid-template-columns:1fr .92fr;gap:clamp(20px,3vw,48px);align-items:center;
}
@media (max-width:960px){.hero-inner{grid-template-columns:1fr;gap:8px}}
.hero h1{
  font-size:clamp(38px,5.6vw,72px);letter-spacing:-.015em;font-weight:800;
  margin:0 0 20px;max-width:14ch;
}
.hero h1 em{font-style:normal;color:var(--accent);display:block}
.hero .lede{margin-bottom:28px}
/* ---------- hero aircraft, in flight ----------
   The render's propellers are already motion-blurred discs, so spinning something on top
   of them fights the image rather than adding to it. What actually sells "airborne" is
   the airframe itself never sitting perfectly still: a long, shallow rise-and-bank on an
   odd-numbered period so the two axes drift out of phase and the loop never reads as a
   loop. Paused outright for anyone who asked for reduced motion. */
/* Amplitude roughly doubled from the original shallow-float pass -- that read as static at
   a glance rather than alive. Still one continuous bank-and-climb, not a bounce: the rotate
   values stay small enough that it reads as flight, not a wobble. */
.hero-art{width:100%;display:block;will-change:transform;animation:fly 9s ease-in-out infinite}
@keyframes fly{
  0%   {transform:translate3d(0,0,0) rotate(0deg)}
  28%  {transform:translate3d(6px,-26px,0) rotate(-1.6deg)}
  55%  {transform:translate3d(-4px,-10px,0) rotate(1deg)}
  78%  {transform:translate3d(8px,-32px,0) rotate(-.8deg)}
  100% {transform:translate3d(0,0,0) rotate(0deg)}
}
@media (prefers-reduced-motion:reduce){.hero-art{animation:none}}
@media (max-width:960px){.hero-art{max-width:560px;margin-inline:auto}}

/* ---------- scroll reveal ----------
   Sections start slightly low and transparent and settle as they enter view. The class is
   added by script, so with JS off nothing is ever left invisible. */
.reveal{opacity:0;transform:translate3d(0,18px,0);
        transition:opacity .7s cubic-bezier(.22,.61,.36,1),transform .7s cubic-bezier(.22,.61,.36,1)}
.reveal.in{opacity:1;transform:none}
@media (prefers-reduced-motion:reduce){.reveal{opacity:1;transform:none;transition:none}}

/* page hero for interior pages — no product art, tighter */
.pagehead{
  border-bottom:1px solid var(--line-soft);
  background:radial-gradient(900px 420px at 26% 0%,rgba(63,180,242,.11),transparent 64%);
}
.pagehead .wrap{padding-block:clamp(46px,6vw,86px)}
/* No max-width: the headline is meant to run the full column and use the right-hand side
   of the screen, which sat empty when it was capped at 16ch. The lede stays measured. */
/* Cap raised from 62px so the headline keeps growing on large displays and actually
   reaches the right-hand side, rather than stopping short and leaving the column empty. */
.pagehead h1{font-size:clamp(34px,4.7vw,86px);letter-spacing:-.015em;font-weight:800;margin-bottom:20px;max-width:none}
.pagehead .lede{max-width:74ch}
.pagehead h1 em{font-style:normal;color:var(--accent)}

/* ---------- stat counters ---------- */
.stats{border-top:1px solid var(--line-soft);border-bottom:1px solid var(--line-soft);background:rgba(7,16,28,.40)}
.stats .row{
  max-width:var(--wrap);margin:0 auto;padding-inline:var(--pad);
  display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));
}
.stat{padding:22px 22px 22px 0;border-right:1px solid var(--line-soft)}
.stat:last-child{border-right:0}
.stat b{
  display:block;font-family:var(--display);font-weight:700;
  font-size:clamp(24px,2.8vw,34px);letter-spacing:.01em;color:var(--text);
  font-variant-numeric:tabular-nums;line-height:1.05;
}
.stat span{
  display:block;font-family:var(--mono);font-size:10px;letter-spacing:.15em;
  text-transform:uppercase;color:var(--muted-2);margin-top:6px;
}
@media (max-width:700px){.stat{border-right:0;border-bottom:1px solid var(--line-soft);padding-right:0}}

/* ---------- sections ---------- */
section.band{padding:clamp(58px,8vw,104px) 0;border-bottom:1px solid var(--line-soft);background:transparent}
section.band.alt{background:rgba(7,16,28,.34)}
/* The 64ch cap used to sit on the whole block, which is a body-text measure — at display
   sizes it forced short headings to wrap after three or four words and left the right of
   the column empty. Cap the paragraph instead and let the heading use the width. */
.sechead{max-width:none;margin-bottom:clamp(30px,4vw,48px)}
.sechead h2.h2{margin-bottom:14px;max-width:24ch}
.sechead .lede,.sechead .sub{max-width:66ch}

/* full-bleed visual rest: a statement and an image, no body copy */
.statement{
  position:relative;border-bottom:1px solid var(--line-soft);
  background:rgba(18,40,63,.42);overflow:hidden;
}
.statement img,.statement video{width:100%;display:block}
.statement .cap{
  max-width:var(--wrap);margin:0 auto;padding:clamp(30px,4vw,52px) var(--pad);
}
.statement h2{font-size:clamp(28px,4.2vw,52px);letter-spacing:-.005em;max-width:18ch}
.statement h2 em{font-style:normal;color:var(--accent)}

/* ---------- form ----------
   The site has no backend -- submitting composes a pre-filled email rather than posting
   anywhere (see site.js). Styled to look like a real form because it behaves like one;
   the honesty is in the copy on the page, not in making the fields look provisional. */
.formgrid{display:grid;grid-template-columns:1fr 1fr;gap:18px;margin-top:clamp(24px,3vw,34px)}
.formgrid .field.full{grid-column:1/-1}
@media (max-width:640px){.formgrid{grid-template-columns:1fr}}
.field label{
  display:block;font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--muted-2);margin-bottom:8px;
}
/* 16px, not 15: iOS Safari zooms the whole page when a field under 16px takes focus,
   and leaves it zoomed after the keyboard closes. Padding is 13px rather than 12 to take
   the fields past a 44px tap height; they sat at 42. */
.field input,.field select,.field textarea{
  width:100%;background:var(--panel);border:1px solid var(--line);border-radius:3px;
  color:var(--text);font-family:var(--body);font-size:16px;padding:13px 14px;
  transition:border-color .15s;
}
.field textarea{resize:vertical;min-height:110px;line-height:1.5}
.field input:focus,.field select:focus,.field textarea:focus{
  outline:none;border-color:var(--accent);
}
.field input::placeholder,.field textarea::placeholder{color:var(--muted-2)}
/* Plain <select>, styled minimally rather than replaced -- a custom dropdown widget is a
   lot of machinery (keyboard nav, screen-reader state) to rebuild for one field. */
.field select{appearance:none;-webkit-appearance:none;cursor:pointer;
  background-image:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="10" height="6"><path d="M0 0l5 6 5-6z" fill="%239db3c9"/></svg>');
  background-repeat:no-repeat;background-position:right 14px center;padding-right:34px;
}
.field select option{background:var(--panel)}
/* CV hand-off row: a button and its explanation, stacked, rather than the label-over-input every
   other field uses. The [hidden] rule is not redundant -- .field.cvrow outranks [hidden]'s own
   display:none, so without it the row would show even while unconfigured. */
.field.cvrow{display:flex;flex-direction:column;align-items:flex-start;gap:10px}
.field.cvrow[hidden]{display:none}
.cvnote{color:var(--muted-2);font-size:13px;line-height:1.55;max-width:62ch;margin:0}

.form-status{
  margin-top:14px;font-family:var(--mono);font-size:12.5px;letter-spacing:.03em;
  color:var(--accent);display:none;
}
.form-status.show{display:block}

/* ---------- two-column prose ----------
   For a section that is genuinely two distinct short ideas (not a heading + one lede),
   set side by side rather than stacked -- avoids the empty-right-column look a single
   capped paragraph gets on a wide screen with nothing else to fill the row. */
.prose2{display:grid;grid-template-columns:1fr 1fr;gap:clamp(28px,4vw,56px);
        margin-top:clamp(22px,2.8vw,30px)}
.prose2 p{color:var(--muted);font-size:16px;line-height:1.7;margin:0;max-width:52ch}
@media (max-width:760px){.prose2{grid-template-columns:1fr}}

/* ---------- image rotator ----------
   Crossfades between stacked real screenshots on a timer (site.js). With JS off, only
   the first image ever gets the "active" class removed from it -- it stays opacity:1
   and simply doesn't rotate, so this degrades to a normal static screenshot rather than
   an empty frame. aspect-ratio holds the frame's height since absolutely positioned
   slides contribute none of their own. */
.rotator{position:relative;aspect-ratio:2880/1661;border-radius:2px;overflow:hidden}
.rotator img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
             display:block;opacity:0;transition:opacity .7s ease}
.rotator img.active{opacity:1}

/* ---------- media frames ---------- */
.screenframe{
  border:1px solid var(--line);border-radius:4px;background:rgba(12,26,42,.72);padding:6px;
  box-shadow:0 30px 80px -30px rgba(0,0,0,.85),0 0 0 1px rgba(46,168,238,.07);
}
.screenframe img,.screenframe video{border-radius:2px;width:100%;display:block}
.screenframe video{background:#000}
.plate-light{
  background:#f2f6fa;border:1px solid var(--line);border-radius:4px;
  padding:clamp(12px,1.6vw,20px);
}
.plate-light img{width:100%;border-radius:2px}
/* Caps a frame at its image's native width so a capture is never upscaled. Used on the
   SAR evidence shot: at 1024px source it was being stretched to 1353px, which softened
   the alert text and the per-person confidences — the details that make it convincing. */
.screenframe.native{max-width:1036px;margin-inline:auto}

.shot-cap{
  font-family:var(--mono);font-size:12px;letter-spacing:.09em;text-transform:uppercase;
  color:var(--muted-2);margin:12px 0 0;display:flex;gap:10px;align-items:center;flex-wrap:wrap;
}
.shot-cap::before{content:"";width:6px;height:6px;border-radius:50%;background:var(--accent);flex-shrink:0}

/* ---------- AI alert slideshow ----------
   Each slide carries the station's own alert banner still in frame, so the claim the
   section makes and the proof of it are the same picture. One frame at full column width
   rather than a grid of five — the banner text is the entire point of the shot, and at
   grid size it falls below readable. The captions repeat it in the page's own type
   because the baked-in banner is small on a phone, and a screenshot's text is invisible
   to search and to a screen reader. */

/* Capped well inside the 1680px column, the way .screenframe.native already is. At the
   full column width the 1.71:1 capture renders about 980px tall, which fills a laptop
   viewport on its own and pushes the caption off the bottom of the screen — you cannot
   see the alert and what it says at the same time, which is the entire point of the
   block. At this width the slide is roughly 650px tall and the caption sits under it in
   the same view. The side margins this leaves are deliberate, not spare space. */
.alertshow{position:relative;max-width:1120px;margin-inline:auto}

/* The five captures came off the display a few pixels apart in height (932-945 at 1600
   wide). Pinning the ratio stops the frame resizing between slides, which would otherwise
   shunt everything below it up and down on every crossfade. */
.alertstage{position:relative;aspect-ratio:1600/938;border-radius:2px;overflow:hidden;background:#000}
.alertstage img{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block;
  opacity:0;transition:opacity .7s ease;
}
.alertstage img.active{opacity:1}

/* All five captions share one grid cell, so the block is as tall as the longest of them
   and nothing below moves when the slide changes; a caption wrapping to two lines would
   otherwise shunt the section below it down on every crossfade. visibility (not display)
   because it also takes the inactive captions out of the accessibility tree. */
.alertcaps{display:grid;margin-top:16px}
.acap{grid-area:1/1;opacity:0;visibility:hidden;transition:opacity .35s ease}
.acap.active{opacity:1;visibility:visible}
.acap .atype{
  display:block;font-family:var(--mono);font-size:10.5px;letter-spacing:.15em;
  text-transform:uppercase;color:var(--amber);margin-bottom:7px;
}
.acap b{
  display:block;font-family:var(--display);font-weight:600;letter-spacing:.01em;
  font-size:clamp(18px,1.7vw,23px);line-height:1.25;color:var(--text);
}
.acap .ameta{
  display:block;font-family:var(--mono);font-size:11.5px;letter-spacing:.06em;
  color:var(--muted-2);margin-top:8px;
}
/* Amber on these labels means "the station raised an alert". The rental page uses the same
   component for a plain tour of the screens, where amber would imply an alarm that isn't
   there, so that one carries .accent and takes the ordinary blue. */
.alertshow.accent .atype{color:var(--accent)}

/* With the manual controls gone, the slideshow is the only way to reach slides 2-5, so it
   has to keep advancing even here — stopping it would leave a reduced-motion visitor on
   the first alert forever. What gets removed is the animation, not the progression: the
   slide and its caption cut straight over instead of crossfading. */
@media (prefers-reduced-motion:reduce){
  .alertstage img,.acap{transition:none}
}

/* ---------- demo capture block ----------
   Narrower than the content column on purpose: at full width the capture competes with the
   screenshots above it, and it reads better as a closing exhibit than as another panel. */
/* ---------- flight video slot ----------
   Unlike the demo-capture block, this one shows a visible placeholder when the file is
   absent: it is a reserved slot for footage that does not exist yet, so it should look
   deliberately empty rather than silently vanish. */
.flightslot{margin:0}
.flightslot .screenframe{padding:0;overflow:hidden}
.flightslot video{width:100%;display:block;background:#000}
/* display:block above outranks the UA stylesheet's [hidden]{display:none}, which would
   otherwise leave an empty player sitting above the placeholder. Put it back explicitly. */
.flightslot video[hidden]{display:none}
.vidplaceholder{
  aspect-ratio:16/9;display:grid;place-content:center;justify-items:center;gap:14px;
  text-align:center;padding:clamp(20px,4vw,44px);
  background:
    radial-gradient(700px 320px at 50% 40%,rgba(46,168,238,.10),transparent 70%),
    repeating-linear-gradient(135deg,transparent 0 12px,rgba(23,50,79,.35) 12px 13px),
    rgba(12,26,42,.62);
}
.vidplaceholder svg{width:clamp(44px,5vw,62px);height:auto;opacity:.85}
.vidplaceholder b{
  font-family:var(--display);font-weight:700;letter-spacing:.01em;
  font-size:clamp(20px,2.4vw,27px);color:var(--text);display:block;
}
.vidplaceholder span{
  font-family:var(--mono);font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--muted-2);display:block;margin-top:8px;
}

/* ---------- cards ---------- */
.grid{display:grid;gap:1px;background:var(--line-soft);border:1px solid var(--line-soft)}
.grid.c3{grid-template-columns:repeat(3,1fr)}
.grid.c2{grid-template-columns:repeat(2,1fr)}
.grid.c4{grid-template-columns:repeat(4,1fr)}
@media (max-width:940px){.grid.c3,.grid.c4{grid-template-columns:repeat(2,1fr)}}
@media (max-width:620px){.grid.c3,.grid.c2,.grid.c4{grid-template-columns:1fr}}
.cell{background:var(--surface);padding:clamp(22px,2.6vw,30px)}
section.band.alt .cell{background:var(--surface-alt)}
.cell .tag{
  font-family:var(--mono);font-size:12.5px;letter-spacing:.13em;text-transform:uppercase;
  color:var(--accent);display:block;margin-bottom:11px;font-weight:500;
}
.cell h3{margin-bottom:8px}
.cell p{color:var(--muted);font-size:14.5px;margin:0}

/* ---------- per-window block ---------- */
.window{
  display:grid;grid-template-columns:1.15fr 1fr;gap:clamp(24px,4vw,56px);
  align-items:center;padding:clamp(28px,4vw,48px) 0;border-bottom:1px solid var(--line-soft);
}
.window:last-of-type{border-bottom:0}
.window.flip>.window-media{order:2}
@media (max-width:940px){
  .window{grid-template-columns:1fr;padding-block:clamp(24px,4vw,36px)}
  .window.flip>.window-media{order:0}
}
/* Bumped from 10.5px: this is the name of the screen being shown and was reading as fine
   print next to a 29px heading. Tracking eased off a touch as the size went up, since wide
   letter-spacing that suits 10px starts to look loose at 14px. */
.window-body .winlabel{
  font-family:var(--mono);font-size:14px;letter-spacing:.12em;text-transform:uppercase;
  color:var(--accent);display:block;margin-bottom:11px;font-weight:500;
}
.window-body h3{font-size:clamp(22px,2.4vw,29px);margin-bottom:14px}

/* ---------- tick list ---------- */
ul.ticks{list-style:none;margin:0;padding:0;display:grid;gap:10px}
ul.ticks li{position:relative;padding-left:23px;color:var(--muted);font-size:14.5px;line-height:1.5}
ul.ticks li::before{
  content:"";position:absolute;left:0;top:8px;width:9px;height:9px;
  border:1px solid var(--accent);background:transparent;
}
ul.ticks li b{color:var(--text);font-weight:600}

/* ---------- aircraft stage ---------- */
.ravin-stage{
  display:grid;grid-template-columns:1.4fr .85fr;align-items:center;
  gap:clamp(4px,1.5vw,24px);margin-bottom:clamp(26px,4vw,44px);
}
@media (max-width:900px){.ravin-stage{grid-template-columns:1fr;gap:0}}
/* backdrop is keyed out of the asset itself, so no mask or filter is needed here */
.stage-art{width:100%;display:block}

.specgrid{margin:0;display:grid;gap:0}
.specgrid>div{
  display:flex;justify-content:space-between;align-items:baseline;gap:14px;
  padding:9px 0;border-bottom:1px solid var(--line-soft);
}
.specgrid>div:last-child{border-bottom:0}
.specgrid dt{
  font-family:var(--mono);font-size:10.5px;letter-spacing:.13em;
  text-transform:uppercase;color:var(--muted-2);margin:0;
}
.specgrid dd{
  margin:0;font-family:var(--display);font-weight:600;font-size:17px;letter-spacing:.01em;
  color:var(--text);text-align:right;font-variant-numeric:tabular-nums;
}

/* ---------- module index ---------- */
.modindex{
  display:grid;gap:clamp(20px,3vw,36px);grid-template-columns:repeat(3,1fr);
  align-items:start;border-top:1px solid var(--line-soft);padding-top:clamp(24px,3vw,34px);
}
@media (max-width:820px){.modindex{grid-template-columns:repeat(2,1fr)}}
@media (max-width:480px){.modindex{grid-template-columns:1fr}}
.modgroup>span{
  display:block;font-family:var(--mono);font-size:12.5px;letter-spacing:.13em;
  text-transform:uppercase;color:var(--accent);margin-bottom:12px;font-weight:500;
  padding-bottom:9px;border-bottom:1px solid var(--line-soft);
}
.modgroup ul{list-style:none;margin:0;padding:0;display:grid;gap:7px}
.modgroup li{color:var(--muted);font-size:13.5px;line-height:1.45;padding-left:14px;position:relative}
.modgroup li::before{content:"";position:absolute;left:0;top:8px;width:5px;height:1px;background:var(--accent-dim)}

/* ---------- downloads ---------- */
.dl{display:grid;gap:1px;background:var(--line-soft);border:1px solid var(--line-soft);
    grid-template-columns:repeat(2,1fr)}
@media (max-width:700px){.dl{grid-template-columns:1fr}}
.dl a{
  background:var(--surface-alt);padding:22px clamp(18px,2.2vw,26px);text-decoration:none;
  display:flex;align-items:center;gap:16px;transition:background .18s;
}
.dl a:hover{background:rgba(26,56,86,.62)}
.dl .ic{
  width:34px;height:34px;flex-shrink:0;border:1px solid var(--line);border-radius:2px;
  display:grid;place-items:center;font-family:var(--mono);font-size:9px;
  letter-spacing:.06em;color:var(--accent);
}
.dl b{display:block;font-family:var(--display);font-weight:600;font-size:17px;letter-spacing:.01em;color:var(--text)}
.dl span{display:block;font-family:var(--mono);font-size:10.5px;letter-spacing:.11em;text-transform:uppercase;color:var(--muted-2);margin-top:4px}

/* ---------- next-page links ---------- */
.nextnav{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:1px;background:var(--line-soft);
         border-top:1px solid var(--line-soft);border-bottom:1px solid var(--line-soft)}
@media (max-width:760px){.nextnav{grid-template-columns:1fr}}
.nextnav a{
  background:var(--surface);padding:clamp(24px,3vw,34px) clamp(20px,2.4vw,30px);
  text-decoration:none;transition:background .18s;
}
.nextnav a:hover{background:rgba(22,48,74,.62)}
.nextnav span{
  font-family:var(--mono);font-size:10px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--accent);display:block;margin-bottom:9px;
}
.nextnav b{font-family:var(--display);font-weight:700;font-size:clamp(19px,2vw,24px);
           color:var(--text);display:block;letter-spacing:.01em}
.nextnav p{color:var(--muted);font-size:14px;margin:7px 0 0}

/* ---------- contact ---------- */
.contact{
  background:radial-gradient(900px 420px at 18% 0%,rgba(63,180,242,.14),transparent 65%),rgba(18,40,63,.45);
  border-bottom:1px solid var(--line-soft);
}
.contact .wrap{padding-block:clamp(56px,8vw,96px)}
/* h2 margins live on .sechead h2.h2, and the contact block is not a .sechead -- on the
   home page that never showed because there is no paragraph under the heading there. The
   rental page puts a lede between the two, which then sat flush against it. */
.contact .h2{margin-bottom:14px}
.contact .lede{margin-bottom:0}
.cbox{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:1px;
  background:var(--line);border:1px solid var(--line);margin-top:34px;
}
.cbox div{background:rgba(20,42,66,.55);padding:22px}
.cbox span{
  display:block;font-family:var(--mono);font-size:10.5px;letter-spacing:.15em;
  text-transform:uppercase;color:var(--muted-2);margin-bottom:8px;
}
.cbox a,.cbox p{
  font-family:var(--display);font-size:18px;font-weight:600;color:var(--text);
  text-decoration:none;margin:0;letter-spacing:.01em;word-break:break-word;
}
.cbox a:hover{color:var(--accent)}
/* The value is the only tappable thing in each cell, and at 28px tall it was well under a
   thumb. The padding grows the hit area; the equal negative margin keeps the visible
   layout exactly where it was. */
.cbox a{display:inline-block;padding-block:8px;margin-block:-8px}

/* ---------- YouTube embed ----------
   A facade rather than an iframe: the page ships a thumbnail and a play button, and
   YouTube's player -- around a megabyte of script, plus its cookies -- only loads once
   someone presses play. Without JS the thumbnail is simply a link to the video on
   YouTube, so it still works. */
.yt{position:relative;display:block;aspect-ratio:16/9;background:#000;overflow:hidden;border-radius:2px}
.yt img{width:100%;height:100%;object-fit:cover;display:block;transition:opacity .2s}
.yt:hover img{opacity:.86}
.yt-play{
  position:absolute;left:50%;top:50%;width:78px;height:54px;transform:translate(-50%,-50%);
  background:rgba(9,20,33,.82);border:1px solid var(--accent);border-radius:2px;transition:background .18s;
}
.yt-play::before{
  content:"";position:absolute;left:50%;top:50%;transform:translate(-35%,-50%);
  border-style:solid;border-width:11px 0 11px 18px;
  border-color:transparent transparent transparent var(--accent);transition:border-color .18s;
}
.yt:hover .yt-play,.yt:focus-visible .yt-play{background:var(--accent)}
.yt:hover .yt-play::before,.yt:focus-visible .yt-play::before{border-left-color:var(--ink)}
.yt-frame{display:block;width:100%;aspect-ratio:16/9;border:0;border-radius:2px;background:#000}

/* ---------- small-screen type floor ----------
   These mono labels are set at 10-10.5px against a desktop column, where they read as
   deliberate small caps. On a phone held at arm's length in daylight the same size reads
   as fine print, so below 560px they come up to 11.5px. Tracking is left alone: the
   spacing is part of what makes them read as labels rather than body text. */
@media (max-width:560px){
  .stat span,.nextnav span,.dl span,.specgrid dt,.field label,.cbox span,.acap .atype,.vidplaceholder span{font-size:11.5px}
}

/* ---------- footer ---------- */
footer{padding:34px 0 44px;color:var(--muted-2);font-size:13px}
footer .wrap{display:flex;justify-content:space-between;gap:20px;flex-wrap:wrap;align-items:center}
footer .fbrand{display:flex;align-items:center;gap:10px}
footer .fbrand img{width:24px;height:24px;object-fit:contain}
footer .fbrand b{
  font-family:var(--display);font-size:15px;letter-spacing:.05em;
  text-transform:uppercase;color:var(--muted);font-weight:700;
}
footer .note{font-family:var(--mono);font-size:11px;letter-spacing:.05em}
