/* Sky5 Labs — shared styling.
 *
 * ONE STYLESHEET FOR THE THREE PAGES, not tokens copied into each. Within the
 * Labs site a restyle should be one edit. (It is still SEPARATE from the Sky5
 * Toolkit site's CSS: those are different sites for different buyers, and a
 * change made for one must not silently restyle the other.)
 *
 * THE LOOK IT IS AIMED AT: an established software company, not a startup
 * landing page. The audience is an operations or quality director at a
 * manufacturer, and an investor -- both of whom are reassured by restraint and
 * put off by decoration. So:
 *
 *   - a cool near-neutral ground, ink-dark text, one deep accent used sparingly
 *   - hairline rules instead of boxes-inside-boxes
 *   - generous vertical rhythm; whitespace is the main signal of confidence
 *   - no gradients, no animation, no drop shadows except one on hover
 *   - type does the work: a wide scale, tight tracking on headings
 *
 * The green lineage is kept but deepened and desaturated, so it still reads as
 * the same family as Sky5 Toolkit without the consumer brightness.
 */

:root {
  --bg: #f7f9f9;
  --surface: #ffffff;
  --ink: #10201c;
  --muted: #566a63;
  --faint: #7d8f89;
  --rule: #e3eae7;
  --rule-strong: #cfdad6;
  --accent: #0d5741;
  --accent-hover: #0a4433;
  --navy: #14232f;
  --navy-deep: #0d1922;
  --radius: 8px;
  --maxw: 1120px;
}

* { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-padding-top: 5rem;
}

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  background: var(--bg);
  color: var(--ink);
  line-height: 1.65;
  overflow-wrap: break-word;
  font-size: 17px;
}

img, svg { max-width: 100%; }
a { color: var(--accent); text-underline-offset: 2px; }
a:hover { color: var(--accent-hover); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 2px; }

.wrap { max-width: var(--maxw); margin: 0 auto; padding: 0 1.5rem; }
.narrow { max-width: 44rem; }

.skip {
  position: absolute; left: -9999px; top: 0;
  background: #fff; color: var(--accent); padding: 0.6rem 1rem; z-index: 30;
}
.skip:focus { left: 0.5rem; top: 0.5rem; }

/* ---- masthead ---------------------------------------------------------- */
/* Solid, quiet, and it stays put. A translucent or shrinking header is the
   kind of flourish that makes a company look newer than it is. */
header.site {
  background: var(--navy);
  color: #fff;
  padding: 1rem 0;
  position: sticky; top: 0; z-index: 20;
  border-bottom: 1px solid rgba(255,255,255,0.08);
}
header.site .wrap { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem 1.5rem; flex-wrap: wrap; }
header.site .brand {
  color: #fff; text-decoration: none; font-weight: 700;
  font-size: 1.1rem; letter-spacing: -0.01em;
}
header.site nav ul { list-style: none; display: flex; gap: 1.6rem; margin: 0; padding: 0; flex-wrap: wrap; }
header.site nav a {
  color: #b6c6c0; text-decoration: none; font-size: 0.94rem;
  padding-bottom: 2px; border-bottom: 1px solid transparent;
}
header.site nav a:hover { color: #fff; border-bottom-color: rgba(255,255,255,0.35); }

/* ---- type -------------------------------------------------------------- */
h1, h2, h3 { letter-spacing: -0.021em; }
h1 { font-size: clamp(2rem, 4.6vw, 3.05rem); line-height: 1.1; margin: 0 0 1.1rem; font-weight: 750; }
h2 { font-size: clamp(1.4rem, 2.5vw, 1.85rem); line-height: 1.2; margin: 0 0 0.8rem; font-weight: 700; }
h3 { font-size: 1.04rem; margin: 0 0 0.4rem; font-weight: 680; }

.eyebrow {
  color: var(--faint); font-weight: 650; letter-spacing: 0.1em;
  text-transform: uppercase; font-size: 0.74rem; margin: 0 0 1rem;
}
.lede { font-size: 1.18rem; color: var(--muted); max-width: 60ch; margin: 0; line-height: 1.55; }
.lead { color: var(--muted); max-width: 64ch; }

/* ---- rhythm ------------------------------------------------------------ */
/* THE HERO IS NAVY, AND IT RUNS ON FROM THE HEADER.
   ================================================
   header.site is already --navy and sticky, so a navy hero continues it into
   one unbroken band -- which is what sky5toolkit.com does, and matching it is
   the point: three sites, one company.

   EVERY COLOUR INSIDE THE HERO IS RE-STATED BELOW. The page tokens (--ink,
   --muted, --faint) are all dark, chosen for the light ground the rest of the
   page uses. Left alone they would put near-black text on near-black -- the
   classic way a dark band ships unreadable. Each replacement was checked
   against WCAG AA rather than eyeballed; the lowest pair here is 8.9:1. */
.hero {
  padding: 3.4rem 0 3.6rem;
  background: var(--navy);
  color: #fff;
  border-bottom: 1px solid rgba(255,255,255,0.1);
}
.hero h1 { color: #fff; }
.hero .lede { color: #cfdae6; }
.hero .lede strong { color: #fff; }
.hero .eyebrow { color: #7fd0ae; }

/* The fact-sheet rules go pale so they read as dividers rather than scars. */
.hero .proof { border-top-color: rgba(255,255,255,0.22); }
.hero .proof div { border-right-color: rgba(255,255,255,0.22); }
.hero .proof .n { color: #fff; }
.hero .proof .l { color: #9fb3c8; }
.section { padding: 3.6rem 0; border-top: 1px solid var(--rule); }

/* ---- cards ------------------------------------------------------------- */
/* Hairline, flat, and only lifted on hover. Resting shadows on every card is
   the single fastest way to look like a template. */
.card {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 1.5rem 1.6rem;
}
.card p { margin: 0; color: var(--muted); font-size: 0.97rem; }
a.card, .card.linked { transition: border-color 0.15s ease, box-shadow 0.15s ease; }
a.card:hover, .card.linked:hover { border-color: var(--rule-strong); box-shadow: 0 2px 14px rgba(16,32,28,0.06); }

.grid-2 { display: grid; gap: 1.25rem; grid-template-columns: repeat(2, 1fr); }
.grid-3 { display: grid; gap: 1.25rem; grid-template-columns: repeat(3, 1fr); }
@media (max-width: 820px) { .grid-2, .grid-3 { grid-template-columns: 1fr; } }

/* ---- product blocks (home) --------------------------------------------- */
.product { display: flex; flex-direction: column; padding: 1.9rem 1.9rem 2rem; }
.product h3 { font-size: 1.5rem; letter-spacing: -0.02em; margin-bottom: 0.2rem; font-weight: 720; }
.product .who { color: var(--faint); font-size: 0.87rem; margin: 0 0 1.1rem; font-weight: 600; line-height: 1.45; }
.product > p { margin: 0 0 1.1rem; color: var(--muted); }
.product ul { margin: 0 0 1.5rem; padding-left: 1.1rem; color: var(--muted); font-size: 0.95rem; }
.product li { margin-bottom: 0.35rem; }
.product .go { margin-top: auto; margin-bottom: 0; }

/* ---- proof figures ----------------------------------------------------- */
/* Rules between, not boxes around. Reads as a fact sheet rather than a
   dashboard, which is the register this audience trusts. */
.proof { display: flex; gap: 0; flex-wrap: wrap; margin-top: 2.6rem; border-top: 1px solid var(--rule); padding-top: 1.6rem; }
.proof div { padding-right: 2.8rem; margin-right: 2.8rem; border-right: 1px solid var(--rule); }
.proof div:last-child { border-right: 0; margin-right: 0; padding-right: 0; }
.proof .n { font-size: 2.15rem; font-weight: 720; color: var(--ink); line-height: 1.05; letter-spacing: -0.03em; }
.proof .l { color: var(--faint); font-size: 0.88rem; margin-top: 0.15rem; }
@media (max-width: 620px) {
  .proof div { border-right: 0; margin-right: 0; padding-right: 0; width: 100%; margin-bottom: 1.1rem; }
}

/* ---- modules / why ----------------------------------------------------- */
.mod h3 { color: var(--ink); }
.mod .num { color: var(--faint); font-variant-numeric: tabular-nums; font-weight: 700; margin-right: 0.45rem; }
.why-item { border-left: 2px solid var(--accent); padding-left: 1.2rem; }
.why-item h3 { margin-bottom: 0.3rem; }
.why-item p { margin: 0; color: var(--muted); font-size: 0.97rem; }

/* ---- lists ------------------------------------------------------------- */
.cols ul { columns: 2; column-gap: 2.6rem; padding-left: 1.15rem; color: var(--muted); margin-top: 1.2rem; }
@media (max-width: 700px) { .cols ul { columns: 1; } }
.cols li { margin-bottom: 0.5rem; break-inside: avoid; }

/* ---- buttons ----------------------------------------------------------- */
.btn {
  display: inline-block; background: var(--accent); color: #fff; text-decoration: none;
  padding: 0.72rem 1.35rem; border-radius: 6px; font-weight: 650; font-size: 0.98rem;
  border: 1px solid var(--accent);
}
.btn:hover { background: var(--accent-hover); border-color: var(--accent-hover); color: #fff; }
.btn.ghost { background: transparent; color: var(--accent); border-color: var(--rule-strong); }
.btn.ghost:hover { background: #fff; border-color: var(--accent); color: var(--accent-hover); }
.btnrow { display: flex; gap: 0.7rem; flex-wrap: wrap; margin-top: 1.6rem; }

/* ---- closing band ------------------------------------------------------ */
.cta-band { background: var(--navy); color: #fff; padding: 4rem 0; }
.cta-band h2 { color: #fff; }
.cta-band p { color: #b9cbc4; max-width: 56ch; }
.cta-band a:not(.btn) { color: #86c9ae; }
.cta-band .btn.ghost { color: #cfe0d9; border-color: rgba(255,255,255,0.3); background: transparent; }
.cta-band .btn.ghost:hover { background: rgba(255,255,255,0.06); color: #fff; border-color: rgba(255,255,255,0.55); }

/* THE SAME TREATMENT THE CTA BAND ALREADY NEEDED, now that the hero is navy
   too. A ghost button is transparent, so its text colour is the only thing
   holding it up -- and the default is --accent, a dark green chosen for a
   light ground. Left alone, "See the platform" was #0d5741 on #14232f: two
   near-blacks, and effectively invisible. Caught by reading computed styles
   in the browser rather than by looking at the page. */
.hero .btn.ghost { color: #cfe0d9; border-color: rgba(255,255,255,0.35); background: transparent; }
.hero .btn.ghost:hover { background: rgba(255,255,255,0.06); color: #fff; border-color: rgba(255,255,255,0.6); }
.cta-band .phone { margin-top: 1.5rem; font-size: 1.05rem; color: #fff; }

/* ---- footer ------------------------------------------------------------ */
footer.site { background: var(--navy-deep); color: #8fa3ac; padding: 2.6rem 0; font-size: 0.9rem; }
footer.site a { color: #86c9ae; }
footer.site p { margin: 0 0 0.5rem; }
footer.site .sep { color: #43555e; margin: 0 0.45rem; }

/* ---- screenshots and photographs ---------------------------------------
   Added 17 Aug 2026. The page had no images at all, which for a system whose
   whole argument is "ten modules, one data model" means the buyer has to take
   the most important claim on trust. A screenshot of one record showing its
   linked tasks, change orders and authorizations proves it in a glance.

   Deliberately bordered and captioned rather than floated in a device frame:
   an audit-minded buyer wants to see the actual screen, not a marketing
   rendering of it. Same pattern as the Toolkit site. */
.shot { margin: 2rem 0; }
.shot-img {
  display: block; width: 100%; height: auto;
  border: 1px solid var(--rule); border-radius: 10px;
  background: #fff;
}
.shot-caption {
  margin: 0.6rem 0 0; font-size: 0.88rem; color: var(--muted);
  line-height: 1.5;
}
/* A band of three, for the modules section. Collapses to one column on a
   phone -- three screenshots side by side on a 375px screen are three
   illegible screenshots. */
.shot-row {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem;
  margin: 2rem 0;
}
@media (max-width: 760px) { .shot-row { grid-template-columns: 1fr; } }
/* Photographs of people carry a slightly deeper crop than a screenshot and no
   border -- a bordered photo reads as a screenshot of a photo. */
.labs-photo {
  display: block; width: 100%; height: auto; border-radius: 10px;
  object-fit: cover; max-height: 380px;
}

/* --------------------------------------------------------------------------
   THE UMBRELLA: each product card wears the accent of the site it opens.
   ERMS is industrial blue, Sky5 Toolkit is its own green. Shared bones,
   different skin -- so clicking a card reads as walking into another room in
   the same building rather than landing on an unrelated site.
   -------------------------------------------------------------------------- */
/* A COLOURED HEAD, not a coloured hairline.
   The first cut used a 4px top border and a tinted heading -- correct in
   principle and almost invisible in practice. A filled head does the job the
   umbrella needs: the card wears the livery of the site it opens, so the click
   is continuous rather than a jump. */
.door-erms, .door-toolkit { padding: 0; overflow: hidden; }
.door-top { padding: 1.5rem 1.9rem 1.25rem; color: #fff; }
.door-erms    .door-top { background: #2a6199; }
.door-toolkit .door-top { background: #0b6e4b; }
.door-top h3 { color: #fff; margin-bottom: 0.25rem; }
.door-top .who { color: rgba(255,255,255,0.9); margin: 0; }
.door-body { padding: 1.4rem 1.9rem 1.9rem; display: flex; flex-direction: column; flex: 1; }
.door-body > p:first-child { margin-top: 0; }

/* THE BUTTON MATCHES ITS OWN CARD HEAD, not the site accent.
   Both buttons used to be the default green while the ERMS head was blue --
   so the ERMS card carried two different colours for one destination. Now the
   whole card, head and button, is the livery of the site it opens, which is
   the point of the umbrella. Both pairs were checked against WCAG AA: white on
   #2a6199 is 6.43:1, white on #0b6e4b is 6.28:1. */
.door-erms    .btn { background: #2a6199; border-color: #2a6199; color: #fff; }
.door-erms    .btn:hover { background: #22507f; border-color: #22507f; }
.door-toolkit .btn { background: #0b6e4b; border-color: #0b6e4b; color: #fff; }
.door-toolkit .btn:hover { background: #095739; border-color: #095739; }

/* A door is more likely to be opened when something real is visible behind it.
   Sits directly above the button, separated so it reads as evidence rather
   than as another feature bullet. */
.card-proof {
  margin: 0 0 1.1rem;
  padding-top: 0.9rem;
  border-top: 1px solid var(--rule);
  color: var(--ink) !important;
  font-weight: 600;
  font-size: 0.93rem !important;
}

.grid-4 { display: grid; gap: 1.25rem; grid-template-columns: repeat(4, 1fr); }
@media (max-width: 1000px) { .grid-4 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px)  { .grid-4 { grid-template-columns: 1fr; } }

/* The About page's history. A rule with dots on it, because the content
   genuinely is a sequence in time -- which is the only thing that justifies a
   timeline rather than a list. */
.timeline { margin-top: 2rem; border-left: 2px solid var(--rule); padding-left: 1.4rem; display: grid; gap: 1.6rem; }
.tl-item { position: relative; }
.tl-item::before {
  content: ""; position: absolute; left: -1.82rem; top: 0.5rem;
  width: 10px; height: 10px; border-radius: 50%; background: #2f6fb0;
}
.tl-when { font-size: 0.85rem; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; color: #2f6fb0; margin: 0; }
.tl-item h3 { font-size: 1.1rem; margin: 0.15rem 0 0.3rem; }
.tl-item p { color: var(--muted); margin: 0; }

/* Two claims that carry more weight than any feature on the page, so they get
   a band of their own above the argument rather than a bullet inside it. */
.callout {
  display: grid; gap: 1.25rem; grid-template-columns: repeat(2, 1fr);
  margin: 0 0 2.4rem;
}
@media (max-width: 760px) { .callout { grid-template-columns: 1fr; } }
.callout > div {
  background: var(--surface); border: 1px solid var(--rule);
  border-left: 4px solid #2f6fb0; border-radius: 10px;
  padding: 1.3rem 1.4rem;
}
.callout h3 { font-size: 1.08rem; margin: 0 0 0.4rem; }
.callout p { margin: 0; color: var(--muted); font-size: 0.97rem; }

/* ==========================================================================
   THE ERMS PAGE
   Built from the mockup the owner approved on 21 Aug 2026. Everything below
   is layout and colour; the copy it carries was already written.
   ========================================================================== */

/* .section.alt was on the deployment band in the markup and defined nowhere,
   so the band never alternated. Now it does -- which is what gives the page
   its rhythm once there are seven bands instead of four. */
.section.alt { background: #eef3f2; }

/* A caption and a couple of table headers exist for screen readers only.
   Clip rather than display:none -- display:none is not announced. */
.visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* ---- hero: headline beside the diagram --------------------------------- */
.hero-grid { display: grid; gap: 2.4rem; grid-template-columns: 1.15fr 1fr; align-items: start; }
@media (max-width: 900px) { .hero-grid { grid-template-columns: 1fr; gap: 2rem; } }
.hero-stack .lede { margin-bottom: 0; }

/* The three facts a security reviewer scans for. The marker is a drawn dot
   rather than a check character -- generated text gets announced by some
   screen readers, and "check mark, runs air-gapped" is noise. */
.hero-badges { list-style: none; display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 1.6rem 0 0; padding: 0; }
.badge {
  display: inline-flex; align-items: center; gap: 0.5rem;
  border: 1px solid rgba(255,255,255,0.25);
  background: rgba(255,255,255,0.05);
  color: #d7e4ea; border-radius: 999px;
  padding: 0.4rem 0.9rem; font-size: 0.86rem; font-weight: 600;
}
.badge::before {
  content: ""; width: 7px; height: 7px; border-radius: 50%;
  background: #7fd0ae; flex: none;
}

/* ---- "what you replace" ------------------------------------------------ */
/* Nine boxes collapsing into one bar. The claim is structural, so it is
   drawn -- a photograph cannot carry "nine spreadsheets into one data
   model", and this costs no licence. */
.replace {
  border: 1px solid rgba(255,255,255,0.16); border-radius: 10px;
  background: rgba(255,255,255,0.035); padding: 1.3rem 1.35rem 1.4rem;
}
.replace-head {
  text-transform: uppercase; letter-spacing: 0.1em; font-size: 0.76rem;
  font-weight: 700; color: #9fb3c8; margin: 0 0 0.9rem;
}
/* Three across at every width, deliberately. The owner asked for a clean 3x3
   and it stays a 3x3 on a phone -- the type steps down instead. */
/* grid-auto-rows: 1fr is what makes it an ARRAY rather than three rows
   that happen to be stacked. Without it each row sizes to its own
   content, so a row of one-line chips sits 10px shorter than the rows
   either side of it and the block reads as ragged. */
.chips { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, 1fr); grid-auto-rows: 1fr; gap: 0.5rem; }
.chip {
  display: flex; align-items: center; justify-content: center; text-align: center;
  min-height: 3.2rem; padding: 0.5rem 0.5rem;
  background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.14);
  border-radius: 5px; color: #cbd8e2; font-size: 0.8rem; line-height: 1.25;
}
@media (max-width: 480px) { .chip { font-size: 0.72rem; min-height: 3rem; padding: 0.4rem 0.3rem; } }
.spine { margin: 0.75rem 0 0.55rem; text-align: center; color: #7fd0ae; font-size: 1.1rem; line-height: 1; }
.one-model {
  margin: 0; text-align: center; background: #7fd0ae; color: #0d1922;
  font-weight: 750; letter-spacing: 0.01em; border-radius: 6px;
  padding: 0.75rem; font-size: 1rem;
}

/* ---- the sector band --------------------------------------------------- */
.sectors { display: grid; gap: 1.25rem; grid-template-columns: repeat(4, 1fr); margin-top: 1.9rem; }
@media (max-width: 1000px) { .sectors { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px)  { .sectors { grid-template-columns: 1fr; } }
.sector {
  background: var(--surface); border: 1px solid var(--rule);
  border-radius: var(--radius); overflow: hidden;
  display: flex; flex-direction: column;
}

/* PHOTO-READY, NOT A PLACEHOLDER.
   There is no dashed "photo goes here" box on this page: a defense prime
   evaluating a Texas LLC must not land on something that looks half-built.
   What ships today is a finished engineering-grid panel. When the four
   photographs are licensed, each one is a TWO-LINE change on the sector rule
   below -- see labs/img/README.md. The scrim behind the name is already
   opaque enough to keep white text legible over any image, so nothing else
   moves and no contrast has to be re-checked. */
.sector-art {
  position: relative; aspect-ratio: 4 / 3; min-height: 150px;
  display: flex; align-items: flex-end;
  background-color: #1d3348;
  background-image:
    linear-gradient(rgba(255,255,255,0.055) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,0.055) 1px, transparent 1px);
  background-size: 24px 24px;
  background-position: center;
}
/* The photograph fills the panel and sits UNDER the scrim. object-fit: cover
   is what lets a 4:3 file survive the panel being a slightly different shape
   on a phone without distorting anyone's aircraft. */
.sector-photo {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
  display: block;
}
.sector-name {
  position: relative; z-index: 1;
  width: 100%; padding: 2.4rem 1rem 0.85rem;
  /* Solid under the text, fading only above it -- so a bright sky in a future
     photograph cannot take the sector name with it. */
  background: linear-gradient(to top, rgba(11,28,41,0.92) 58%, rgba(11,28,41,0));
  color: #fff; font-weight: 700; font-size: 0.98rem; line-height: 1.25;
}
.sector-body { padding: 1rem 1.1rem 1.2rem; }
.sector-body p { margin: 0; color: var(--muted); font-size: 0.93rem; line-height: 1.5; }

/* The qualifying criteria under the tiles: two columns of short lines, one on
   a phone. Same treatment the page already gives .cols. */
.who-list { columns: 2; column-gap: 2.6rem; padding-left: 1.15rem; color: var(--muted); margin-top: 0.9rem; }
@media (max-width: 700px) { .who-list { columns: 1; } }
.who-list li { margin-bottom: 0.5rem; break-inside: avoid; }

/* ---- the comparison matrix --------------------------------------------- */
/* Six rows of architecture. It scrolls sideways below 660px rather than
   reflowing -- a comparison that has been stacked into one column is no
   longer a comparison. */
.tablescroll { overflow-x: auto; margin-top: 1.8rem; }
.matrix { border-collapse: collapse; width: 100%; min-width: 640px; font-size: 0.93rem; }
.matrix th, .matrix td { text-align: left; padding: 0.8rem 0.95rem; border-bottom: 1px solid var(--rule); vertical-align: top; }
.matrix thead th {
  font-size: 0.82rem; text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--faint); border-bottom: 2px solid var(--rule-strong); font-weight: 700;
}
.matrix thead th.us {
  color: #fff; background: #2a6199; border-bottom-color: #2a6199;
  border-radius: 6px 6px 0 0; text-transform: none; font-size: 0.98rem;
  letter-spacing: -0.01em;
}
.th-sub { display: block; font-weight: 500; text-transform: none; letter-spacing: 0; font-size: 0.76rem; color: var(--faint); margin-top: 0.15rem; }
.matrix tbody th { font-weight: 650; color: var(--ink); width: 23%; }
.matrix td.us { background: rgba(42,97,153,0.07); color: var(--ink); font-weight: 600; }
.matrix td.them { color: var(--muted); }
.matrix tbody tr:last-child th, .matrix tbody tr:last-child td { border-bottom: 0; }
.matrix-note { margin: 1.1rem 0 0; color: var(--faint); font-size: 0.88rem; max-width: 72ch; line-height: 1.55; }

/* ---- the module index -------------------------------------------------- */
/* Numbered markers are usually decoration. Here they are not: the page spends
   its whole argument on the number ten, so this is the one place a counter
   carries information. */
.modindex { list-style: none; padding: 0; display: grid; gap: 0.7rem; grid-template-columns: repeat(5, 1fr); margin: 1.6rem 0 0; }
@media (max-width: 900px) { .modindex { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 560px) { .modindex { grid-template-columns: repeat(2, 1fr); } }
.mi { background: var(--surface); border: 1px solid var(--rule); border-radius: 5px; padding: 0.65rem 0.75rem; }
.mi .n { display: block; font-weight: 750; color: #2a6199; font-size: 1rem; line-height: 1; font-variant-numeric: tabular-nums; }
.mi .t { display: block; font-size: 0.85rem; font-weight: 600; margin-top: 0.2rem; color: var(--ink); line-height: 1.3; }

/* THE FOUR PANELS, AND THE ONE PLACE THE PHOTOGRAPHS LAND.
   Related hues rather than one repeated swatch. To drop in a licensed photo,
   add two lines to the sector's rule and nothing else changes:

       .sector-1 {
         background-color: #1d3348;
         background-image: url("img/sector-aerospace.jpg");
         background-size: cover;
       }

   background-image here overrides the engineering grid on .sector-art, and
   the scrim behind the name is already opaque under the text, so the sector
   name stays legible over any image and no contrast needs re-checking.
   labs/img/README.md says exactly what to buy for each one. */
.sector-1 { background-color: #1d3348; }   /* Aerospace & defense */
.sector-2 { background-color: #24323b; }   /* Commercial manufacturing */
.sector-3 { background-color: #1f3a38; }   /* Engineering services */
.sector-4 { background-color: #2b3340; }   /* Industrial & regulated */
