/* SteelFabSolutions — site stylesheet
   Brand tokens locked from the logo/card work: ink #091B34, mid #33526E, accent #4C72A1
   Dark-mode-forward marketing site, derived from that same navy family (not a separate palette). */

@font-face {
  font-family: 'Inter';
  font-weight: 400 900;
  font-style: normal;
  font-display: swap;
  src: url('fonts/inter.woff2') format('woff2');
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-weight: 500;
  font-style: normal;
  font-display: swap;
  src: url('fonts/plexmono.woff2') format('woff2');
}

:root {
  --bg: #060d16;
  --panel: #091b34;
  --panel-2: #0e2338;
  --panel-3: #133055;
  --line: rgba(140, 168, 197, 0.16);
  --line-bright: rgba(140, 168, 197, 0.32);
  --text: #f3f5f7;
  --text-soft: #a9bacb;
  --text-faint: #6d8099;
  --mid: #33526e;
  --accent: #4c72a1;
  --accent-bright: #86aad9;
  /* Redline: the one warm color on the page, used only for the detail-bubble
     numbering system (steps-list, pipeline) and the "Never Trusted" marks —
     a direct reference to how revisions actually get marked up on a real
     drawing (red pen/redline), not a decorative accent color. Everywhere
     else stays in the blue family on purpose. Value picked for contrast, not
     just hue: 5.6:1 against --bg and 5.0:1 against --panel (WCAG AA needs
     4.5:1 for normal-size text) — it's used at 11px inside actual circled
     numerals, so it has to hold up as text, not just as a border color. */
  --redline: #d66b4f;
  --shadow: 0 30px 70px -30px rgba(0, 0, 0, 0.65);
  --maxw: 1120px;
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
html, body {
  /* Defensive: the fixed hero-structure art sits partly off the right edge
     by design (`right: -8%`) — this guarantees that can never cause a
     horizontal scrollbar/rubber-band on any device, iOS included. */
  overflow-x: hidden;
}
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: 'Inter', ui-sans-serif, system-ui, sans-serif;
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  /* iOS shows a gray flash box on tap by default since there's no real
     :hover state on touch — kill it and lean on each element's own :active/
     :hover styling (buttons and navlinks already have explicit hover states
     below) instead of the browser's default highlight rectangle. */
  -webkit-tap-highlight-color: transparent;
  /* Faint drafting-sheet grid, everywhere — much lighter than the hero's own
     .hero::after grid (0.03 vs 0.055) so it reads as "this whole page is one
     continuous sheet" rather than a repeated effect. Plain background-image,
     not background-attachment: fixed — that's a known iOS Safari jank source
     and there's no reason to risk it for something this subtle. */
  background-image:
    linear-gradient(rgba(140, 168, 197, 0.03) 1px, transparent 1px),
    linear-gradient(90deg, rgba(140, 168, 197, 0.03) 1px, transparent 1px);
  background-size: 44px 44px;
}
img, svg { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
::selection { background: var(--accent); color: #060d16; }

/* Visible keyboard focus, sitewide — nav links, buttons, form fields, footer
   contact links. The browser default outline works but doesn't match
   anything else on a page this considered; this is the same accent-bright
   used for hover states, so focus and hover read as the same "interactive"
   language. Never removed without a replacement anywhere on this site. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible {
  outline: 2px solid var(--accent-bright);
  outline-offset: 3px;
  border-radius: 2px;
}

.wrap {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 28px;
}

/* ---------- type ---------- */
.mono {
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
}
.eyebrow {
  font-family: 'IBM Plex Mono', monospace;
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent-bright);
  display: inline-flex;
  align-items: center;
  gap: 10px;
}
.eyebrow::before {
  content: "";
  width: 20px;
  height: 1.5px;
  background: var(--accent);
  display: inline-block;
}
h1, h2, h3 {
  font-weight: 800;
  letter-spacing: -0.02em;
  margin: 0;
  text-wrap: balance;
}
h1 { font-size: clamp(38px, 5.4vw, 62px); line-height: 1.04; }
h2 { font-size: clamp(28px, 3.6vw, 40px); line-height: 1.1; }
h3 { font-size: 20px; line-height: 1.3; font-weight: 700; }
p { color: var(--text-soft); margin: 0; }
p.lede { font-size: 19px; line-height: 1.6; color: var(--text-soft); max-width: 62ch; }

/* ---------- nav ---------- */
header.site {
  position: sticky;
  top: 0;
  z-index: 40;
  background: rgba(6, 13, 22, 0.86);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
  /* Clears the Dynamic Island / notch / rounded-corner safe area in landscape
     on iPhone — env() resolves to 0 on every device without one, so this is
     a no-op everywhere else. */
  padding-left: env(safe-area-inset-left);
  padding-right: env(safe-area-inset-right);
}
header.site .wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 72px;
}
.brand { display: flex; align-items: center; gap: 12px; }
.brand svg, .brand .brand-mark {
  width: 30px; height: 30px; object-fit: contain; flex-shrink: 0;
  transition: transform 0.25s ease;
}
/* Small dial-turn on hover — a plain nudge that the mark is a link, not
   trying to be a bigger moment than that. Untouched at rest; this is a
   hover-only nicety, not a looping/autoplay animation, so no
   reduced-motion gate, same as the existing .btn/.navlink hover
   transitions below. */
.brand:hover .brand-mark { transform: rotate(14deg) scale(1.08); }
.brand-text { display: flex; flex-direction: column; gap: 2px; }
.brand .word { font-weight: 800; font-size: 16px; letter-spacing: -0.01em; line-height: 1; }
.brand .word .steel { color: var(--text-soft); }
.brand .word .fab { color: var(--text); }
.brand .tagline {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
  line-height: 1;
  transition: color 0.2s ease, letter-spacing 0.2s ease;
}
.brand:hover .tagline { color: var(--accent-bright); letter-spacing: 0.17em; }
nav.links { display: flex; align-items: center; gap: 32px; }
nav.links a.navlink {
  font-size: 14px;
  color: var(--text-soft);
  transition: color 0.15s ease;
  position: relative;
  padding-bottom: 2px;
}
nav.links a.navlink:hover { color: var(--text); }
/* Every other interactive control on this page picked up a hover treatment
   tonight (cards, form fields, buttons, the icon, the tagline) — the nav
   links were left with a bare color swap, which by comparison now reads
   as the one unfinished control rather than a deliberate restraint choice.
   A thin underline that expands from the left is the same depth of
   feedback the rest of the nav already has, nothing louder. */
nav.links a.navlink::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: var(--accent-bright);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.2s ease;
}
nav.links a.navlink:hover::after { transform: scaleX(1); }

.btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: 'Inter', sans-serif;
  font-weight: 600;
  font-size: 14.5px;
  padding: 11px 20px;
  border-radius: 3px;
  transition: transform 0.15s ease, background 0.15s ease, border-color 0.15s ease;
  white-space: nowrap;
}
.btn.primary {
  background: var(--accent);
  color: #060d16;
}
.btn.primary:hover { background: var(--accent-bright); transform: translateY(-1px); }
.btn.ghost {
  border: 1px solid var(--line-bright);
  color: var(--text);
}
.btn.ghost:hover { border-color: var(--accent); color: var(--accent-bright); }

/* ---------- hero ---------- */
.hero {
  padding: 96px 0 72px;
  border-bottom: 1px solid var(--line);
  position: relative;
  overflow: hidden;
}
.hero::before {
  content: "";
  position: absolute;
  inset: -20% -10% auto -10%;
  height: 620px;
  background: radial-gradient(ellipse at 50% 0%, rgba(76, 114, 161, 0.22) 0%, rgba(76, 114, 161, 0) 62%);
  pointer-events: none;
  z-index: 0;
}
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(140, 168, 197, 0.055) 1px, transparent 1px),
    linear-gradient(90deg, rgba(140, 168, 197, 0.055) 1px, transparent 1px);
  background-size: 44px 44px;
  background-position: center top;
  -webkit-mask-image: linear-gradient(180deg, black 0%, black 55%, transparent 92%);
  mask-image: linear-gradient(180deg, black 0%, black 55%, transparent 92%);
  pointer-events: none;
  z-index: 0;
}
.hero-structure {
  /* Fixed to the viewport (not .hero) so it can persist and parallax past the hero
     section as the user scrolls — see the second IIFE in script.js. It lives as a
     direct child of <body>, before <header>, so .hero's overflow: hidden can't clip it.

     v2: full-bleed centerpiece, not a right-anchored corner accent. Alex's
     direction: "logo more prominent... put the logo back in and do something
     different" — this is that. Centered, much wider (max-width 1320 -> 1800),
     paired with a massive headline overlaid on top of it (see .hero h1 below)
     and a dedicated .hero-scrim for legibility, instead of a faded wash tucked
     into a third of the hero.

     top is a fixed px offset, not a percentage, and deliberately NOT negative
     — the old `top: -8%` pushed the box's top edge above y:0, clipping the
     roofline/gridline-bubble annotations off-screen at load on every
     viewport. 62px clears the 72px sticky header (allowed to tuck slightly
     behind it — header has its own background and a higher z-index). */
  position: fixed;
  top: 62px;
  left: 50%;
  transform: translateX(-50%);
  width: 100%;
  max-width: 1800px;
  /* Resting opacity is NOT set here — it's controlled by BASE_OPACITY in script.js,
     which sets it via inline style on load. Edit the value there, not here, or the
     two will silently desync. */
  pointer-events: none;
  /* No other element in this stylesheet uses a negative or zero z-index outside of
     .hero's own internal layers (checked: header.site is 40, .hero::before/::after
     and .hero .wrap are 0/1, both scoped inside .hero's own stacking context). Body
     has no explicit background-establishing stacking context of its own, and body's
     background color propagates to the canvas (painted at the very bottom, below any
     negative z-index content) — so z-index: -1 here sits above the page background
     but behind every other real element on the page, including the sticky header. */
  z-index: -1;
  will-change: transform, opacity;
  /* No CSS mask-image here anymore — the 4-edge feather (fades to transparent on
     all sides, not just left-to-right) is now baked directly into the PNG's own
     alpha channel, along with a recolor from neutral gray into the site's blue
     accent family (--panel-2 -> --accent-bright duotone). See
     _hero_asset_redesign.py (site history) for how it was generated. Baking it in
     beats a CSS mask for two reasons: (1) it feathers top/bottom too, which a
     single linear-gradient mask direction can't do without stacking multiple
     mask layers and mask-composite, which iOS Safari has historically had bugs
     with; (2) it's the actual color source, not just the alpha shape, so the
     recolor and the fade are guaranteed to travel together as one asset. */
}
.hero-scrim {
  /* Sits directly on top of .hero-structure (same fixed positioning, DOM
     order right after it, same z-index: -1 — paint order for equal z-index
     values follows DOM order, so this is guaranteed to render above the
     structure art and still below everything real on the page).

     Rebuilt after actually seeing the live site (real browser screenshot,
     not a Pillow approximation) — the earlier flat vertical gradient was
     darkening the ENTIRE hero uniformly, right side included, where there's
     no text and nothing needs protecting. That's what was making the
     structure art read as "too hard to see" — the scrim was suppressing
     visibility everywhere to protect legibility in one column.
     Two gradients now, not one: a horizontal one that's dark only over the
     text column (left) and nearly gone by the art-dominant right side, plus
     a lighter vertical one for the button row at the bottom of the text
     column specifically. The art on the right is meant to be the most
     visible thing in the hero now — this scrim's job is narrower than it
     was: protect the text, stop apologizing for the art. Fades out in
     lockstep with .hero-structure — see script.js and the @supports block
     below — so it never lingers as an orphaned dark band once the art
     itself has scrolled away. */
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 100vh;
  background:
    linear-gradient(
      90deg,
      rgba(6, 13, 22, 0.92) 0%,
      rgba(6, 13, 22, 0.7) 28%,
      rgba(6, 13, 22, 0.25) 55%,
      rgba(6, 13, 22, 0.04) 80%
    ),
    linear-gradient(
      180deg,
      rgba(6, 13, 22, 0.05) 0%,
      rgba(6, 13, 22, 0.2) 55%,
      rgba(6, 13, 22, 0.55) 100%
    );
  pointer-events: none;
  z-index: -1;
}
.hero .wrap { z-index: 1; }
.hero .wrap { position: relative; }
.hero h1 {
  /* v2: this is now the hero's dominant visual element, not just its
     headline — 2026 award-tier sites lean on oversized type as the
     centerpiece instead of a smaller headline next to a background image
     (researched, not guessed — Awwwards/design-trend sources consistently
     put hero headlines in the 80-120px range). clamp() scales it from a
     readable 30px on the narrowest phones up to 92px on desktop, verified
     at both ends against a pixel mockup before implementing. */
  font-size: clamp(30px, 8vw, 92px);
  line-height: 1.02;
  max-width: 900px;
}
.hero .actions { display: flex; align-items: center; gap: 16px; margin-top: 32px; flex-wrap: wrap; }
.hero p.lede { margin-top: 22px; max-width: 52ch; }

@media (prefers-reduced-motion: no-preference) {
  /* Load-time entrance, once, for the hero only — the "single hero-level
     moment" this kind of choreography is meant for, not applied page-wide
     (the rest of the page uses the existing scroll-triggered reveal system
     instead of a second competing animation language). Stops at .hero-meta —
     .pipeline keeps its own reveal-on-scroll behavior untouched below. */
  .hero .eyebrow, .hero h1, .hero p.lede, .hero .actions, .hero .hero-meta, .hero .dwg-stamp {
    opacity: 0;
    animation: hero-rise 0.8s cubic-bezier(0.16, 1, 0.3, 1) both;
  }
  .hero .eyebrow { animation-delay: 0.05s; }
  .hero h1 { animation-delay: 0.16s; }
  .hero p.lede { animation-delay: 0.3s; }
  .hero .actions { animation-delay: 0.44s; }
  .hero .hero-meta { animation-delay: 0.54s; }
  .hero .dwg-stamp { animation-delay: 0.62s; }
  @keyframes hero-rise {
    from { opacity: 0; transform: translateY(18px); }
    to { opacity: 1; transform: translateY(0); }
  }
}

/* Native scroll-driven exit for the structure art — progressive enhancement,
   Chrome/Edge/Safari only (Firefox doesn't support animation-timeline as of
   2026; script.js feature-detects the same way and runs the old rAF-based
   parallax loop there instead — see the comment in that file). The two
   paths are mutually exclusive by construction: when this @supports block
   is active, script.js sets --base-opacity once and returns without ever
   touching this element's inline style or attaching a scroll listener, so
   there's no fight over who owns opacity/transform.
   animation-range: 0px 100vh matches the old JS's FADE_DISTANCE (one
   viewport height) so the two paths feel identical to a user regardless of
   which browser they're on. */
@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    .hero-structure {
      animation: hero-structure-exit linear both;
      animation-timeline: scroll(root);
      animation-range: 0px 100vh;
    }
    @keyframes hero-structure-exit {
      from { opacity: var(--base-opacity, 0.42); transform: translateY(0) scale(1) rotate(0deg); }
      to { opacity: 0; transform: translateY(35vh) scale(1.06) rotate(-1.5deg); }
    }
    /* Same mechanism, applied to the scrim too — it has to disappear in
       lockstep with the art it's legibility-support for, or it's just a
       dark band sitting over unrelated page content once .hero-structure
       is long gone. No transform here (a flat gradient overlay scaling/
       rotating would look like a rendering glitch, not an effect). */
    .hero-scrim {
      animation: hero-scrim-exit linear both;
      animation-timeline: scroll(root);
      animation-range: 0px 100vh;
    }
    @keyframes hero-scrim-exit {
      from { opacity: 1; }
      to { opacity: 0; }
    }
  }
}
.hero-meta {
  margin-top: 20px;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 12.5px;
  color: var(--text-faint);
  letter-spacing: 0.02em;
}
.dwg-stamp {
  /* A real title-block line — DWG NO. / REV / SCALE is the exact convention
     printed in the corner of every drawing sheet Alex has spent three years
     reading. Small, quiet, unbordered — it's a signature detail for someone
     who'd actually recognize the format, not a badge trying to get noticed. */
  margin-top: 10px;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 11px;
  color: var(--text-faint);
  opacity: 0.6;
  letter-spacing: 0.04em;
}

/* ---------- pipeline diagram ---------- */
.pipeline {
  margin-top: 64px;
  border: 1px solid var(--line);
  background: linear-gradient(180deg, var(--panel) 0%, var(--panel-2) 100%);
  border-radius: 4px;
  padding: 34px 30px 30px;
  overflow-x: auto;
}
.pipeline-row {
  display: flex;
  align-items: stretch;
  gap: 0;
  min-width: 780px;
}
.p-step {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 0 18px;
  position: relative;
}
.p-step:first-child { padding-left: 0; }
.p-step:last-child { padding-right: 0; }
.p-step .n {
  /* Detail bubble: the same circled-callout convention as the gridline
     markers (A, B, C, 1, 2, 3) baked into the hero's structure art — this
     is a real sequence (processing order), so it's marked the way an actual
     drawing marks a sequence, not with a generic numeral. */
  font-family: 'IBM Plex Mono', monospace;
  font-size: 10.5px;
  font-weight: 500;
  color: var(--redline);
  width: 22px;
  height: 22px;
  border: 1.5px solid var(--redline);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  transition: background 0.2s ease, color 0.2s ease;
}
/* Fills solid on hover, like a drawing callout getting checked off. Redline
   is the one warm color on this whole page (see the --redline comment
   above) — reusing it here instead of introducing a second interactive
   color keeps that restraint intact. */
.p-step:hover .n { background: var(--redline); color: var(--bg); }
.p-step .t {
  font-weight: 700;
  font-size: 15px;
  color: var(--text);
}
.p-step .d {
  font-size: 13px;
  color: var(--text-faint);
  line-height: 1.5;
}
.p-arrow {
  align-self: center;
  color: var(--text-faint);
  font-family: 'IBM Plex Mono', monospace;
  font-size: 18px;
  padding: 0 4px;
  flex: none;
}
.p-step.future { opacity: 0.55; }
.p-step.future .t::after {
  content: "IN DEVELOPMENT";
  display: block;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 9.5px;
  letter-spacing: 0.1em;
  color: var(--text-faint);
  font-weight: 500;
  margin-top: 6px;
}

/* ---------- sections ---------- */
section.block { padding: 92px 0; border-bottom: 1px solid var(--line); }
section.block:last-of-type { border-bottom: none; }
.block-head { max-width: 62ch; margin-bottom: 44px; }
.block-head h2 { margin-top: 14px; }
.block-head p { margin-top: 14px; font-size: 16.5px; }

/* problem list */
.problem-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: 4px;
  overflow: hidden;
}
.problem-card {
  background: var(--bg);
  padding: 28px 26px;
  /* Same pattern as .bento-cell below — that grid already does this exact
     background-swap-on-hover, this grid just never got it. Consistency
     with an already-proven pattern in this same file, not a new idea. */
  transition: background 0.2s ease;
}
.problem-card:hover { background: var(--panel); }
.problem-card .stat {
  font-family: 'IBM Plex Mono', monospace;
  font-weight: 500;
  font-size: 30px;
  color: var(--accent-bright);
  letter-spacing: -0.01em;
}
.problem-card .label {
  margin-top: 10px;
  font-size: 14px;
  color: var(--text-soft);
  line-height: 1.5;
}

.steps-list { margin-top: 40px; display: flex; flex-direction: column; }
.step-row {
  display: grid;
  grid-template-columns: 44px 1fr;
  gap: 20px;
  padding: 16px 0;
  border-top: 1px solid var(--line);
}
.step-row:last-child { border-bottom: 1px solid var(--line); }
.step-row .num {
  /* Same detail-bubble convention as .p-step .n (see comment there) — plus a
     short leader tick, the way a real drawing callout points from its bubble
     toward the thing it's annotating. */
  font-family: 'IBM Plex Mono', monospace;
  font-size: 11px;
  font-weight: 500;
  color: var(--redline);
  width: 26px;
  height: 26px;
  border: 1.5px solid var(--redline);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  align-self: start;
  margin-top: 1px;
  position: relative;
}
.step-row .num::after {
  content: "";
  position: absolute;
  left: 100%;
  top: 50%;
  width: 10px;
  height: 1px;
  background: var(--redline);
  opacity: 0.45;
}
.step-row .txt { color: var(--text-soft); font-size: 15px; }
.step-row .txt b { color: var(--text); font-weight: 600; }

/* ---------- proof bento (case study: terminal + golden rule + compare) ----------
   Was three stacked full-width sections (rule-panel, compare-row, and a whole
   separate "interface" section for the terminal) telling one story across
   three scrolls. One bento grid instead — the terminal (the actual proof —
   watch it work) gets the big cell, the other two are supporting detail next
   to it. Matches how the rest of the page already builds cards (.bento,
   .problem-grid) instead of introducing a new pattern. */
.proof-bento {
  display: grid;
  grid-template-columns: 1.25fr 1fr;
  grid-template-rows: auto auto;
  gap: 24px;
  margin-top: 44px;
}
.proof-cell {
  border: 1px solid var(--line);
  background: var(--panel);
  border-radius: 4px;
  padding: 30px;
}
.proof-terminal { grid-row: 1 / 3; display: flex; flex-direction: column; gap: 22px; background: transparent; border: none; padding: 0; }
.proof-caption h3 { font-size: 18px; }
.proof-caption p { margin-top: 8px; font-size: 14.5px; }
.proof-terminal .terminal { flex: 1; }

.proof-rule h3 {
  font-size: 13px;
  color: var(--accent-bright);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-family: 'IBM Plex Mono', monospace;
  font-weight: 500;
}
.proof-rule-sub { margin-top: 10px; font-size: 14px; }
.rule-lists {
  margin-top: 20px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 18px;
}
.no-trust, .yes-trust { display: flex; flex-direction: column; gap: 8px; }
.item { display: flex; align-items: baseline; gap: 9px; font-size: 13.5px; color: var(--text-soft); line-height: 1.4; }
.item .mark { font-family: 'IBM Plex Mono', monospace; font-size: 12px; flex: none; }
.no .mark { color: var(--redline); }
.yes .mark { color: var(--accent-bright); }
.rule-quote {
  margin-top: 22px;
  padding-top: 18px;
  border-top: 1px solid var(--line);
  font-size: 15px;
  color: var(--text);
  font-weight: 500;
  line-height: 1.5;
}

.proof-compare { display: flex; flex-direction: column; justify-content: center; gap: 18px; }
.proof-compare-note { font-size: 13.5px; line-height: 1.5; color: var(--text-soft); }

/* stat compare */
.compare-row { display: flex; gap: 28px; flex-wrap: wrap; width: 100%; }
.compare-cell { flex: 1; min-width: 130px; }
.compare-cell .big { font-family: 'IBM Plex Mono', monospace; font-size: 40px; font-weight: 500; letter-spacing: -0.01em; }
.compare-cell.good .big { color: var(--accent-bright); }
.compare-cell.bad .big { color: var(--text-faint); }
.compare-cell .cap { margin-top: 6px; font-size: 12.5px; color: var(--text-faint); line-height: 1.4; }

@media (max-width: 860px) {
  .proof-bento { grid-template-columns: 1fr; grid-template-rows: auto; }
  .proof-terminal { grid-row: auto; }
}

/* how you talk to it */
.terminal {
  /* The one cut corner on the page. Sharp everywhere else (border-radius: 0,
     not the 4-6px used elsewhere) so the single chamfered top-right corner
     reads as a deliberate plate-cut detail, not a rounding inconsistency —
     this is the visual language of steel plate/panel edges, used exactly
     once so it stays a signature instead of a repeated decoration. */
  border: 1px solid var(--line-bright);
  background: #04090f;
  border-radius: 0;
  clip-path: polygon(0 0, calc(100% - 22px) 0, 100% 22px, 100% 100%, 0 100%);
  overflow: hidden;
  box-shadow: var(--shadow);
}
.terminal .bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--line);
  background: var(--panel);
}
.terminal .dot { width: 9px; height: 9px; border-radius: 50%; background: var(--line-bright); }
.terminal .label { margin-left: 8px; font-family: 'IBM Plex Mono', monospace; font-size: 11.5px; color: var(--text-faint); }
.terminal .body { padding: 24px 26px; font-family: 'IBM Plex Mono', monospace; font-size: 13.5px; line-height: 1.9; }
.terminal .u { color: var(--text-soft); }
.terminal .u::before { content: "› "; color: var(--accent-bright); }
.terminal .r { color: var(--accent-bright); margin: 6px 0 18px; white-space: pre-wrap; }

/* template system */
.two-col { display: grid; grid-template-columns: 1.1fr 0.9fr; gap: 56px; align-items: center; }
.tmpl-card { border: 1px solid var(--line); background: var(--panel); border-radius: 4px; padding: 26px; overflow: hidden; }
.tmpl-card .row {
  display: flex; justify-content: space-between; font-family: 'IBM Plex Mono', monospace;
  font-size: 12.5px; padding: 9px 26px; margin: 0 -26px; border-bottom: 1px solid var(--line);
  transition: background 0.15s ease;
}
.tmpl-card .row:last-child { border-bottom: none; }
.tmpl-card .row:hover { background: var(--panel-2); }
.tmpl-card .row .k { color: var(--text-faint); }
.tmpl-card .row .v { color: var(--accent-bright); }

/* cta band */
.cta-band {
  padding: 90px 0;
  text-align: center;
  background: linear-gradient(180deg, var(--bg) 0%, var(--panel) 140%);
}
.cta-band h2 { max-width: 20ch; margin: 0 auto; }
.cta-band p.lede { margin: 18px auto 0; text-align: center; }
.cta-band .actions { justify-content: center; margin-top: 30px; }
.cta-seal {
  /* The actual brand mark, brought back for exactly one moment on the page —
     the nav/footer deliberately dropped it (per the original design spec:
     it doesn't reduce legibly to icon size, and the hero's structure art is
     the real centerpiece). Here it's not doing nav-icon duty, it's playing a
     different role: the sealed/stamped mark on a drawing, right where you're
     asking someone to commit — an engineer's stamp, not a logo bug. */
  width: 100%;
  max-width: 320px;
  height: auto;
  object-fit: contain;
  margin: 0 auto 26px;
}
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .cta-seal {
      animation: seal-stamp linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 65%;
    }
    @keyframes seal-stamp {
      from { opacity: 0; transform: scale(1.5) rotate(-14deg); }
      to { opacity: 1; transform: scale(1) rotate(0deg); }
    }
  }
}

/* footer */
footer.site {
  padding: 48px 0 56px;
  padding-left: env(safe-area-inset-left);
  padding-right: env(safe-area-inset-right);
  /* Home-indicator clearance on iPhone in standalone/home-screen mode. */
  padding-bottom: calc(56px + env(safe-area-inset-bottom));
}
footer.site .wrap { display: flex; align-items: flex-start; justify-content: space-between; flex-wrap: wrap; gap: 24px; }
footer.site .f-brand { display: flex; align-items: center; gap: 10px; }
footer.site .f-brand svg { width: 22px; height: 22px; }
footer.site .f-brand .word { font-weight: 800; font-size: 14px; }
footer.site .f-contact { font-family: 'IBM Plex Mono', monospace; font-size: 12.5px; color: var(--text-faint); display: flex; flex-direction: column; gap: 5px; }
footer.site .f-contact a:hover { color: var(--accent-bright); }
footer.site .f-note { font-size: 12px; color: var(--text-faint); margin-top: 18px; }

/* ---------- demo page ---------- */
.demo-hero { padding: 72px 0 56px; border-bottom: 1px solid var(--line); }
.demo-layout { display: grid; grid-template-columns: 1fr 1fr; gap: 64px; padding: 72px 0; align-items: start; }
.demo-why { display: flex; flex-direction: column; gap: 22px; }
.demo-why .item { display: flex; gap: 14px; }
.demo-why .item .ix {
  /* Same detail-bubble convention as .step-row .num — this is also a real,
     ordered sequence (what happens first, second, third, fourth on the call). */
  font-family: 'IBM Plex Mono', monospace;
  font-size: 11px;
  font-weight: 500;
  color: var(--redline);
  width: 26px;
  height: 26px;
  border: 1.5px solid var(--redline);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
}
.demo-why .item .tx b { color: var(--text); display: block; margin-bottom: 4px; font-size: 15px; }
.demo-why .item .tx p { font-size: 14.5px; }

form.demo-form { display: flex; flex-direction: column; gap: 18px; border: 1px solid var(--line-bright); background: var(--panel); border-radius: 6px; padding: 32px; }
form.demo-form label { font-family: 'IBM Plex Mono', monospace; font-size: 11.5px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-faint); margin-bottom: 7px; display: block; }
form.demo-form .field { display: flex; flex-direction: column; }
form.demo-form input, form.demo-form textarea, form.demo-form select {
  background: var(--bg);
  border: 1px solid var(--line-bright);
  border-radius: 3px;
  padding: 11px 13px;
  color: var(--text);
  font-family: 'Inter', sans-serif;
  /* 16px, not 14.5px: iOS Safari auto-zooms the whole page on focus for any
     input with a computed font-size under 16px. This is the fix, not a
     workaround — there's no other way to disable that behavior. */
  font-size: 16px;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
form.demo-form input:focus, form.demo-form textarea:focus, form.demo-form select:focus {
  /* outline:none here is the documented exception, not a removal — the
     border-color + glow below is the replacement indicator required by the
     comment near the top of this file. Keyboard users still get the real
     outline everywhere else on the site; this is specifically the case
     that already had an equivalent visible substitute before this change,
     now just smoother and slightly more visible than a flat border swap. */
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(76, 114, 161, 0.18);
}
form.demo-form textarea { resize: vertical; min-height: 90px; }
form.demo-form .row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
form.demo-form .submit-note { font-size: 12.5px; color: var(--text-faint); margin-top: -4px; }
form.demo-form button.btn { margin-top: 6px; width: 100%; justify-content: center; cursor: pointer; border: none; font-size: 15px; padding: 13px 20px; }

@media (max-width: 600px) {
  /* The spelled-out word mark is the first thing to go, not the tagline —
     "SteelFabSolutions" is redundant with the icon + page context, the
     tagline is the one thing that has to survive down to phone widths. */
  header.site .brand .word { display: none; }
}
@media (max-width: 480px) {
  header.site .brand .tagline { font-size: 8px; letter-spacing: 0.09em; }
  header.site .brand { gap: 8px; }
  header.site .btn.primary { padding: 9px 14px; font-size: 13.5px; }
  .dwg-stamp { font-size: 10px; }
}

@media (max-width: 860px) {
  nav.links a.navlink { display: none; }
  .problem-grid { grid-template-columns: 1fr; }
  .two-col { grid-template-columns: 1fr; }
  .demo-layout { grid-template-columns: 1fr; gap: 40px; }
  form.demo-form .row2 { grid-template-columns: 1fr; }
  /* At phone widths, full-bleed centered (left: 0, no transform — simpler
     than fighting the desktop centering transform at a width where it's
     already edge-to-edge anyway) sitting just under the header. Same
     reasoning as desktop v2: full-bleed centerpiece, not a corner accent —
     just without the desktop max-width cap, since phones never need one. */
  .hero-structure { left: 0; transform: none; width: 100%; max-width: none; top: 66px; }
}

@media (prefers-reduced-motion: no-preference) {
  .reveal { animation: rise 0.6s ease-out both; }
  @keyframes rise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }

  .reveal-on-scroll {
    opacity: 0;
    transform: translateY(16px);
    transition: opacity 0.6s ease-out, transform 0.6s ease-out;
  }
  .reveal-on-scroll.is-visible { opacity: 1; transform: translateY(0); }
  .reveal-on-scroll.d1 { transition-delay: 0.08s; }
  .reveal-on-scroll.d2 { transition-delay: 0.16s; }
  .reveal-on-scroll.d3 { transition-delay: 0.24s; }
  .reveal-on-scroll.d4 { transition-delay: 0.32s; }
}

/* ---------- bento capability grid ---------- */
.bento {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-auto-rows: minmax(178px, auto);
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: 4px;
  overflow: hidden;
}
.bento-cell {
  background: var(--bg);
  padding: 24px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  transition: background 0.2s ease;
}
.bento-cell:hover { background: var(--panel); }
.bento-cell.wide { grid-column: span 2; }
.bento-cell .bi {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.08em;
  color: var(--accent-bright);
  text-transform: uppercase;
}
.bento-cell .bt { font-weight: 700; font-size: 16px; color: var(--text); margin-top: 10px; }
.bento-cell .bd { font-size: 13.5px; color: var(--text-faint); line-height: 1.5; margin-top: 6px; }
@media (max-width: 860px) {
  .bento { grid-template-columns: 1fr 1fr; }
  .bento-cell.wide { grid-column: span 2; }
}
@media (max-width: 560px) {
  .bento { grid-template-columns: 1fr; }
  .bento-cell.wide { grid-column: span 1; }
}
