/* ================================================================
   PGISR — SITE DESIGN SYSTEM LAYER
   ----------------------------------------------------------------
   The homepage editorial language is the site's language now. This
   sheet promotes it to the shared shell and maps the older
   page-level components onto the same grammar, so every page reads
   as one brand instead of a new homepage surrounded by older pages.

   Loaded LAST on every page, after site.css / premium.css /
   equipment.css / editorial.css. Everything is scoped to
   `body.pgisr` so the specificity lands without !important.
   ================================================================ */

/* ================================================================
   1 · RHYTHM AND MEASURE
   One vertical scale and one page measure for the whole site. The
   interior pages ran on a 1180px shell while the homepage ran on
   1440px — that alone made them read as an older site.
   ================================================================ */
body.pgisr {
  --pgi-band:       clamp(3.75rem, 6.25vw, 7rem);
  --pgi-band-tight: clamp(2.75rem, 4vw, 4.5rem);
  --pgi-gap:        clamp(1.75rem, 3.5vw, 3.5rem);
  --pgi-wide:       min(100% - (2 * var(--page-gutter)), 1440px);
  --pgi-chip-bg:    rgba(61,184,166,0.14);
  --pgi-chip-line:  rgba(61,184,166,0.55);
  /* Brighter than --accent so small mono type on the dark ground
     stays legible; --accent stays the fill/rule colour. */
  --pgi-chip-ink:   #4cc4b1;
}

body.pgisr .shell,
body.pgisr .shell-wide {
  width: var(--pgi-wide);
  margin-inline: auto;
}

body.pgisr .section {
  padding-block: var(--pgi-band);
  border-bottom: 1px solid var(--line);
}

/* Surface alternation is now a site-wide rule rather than a
   per-page decision, so the scroll has a rhythm on every page. */
body.pgisr .section-alt,
body.pgisr .pgi-surface--alt { background: var(--bg-2); }
body.pgisr .pgi-surface--deep { background: #090d13; }
body.pgisr .pgi-surface--calm {
  background:
    radial-gradient(120% 90% at 78% 10%, rgba(42,150,136,0.07), transparent 62%),
    var(--bg);
}

/* ================================================================
   2 · TYPE SYSTEM
   Three levels, used identically everywhere: kicker → display →
   supporting copy. Interior headings get real scale without every
   section turning into another homepage hero.
   ================================================================ */

/* ---- Kicker ----------------------------------------------------
   The homepage's dotted mono kicker becomes the site's single
   eyebrow treatment. `.ops-label`, `.eyebrow`, `.mv-values-label`
   and the page-specific kickers all resolve to it. */
body.pgisr .ops-label,
body.pgisr .eyebrow,
body.pgisr .mv-values-label,
body.pgisr .pgi-system-kicker,
body.pgisr .pgi-foundations-kicker,
body.pgisr .about-id-card-label,
body.pgisr .equipment-sensor-legend-label,
body.pgisr .feed-panel-title,
body.pgisr .pgisr-footer-cta-kicker {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 1.4rem;
}
body.pgisr .ops-label::before,
body.pgisr .eyebrow::before,
body.pgisr .mv-values-label::before,
body.pgisr .pgi-system-kicker::before,
body.pgisr .pgi-foundations-kicker::before,
body.pgisr .about-id-card-label::before,
body.pgisr .equipment-sensor-legend-label::before,
body.pgisr .feed-panel-title::before,
body.pgisr .pgisr-footer-cta-kicker::before {
  content: "";
  width: 5px; height: 5px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}
/* The footer sits on paper, so its kicker keeps the copper. */
body.pgisr .pgisr-footer-cta-kicker { color: var(--footer-copper); }

/* Kickers that sit inside a tight component need less air below. */
body.pgisr .pgi-system-kicker,
body.pgisr .pgi-foundations-kicker,
body.pgisr .feed-panel-title,
body.pgisr .equipment-sensor-legend-label { margin-bottom: 0.75rem; }

/* ---- Display and section headings ------------------------------
   The shared `.ops-title` capped at 2.8rem, which is why interior
   pages read timid next to the homepage. Interior pages get the
   editorial scale one step down from the homepage display. */
body.pgisr .ops-title,
body.pgisr .equipment-section-head h2,
body.pgisr .mv-section-head h2,
body.pgisr .deployment-demo-header h2,
body.pgisr .pgi-intro-head h1 {
  font-family: var(--font-display);
  font-size: clamp(2.1rem, 4vw, 3.6rem);
  font-weight: 700;
  line-height: 1.0;
  letter-spacing: -0.025em;
  color: var(--ink);
  margin: 0;
  text-wrap: balance;
}

/* Page titles — the largest type an interior page carries. */
body.pgisr .page-hero h1,
body.pgisr .about-hero-v2-title,
body.pgisr .equipment-hero-title,
body.pgisr .legal-title,
body.pgisr .error-title {
  font-family: var(--font-display);
  font-size: clamp(2.6rem, 5vw, 4.4rem);
  font-weight: 700;
  line-height: 0.99;
  letter-spacing: -0.03em;
  color: var(--ink);
  margin: 0;
  text-wrap: balance;
}
body.pgisr .legal-title,
body.pgisr .error-title { font-size: clamp(2.2rem, 4vw, 3.4rem); }

/* The manual <br> already sets the two lines; balance would re-split the
   first one even when it fits. Sizing stays on the .page-hero h1 scale
   above, shared with the other interior page titles. */
body.pgisr .pgi-intro-head h1 {
  text-wrap: wrap;
}

/* Supporting copy — one measure, one colour, one line height. */
body.pgisr .pgi-intro-lede,
body.pgisr .about-hero-v2-lede,
body.pgisr .equipment-hero-lede,
body.pgisr .contact-hero-copy p,
body.pgisr .equipment-section-head > p,
body.pgisr .mv-section-head-copy > p {
  font-size: clamp(1rem, 1.2vw, 1.1rem);
  line-height: 1.65;
  color: var(--body);
  max-width: 48ch;
}

/* ================================================================
   3 · INTERIOR PAGE INTRO SYSTEM
   Every interior page opens the same way: a hairline meta rail, a
   large editorial title, one supporting block, and a closing rule.
   Related to the homepage hero, deliberately more compact — no
   page-tall empty openings.
   ================================================================ */
body.pgisr:not(.legal-page) .page-hero,
body.pgisr .equipment-hero {
  position: relative;
  min-height: 0;
  padding-block: calc(var(--header-h) + var(--pgi-band-tight)) var(--pgi-band-tight);
  border-bottom: 1px solid var(--line-strong);
  background:
    radial-gradient(88% 60% at 84% 8%, rgba(42,150,136,0.10), transparent 62%),
    linear-gradient(180deg, #121b26 0%, var(--bg) 78%);
}
/* A single accent tick at the page's top-left corner marks the start
   of every interior page — the smallest possible shared signature. */
body.pgisr:not(.legal-page) .page-hero::before,
body.pgisr .equipment-hero::before {
  content: "";
  position: absolute;
  left: 0;
  top: var(--header-h);
  width: clamp(56px, 8vw, 120px);
  height: 2px;
  background: var(--accent);
}

/* The shared interior page head: kicker, then the page title across
   the full measure, closed by a rule. Whatever supports the title —
   a lede, an identity readout, a spec rail — sits in the row below
   rather than fighting the title for the same horizontal band. */
body.pgisr .pgi-pagehead {
  padding-bottom: clamp(1.5rem, 2.5vw, 2.25rem);
  border-bottom: 1px solid var(--line-strong);
}
body.pgisr .pgi-pagehead + * { margin-top: clamp(1.75rem, 3vw, 2.75rem); }

/* Breadcrumb becomes part of the meta rail rather than stray text. */
body.pgisr .breadcrumb {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin: 0 0 1.6rem;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}

/* ================================================================
   4 · SHARED WORKFLOW SEQUENCE
   `.pipeline-steps` is the one ordered-process component the site
   owns — LEOPARD on How It Works, sensor coordination on Equipment.
   It now speaks the homepage's Detect → Verify → Assess → Respond
   language: index chip, continuous rail, terminal direction cue.
   ================================================================ */
body.pgisr .pipeline-steps {
  position: relative;
  display: block;
  margin-top: clamp(2rem, 3.5vw, 3rem);
  padding: 0;
  border-top: 0;
  gap: 0;
}
/* The rail is drawn per stage rather than once across the list, so
   it always lands on the centre of the index column regardless of
   what margins the host section puts on the list itself. */
body.pgisr .pipeline-steps::before,
body.pgisr .pipeline-steps::after { content: none; }
body.pgisr .pipeline-step::before {
  content: "";
  position: absolute;
  left: 1.1rem;
  top: 0;
  bottom: -1px;
  width: 1px;
  background: var(--line-strong);
}
body.pgisr .pipeline-step:first-child::before {
  top: 0.9rem;
  background: linear-gradient(180deg, var(--accent), var(--line-strong) 55%);
}
/* Direction of travel, closing the run. */
body.pgisr .pipeline-step:last-child::before { bottom: 1.55rem; }
body.pgisr .pipeline-step:last-child::after {
  content: "";
  position: absolute;
  left: calc(1.1rem - 4.5px);
  bottom: 0.9rem;
  width: 0; height: 0;
  border-left: 4.5px solid transparent;
  border-right: 4.5px solid transparent;
  border-top: 7px solid var(--accent);
}
body.pgisr .pipeline-step {
  position: relative;
  display: grid;
  grid-template-columns: 2.2rem minmax(0, 1fr);
  align-items: start;
  gap: 0 1.5rem;
  min-height: 0;
  padding: 0.95rem 0 1.05rem;
  border: 0;
  border-bottom: 1px solid var(--line);
  background: transparent;
}
body.pgisr .pipeline-step:last-child { border-bottom: 0; }
body.pgisr .pipeline-step:not(:last-child)::after { content: none; }
/* Index chip, sitting on the rail — same chip as the homepage. */
body.pgisr .step-num {
  align-self: start;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2.2rem;
  padding: 0.34rem 0.4rem;
  border: 1px solid var(--pgi-chip-line);
  border-right: 1px solid var(--pgi-chip-line);
  position: relative;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.08em;
  color: var(--pgi-chip-ink);
}
body.pgisr .pipeline-step .step-num {
  /* Opaque: the rail passes behind the chip, never through it. */
  background: linear-gradient(var(--pgi-chip-bg), var(--pgi-chip-bg)), var(--bg);
}
body.pgisr .step-title {
  font-family: var(--font-display);
  font-size: clamp(1.1rem, 1.5vw, 1.4rem);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.015em;
  text-transform: none;
  color: var(--ink);
  margin: 0;
}
body.pgisr .step-desc {
  margin: 0.4rem 0 0;
  font-size: 0.92rem;
  line-height: 1.6;
  color: var(--body);
  max-width: 52ch;
}
@media (max-width: 700px) {
  body.pgisr .pipeline-step { grid-template-columns: 2.2rem minmax(0, 1fr); gap: 0 1rem; }
}

/* ================================================================
   5 · STRUCTURED READOUTS
   Short label/value and label-only lists stop being card grids and
   become the homepage's readout treatment — rules doing the
   structural work instead of borders around every item.
   ================================================================ */
body.pgisr .equipment-sensor-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1.75rem 1.5rem;
  border: 0;
}
body.pgisr .equipment-component {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  padding: 0;
  border: 0;
  background: transparent;
  border-radius: 0;
}
body.pgisr .equipment-component-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.6rem;
  height: 2.6rem;
  margin-bottom: 0.65rem;
  border: 0;
  border-radius: 0.4rem;
  background:
    radial-gradient(circle at 30% 25%, rgba(42, 150, 136, 0.16), transparent 70%),
    rgba(42, 150, 136, 0.04);
  color: var(--accent);
  transition: background 0.2s ease;
}
.equipment-component:hover .equipment-component-icon {
  background:
    radial-gradient(circle at 30% 25%, rgba(42, 150, 136, 0.26), transparent 70%),
    rgba(42, 150, 136, 0.07);
}
body.pgisr .equipment-component-icon svg {
  width: 1.5rem;
  height: 1.5rem;
  overflow: visible;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
body.pgisr .equipment-component-body {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  min-width: 0;
}
body.pgisr .equipment-component-num {
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  color: var(--accent);
}
body.pgisr .equipment-component h3 {
  font-family: var(--font-display);
  font-size: clamp(1.15rem, 1.6vw, 1.45rem);
  font-weight: 700;
  letter-spacing: -0.015em;
  color: var(--ink);
  margin: 0;
}
body.pgisr .equipment-component p {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
}

/* System behavior — borderless spec-sheet rows (Equipment "What happens
   when activity is detected" / How It Works "system behavior" section).
   Heading beside the rows rather than stacked above them: at two items, a
   full-width heading over a two-column grid left the heading looking
   oversized against a mostly-empty section. */
.equipment-workflow {
  padding-top: clamp(2.75rem, 5.5vw, 4.875rem);
  padding-bottom: clamp(2.5rem, 4vw, 3.5rem);
}

.equipment-workflow-layout {
  display: grid;
  grid-template-columns: minmax(0, 0.46fr) minmax(0, 0.54fr);
  gap: clamp(2rem, 6vw, 5rem);
  align-items: start;
}

.equipment-workflow-head {
  display: flex;
  flex-direction: column;
}

.equipment-workflow-head h2 {
  max-width: 18ch;
  margin: 0.85rem 0 0;
  /* Matches .ops-title's how-it-works-page scale (used for "Try the
     simulator below") exactly. Both are section-level H2s under the
     page's one H1, and this one was left on the old h1-adjacent clamp
     (2.1rem-3.4rem) when .ops-title was tuned down to sit clearly below
     the H1 -- so the page's type scale jumped H1-size, H1-size again,
     then suddenly smaller, instead of stepping down once and holding. */
  font-size: clamp(1.55rem, 2.8vw, 2.5rem);
  line-height: 1.1;
}

#equipment-workflow-title {
  scroll-margin-top: calc(var(--header-h) + 1rem);
}

.equipment-behavior-grid {
  display: grid;
  gap: clamp(1.75rem, 3vw, 2.5rem);
  margin-bottom: 0;
}

.equipment-behavior-row {
  display: flex;
  align-items: flex-start;
  gap: 1.1rem;
}

.equipment-behavior-row .equipment-component-icon {
  flex: 0 0 auto;
  margin-bottom: 0;
}

.equipment-behavior-row .equipment-component-num {
  display: block;
  margin-bottom: 0.35rem;
}

.equipment-behavior-row h3 {
  margin: 0 0 0.55rem;
  font-family: var(--font-display);
  font-size: 1.12rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--ink);
}

.equipment-behavior-row p {
  margin: 0;
  color: var(--body);
  font-size: 0.94rem;
  line-height: 1.68;
}

@media (max-width: 860px) {
  .equipment-workflow-layout { grid-template-columns: 1fr; gap: 1.75rem; }
}

@media (max-width: 900px) { body.pgisr .equipment-sensor-grid { grid-template-columns: repeat(2, minmax(0,1fr)); } }
@media (max-width: 520px) {
  body.pgisr .equipment-sensor-grid { grid-template-columns: 1fr; gap: 0.2rem; }
  /* Single column: a full-width row is wide enough that stacking icon
     above num/title (the desktop card layout) burns a lot of scroll for
     very little content. Lay the icon beside the text instead. */
  body.pgisr .equipment-sensor-grid .equipment-component {
    flex-direction: row;
    align-items: center;
    gap: 0.85rem;
    padding: 0.8rem 0;
  }
  body.pgisr .equipment-sensor-grid .equipment-component-icon {
    flex: 0 0 auto;
    width: 2.3rem;
    height: 2.3rem;
    margin-bottom: 0;
  }
  body.pgisr .equipment-sensor-grid .equipment-component-icon svg {
    width: 1.3rem;
    height: 1.3rem;
  }
  body.pgisr .equipment-sensor-grid .equipment-component-body {
    flex: 1 1 auto;
    min-width: 0;
    gap: 0.15rem;
  }
  body.pgisr .equipment-sensor-grid .equipment-component h3 {
    font-size: 1.05rem;
  }
}

/* Identity / spec panels read as instrument readouts. */
body.pgisr .about-id-card {
  padding: 1.5rem 1.6rem 0.4rem;
  border: 1px solid var(--line-strong);
  border-top: 2px solid var(--accent);
  background: rgba(255,255,255,0.02);
}
body.pgisr .about-id-card::before { content: none; }
body.pgisr .about-id-cell dt {
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--muted);
}
body.pgisr .about-id-cell dd {
  margin: 0.35rem 0 0;
  font-size: 1rem;
  font-weight: 600;
  color: var(--ink);
}

/* ================================================================
   6 · QUALITIES / PRINCIPLES
   Icon-free, border-free, rule-led — the homepage Core Qualities
   treatment, reused for About's operating principles.
   ================================================================ */
body.pgisr .mv-values-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  gap: clamp(1.5rem, 2.5vw, 2.25rem) var(--pgi-gap);
  margin-top: clamp(1.5rem, 2.5vw, 2rem);
}
body.pgisr .mv-value {
  padding: 1.1rem 0 0;
  border: 0;
  border-top: 1px solid var(--line-strong);
  background: transparent;
  border-radius: 0;
}
body.pgisr .mv-value-hdr {
  display: block;
  margin: 0 0 0.7rem;
}
body.pgisr .mv-value-num {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  color: var(--accent);
  margin-bottom: 0.9rem;
}
body.pgisr .mv-values-grid .mv-value-title,
body.pgisr .mv-value-title {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(1.3rem, 2vw, 1.7rem);
  font-weight: 700;
  letter-spacing: -0.015em;
  text-transform: none;
  color: var(--ink);
}
body.pgisr .mv-values-grid .mv-value-desc,
body.pgisr .mv-value-desc {
  font-size: 0.92rem;
  line-height: 1.65;
  color: var(--body);
  margin: 0;
}

/* ================================================================
   7 · LINKS, BUTTONS, NAVIGATION
   ================================================================ */
/* One primary action colour across the site: the brand gold from the
   logo (was the copper of the old header and footer calls to action). */
body.pgisr .button-primary,
body.pgisr .form-submit {
  background: #D4A72C;
  border-color: #D4A72C;
  color: #140a03;
}
body.pgisr .button-primary:hover,
body.pgisr .form-submit:hover {
  background: #EBC65A;
  border-color: #EBC65A;
}

/* Active page is stated, not hinted. */
body.pgisr .pgisr-nav a[aria-current="page"] {
  color: var(--ink);
}
body.pgisr .pgisr-nav a[aria-current="page"]::after {
  background: var(--accent);
  height: 2px;
}

/* Inline text links inside body copy share one underline language. */
body.pgisr .pgi-intro-lede a,
body.pgisr .equipment-hero-lede a,
body.pgisr .intel-feed-copy a,
body.pgisr .origin-lede a,
body.pgisr .legal-doc a {
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px solid var(--accent);
  padding-bottom: 1px;
}
body.pgisr .pgi-intro-lede a:hover,
body.pgisr .equipment-hero-lede a:hover,
body.pgisr .intel-feed-copy a:hover,
body.pgisr .origin-lede a:hover,
body.pgisr .legal-doc a:hover { color: var(--accent); }

/* The TOC nav is nested inside .legal-doc, so the inline-link underline
   above would otherwise land under every TOC entry instead of just body
   copy — .legal-toc already defines its own no-underline, shift-on-hover
   treatment. */
body.pgisr .legal-toc a {
  border-bottom: none;
  padding-bottom: 0;
}

/* ================================================================
   8 · FAQ — disclosure rows, not cards
   ================================================================ */
body.pgisr .faq-list {
  border-top: 1px solid var(--line-strong);
  /* Was 1000px pinned to the shell's left edge, which left ~440px of empty
     shell to its right on a 1920px screen and read as an unfinished page.
     Centred on a slightly tighter measure so the leftover space falls
     evenly either side and the column looks deliberate. Below the cap the
     list is still full width, so tablet and phone are unchanged. */
  max-width: 900px;
  margin-inline: auto;
}
body.pgisr .faq-item {
  border: 0;
  border-bottom: 1px solid var(--line);
  border-radius: 0;
  background: transparent;
}
body.pgisr .faq-item summary {
  display: flex;
  align-items: baseline;
  gap: 1.25rem;
  /* Right padding reserves room for the absolutely positioned +/- mark
     (site.css sets it at right: 0.25rem). Without it — as this rule had,
     since padding is a shorthand and overwrites all four sides — a
     question with no right margin can wrap so its last line runs right
     up to and under the icon instead of stopping short of it. */
  padding: 1.15rem 2.25rem 1.15rem 0;
  font-family: var(--font-display);
  font-size: clamp(1.05rem, 1.4vw, 1.3rem);
  font-weight: 700;
  letter-spacing: -0.015em;
  color: var(--ink);
}
body.pgisr .faq-num {
  flex: none;
  font-family: var(--font-mono);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  color: var(--accent);
}
body.pgisr .faq-item p {
  margin: 0 0 1.4rem;
  padding-left: calc(0.66rem * 3 + 1.25rem);
  font-size: 0.95rem;
  line-height: 1.7;
  color: var(--body);
  max-width: 72ch;
}

/* ================================================================
   9 · LEGAL PAGES
   The shell is wide now, so the document keeps its own measure.
   ================================================================ */
/* The legal pages carry a deliberate cream document treatment that
   predates this layer and reads well; the system contributes the
   shared kicker and page title only, and hands the measure back to
   the document rather than stretching it across the wide shell. */
body.pgisr.legal-page .shell {
  width: min(var(--max), calc(100% - (2 * var(--page-gutter))));
}
body.pgisr.legal-page .page-hero { border-bottom: 1px solid var(--cream-line-strong); }

/* ================================================================
   10 · FORMS — part of the design system, not browser default
   ================================================================ */
body.pgisr .form-field input,
body.pgisr .form-field select,
body.pgisr .form-field textarea {
  border-radius: 0;
  background: rgba(255,255,255,0.02);
  border: 1px solid var(--line-strong);
}
body.pgisr .form-field input:focus,
body.pgisr .form-field select:focus,
body.pgisr .form-field textarea:focus {
  border-color: var(--accent);
  outline: none;
  box-shadow: 0 0 0 1px var(--accent);
}
body.pgisr .form-label,
body.pgisr .form-field > label {
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}

/* ================================================================
   11 · FOOTER TYPE (layout follows in section 17)
   ================================================================ */
body.pgisr .pgisr-footer-cta-title {
  font-family: var(--font-display);
  font-size: clamp(2.2rem, 4vw, 3.4rem);
  font-weight: 700;
  line-height: 1.0;
  letter-spacing: -0.03em;
}
body.pgisr .pgisr-footer-col-head {
  font-family: var(--font-mono);
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--footer-body);
}

/* ================================================================
   12 · PAGE-LEVEL FIT
   A few titles are long enough that the shared page-title scale
   would overrun its column; they get their own ceiling rather than
   a smaller scale for everyone.
   ================================================================ */
body.pgisr .page-hero .about-hero-v2-title {
  max-width: 100%;
  font-size: clamp(2rem, 4.4vw, 4.2rem);
  letter-spacing: -0.028em;
  margin: 1.1rem 0 1.5rem;
}
/* The shared page-title ceiling (4.4rem) let this briefly match or exceed
   the homepage hero at common laptop widths. Its own lower ceiling keeps
   the hero clearly the largest title on the site; the vw coefficient is
   nudged down with it so the gap holds below the ceiling too, not just at it. */
body.pgisr .equipment-hero .equipment-hero-title {
  max-width: 14ch;
  font-size: clamp(2.6rem, 4.6vw, 4.2rem);
}
body.pgisr .page-hero .contact-hero-grid h1 { max-width: 12ch; }

/* Offset anchor for the merged pipeline section. */
body.pgisr .pgi-anchor {
  display: block;
  height: 0;
  scroll-margin-top: calc(var(--header-h) + 1rem);
}

/* ================================================================
   13 · ABOUT — composed grid, no sheet chrome
   The page keeps its asymmetric composition — copy paired with the
   media beside it, sides trading between rows, one full-measure
   statement beat — but carries it on spacing rather than framed
   cells, so it reads with the same hairline-and-air language as the
   rest of the site. Below the breakpoint it is a plain stack.
   ================================================================ */
/* Only the words that form the PGISR acronym carry the bold; the
   connective "and" steps back to regular weight.

   The acronym is marked, not coloured: the title stays one tone and
   one weight, each line closes on the site's hairline, and a short
   accent segment sits on that rule beneath each initial. The mark
   belongs to the rule language the whole site uses rather than
   floating under letters. (Tinting the initials teal read as five
   highlighted letters; dimming the rest of the line read as faded.)
   The second line's hairline is the title plate's closing rule, so
   the plate no longer draws its own. */
body.pgisr .about-hero-v2-title .about-title-and { font-weight: 400; }
body.pgisr .about-hero-v2-title { color: var(--ink); }
body.pgisr .about-hero-v2-title > span {
  display: block;
  position: relative;
  padding-bottom: 0.14em;
  border-bottom: 1px solid var(--line-strong);
}
body.pgisr .about-hero-v2-title > span + span { margin-top: 0.14em; }
body.pgisr .about-hero-v2-title .about-title-initial {
  position: relative;
  display: inline-block;
  color: var(--ink);
}
body.pgisr .about-hero-v2-title .about-title-initial::after {
  content: "";
  position: absolute;
  left: 0.04em;
  right: 0.04em;
  bottom: calc(-0.14em - 1px);
  height: 2px;
  background: var(--accent);
}
/* On narrow screens each title line wraps inside its span, so a rule
   per span would sit under the wrapped pair and strand the marks of
   the first visual line mid-text (P and G at 375px). Below that width
   the marks sit directly under their letters instead, and the plate
   draws its closing rule again. */
@media (max-width: 640px) {
  body.pgisr .about-hero-v2-title > span {
    padding-bottom: 0;
    border-bottom: 0;
  }
  body.pgisr .about-hero-v2-title > span + span { margin-top: 0; }
  body.pgisr .about-hero-v2-title .about-title-initial::after { bottom: -0.08em; }
}

body.pgisr .about-sheet {
  padding-block: calc(var(--header-h) + clamp(1.75rem, 3vw, 2.75rem)) clamp(3rem, 5vw, 4.5rem);
  background:
    radial-gradient(88% 50% at 84% 0%, rgba(42,150,136,0.10), transparent 62%),
    linear-gradient(180deg, #121b26 0%, var(--bg) 42%);
}
/* The sheet's bottom padding used to be the page's trailing space. With the
   closing band as the last element, the content block owns that rhythm — one
   standard band above the rule — and the band sits flush to the footer the
   way it does on every other page. */
body.pgisr .about-sheet { padding-bottom: 0; }
body.pgisr .about-sheet > .shell { padding-bottom: var(--pgi-band); }
body.pgisr .about-grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: clamp(2rem, 4vw, 4rem);
  row-gap: clamp(1.85rem, 3vw, 2.75rem);
  align-items: center;
}
body.pgisr .about-cell { min-width: 0; }

/* Title takes the full measure and closes with the same rule every
   other interior page opens with. */
body.pgisr .about-cell--title {
  grid-column: 1 / -1;
  padding-bottom: clamp(1.25rem, 2vw, 1.75rem);
  border-bottom: 1px solid var(--line-strong);
}
/* Above the phone breakpoint the title's own last line draws the
   closing rule (see the title treatment above), so the plate does not. */
@media (min-width: 641px) {
  body.pgisr .about-cell--title { border-bottom: 0; }
}
body.pgisr .about-cell--title .about-hero-v2-title {
  font-size: clamp(1.9rem, 3.6vw, 2.85rem);
  line-height: 1.04;
  letter-spacing: -0.028em;
  margin: 0.9rem 0 0;
}

/* Copy columns. */
body.pgisr .about-cell--copy > * { max-width: 60ch; }
body.pgisr .about-lede {
  font-size: clamp(1.02rem, 1.25vw, 1.15rem);
  line-height: 1.6;
  color: var(--ink);
  margin: 0 0 1.1rem;
  max-width: 44ch;
}
body.pgisr .about-cell--copy .origin-lede { margin: 0 0 1rem; }
body.pgisr .about-cell--copy .origin-lede:last-child { margin-bottom: 0; }
body.pgisr .about-cell--copy .origin-statement-headline {
  font-size: clamp(1.5rem, 2.2vw, 2.1rem);
  margin: 0.75rem 0 1rem;
}

/* Copy and media trade sides between the two narrative rows. */
body.pgisr .about-cell--story  { grid-column: span 7; }
body.pgisr .about-cell--origin { grid-column: span 7; }
body.pgisr .about-cell--media  { grid-column: span 5; margin: 0; }

body.pgisr .about-cell--registration {
  grid-column: 1 / -1;
  padding-top: clamp(1.25rem, 2vw, 1.75rem);
  border-top: 1px solid var(--line-strong);
}
body.pgisr .about-cell--registration .contact-data-table {
  max-width: 32rem;
  margin-top: 0.85rem;
}

/* The statement is the page's one focal beat: everything else on the
   sheet runs the same eyebrow → heading → copy cadence, so this line is
   allowed to outscale it. Big display type on two lines (the max-width
   forces the wrap after "and"), a short accent rule above marking the
   beat, and the payoff word in the brand teal. Still no box, wash, or
   banner chrome — the scale and the accent do the work, and the air
   around it is deliberate rather than leftover. */
body.pgisr .about-cell--pull {
  grid-column: 1 / -1;
  text-align: left;
  padding-block: clamp(1.1rem, 2vw, 1.9rem);
  background: none;
}
body.pgisr .about-cell--pull::before {
  content: "";
  display: block;
  width: 2.75rem;
  height: 2px;
  margin-bottom: clamp(1rem, 1.6vw, 1.4rem);
  background: var(--accent);
}
body.pgisr .about-cell--pull p {
  margin: 0;
  max-width: 15ch;
  font-family: var(--font-display);
  font-size: clamp(2.2rem, 4.4vw, 3.7rem);
  font-weight: 700;
  line-height: 1.04;
  letter-spacing: -0.03em;
  color: var(--ink);
  text-wrap: balance;
}
body.pgisr .about-cell--pull .about-pull-accent {
  color: var(--accent);
}

/* Direction — heading across the measure, then mission and
   principles as two rule-topped columns. */
body.pgisr .about-cell--dirhead { grid-column: 1 / -1; }
body.pgisr .about-cell--dirhead .origin-statement-headline {
  font-size: clamp(1.6rem, 2.6vw, 2.3rem);
  margin: 0;
}
body.pgisr .about-cell--mission,
body.pgisr .about-cell--principles {
  align-self: start;
  padding-top: clamp(1rem, 1.8vw, 1.5rem);
  border-top: 1px solid var(--line-strong);
}
body.pgisr .about-cell--mission { grid-column: span 7; }
body.pgisr .about-cell--principles { grid-column: span 5; }
body.pgisr .about-mission-text {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(1.35rem, 2vw, 1.8rem);
  font-weight: 700;
  line-height: 1.16;
  letter-spacing: -0.02em;
  color: var(--ink);
  max-width: 24ch;
  text-wrap: balance;
}
body.pgisr .about-principle {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  padding: 0.55rem 0;
}
body.pgisr .about-principle + .about-principle { border-top: 1px solid var(--line); }
body.pgisr .about-principle span {
  flex: none;
  font-family: var(--font-mono);
  font-size: 0.64rem;
  font-weight: 700;
  color: var(--accent);
}
body.pgisr .about-principle strong {
  font-family: var(--font-display);
  font-size: clamp(0.98rem, 1.2vw, 1.1rem);
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--ink);
}
body.pgisr .about-principles-list { margin-top: 0; }

/* Focus, Direction, Mission, and Operating Principles share one eyebrow
   cadence. Local heading margins stay out of the relationship so every
   label has the same measured gap to the content it introduces. */
body.pgisr .about-cell--origin > .ops-label,
body.pgisr .about-cell--dirhead > .ops-label,
body.pgisr .about-cell--direction .ops-label {
  margin-bottom: clamp(0.75rem, 1vw, 0.9rem);
}
body.pgisr .about-cell--origin > .origin-statement-headline {
  margin-top: 0;
}

/* Single column below the breakpoint. */
@media (max-width: 860px) {
  body.pgisr .about-grid { grid-template-columns: 1fr; row-gap: clamp(1.75rem, 7vw, 2.25rem); }
  body.pgisr .about-cell--story,
  body.pgisr .about-cell--origin,
  body.pgisr .about-cell--media,
  body.pgisr .about-cell--focus-copy,
  body.pgisr .about-cell--mission,
  body.pgisr .about-cell--principles { grid-column: 1 / -1; }
  body.pgisr .about-cell--copy > * { max-width: none; }
}

/* The mission is the page's central claim; it was set as body copy. */
body.pgisr .mv-statement-row {
  display: grid;
  grid-template-columns: minmax(8rem, 0.22fr) minmax(0, 1fr);
  gap: clamp(1rem, 3vw, 3rem);
  align-items: baseline;
  padding: clamp(1.25rem, 2vw, 1.75rem) 0 0;
  border-top: 1px solid var(--line-strong);
}
body.pgisr .mv-statement-label {
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}
body.pgisr .mv-statement-text {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 2.6vw, 2.4rem);
  font-weight: 700;
  line-height: 1.12;
  letter-spacing: -0.025em;
  color: var(--ink);
  max-width: 30ch;
  text-wrap: balance;
}
body.pgisr .mv-statement-list { margin-top: clamp(1.75rem, 3vw, 2.5rem); }
body.pgisr .mv-values-intro { margin-top: clamp(1.75rem, 3vw, 2.5rem); }

/* Two principles, two columns — the auto-fit grid was sizing for
   four and leaving half the band empty. */
body.pgisr .mv-values-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (max-width: 760px) {
  body.pgisr .mv-values-grid { grid-template-columns: 1fr; }
  body.pgisr .about-whatis-section .origin-statement { grid-template-columns: 1fr; }
  body.pgisr .about-whatis-section .origin-pull { grid-column: 1; grid-row: auto; margin-top: 1rem; }
  body.pgisr .mv-statement-row { grid-template-columns: 1fr; gap: 0.9rem; }
}

/* The legacy 884px cap was tuned for the old 1180 shell; the band
   now runs the full measure with the copy keeping its own. */
body.pgisr .mv-values-grid { max-width: none; }
body.pgisr .mv-values-grid .mv-value-title { max-width: 24ch; }
body.pgisr .mv-values-grid .mv-value-desc { max-width: 46ch; }

/* Keep the opening deliberate without turning it into a full-screen hero. */
body.pgisr .section.pgi-intro-section {
  padding-top: clamp(1.4rem, 2.2vw, 2rem);
  /* Extra room below the sensor/operator graphic so it doesn't run
     straight into the Site Monitoring photo below — two similar
     monitoring-desk images back to back need a clearer break than
     the tight hero padding gives them. */
  padding-bottom: clamp(3rem, 5vw, 4.5rem);
}
body.pgisr .page-hero.pgi-intro-section {
  padding-top: calc(var(--header-h) + clamp(1.4rem, 2.2vw, 2rem));
}

/* ================================================================
   14 · HOW IT WORKS — first-glance system story
   The primary row is the actual event journey. Passive sensing,
   communications and configuration sit below as supporting system
   characteristics, never as steps in that journey.
   ================================================================ */
/* One plain sentence saying what the system does, for readers who have
   never seen the acronym. Secondary to the kicker, never a copy block. */
/* The intro head's row gap was tuned for a title beside a side column;
   a single explanatory line needs to sit closer to its kicker. */
body.pgisr.how-it-works-page .pgi-intro-head { row-gap: 0.55rem; }

/* The opening statement is sized against what follows it. With the summary
   paragraph gone, the h1 runs straight into the 20px card row: on the shared
   .page-hero scale (4.4rem) that is 3.5x the cards it introduces, which is
   what makes the section read top-heavy. The intro's own 3.6rem scale --
   authored at the top of this file, but out-cascaded there by the equally
   specific .page-hero h1 rule that follows it -- lands at 2.9x. */
body.pgisr.how-it-works-page .pgi-intro-head h1 {
  font-size: clamp(2.1rem, 4vw, 3.6rem);
}

/* "Try the simulator" is the page's only .ops-title, and the shared scale was
   set against the old 4.4rem h1. Against the h1 above it now reads level, so
   step it down onto a ramp that holds ~1.4x below the h1 at every width. This
   also retires the shared phone rule (6vw/3.5rem), which overtook the h1 below
   693px and then dropped 13px across a single pixel of viewport at 700px. */
body.pgisr.how-it-works-page .ops-title {
  font-size: clamp(1.55rem, 2.8vw, 2.5rem);
}
body.pgisr .pgi-intro-summary {
  grid-column: 1 / -1;
  margin: 0 0 0.4rem;
  max-width: 68ch;
  font-size: clamp(0.88rem, 1vw, 0.97rem);
  line-height: 1.55;
  color: var(--body);
}

/* Shared responsive system illustrations on How It Works and Equipment. */
body.pgisr .pgisr-system-graphic {
  width: 100%;
  margin: clamp(1rem, 1.8vw, 1.4rem) 0 0;
  overflow: hidden;
  border: 1px solid var(--line-strong);
  background: #06111a;
}
body.pgisr .pgisr-system-graphic > img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1672 / 941;
  object-fit: cover;
}
body.pgisr .pgisr-system-graphic > picture,
body.pgisr .pgisr-system-graphic > picture > img {
  display: block;
  width: 100%;
}
body.pgisr .pgisr-system-graphic > picture > img {
  height: auto;
}
body.pgisr .pgisr-system-graphic-caption {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin: 0;
  padding: 0.8rem clamp(0.9rem, 1.8vw, 1.35rem);
  border-top: 1px solid var(--line);
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 0.6rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  line-height: 1.45;
  text-transform: uppercase;
}
body.pgisr .pgisr-system-graphic-caption strong {
  color: var(--ink);
  font-family: var(--font-display);
  font-size: clamp(0.98rem, 1.25vw, 1.15rem);
  letter-spacing: -0.015em;
  line-height: 1.15;
  text-transform: none;
}
body.pgisr .pgisr-system-graphic-caption p { margin: 0; }
body.pgisr .pgisr-system-graphic-steps {
  display: grid;
  flex: 1;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0;
  margin: 0;
  padding: 0;
  list-style: none;
}
body.pgisr .pgisr-system-graphic-steps li {
  display: grid;
  gap: 0.38rem;
  min-width: 0;
  padding: 0.7rem clamp(0.75rem, 1.5vw, 1.2rem);
  border-right: 1px solid var(--line);
}
body.pgisr .pgisr-system-graphic-steps li:first-child { padding-left: 0; }
body.pgisr .pgisr-system-graphic-steps li:last-child { border-right: 0; }
body.pgisr .pgisr-system-graphic-steps span {
  color: var(--accent);
  font-size: 0.56rem;
  letter-spacing: 0.13em;
}
body.pgisr .pgisr-system-graphic-steps strong {
  max-width: 18ch;
}
body.pgisr .pgisr-system-graphic--equipment {
  margin-top: 0;
}
body.pgisr .pgisr-system-graphic--equipment .pgisr-system-graphic-caption {
  align-items: stretch;
  flex-direction: column;
  padding-block: 0.55rem 0.75rem;
}
body.pgisr .pgisr-system-graphic--equipment .pgisr-system-graphic-caption > p {
  padding-inline: clamp(0rem, 0.6vw, 0.45rem);
}
@media (max-width: 760px) {
  body.pgisr .pgisr-system-graphic-caption--compact {
    align-items: flex-start;
    flex-direction: column;
    gap: 0.35rem;
  }
  body.pgisr .pgisr-system-graphic-steps {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  body.pgisr .pgisr-system-graphic-steps li {
    border-bottom: 1px solid var(--line);
  }
  body.pgisr .pgisr-system-graphic-steps li:nth-child(2) { border-right: 0; }
  body.pgisr .pgisr-system-graphic-steps li:nth-last-child(-n + 2) { border-bottom: 0; }
  body.pgisr .pgisr-system-graphic-steps li:nth-child(3) { padding-left: 0; }
}

@media (max-width: 520px) {
  body.pgisr .pgisr-system-graphic {
    margin-top: 0.9rem;
  }
  body.pgisr .pgisr-system-graphic > img {
    min-height: 12rem;
    object-fit: cover;
  }
  body.pgisr .pgisr-system-graphic--overview > img {
    object-position: center;
  }
  body.pgisr .pgisr-system-graphic--equipment > img {
    object-position: center;
  }
  body.pgisr .pgisr-system-graphic-caption {
    padding: 0.72rem 0.8rem;
  }
  body.pgisr .pgisr-system-graphic-steps {
    grid-template-columns: 1fr;
  }
  body.pgisr .pgisr-system-graphic-steps li,
  body.pgisr .pgisr-system-graphic-steps li:nth-child(2),
  body.pgisr .pgisr-system-graphic-steps li:nth-last-child(-n + 2) {
    padding: 0.68rem 0;
    border-right: 0;
    border-bottom: 1px solid var(--line);
  }
  body.pgisr .pgisr-system-graphic-steps li:last-child { border-bottom: 0; }
  body.pgisr .pgisr-system-graphic-steps strong { max-width: none; }
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

body.pgisr .pgi-overview-flow {
  --overview-gap: clamp(1.5rem, 2.8vw, 2.8rem);
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  /* Top-aligned, not stretched: the illustration below is the diagram, and
     this row is its key. Boxed cards sized to the tallest step left the
     other four mostly empty and put a second, heavier diagram on top of
     the first. Each step is now a plain ledger cell — number, glyph,
     label, line — that is only as tall as its own content. */
  align-items: start;
  gap: var(--overview-gap);
  list-style: none;
  width: 100%;
  /* The summary paragraph that used to buffer the headline from this row is
     gone, so the row owns that separation now. */
  margin: clamp(1.5rem, 2.4vw, 2.25rem) 0 0;
  padding: 0;
}
body.pgisr .pgi-overview-stage {
  position: relative;
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: 0;
}
/* The flow thread runs between glyphs rather than at half the cell height,
   since cells no longer share a height. Its top is the glyph's centre:
   meta line (~0.85rem) + glyph margin (1rem) + half the glyph (1.3rem). */
body.pgisr .pgi-overview-stage::after {
  position: absolute;
  z-index: 2;
  top: calc(3.15rem - 4px);
  left: 100%;
  /* Stops short of the gap so the head clears the next glyph, including
     the wider two-part Response/Dismissal one. */
  width: calc(var(--overview-gap) - 0.45rem);
  height: 8px;
  background: rgba(66, 197, 187, 0.6);
  clip-path: polygon(0 44%, 70% 44%, 70% 0, 100% 50%, 70% 100%, 70% 56%, 0 56%);
  content: "";
}
body.pgisr .pgi-overview-stage:last-child::after { content: none; }
body.pgisr .pgi-overview-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  font-family: var(--font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
}
body.pgisr .pgi-overview-meta span { color: var(--accent); }
body.pgisr .pgi-overview-meta strong {
  color: var(--muted);
  font-weight: 700;
}
/* Bare glyph, no tile behind it: the tile was a box inside the box. */
body.pgisr .pgi-overview-visual {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  width: auto;
  height: 2.6rem;
  margin: 1rem 0 0.75rem;
  color: var(--accent);
}
body.pgisr .pgi-overview-visual svg {
  width: 3.25rem;
  height: 2.6rem;
  overflow: visible;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: square;
  stroke-linejoin: miter;
}
/* The step label is the whole point of the card, so it is set as a short
   uppercase phrase. Some labels are now two words or a slash-compound
   (Data Collection, Response/Dismissal) and may wrap to a second line at
   narrow card widths — line-height is set to read cleanly either way.
   Response/Dismissal has no space for the browser to break on, so at
   mid-range widths (~960px, 5 cards across) it ran past the card edge
   into the next one. overflow-wrap keeps any label inside its card; the
   matching <wbr> in the markup gives it a clean break after the slash
   instead of a mid-word one if it has to wrap. */
body.pgisr .pgi-overview-stage h3 {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(1.05rem, 1.4vw, 1.3rem);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  overflow-wrap: anywhere;
  color: var(--ink);
}
body.pgisr .pgi-overview-line {
  margin: 0.4rem 0 0;
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--muted);
  text-wrap: pretty;
}
/* Single column: the step becomes a row — icon left, then number, label
   and line stacked beside it — so the sequence still reads top-to-bottom
   in one pass and the arrows stay in the gaps between cards. */
@media (max-width: 900px) {
  body.pgisr .pgi-overview-flow {
    --overview-gap: 1.5rem;
    grid-template-columns: 1fr;
  }
  body.pgisr .pgi-overview-stage {
    display: grid;
    grid-template-columns: 3.25rem minmax(0, 1fr);
    align-items: center;
    gap: 0 1rem;
    padding: 0.4rem 0;
  }
  body.pgisr .pgi-overview-stage::after {
    /* Centred in the row gap, so the rotated thread sits between cells
       rather than over the last line of the one above. */
    top: calc(100% + (var(--overview-gap) / 2) - 4px);
    left: calc(50% - ((var(--overview-gap) - 0.45rem) / 2));
    transform: rotate(90deg);
  }
  body.pgisr .pgi-overview-visual {
    grid-column: 1;
    grid-row: 1 / 4;
    align-self: center;
    width: 3.25rem;
    height: 2.6rem;
    margin: 0;
  }
  body.pgisr .pgi-overview-visual svg { width: 3.25rem; height: 2.6rem; }
  body.pgisr .pgi-overview-meta {
    grid-column: 2;
    grid-row: 1;
  }
  body.pgisr .pgi-overview-stage h3 {
    grid-column: 2;
    grid-row: 2;
    margin-top: 0.5rem;
  }
  body.pgisr .pgi-overview-line {
    grid-column: 2;
    grid-row: 3;
  }
}

@media (max-width: 600px) {
  body.pgisr .section.pgi-intro-section { padding-bottom: 1.1rem; }
  body.pgisr .pgi-overview-flow {
    --overview-gap: 1.35rem;
    margin-top: 0.9rem;
  }
  body.pgisr .pgi-overview-stage {
    grid-template-columns: 2.75rem minmax(0, 1fr);
    padding: 0.35rem 0;
  }
  body.pgisr .pgi-overview-visual { width: 2.75rem; height: 2.2rem; }
  body.pgisr .pgi-overview-visual svg { width: 2.75rem; height: 2.2rem; }
}

/* ================================================================
   15 · EQUIPMENT
   ================================================================ */
/* The section head's 8rem gutter was tuned for the narrow shell and
   now forces four-line headings beside a half-empty band. */
body.pgisr .equipment-section-head {
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 0.8fr);
  gap: clamp(1.75rem, 4vw, 4rem);
  align-items: end;
}
body.pgisr .equipment-section-head h2 { max-width: 18ch; }

/* Two consecutive lede paragraphs were running together. */
body.pgisr .equipment-hero-lede + .equipment-hero-lede { margin-top: 1rem; }

/* Spec chips read as a measured row of characteristics, matching the
   index chips used by the workflow and system components. */
body.pgisr .equipment-hero-points li {
  border-color: var(--line-strong);
  border-radius: 0;
  background: rgba(255,255,255,0.02);
  font-family: var(--font-mono);
  /* Was 0.62rem — around 10px, the smallest type in the hero. */
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--body);
}

/* The engineering-status footnote closes the page; keep it quiet but
   part of the system rather than loose text. */
body.pgisr .equipment-status-footnote {
  border-top: 1px solid var(--line-strong);
  background: var(--bg-2);
}

/* ================================================================
   16 · KICKER — contexts that set their own display
   Several pages override `.ops-label`'s display for local layout.
   Those keep their spacing but pick up the shared dot treatment.
   ================================================================ */
body.pgisr .contact-hero > .shell > .ops-label,
body.pgisr .intel-feed-transition .ops-label,
body.pgisr .mv-section-head > .ops-label,
body.pgisr .about-direction-section .mv-section-head > .ops-label,
body.pgisr .faq-section .mv-section-head > .ops-label,
body.pgisr .concept-specs-head .ops-label,
body.pgisr .quiet-band .ops-label,
body.pgisr .equipment-section-head .ops-label {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
}

/* ================================================================
   17 · FOOTER — compact closing band
   Same content as before, composed to a fraction of the height:
   a moderate CTA lockup sits level with the three link columns,
   and the signature/baseline collapse into one quiet strip.
   ================================================================ */
/* Each page converts on its own closing CTA band, so the footer carries no
   CTA at all. The lead row is the brand lockup on the left and the two
   functional columns on the right; legal links and the copyright share one
   ruled baseline beneath. */
body.pgisr .pgisr-footer-lead {
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap: clamp(2rem, 5vw, 5rem);
  align-items: center;
  padding-block: clamp(2rem, 3vw, 2.5rem) clamp(1.5rem, 2.5vw, 2rem);
}
body.pgisr .pgisr-footer-brand { display: flex; flex-direction: column; align-items: flex-start; }
body.pgisr .pgisr-footer-picture { display: block; }
body.pgisr .pgisr-footer-expansion { display: none; }
/* Sized so the expansion line under the wordmark is legible, not just
   present. The phone-specific size is set below. */
body.pgisr .pgisr-footer-mark { height: clamp(90px, 11vw, 112px); }
body.pgisr .pgisr-footer-cols {
  grid-template-columns: 1.25fr 1fr;
  gap: clamp(1.5rem, 3vw, 3rem);
  padding-top: 0;
}
body.pgisr .pgisr-footer-col-head { margin-bottom: 0.8rem; }
body.pgisr .pgisr-footer-nav-list li { margin-bottom: 0.35rem; }
body.pgisr .pgisr-footer-nav-list a {
  font-size: 0.9rem;
  line-height: 1.5;
}
body.pgisr .pgisr-footer-baseline {
  border-top: 1px solid var(--footer-line);
  padding: 1rem 0 1.25rem;
}
body.pgisr .pgisr-footer-legal a { font-size: 0.68rem; font-family: var(--font-mono); letter-spacing: 0.02em; }

/* ================================================================
   18 · RESPONSIVE
   This layer sets several grids without a media query, which
   outranks the older breakpoint rules on specificity. Each grid it
   touches is restated here so the existing mobile and tablet
   behaviour survives.
   ================================================================ */
@media (max-width: 1100px) {
  body.pgisr .pgisr-footer-cols { gap: 2rem; }
}
@media (max-width: 980px) {
  body.pgisr .equipment-section-head {
    grid-template-columns: 1fr;
    gap: 1.5rem;
    align-items: start;
  }
  body.pgisr .equipment-section-head h2 { max-width: 22ch; }
}
@media (max-width: 900px) {
  body.pgisr .pgisr-footer-lead {
    grid-template-columns: 1fr;
    gap: 2rem;
    padding-block: 2.5rem 2rem;
  }
}
@media (max-width: 700px) {
  body.pgisr .pgisr-footer-lead {
    padding-block: 0.75rem 0.65rem;
    gap: 0.65rem;
  }
  /* Phone shows the same full logo as desktop, so the expansion line stays
     part of the artwork instead of being re-set in HTML. Driven by width
     rather than height here: the descriptor is only 3.08 of the 48-unit
     artwork, so letting it run to the container keeps that line at roughly
     the size it renders at on desktop (~6.5px vs ~7.2px cap). */
  body.pgisr .pgisr-footer-picture {
    width: 100%;
    max-width: 360px;
    height: auto;
  }
  body.pgisr .pgisr-footer-mark {
    width: 100%;
    height: auto;
  }
  body.pgisr .pgisr-footer-cols {
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
    gap: 0.75rem;
  }
  body.pgisr .pgisr-footer-col-head { margin-bottom: 0.3rem; }
  body.pgisr .pgisr-footer-contact-row { margin-bottom: 0.2rem; }
  body.pgisr .pgisr-footer-nav-list li { margin-bottom: 0; }
  body.pgisr .pgisr-footer-nav-list { display: block; }
  body.pgisr .pgisr-footer-baseline {
    gap: 0.3rem 0.75rem;
    padding-block: 0.55rem 0.7rem;
  }
  body.pgisr .pgisr-footer-baseline-meta {
    font-size: 0.62rem;
    line-height: 1.45;
  }
  body.pgisr .pgisr-footer-pwi-credit a {
    display: inline;
    min-height: 0;
  }
  body.pgisr .pgisr-footer-legal { margin-top: -0.35rem; }
  /* Interior pages open tighter on a phone — the title carries the
     page, so the surrounding air comes down with the viewport. */
  body.pgisr:not(.legal-page) .page-hero,
  body.pgisr .equipment-hero {
    padding-block: calc(var(--header-h) + 2rem) 2.5rem;
  }
  body.pgisr .pgi-pagehead { padding-bottom: 1.25rem; }
  body.pgisr .pgi-pagehead + * { margin-top: 1.5rem; }
}
@media (max-width: 300px) {
  body.pgisr .pgisr-footer-cols { grid-template-columns: 1fr; }
}

/* Touch targets: disclosure rows, footer links and nav items all
   clear 44px on a phone. */
@media (max-width: 900px) {
  body.pgisr .faq-item summary { padding-block: 1rem; min-height: 44px; }
  body.pgisr .pgisr-footer-nav-list a,
  body.pgisr .pgisr-footer-contact-row a { display: inline-block; padding-block: 0.35rem; }
}

@media (max-width: 700px) {
  body.pgisr .about-hero-v2-grid { padding: 0 0 0.25rem; gap: 1.75rem; }
}

/* The page head already provides the separation; the row beneath it
   should not add its own top padding on top of that. */
body.pgisr .pgi-pagehead + .about-hero-v2-grid { padding-top: 0; }

/* ================================================================
   19 · VISUAL QA PASS
   ================================================================ */
/* ---- Shared band media -----------------------------------------
   Interior pages use the same placeholder treatment as the homepage
   while retaining their own final-media ratios. */
body.pgisr .pgi-band-media {
  position: relative;
  margin: clamp(2rem, 3.5vw, 3rem) 0 0;
  overflow: hidden;
  border: 1px solid var(--line-strong);
  background: var(--bg-3);
}
body.pgisr .pgi-band-media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
body.pgisr .pgi-media-caption {
  margin: 0;
  padding: 0.7rem 0.9rem;
  border-top: 1px solid var(--line);
  background: #09131e;
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 0.6rem;
  line-height: 1.45;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}
body.pgisr .pgi-band-media > .ed-ph { border: 0; }
/* Ratio classes are shared by placeholders and their eventual images,
   including at mobile widths. */
body.pgisr .pgi-band-media--21x9 .ed-ph,
body.pgisr .pgi-band-media--21x9 img { aspect-ratio: 21 / 9; }
body.pgisr .pgi-band-media--3x2 .ed-ph,
body.pgisr .pgi-band-media--3x2 img { aspect-ratio: 3 / 2; }

/* About carries no second image slot: the only concept its copy
   supports here is PWI's component manufacture, which the existing
   engineering-environment photograph two bands below already shows.
   The band stays typographic rather than repeating that image. */

/* ---- LEOPARD head runs the full measure ------------------------ */
/* The transition question already draws a rule immediately above this
   head; a second one 300px below it reads as a tic, not structure. */
body.pgisr #leopard .intel-feed-copy.pgi-pagehead {
  margin-bottom: 0;
  padding-bottom: 0;
  border-bottom: 0;
}
body.pgisr #leopard .pipeline-steps { margin-top: 0; }

/* ---- The dot means "a section starts here" ---------------------
   Panel and readout headers share the kicker's mono treatment but
   drop the marker, so the dot keeps signalling section openings
   rather than appearing on every label on the page. */
body.pgisr .about-id-card-label::before,
body.pgisr .equipment-sensor-legend-label::before,
body.pgisr .feed-panel-title::before {
  content: none;
}
body.pgisr .about-id-card-label,
body.pgisr .equipment-sensor-legend-label,
body.pgisr .feed-panel-title {
  color: var(--muted);
}

/* ---- Contact: the intake grid needs to stack sooner --------------
   The two-column split holds a 280px minimum for the info column,
   which squeezed the form into ~280px between 700px and 1000px and
   clipped the two-up field placeholders. The single-column rules
   only started at 700px. */
@media (max-width: 1000px) {
  body.pgisr .contact-grid { grid-template-columns: 1fr; gap: 2.75rem; }
  body.pgisr .contact-info-column { position: static; }
}

/* ---- The simulation head was the last side-label opener ---------
   Every other section on the site puts the kicker above the title
   at the shell's left edge; this one held the kicker in a 220px
   side column, which pushed the heading off the page's left rule. */
body.pgisr .deployment-demo-header {
  grid-template-columns: 1fr;
  gap: 0;
}
body.pgisr .deployment-demo-header > .ops-label { margin-bottom: 1.1rem; }

/* ================================================================
   20 · MAP SYMBOL KEY
   Explains the deployment map's glyph vocabulary once, outside the
   map, rather than labeling all 8 sensor nodes / 4 cameras / the
   gateway individually — keeps the diagram itself uncluttered while
   a first-time visitor still gets the meaning of each icon.
   ================================================================ */
body.pgisr .map-legend {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1.1rem 1.75rem;
  list-style: none;
  margin: 0;
  padding: 0.85rem clamp(1rem, 3vw, 1.5rem);
  border-top: 1px solid var(--line-strong);
  background: var(--bg-2);
  font-family: var(--font-mono);
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--body);
}
body.pgisr .map-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
}
body.pgisr .map-legend-icon {
  flex: none;
  color: var(--accent);
  overflow: visible;
}
body.pgisr .map-legend-icon--line { color: rgba(232,236,240,0.55); }
@media (max-width: 520px) {
  body.pgisr .map-legend { gap: 0.7rem 1.15rem; font-size: 0.62rem; }
}

/* Simulator + debrief read as one beat: the simulator closes on a short tail
   and the debrief opens directly under it, instead of both carrying the full
   section band and drifting apart. */
body.pgisr .deployment-demo-section {
  padding-bottom: clamp(2rem, 3vw, 3rem);
}
body.pgisr .intel-feed-section {
  padding-top: 0;
}

/* Preserve the interior-page display scale at 320px without letting a few
   longer titles collapse into single-word towers. */
@media (max-width: 340px) {
  body.how-it-works-page #pgi-intro-title {
    width: calc(100% + 1.25rem);
    margin-inline: -0.5rem;
    font-size: 2.3rem;
  }
  body.how-it-works-page #deployment-demo-title {
    width: calc(100% + 0.5rem);
    margin-inline: 0;
    text-wrap: pretty;
  }
  body.how-it-works-page #deployment-demo-title { font-size: 1.78rem; }
  body.pgisr #direction-title {
    width: 100%;
    max-width: 260px;
    margin-inline: 0;
    font-size: 1.825rem;
    text-wrap: pretty;
  }
}

/* ── About grid — paired rows share a top edge ───────────────────
   The 7/5 copy+image rows were vertically centred, so a short copy
   block floated ~53px below its image while a taller one happened to
   line up. Top alignment gives every pair the same baseline.
   The images also inherited .pgi-band-media's stacked-band top margin
   (~49px), which the grid's row-gap already provides — .about-cell--media
   tried to cancel it but tied on specificity and lost. */
body.pgisr .about-grid {
  align-items: start;
}

body.pgisr .about-grid .about-cell--media.pgi-band-media {
  margin-top: 0;
}

/* Keeps a figure/caption clear of the fixed header if it's ever the
   scroll target — keyboard focus landing on the "magnetometers" link,
   find-in-page, etc. — instead of settling with its top edge under it. */
body.pgisr .about-grid .about-cell--media {
  scroll-margin-top: calc(var(--header-h) + 1rem);
}

/* Our Focus and Our Direction now share one flex column (.about-cell--
   focus-copy, wrapping both in the markup) beside the engineering image,
   instead of each being its own grid row sized to match the image's
   height. That previous row-per-heading approach left a large empty gap
   between the two headings whenever the image was taller than the
   combined text (it usually is) — the text was pinned to the top and
   bottom of the shared row span with nothing to fill the middle. A flex
   column sizes itself from its own content, so the two headings sit a
   fixed, modest distance apart regardless of image height; any leftover
   height (image taller than the text column) simply extends below the
   text, the same way the story/media pair above it already behaves.
   Image/copy pairing, source order, and the 5/7-column split stay intact. */
body.pgisr .about-cell--focus-copy {
  display: flex;
  flex-direction: column;
  gap: clamp(1rem, 1.6vw, 1.5rem);
}

@media (min-width: 861px) {
  body.pgisr .about-cell--focus-media {
    grid-column: 1 / span 5;
  }

  body.pgisr .about-cell--focus-copy {
    grid-column: 6 / -1;
  }
}

/* A hairline rule marks the seam between the two headings — still two
   sections, but tied together instead of adrift in whitespace. */
body.pgisr .about-cell--focus-copy .about-cell--dirhead {
  padding-top: clamp(1rem, 1.6vw, 1.5rem);
  border-top: 1px solid var(--line);
}

/* ── About · Mission + Operating Principles read as one block ────
   They answer the same heading, so they share one container with a single
   continuous top rule. Each previously drew its own rule and the grid's
   column gap cut the line in half, so they read as two blocks sitting
   near each other rather than one statement.
   The container repeats the parent's 12-column track and gap so the two
   halves land on exactly the same edges as the copy/image rows above —
   a split of its own would have drifted off that rhythm.
   Roughly 1/3 mission, 2/3 principles (4/8 of the 12-track container):
   the mission is one short line: it doesn't need — and previously wasted —
   over half the row, while the principles were left with barely any room
   to breathe. More padding-top on the container and larger type on both
   halves give the block real presence instead of reading as an
   afterthought under "Mission and operating principles". */
body.pgisr .about-cell--direction {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: clamp(2rem, 4vw, 4rem);
  align-items: start;
  padding-top: clamp(1.5rem, 2.4vw, 2.25rem);
  border-top: 1px solid var(--line-strong);
}

body.pgisr .about-cell--direction > .about-cell--mission { grid-column: span 4; }
body.pgisr .about-cell--direction > .about-cell--principles { grid-column: span 8; }

/* Inside the shared container the container owns the rule and spacing. */
body.pgisr .about-cell--direction > .about-cell--mission,
body.pgisr .about-cell--direction > .about-cell--principles {
  align-self: start;
  padding-top: 0;
  border-top: 0;
}

@media (max-width: 860px) {
  body.pgisr .about-cell--direction { grid-template-columns: 1fr; row-gap: 1.5rem; }
  body.pgisr .about-cell--direction > .about-cell--mission,
  body.pgisr .about-cell--direction > .about-cell--principles { grid-column: auto; }
}

/* The narrower 1/3 column gives the mission line room to wrap and read as
   a real statement — larger and bolder than the old single-line squeeze. */
body.pgisr .about-cell--direction .about-mission-text {
  max-width: none;
  font-size: clamp(1.3rem, 2vw, 1.75rem);
  text-wrap: pretty;
}

/* Principles stack as two full rows rather than a tight inline pair, each
   with generous padding and its own rule — more weight per item, matching
   the mission column's larger type instead of feeling like an afterthought. */
body.pgisr .about-cell--direction .about-principles-list {
  display: flex;
  flex-direction: column;
}

body.pgisr .about-cell--direction .about-principle {
  padding: clamp(0.85rem, 1.3vw, 1.1rem) 0;
}

body.pgisr .about-cell--direction .about-principle + .about-principle {
  border-top: 1px solid var(--line);
}

body.pgisr .about-cell--direction .about-principle span {
  font-size: 0.72rem;
}

body.pgisr .about-cell--direction .about-principle strong {
  font-size: clamp(1.1rem, 1.4vw, 1.3rem);
}

/* ── Contact · hero-to-intake gap ────────────────────────────────
   The hero's closing space (~58px) and the intake band's opening space
   (a full --pgi-band, ~90px) stack into one ~148px void on desktop, which
   reads as a bigger break than the two sections deserve. Trimming a fifth
   off the band's top edge takes it to ~130px — the hero, the section
   divider, the two-column layout and the mobile stack are all untouched.
   Desktop only: below 761px premium.css already sets its own 3.5rem top
   padding here, and that spacing is fine as it stands. */
@media (min-width: 761px) {
  body.pgisr .contact-intake-section {
    padding-top: calc(var(--pgi-band) * 0.8);
  }
}

/* ── Contact · one section ───────────────────────────────────────
   Title, lede and Direct Contact stack in the left column and the
   form starts beside them in the same row — there is no separate
   hero band to feel disconnected from. The section keeps the
   interior-page opening (header offset, accent tick, breadcrumb, a
   tint at the top) and closes on a plain band like any other page.
   FAQ shares .contact-hero; everything here is keyed to this page's
   own title id and leaves that page untouched. */
body.pgisr .page-hero.contact-hero[aria-labelledby="contact-title"] {
  border-bottom: 0;
  padding-bottom: var(--pgi-band);
  background:
    radial-gradient(88% 60% at 84% 8%, rgba(42,150,136,0.10), transparent 62%),
    linear-gradient(180deg, #121b26 0, var(--bg-2) 520px);
}
body.pgisr .contact-hero[aria-labelledby="contact-title"] .contact-hero-copy {
  padding: 1.25rem 0 0;
  border-left: 0;
  max-width: 40ch;
}
body.pgisr .contact-hero[aria-labelledby="contact-title"] .contact-info-column > .eyebrow {
  margin-top: clamp(2rem, 3vw, 3rem);
}
/* Two columns above 1080px: the title column gets a little more of
   the measure than the contact rows alone needed, and the title is
   sized to that column rather than to the full shell. Below it the
   columns stack and the title has to lead, so the form gives up the
   order:-1 it had when the left column held only the contact rows. */
@media (min-width: 1081px) {
  body.pgisr .contact-hero[aria-labelledby="contact-title"] .contact-grid {
    grid-template-columns: minmax(300px, 0.78fr) minmax(0, 1.22fr);
  }
  /* No ch cap here: the column itself sets the wrap, and at every
     width above the breakpoint that lands "Tell us about" on the
     first line and "your site" on the second. A 9ch cap forced a
     third line at laptop widths. */
  body.pgisr .contact-hero[aria-labelledby="contact-title"] h1 {
    font-size: clamp(2.8rem, 4.6vw, 4.4rem);
    max-width: none;
  }
}
@media (max-width: 1080px) {
  body.pgisr .contact-hero[aria-labelledby="contact-title"] .contact-form-column { order: 0; }
}

/* ── FAQ · title and lede as one block ───────────────────────────
   contact.html's two-column hero (title left, lede baseline-aligned
   at bottom-right) works there because a form sits opposite it in the
   same row. FAQ has no second column, so the same layout left the
   lede floating off to the side at desktop widths — further from the
   title than from the question list below it, reading as unrelated
   to both. Stacking it directly under the title at every width joins
   the two into one opening block instead of a heading with a caption
   parked beside it. Scoped to this page's own title id, same as the
   rhythm block below, so contact.html's row is untouched. */
body.pgisr .contact-hero[aria-labelledby="faq-title"] .contact-hero-grid {
  grid-template-columns: 1fr;
  gap: 1.1rem;
}
body.pgisr .contact-hero[aria-labelledby="faq-title"] .contact-hero-copy {
  align-self: start;
  padding: 0;
  border-left: 0;
  max-width: 60ch;
}

/* ── FAQ · hero and list as one surface ──────────────────────────
   The shared interior-page hero closes on a 1px rule (line-strong)
   meant to separate a hero from unrelated content below — but here
   "below" is just the rest of the same question-and-answer page, so
   the rule read as a seam cutting one page into two. The hero's own
   background already fades to var(--bg) by 78% of its height, which
   is what the page sits on everywhere else, so dropping the rule
   alone is enough for the two to read as one continuous surface. */
body.pgisr .page-hero.contact-hero[aria-labelledby="faq-title"] {
  border-bottom: 0;
}

/* ── FAQ · desktop vertical rhythm ───────────────────────────────
   The FAQ page carries one short hero and eight disclosure rows, so
   the shared interior-page bands leave it reading as a mostly-empty
   page on a wide screen, and the title-plus-lede block above now
   reads as its own island above that gap. The hero's own top offset
   (header clearance) and the list's bottom padding (space before the
   footer) are left alone — only the gap *between* the lede and the
   first question is cut, down to a third of the original band, so
   the list sits right under the hero instead of stranded below it.

   Deliberately untouched: the list's 900px centred measure, the
   accordion row padding, type, colour, alignment and behaviour.

   Scoped two ways. Horizontally: the hero rule is keyed to this
   page's `aria-labelledby="faq-title"` so contact.html, which shares
   .contact-hero, keeps its current opening. Vertically, the hero's own
   band is only trimmed >=901px, because at 820px and below it already
   sits at the low end of its clamp (--pgi-band-tight 44px) and does
   not read as empty there. The list's top padding is a different
   variable — .faq-section is also a plain .section, so below 901px it
   was still pulling the generic --section-space clamp (72-144px, or a
   flat 4.5rem under 760px), which is sized for a section that follows
   unrelated content, not a question list right under its own hero. That
   one is cut at every width, mobile included. */
body.pgisr .faq-section {
  padding-top: calc(var(--pgi-band) * 0.3);
}
@media (min-width: 901px) {
  body.pgisr .page-hero.contact-hero[aria-labelledby="faq-title"] {
    padding-block: calc(var(--header-h) + var(--pgi-band-tight) * 0.55)
                   calc(var(--pgi-band-tight) * 0.3);
  }
  body.pgisr .faq-section {
    padding-bottom: calc(var(--pgi-band) * 0.55);
  }
}

/* ---- Sensor legend under the detect-to-archive graphic ----
   The eight sensor names are painted into the artwork, which drops below
   readable size on narrow screens. This repeats them as real text so the
   list survives at every width and is reachable by screen readers. */
body.pgisr .pgisr-sensor-legend {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem 1rem;
  padding: 0.85rem clamp(0.9rem, 1.8vw, 1.35rem);
  border-top: 1px solid var(--line);
  font-family: var(--font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
body.pgisr .pgisr-sensor-legend-title {
  color: var(--muted);
  white-space: nowrap;
}
body.pgisr .pgisr-sensor-legend ul {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 0.9rem;
  flex: 1 1 auto;
  margin: 0;
  padding: 0;
  list-style: none;
}
body.pgisr .pgisr-sensor-legend li {
  color: var(--ink);
  white-space: nowrap;
}
body.pgisr .pgisr-sensor-legend li small {
  margin-left: 0.3rem;
  color: var(--muted);
  font-size: 0.92em;
  letter-spacing: 0.05em;
  text-transform: none;
}
body.pgisr .pgisr-sensor-legend a {
  color: var(--accent, #4be7ef);
  white-space: nowrap;
  text-decoration: none;
  border-bottom: 1px solid currentColor;
}
body.pgisr .pgisr-sensor-legend a:hover { opacity: 0.8; }

@media (max-width: 560px) {
  body.pgisr .pgisr-sensor-legend { font-size: 0.58rem; gap: 0.45rem 0.7rem; }
  body.pgisr .pgisr-sensor-legend li small { display: none; }
}

/* ================= Overview flow graphic =================
   Two photographs with everything else generated over them. Replaces a
   flattened PNG whose baked-in labels kept garbling between regenerations. */
body.pgisr .pgi-flow {
  /* Deliberately much wider than the old clamp(1rem,1.8vw,1.4rem): the
     overview row above is the fast summary and this figure is the detailed
     demonstration of it, and at the old gap they read as one continuous
     list instead of two sections with different jobs. Roughly matches the
     section's own bottom padding, so this internal break reads as
     comparable in weight to a real section boundary. */
  margin: clamp(2.75rem, 4.5vw, 4rem) 0 0;
  border: 1px solid var(--line-strong);
  background: #06111a;
}
body.pgisr .pgi-flow-title {
  padding: 0.85rem clamp(0.9rem, 1.8vw, 1.35rem);
  border-bottom: 1px solid var(--line);
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
body.pgisr .pgi-flow-grid { display: grid; grid-template-columns: 1fr; }
@media (min-width: 1100px) {
  /* The two plates used to butt together on a single hairline, which read as
     one photograph awkwardly spliced - and worse, it put the operations room
     physically next door to the estate when the whole point of 04 is that it
     is somewhere else. The gutter shows the figure's own background (the
     same #06111a as the title bar), so the separation reads as part of the
     frame rather than as a stripe laid over the pictures, and the secure
     uplink now visibly crosses open space between two locations.
     js/overview-flow.js measures the real edges, so the connector spans
     whatever this gap resolves to. */
  body.pgisr .pgi-flow-grid {
    grid-template-columns: 1.85fr 1fr;
    column-gap: clamp(14px, 1.4vw, 22px);
  }
}
body.pgisr .pgi-flow-site,
body.pgisr .pgi-flow-ops { position: relative; overflow: hidden; }
/* Was the photo's native 1672/941 (16:9) ratio, shown uncropped - visual QA
   found the whole illustration reading as a compressed strip for how much
   it has to carry (estate, sensor ring, rack, ops room, five callouts).
   Cropped in to 1672/1220 instead of just adding height: ~30% taller at the
   same width, with the excess coming off the sides of the estate photo
   (already wide parkland either side of the house) via object-fit: cover
   rather than as empty top/bottom padding. js/overview-flow.js remaps every
   label position for this crop; js/estate-geometry.js (shared with the
   simulator) is untouched. */
body.pgisr .pgi-flow-site { aspect-ratio: 1672 / 1220; }
/* The photograph and its overlay keep the box the SVG is registered to.
   The labels sit outside it in the DOM so that on narrow screens they can
   drop below the picture instead of burying it - at 375px the sensor panel
   alone was taller than the whole map and covered 47% of it. */
body.pgisr .pgi-flow-plate { position: relative; aspect-ratio: 1672 / 1220; overflow: hidden; }
@media (max-width: 1099px) {
  body.pgisr .pgi-flow-site { aspect-ratio: auto; display: flex; flex-direction: column; }
  body.pgisr .pgi-flow-site .pgi-callout,
  body.pgisr .pgi-flow-site .pgi-sensor-inputs {
    position: static;
    width: auto;
    transform: none;
    border-left: 0; border-right: 0; border-bottom: 0;
    background: #06111a;
  }
  body.pgisr .pgi-sensor-inputs ul { display: flex; flex-wrap: wrap; gap: 0.2rem 0.75rem; }
  /* Stacked, these read as list rows, not floating pins — the pin's own
     tight padding/line-height left them cramped (title and subline almost
     touching, rows packed edge to edge). More padding and a little room
     between the two lines only; no text, size or order changes. */
  body.pgisr .pgi-flow-site .pgi-callout,
  body.pgisr .pgi-flow-ops .pgi-callout {
    padding: 1rem 0.5rem;
    gap: 0.65rem;
  }
  body.pgisr .pgi-flow-site .pgi-callout span,
  body.pgisr .pgi-flow-ops .pgi-callout span {
    margin-top: 0.25rem;
  }
}
/* Matches .pgi-flow-site's new crop below 1100px (its own stacked box, not
   tied to the estate photo's coordinate system) so the ops room gets the
   same taller treatment in the mobile layout. */
/* No border-left on desktop: with the gutter above doing the separating, a
   hairline on this one edge only read as a stray line floating beside the
   gap. The stacked layout below 1100px still gets its border-top. */
body.pgisr .pgi-flow-ops { aspect-ratio: 1672 / 1220; }
@media (min-width: 1100px) {
  /* The estate column is locked to this ratio because the SVG overlay crops
     to match it - any other ratio slides the perimeter off the photograph.
     The ops plate is portrait, so left to itself it made the grid row taller
     than the map and left an empty band underneath. Pinning it to the row
     height and cropping inside instead keeps both columns flush. */
  body.pgisr .pgi-flow-ops { aspect-ratio: auto; height: 100%; }
  body.pgisr .pgi-flow-ops > img { position: absolute; inset: 0; }
}
/* :not() keeps these off the car, which is a separate absolutely-positioned
   image inside the same box - without it the plate rule won by specificity
   and stretched the car to fill the map. */
/* The plate lives inside .pgi-flow-plate now, so these must target it there.
   As a direct-child rule on .pgi-flow-site it silently stopped matching when
   the wrapper was introduced, and the photograph rendered at natural size,
   clipped, with the overlay still spanning the full box. */
body.pgisr .pgi-flow-plate > img:not(.pgi-vehicle-photo),
body.pgisr .pgi-flow-ops > img {
  display: block; width: 100%; height: 100%; object-fit: cover;
}
body.pgisr .pgi-flow-plate > img:not(.pgi-vehicle-photo) { filter: saturate(0.72) contrast(1.05) brightness(0.86); }
/* Properly lit plate, so only a light grade to sit it beside the estate. */
body.pgisr .pgi-flow-ops > img { filter: saturate(0.9) contrast(1.02) brightness(0.94); }
body.pgisr .pgi-flow-overlay {
  position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none;
}

/* ---- drawn boundary, sensors and approach ---- */
body.pgisr .pgi-cone { fill: rgba(76, 223, 226, 0.17); stroke: none; }
body.pgisr .pgi-perimeter {
  fill: none; stroke: #4be7ef; stroke-width: 4; stroke-linejoin: round;
  filter: drop-shadow(0 0 9px rgba(75, 231, 239, 0.85));
}
body.pgisr .pgi-sensor-ring { fill: rgba(4, 18, 26, 0.85); stroke: #6cf3f1; stroke-width: 2.5; }
body.pgisr .pgi-sensor-core { fill: #c7ffff; }
body.pgisr .pgi-approach { fill: none; stroke: rgba(255, 150, 60, 0.85); stroke-width: 3.5; stroke-dasharray: 14 11; }
body.pgisr .pgi-approach-head {
  fill: #D4A72C;
  stroke: #ffc078;
  stroke-width: 1.1;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  filter: drop-shadow(0 0 2px rgba(212, 167, 44, 0.5));
}
/* ---- the hub: everything on the property reports here ----
   Dimmed and de-arrowed from the original 0.62-opacity, arrowheaded
   lines: eight of those converging on one point, on top of eight
   sensor tags and three numbered callouts, read as noise before
   anything else did. Still visible enough to carry "reports to the
   hub"; just background texture now, not eight assertive lines
   competing with the boundary. */
body.pgisr .pgi-spoke {
  fill: none;
  stroke: rgba(108, 243, 241, 0.4);
  stroke-width: 1.4;
  stroke-dasharray: 5 5;
  stroke-linecap: round;
}
body.pgisr .pgi-spoke-head { display: none; }
body.pgisr .pgi-house-halo {
  fill: rgba(76, 223, 226, 0.1);
  stroke: rgba(108, 243, 241, 0.35);
  stroke-width: 1.5;
}
body.pgisr .pgi-chip-body {
  fill: rgba(4, 20, 28, 0.92);
  stroke: #6cf3f1;
  stroke-width: 2.4;
  filter: drop-shadow(0 0 11px rgba(75, 231, 239, 0.7));
}
body.pgisr .pgi-chip-pin {
  stroke: #6cf3f1;
  stroke-width: 2;
  stroke-linecap: round;
}
body.pgisr .pgi-house-core { fill: #c7ffff; }
body.pgisr .pgi-hub-tag {
  border-color: rgba(108, 243, 241, 0.65);
  background: rgba(5, 20, 28, 0.94);
  color: #dffbfc;
  font-weight: 600;
}

/* ---- sensor inputs panel ---- */
body.pgisr .pgi-sensor-inputs {
  position: absolute; top: 3%; left: 1.6%; width: min(20%, 178px);
  padding: 0.6rem 0.65rem;
  border: 1px solid rgba(104, 220, 229, 0.3);
  background: rgba(5, 17, 25, 0.9);
  font-family: var(--font-mono);
}
body.pgisr .pgi-sensor-inputs h4 {
  margin: 0 0 0.45rem; color: #6cf3f1;
  font-size: 0.56rem; font-weight: 600; letter-spacing: 0.11em; text-transform: uppercase;
}
body.pgisr .pgi-sensor-inputs ul { margin: 0; padding: 0; list-style: none; }
body.pgisr .pgi-sensor-inputs li {
  display: flex; align-items: center; gap: 0.4rem;
  padding: 0.2rem 0; color: #dceff1;
  font-size: 0.58rem; letter-spacing: 0.07em; text-transform: uppercase;
}
body.pgisr .pgi-sensor-inputs li::before {
  content: ""; flex: none; width: 6px; height: 6px; border-radius: 50%;
  background: #4be7ef; box-shadow: 0 0 7px rgba(75, 231, 239, 0.8);
}
body.pgisr .pgi-sensor-inputs li:nth-child(1)::before,
body.pgisr .pgi-sensor-inputs li:nth-child(5)::before {
  background: #D4A72C; box-shadow: 0 0 7px rgba(212, 167, 44, 0.75);
}
body.pgisr .pgi-sensor-inputs a {
  display: inline-block; margin-top: 0.5rem; color: #6cf3f1;
  font-size: 0.54rem; letter-spacing: 0.08em; text-transform: uppercase; text-decoration: none;
  border-bottom: 1px solid currentColor;
}

/* ---- numbered callouts ----
   These carry the same 01-05 numbers as the overview row above the figure,
   so they are the "story" layer's primary anchors -- the obvious path a
   reader's eye should take through the photograph. A soft amber-tinted
   glow (the same accent as the number badge itself) gives them a touch
   more presence now that the sensor-tag layer around them reads quieter,
   without changing their size, position or any text. */
body.pgisr .pgi-callout {
  position: absolute; display: flex; align-items: center; gap: 0.5rem;
  margin: 0; padding: 0.4rem 0.6rem 0.4rem 0.4rem;
  border: 1px solid rgba(212, 167, 44, 0.32);
  background: rgba(6, 16, 24, 0.92);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.4);
  font-family: var(--font-mono);
}
body.pgisr .pgi-callout b {
  display: grid; place-items: center; flex: none; width: 26px; height: 26px;
  border-radius: 50%; background: #D4A72C; color: #08131a;
  font-size: 0.66rem; font-weight: 700;
}
body.pgisr .pgi-callout span { display: block; line-height: 1.3; }
body.pgisr .pgi-callout strong {
  display: block; color: #f2f7f8;
  font-size: 0.62rem; font-weight: 600; letter-spacing: 0.07em; text-transform: uppercase;
}
body.pgisr .pgi-callout span {
  color: var(--muted); font-size: 0.55rem; letter-spacing: 0.05em; text-transform: uppercase;
}
body.pgisr .pgi-callout--01,
body.pgisr .pgi-callout--02 {
  /* Placed from LABEL_ANCHORS in js/overview-flow.js, the same points
     their leader lines are drawn to. */
  left: var(--label-x);
  top: var(--label-y);
  transform: translateY(-50%);
}


body.pgisr .pgi-callout--04 { left: 5%; bottom: 6%; }
/* Directly above the event record, so label and list read as one unit. */
body.pgisr .pgi-callout--05 { right: 5%; top: 5.5%; }

/* ---- operator alert and event log, laid over the screens ---- */
body.pgisr .pgi-ops-alert {
  position: absolute; right: 6%; bottom: 20%;
  display: flex; align-items: flex-start; gap: 0.45rem;
  padding: 0.45rem 0.6rem;
  border: 1px solid #D4A72C; border-radius: 3px;
  background: rgba(10, 8, 4, 0.9);
  color: #EBC65A; font-family: var(--font-mono);
  font-size: 0.56rem; letter-spacing: 0.08em; line-height: 1.45; text-transform: uppercase;
}
body.pgisr .pgi-ops-alert-mark {
  display: grid; place-items: center; flex: none; width: 15px; height: 15px;
  border: 1px solid #D4A72C; color: #EBC65A; font-size: 0.6rem; font-weight: 700;
}
body.pgisr .pgi-ops-log {
  /* Sits under the 05 label, which is at top 5.5%. At 12% the two boxes
     overlapped by ~980px². */
  position: absolute; right: 5%; top: 21%; width: 92px;
  margin: 0; padding: 0.3rem; list-style: none;
  border: 1px solid rgba(111, 176, 193, 0.24);
  background: rgba(5, 12, 18, 0.9);
}
body.pgisr .pgi-ops-log li {
  padding: 0.16rem 0.3rem; color: rgba(214, 233, 236, 0.72);
  font-family: var(--font-mono); font-size: 0.55rem; letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
}
body.pgisr .pgi-ops-log li.is-current { background: #D4A72C; color: #0a1014; font-weight: 600; }
/* Quiet stem reaching up from the archive list toward the 05 label above
   it, so the record reads as continuing from the decision rather than
   sitting nearby by coincidence. Desktop only - see the max-width:1099px
   guard near .pgi-uplink, where these boxes go static and stack. */
body.pgisr .pgi-ops-log::before {
  content: '';
  position: absolute; left: 50%; bottom: 100%;
  width: 1px; height: 22px;
  background: linear-gradient(to bottom, rgba(111, 176, 193, 0), rgba(111, 176, 193, 0.55));
  pointer-events: none;
}

@media (max-width: 640px) {
  body.pgisr .pgi-sensor-inputs { width: 40%; }
  body.pgisr .pgi-callout { padding: 0.3rem 0.45rem 0.3rem 0.3rem; gap: 0.35rem; }
  body.pgisr .pgi-callout b { width: 20px; height: 20px; font-size: 0.55rem; }
  body.pgisr .pgi-ops-log { width: 76px; }
}

/* ---- 03 sits on the house, where the "Security computer" tag is ----
   Was a panel wrapping a photograph of the server rack. The photo raised
   more questions than it answered (see how-it-works.html) and its 132px
   panel was narrow enough to break "PROCESSING" mid-word on phones, so 03
   is now an ordinary callout like 01 and 02. Positioned from RACK in
   js/overview-flow.js, the same constant the connecting link is drawn to. */
body.pgisr .pgi-callout--03 {
  left: var(--rack-x, 59%);
  top: var(--rack-y, 34%);
  transform: translateY(-50%);
}

body.pgisr .pgi-rack-link {
  stroke: rgba(108, 243, 241, 0.75);
  stroke-width: 2.5;
  filter: drop-shadow(0 0 6px rgba(75, 231, 239, 0.6));
}

/* ---- the detected vehicle at step 01 ---- */
body.pgisr .pgi-vehicle-photo {
  position: absolute;
  left: var(--veh-x, 52%);
  top: var(--veh-y, 95%);
  /* Deliberately over-scale. At true scale a car on this estate is about
     1% of the frame - a few pixels - and unreadable. */
  width: 3.4%;
  height: auto;
  transform: translate(-50%, -50%) rotate(var(--veh-rot, 0deg));
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.6));
  pointer-events: none;
}
body.pgisr .pgi-target-bracket {
  fill: none;
  stroke: #D4A72C;
  stroke-width: 2.4;
  filter: drop-shadow(0 0 5px rgba(212, 167, 44, 0.55));
}



/* Short leader joining a numbered label to the feature it names. Moved
   from a neutral hairline into the same cyan family as the sensor
   markers and the hub chip: on the busy map, a color that belonged to
   no other system read as an unstyled leftover rather than part of the
   diagram. Still distinct from the amber vehicle route, just no longer
   the only gray line on a cyan-and-orange plate. */
body.pgisr .pgi-leader {
  stroke: rgba(108, 243, 241, 0.5);
  stroke-width: 1.4;
}
/* Ring at the end the leader points to, so the named feature is explicit.
   Same dark-fill-plus-cyan-ring treatment as .pgi-sensor-ring, so it
   reads as one marker family instead of a separate highlight style. */
body.pgisr .pgi-leader-target {
  fill: rgba(4, 18, 26, 0.7);
  stroke: #6cf3f1;
  stroke-width: 2.2;
  filter: drop-shadow(0 0 5px rgba(75, 231, 239, 0.65));
}

/* ================= Overview flow: narrow screens =================
   These come last and are written with enough specificity to beat the
   desktop rules for the ops overlays. Earlier attempts tied on specificity
   and lost to whichever rule appeared later, which left the ops labels
   stacked on a 341px-wide photograph.
   03 needs nothing of its own here any more: as a plain callout it is reset
   to the stacked layout by the .pgi-flow-site .pgi-callout rule above, which
   already outranks its desktop positioning. */
@media (max-width: 1099px) {
  /* The operations half gets the same treatment: photograph first, then its
     labels underneath, instead of four absolute boxes on a tiny image. */
  body.pgisr .pgi-flow-ops {
    aspect-ratio: auto;
    height: auto;
    display: flex;
    flex-direction: column;
    border-left: 0;
    border-top: 1px solid var(--line);
  }
  body.pgisr .pgi-flow-ops > img {
    position: static;
    width: 100%;
    height: auto;
    aspect-ratio: 1 / 1;
    /* The source is a portrait photograph. A centered crop starts on an
       empty bank of wall screens, so the hand-off from step 03 looks like a
       stray image strip on phones. A plain bottom anchor fixed that but cut
       through the monitors mid-screen, which read as broken hardware rather
       than a deliberate crop - taller box plus a bias toward the bottom
       (not all the way) keeps the operator anchored while bringing the
       monitor tops into frame. */
    object-position: center 75%;
  }
  body.pgisr .pgi-flow-ops .pgi-callout,
  body.pgisr .pgi-flow-ops .pgi-ops-alert,
  body.pgisr .pgi-flow-ops .pgi-ops-log {
    position: static;
    width: auto;
    inset: auto;
    transform: none;
    border-left: 0; border-right: 0; border-bottom: 0;
  }
  body.pgisr .pgi-flow-ops .pgi-ops-log {
    display: flex;
    flex-wrap: wrap;
    gap: 0.15rem 0.5rem;
  }
}

/* Once the labels leave the photograph they are no longer competing with it
   for space, so they can be read at a normal size. Held at map scale they
   measured 8.6-9.0px on a phone, which is too small to read comfortably. */
@media (max-width: 1099px) {
  body.pgisr .pgi-flow-site .pgi-callout strong,
  body.pgisr .pgi-flow-ops .pgi-callout strong { font-size: 0.74rem; }
  body.pgisr .pgi-flow-site .pgi-callout span,
  body.pgisr .pgi-flow-ops .pgi-callout span { font-size: 0.68rem; }
  body.pgisr .pgi-flow-site .pgi-callout b,
  body.pgisr .pgi-flow-ops .pgi-callout b {
    width: 26px; height: 26px; font-size: 0.7rem;
  }
  body.pgisr .pgi-sensor-inputs h4 { font-size: 0.7rem; }
  body.pgisr .pgi-sensor-inputs li { font-size: 0.7rem; }
  body.pgisr .pgi-sensor-inputs a {
    font-size: 0.68rem;
    /* Was a 13px-tall tap target. */
    padding: 0.45rem 0;
  }
  body.pgisr .pgi-ops-log li { font-size: 0.7rem; }
  body.pgisr .pgi-ops-alert { font-size: 0.68rem; }
}

/* ---- sensor names on the rings ---- */
body.pgisr .pgi-sensor-tag {
  position: absolute;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  gap: 0.28rem;
  padding: 0.3rem 0.5rem;
  /* Quiet/system layer, dialed back further than its first pass: the eight
     sensor names still read at a glance, but at this contrast they sit
     behind the numbered 01-05 callouts (the "story" layer, in amber)
     instead of competing with them at equal weight. Hue is unchanged --
     only opacity drops -- so the two-layer color system stays intact. */
  border: 1px solid rgba(104, 220, 229, 0.16);
  background: rgba(5, 17, 25, 0.68);
  color: rgba(217, 242, 243, 0.6);
  font-family: var(--font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  white-space: nowrap;
  pointer-events: none;
}
/* The optical layer reads as secondary to the boundary it verifies. */
body.pgisr .pgi-sensor-tag--inner {
  border-color: rgba(158, 214, 226, 0.16);
  color: rgba(182, 216, 221, 0.55);
}

/* ---- the inner optical ring ---- */
body.pgisr .pgi-inner-ring {
  fill: none;
  stroke: rgba(120, 205, 220, 0.55);
  stroke-width: 2;
  stroke-dasharray: 9 7;
}
body.pgisr .pgi-inner-marker {
  fill: rgba(4, 18, 26, 0.85);
  stroke: rgba(150, 224, 232, 0.9);
  stroke-width: 2;
}
body.pgisr .pgi-inner-core { fill: #b9f0f4; }

/* The eight names are labelled on the rings now, so the panel becomes a
   caption strip below the figure rather than a second list on the map -
   where it also collided with the Radioactivity tag. Still real text, so it
   survives at phone width and for screen readers. */
body.pgisr .pgi-flow > .pgi-sensor-inputs {
  position: static;
  width: auto;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.4rem 1rem;
  padding: 0.75rem clamp(0.9rem, 1.8vw, 1.35rem);
  border: 0;
  border-top: 1px solid var(--line);
  background: transparent;
}
body.pgisr .pgi-flow > .pgi-sensor-inputs h4 { margin: 0; white-space: nowrap; }
body.pgisr .pgi-flow > .pgi-sensor-inputs ul {
  display: flex; flex-wrap: wrap; gap: 0.3rem 0.85rem; flex: 1 1 auto;
}
body.pgisr .pgi-flow > .pgi-sensor-inputs a { margin-top: 0; }

/* Icons come from equipment.html, so they are stroked the same way here -
   fill:none with a currentColor stroke - and inherit the tag's colour. */
body.pgisr .pgi-sensor-icon {
  width: 1.3rem;
  height: 1.3rem;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  /* Cyan, not the orange this used to be: orange is now reserved for the
     "story" layer (numbered badges + vehicle route) so it reads as one
     signal. Sensor icons are part of the quiet/system layer with the
     spokes, rings and hub, so they take that layer's colour instead of
     competing with the badges for the same attention. */
  color: rgba(108, 243, 241, 0.62);
}
body.pgisr .pgi-sensor-tag--inner .pgi-sensor-icon { color: rgba(185, 240, 244, 0.55); }
/* A few of the equipment icons use solid shapes; keep those filled. */
body.pgisr .pgi-sensor-icon [fill="currentColor"] { fill: currentColor; stroke: none; }

/* ---- 03 to 04: the processed event leaving the property ---- */
body.pgisr .pgi-flow-grid { position: relative; }
body.pgisr .pgi-uplink {
  position: absolute;
  z-index: 4;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  height: 0;
  pointer-events: none;
}
body.pgisr .pgi-uplink-line {
  position: absolute;
  inset: 0 0 auto 0;
  height: 2px;
  background: repeating-linear-gradient(90deg,
    rgba(212, 167, 44, 0.85) 0 7px, transparent 7px 14px);
}
body.pgisr .pgi-uplink-lock {
  position: absolute;
  left: 100%;
  transform: translateX(-50%);
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border: 1px solid rgba(108, 243, 241, 0.55);
  border-radius: 50%;
  background: #08151d;
  color: #6cf3f1;
}
body.pgisr .pgi-uplink-lock svg {
  width: 16px; height: 16px;
  fill: none; stroke: currentColor; stroke-width: 1.6;
  stroke-linecap: round; stroke-linejoin: round;
}
body.pgisr .pgi-uplink-label {
  position: absolute;
  bottom: 20px;
  left: 100%;
  transform: translateX(-50%);
  color: rgba(160, 220, 226, 0.8);
  font-family: var(--font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
}

@media (max-width: 1099px) {
  /* No seam to cross once the columns stack. The JS also guards this, but a
     rule here is deterministic and does not depend on a resize firing. */
  body.pgisr .pgi-uplink { display: none; }
  /* .pgi-ops-log goes position:static here, so its ::before stem would
     position against the wrong ancestor instead of the list itself. */
  body.pgisr .pgi-ops-log::before { content: none; }
}

/* ================= Phone type floor =================
   Appended last, with enough specificity to beat every earlier rule. On a
   375px screen the mono labels across this page measured 8.8-9.9px - step
   numbers, eyebrows, kickers. Nothing below is allowed under ~11px. */
@media (max-width: 1099px) {
  body.pgisr .pgi-flow .pgi-callout b {
    width: 28px; height: 28px; font-size: 0.74rem;
  }
  body.pgisr .pgi-flow .pgi-callout strong { font-size: 0.78rem; }
  body.pgisr .pgi-flow .pgi-callout span { font-size: 0.7rem; }
  body.pgisr .pgi-flow .pgi-ops-alert { font-size: 0.72rem; }
  body.pgisr .pgi-flow .pgi-ops-alert-mark { width: 20px; height: 20px; font-size: 0.72rem; }
  body.pgisr .pgi-flow .pgi-ops-log li { font-size: 0.74rem; }
  body.pgisr .pgi-flow-title { font-size: 0.74rem; }
  body.pgisr .ops-label,
  body.pgisr .pgi-eyebrow,
  body.pgisr .section-eyebrow { font-size: 0.72rem; }
}
@media (max-width: 899px) {
  /* The five step numerals in the overview list at the top of the page. */
  body.pgisr .pgi-overview-meta { font-size: 0.74rem; }
}

/* The phone "rack row" block that used to live here sized and flipped the
   rack photograph inside the 03 callout. 03 no longer carries a photograph,
   so 01, 02 and 03 are now identical pills and the shared callout rules
   cover all three at every width. */
