/* ═══════════════════════════════════════════════════════════════════════════
   OnSiight marketing site — the only file that is not the pack.

   It declares NO hex values. Every colour is a pack token from styles.css or
   tokens/marketing.css. Every hover, depth, parallax and motion effect below
   is lifted from templates/interaction-layer-2.html and interaction-layer-3.html
   with its section number named, and every one of them is guarded by
   prefers-reduced-motion.

   Surface: MARKETING. tokens/marketing.css is loaded. Glass, scrim, ambient
   drift and the display scale are permitted here and banned in the product app.
   ═══════════════════════════════════════════════════════════════════════════ */

:root{
  /* the lift ladder, carried verbatim from interaction-layer-2 so the two agree */
  --lift-rest:  0 1px 2px rgba(16,28,42,.05), 0 8px 24px -10px rgba(16,28,42,.14);
  --lift-hover: 0 2px 4px rgba(16,28,42,.07), 0 22px 48px -16px rgba(16,28,42,.26);
  --edge-light: inset 1px 1px 0 rgba(255,255,255,.85), inset -1px -1px 0 rgba(16,28,42,.07);
  --edge-light-strong: inset 1px 1px 0 rgba(255,255,255,1), inset -1px -1px 0 rgba(16,28,42,.12);
  /* IL2 §29 — the five-stop shadow ramp, neutral ink, never tinted */
  --ramp-rest:  0 96px 40px rgba(16,28,42,.01), 0 54px 32px rgba(16,28,42,.03),
                0 24px 24px rgba(16,28,42,.05), 0 6px 13px rgba(16,28,42,.07);
  --rule: 1px solid var(--color-border-subtle);
}

*{box-sizing:border-box;margin:0;padding:0}
html{font-size:16px;scroll-behavior:smooth}
body{
  background:var(--color-bg-page);
  color:var(--color-text-primary);
  font-family:var(--font-body);
  font-size:var(--mkt-body);
  line-height:var(--mkt-body-line-h);
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
img{display:block;max-width:100%}
a{color:inherit;text-decoration:none}

.wrap{width:100%;max-width:var(--mkt-container);margin:0 auto;padding:0 32px}
.wrap-wide{width:100%;max-width:var(--mkt-container-wide);margin:0 auto;padding:0 32px}

/* ── Type ─────────────────────────────────────────────────────────────────
   Archivo 22px and up only. Source Sans 3 body. IBM Plex Mono every numeral. */
.d1{font-family:var(--font-display);font-weight:700;
    /* 30px floor, not 44px: at 390px the viewport term is 28.9px, so a 44px floor
       won the clamp and 'Building Intelligence.' ran off the right edge - measured
       2026-09-14, an 18-row band of ink touching the last column at 390x844.
       Above ~595px wide 7.4vw already exceeds 44px, so desktop is unchanged. */
    font-size:clamp(30px,7.4vw,var(--mkt-display-2xl));
    line-height:var(--mkt-display-line-h);letter-spacing:var(--mkt-display-tracking)}
.d2{font-family:var(--font-display);font-weight:700;
    font-size:clamp(34px,4.6vw,var(--mkt-display-xl));
    line-height:1.02;letter-spacing:var(--mkt-display-tracking)}
.d3{font-family:var(--font-display);font-weight:700;
    font-size:clamp(28px,3vw,var(--mkt-display-md));
    line-height:1.06;letter-spacing:-.025em}
.d4{font-family:var(--font-display);font-weight:600;font-size:22px;line-height:1.2;
    letter-spacing:-.015em}
/* approved/02 — the SIZE GAP between headline and describer is the design.
   Do not balance them. 12.5px, ~330px measure, tucked directly under. */
.describer{font-size:13px;line-height:1.5;color:var(--color-text-secondary);
  max-width:34ch;margin-top:22px}
.lede{font-size:var(--mkt-body-lead);line-height:1.5;color:var(--color-text-secondary);
  max-width:52ch}
.overline{font-family:var(--font-mono);font-size:11px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--color-text-accent)}
.overline.quiet{color:var(--color-text-secondary)}
.num{font-family:var(--font-mono);font-weight:700;letter-spacing:var(--mkt-numeral-tracking);
  font-variant-numeric:tabular-nums}
.on-dark{color:var(--color-text-on-accent)}
.on-dark .overline{color:var(--color-accent-fill)}
.on-dark .lede,.on-dark .describer{color:rgba(255,255,255,.76)}

/* ── Nav — one nav, shared by the scroll narrative and every deep page ─────
   Navy is chrome. This is a floating pill, never a full-bleed page ground. */
.nav{position:fixed;top:16px;left:0;right:0;z-index:60;pointer-events:none}
.nav{transition:transform var(--duration-base) var(--ease-standard),opacity var(--duration-base) var(--ease-standard)}
.nav.away{transform:translateY(-120%);opacity:0;pointer-events:none}
@media (prefers-reduced-motion: reduce){.nav{transition:none}}
html{scroll-padding-top:96px}
.nav-in{pointer-events:auto;display:flex;align-items:center;gap:28px;
  max-width:var(--mkt-container);margin:0 auto;padding:8px 8px 8px 22px;
  border-radius:999px;
  background:var(--mkt-glass-dark-bg);border:var(--mkt-glass-dark-border);
  backdrop-filter:var(--mkt-glass-blur-sm);-webkit-backdrop-filter:var(--mkt-glass-blur-sm);
  box-shadow:var(--mkt-shadow-card)}
.brand{font-family:var(--font-display);font-weight:700;font-size:19px;letter-spacing:-.02em;
  color:var(--color-text-on-accent);white-space:nowrap}
.nav-links{display:flex;gap:4px;margin-left:auto;align-items:center}
/* IL3 §33 — dock behaviour reduced to its honest part: a background that
   arrives on hover, a scale(.97) press. No magnification on a text nav. */
.nav-links a{position:relative;display:block;padding:8px 14px;border-radius:999px;
  font-size:13.5px;font-weight:500;color:rgba(255,255,255,.78);white-space:nowrap;
  transition:background var(--duration-base) var(--ease-standard),
             color var(--duration-base) var(--ease-standard)}
.nav-links a:hover{background:rgba(255,255,255,.14);color:var(--color-text-on-accent)}
.nav-links a:active{transform:scale(.97)}
.nav-links a[aria-current="page"]{background:rgba(255,255,255,.92);color:var(--color-text-accent)}
.nav-cta{margin-left:6px}
/* IL2 §2 — inset edge-light. A 1px bright rim, a 1px dark rim. No glow.
   IL2 §2 also gives the letter-spacing widening on press. */
.btn{display:inline-flex;align-items:center;gap:9px;height:44px;padding:0 22px;border:0;
  border-radius:999px;cursor:pointer;font-family:var(--font-body);font-size:14px;
  font-weight:600;letter-spacing:.01em;
  background:var(--color-accent);color:var(--color-text-on-accent);
  box-shadow:inset 1px 1px 0 rgba(255,255,255,.28), var(--lift-rest);
  transition:background var(--duration-base) var(--ease-standard),
             box-shadow var(--duration-base) var(--ease-standard),
             transform var(--duration-fast) var(--ease-standard),
             letter-spacing var(--duration-base) var(--ease-standard)}
.btn:hover{background:var(--color-accent-hover);
  box-shadow:inset 1px 1px 0 rgba(255,255,255,.38), var(--lift-hover)}
.btn:active{transform:translateY(1px);letter-spacing:.05em}
.btn.ghost{background:transparent;color:var(--color-text-on-accent);
  box-shadow:inset 0 0 0 1.5px rgba(255,255,255,.42)}
.btn.ghost:hover{background:rgba(255,255,255,.14);box-shadow:inset 0 0 0 1.5px rgba(255,255,255,.7)}
.btn.dark{background:var(--color-chrome)}
.btn.dark:hover{background:var(--color-slate-700)}

/* ── The full-bleed photographic panel ────────────────────────────────────
   One idea per viewport. Real photography only — never a map tile, never a
   render, never a drawn grid (ruled 2026-09-05). Graded to the pack's
   --mkt-photo-filter so sky stays the only saturated thing on the page. */
.panel{position:relative;min-height:100svh;display:flex;align-items:flex-end;
  overflow:clip;isolation:isolate}
.panel.short{min-height:78svh}
.panel .shot{position:absolute;inset:-8% 0 -8% 0;z-index:0}
.panel .shot img{width:100%;height:100%;object-fit:cover;
  filter:var(--mkt-photo-filter);will-change:transform}
.panel .scrim{position:absolute;inset:0;z-index:1;background:var(--mkt-scrim-bottom)}
.panel .scrim.left{background:var(--mkt-scrim-left)}
.panel .scrim.flat{background:var(--mkt-scrim-flat)}
.panel .content{position:relative;z-index:2;width:100%;padding:0 0 84px}
.panel .content .wrap{width:100%}
/* a photograph credit — real place, named. Never a stock caption. */
.shot-credit{position:absolute;right:18px;bottom:14px;z-index:2;
  font-family:var(--font-mono);font-size:10px;letter-spacing:.09em;text-transform:uppercase;
  color:rgba(255,255,255,.62)}

/* ── Plain sections on stone ─────────────────────────────────────────────── */
.sec{padding:var(--mkt-section-y) 0}
.sec.lg{padding:var(--mkt-section-y-lg) 0}
.sec.white{background:var(--color-surface-0)}
.sec.stone{background:var(--color-bg-page)}
/* the one dark ground the system permits on marketing: blue-950, with the
   blueprint grid as page TEXTURE (permitted; banned only when it stands in
   for a map) and the ambient glow that marketing.css exists to carry. */
.sec.dark{position:relative;background:var(--mkt-dark-bg);color:var(--color-text-on-accent);
  overflow:clip}
.sec.dark::before{content:"";position:absolute;inset:0;background:var(--mkt-grid);
  pointer-events:none}
.sec.dark::after{content:"";position:absolute;inset:0;background:var(--mkt-glow-ambient);
  pointer-events:none}
.sec.dark > *{position:relative;z-index:1}
.sec-head{display:flex;flex-direction:column;gap:18px;max-width:none}
.sec-head h2{max-width:17ch}
.sec-head > .lede{max-width:52ch}
.sec-head .d2,.sec-head .d3{margin-top:2px}

/* ── KPI band — IL3 §11 ───────────────────────────────────────────────────
   A band leads, a table never does. On a WHITE surface over warm stone:
   navy is never a page ground, not even as a KPI band (ruled 2026-08-31). */
.kpis{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--mkt-gutter)}
.kpi{background:var(--color-surface-0);border-radius:var(--mkt-radius-card);
  padding:24px 24px 22px;box-shadow:var(--edge-light), var(--lift-rest);
  transition:transform var(--duration-base) var(--ease-standard),
             box-shadow var(--duration-base) var(--ease-standard)}
.kpi:hover{transform:translateY(-3px);box-shadow:var(--edge-light-strong), var(--lift-hover)}
.kpi .k{font-family:var(--font-mono);font-size:10.5px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--color-text-secondary);white-space:nowrap}
.kpi .v{font-family:var(--font-mono);font-weight:700;font-size:var(--mkt-numeral-lg);
  line-height:1;margin-top:12px;letter-spacing:var(--mkt-numeral-tracking);
  font-variant-numeric:tabular-nums}
.kpi .v small{font-size:.44em;font-weight:500;margin-left:4px;
  color:var(--color-text-secondary);letter-spacing:0}
.kpi .s{font-size:13px;color:var(--color-text-secondary);margin-top:12px;
  min-height:2.9em;line-height:1.45}

/* ── The gradient — IL2 §10 ───────────────────────────────────────────────
   navy -> sky -> fill, the ramp Matt named. Navy is legitimate INSIDE a
   panel; it is never the page ground. */
.grad{position:relative;overflow:hidden;border-radius:var(--mkt-radius-hero);
  color:var(--color-text-on-accent);
  background:linear-gradient(100deg,var(--color-chrome) 6%,
             var(--color-accent) 62%, var(--color-accent-fill) 98%);
  box-shadow:var(--mkt-shadow-float);padding:44px 44px 40px}
.grad::after{content:"";position:absolute;top:-96px;right:-70px;width:320px;height:320px;
  border-radius:50%;background:rgba(255,255,255,.10)}
.grad::before{content:"";position:absolute;top:-24px;right:58px;width:168px;height:168px;
  border-radius:50%;background:rgba(255,255,255,.08)}
.grad > *{position:relative}
/* the before/after hero, approved 13-product-inspector: BOTH numbers visible
   at once with a delta pill beneath. Never a card flip (rejected #14). */
.ba{display:flex;align-items:center;justify-content:center;gap:clamp(14px,2.6vw,38px);
  flex-wrap:nowrap;max-width:100%}
.ba .side{text-align:center;min-width:0}
.ba .side .k{font-family:var(--font-mono);font-size:11px;letter-spacing:.12em;
  text-transform:uppercase;opacity:.8;white-space:nowrap}
.ba .side .v{font-family:var(--font-mono);font-weight:700;
  font-size:clamp(26px,3.4vw,52px);line-height:1;margin-top:10px;
  letter-spacing:var(--mkt-numeral-tracking);white-space:nowrap}
.ba .side.was .v{opacity:.62}
.ba .arrow{font-family:var(--font-mono);font-size:26px;opacity:.7;flex:0 0 auto}
.delta{display:inline-flex;align-items:center;gap:9px;margin-top:22px;padding:8px 18px;
  border-radius:999px;background:rgba(255,255,255,.16);
  border:1px solid rgba(255,255,255,.28);
  font-family:var(--font-mono);font-size:13px;white-space:nowrap}

/* ── Photo over a colour block — approved/05 ──────────────────────────────
   Photograph on top, a SOLID block beneath carrying the meta. A white card
   under a photo does not do this. */
.pcards{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--mkt-gutter);
  align-items:end}
.pcard{border-radius:var(--mkt-radius-tile);overflow:hidden;
  box-shadow:var(--mkt-shadow-card);
  transition:transform var(--duration-moderate) var(--ease-standard),
             box-shadow var(--duration-moderate) var(--ease-standard)}
/* the middle card is proud by 26px — approved/05, "cards sit at different heights" */
.pcard.proud{margin-bottom:var(--mkt-proud,26px)}
.pcard:hover{transform:translateY(-6px);box-shadow:var(--mkt-shadow-card-hover)}
.pcard .shot{aspect-ratio:var(--mkt-photo-ratio-card);overflow:hidden}
.pcard .shot img{width:100%;height:100%;object-fit:cover;filter:var(--mkt-photo-filter);
  transition:transform var(--duration-slow) var(--ease-standard)}
.pcard:hover .shot img{transform:scale(1.035)}
.pcard .block{padding:22px 22px 20px;color:var(--color-text-on-accent);
  background:var(--color-accent)}
.pcard .block.navy{background:var(--color-chrome)}
.pcard .block.sage{background:var(--color-status-healthy)}
.pcard .block h3{font-family:var(--font-display);font-size:19px;font-weight:600;
  line-height:1.22;letter-spacing:-.015em;min-height:2.44em}
.pcard .block .hr{height:1px;background:rgba(255,255,255,.30);margin:16px 0 14px}
.pcard .block .pfoot{display:flex;align-items:center;gap:12px}
.pcard .chip{flex:0 0 auto;background:var(--color-surface-0);border-radius:9px;
  padding:7px 10px;text-align:center;min-width:64px}
.pcard .chip .cv{font-family:var(--font-mono);font-weight:700;font-size:17px;
  color:var(--color-text-primary);line-height:1}
.pcard .chip .ck{font-family:var(--font-mono);font-size:8.5px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--color-text-secondary);margin-top:3px;white-space:nowrap}
.pcard .place{font-size:12.5px;line-height:1.35;opacity:.86;min-height:2.7em}
.pcard .right{margin-left:auto;font-family:var(--font-mono);font-size:12.5px;
  text-align:right;white-space:nowrap}

/* ── Status spine that floods — IL2 §21 ──────────────────────────────────
   A spine at rest, the ground on hover. scaleX from the left, never width.
   The card drops its shadow as the colour arrives, so it settles rather
   than floating. Used for the three phase links into the deep pages. */
.spine{position:relative;display:block;overflow:hidden;cursor:pointer;
  border-radius:var(--mkt-radius-card);background:var(--color-surface-0);
  padding:30px 32px 28px;box-shadow:var(--lift-rest);
  transition:box-shadow var(--duration-moderate) var(--ease-standard),
             color var(--duration-moderate) var(--ease-standard)}
.spine::before{content:"";position:absolute;left:0;top:0;bottom:0;width:100%;
  background:var(--color-accent);transform-origin:left;transform:scaleX(.014);z-index:0;
  transition:transform var(--duration-slow) var(--ease-standard)}
.spine > *{position:relative;z-index:1}
.spine:hover,.spine:focus-visible{box-shadow:none;color:var(--color-text-on-accent);outline:0}
.spine:hover::before,.spine:focus-visible::before{transform:scaleX(1)}
.spine .sk{font-family:var(--font-mono);font-size:10.5px;letter-spacing:.12em;
  text-transform:uppercase;opacity:.7}
.spine h3{font-family:var(--font-display);font-size:26px;font-weight:700;margin-top:12px;
  letter-spacing:-.02em}
.spine p{font-size:14.5px;line-height:1.5;margin-top:12px;opacity:.78;min-height:4.5em}
.spine .go{display:inline-flex;align-items:center;gap:8px;margin-top:20px;
  font-family:var(--font-mono);font-size:11px;letter-spacing:.1em;text-transform:uppercase}
.spine .go span{transition:transform var(--duration-moderate) var(--ease-standard)}
.spine:hover .go span{transform:translateX(5px)}

/* ── Depth numeral — IL2 §23 ─────────────────────────────────────────────
   The same glyph at three translateZ depths, descending opacity and blur, so
   one number has thickness. Hero use only, never on a dense panel. */
.holo-stage{perspective:900px;display:grid;place-items:center;min-height:190px}
.holo{position:relative;transform-style:preserve-3d;display:grid;place-items:center;
  transform:rotateX(11deg) rotateY(-11deg)}
.holo b{font-family:var(--font-mono);font-weight:700;
  font-size:clamp(92px,13vw,188px);line-height:1;letter-spacing:-.045em;
  transform-style:preserve-3d}
.holo b:not(.l1){position:absolute;inset:0;display:grid;place-items:center}
.holo .l3{opacity:.16;filter:blur(1px);transform:translateZ(-48px);color:var(--color-accent-fill)}
.holo .l2{opacity:.40;filter:blur(.4px);transform:translateZ(-24px);color:var(--color-accent-fill)}
.holo .l1{opacity:1;transform:translateZ(0);color:var(--color-text-on-accent)}

/* ── Glass over photography — approved/04, the flagship ──────────────────
   The property is behind the interface, made literal. Glass is marketing and
   map chrome only; it never ships in the product app. */
.glassgrid{display:grid;grid-template-columns:repeat(4,1fr);gap:14px}
.glasstile{padding:20px 20px 18px;border-radius:14px;
  background:var(--mkt-glass-bg-dense);border:var(--mkt-glass-border);
  backdrop-filter:var(--mkt-glass-blur);-webkit-backdrop-filter:var(--mkt-glass-blur);
  box-shadow:inset 1px 1px 0 rgba(255,255,255,.30), var(--mkt-glass-shadow);
  color:var(--color-text-on-accent);
  transition:border-color var(--duration-moderate) var(--ease-standard),
             transform var(--duration-moderate) var(--ease-standard)}
.glasstile:hover{border-color:rgba(255,255,255,.58);transform:translateY(-4px)}
.glasstile .k{font-family:var(--font-mono);font-size:10px;letter-spacing:.11em;
  text-transform:uppercase;opacity:.82;white-space:nowrap}
.glasstile .v{font-family:var(--font-mono);font-weight:700;font-size:34px;line-height:1;
  margin-top:11px;letter-spacing:-.035em;font-variant-numeric:tabular-nums}
.glasstile .s{font-size:12px;opacity:.76;margin-top:10px;line-height:1.4;min-height:2.8em}

/* ── The single artifact, shown large — the Apple move ────────────────────
   One real artifact per section, product shown not described. The artifact
   sits on a nested panel so it reads as a thing on a stage. */
.artifact{position:relative;border-radius:var(--mkt-radius-canvas);overflow:hidden;
  background:var(--color-surface-0);box-shadow:var(--ramp-rest);border:var(--rule)}
.artifact.dark{background:var(--mkt-dark-raised);border-color:var(--mkt-dark-border);
  color:var(--color-text-on-accent)}
.artifact .bar{display:flex;align-items:center;gap:10px;padding:14px 20px;
  border-bottom:var(--rule)}
.artifact.dark .bar{border-bottom-color:var(--mkt-dark-border)}
.artifact .bar .t{font-family:var(--font-mono);font-size:11px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--color-text-secondary)}
.artifact.dark .bar .t{color:var(--color-chrome-ink)}
.artifact .bar .r{margin-left:auto;font-family:var(--font-mono);font-size:11px;
  color:var(--color-text-secondary)}
.artifact.dark .bar .r{color:var(--color-chrome-ink)}
.artifact .body{padding:26px 28px 28px}
.artifact .shotwrap{aspect-ratio:16/9;overflow:hidden}
.artifact .shotwrap img{width:100%;height:100%;object-fit:cover;filter:var(--mkt-photo-filter)}

/* ledger rows — label left, mono value right, hairline between.
   Copied from approved/13-product-inspector's language. */
.ledger{display:flex;flex-direction:column}
.ledger .row{display:flex;align-items:baseline;gap:16px;padding:13px 0;
  border-bottom:var(--rule)}
.artifact.dark .ledger .row{border-bottom-color:var(--mkt-dark-border)}
.ledger .row:last-child{border-bottom:0}
.ledger .row .l{font-size:14px;color:var(--color-text-secondary)}
.artifact.dark .ledger .row .l{color:var(--color-chrome-ink)}
.ledger .row .v{margin-left:auto;font-family:var(--font-mono);font-weight:600;font-size:15px;
  font-variant-numeric:tabular-nums;white-space:nowrap}
.ledger .row .v.absent{font-weight:400;color:var(--color-status-inactive)}

/* status — always colour PLUS icon PLUS word. Never colour alone. */
.stat{display:inline-flex;align-items:center;gap:7px;padding:5px 11px;border-radius:999px;
  font-family:var(--font-mono);font-size:11px;letter-spacing:.05em;white-space:nowrap}
.stat svg{width:13px;height:13px;flex:0 0 auto}
.stat.ok{background:var(--color-status-healthy-bg);color:var(--color-status-healthy)}
.stat.att{background:var(--color-status-warning-bg);color:var(--color-status-warning)}
.stat.crit{background:var(--color-status-critical-bg);color:var(--color-status-critical)}
.stat.none{background:var(--color-status-inactive-bg);color:var(--color-status-inactive)}

/* ── Line-draw chart — IL3 §19 ───────────────────────────────────────────
   Draws ONCE on reveal. The reference looped it forever, which erases the
   chart every 8s. Gridlines fade at top and bottom instead of boxing the plot. */
.chart .plot{position:relative;height:170px;margin-top:20px}
.chart .grid{position:absolute;inset:0;display:flex;justify-content:space-between}
.chart .grid span{width:1px;background:linear-gradient(to top,
  transparent 0%, var(--color-slate-100) 50%, transparent 100%)}
.chart svg{position:absolute;inset:0;width:100%;height:100%;overflow:visible}
.chart path.s{fill:none;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;
  stroke-dasharray:1400;stroke-dashoffset:1400}
.chart path.s1{stroke:var(--color-accent)}
.chart path.s2{stroke:var(--color-slate-400)}
.chart .axis{display:flex;justify-content:space-between;margin-top:12px;
  font-family:var(--font-mono);font-size:10.5px;color:var(--color-text-secondary)}
.chart .legend{display:flex;gap:20px;margin-top:14px;font-family:var(--font-mono);
  font-size:11px;color:var(--color-text-secondary)}
.chart .legend i{display:inline-block;width:14px;height:2.5px;margin-right:7px;
  vertical-align:middle;border-radius:2px}

/* ── Stacked sheets — IL2 §7 ─────────────────────────────────────────────
   Layers fan open on rotateX at increasing angles from a shared origin-bottom.
   Here it carries the document stack a survey returns. */
.stack{position:relative;width:100%;max-width:300px;aspect-ratio:3/2;cursor:default;
  perspective:1500px;transform-style:preserve-3d}
.stack .sheet{position:absolute;inset:6px 6px 0;border-radius:12px;
  transform-origin:bottom center;box-shadow:0 1px 2px rgba(16,28,42,.10);
  transition:transform var(--duration-slow) var(--ease-standard)}
.stack .s4{background:var(--color-slate-100)}
.stack .s3{background:var(--color-surface-2)}
.stack .s2{background:var(--color-surface-0)}
.stack:hover .s4{transform:rotateX(-20deg)}
.stack:hover .s3{transform:rotateX(-30deg)}
.stack:hover .s2{transform:rotateX(-38deg)}
.stack .front{position:absolute;left:0;right:0;bottom:0;height:100%;border-radius:13px;
  border-top-left-radius:0;background:var(--color-accent);transform-origin:bottom center;
  box-shadow:var(--lift-rest);
  transition:transform var(--duration-slow) var(--ease-standard),
             box-shadow var(--duration-slow) var(--ease-standard)}
.stack .front::after{content:"";position:absolute;bottom:99%;left:0;width:96px;height:16px;
  background:var(--color-accent);border-radius:12px 12px 0 0}
.stack .front::before{content:"";position:absolute;top:-15px;left:96px;width:16px;height:16px;
  background:var(--color-accent);clip-path:polygon(0 35%,0 100%,55% 100%)}
.stack:hover .front{transform:rotateX(-46deg) translateY(1px);box-shadow:var(--lift-hover)}
.stack .front .label{position:absolute;left:18px;bottom:16px;color:var(--color-text-on-accent);
  font-family:var(--font-mono);font-size:11px;letter-spacing:.08em;text-transform:uppercase;
  white-space:nowrap}

/* ── Media card — IL2 §27 ────────────────────────────────────────────────
   Photograph on top, chips pinned ON the image, one chip hidden at rest that
   slides in on hover. Used for the property grid. */
.media{display:block;border-radius:var(--mkt-radius-card);overflow:hidden;
  background:var(--color-surface-0);box-shadow:var(--lift-rest);
  transition:transform var(--duration-moderate) var(--ease-standard),
             box-shadow var(--duration-moderate) var(--ease-standard)}
.media:hover{transform:translateY(-5px);box-shadow:var(--lift-hover)}
.media .shot{position:relative;aspect-ratio:var(--mkt-photo-ratio-card);overflow:hidden;
  background:var(--color-surface-2)}
.media .shot img{width:100%;height:100%;object-fit:cover;filter:var(--mkt-photo-filter);
  transition:transform var(--duration-slow) var(--ease-standard)}
.media:hover .shot img{transform:scale(1.04)}
/* absence renders as absence: a property with no photograph on record gets a
   typographic slot that SAYS so. Never a stock image, never an aerial. */
.media .noshot{position:absolute;inset:0;display:grid;place-content:center;text-align:center;
  gap:8px;background:var(--color-surface-2);padding:20px}
.media .noshot .np{font-family:var(--font-mono);font-size:10.5px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--color-status-inactive)}
.media .chips{position:absolute;inset:auto 0 0 0;display:flex;justify-content:flex-end;gap:7px;
  padding:10px;pointer-events:none}
.media .chip{background:rgba(11,19,29,.66);color:var(--color-text-on-accent);padding:4px 9px;border-radius:7px;
  font-family:var(--font-mono);font-size:10px;letter-spacing:.04em;white-space:nowrap}
.media .chip.late{opacity:0;transform:translateY(-8px);
  transition:opacity var(--duration-slow) var(--ease-standard),
             transform var(--duration-slow) var(--ease-standard)}
.media:hover .chip.late{opacity:1;transform:translateY(0)}
.media .body{padding:18px 20px 20px}
.media .mt{font-family:var(--font-display);font-size:17px;font-weight:600;line-height:1.25;
  letter-spacing:-.015em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.media .mm{font-size:12.5px;color:var(--color-text-secondary);margin-top:6px;white-space:nowrap}
.media .mrow{display:flex;gap:26px;margin-top:16px;padding-top:14px;border-top:var(--rule)}
.media .mrow div{min-width:0}
.media .mrow .mv{font-family:var(--font-mono);font-weight:700;font-size:16px;
  font-variant-numeric:tabular-nums;white-space:nowrap}
.media .mrow .mk{font-family:var(--font-mono);font-size:9.5px;letter-spacing:.09em;
  text-transform:uppercase;color:var(--color-text-secondary);margin-top:4px;white-space:nowrap}

/* ── Glass over drifting orbs — IL2 §39 ──────────────────────────────────
   Atmosphere, not motion: a 28s and a 34s loop, slow enough that the
   refraction changes and the glass never looks like flat grey. Guarded. */
.drift{position:relative;overflow:hidden;border-radius:var(--mkt-radius-hero);
  background:linear-gradient(140deg,var(--color-chrome),var(--color-accent));
  display:grid;place-items:center;padding:54px 40px}
.drift .o1,.drift .o2{position:absolute;border-radius:50%;background:rgba(255,255,255,.18)}
.drift .o1{width:300px;height:300px;top:8%;right:4%}
.drift .o2{width:170px;height:170px;bottom:6%;left:6%;background:rgba(255,255,255,.12)}
.drift .panel-g{position:relative;max-width:660px;text-align:center;padding:34px 34px 32px;
  border-radius:18px;color:var(--color-text-on-accent);background:rgba(255,255,255,.10);
  border:1px solid rgba(255,255,255,.26);
  box-shadow:inset 1px 1px 0 rgba(255,255,255,.35);
  backdrop-filter:var(--mkt-glass-blur);-webkit-backdrop-filter:var(--mkt-glass-blur)}

/* ── Reveal on scroll — approved/08, the interaction layer ────────────────
   Staggered, and it serves reading order rather than decorating. Elements are
   VISIBLE by default so a failed observer or a no-JS load never hides content. */
[data-reveal]{opacity:1;transform:none}
.js [data-reveal]{opacity:0;transform:translateY(22px);
  transition:opacity 620ms var(--ease-standard), transform 620ms var(--ease-standard)}
.js [data-reveal].in{opacity:1;transform:none}

/* ── Parallax — one transform, driven by scroll, on the photograph only ──── */
.js .panel .shot img{transform:translate3d(0,var(--par,0px),0)}

/* ── Foot ─────────────────────────────────────────────────────────────────── */
.foot{background:var(--color-chrome);color:var(--color-chrome-ink);padding:64px 0 40px}
.foot .cols{display:grid;grid-template-columns:1.6fr 1fr 1fr 1fr;gap:32px}
.foot .brand{font-size:24px;margin-bottom:14px}
.foot h4{font-family:var(--font-mono);font-size:10.5px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--color-accent-fill);margin-bottom:14px}
.foot a{display:block;padding:5px 0;font-size:14px;color:rgba(255,255,255,.72);
  transition:color var(--duration-base) var(--ease-standard)}
.foot a:hover{color:var(--color-text-on-accent)}
.foot .rule{height:1px;background:rgba(255,255,255,.14);margin:44px 0 22px}
.foot .fine{display:flex;gap:26px;flex-wrap:wrap;font-family:var(--font-mono);font-size:11px;
  color:rgba(255,255,255,.5)}

/* ── Grids ────────────────────────────────────────────────────────────────── */
.g3{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--mkt-gutter)}
.g2{display:grid;grid-template-columns:repeat(2,1fr);gap:var(--mkt-gutter)}
.g2.wide{grid-template-columns:1fr 1.1fr;gap:64px;align-items:center}
.split{display:grid;grid-template-columns:1fr 1fr;gap:72px;align-items:center}

/* ── Reduced motion — the global brake, IL2's own closing rule ────────────
   Every animation and every transition above stops. Glass and scrims stay:
   they are not motion. */
@media (prefers-reduced-motion: reduce){
  html{scroll-behavior:auto}
  *{animation:none!important;transition-duration:1ms!important}
  .js [data-reveal]{opacity:1;transform:none}
  .js .panel .shot img{transform:none}
  .pcard:hover,.media:hover,.kpi:hover,.glasstile:hover{transform:none}
  .stack:hover .s2,.stack:hover .s3,.stack:hover .s4,.stack:hover .front{transform:none}
  .holo{transform:none}
  .chart path.s{stroke-dashoffset:0}
}
@media (prefers-reduced-motion: no-preference){
  .drift .o1{animation:drift-a 28s ease-in-out infinite}
  .drift .o2{animation:drift-b 34s ease-in-out infinite}
  .chart.in path.s{animation:draw-in 1.6s var(--ease-standard) forwards}
  .chart.in path.s2{animation-delay:.45s}
}
@keyframes drift-a{0%,100%{transform:translate(0,0) scale(1)}
                   50%{transform:translate(-70px,26px) scale(.84)}}
@keyframes drift-b{0%,100%{transform:translate(0,0)}
                   50%{transform:translate(42px,-28px)}}
@keyframes draw-in{to{stroke-dashoffset:0}}

/* ── Responsive ───────────────────────────────────────────────────────────
   390px is a tested width, not an afterthought. Everything collapses to one
   column; nothing is allowed to overflow. */
@media (max-width:1080px){
  .kpis{grid-template-columns:repeat(2,1fr)}
  .glassgrid{grid-template-columns:repeat(2,1fr)}
  .g3{grid-template-columns:1fr}
  .pcards{grid-template-columns:1fr}
  .pcard.proud{margin-bottom:0}
  .split,.g2.wide,.g2{grid-template-columns:1fr;gap:40px}
  .foot .cols{grid-template-columns:1fr 1fr}
}
@media (max-width:720px){
  .wrap,.wrap-wide{padding:0 20px}
  .nav{top:10px}
  .nav-in{margin:0 12px;padding:8px 8px 8px 16px;gap:10px}
  .nav-links{display:none}
  .sec{padding:64px 0}
  .sec.lg{padding:76px 0}
  .kpis,.glassgrid{grid-template-columns:1fr}
  .kpi .s,.glasstile .s,.spine p,.pcard .place,.pcard .block h3{min-height:0}
  .grad{padding:30px 24px 28px}
  .ba{gap:14px}
  .ba .arrow{font-size:20px}
  .panel .content{padding-bottom:56px}
  .foot .cols{grid-template-columns:1fr}
  .drift{padding:36px 20px}
  .drift .panel-g{padding:24px 20px}
  .media .mrow{gap:18px}
}

/* ── Quote card — the dark buyer-signal band. Peer cards are one height, so
   the headline and meta lines carry a floor (symmetry ruling 2026-08-27). ── */
.quote{padding:28px 28px 26px;border-radius:var(--mkt-radius-card);
  background:var(--mkt-dark-raised);border:1px solid var(--mkt-dark-border)}
.quote .d4{margin-top:16px;line-height:1.35;min-height:3.6em}
.quote .qm{font-size:13.5px;color:rgba(255,255,255,.7);margin-top:16px;line-height:1.5;
  min-height:4.5em}
@media (max-width:1080px){ .quote .d4,.quote .qm{min-height:0} }

/* An overline sitting ON a photograph is white, not sky fill — sky at 4EA8E8
   fails against a bright sign, which is what the Lorton frame proved. */
.panel .overline{color:var(--color-text-on-accent)!important;opacity:.9}

/* ── Deep-page furniture ──────────────────────────────────────────────────
   The three phase pages and the platform page are Apple-shaped: one real
   artifact per section, shown large, with the words beside it rather than
   in place of it. */
.pagehead{position:relative;padding:190px 0 var(--mkt-section-y)}
.pagehead .overline{margin-bottom:22px}
.pagehead h1{max-width:15ch}
.pagehead .lede{margin-top:26px}
/* the phase rail: where you are in the three phases, on every deep page */
.rail{display:flex;gap:0;margin-top:46px;border-top:var(--rule);flex-wrap:wrap}
.rail a{flex:1 1 0;min-width:150px;padding:16px 0 0;border-top:3px solid transparent;
  margin-top:-1px;
  transition:border-color var(--duration-base) var(--ease-standard),
             color var(--duration-base) var(--ease-standard)}
.rail a .n{font-family:var(--font-mono);font-size:10.5px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--color-text-secondary)}
.rail a .t{font-family:var(--font-display);font-size:19px;font-weight:600;margin-top:7px;
  letter-spacing:-.015em}
.rail a:hover{border-top-color:var(--color-accent-fill)}
.rail a[aria-current]{border-top-color:var(--color-accent)}
.rail a[aria-current] .n{color:var(--color-text-accent)}

/* an artifact section: the thing on the left or right, the sentence opposite */
.stage{display:grid;grid-template-columns:1fr 1.25fr;gap:72px;align-items:center}
.stage.flip > :first-child{order:2}
.stage .say h2{max-width:15ch}
.stage .say .lede{margin-top:22px}
@media (max-width:1080px){
  .stage{grid-template-columns:1fr;gap:38px}
  .stage.flip > :first-child{order:0}
  .pagehead{padding:130px 0 64px}
}

/* a spec grid inside an artifact — peer cells at one width and one height */
.specs{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;
  background:var(--color-border-subtle)}
.artifact.dark .specs{background:var(--mkt-dark-border)}
.specs > div{background:var(--color-surface-0);padding:18px 20px 16px}
.artifact.dark .specs > div{background:var(--mkt-dark-raised)}
.specs .k{font-family:var(--font-mono);font-size:9.5px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--color-text-secondary);white-space:nowrap}
.artifact.dark .specs .k{color:var(--color-chrome-ink)}
.specs .v{font-family:var(--font-mono);font-weight:700;font-size:19px;margin-top:8px;
  font-variant-numeric:tabular-nums;white-space:nowrap}
@media (max-width:720px){ .specs{grid-template-columns:1fr 1fr} }

/* the photo strip — real field photography, at one height */
.strip{display:grid;grid-template-columns:repeat(4,1fr);gap:12px}
.strip figure{border-radius:var(--mkt-radius-media);overflow:hidden;
  box-shadow:var(--lift-rest);background:var(--color-surface-2)}
.strip img{width:100%;aspect-ratio:4/3;object-fit:cover;filter:var(--mkt-photo-filter);
  transition:transform var(--duration-slow) var(--ease-standard)}
.strip figure:hover img{transform:scale(1.05)}
.strip figcaption{padding:11px 13px;font-family:var(--font-mono);font-size:10px;
  letter-spacing:.06em;text-transform:uppercase;color:var(--color-text-secondary);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
@media (max-width:1080px){ .strip{grid-template-columns:1fr 1fr} }

/* properties table-below-a-band; a table never leads (rejected #02) */
.ptable{width:100%;border-collapse:collapse;background:var(--color-surface-0);
  border-radius:var(--mkt-radius-card);overflow:hidden;box-shadow:var(--lift-rest)}
.ptable th,.ptable td{text-align:left;padding:15px 20px;border-bottom:var(--rule);
  white-space:nowrap}
.ptable th{font-family:var(--font-mono);font-size:10px;letter-spacing:.11em;
  text-transform:uppercase;color:var(--color-text-secondary);font-weight:400}
.ptable td{font-size:14.5px}
.ptable td.n{font-family:var(--font-mono);font-variant-numeric:tabular-nums;
  text-align:right;font-weight:600}
.ptable th.n{text-align:right}
.ptable tr:last-child td{border-bottom:0}
.ptable tbody tr{transition:background var(--duration-base) var(--ease-standard)}
.ptable tbody tr:hover{background:var(--color-accent-subtle)}
.tscroll{overflow-x:auto;-webkit-overflow-scrolling:touch;border-radius:var(--mkt-radius-card)}

/* ── Idle float — IL2 §32. The tilt is held CONSTANT and only the lift
   animates; that is why it hovers rather than wobbles. Guarded below. ────── */
.floatc{width:100%;max-width:230px;padding:26px;border-radius:18px;text-align:center;
  background:var(--color-surface-0);box-shadow:var(--lift-rest);transform:rotateX(6deg)}
.floatc .fk{font-family:var(--font-mono);font-size:10px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--color-text-secondary)}
.floatc .fv{font-family:var(--font-mono);font-weight:700;font-size:60px;line-height:1;
  margin-top:10px;letter-spacing:-.04em}
@media (prefers-reduced-motion: no-preference){
  .floatc{animation:breathe 3.4s ease-in-out infinite}
}
@media (prefers-reduced-motion: reduce){ .floatc{transform:none} }
@keyframes breathe{0%,100%{transform:rotateX(6deg) translateY(0)}
                   50%{transform:rotateX(6deg) translateY(-8px)}}

/* ── Symmetry at 390, measured not eyeballed ──────────────────────────────
   getBoundingClientRect at 390px returned two and three distinct heights per
   peer group once the desktop min-heights were dropped. The symmetry ruling
   (2026-08-27) binds at both widths, so the floors come back at mobile scale
   rather than being removed, and the two groups that reflowed into a ragged
   2+1 grid are stacked instead. */
@media (max-width:1080px){
  .kpi .s{min-height:2.9em}
  .glasstile .s{min-height:2.8em}
  .spine p{min-height:4.5em}
  .quote .d4{min-height:3.6em}
  .quote .qm{min-height:4.5em}
  .pcard .place{min-height:2.7em}
  .pcard .block h3{min-height:2.44em}
}
@media (max-width:720px){
  /* the rail wrapped 2 + 1, leaving one item at double the width of its peers */
  .rail{flex-direction:column}
  .rail a{flex:1 1 auto;width:100%;min-width:0;padding-bottom:14px}
  /* three short values fit three columns at 390; a 2 + 1 grid does not */
  .specs{grid-template-columns:repeat(3,1fr)}
  .specs .v{font-size:15px}
  .specs .k{font-size:8.5px;letter-spacing:.07em}
  /* footer columns carry different link counts; give them one floor */
  .foot .cols > div{min-height:122px}
  .foot .cols > div:first-child{min-height:0}
}

/* ── The last of the measured asymmetries ─────────────────────────────────
   `1fr` resolves to min-content when a cell holds `white-space:nowrap`, so
   the three spec cells came back at three different widths and the third one
   ran 20px past a 390 viewport. minmax(0,1fr) is the fix, and it also closes
   the 0.01px desktop split. The two remaining height splits were em-based
   floors landing on different line boxes; they are px floors now. */
.specs{grid-template-columns:repeat(3,minmax(0,1fr))}
.specs .k,.specs .v{white-space:normal;overflow-wrap:anywhere}
@media (max-width:720px){ .specs{grid-template-columns:repeat(3,minmax(0,1fr))} }
@media (max-width:1080px){
  .glasstile .s{min-height:42px}
  /* Size the CONTAINER to the longest card rather than flooring each line
     independently — stacked inner floors grow the tall card in step with the
     short ones and the gap never closes. Ruling 2026-08-27. */
  .quote{min-height:300px}
  .quote .d4{min-height:0}
  .quote .qm{min-height:0}
}

/* One quote headline runs four lines at 390 where its peers run three; the
   floor has to clear the longest, not the average. Measured, not guessed. */

/* ── Two defects the hover pairs caught, invisible at rest ────────────────
   1. Every anchor re-underlined on hover, so the spine flood, the media card
      and the photo card all grew underlines the rest state does not have.
   2. Headings did not inherit colour, so when the status spine flooded to sky
      the card body inverted to white and the h3 stayed dark on blue. The
      interaction-layer templates carry `h1..h6{color:inherit}` at the top for
      exactly this reason; it was missed on the way across. */
a,a:hover,a:focus{text-decoration:none}
h1,h2,h3,h4,h5,h6{color:inherit}

/* The media card is an anchor, so on hover the whole body was inheriting the
   link colour and the WATTAGES turned sky. Sky means affordance; a numeral is
   not pressable, and one-meaning-per-colour (2026-08-27) says it cannot carry
   two jobs. The title takes the accent deliberately — it is the link — and
   every numeral stays ink. */
.media:hover .mt{color:var(--color-text-accent)}
.media .mv,.media .mk,.media .mm{color:var(--color-text-primary)}
.media .mk,.media .mm{color:var(--color-text-secondary)}
.media .mv.absent{color:var(--color-status-inactive)}

/* ══ Contrast, measured from rendered pixels ═══════════════════════════════
   CSS-computed contrast cannot answer text over a gradient, over glass, or
   over a photograph, so each of these was sampled from the actual render with
   the text hidden, comparing the text colour against the 2nd and 98th
   percentile of the ground it has to survive. Six pairs came back under AA.

   1 · The gradient card reached --color-accent-fill inside the visible frame,
       and white on the fill measures 1.99:1. It is a fills-only token by
       its own comment. The stop is pushed past the right edge so the visible
       ramp ends on the accent, which white clears.                          */
.grad{background:linear-gradient(100deg,var(--color-chrome) 4%,
      var(--color-accent) 72%, var(--color-accent-fill) 132%)}

/*  2 · An overline inside a dark section that was not also .on-dark kept the
       sky accent, which is 3.20:1 on the blue-950 ground and fails AA at
       11px. On a dark ground the accent steps up to the fill.               */
.sec.dark .overline,.panel .overline{color:var(--color-accent-fill)}
.sec.dark .overline.quiet{color:var(--color-chrome-ink)}

/*  3 · The nav pill sat at 4.27:1 against the brightest part of the hero
       photograph, just under the 4.5 its 14px links need. The dark glass goes
       deeper; it is still glass, and glass is not motion.                   */
.nav-in{background:rgba(11,19,29,.62)}

/*  4 · The glass stat tiles measured 4.49:1 against a bright sky — at the
       threshold, not clear of it. Denser glass, same blur.                  */
.glasstile{background:rgba(11,19,29,.40)}

/*  5 · A section headline over the Fayette photograph measured 2.59:1 where
       the left scrim runs out. The scrim carries further across the frame.  */
.panel .scrim.left{background:linear-gradient(to right,
    rgba(11,19,29,.90) 0%, rgba(11,19,29,.66) 46%,
    rgba(11,19,29,.30) 74%, rgba(11,19,29,.06) 100%)}

/*  6 · The drifting orbs reach rgba(255,255,255,.18) over sky, which puts
       near-white behind a white-text glass panel at its worst point. The
       panel ground is dark glass rather than light, and the orbs are calmer. */
.drift .panel-g{background:rgba(11,19,29,.42)}
.drift .o1{background:rgba(255,255,255,.12)}
.drift .o2{background:rgba(255,255,255,.09)}

/* ══ Per-element contrast, second pass ════════════════════════════════════
   Sampling each text node against only the ground behind IT found three more.

   a · The 11px labels on the gradient card measured 3.43–3.51:1. White on
       sky-600 is 4.11:1 — under AA at that size no matter what the opacity
       is, so the opacity was never the whole story. The ramp steps one stop
       deeper: chrome → sky-700 → sky-600. It is still the navy-to-bright-blue
       gradient of IL2 §10, and white on sky-700 is 6.98:1.                  */
.grad{background:linear-gradient(100deg,var(--color-chrome) 4%,
      var(--color-accent-hover) 64%, var(--color-accent) 122%)}
.grad .overline,.grad .k{opacity:1}

/*  b · An overline over PHOTOGRAPHY in accent-fill measured 2.67:1 against a
       scrimmed sky. Over a photograph the overline is white; the sky fill is
       for a dark solid ground, not for a picture.                           */
.panel .overline{color:var(--color-text-on-accent);opacity:1}

/* c · An overline high in a .short panel sat above the reach of the bottom
       scrim, on open sky, at 2.63:1. The short panels carry the scrim further
       up the frame; a scrim is not motion and costs nothing under reduced
       motion. */
.panel.short .scrim{background:linear-gradient(to top,
    rgba(11,19,29,.90) 0%, rgba(11,19,29,.78) 30%,
    rgba(11,19,29,.52) 58%, rgba(11,19,29,.18) 84%, rgba(11,19,29,.04) 100%)}
/* d · the gradient labels landed at 4.47:1, three hundredths under AA. */
.grad{background:linear-gradient(100deg,var(--color-chrome) 4%,
      var(--color-accent-hover) 72%, var(--color-accent) 128%)}

/* ══ The absence styling was the least readable text on the site ══════════
   "not on record" and "No photograph on record" were set in
   --color-status-inactive, which measures 2.71:1 on white and 2.32:1 on
   stone. That is the one string on these pages that must survive being read,
   because absence rendering as absence is the whole honesty rule — a gap
   nobody can read is just a gap. Inactive grey stays the DOT colour; the
   words move to secondary ink at 7.0:1, and the state is carried by the word
   itself rather than by the colour, which is the standing rule anyway. */
.ledger .row .v.absent,.media .mv.absent{color:var(--color-text-secondary);font-weight:400}
.media .noshot .np{color:var(--color-text-secondary)}
.ptable td span[style*="status-inactive"]{color:var(--color-text-secondary)!important}

/* A chip pinned ON a photograph has to survive whatever is behind it, and the
   portfolio holds bright open skies. At rgba(11,19,29,.66) white text over a
   blown sky lands near 4:1; at .78 the worst case a pure-white sky can give
   is rgb(65,68,72), which is 8.9:1. The chip is legible on every photograph
   in the set rather than on most of them. */
.media .chip{background:rgba(11,19,29,.78)}

/* A 4:3 property photograph cropped to a 16:9 panel lands on sky and loses the
   building. The panels favour the lower two thirds of the frame, which is
   where the elevation is in every photograph in this set. */
.panel .shot img{object-position:center 62%}

/* ── The conversion layer (loop-1) ────────────────────────────────────────
   ONE CTA component, ONE size, ONE label family. Everything that books is a
   .btn emitted by shell.book(); everything that only navigates is a .textlink.
   Before this pass the site shipped three different CTA sizes — nav 116x38,
   hero 146x44, footer 235x32 — which is why they are now emitted from a
   single helper and why _verify measures them.                             */

.cta-row{display:flex;gap:12px;flex-wrap:wrap;align-items:center}

/* the secondary on a LIGHT ground. .btn.ghost is white on transparent and
   only reads over a photograph; on stone it renders as an invisible pill. */
.btn.outline{background:transparent;color:var(--color-text-accent);
  box-shadow:inset 0 0 0 1.5px var(--color-accent)}
.btn.outline:hover{background:var(--color-accent);color:var(--color-text-on-accent);
  box-shadow:inset 0 0 0 1.5px var(--color-accent), var(--lift-hover)}

/* a secondary that reads on the glass panel over drifting orbs */
.btn.on-glass{background:var(--color-surface-0);color:var(--color-text-accent);
  box-shadow:inset 1px 1px 0 rgba(255,255,255,.5), var(--lift-rest)}
.btn.on-glass:hover{background:var(--color-surface-0);box-shadow:inset 1px 1px 0 rgba(255,255,255,.6), var(--lift-hover)}

/* Navigation that is not a call to action. IL3 §19's travelling underline,
   reduced to its honest part: a rule that draws in from the left. */
.textlink{display:inline-flex;align-items:center;gap:8px;position:relative;
  font-size:14px;font-weight:600;color:var(--color-text-accent);padding-bottom:3px}
.textlink.on-dark{color:var(--color-text-on-accent)}
.textlink span{transition:transform var(--duration-base) var(--ease-standard)}
.textlink::after{content:"";position:absolute;left:0;right:0;bottom:0;height:1.5px;
  background:currentColor;transform:scaleX(0);transform-origin:left;
  transition:transform var(--duration-base) var(--ease-standard)}
.textlink:hover::after{transform:scaleX(1)}
.textlink:hover span{transform:translateX(4px)}

/* ── The end-of-page CTA block. Emitted by the shell on all six pages. ──── */
/* The block fills its row edge to edge. A heading and a button centred in a
   margin is an unfinished page (ruled 2026-09-06). */
.endcta{background:var(--color-surface-0);border-top:var(--rule)}
.endcta-in{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:72px;align-items:center}
.endcta-say{display:flex;flex-direction:column;gap:18px}
.endcta-say .lede{max-width:46ch}
.endcta-say .cta-row{margin-top:12px}
.endcta-fig .ledger{background:var(--color-bg-page);border-radius:var(--mkt-radius-card);
  padding:6px 26px;box-shadow:var(--edge-light),var(--lift-rest)}
.endcta-fine{font-family:var(--font-mono);font-size:11.5px;
  color:var(--color-text-secondary);margin-top:16px}
@media (max-width:1080px){
  .endcta-in{grid-template-columns:1fr;gap:44px}
}

/* ── Persistent CTA on phone. Above 720px the fixed nav pill already carries
      one, so this is hidden and cannot double up.                          */
.stickybar{display:none}
@media (max-width:720px){
  .stickybar{display:block;position:fixed;left:0;right:0;bottom:0;z-index:70;
    padding:10px 16px calc(10px + env(safe-area-inset-bottom));
    background:var(--mkt-glass-dark-bg);border-top:var(--mkt-glass-dark-border);
    backdrop-filter:var(--mkt-glass-blur-sm);-webkit-backdrop-filter:var(--mkt-glass-blur-sm)}
  .stickybar-in{display:flex;justify-content:center}
  /* tucked while the hero's own CTA is still on screen; see site.js */
  .stickybar{transition:transform var(--duration-base) var(--ease-standard)}
  .stickybar.tuck{transform:translateY(105%)}
  /* The bar is 44px of button + 20px of padding + the safe-area inset, so the
     reserve has to carry the same inset or it covers the last footer line on a
     notched phone. */
  body{padding-bottom:calc(64px + env(safe-area-inset-bottom) + 8px)}
  .nav-in{gap:8px;padding:7px 7px 7px 16px}
  .brand{font-size:17px}
  .nav-cta{margin-left:auto}
}

@media (prefers-reduced-motion: reduce){ .stickybar{transition:none} }

/* the mark rides the wordmark at cap height, one gap, never scaled on hover */
.brand{display:inline-flex;align-items:center;gap:10px}
.brand .mark{width:28px;height:28px;display:block}
@media (max-width:720px){.brand .mark{width:26px;height:26px}}

/* ---- craft pass 2026-09-09 ----------------------------------------------
   Tap targets: every interactive element clears 44px on a phone, per the
   platform HIG. Measured at 390: footer links were 32px and the two inline
   text links 25-26px. */
@media (max-width:720px){
  .foot a{padding:11px 0;min-height:44px;display:flex;align-items:center}
  .foot .brand{min-height:44px;display:inline-flex;align-items:center}
  .textlink{display:inline-flex;align-items:center;min-height:44px}
  .brand{min-height:44px}
}

/* Press feedback lands on pointer-down, not on release, and it is instant. */
.btn:active,.textlink:active{transform:scale(.97)}
.btn{transition:background var(--duration-fast,120ms) var(--ease-standard),transform 100ms ease-out}

/* The translucent chrome has to survive the accessibility settings that turn
   translucency and low contrast off. Tokens only; no hand-copied hex. */
@media (prefers-reduced-transparency: reduce){
  .nav-in{background:var(--color-chrome);backdrop-filter:none}
  .glasstile,.panel-g{backdrop-filter:none;background:var(--color-chrome)}
}
@media (prefers-contrast: more){
  .nav-in{background:var(--color-chrome);border:1px solid var(--color-text-on-accent)}
  .nav-links a{color:var(--color-text-on-accent)}
  .btn{outline:2px solid var(--color-text-on-accent);outline-offset:-2px}
}

/* ---- components from references/liked-2026-09-03, remapped to system tokens ----

   1. Dot field  (grid-interactive-dots-MARKETING.tsx — flagged by Matt as a MARKETING
      surface, where ambient light is permitted). Dots light within a radius of the
      cursor: a light pool, on the section about what a light being out costs. Content
      sits above with pointer-events through it, so the cursor drives the field. */
.dotfield-host{position:relative;overflow:hidden}
/* No square gridlines anywhere. Matt, 2026-09-09: "I want the grid gone everywhere."
   The pack paints --mkt-grid on every dark section; the ambient glow on ::after stays,
   so the dark ground keeps its depth without the graph paper. */
.sec.dark::before{background:none}
.dotfield{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}
.dotfield-host > .wrap{position:relative;z-index:1}

/* 2. Five-stop shadow ramp (card-shadow-ramp-invert-chethan025). A real shadow is not
      one blur: wide-and-faint through tight-and-dense puts a surface IN space rather
      than on a grey smudge. Neutral ink only — the reference tinted its ramp. */
:root{
  --ramp-rest: 0 54px 34px -34px rgba(16,28,42,.07), 0 30px 20px -18px rgba(16,28,42,.06),
               0 13px 10px -8px rgba(16,28,42,.05), 0 3px 4px -2px rgba(16,28,42,.05),
               0 1px 1px rgba(16,28,42,.04);
  --ramp-hover: 0 84px 52px -40px rgba(16,28,42,.12), 0 46px 30px -22px rgba(16,28,42,.10),
                0 20px 15px -10px rgba(16,28,42,.08), 0 5px 6px -3px rgba(16,28,42,.07),
                0 1px 2px rgba(16,28,42,.06);
}
.kpi{box-shadow:var(--edge-light), var(--ramp-rest)}
.kpi:hover{box-shadow:var(--edge-light-strong), var(--ramp-hover)}
.pcard{box-shadow:var(--ramp-rest)}
.pcard:hover{box-shadow:var(--ramp-hover)}

/* 3. Four-shadow surface (surface-metallic-shine-chase2k25) on the nav pill: two outer
      shadows lift it, two inset edges carve the face. The reference's whole effect is
      shadow, no colour — which is why it costs nothing here. The 2s infinite shine that
      came with it is left behind (marketing shine that never stops, rejected #09). */
.nav-in{box-shadow:0 1px 2px rgba(16,28,42,.28), 0 20px 44px -20px rgba(16,28,42,.46),
        inset 1px 1px 0 rgba(255,255,255,.16), inset -1px -1px 0 rgba(16,28,42,.34)}

/* ---- awwwards pass 2026-09-09 : mechanics from references/liked-2026-09-03 ----

   1. Slide-up detail (card-slide-up-detail-gharsh11032000). The panel rests at 94%
      translate — the 6% sliver IS the affordance — and covers the photograph on hover.
      Absolutely positioned, so the grid can never reflow. */
.pcard .shot{position:relative}
.pslide{position:absolute;left:0;right:0;bottom:0;height:46%;
  display:flex;align-items:flex-start;padding:14px 20px 0;
  background:linear-gradient(180deg,transparent,var(--color-chrome) 42%);
  transform:translateY(94%);pointer-events:none;
  transition:transform var(--duration-slow) var(--ease-standard)}
.pslide p{font-family:var(--font-mono);font-size:11.5px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--color-text-on-accent)}
.pslide span{display:inline-block;transition:transform var(--duration-base) var(--ease-standard)}
.pcard:hover .pslide,.pcard:focus-visible .pslide{transform:translateY(0)}
.pcard:hover .pslide span{transform:translateX(5px)}

/* 2. Wobble (aceternity/wobble-card — "i love that"). One perspective on the row, a
      pointer-tracked rotate3d on the card, and the heading riding its own translateZ so
      the stack parallaxes rather than tilting as a flat plate. */
.g3.wobble-row{perspective:1100px}
.wobble{transform-style:preserve-3d;will-change:transform}
.wobble h3{transform:translateZ(26px)}
.wobble .sk{transform:translateZ(14px)}
.wobble .go{transform:translateZ(20px)}

/* 3. Magnetic primary button (interaction-layer §2). Translation comes from script;
      the spring back is a critically damped settle, never a bounce. */
.btn.magnetic{will-change:transform}

/* 4. Headline arriving by word (mask reveal). Each word sits in its own overflow box,
      so the line reads as type being set rather than a block fading in. */
.reveal-words .w{display:inline-block;overflow:hidden;vertical-align:top}
.reveal-words .wi{display:inline-block;}
.jsr .reveal-words .wi{transform:translateY(105%);
  transition:transform .82s cubic-bezier(.16,1,.3,1)}
.reveal-words.in .wi{transform:translateY(0)}

/* 5. Scroll progress. Two pixels of sky reporting position — the only fixed element
      besides the nav, and it never covers anything. */
.progress{position:fixed;left:0;top:0;height:2px;width:100%;z-index:80;
  background:var(--color-accent);transform:scaleX(0);transform-origin:left;
  pointer-events:none}

/* 6. Tabular numerals so a counting figure cannot change the width of its card. */
.kpi .v.num,.glasstile .v{font-variant-numeric:tabular-nums}

@media (prefers-reduced-motion: reduce){
  .pslide,.pslide span,.reveal-words .wi{transition:none}
  .reveal-words .wi{transform:none}
  .wobble{transform:none !important}
}

/* Product cards — the screenshot as an object in space, not a sticker.
   Mechanics: card-parallax-layers (every layer on its own translateZ inside one
   perspective), card-shadow-ramp-invert (the body inverts wholesale on hover),
   surface-metallic-shine (the plate is lifted by shadow, not by a border). */
.prodcards{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--mkt-gutter);
  perspective:1600px}
.prodcard{display:block;border-radius:var(--mkt-radius-tile);overflow:hidden;
  background:var(--color-surface-0);box-shadow:var(--ramp-rest);transform-style:preserve-3d;
  transition:transform .5s var(--ease-standard), box-shadow .5s var(--ease-standard)}
.prodcard:hover{box-shadow:var(--ramp-hover)}

/* the bed: the approved navy-to-sky ribbon, with the plate rising out of it */
.prodcard .shot{position:relative;aspect-ratio:16/9;overflow:hidden;
  background:linear-gradient(157deg, var(--color-chrome) 4%, var(--color-accent) 128%);
  display:flex;align-items:flex-end;justify-content:center;padding:26px 24px 0}
.prodcard .shot::after{content:"";position:absolute;top:-70px;right:-60px;width:260px;height:260px;
  border-radius:50%;background:rgba(255,255,255,.10)}
.prodcard .plate{position:relative;width:100%;border-radius:10px;overflow:hidden;margin-bottom:-12px;
  transform-origin:bottom center;transform:translateZ(30px) rotateX(7deg) scale(.98);
  box-shadow:0 2px 6px rgba(16,28,42,.22), 0 26px 44px -18px rgba(16,28,42,.55),
             inset 0 1px 0 rgba(255,255,255,.5);
  transition:transform .55s var(--ease-standard), box-shadow .55s var(--ease-standard)}
.prodcard .plate img{display:block;width:100%;height:auto}
.prodcard:hover .plate{transform:translateZ(58px) rotateX(0deg) scale(1);
  box-shadow:0 3px 8px rgba(16,28,42,.26), 0 44px 64px -20px rgba(16,28,42,.62),
             inset 0 1px 0 rgba(255,255,255,.6)}

/* the body inverts on hover — ground and text swap, no glow */
.prodcard .body{padding:22px 24px 26px;transform:translateZ(12px);
  transition:background .45s var(--ease-standard)}
.prodcard .body h3{font-family:var(--font-display);font-size:21px;font-weight:700;
  letter-spacing:-.018em;line-height:1.2;color:var(--color-text-primary);
  transition:color .45s var(--ease-standard)}
.prodcard .body p{margin-top:10px;font-size:14.5px;line-height:1.55;
  color:var(--color-text-secondary);transition:color .45s var(--ease-standard)}
.prodcard .body .go{margin-top:16px;font-family:var(--font-mono);font-size:11px;
  letter-spacing:.12em;text-transform:uppercase;color:var(--color-text-accent)}
.prodcard .body .go span{display:inline-block;transition:transform .3s var(--ease-standard)}
.prodcard:hover .body{background:var(--color-chrome)}
.prodcard:hover .body h3{color:var(--color-text-on-accent)}
.prodcard:hover .body p{color:rgba(255,255,255,.74)}
.prodcard:hover .body .go{color:var(--color-accent-fill)}
.prodcard:hover .body .go span{transform:translateX(6px)}

@media (max-width:900px){.prodcards{grid-template-columns:1fr;perspective:none}
  .prodcard .plate{transform:none}}
@media (prefers-reduced-motion: reduce){
  .prodcard,.prodcard .plate,.prodcard .body{transition:none}
  .prodcard .plate{transform:translateZ(0) rotateX(0) scale(1)}}

/* Segment row. Pills, not cards: the choice should read as a filter on one story,
   not as twelve separate products. */
.segrow{display:flex;flex-wrap:wrap;gap:10px}
.seg{display:inline-flex;align-items:center;min-height:44px;padding:0 20px;
  border-radius:999px;background:var(--color-surface-0);color:var(--color-text-primary);
  border:1px solid var(--color-border-subtle);font-size:15px;font-weight:600;
  box-shadow:var(--ramp-rest);
  transition:background var(--duration-base) var(--ease-standard),
             color var(--duration-base) var(--ease-standard),
             transform var(--duration-base) var(--ease-standard)}
.seg:hover{background:var(--color-accent);color:var(--color-text-on-accent);
  border-color:transparent;transform:translateY(-2px)}
.seg:active{transform:scale(.97)}

/* Peer groups stay one box. Stacked to a single column the rows size to their own
   copy, so a card with one more line of text is taller than its neighbours — the
   exact failure matt-taste names (a caption line, an icon column, content-sized
   pills). Equal rows fix it without touching the copy. Measured at 390 across
   index and industries: three groups were unequal before this. */
@media (max-width:900px){
  .g3, .prodcards, .pcards, .kpis, .glassgrid{grid-auto-rows:1fr}
}

/* 404 wayfinding. Five destinations, one row at desk, stacked on phone.
   Not cards: a lost visitor wants a list to scan, not objects to weigh. */
.lost{display:grid;gap:10px;max-width:520px}
.lost-link{display:flex;align-items:center;justify-content:space-between;gap:16px;
  padding:15px 20px;border-radius:var(--mkt-radius-card);text-decoration:none;
  background:var(--color-surface-0);box-shadow:var(--edge-light),var(--ramp-rest);
  transition:box-shadow .22s ease,transform .22s ease}
.lost-link .t{font-size:16px;color:var(--color-text-primary)}
.lost-link .a{color:var(--color-text-secondary);transition:transform .22s ease}
.lost-link:hover{box-shadow:var(--edge-light),var(--ramp-hover);transform:translateY(-1px)}
.lost-link:hover .a{transform:translateX(4px)}
@media (prefers-reduced-motion:reduce){
  .lost-link,.lost-link .a{transition:none}
  .lost-link:hover{transform:none}
}
