// SAME Analog Modular Ecosystem
//
// / SPDX-FileCopyrightText: 2026 Denis Chevalier <perso@denischevalier.fr>
// / SPDX-License-Identifier: CC-BY-SA-4.0
// / SPDX-License-Identifier: CERN-OHL-S-2.0+
// / SPDX-License-Identifier: GPL-3.0-or-later
//
// The prose, explanatory text, rendered figures, tables, and mathematical
// content of this specification are licensed under CC BY-SA 4.0. If a later
// version of CC BY-SA is published, the author grants permission to distribute
// this work under that later version as well.
//
// Hardware designs contained herein (schematics, PCB layouts, mechanical
// drawings, and CAD models) are licensed under CERN-OHL-S-2.0+.
//
// All executable code, helper libraries (`lib/*`), metrology assertions, and
// embedded verification scripts throughout the source documents are licensed
// under the GNU General Public License v3.0 or later (GPL-3.0-or-later).

#import "../lib/unify.typ": qty
#import "@preview/cetz:0.5.2"

#figure(
  cetz.canvas({
    import cetz.draw: *

    // Scale factor: 1 mm = 0.04 drawing units
    let s = 0.04

    // =========================================================================
    // VIEW A: SIDE ELEVATION CUTAWAY (Chassis & Module Clearance)
    // =========================================================================
    let x-side-start = -3.8
    let y-side-bot = 0
    let h-panel = 177.8 * s // 4.2672
    let h-body = 165.1 * s // 3.9624
    let h-lip = 6.35 * s // 0.1524
    let d-body = 152.4 * s // 3.6576
    let d-cable = 28.0 * s // 0.672 (>= 25 mm cable bend zone)

    let y-side-top = y-side-bot + h-panel
    let y-body-bot = y-side-bot + h-lip
    let y-body-top = y-side-top - h-lip
    let x-panel-front = x-side-start
    let x-body-start = x-panel-front + 3.0 * s
    let x-body-rear = x-body-start + d-body
    let x-chassis-rear = x-body-rear + d-cable

    // View Title
    content((x-body-start + (d-body + d-cable) / 2, y-side-top + 1.5), text(
      size: 8.5pt,
      weight: "bold",
    )[VIEW A: SIDE ELEVATION CUTAWAY])
    content((x-body-start + (d-body + d-cable) / 2, y-side-top + 1.15), text(
      size: 7pt,
      fill: luma(90),
    )[(Chassis enclosure & module interface clearance)])

    // Chassis Steel Structure Outline (1.5 mm / 2.0 mm outer shell)
    rect(
      (x-body-start - 2.0 * s, y-side-bot - 2.0 * s),
      (x-chassis-rear + 2.0 * s, y-side-top + 2.0 * s),
      fill: luma(250),
      stroke: 1.2pt + black,
    )

    // Cassette Guide Rails (Top and Bottom Channels)
    rect(
      (x-body-start, y-side-top - 8.0 * s),
      (x-body-rear, y-side-top),
      fill: luma(210),
      stroke: 0.8pt + black,
    )
    rect(
      (x-body-start, y-side-bot),
      (x-body-rear, y-side-bot + 8.0 * s),
      fill: luma(210),
      stroke: 0.8pt + black,
    )

    // Installed Cassette Outer Body (White fill inside chassis)
    rect(
      (x-body-start, y-body-bot),
      (x-body-rear, y-body-top),
      fill: white,
      stroke: 1pt + black,
    )

    // Front Panel Attached to Cassette Lip
    rect(
      (x-panel-front, y-side-bot),
      (x-body-start, y-side-top),
      fill: luma(225),
      stroke: 1.2pt + black,
    )

    // DB-25 Backplane Connector (Mating Pair at Rear of Cassette)
    let db-h = 50.0 * s
    rect(
      (x-body-rear - 2.0 * s, y-side-bot + (h-panel - db-h) / 2),
      (x-body-rear + 8.0 * s, y-side-bot + (h-panel + db-h) / 2),
      fill: luma(180),
      stroke: 0.9pt + black,
    )

    // Cable Bend & Wiring Harness Zone (Dashed hatched path behind backplane)
    line(
      (x-body-rear + 8.0 * s, y-side-bot + h-panel / 2),
      (x-chassis-rear - 4.0 * s, y-side-bot + h-panel / 2),
      (x-chassis-rear - 4.0 * s, y-side-bot + 15.0 * s),
      stroke: (paint: luma(120), thickness: 0.8pt, dash: "dashed"),
    )

    // Dimensions for View A
    // Total Panel Height (177.8 mm / 4U)
    line(
      (x-panel-front, y-side-bot),
      (x-panel-front - 0.5, y-side-bot),
      stroke: 0.4pt + luma(140),
    )
    line(
      (x-panel-front, y-side-top),
      (x-panel-front - 0.5, y-side-top),
      stroke: 0.4pt + luma(140),
    )
    line(
      (x-panel-front - 0.45, y-side-bot),
      (x-panel-front - 0.45, y-side-top),
      mark: (start: "stealth", end: "stealth"),
      mark-size: 0.08,
      stroke: 0.6pt + black,
    )
    content(
      (x-panel-front - 0.75, (y-side-bot + y-side-top) / 2),
      text(size: 6.5pt, weight: "bold")[$qty(177.8, "mm")$ ($qty(4, "U")$)],
      angle: 90deg,
    )

    // Lip Height (6.35 mm)
    line(
      (x-body-start, y-side-top),
      (x-body-start + 0.4, y-side-top),
      stroke: 0.4pt + luma(140),
    )
    line(
      (x-body-start, y-body-top),
      (x-body-start + 0.4, y-body-top),
      stroke: 0.4pt + luma(140),
    )
    line(
      (x-body-start + 0.35, y-body-top),
      (x-body-start + 0.35, y-side-top),
      mark: (start: "stealth", end: "stealth"),
      mark-size: 0.06,
      stroke: 0.6pt + black,
    )
    content((x-body-start + 0.65, (y-body-top + y-side-top) / 2), text(
      size: 5.5pt,
    )[$qty(6.35, "mm")$])

    // Body Height (165.1 mm)
    line(
      (x-body-start + 0.8, y-body-bot),
      (x-body-start + 0.8, y-body-top),
      stroke: (paint: luma(140), thickness: 0.4pt, dash: "dashed"),
    )
    line(
      (x-body-start + 0.8, y-body-bot),
      (x-body-start + 0.8, y-body-top),
      mark: (start: "stealth", end: "stealth"),
      mark-size: 0.08,
      stroke: 0.6pt + black,
    )
    content(
      (x-body-start + 1.1, (y-body-bot + y-body-top) / 2),
      text(size: 6.5pt)[$qty(165.1, "mm")$ body],
      angle: -90deg,
    )

    // Cassette Depth (152.4 mm)
    line(
      (x-body-start, y-side-top + 2.0 * s),
      (x-body-start, y-side-top + 0.5),
      stroke: 0.4pt + luma(140),
    )
    line(
      (x-body-rear, y-side-top + 2.0 * s),
      (x-body-rear, y-side-top + 0.5),
      stroke: 0.4pt + luma(140),
    )
    line(
      (x-body-start, y-side-top + 0.45),
      (x-body-rear, y-side-top + 0.45),
      mark: (start: "stealth", end: "stealth"),
      mark-size: 0.08,
      stroke: 0.6pt + black,
    )
    content(((x-body-start + x-body-rear) / 2, y-side-top + 0.65), text(
      size: 6.5pt,
    )[$qty(152.4, "mm")$])

    // Cable Zone Depth (>= 25.0 mm)
    line(
      (x-chassis-rear, y-side-top + 2.0 * s),
      (x-chassis-rear, y-side-top + 0.5),
      stroke: 0.4pt + luma(140),
    )
    line(
      (x-body-rear, y-side-top + 0.45),
      (x-chassis-rear, y-side-top + 0.45),
      mark: (start: "stealth", end: "stealth"),
      mark-size: 0.08,
      stroke: 0.6pt + black,
    )
    content(((x-body-rear + x-chassis-rear) / 2, y-side-top + 0.65), text(
      size: 6pt,
    )[$gt.eq qty(25.0, "mm")$])

    // Callout Annotations for View A
    line(
      (x-body-rear + 3.0 * s, y-side-bot + h-panel / 2),
      (x-body-rear + 1.2, y-side-bot + h-panel / 2 + 0.6),
      stroke: 0.5pt + black,
    )
    content(
      (x-body-rear + 1.25, y-side-bot + h-panel / 2 + 0.6),
      text(size: 6pt)[DB-25 backplane \
        (grounded via shell & pin 25)],
      anchor: "south-west",
    )

    line(
      (x-chassis-rear - 2.0 * s, y-side-bot + 20.0 * s),
      (x-chassis-rear + 0.5, y-side-bot - 0.3),
      stroke: 0.5pt + black,
    )
    content(
      (x-chassis-rear + 0.55, y-side-bot - 0.3),
      text(size: 6pt)[Cable bend & wiring zone],
      anchor: "west",
    )

    // =========================================================================
    // VIEW B: FRONT ELEVATION (Module Pitch Alignment)
    // =========================================================================
    let x-front-view = 7.2
    let w-module = 38.0 * s // 0.912
    let pitch-module = 38.1 * s // 0.9144

    // View Title
    content((x-front-view + 1.5 * pitch-module, y-side-top + 1.5), text(
      size: 8.5pt,
      weight: "bold",
    )[VIEW B: FRONT ELEVATION])
    content((x-front-view + 1.5 * pitch-module, y-side-top + 1.15), text(
      size: 7pt,
      fill: luma(90),
    )[(Module pitch & slot interface alignment)])

    // Chassis Front Frame
    rect(
      (x-front-view - 0.2, y-side-bot - 2.0 * s),
      (x-front-view + 3 * pitch-module + 0.2, y-side-top + 2.0 * s),
      fill: luma(240),
      stroke: 1.2pt + black,
    )

    // Module Slot 1 (Module 1 Installed)
    let m1-x = x-front-view
    rect(
      (m1-x, y-side-bot),
      (m1-x + w-module, y-side-top),
      fill: luma(250),
      stroke: 1pt + black,
    )
    circle(
      (m1-x + w-module / 2, y-side-bot + h-lip / 2),
      radius: 1.2 * s,
      fill: white,
      stroke: 0.6pt + black,
    )
    circle(
      (m1-x + w-module / 2, y-side-top - h-lip / 2),
      radius: 1.2 * s,
      fill: white,
      stroke: 0.6pt + black,
    )
    content((m1-x + w-module / 2, y-side-bot + h-panel / 2), text(
      size: 6.5pt,
      weight: "bold",
    )[Module 1])

    // Module Slot 2 (Module 2 Installed)
    let m2-x = x-front-view + pitch-module
    rect(
      (m2-x, y-side-bot),
      (m2-x + w-module, y-side-top),
      fill: luma(250),
      stroke: 1pt + black,
    )
    circle(
      (m2-x + w-module / 2, y-side-bot + h-lip / 2),
      radius: 1.2 * s,
      fill: white,
      stroke: 0.6pt + black,
    )
    circle(
      (m2-x + w-module / 2, y-side-top - h-lip / 2),
      radius: 1.2 * s,
      fill: white,
      stroke: 0.6pt + black,
    )
    content((m2-x + w-module / 2, y-side-bot + h-panel / 2), text(
      size: 6.5pt,
      weight: "bold",
    )[Module 2])

    // Module Slot 3 (Empty Slot showing chassis guide rails)
    let m3-x = x-front-view + 2 * pitch-module
    rect(
      (m3-x, y-side-bot),
      (m3-x + w-module, y-side-top),
      fill: white,
      stroke: 0.8pt + black,
    )
    rect(
      (m3-x, y-side-top - h-lip),
      (m3-x + w-module, y-side-top),
      fill: luma(210),
      stroke: 0.5pt + black,
    )
    rect(
      (m3-x, y-side-bot),
      (m3-x + w-module, y-side-bot + h-lip),
      fill: luma(210),
      stroke: 0.5pt + black,
    )
    content((m3-x + w-module / 2, y-side-bot + h-panel / 2), text(
      size: 6pt,
      fill: luma(100),
    )[Empty slot \ (rails visible)])

    // Centerlines for Module Center Pitch
    line(
      (m1-x + w-module / 2, y-side-bot - 0.4),
      (m1-x + w-module / 2, y-side-top + 0.4),
      stroke: (paint: luma(120), thickness: 0.4pt, dash: "dash-dotted"),
    )
    line(
      (m2-x + w-module / 2, y-side-bot - 0.4),
      (m2-x + w-module / 2, y-side-top + 0.4),
      stroke: (paint: luma(120), thickness: 0.4pt, dash: "dash-dotted"),
    )
    line(
      (m3-x + w-module / 2, y-side-bot - 0.4),
      (m3-x + w-module / 2, y-side-top + 0.4),
      stroke: (paint: luma(120), thickness: 0.4pt, dash: "dash-dotted"),
    )

    // Dimension: Module Pitch (38.1 mm / 1.5")
    line(
      (m1-x + w-module / 2, y-side-top + 0.35),
      (m2-x + w-module / 2, y-side-top + 0.35),
      mark: (start: "stealth", end: "stealth"),
      mark-size: 0.08,
      stroke: 0.6pt + black,
    )
    content(((m1-x + m2-x + w-module) / 2, y-side-top + 0.55), text(
      size: 6.5pt,
    )[$qty(38.1, "mm")$ ($qty(1.5, "inch")$) pitch])

    // =========================================================================
    // VIEW C: CASSETTE RAIL GEOMETRY & RETENTION (ENLARGED DETAIL)
    // =========================================================================
    let x-rail-center = 4.8
    let y-rail-center = -3.6
    let rail-w = 38.1 * 0.08 // Magnified channel width (38.1 mm)
    let rail-h = 6.35 * 0.08 // Magnified rail height (6.35 mm)
    let lip-t = 1.2 * 0.08 // Sheet metal thickness (1.2 mm)

    let rx1 = x-rail-center - rail-w / 2
    let rx2 = x-rail-center + rail-w / 2
    let ry1 = y-rail-center - rail-h / 2
    let ry2 = y-rail-center + rail-h / 2

    // View Title
    content((x-rail-center, y-rail-center + 2.2), text(
      size: 8.5pt,
      weight: "bold",
    )[VIEW C: CASSETTE RAIL GEOMETRY & RETENTION])
    content((x-rail-center, y-rail-center + 1.85), text(
      size: 7pt,
      fill: luma(90),
    )[(Cross-section of guide rail channel -- scale enlarged)])

    // Main Chassis Guide Channel (U-shaped metal guide track)
    line(
      (rx1 - 0.4, ry2 + 0.4),
      (rx1 - 0.4, ry1 - lip-t),
      (rx2 + 0.4, ry1 - lip-t),
      (rx2 + 0.4, ry2 + 0.4),
      stroke: 1.2pt + black,
    )
    line(
      (rx1, ry2 + 0.4),
      (rx1, ry1),
      (rx2, ry1),
      (rx2, ry2 + 0.4),
      stroke: 1.2pt + black,
    )

    // Inserted Cassette Front Panel Lip (Mating into Channel)
    rect(
      (rx1 + 0.05, ry1 + 0.05),
      (rx2 - 0.05, ry2),
      fill: luma(230),
      stroke: 0.8pt + black,
    )

    // Optional Spring Clip / Retention Latch (Contact spring on left side)
    line(
      (rx1 - 0.3, ry1 + 0.2),
      (rx1 - 0.05, ry1 + 0.25),
      (rx1 + 0.2, ry1 + 0.2),
      stroke: 0.8pt + black,
    )
    circle((rx1 - 0.3, ry1 + 0.2), radius: 0.04, fill: black)

    // Centerline
    line(
      (x-rail-center, ry1 - 0.6),
      (x-rail-center, ry2 + 0.6),
      stroke: (paint: luma(120), thickness: 0.4pt, dash: "dash-dotted"),
    )

    // Dimension: Channel Width (38.1 mm +0.2/-0.0 mm)
    line((rx1, ry2 + 0.1), (rx1, ry2 + 0.7), stroke: 0.4pt + luma(140))
    line((rx2, ry2 + 0.1), (rx2, ry2 + 0.7), stroke: 0.4pt + luma(140))
    line(
      (rx1, ry2 + 0.6),
      (rx2, ry2 + 0.6),
      mark: (start: "stealth", end: "stealth"),
      mark-size: 0.08,
      stroke: 0.6pt + black,
    )
    content((x-rail-center, ry2 + 0.85), text(
      size: 7pt,
    )[Channel width: $qty(38.1, "mm") +0.2/(-0.0)$])

    // Dimension: Rail Height (6.35 mm / 0.25")
    line((rx2 + 0.1, ry1), (rx2 + 0.7, ry1), stroke: 0.4pt + luma(140))
    line((rx2 + 0.1, ry2), (rx2 + 0.7, ry2), stroke: 0.4pt + luma(140))
    line(
      (rx2 + 0.6, ry1),
      (rx2 + 0.6, ry2),
      mark: (start: "stealth", end: "stealth"),
      mark-size: 0.08,
      stroke: 0.6pt + black,
    )
    content(
      (rx2 + 0.8, (ry1 + ry2) / 2),
      text(
        size: 6.5pt,
      )[$qty(6.35, "mm")$ ($qty(0.25, "inch")$) rail height],
      anchor: "west",
    )

    // Callout Annotations for View C
    line(
      (rx1 - 0.15, ry1 + 0.2),
      (rx1 - 1.2, ry1 - 0.4),
      stroke: 0.5pt + black,
    )
    content(
      (rx1 - 1.25, ry1 - 0.4),
      text(
        size: 6pt,
      )[Optional positive retention \ (spring clip / latch mechanism)],
      anchor: "east",
    )

    line(
      (rx2 - 0.3, ry1 + 0.1),
      (rx2 + 1.2, ry1 - 0.4),
      stroke: 0.5pt + black,
    )
    content(
      (rx2 + 1.25, ry1 - 0.4),
      text(
        size: 6pt,
      )[Metal-to-metal grounding contact \ (cassette lip insertion clearance)],
      anchor: "west",
    )
  }),
  caption: [Chassis dimensional requirements and module loading interface specifications detailing Side Elevation Cutaway (View A), Front Elevation Module Pitch Alignment (View B), and enlarged Cassette Rail Geometry & Retention Cross-Section (View C).],
) <figure-chassis-dimensional-requirements-diagram>
