// The whole building spec, redrawn from the client's print brochure.
//
// SCOPE: this file is now the site's single answer to "what is actually in this
// building". It covers the structural half of the brochure - how the building
// is framed and shaped (pp. 3, 5, 7, 11) - and, since Jul 2026, the envelope
// half that used to live on the Services page: how the parts fit together
// (p. 4), panels and color (pp. 6, 12), doors, accessories and openings
// (pp. 9-10) and insulation (p. 10).
//
// Services now sells the *job* (what we deliver, what we build it for) and
// hands off to this page for what the building is made of. The handoff link
// lives under the build-sequence strip in services.jsx; don't add a second
// copy of any section below back onto that page.
//
// Every drawing in the source brochure is trapped in a full-page 72 DPI raster
// (612x791px on a 612x792pt page), so none of it could be lifted. These are
// redrawn as vector, which themes with the site and stays sharp at any size.
//
// Each export below is a standalone <section>, matching how they were written
// on Services, so they can be dropped into a page in any order:
//   <BuildEnvelope /> <FrameTypes /> <RoofStyles /> <Assembly />
//   <Panels /> <Doors /> <Accessories /> <Insulation /> <StandardFeatures />
//
// COPY STATUS: names and technical claims are the brochure's own, condensed.
// The frame, roof, trim and accessory descriptions are close paraphrases of its
// wording; the standard-feature blurbs are near-verbatim. Worth a read-through
// by Brad before this goes live, but it is not invented copy.

//. SHARED AXONOMETRIC ,
// Same projection as the frame-anatomy figure, so the two read as one drawing
// set. Small enough to inline rather than share a module: these thumbnails use
// their own scale and origin.
const SP_W = 104, SP_D = 72, SP_E = 40, SP_R = 66, SP_MID = 52;
const SP_OX = 12, SP_OY = 98;

const spX = (x, y) => SP_OX + x + 0.55 * y;
const spY = (y, z) => SP_OY - 0.32 * y - z;

// Walls + eave line, shared by every roof style. `e` lets the parapet raise them.
const spShell = (e = SP_E) => [
  [[0, 0, 0], [SP_W, 0, 0]], [[SP_W, 0, 0], [SP_W, SP_D, 0]],
  [[0, 0, 0], [0, SP_D, 0]], [[0, SP_D, 0], [SP_W, SP_D, 0]],
  [[0, 0, 0], [0, 0, e]], [[SP_W, 0, 0], [SP_W, 0, e]],
  [[SP_W, SP_D, 0], [SP_W, SP_D, e]], [[0, SP_D, 0], [0, SP_D, e]],
  [[0, 0, e], [SP_W, 0, e]], [[SP_W, 0, e], [SP_W, SP_D, e]],
  [[0, 0, e], [0, SP_D, e]], [[0, SP_D, e], [SP_W, SP_D, e]],
];

//. SHARED PIECES OF THE FEATURE BLOCKS ,
// The manufacturer credit. Both feature blocks below used to lead with the
// brand ("Our roll-up doors are Janus", "We build our wainscots out of
// GenStone"), which read like the supplier's page rather than ours. The
// headings now say what the thing IS; the brand sits here, once, linked, at the
// end of the copy where someone who cares can follow it.
const SupplierNote = ({ href, brand, lead, tail }) => (
  <p style={{ marginTop: 18, fontSize: 13, lineHeight: 1.6, color: 'var(--fg-faint)' }}>
    {lead}{' '}
    <a href={href} target="_blank" rel="noopener noreferrer" className="inline-link">
      {brand}
      <span aria-hidden="true" style={{ fontSize: 10, marginLeft: 3 }}>↗</span>
    </a>
    . {tail}
  </p>
);

// The photo half of a feature block. Capped and sticky rather than stretched:
// see .spec-media in styles.css for why. `cap` puts a caption strip inside the
// sticky frame, which both closes off its bottom edge and matches the captions
// on the wainscot thumbnails further down.
const SpecMedia = ({ src, label, cap }) => (
  <div>
    <div className="spec-media" style={{ display: 'flex', flexDirection: 'column' }}>
      {/* height:'auto' overrides ImgSlot's own `height` prop so flex, not a
          percentage, decides how much of the frame the photo gets. */}
      <ImgSlot src={src} label={label} style={{ flex: 1, minHeight: 0, height: 'auto', border: 'none' }} />
      {cap && (
        <div className="mono" style={{
          flexShrink: 0, padding: '14px 20px', borderTop: '1px solid var(--border)',
          fontSize: 10, letterSpacing: '0.08em', color: 'var(--fg-faint)',
        }}>
          {cap}
        </div>
      )}
    </div>
  </div>
);

const SpDrawing = ({ shell, roof, dashed = [] }) => (
  <svg viewBox="0 0 168 116" width="100%" aria-hidden="true" style={{ display: 'block' }}>
    {shell.map((l, i) => (
      <line key={`s${i}`}
        x1={spX(l[0][0], l[0][1])} y1={spY(l[0][1], l[0][2])}
        x2={spX(l[1][0], l[1][1])} y2={spY(l[1][1], l[1][2])}
        stroke="var(--fg-faint)" strokeWidth="1" opacity="0.55" />
    ))}
    {dashed.map((l, i) => (
      <line key={`d${i}`}
        x1={spX(l[0][0], l[0][1])} y1={spY(l[0][1], l[0][2])}
        x2={spX(l[1][0], l[1][1])} y2={spY(l[1][1], l[1][2])}
        stroke="var(--fg-faint)" strokeWidth="1" strokeDasharray="3 3" opacity="0.4" />
    ))}
    {roof.map((l, i) => (
      <line key={`r${i}`}
        x1={spX(l[0][0], l[0][1])} y1={spY(l[0][1], l[0][2])}
        x2={spX(l[1][0], l[1][1])} y2={spY(l[1][1], l[1][2])}
        stroke="var(--accent)" strokeWidth="1.7" strokeLinecap="square" />
    ))}
  </svg>
);

//. ROOF STYLES - brochure p. 7 "Custom Designs" ,
const HIP = 18;          // how far the hip ends inset from the endwalls
const GAM_BRK = 26;      // gambrel lower/upper slope break
const GAM_Z = 58;
const MAN_IN = 18;       // mansard top inset
const MAN_Z = 58;

const ROOF_STYLES = [
  {
    name: 'Gabled',
    blurb: 'The peak faces the front. The most common roof line, and the most economical.',
    roof: [
      [[SP_MID, 0, SP_R], [SP_MID, SP_D, SP_R]],
      [[0, 0, SP_E], [SP_MID, 0, SP_R]], [[SP_W, 0, SP_E], [SP_MID, 0, SP_R]],
      [[0, SP_D, SP_E], [SP_MID, SP_D, SP_R]], [[SP_W, SP_D, SP_E], [SP_MID, SP_D, SP_R]],
    ],
  },
  {
    name: 'Hipped',
    blurb: 'All four roof faces rise to a ridge across the top, with broader faces across the front slope and narrower sections at the sides.',
    roof: [
      [[SP_MID, HIP, SP_R], [SP_MID, SP_D - HIP, SP_R]],
      [[0, 0, SP_E], [SP_MID, HIP, SP_R]], [[SP_W, 0, SP_E], [SP_MID, HIP, SP_R]],
      [[0, SP_D, SP_E], [SP_MID, SP_D - HIP, SP_R]], [[SP_W, SP_D, SP_E], [SP_MID, SP_D - HIP, SP_R]],
    ],
  },
  {
    name: 'Cross-hipped',
    blurb: 'Multiple sections or wings crossing the main section, meeting in a valley, each with its own hipped profile.',
    // The odd one out: this main ridge runs left to right, because a cross
    // needs the wing ridge perpendicular to it. The wing projects toward the
    // viewer and its ridge lands on the main ridge. Pitches are not reconciled
    // between the two roofs - at this size that is invisible, and forcing it
    // would push the wing off the front wall.
    shell: [
      ...spShell(),
      [[34, -34, 0], [70, -34, 0]], [[34, -34, 0], [34, 0, 0]], [[70, -34, 0], [70, 0, 0]],
      [[34, -34, 0], [34, -34, SP_E]], [[70, -34, 0], [70, -34, SP_E]],
      [[34, -34, SP_E], [70, -34, SP_E]],
      [[34, -34, SP_E], [34, 0, SP_E]], [[70, -34, SP_E], [70, 0, SP_E]],
    ],
    // Valleys sit in the dashed layer rather than the accent layer: drawn at
    // full weight, five lines meeting at the ridge crossing read as a starburst.
    dashed: [
      [[34, 0, SP_E], [SP_MID, SP_D / 2, SP_R]], [[70, 0, SP_E], [SP_MID, SP_D / 2, SP_R]],
    ],
    roof: [
      [[HIP, SP_D / 2, SP_R], [SP_W - HIP, SP_D / 2, SP_R]],
      [[0, 0, SP_E], [HIP, SP_D / 2, SP_R]], [[0, SP_D, SP_E], [HIP, SP_D / 2, SP_R]],
      [[SP_W, 0, SP_E], [SP_W - HIP, SP_D / 2, SP_R]], [[SP_W, SP_D, SP_E], [SP_W - HIP, SP_D / 2, SP_R]],
      [[SP_MID, -20, SP_R], [SP_MID, SP_D / 2, SP_R]],
      [[34, -34, SP_E], [SP_MID, -20, SP_R]], [[70, -34, SP_E], [SP_MID, -20, SP_R]],
    ],
  },
  {
    name: 'Gambrel',
    blurb: 'A broad upper story and side façade. Most often associated with barns.',
    roof: [
      [[SP_MID, 0, 70], [SP_MID, SP_D, 70]],
      [[GAM_BRK, 0, GAM_Z], [GAM_BRK, SP_D, GAM_Z]],
      [[SP_W - GAM_BRK, 0, GAM_Z], [SP_W - GAM_BRK, SP_D, GAM_Z]],
      [[0, 0, SP_E], [GAM_BRK, 0, GAM_Z]], [[GAM_BRK, 0, GAM_Z], [SP_MID, 0, 70]],
      [[SP_MID, 0, 70], [SP_W - GAM_BRK, 0, GAM_Z]], [[SP_W - GAM_BRK, 0, GAM_Z], [SP_W, 0, SP_E]],
      [[0, SP_D, SP_E], [GAM_BRK, SP_D, GAM_Z]], [[GAM_BRK, SP_D, GAM_Z], [SP_MID, SP_D, 70]],
      [[SP_MID, SP_D, 70], [SP_W - GAM_BRK, SP_D, GAM_Z]], [[SP_W - GAM_BRK, SP_D, GAM_Z], [SP_W, SP_D, SP_E]],
    ],
  },
  {
    name: 'Mansard',
    blurb: 'Typically aesthetic. It hides the roof slope and conceals any roof accessories, and creates an exceptional area for signage, which makes a building a much more attractive commercial structure.',
    roof: [
      [[MAN_IN, 12, MAN_Z], [SP_W - MAN_IN, 12, MAN_Z]],
      [[MAN_IN, SP_D - 12, MAN_Z], [SP_W - MAN_IN, SP_D - 12, MAN_Z]],
      [[MAN_IN, 12, MAN_Z], [MAN_IN, SP_D - 12, MAN_Z]],
      [[SP_W - MAN_IN, 12, MAN_Z], [SP_W - MAN_IN, SP_D - 12, MAN_Z]],
      [[0, 0, SP_E], [MAN_IN, 12, MAN_Z]], [[SP_W, 0, SP_E], [SP_W - MAN_IN, 12, MAN_Z]],
      [[0, SP_D, SP_E], [MAN_IN, SP_D - 12, MAN_Z]], [[SP_W, SP_D, SP_E], [SP_W - MAN_IN, SP_D - 12, MAN_Z]],
    ],
  },
  {
    name: 'Parapet',
    blurb: 'Walls raised past the eave to cover the roof line. The end result looks as if the roof has no slope in any direction, an effect some customers want.',
    shell: spShell(52),
    // The real roof sits below the parapet, so it is drawn dashed - hidden.
    dashed: [
      [[6, 6, 44], [SP_W - 6, 6, 44]], [[6, SP_D - 6, 44], [SP_W - 6, SP_D - 6, 44]],
      [[6, 6, 44], [6, SP_D - 6, 44]], [[SP_W - 6, 6, 44], [SP_W - 6, SP_D - 6, 44]],
    ],
    roof: [
      [[0, 0, 52], [SP_W, 0, 52]], [[SP_W, 0, 52], [SP_W, SP_D, 52]],
      [[0, 0, 52], [0, SP_D, 52]], [[0, SP_D, 52], [SP_W, SP_D, 52]],
    ],
  },
];

const RoofStyles = () => (
  <section className="section" style={{ borderTop: '1px solid var(--border)' }}>
    <div className="page">
      <SectionEyebrow id="FIG. 03" label="Custom designs" />
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'end', flexWrap: 'wrap', gap: 24 }}>
        <h2 style={{ maxWidth: 640 }}>Pick your roof line.</h2>
        <span className="mono" style={{ fontSize: 10, color: 'var(--fg-faint)', letterSpacing: '0.08em' }}>
          SIX PROFILES · ALL CUSTOM
        </span>
      </div>
      <p style={{ marginTop: 20, maxWidth: 640, fontSize: 16, color: 'var(--fg-dim)' }}>
        We build custom-designed buildings, so the roof is a choice, not a default.
        Lean-to&rsquo;s, canopies, hip roofs, gambrel roofs, and mezzanines all come off the same shop.
      </p>

      <div className="mob-2col" style={{
        marginTop: 48,
        display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 0,
        border: '1px solid var(--border)', background: 'var(--bg-card)',
      }}>
        {ROOF_STYLES.map((s, i) => (
          <div key={s.name} className="lift" style={{
            padding: 24,
            borderRight: (i % 3 !== 2) ? '1px solid var(--border)' : 'none',
            borderBottom: i < 3 ? '1px solid var(--border)' : 'none',
            display: 'flex', flexDirection: 'column', gap: 14,
          }}>
            <SpDrawing shell={s.shell || spShell()} roof={s.roof} dashed={s.dashed || []} />
            <div className="mono" style={{ fontSize: 10, letterSpacing: '0.08em', color: 'var(--fg-faint)' }}>
              <span style={{ color: 'var(--accent)' }}>{String(i + 1).padStart(2, '0')}</span> · ROOF STYLE
            </div>
            <h3 className="cap-card-title">{s.name}</h3>
            <p style={{ margin: 0, fontSize: 13.5, lineHeight: 1.55, color: 'var(--fg-dim)' }}>{s.blurb}</p>
          </div>
        ))}
      </div>
    </div>
  </section>
);

//. FRAME TYPES - brochure p. 5 ,
// Drawn as 2D sections rather than axonometric: a frame type is a section, and
// that is how the brochure and every shop drawing shows it.
const FRAME_TYPES = [
  {
    name: 'Rigid Frame Clearspan',
    tag: "30' to 200'",
    blurb: 'The proven performer. Nothing between the columns, so the entire floor is usable. Incredible strength, durability, versatility, and economy, and the most practical solution to most ordinary building requirements.',
    lines: [
      [[20, 88], [20, 42]], [[180, 88], [180, 42]],
      [[20, 42], [100, 18]], [[100, 18], [180, 42]],
    ],
  },
  {
    name: 'Rigid Frame Multi-Span',
    tag: "up to 400'",
    blurb: "The most economical cost per square foot of coverage once spans over 80' are required and interior column supports are not objectionable. Available up to 400' with multiple interior column spacing.",
    lines: [
      [[20, 88], [20, 48]], [[180, 88], [180, 48]],
      [[20, 48], [100, 20]], [[100, 20], [180, 48]],
      [[73, 88], [73, 29.4]], [[127, 88], [127, 29.4]],
    ],
  },
  {
    name: 'Single Slope',
    tag: 'no ridge',
    blurb: 'One continuous slope. A wide range of uses, from shopping centers to large office complexes, and with fascia systems and parapet walls it gives exquisite building lines. Also used as a wing unit or an addition onto an existing building.',
    lines: [
      [[20, 88], [20, 24]], [[180, 88], [180, 56]],
      [[20, 24], [180, 56]],
    ],
  },
  {
    name: 'Lean-To',
    tag: 'attached',
    blurb: "Partially supported by another structure. Designed in alongside the main building or added later as a future addition, open or enclosed, for extra covered space off an existing wall.",
    lines: [
      [[20, 88], [20, 44]], [[110, 88], [110, 44]],
      [[20, 44], [65, 20]], [[65, 20], [110, 44]],
      [[110, 46], [185, 64]], [[185, 64], [185, 88]],
    ],
  },
];

const FrameSection = ({ lines }) => (
  <svg viewBox="0 0 200 100" width="100%" aria-hidden="true" style={{ display: 'block' }}>
    {/* grade line */}
    <line x1="8" y1="88" x2="192" y2="88" stroke="var(--fg-faint)" strokeWidth="1" opacity="0.5" />
    {lines.map((l, i) => (
      <line key={i} x1={l[0][0]} y1={l[0][1]} x2={l[1][0]} y2={l[1][1]}
        stroke="var(--accent)" strokeWidth="2.2" strokeLinecap="square" />
    ))}
  </svg>
);

const FrameTypes = () => (
  <section className="section" style={{ borderTop: '1px solid var(--border)' }}>
    <div className="page">
      <SectionEyebrow id="FIG. 02" label="Frame types" />
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'end', flexWrap: 'wrap', gap: 24 }}>
        <h2 style={{ maxWidth: 640 }}>Frame types.</h2>
        <span className="mono" style={{ fontSize: 10, color: 'var(--fg-faint)', letterSpacing: '0.08em' }}>
          SECTION VIEW · SCHEMATIC
        </span>
      </div>
      <p style={{ marginTop: 20, maxWidth: 640, fontSize: 16, color: 'var(--fg-dim)' }}>
        Which frame you want comes down to how wide the building is and whether you
        can live with columns in the middle of the floor.
      </p>

      <div className="mob-stack" style={{
        marginTop: 48,
        display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 0,
        border: '1px solid var(--border)', background: 'var(--bg-card)',
      }}>
        {FRAME_TYPES.map((f, i) => (
          <div key={f.name} className="lift" style={{
            padding: 32,
            borderRight: (i % 2 === 0) ? '1px solid var(--border)' : 'none',
            borderBottom: i < 2 ? '1px solid var(--border)' : 'none',
          }}>
            <FrameSection lines={f.lines} />
            <div className="mono" style={{
              marginTop: 20, fontSize: 10, letterSpacing: '0.08em', color: 'var(--fg-faint)',
              display: 'flex', justifyContent: 'space-between',
            }}>
              <span><span style={{ color: 'var(--accent)' }}>{String(i + 1).padStart(2, '0')}</span> · FRAME</span>
              <span style={{ color: 'var(--accent)' }}>{f.tag}</span>
            </div>
            <h3 className="cap-card-title" style={{ marginTop: 12 }}>{f.name}</h3>
            <p style={{ marginTop: 12, fontSize: 14, lineHeight: 1.55, color: 'var(--fg-dim)' }}>{f.blurb}</p>
          </div>
        ))}
      </div>
    </div>
  </section>
);

//. BUILD ENVELOPE - brochure pp. 3, 11 ,
// The strongest trust signals in the whole brochure and they appear nowhere on
// the site, so they get a strip of their own rather than a line of body copy.
const ENVELOPE = [
  { fig: '200', unit: 'MPH', label: 'Wind rating', note: 'We build for the coastal counties that see hurricanes.' },
  { fig: '1-4', unit: 'ZONES', label: 'Seismic', note: 'Equipped to engineer for seismic zones 1 through 4.' },
  { fig: '400', unit: 'FT', label: 'Max span', note: 'Multi-span with interior columns. 200 ft clear span.' },
  { fig: '40', unit: 'YR', label: 'Panel warranty', note: 'Against rusting, fading, and chalking.' },
];

const BuildEnvelope = () => (
  <section className="section" style={{ borderTop: '1px solid var(--border)' }}>
    <div className="page">
      <SectionEyebrow label="What it stands up to" />
      <h2 style={{ maxWidth: 720 }}>What it's rated for.</h2>
      <p style={{ marginTop: 20, maxWidth: 640, fontSize: 16, color: 'var(--fg-dim)' }}>
        Every building leaves here with a complete set of drawings ready to submit for your
        building permit. Our team knows the codes and the regulations, so what shows up on
        site is safe, compliant, and inspectable.
      </p>

      <div className="mob-2col" style={{
        marginTop: 48,
        display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 0,
        border: '1px solid var(--border)', background: 'var(--bg-card)',
      }}>
        {ENVELOPE.map((e, i) => (
          <div key={e.label} style={{
            padding: 28,
            borderRight: i < ENVELOPE.length - 1 ? '1px solid var(--border)' : 'none',
            display: 'flex', flexDirection: 'column', gap: 10,
          }}>
            <div style={{ display: 'flex', alignItems: 'baseline', gap: 6 }}>
              {/* nowrap: "1-4" is a range, and browsers will happily break a
                  line straight after the hyphen once the column gets narrow. */}
              <span className="mono" style={{ fontSize: 38, lineHeight: 1, color: 'var(--fg)', whiteSpace: 'nowrap' }}>{e.fig}</span>
              <span className="mono" style={{ fontSize: 12, color: 'var(--accent)', letterSpacing: '0.08em' }}>{e.unit}</span>
            </div>
            <div className="mono" style={{ fontSize: 10, letterSpacing: '0.08em', color: 'var(--fg-faint)', textTransform: 'uppercase' }}>
              {e.label}
            </div>
            <p style={{ margin: 0, fontSize: 13, lineHeight: 1.5, color: 'var(--fg-dim)' }}>{e.note}</p>
          </div>
        ))}
      </div>

      <div className="mono" style={{ marginTop: 14, fontSize: 10, color: 'var(--fg-faint)', letterSpacing: '0.08em' }}>
        PERMIT-READY DRAWING SET INCLUDED WITH EVERY BUILDING
      </div>
    </div>
  </section>
);

//. ASSEMBLY / TRIM & CLOSURES - brochure p. 4 "Basic Design" ,
// The brochure's most useful page and the one that had never made it onto the
// site: the seven pieces that turn a bare frame plus flat panels into a sealed
// building. Each blurb is the brochure's own text, condensed.
//
// One naming fix: the brochure prints the rake-trim description under a
// heading that reads "Roof Panels". It is describing the rake trim - it says so
// in the sentence - so it is labelled Rake Trim here.
//
// The drawings are schematic details, not shop drawings. They exist so the
// names attach to a shape; the point of the section is the seven names.

// Square-wave rib profile - the section you'd see cutting across a steel panel.
// `n` full ribs between x0 and x1, standing `h` proud of baseline `y`.
const ribWave = (x0, x1, y, h, n) => {
  const step = (x1 - x0) / n;
  let d = `M${x0} ${y}`;
  for (let i = 0; i < n; i++) {
    const a = x0 + i * step;
    d += ` L${(a + step * 0.28).toFixed(1)} ${y}`
      + ` L${(a + step * 0.38).toFixed(1)} ${y - h}`
      + ` L${(a + step * 0.62).toFixed(1)} ${y - h}`
      + ` L${(a + step * 0.72).toFixed(1)} ${y}`;
  }
  return `${d} L${x1} ${y}`;
};

// Evenly spaced tick marks along a line, used to read "ribbed panel" on a plane
// that is drawn as an outline rather than a profile.
const ribTicks = (x0, y0, x1, y1, n, len) => {
  const dx = (x1 - x0) / (n + 1), dy = (y1 - y0) / (n + 1);
  return Array.from({ length: n }, (_, i) => {
    const px = x0 + dx * (i + 1), py = y0 + dy * (i + 1);
    return [px, py, px, py + len];
  });
};

const FAINT = { stroke: 'var(--fg-faint)', strokeWidth: 1, opacity: 0.55, fill: 'none' };
const ACCENT = { stroke: 'var(--accent)', strokeWidth: 2.4, fill: 'none', strokeLinejoin: 'round', strokeLinecap: 'round' };

// One detail per trim piece. Faint geometry is the building; the accent stroke
// is the piece being named.
const TRIM_DETAILS = {
  ridge: (
    <g>
      <path d="M14 62 L70 32" {...FAINT} />
      <path d="M70 32 L126 62" {...FAINT} />
      {ribTicks(20, 59, 64, 35, 4, 5).map((t, i) => <line key={`l${i}`} x1={t[0]} y1={t[1]} x2={t[2]} y2={t[3]} {...FAINT} />)}
      {ribTicks(76, 35, 120, 59, 4, 5).map((t, i) => <line key={`r${i}`} x1={t[0]} y1={t[1]} x2={t[2]} y2={t[3]} {...FAINT} />)}
      {/* Sits ON the ridge, overlapping both slopes, which is what it does. */}
      <path d="M54 41 L70 27 L86 41" {...ACCENT} />
    </g>
  ),
  peakbox: (
    <g>
      <path d="M22 68 L70 34 L118 68" {...FAINT} />
      <path d="M22 68 L118 68" {...FAINT} />
      <path d="M36 68 L70 44 L104 68" {...FAINT} />
      {/* Straddles the apex, covering where the two rakes meet. */}
      <rect x="59" y="27" width="22" height="16" rx="1.5" {...ACCENT} />
    </g>
  ),
  rake: (
    <g>
      <path d="M24 68 L24 44 L118 22 L118 68 Z" {...FAINT} />
      {[40, 56, 72, 88, 104].map((x) => (
        <line key={x} x1={x} y1={68} x2={x} y2={44 - (x - 24) * 0.234} {...FAINT} />
      ))}
      <path d="M20 46 L122 22" {...ACCENT} />
    </g>
  ),
  // An OUTSIDE corner: the corner edge is nearest the viewer and both wall
  // planes recede away from it. That is the corner this trim goes on.
  corner: (
    <g>
      <path d="M70 40 L26 26 L26 62 L70 78 Z" {...FAINT} />
      <path d="M70 40 L114 26 L114 62 L70 78 Z" {...FAINT} />
      {[40, 54].map((x) => <line key={`a${x}`} x1={x} y1={26 + (x - 26) * 0.318} x2={x} y2={62 + (x - 26) * 0.364} {...FAINT} />)}
      {[86, 100].map((x) => <line key={`b${x}`} x1={x} y1={40 - (x - 70) * 0.318} x2={x} y2={78 - (x - 70) * 0.364} {...FAINT} />)}
      <path d="M70 40 L70 78" {...ACCENT} />
    </g>
  ),
  // Eave detail. The trough is drawn as an open-top U channel rather than in
  // the axo: at this size a tilted quadrilateral reads as nothing at all.
  gutter: (
    <g>
      <path d="M16 22 L112 46" {...FAINT} />
      {ribTicks(22, 23.5, 104, 44, 4, 5).map((t, i) => <line key={i} x1={t[0]} y1={t[1]} x2={t[2]} y2={t[3]} {...FAINT} />)}
      <path d="M30 62 L84 62 L84 84 L30 84 Z" {...FAINT} />
      {[44, 58, 72].map((x) => <line key={x} x1={x} y1={62} x2={x} y2={84} {...FAINT} />)}
      <path d="M86 44 L86 62 L110 62 L110 48" {...ACCENT} />
    </g>
  ),
  base: (
    <g>
      <path d="M24 18 L116 18 L116 56 L24 56 Z" {...FAINT} />
      {[40, 56, 72, 88, 102].map((x) => <line key={x} x1={x} y1={18} x2={x} y2={56} {...FAINT} />)}
      <path d="M18 72 L122 72" {...FAINT} />
      <path d="M20 56 L120 56 L120 64 L20 64 Z" {...ACCENT} />
    </g>
  ),
  closure: (
    <g>
      <path d={ribWave(20, 120, 40, 14, 4)} {...FAINT} />
      <path d="M20 62 L120 62" {...FAINT} />
      <path d={`${ribWave(20, 120, 56, 14, 4)} L120 62 L20 62 Z`} {...ACCENT} fill="var(--accent)" fillOpacity="0.14" />
    </g>
  ),
};

const TrimDetail = ({ kind }) => (
  <svg viewBox="0 0 140 86" width="100%" aria-hidden="true" style={{ display: 'block' }}>
    {TRIM_DETAILS[kind]}
  </svg>
);

const TRIM_PIECES = [
  { kind: 'ridge', name: 'Ridge Cap', tag: 'PEAK',
    blurb: 'Die-cut and form-fitting, in the same profile as our roof panel. It ties the roof panels together at the peak and covers the peak of the building.' },
  { kind: 'peakbox', name: 'Peak Box', tag: 'PEAK',
    blurb: 'Covers the rake trim where it meets at the peak of the building, so the top of the gable closes out clean instead of in a raw joint.' },
  { kind: 'rake', name: 'Rake Trim', tag: 'ENDWALL',
    blurb: 'Runs the slope of the endwall and connects the roof and wall panels where they meet at the gable.' },
  { kind: 'corner', name: 'Corner Trim', tag: 'CORNERS',
    blurb: 'Connects the wall panels at the corners of the building and gives the vertical edge a finished line.' },
  { kind: 'gutter', name: 'Gutters', tag: 'EAVE',
    blurb: 'Keeps water away from the building. Our contoured fitting gutter system doubles as an attractive contoured trim along the eaves.' },
  { kind: 'base', name: 'Base Trim', tag: 'BASE',
    blurb: 'Together with the base angle it forms a tight seal, keeping out water, dirt and critters. It also makes erection easier and faster, and it looks better than the alternative.' },
  { kind: 'closure', name: 'Foam Closures', tag: 'SEALS',
    blurb: 'Custom cut to our panel profile so they fill every rib. They form an air-tight seal at the eave, ridge and base, keeping out water, dirt and critters.' },
];

const Assembly = () => (
  <section className="section" style={{ borderTop: '1px solid var(--border)' }}>
    <div className="page">
      <SectionEyebrow id="FIG. 04" label="Basic design" />
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'end', flexWrap: 'wrap', gap: 24 }}>
        <h2 style={{ maxWidth: 700 }}>Trim and closures.</h2>
        <span className="mono" style={{ fontSize: 10, color: 'var(--fg-faint)', letterSpacing: '0.08em' }}>
          DETAIL · SCHEMATIC
        </span>
      </div>
      <p style={{ marginTop: 20, maxWidth: 660, fontSize: 16, color: 'var(--fg-dim)' }}>
        A steel building is a frame, flat panels, and about seven small pieces that keep the
        weather out. This is how the system fits together, and these details are where the
        quality of a building shows.
      </p>

      <div className="mob-2col" style={{
        marginTop: 48,
        display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 0,
        border: '1px solid var(--border)', background: 'var(--bg-card)',
      }}>
        {TRIM_PIECES.map((p, i) => (
          <div key={p.name} className="lift" style={{
            padding: 24,
            borderRight: (i % 4 !== 3) ? '1px solid var(--border)' : 'none',
            borderBottom: i < 4 ? '1px solid var(--border)' : 'none',
            display: 'flex', flexDirection: 'column', gap: 12,
          }}>
            <TrimDetail kind={p.kind} />
            <div className="mono" style={{ fontSize: 10, letterSpacing: '0.08em', color: 'var(--fg-faint)' }}>
              <span style={{ color: 'var(--accent)' }}>{String(i + 1).padStart(2, '0')}</span> · {p.tag}
            </div>
            <h3 className="cap-card-title">{p.name}</h3>
            <p style={{ margin: 0, fontSize: 13.5, lineHeight: 1.55, color: 'var(--fg-dim)' }}>{p.blurb}</p>
          </div>
        ))}
        {/* Eighth cell of a 4-across grid: the takeaway, rather than a hole in
            the border grid where a card would be. */}
        <div style={{ padding: 24, display: 'flex', flexDirection: 'column', justifyContent: 'center', gap: 12 }}>
          <div className="mono" style={{ fontSize: 10, letterSpacing: '0.08em', color: 'var(--accent)' }}>
            WHY IT MATTERS
          </div>
          <p style={{ margin: 0, fontSize: 13.5, lineHeight: 1.6, color: 'var(--fg-dim)' }}>
            Every one of these is die-formed to our own panel profile, and every one of them
            ships as part of your building. These are the pieces many metal building companies
            treat as optional. We do not.
          </p>
        </div>
      </div>
    </div>
  </section>
);

//. PANELS, COLOR & WAINSCOT - brochure pp. 6, 12 ,
// Moved here from services.jsx (Jul 2026) and expanded with brochure p. 6,
// which the Services version never covered: the deck panel, and the fact that
// every panel is offered in bare Galvalume as well as the color chart.
//
// NAMING: the brochure calls its wall/roof panel the "Multi-Purpose Xtra Rib",
// and p. 11 explicitly sells against "the standard 'R' or 'PBR' panels which
// most companies use". The old Services copy called it "PBR panel ... what most
// of our buildings wear", which contradicted the client's own brochure on their
// own site. The brochure name leads here, with the PBR profile named after it
// so the page and the quote form (quote.jsx offers 'PBR' / 'Standing Seam')
// still line up. Flagged for Brad.
//
// BRANDING: GenStone is still named, and linked, but it no longer leads. The
// heading and the eyebrow describe the product category ("manufactured stone",
// "without the mason") and the brand lands once at the end of the copy in a
// <SupplierNote>. Same treatment on the door block below. Naming the supplier
// is worth doing (customers ask for it by name off a finished job), but the
// old version read like GenStone's own page instead of ours.
const PANEL_SYSTEMS = [
  {
    tag: 'WALLS & ROOF',
    title: 'Multi-Purpose Xtra Rib',
    blurb: 'The workhorse. An extremely popular exposed-fastener ribbed panel used on both roof and walls, ' +
           '26 gauge in Grade 80 and Grade 50, on the PBR profile. Bare Galvalume or any color on the chart below.',
  },
  {
    tag: 'ROOF',
    title: 'Standing Seam',
    blurb: 'Concealed-fastener roof panel with no exposed screws to back out over time. Watertight, and the ' +
           'upgrade for high-profile projects that want the longest-lived roof and the cleanest lines.',
  },
  {
    tag: 'MEZZANINE',
    title: 'Deck Panel',
    blurb: 'Used primarily as the floor deck on mezzanines, in 22 and 24 gauge. It can also run as roof ' +
           'paneling. This panel makes a second level inside the building possible.',
  },
  {
    tag: 'BARE',
    title: 'Galvalume',
    blurb: 'Unpainted aluminum-zinc coated steel, available on any of our panel profiles. The value ' +
           'option. It reflects heat well, and it is a common choice for ag and storage roofs.',
  },
];

// Our own paperwork, shipped in assets/pdf/ so a visitor can check the panel
// gauge, trims and colors against the source rather than taking the page's word
// for it. The color chart is page 12 of the brochure, pulled out on its own so
// the link goes straight to the swatches instead of a 4 MB download.
const FINISH_PDFS = [
  { href: 'assets/pdf/chambliss-panel-color-chart.pdf', label: 'Panel color chart' },
  { href: 'assets/pdf/chambliss-building-brochure.pdf', label: 'Building brochure' },
];

// Photos off our own jobs, under assets/img/wainscot/.
const WAINSCOT_SHOTS = [
  {
    src: 'assets/img/wainscot/genstone-charcoal-dusk.jpg',
    label: 'Charcoal ribbed steel sidewall over gray stacked-stone wainscot at dusk',
    cap: 'CHARCOAL WALLS · GRAY STACKED STONE',
  },
  {
    src: 'assets/img/wainscot/genstone-gray-sidewall.jpg',
    label: 'Gray steel sidewall with stacked-stone wainscot running the full length',
    cap: 'FULL-LENGTH WAINSCOT · TRIM CAP',
  },
  {
    src: 'assets/img/wainscot/genstone-porch-column.jpg',
    label: 'Dark steel entry wall with stone wainscot and a matching wrapped stone column',
    cap: 'WRAPPED COLUMNS · MATCHED WAINSCOT',
  },
  {
    src: 'assets/img/wainscot/genstone-rollup-doors.jpg',
    label: 'Light sidewall with charcoal roll-up doors and dark stone wainscot at the column bases',
    cap: 'DARK STONE · COLUMN BASES ONLY',
  },
  {
    src: 'assets/img/wainscot/genstone-delivery.jpg',
    label: 'A trailer load of stone panel boxes delivered to a Chambliss job site',
    cap: 'WE STOCK IT · DELIVERED TO SITE',
  },
];

const Panels = ({ setRoute }) => (
  <section className="section" style={{ borderTop: '1px solid var(--border)' }}>
    <div className="page">
      <SectionEyebrow id="FIG. 05" label="Panels, color & wainscot" />
      <h2 style={{ maxWidth: 760 }}>Siding, color, and wainscot.</h2>
      <p style={{ marginTop: 16, maxWidth: 640, fontSize: 16, color: 'var(--fg-dim)' }}>
        Two buildings can be framed identically and look nothing alike. The panel system,
        the color, and the wainscot are where a steel building stops looking like a shop
        and starts looking like it belongs on your property.
      </p>

      {/* Panel systems, off brochure p. 6 */}
      <div style={{ marginTop: 48 }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', flexWrap: 'wrap', gap: 12, marginBottom: 14 }}>
          <span className="mono" style={{ fontSize: 11, color: 'var(--fg-faint)', letterSpacing: '0.08em', textTransform: 'uppercase' }}>
            Panel systems &amp; siding
          </span>
          <span className="mono" style={{ fontSize: 10, color: 'var(--fg-faint)', letterSpacing: '0.06em' }}>
            BARE GALVALUME OR COLOR ON ALL THREE
          </span>
        </div>
        <div className="mob-2col" style={{
          display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 0,
          border: '1px solid var(--border)', background: 'var(--bg-card)',
        }}>
          {PANEL_SYSTEMS.map((p, i) => (
            <div key={p.title} style={{
              padding: 24,
              borderRight: i < PANEL_SYSTEMS.length - 1 ? '1px solid var(--border)' : 'none',
              display: 'flex', flexDirection: 'column', gap: 10,
            }}>
              <div className="mono" style={{ fontSize: 10, letterSpacing: '0.08em', color: 'var(--accent)' }}>
                {p.tag}
              </div>
              <h3 className="cap-card-title">{p.title}</h3>
              <p style={{ fontSize: 14, lineHeight: 1.5, color: 'var(--fg-dim)' }}>{p.blurb}</p>
            </div>
          ))}
        </div>
      </div>

      {/* The wainscot, led by what it is rather than who makes it. */}
      <div className="mob-stack" style={{
        marginTop: 56, display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 0,
        border: '1px solid var(--border)', background: 'var(--bg-card)',
      }}>
        <div style={{ padding: 48, borderRight: '1px solid var(--border)' }}>
          <span className="mono" style={{ fontSize: 11, color: 'var(--accent)', letterSpacing: '0.08em' }}>
            WAINSCOT
          </span>
          <h3 className="featured-row-title" style={{ marginTop: 16 }}>
            A finished base<br />for your walls.
          </h3>
          <p style={{ marginTop: 16, fontSize: 15, lineHeight: 1.55, color: 'var(--fg-dim)' }}>
            Wainscot is the band that runs along the bottom of the wall. Manufactured stone is
            one of the options. It installs like siding, fastening straight to the wall with no
            mortar, no wire lath, and no mason on the schedule. It holds up well to Florida sun
            and salt air.
          </p>
          <p style={{ marginTop: 14, fontSize: 15, lineHeight: 1.55, color: 'var(--fg-dim)' }}>
            We supply it and we install it. Run it along the base of the walls, the full length
            of a sidewall, around porch columns, or up an entire gable end.
          </p>
          <SupplierNote
            href="https://www.genstone.com"
            brand="GenStone®"
            lead="The panel we buy, stock and install is"
            tail="Customers tend to ask for it by name once they've seen it on a finished job."
          />
          <div style={{ marginTop: 24, display: 'flex', gap: 8, flexWrap: 'wrap' }}>
            <span className="pill"><span className="led"></span>Supplied &amp; installed</span>
            <span className="pill">No mortar</span>
            <span className="pill">Stacked stone profile</span>
            <span className="pill">Columns &amp; gable ends</span>
          </div>
          {/* Our own paperwork: the numbers on this page come off these two, so
              they sit with the copy rather than being buried in a footer. */}
          <div style={{ marginTop: 28, display: 'flex', gap: 10, flexWrap: 'wrap' }}>
            {FINISH_PDFS.map(p => (
              <a key={p.href} href={p.href} target="_blank" rel="noopener noreferrer" className="btn">
                {p.label}
                <svg width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true"><path d="M6 2 L6 8 M3 5.5 L6 8.5 L9 5.5 M2 10.5 L10 10.5" stroke="currentColor" strokeWidth="1.5" /></svg>
              </a>
            ))}
          </div>

          <div style={{ marginTop: 20 }}>
            <button className="btn" onClick={() => setRoute('quote')}>
              Spec a wainscot on your build
              <svg width="12" height="12" viewBox="0 0 12 12" fill="none"><path d="M3 6 L9 6 M6 3 L9 6 L6 9" stroke="currentColor" strokeWidth="1.6" /></svg>
            </button>
          </div>
        </div>
        <SpecMedia src={WAINSCOT_SHOTS[0].src} label={WAINSCOT_SHOTS[0].label} cap={WAINSCOT_SHOTS[0].cap} />
      </div>

      {/* Wainscot on our jobs */}
      <div style={{ marginTop: 32 }}>
        <span className="mono" style={{ display: 'block', marginBottom: 14, fontSize: 11, color: 'var(--fg-faint)', letterSpacing: '0.08em', textTransform: 'uppercase' }}>
          Wainscot on our buildings
        </span>
        <div className="mob-2col" style={{
          display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 0,
          border: '1px solid var(--border)', background: 'var(--bg-card)',
        }}>
          {/* [0] is already the hero shot in the panel above. */}
          {WAINSCOT_SHOTS.slice(1).map((s, i) => (
            <div key={s.src} style={{
              display: 'flex', flexDirection: 'column',
              borderRight: i < WAINSCOT_SHOTS.length - 2 ? '1px solid var(--border)' : 'none',
            }}>
              <ImgSlot
                src={s.src}
                label={s.label}
                height={240}
                style={{ border: 'none', borderBottom: '1px solid var(--border)' }}
              />
              <div className="mono" style={{ padding: '14px 20px', fontSize: 10, letterSpacing: '0.08em', color: 'var(--fg-faint)' }}>
                {s.cap}
              </div>
            </div>
          ))}
        </div>
      </div>

      {/* Color chart, same palette the quote form shows */}
      <div style={{ marginTop: 56, padding: 24, border: '1px solid var(--border)', background: 'var(--bg-card)' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', flexWrap: 'wrap', gap: 12, marginBottom: 20 }}>
          <span className="mono" style={{ fontSize: 11, color: 'var(--fg-faint)', letterSpacing: '0.08em', textTransform: 'uppercase' }}>
            Standard panel colors
          </span>
          <span className="mono" style={{ fontSize: 10, color: 'var(--fg-faint)', letterSpacing: '0.06em' }}>
            26 GA, GRADE 80 &amp; 50 · OTHER COLORS ON REQUEST
          </span>
        </div>
        <div className="mob-4col" style={{ display: 'grid', gridTemplateColumns: 'repeat(8, 1fr)', gap: 8 }}>
          {STEEL_COLORS.map(([c, n]) => (
            <div key={n} style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
              <div style={{ height: 48, background: c, border: '1px solid var(--border)' }}></div>
              <span className="mono" style={{ fontSize: 9, color: 'var(--fg-dim)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>{n}</span>
            </div>
          ))}
        </div>
        <p style={{ marginTop: 20, fontSize: 13.5, lineHeight: 1.55, color: 'var(--fg-dim)', maxWidth: 720 }}>
          Roof, walls, wainscot band and trim are all specified separately, so you can run a
          light stone wall over a charcoal wainscot cap, match the trim to the roof, or keep
          the whole envelope one color. Bring us a photo of a building you like and we'll tell
          you what it's wearing. Final color selection should be made off actual chips, not a
          screen.
        </p>
        {/* SR / SRI. The brochure's color chart carries the definitions and the
            thresholds but publishes no per-color values, so this says what the
            numbers are for and tells you to ask - it does not claim compliance
            for any specific color. Do not add values here without the mill data. */}
        <div style={{ marginTop: 24, paddingTop: 20, borderTop: '1px solid var(--border)' }}>
          <span className="mono" style={{ display: 'block', marginBottom: 12, fontSize: 10, color: 'var(--accent)', letterSpacing: '0.08em' }}>
            SOLAR REFLECTANCE · FOR ENERGY STAR &amp; LEED PROJECTS
          </span>
          <div className="mob-stack" style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 28 }}>
            <p style={{ margin: 0, fontSize: 12.5, lineHeight: 1.55, color: 'var(--fg-faint)' }}>
              <strong style={{ color: 'var(--fg-dim)', fontWeight: 500 }}>SR</strong> is how much
              solar energy the surface reflects, 0 to 1.0. ENERGY STAR wants 0.25 or higher on
              steep-slope roofing (above 2:12) and 0.65 or higher on low-slope (2:12 or less).
            </p>
            <p style={{ margin: 0, fontSize: 12.5, lineHeight: 1.55, color: 'var(--fg-faint)' }}>
              <strong style={{ color: 'var(--fg-dim)', fontWeight: 500 }}>SRI</strong> is
              calculated per ASTM E 1980 from reflectance and emissivity, and it is what LEED
              is scored on: 29 or greater steep-slope, 78 or higher low-slope.
            </p>
          </div>
        </div>
      </div>
    </div>
  </section>
);

//. DOORS / OPENINGS - brochure p. 9 ,
// Moved here from services.jsx (Jul 2026).
// BRANDING: same treatment as the wainscot block, the heading sells the
// property that matters here (it passes the wind load), and Janus and the 3652
// Commercial are credited once, linked, in the <SupplierNote> under the copy.
// The spec numbers below are off the 3652 sheet, which ships in assets/pdf/ so
// anyone can check them; the color tiers are Janus's own.
const DOOR_SPECS = [
  { k: 'MAX OPENING', v: '18′ × 14′' },
  { k: 'CURTAIN', v: '26-ga corrugated' },
  { k: 'STEEL', v: 'Galvanized grade-80' },
  { k: 'COLORS', v: '32, in 5 tiers' },
];

const DOOR_PDFS = [
  { href: 'assets/pdf/janus-3652-commercial-door.pdf', label: 'Door spec sheet' },
  { href: 'assets/pdf/janus-door-color-chart.pdf', label: 'Full color chart' },
];

const DoorSwatchGroup = ({ group }) => (
  <div style={{ marginTop: 24 }}>
    <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', flexWrap: 'wrap', gap: 10, marginBottom: 12 }}>
      <span className="mono" style={{ fontSize: 10, letterSpacing: '0.08em', textTransform: 'uppercase', color: 'var(--accent)' }}>
        {group.tier}
      </span>
      <span className="mono" style={{ fontSize: 10, letterSpacing: '0.06em', textTransform: 'uppercase', color: 'var(--fg-faint)' }}>
        {group.note}
      </span>
    </div>
    <div className="mob-4col" style={{ display: 'grid', gridTemplateColumns: 'repeat(8, 1fr)', gap: 8 }}>
      {group.colors.map(([c, n, texture]) => (
        <div key={n} style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
          <div style={{ height: 48, background: c, border: '1px solid var(--border)' }}></div>
          <span className="mono" style={{ fontSize: 9, color: 'var(--fg-dim)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>
            {n}{texture ? ' *' : ''}
          </span>
        </div>
      ))}
    </div>
  </div>
);

const Doors = ({ setRoute }) => (
  <section className="section" style={{ borderTop: '1px solid var(--border)' }}>
    <div className="page">
      <SectionEyebrow id="FIG. 06" label="Doors" />
      <h2 style={{ maxWidth: 760 }}>Doors and colors.</h2>
      <p style={{ marginTop: 16, maxWidth: 640, fontSize: 16, color: 'var(--fg-dim)' }}>
        A door is the part of the building you touch every day. Here is what we hang and what
        you get to pick.
      </p>

      {/* The roll-up, led by the rating. Same treatment the wainscot gets. */}
      <div className="mob-stack" style={{
        marginTop: 48, display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 0,
        border: '1px solid var(--border)', background: 'var(--bg-card)',
      }}>
        <div style={{ padding: 48, borderRight: '1px solid var(--border)' }}>
          <span className="mono" style={{ fontSize: 11, color: 'var(--accent)', letterSpacing: '0.08em' }}>
            ROLL-UP DOORS · WINDLOAD RATED
          </span>
          <h3 className="featured-row-title" style={{ marginTop: 16 }}>
            Roll-up doors that<br />pass the wind load.
          </h3>
          <p style={{ marginTop: 16, fontSize: 15, lineHeight: 1.55, color: 'var(--fg-dim)' }}>
            The door we hang on most buildings is a rolling sheet door that is{' '}
            <strong style={{ color: 'var(--fg)', fontWeight: 500 }}>certified windload
            rated</strong>. That matters here. It is what lets the opening meet Florida wind
            code, instead of becoming the weak spot in an otherwise rated building.
          </p>
          <p style={{ marginTop: 14, fontSize: 15, lineHeight: 1.55, color: 'var(--fg-dim)' }}>
            The curtain is 26-gauge corrugated galvanized steel in a super-durable polyester
            finish. The springs are pre-lubricated and sealed in a tube, so weather never
            reaches them. The axle runs in an enclosed spiral barrel, which spreads the
            curtain weight instead of loading one point. Insulated versions add side and top
            draft stops. Vision panels are an option if you want daylight through a closed door.
          </p>
          <p style={{ marginTop: 14, fontSize: 15, lineHeight: 1.55, color: 'var(--fg-dim)' }}>
            We order it, we hang it, and we set it up as part of the build. For openings wider
            or taller than a roll-up will carry, we install hangar bi-folds and hydraulic doors
            up to 38,000 lb.
          </p>
          <SupplierNote
            href="https://www.janusintl.com"
            brand="Janus International®"
            lead="Our roll-up doors are made by"
            tail="The model we install on most buildings is the 3652 Commercial. Its spec sheet is below."
          />
          <div style={{ marginTop: 24, display: 'flex', gap: 8, flexWrap: 'wrap' }}>
            <span className="pill"><span className="led"></span>Supplied &amp; installed</span>
            <span className="pill">Windload rated</span>
            <span className="pill">Insulated option</span>
            <span className="pill">Vision panels</span>
          </div>

          {/* Spec strip off the 3652 sheet */}
          <div style={{
            marginTop: 28, display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)',
            gap: 0, borderTop: '1px solid var(--border)', borderLeft: '1px solid var(--border)',
          }}>
            {DOOR_SPECS.map(s => (
              <div key={s.k} style={{
                padding: '14px 16px',
                borderRight: '1px solid var(--border)', borderBottom: '1px solid var(--border)',
              }}>
                <div className="mono" style={{ fontSize: 9, letterSpacing: '0.08em', color: 'var(--fg-faint)' }}>{s.k}</div>
                <div className="mono" style={{ marginTop: 4, fontSize: 12, color: 'var(--fg)' }}>{s.v}</div>
              </div>
            ))}
          </div>

          {/* The manufacturer's own paperwork sits with the copy about the door,
              which is where someone reading it goes looking for the numbers. */}
          <div style={{ marginTop: 28, display: 'flex', gap: 10, flexWrap: 'wrap' }}>
            {DOOR_PDFS.map(p => (
              <a key={p.href} href={p.href} target="_blank" rel="noopener noreferrer" className="btn">
                {p.label}
                <svg width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true"><path d="M6 2 L6 8 M3 5.5 L6 8.5 L9 5.5 M2 10.5 L10 10.5" stroke="currentColor" strokeWidth="1.5" /></svg>
              </a>
            ))}
          </div>

          <div style={{ marginTop: 20 }}>
            <button className="btn" onClick={() => setRoute('quote')}>
              Spec your doors
              <svg width="12" height="12" viewBox="0 0 12 12" fill="none"><path d="M3 6 L9 6 M6 3 L9 6 L6 9" stroke="currentColor" strokeWidth="1.6" /></svg>
            </button>
          </div>
        </div>
        <SpecMedia
          src="assets/img/doors/janus-rollup-installed.jpg"
          label="A windload-rated roll-up door hung in a finished Chambliss steel building"
          cap="26-GA CORRUGATED CURTAIN · WINDLOAD RATED"
        />
      </div>

      {/* Door color chart, grouped by Janus's own pricing tiers */}
      <div style={{ marginTop: 32, padding: 24, border: '1px solid var(--border)', background: 'var(--bg-card)' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', flexWrap: 'wrap', gap: 12 }}>
          <span className="mono" style={{ fontSize: 11, color: 'var(--fg-faint)', letterSpacing: '0.08em', textTransform: 'uppercase' }}>
            Door colors
          </span>
        </div>
        <p style={{ marginTop: 14, fontSize: 13.5, lineHeight: 1.55, color: 'var(--fg-dim)', maxWidth: 720 }}>
          Eleven colors are standard and cost the same as any other standard color. The
          specialty colors carry an upcharge that goes up by tier.
        </p>

        {JANUS_DOOR_COLORS.map(g => (
          <DoorSwatchGroup key={g.tier} group={g} />
        ))}

        <p style={{ marginTop: 24, fontSize: 12, lineHeight: 1.5, color: 'var(--fg-faint)', maxWidth: 720 }}>
          * Galvalume and Woodgrain are finishes rather than flat colors, so the swatch above
          is an approximation. Door color is specified separately from your roof, walls and
          trim, so the doors can match the building or deliberately not.
        </p>
      </div>
    </div>
  </section>
);

//. ACCESSORIES - brochure pp. 9-10 ,
// Everything on the brochure's two accessory pages except the roll-up door,
// which has FIG. 06 to itself. Four of these (sectional overhead, walk doors,
// skylights, vents) used to appear on Services as a four-card "rest of the
// envelope" strip inside the Insulation block; they are here now, in full, with
// the insulated-version note folded into each rather than split across two
// sections.
//
// The wind-lock note on the two door types is the brochure's own claim and it
// is the one that matters most in this market, so it leads both blurbs.
const ACCESSORIES = [
  {
    tag: 'OPENINGS', title: 'Sectional overhead doors',
    blurb: 'A large variety of sizes and colors, with low-profile hardware available where headroom ' +
           'is limited. They can be designed wind-locked to meet the high wind loads of the coastal ' +
           'counties, and insulation can be added as an option.',
  },
  {
    tag: 'OPENINGS', title: 'Walk & passage doors',
    blurb: 'Single or double, solid or half glass. Our standard door is pre-finished commercial ' +
           'bronze with solid core insulation and a complete hardware package, and wind-rated doors ' +
           'are available for high wind load counties. We carry the full hardware line.',
  },
  {
    tag: 'DAYLIGHT', title: 'Skylights & wall lights',
    blurb: 'Fiberglass translucent panels light the building through the roof or the walls with no ' +
           'power bill. Each panel is 3′ wide and comes in various lengths. Insulated skylights are ' +
           'also an option, so the daylight does not cost you the R-value around it.',
  },
  {
    tag: 'GLAZING', title: 'Sliding glass windows',
    blurb: 'Windows come complete with framing and flashing in a large variety of sizes, in vertical ' +
           'and horizontal sliders. Double pane glass is available as an option.',
  },
  {
    tag: 'SHADE', title: 'Canopies',
    blurb: 'Custom and standard canopies over windows, walkways and doors. They distinguish the ' +
           'building and can be run in a contrasting color to set them off, in a wide range of ' +
           'shapes, sizes and colors.',
  },
  {
    tag: 'AIRFLOW', title: 'Ridge vents',
    blurb: 'We carry several types. The common options are the continuous ridge vent and the ' +
           'low-profile ridge vent, both running the length of the peak where the hot air collects.',
  },
  {
    tag: 'AIRFLOW', title: 'Louver & circular vents',
    blurb: 'Fixed louvers in various sizes and colors are often the only ventilation possible on a ' +
           'smaller building, and are best used to generate cross-flow on a larger one. Circular ' +
           'roof vents are the economical way to move air out through the roof.',
  },
  {
    tag: 'DETAIL', title: 'Cupolas',
    blurb: 'Available in 24″, 36″ and 48″, louvered-sided or window-sided, in a variety of colors ' +
           'including two-tone. Cupolas add ventilation, and they add both beauty and ' +
           'individuality to your building.',
  },
];

const Accessories = ({ setRoute }) => (
  <section className="section" style={{ borderTop: '1px solid var(--border)' }}>
    <div className="page">
      <SectionEyebrow id="FIG. 07" label="Accessories" />
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'end', flexWrap: 'wrap', gap: 24 }}>
        <h2 style={{ maxWidth: 700 }}>Accessories.</h2>
        <span className="mono" style={{ fontSize: 10, color: 'var(--fg-faint)', letterSpacing: '0.08em' }}>
          SUPPLIED &amp; INSTALLED
        </span>
      </div>
      <p style={{ marginTop: 20, maxWidth: 660, fontSize: 16, color: 'var(--fg-dim)' }}>
        Openings, daylight, airflow, and the finishing details. All of it is specified and
        engineered with your building rather than added afterward, so every opening is framed
        into the wall the way it was drawn.
      </p>

      <div className="mob-2col" style={{
        marginTop: 48,
        display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 0,
        border: '1px solid var(--border)', background: 'var(--bg-card)',
      }}>
        {ACCESSORIES.map((a, i) => (
          <div key={a.title} className="lift" style={{
            padding: 24,
            borderRight: (i % 4 !== 3) ? '1px solid var(--border)' : 'none',
            borderBottom: i < 4 ? '1px solid var(--border)' : 'none',
            display: 'flex', flexDirection: 'column', gap: 10,
          }}>
            <div className="mono" style={{ fontSize: 10, letterSpacing: '0.08em', color: 'var(--fg-faint)' }}>
              <span style={{ color: 'var(--accent)' }}>{String(i + 1).padStart(2, '0')}</span> · {a.tag}
            </div>
            <h3 className="cap-card-title">{a.title}</h3>
            <p style={{ margin: 0, fontSize: 13.5, lineHeight: 1.55, color: 'var(--fg-dim)' }}>{a.blurb}</p>
          </div>
        ))}
      </div>

      {/* justifyContent flex-end, not space-between: the explanatory <p> that used to
          sit on the left was removed, and the button should stay where it was. */}
      <div style={{ marginTop: 20, display: 'flex', justifyContent: 'flex-end', alignItems: 'baseline', gap: 24, flexWrap: 'wrap' }}>
        <button className="btn" onClick={() => setRoute('quote')}>
          Add these to your quote
          <svg width="12" height="12" viewBox="0 0 12 12" fill="none"><path d="M3 6 L9 6 M6 3 L9 6 L6 9" stroke="currentColor" strokeWidth="1.6" /></svg>
        </button>
      </div>
    </div>
  </section>
);

//. INSULATION / THE THERMAL ENVELOPE - brochure p. 10 ,
// Moved here from services.jsx (Jul 2026). The four-card "rest of the envelope"
// strip that used to close this section now lives in FIG. 07 above, so this
// section stays on one subject: the blanket, and how much of it.
//
// The three levels below are deliberately the same three choices the quote form
// offers (quote.jsx: 'Minimum R-Value' / 'Best R-Value' / 'None'), so someone
// who reads this page arrives at the form already knowing which one they want.
// TODO(client): Brad hasn't given us the actual R-values or the blanket/facing
// spec behind "minimum" and "best". The brochure only makes the case for
// insulating at all. Copy stays deliberately unnumbered until we have them,
// rather than publishing an R-value we'd have to walk back.
const INSULATION_LEVELS = [
  {
    tag: 'BEST R-VALUE',
    note: 'What the quote form defaults to',
    title: 'Roof and walls',
    blurb: 'The complete envelope, at the highest R-value we carry. The right choice for any ' +
           'building you plan to heat, cool, work in year round, or use to store anything ' +
           'sensitive to temperature.',
  },
  {
    tag: 'MINIMUM R-VALUE',
    title: 'The baseline package',
    blurb: 'Prevents condensation and takes the edge off the summer heat, at a lower cost than ' +
           'a fully conditioned envelope. A practical choice for equipment barns, shops and ' +
           'unconditioned storage.',
  },
  {
    tag: 'NONE',
    note: 'Open structures',
    title: 'Bare steel inside',
    blurb: 'Suited to open-sided hay barns and carports, where air moves through the building ' +
           'and there is no envelope to seal. On an enclosed building we recommend insulation, ' +
           'and we are glad to walk you through why.',
  },
];

const Insulation = ({ setRoute }) => (
  <section className="section" style={{ borderTop: '1px solid var(--border)' }}>
    <div className="page">
      <SectionEyebrow id="FIG. 08" label="Insulation" />
      <h2 style={{ maxWidth: 760 }}>Insulation.</h2>
      <p style={{ marginTop: 16, maxWidth: 640, fontSize: 16, color: 'var(--fg-dim)' }}>
        Insulation is what makes a steel building comfortable to work in and keeps your
        equipment dry. We install it as part of the build, and we will help you choose
        the right level for how you plan to use the building.
      </p>

      {/* The case for insulating, straight off the brochure. */}
      <div className="mob-stack" style={{
        marginTop: 48, display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 0,
        border: '1px solid var(--border)', background: 'var(--bg-card)',
      }}>
        <div style={{ padding: 48, borderRight: '1px solid var(--border)' }}>
          <span className="mono" style={{ fontSize: 11, color: 'var(--accent)', letterSpacing: '0.08em' }}>
            THERMAL ENVELOPE · VAPOR BARRIER
          </span>
          <h3 className="featured-row-title" style={{ marginTop: 16 }}>
            Why we recommend insulating.
          </h3>
          <p style={{ marginTop: 16, fontSize: 15, lineHeight: 1.55, color: 'var(--fg-dim)' }}>
            A non-insulated metal building will allow the outside temperature into the building.
            This can make the structure unbearably hot in the summer and very cold in the winter,
            and you pay for that difference on your heating and cooling bill for as long as you
            own the building.
          </p>
          <p style={{ marginTop: 14, fontSize: 15, lineHeight: 1.55, color: 'var(--fg-dim)' }}>
            Enclosed buildings are also susceptible to{' '}
            <strong style={{ color: 'var(--fg)', fontWeight: 500 }}>condensation</strong>. Warm,
            humid air meets cold steel, and the inside face of the roof and walls begins to sweat
            onto whatever is stored below. In our climate that is a concern most of the year.
          </p>
          <p style={{ marginTop: 14, fontSize: 15, lineHeight: 1.55, color: 'var(--fg-dim)' }}>
            Insulation reverses both effects. It keeps the heat out in the summer and the cold out
            in the winter, and it acts as a vapor barrier that prevents condensation. We install it
            at dry-in, along with the panels and the trim, as part of your building.
          </p>
          <div style={{ marginTop: 24, display: 'flex', gap: 8, flexWrap: 'wrap' }}>
            <span className="pill"><span className="led"></span>Supplied &amp; installed</span>
            <span className="pill">Vapor barrier</span>
            <span className="pill">Roof &amp; walls</span>
            <span className="pill">Goes in at dry-in</span>
          </div>

          <div style={{ marginTop: 28, display: 'flex', gap: 10, flexWrap: 'wrap' }}>
            <a href="assets/pdf/chambliss-building-brochure.pdf" target="_blank" rel="noopener noreferrer" className="btn">
              Building brochure
              <svg width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true"><path d="M6 2 L6 8 M3 5.5 L6 8.5 L9 5.5 M2 10.5 L10 10.5" stroke="currentColor" strokeWidth="1.5" /></svg>
            </a>
          </div>

          <div style={{ marginTop: 20 }}>
            <button className="btn" onClick={() => setRoute('quote')}>
              Pick your insulation level
              <svg width="12" height="12" viewBox="0 0 12 12" fill="none"><path d="M3 6 L9 6 M6 3 L9 6 L6 9" stroke="currentColor" strokeWidth="1.6" /></svg>
            </button>
          </div>
        </div>
        {/* No photo of this yet — ImgSlot shows its labelled placeholder. Keep
            the label short: the placeholder prints it in full and a long one
            runs the width of the frame. */}
        <SpecMedia
          label="Insulated liner behind the roof and wall panels"
          cap="ROOF & WALL BLANKET · GOES IN AT DRY-IN"
        />
      </div>

      {/* The three levels, same three the quote form asks for. */}
      <div style={{ marginTop: 56 }}>
        <span className="mono" style={{ display: 'block', marginBottom: 14, fontSize: 11, color: 'var(--fg-faint)', letterSpacing: '0.08em', textTransform: 'uppercase' }}>
          How much insulation
        </span>
        <div className="mob-stack" style={{
          display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 0,
          border: '1px solid var(--border)', background: 'var(--bg-card)',
        }}>
          {INSULATION_LEVELS.map((lvl, i) => (
            <div key={lvl.tag} style={{
              padding: 32,
              borderRight: i < INSULATION_LEVELS.length - 1 ? '1px solid var(--border)' : 'none',
              display: 'flex', flexDirection: 'column', gap: 12,
            }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', gap: 10, flexWrap: 'wrap' }}>
                <span className="mono" style={{ fontSize: 10, letterSpacing: '0.08em', color: 'var(--accent)' }}>
                  {lvl.tag}
                </span>
                {/* Guarded: not every level carries a note, and an empty span
                    would still consume a flex slot in the space-between row. */}
                {lvl.note && (
                  <span className="mono" style={{ fontSize: 9, letterSpacing: '0.06em', textTransform: 'uppercase', color: 'var(--fg-faint)' }}>
                    {lvl.note}
                  </span>
                )}
              </div>
              <h3 className="cap-card-title">{lvl.title}</h3>
              <p style={{ fontSize: 14, lineHeight: 1.5, color: 'var(--fg-dim)' }}>{lvl.blurb}</p>
            </div>
          ))}
        </div>
      </div>
    </div>
  </section>
);

//. STANDARD FEATURES - brochure p. 11 ,
// The brochure's own framing: these are not upsells, they are what every
// Chambliss building ships with, and several are explicitly a dig at what
// other metal building companies do instead.
const STANDARD_FEATURES = [
  { name: 'Premium Lifetime Fasteners',
    blurb: 'Matching finish, self-drilling, self-tapping, on all roof and wall panels. Guaranteed not to rust. Fasteners that are not lifetime void your warranty.' },
  { name: '40 Year Warranty',
    blurb: 'High gloss, high luster painted panels carry up to a 40 year warranty against rusting, fading, and chalking, and look far better than the standard R or PBR panels most companies use.' },
  { name: 'Formed Eave Trim',
    blurb: 'Deluxe contoured trim instead of simple eave trim, which gives the whole structure a consistent, refined finish.' },
  { name: 'Base Trim',
    blurb: 'Standard on every building. Makes erection much easier and seals better than the foam closures most metal building companies rely on to keep out dust, water, and critters.' },
  { name: 'Purlin Strapping',
    blurb: 'Included wherever it is beneficial. Greatly increases purlin strength and eliminates purlin rotation and sag.' },
  { name: 'Jamb & Header Cover Trim',
    blurb: 'On every framed opening, covering the door jambs and the header beam for a finished, sophisticated look.' },
];

const StandardFeatures = () => (
  <section className="section" style={{ borderTop: '1px solid var(--border)' }}>
    <div className="page">
      <SectionEyebrow id="FIG. 09" label="Standard, not extra" />
      <div className="mob-stack" style={{ display: 'grid', gridTemplateColumns: '1fr 1.4fr', gap: 64, alignItems: 'start' }}>
        <div>
          {/* Not "on every building": purlin strapping is conditional in the
              brochure ("when beneficial"), so an absolute heading overstates it. */}
          <h2>What comes standard.</h2>
          {/* Wording is deliberately conservative against brochure p. 11. Dropped
              "at no additional cost" (the brochure says "standard feature", never
              anything about price) and "most of them are upgrades elsewhere" (the
              brochure says competitors use a CHEAPER alternative, not that they
              charge extra for these). */}
          <p style={{ marginTop: 20, fontSize: 16, color: 'var(--fg-dim)' }}>
            Six features that come standard on a Chambliss building. Several are where
            other companies use a cheaper alternative.
          </p>
        </div>
        <div style={{ border: '1px solid var(--border)', background: 'var(--bg-card)' }}>
          {STANDARD_FEATURES.map((f, i) => (
            <div key={f.name} style={{
              padding: '20px 24px',
              borderBottom: i < STANDARD_FEATURES.length - 1 ? '1px solid var(--border)' : 'none',
              display: 'flex', gap: 16, alignItems: 'baseline',
            }}>
              <span className="mono" style={{ fontSize: 10, color: 'var(--accent)', flexShrink: 0 }}>
                {String(i + 1).padStart(2, '0')}
              </span>
              <div>
                <h3 className="cap-card-title" style={{ fontSize: 15 }}>{f.name}</h3>
                <p style={{ margin: '8px 0 0', fontSize: 13.5, lineHeight: 1.55, color: 'var(--fg-dim)' }}>{f.blurb}</p>
              </div>
            </div>
          ))}
        </div>
      </div>
    </div>
  </section>
);

//. PANEL COLOR CHART ,
// Lives in STEEL_COLORS in components.jsx, not here, so the panel chart above
// and the quote swatch row keep reading from one list. Galvalume Plus
// (#7f8d8f, an average - it prints as a texture, not a flat fill) is not in that
// list on purpose: it is a bare finish rather than a paint color and the quote
// form offers it as its own roof-color choice.

//. PAGE ,
// The sections above stay standalone so they can be reused or reordered; this
// just composes them. Anchors live on wrapper divs rather than on the sections
// themselves, so nothing here leaks page-specific ids into a reusable section.
//
// Order runs structure first (what holds it up), then envelope (what it wears),
// then what ships as standard. The jump list below is grouped the same way.
const SPECS_JUMP = [
  { href: 'envelope', label: 'What it stands up to', group: 'Structure' },
  { href: 'anatomy', label: 'Frame anatomy', group: 'Structure' },
  { href: 'frames', label: 'Frame types', group: 'Structure' },
  { href: 'roofs', label: 'Roof styles', group: 'Structure' },
  // Hidden alongside its section in <Specs> below (Jul 2026, client request).
  // { href: 'assembly', label: 'Trim & closures', group: 'Envelope' },
  { href: 'panels', label: 'Panels & color', group: 'Envelope' },
  { href: 'doors', label: 'Doors', group: 'Envelope' },
  { href: 'accessories', label: 'Accessories', group: 'Envelope' },
  { href: 'insulation', label: 'Insulation', group: 'Envelope' },
  { href: 'standard', label: 'Standard features', group: 'Included' },
];

const SPECS_JUMP_GROUPS = ['Structure', 'Envelope', 'Included'];

const SpecsHero = () => (
  <section style={{ borderBottom: '1px solid var(--border)', position: 'relative' }}>
    <div className="grid-bg" style={{
      position: 'absolute', inset: 0, opacity: 0.4,
      maskImage: 'linear-gradient(to bottom, black, transparent)',
      WebkitMaskImage: 'linear-gradient(to bottom, black, transparent)',
    }}></div>
    <div className="page" style={{ position: 'relative', paddingTop: 80, paddingBottom: 80 }}>
      <SectionEyebrow id="specs" label="How it's built" />
      <h1 style={{ maxWidth: 1000 }}>Building specs.</h1>

      {/* Jump list carries the intro's job now that the standfirst under the h1
          is gone, so it starts straight off the heading. Grouped rather than one
          undifferentiated row of chips: hold-it-up, wear-it, ships-with-it. */}
      <div style={{ marginTop: 40, display: 'flex', flexDirection: 'column', gap: 18 }}>
        {SPECS_JUMP_GROUPS.map(g => (
          <div key={g} style={{ display: 'flex', gap: 12, flexWrap: 'wrap', alignItems: 'center' }}>
            <span className="mono" style={{
              width: 78, flexShrink: 0, fontSize: 10, letterSpacing: '0.08em',
              textTransform: 'uppercase', color: 'var(--fg-faint)',
            }}>
              {g}
            </span>
            {SPECS_JUMP.filter(c => c.group === g).map(c => (
              <a
                key={c.href}
                href={`#${c.href}`}
                onClick={(e) => {
                  e.preventDefault();
                  document.getElementById(c.href)?.scrollIntoView({ behavior: 'smooth', block: 'start' });
                }}
                className="btn"
              >
                {c.label}
                <svg width="10" height="10" viewBox="0 0 10 10" fill="none"><path d="M5 2 L5 8 M2 5 L5 8 L8 5" stroke="currentColor" strokeWidth="1.5" /></svg>
              </a>
            ))}
          </div>
        ))}
      </div>
    </div>
  </section>
);

const SpecsCTA = ({ setRoute }) => (
  <section className="section" style={{ borderTop: '1px solid var(--border)' }}>
    <div className="page" style={{ textAlign: 'center' }}>
      <h2 style={{ maxWidth: 760, margin: '0 auto' }}>Know what you want?</h2>
      <p style={{ margin: '20px auto 0', maxWidth: 560, fontSize: 16, color: 'var(--fg-dim)' }}>
        Shape it in the 3D configurator, or send us your dimensions and we&rsquo;ll
        come back with a real number.
      </p>
      <div style={{ marginTop: 36, display: 'flex', gap: 12, justifyContent: 'center', flexWrap: 'wrap' }}>
        <button className="btn btn-primary btn-lg" onClick={() => setRoute('quote')}>Get a quote</button>
        <button className="btn btn-lg" onClick={() => setRoute('configurator')}>Open the configurator</button>
      </div>
      <div style={{ marginTop: 24 }}>
        <a href="assets/pdf/chambliss-building-brochure.pdf" target="_blank" rel="noopener noreferrer" className="btn">
          Read the full brochure
          <svg width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true"><path d="M6 2 L6 8 M3 5.5 L6 8.5 L9 5.5 M2 10.5 L10 10.5" stroke="currentColor" strokeWidth="1.5" /></svg>
        </a>
      </div>
    </div>
  </section>
);

const SpecsAnchor = ({ id, children }) => (
  <div id={id} style={{ scrollMarginTop: 80 }}>{children}</div>
);

const Specs = ({ setRoute }) => (
  <div className="page-anim">
    <SpecsHero />
    <SpecsAnchor id="envelope"><BuildEnvelope /></SpecsAnchor>
    <SpecsAnchor id="anatomy"><FrameAnatomy /></SpecsAnchor>
    <SpecsAnchor id="frames"><FrameTypes /></SpecsAnchor>
    <SpecsAnchor id="roofs"><RoofStyles /></SpecsAnchor>
    {/* FIG. 04 Trim and closures hidden for now (Jul 2026, client request). The
        <Assembly> component and its TRIM_PARTS data are left intact above, and
        its SPECS_JUMP entry is commented out to match, so restoring it is
        uncommenting this line and that one. */}
    {/* <SpecsAnchor id="assembly"><Assembly /></SpecsAnchor> */}
    <SpecsAnchor id="panels"><Panels setRoute={setRoute} /></SpecsAnchor>
    <SpecsAnchor id="doors"><Doors setRoute={setRoute} /></SpecsAnchor>
    <SpecsAnchor id="accessories"><Accessories setRoute={setRoute} /></SpecsAnchor>
    <SpecsAnchor id="insulation"><Insulation setRoute={setRoute} /></SpecsAnchor>
    <SpecsAnchor id="standard"><StandardFeatures /></SpecsAnchor>
    <SpecsCTA setRoute={setRoute} />
  </div>
);

Object.assign(window, {
  Specs, FrameTypes, RoofStyles, BuildEnvelope, StandardFeatures,
  Assembly, Panels, Doors, Accessories, Insulation,
});
