/ concepts / concept1-tactical.jsx
concept1-tactical.jsx
  1  // Concept 1 — ORBITAL TACTICAL HUD
  2  // Holographic cyan-on-deep-navy. Threat/flight-computer vibe.
  3  // Central ship silhouette framed by crosshair brackets, orbited by
  4  // radial gauges. Think: locking-on dossier before purchase.
  5  
  6  function Concept1_Tactical({ seed = "C1-default" }) {
  7    const ship = makeShip(seed);
  8    const cyan = "#5df0ff";
  9    const cyanDim = "#2a6a75";
 10    const navy = "#040b14";
 11    const navy2 = "#0a1624";
 12    const amber = "#ffb347";
 13  
 14    // Radial gauge (SVG arc)
 15    const Radial = ({ label, value, max = 100, color = cyan }) => {
 16      const r = 34, c = 2*Math.PI*r;
 17      const pct = Math.min(1, value/max);
 18      return (
 19        <div style={{display:"flex", flexDirection:"column", alignItems:"center", gap:4}}>
 20          <svg width={84} height={84} style={{filter:`drop-shadow(0 0 4px ${color})`}}>
 21            <circle cx={42} cy={42} r={r} fill="none" stroke={cyanDim} strokeWidth={1} opacity={0.4}/>
 22            <circle cx={42} cy={42} r={r} fill="none" stroke={color} strokeWidth={3}
 23              strokeDasharray={`${c*pct} ${c}`} transform="rotate(-90 42 42)" strokeLinecap="butt"/>
 24            {/* tick marks */}
 25            {Array.from({length: 24}).map((_,i) => {
 26              const a = (i/24)*2*Math.PI - Math.PI/2;
 27              const r0 = r+4, r1 = r+7;
 28              return <line key={i} x1={42+Math.cos(a)*r0} y1={42+Math.sin(a)*r0}
 29                x2={42+Math.cos(a)*r1} y2={42+Math.sin(a)*r1} stroke={color} strokeWidth={1} opacity={0.5}/>;
 30            })}
 31            <text x={42} y={40} textAnchor="middle" fill={color} fontFamily="Orbitron" fontSize={14} fontWeight={700}>{value}</text>
 32            <text x={42} y={54} textAnchor="middle" fill={color} fontFamily="JetBrains Mono" fontSize={8} opacity={0.7}>/{max}</text>
 33          </svg>
 34          <div style={{fontFamily:"JetBrains Mono", fontSize:9, color:color, letterSpacing:1, opacity:0.8}}>{label}</div>
 35        </div>
 36      );
 37    };
 38  
 39    const Chip = ({ children, warn, ok }) => (
 40      <span style={{
 41        border: `1px solid ${warn ? amber : ok ? "#5cffa1" : cyan}`,
 42        color: warn ? amber : ok ? "#5cffa1" : cyan,
 43        padding: "2px 8px", fontFamily:"JetBrains Mono", fontSize:10, letterSpacing:1.5,
 44        background: "rgba(0,0,0,0.3)",
 45      }}>{children}</span>
 46    );
 47  
 48    // Corner brackets
 49    const Bracket = ({ corner }) => {
 50      const size = 22;
 51      const s = { position:"absolute", width:size, height:size, borderColor: cyan };
 52      if (corner === "tl") return <div style={{...s, top:0, left:0, borderTop:`2px solid ${cyan}`, borderLeft:`2px solid ${cyan}`}}/>;
 53      if (corner === "tr") return <div style={{...s, top:0, right:0, borderTop:`2px solid ${cyan}`, borderRight:`2px solid ${cyan}`}}/>;
 54      if (corner === "bl") return <div style={{...s, bottom:0, left:0, borderBottom:`2px solid ${cyan}`, borderLeft:`2px solid ${cyan}`}}/>;
 55      return <div style={{...s, bottom:0, right:0, borderBottom:`2px solid ${cyan}`, borderRight:`2px solid ${cyan}`}}/>;
 56    };
 57  
 58    // Scanlines background
 59    const scanlines = `repeating-linear-gradient(0deg, transparent 0 2px, rgba(93,240,255,0.025) 2px 3px)`;
 60  
 61    return (
 62      <div style={{
 63        width:1280, height:880, background: `radial-gradient(ellipse at center, ${navy2} 0%, ${navy} 80%)`,
 64        color: cyan, fontFamily:"'Space Grotesk', sans-serif", position:"relative", overflow:"hidden",
 65      }}>
 66        {/* bg scanlines + grid */}
 67        <div style={{position:"absolute", inset:0, background: scanlines, pointerEvents:"none"}}/>
 68        <div style={{position:"absolute", inset:0, backgroundImage:`
 69          linear-gradient(${cyan}11 1px, transparent 1px),
 70          linear-gradient(90deg, ${cyan}11 1px, transparent 1px)`,
 71          backgroundSize:"40px 40px", pointerEvents:"none"}}/>
 72  
 73        {/* TOP BAR */}
 74        <div style={{display:"flex", justifyContent:"space-between", alignItems:"center", padding:"14px 32px", borderBottom:`1px solid ${cyan}44`, position:"relative", zIndex:2}}>
 75          <div style={{display:"flex", alignItems:"center", gap:24}}>
 76            <div style={{fontFamily:"Orbitron", fontWeight:900, fontSize:16, letterSpacing:4, color:cyan}}>◈ FLEET.PROCURE</div>
 77            <div style={{fontFamily:"JetBrains Mono", fontSize:10, color:cyanDim, letterSpacing:2}}>NODE 07 // SECTOR G-4 // AUTH:COMMODORE</div>
 78          </div>
 79          <div style={{display:"flex", gap:16, fontFamily:"JetBrains Mono", fontSize:10, color:cyanDim, letterSpacing:2}}>
 80            <span>STARDATE 2396.114</span>
 81            <span style={{color:"#5cffa1"}}>● LINK STABLE</span>
 82            <span>LAT 14°44'N</span>
 83          </div>
 84        </div>
 85  
 86        {/* BREADCRUMB */}
 87        <div style={{padding:"10px 32px", fontFamily:"JetBrains Mono", fontSize:10, color:cyanDim, letterSpacing:2, borderBottom:`1px solid ${cyan}22`}}>
 88          CATALOG ▸ {ship.cls.name.toUpperCase()} ▸ {ship.mfg.name.toUpperCase()} ▸ <span style={{color:cyan}}>{ship.serial}</span>
 89        </div>
 90  
 91        {/* MAIN — 3col */}
 92        <div style={{display:"grid", gridTemplateColumns:"280px 1fr 280px", gap:0, height: "calc(100% - 140px)"}}>
 93  
 94          {/* LEFT — dossier */}
 95          <div style={{borderRight:`1px solid ${cyan}22`, padding:"20px 22px"}}>
 96            <div style={{fontFamily:"JetBrains Mono", fontSize:9, color:cyanDim, letterSpacing:2, marginBottom:6}}>▸ DOSSIER</div>
 97            <div style={{fontFamily:"Orbitron", fontWeight:700, fontSize:22, color:cyan, lineHeight:1.1, letterSpacing:1}}>{ship.model}</div>
 98            <div style={{fontFamily:"JetBrains Mono", fontSize:10, color:cyanDim, marginTop:6, letterSpacing:1}}>{ship.serial}</div>
 99  
100            <div style={{marginTop:18, display:"flex", flexWrap:"wrap", gap:6}}>
101              <Chip>{ship.cls.code} · {ship.cls.name.toUpperCase()}</Chip>
102              <Chip>{ship.mfg.code}</Chip>
103              <Chip warn>{ship.avail}</Chip>
104            </div>
105  
106            <div style={{marginTop:24, fontFamily:"JetBrains Mono", fontSize:11, color:cyan, lineHeight:1.9}}>
107              <Row k="MFG" v={ship.mfg.name}/>
108              <Row k="ORIGIN" v={ship.mfg.loc}/>
109              <Row k="YEAR" v={ship.year}/>
110              <Row k="HULL" v={ship.cond}/>
111              <Row k="FACTION" v={ship.faction}/>
112              <Row k="DRIVE" v={ship.drive}/>
113              <Row k="WARRANTY" v={ship.warranty}/>
114            </div>
115  
116            <div style={{marginTop:24, fontFamily:"JetBrains Mono", fontSize:9, color:cyanDim, letterSpacing:2, marginBottom:10}}>▸ THREAT PROFILE</div>
117            <ThreatBars ship={ship} color={cyan} dim={cyanDim}/>
118          </div>
119  
120          {/* CENTER — silhouette stage */}
121          <div style={{position:"relative", padding:"20px", display:"flex", flexDirection:"column"}}>
122            {/* Stage */}
123            <div style={{flex:1, position:"relative", border:`1px solid ${cyan}33`, background:"rgba(10,22,36,0.6)"}}>
124              <Bracket corner="tl"/><Bracket corner="tr"/><Bracket corner="bl"/><Bracket corner="br"/>
125              {/* crosshair */}
126              <div style={{position:"absolute", inset:0, pointerEvents:"none"}}>
127                <div style={{position:"absolute", left:"50%", top:0, bottom:0, width:1, background:`${cyan}22`}}/>
128                <div style={{position:"absolute", top:"50%", left:0, right:0, height:1, background:`${cyan}22`}}/>
129              </div>
130              {/* ship */}
131              <div style={{position:"absolute", inset:"12% 10%"}}>
132                <ShipSilhouette ship={ship} stroke={cyan} fill="rgba(93,240,255,0.06)" glow/>
133              </div>
134              {/* callouts */}
135              <Callout top="18%" left="18%" label="FORWARD ARRAY" val={`${ship.hardpoints} HP`} color={cyan}/>
136              <Callout top="72%" left="60%" label="DRIVE" val={ship.drive.toUpperCase()} color={amber}/>
137              <Callout top="38%" left="78%" label="COCKPIT" val={`CREW ${ship.crew}`} color={cyan}/>
138              {/* stamp */}
139              <div style={{position:"absolute", bottom:14, left:14, fontFamily:"JetBrains Mono", fontSize:9, color:cyanDim, letterSpacing:2}}>
140                VIEW.PORT 03 · PLANAR · ORTHO · SCALE 1:{Math.round(ship.length_m/12)}
141              </div>
142              <div style={{position:"absolute", bottom:14, right:14, fontFamily:"JetBrains Mono", fontSize:9, color:cyanDim, letterSpacing:2}}>
143                ◉ SCAN COMPLETE · INTEGRITY 98.4%
144              </div>
145            </div>
146  
147            {/* radial strip */}
148            <div style={{display:"flex", justifyContent:"space-around", marginTop:16, padding:"14px 8px", border:`1px solid ${cyan}33`, background:"rgba(10,22,36,0.6)"}}>
149              <Radial label="THRUST"   value={ship.thrust}   max={100}/>
150              <Radial label="MANEUVER" value={ship.maneuver} max={100}/>
151              <Radial label="SIG"      value={ship.signature} max={100} color={amber}/>
152              <Radial label="JUMP"     value={ship.jumpRange} max={40}/>
153              <Radial label="SPEED"    value={Math.round(ship.topSpeed/30)} max={100}/>
154              <Radial label="CARGO"    value={Math.round(ship.cargo_t/100)} max={100}/>
155            </div>
156          </div>
157  
158          {/* RIGHT — procure */}
159          <div style={{borderLeft:`1px solid ${cyan}22`, padding:"20px 22px", display:"flex", flexDirection:"column"}}>
160            <div style={{fontFamily:"JetBrains Mono", fontSize:9, color:cyanDim, letterSpacing:2, marginBottom:6}}>▸ VALUATION</div>
161            <div style={{fontFamily:"Orbitron", fontWeight:900, fontSize:36, color:cyan, letterSpacing:1, lineHeight:1}}>
162              ₵ {formatCred(ship.price)}
163            </div>
164            <div style={{fontFamily:"JetBrains Mono", fontSize:10, color:cyanDim, marginTop:4, letterSpacing:1}}>
165              UNIT PRICE · FOB {ship.mfg.loc.toUpperCase()}
166            </div>
167  
168            <div style={{marginTop:20, fontFamily:"JetBrains Mono", fontSize:11, color:cyan, lineHeight:2}}>
169              <Row k="DELIVERY" v={`${ship.delivery} CYCLES`}/>
170              <Row k="LEASE/MO" v={`₵ ${formatCred(Math.round(ship.price/120))}`}/>
171              <Row k="INSURE"   v={`₵ ${formatCred(Math.round(ship.price*0.018))}`}/>
172              <Row k="ESCROW"   v="STELLAR BANK"/>
173            </div>
174  
175            <div style={{marginTop:20, fontFamily:"JetBrains Mono", fontSize:9, color:cyanDim, letterSpacing:2, marginBottom:8}}>▸ LOADOUT CONFIG</div>
176            <div style={{display:"grid", gridTemplateColumns:"1fr 1fr", gap:6}}>
177              {["STANDARD","TACTICAL","CARGO","CIVIL"].map((p,i) => (
178                <div key={p} style={{
179                  border:`1px solid ${i===1?cyan:cyan+"33"}`, padding:"10px 8px", textAlign:"center",
180                  fontFamily:"JetBrains Mono", fontSize:10, letterSpacing:2, color: i===1?cyan:cyanDim,
181                  background: i===1 ? `${cyan}11` : "transparent",
182                }}>{p}</div>
183              ))}
184            </div>
185  
186            <div style={{marginTop:"auto"}}>
187              <div style={{border:`1px solid ${amber}`, padding:10, background:`${amber}11`, fontFamily:"JetBrains Mono", fontSize:10, color:amber, letterSpacing:1, marginBottom:12}}>
188                ⚠ EXPORT LICENSE REQUIRED · CLASS {ship.cls.code}
189              </div>
190              <button style={{
191                width:"100%", padding:"18px 0", background: cyan, color: navy, border:"none",
192                fontFamily:"Orbitron", fontWeight:900, letterSpacing:4, fontSize:14, cursor:"pointer",
193                boxShadow:`0 0 24px ${cyan}aa`,
194              }}>▸ PROCURE UNIT</button>
195              <button style={{
196                marginTop:8, width:"100%", padding:"14px 0", background: "transparent", color: cyan,
197                border: `1px solid ${cyan}`, fontFamily:"Orbitron", fontWeight:700, letterSpacing:3, fontSize:11, cursor:"pointer",
198              }}>REQUEST DEMO FLIGHT</button>
199            </div>
200          </div>
201        </div>
202  
203        {/* BOTTOM TICKER */}
204        <div style={{position:"absolute", bottom:0, left:0, right:0, padding:"8px 32px", borderTop:`1px solid ${cyan}33`, background:`${navy}`, fontFamily:"JetBrains Mono", fontSize:10, color:cyanDim, letterSpacing:2, display:"flex", justifyContent:"space-between"}}>
205          <span>◉ 14,208 SIMILAR UNITS · 87 WATCHERS · PEER AVG ₵ {formatCred(Math.round(ship.price*1.05))}</span>
206          <span>v7.4.2 · FLEET-PROCURE © COALITION COMMONS</span>
207        </div>
208      </div>
209    );
210  }
211  
212  function Row({k, v}) {
213    return (
214      <div style={{display:"flex", justifyContent:"space-between", alignItems:"baseline", borderBottom:"1px dashed rgba(93,240,255,0.15)", paddingBottom:2}}>
215        <span style={{color:"rgba(93,240,255,0.55)", fontSize:10, letterSpacing:2}}>{k}</span>
216        <span style={{color:"#5df0ff", fontWeight:500}}>{v}</span>
217      </div>
218    );
219  }
220  
221  function Callout({ top, left, label, val, color }) {
222    return (
223      <div style={{position:"absolute", top, left, fontFamily:"JetBrains Mono", fontSize:9, color, letterSpacing:1.5}}>
224        <div style={{width:40, height:1, background:color, marginBottom:4, boxShadow:`0 0 6px ${color}`}}/>
225        <div style={{opacity:0.7}}>{label}</div>
226        <div style={{fontWeight:700}}>{val}</div>
227      </div>
228    );
229  }
230  
231  function ThreatBars({ ship, color, dim }) {
232    const rows = [
233      ["HULL",   Math.min(100, Math.round(ship.armor/30))],
234      ["SHIELD", Math.min(100, Math.round(ship.shields/20))],
235      ["EW",     Math.min(100, Math.round(ship.signature))],
236      ["DPS",    Math.min(100, ship.hardpoints*12)],
237    ];
238    return (
239      <div style={{display:"flex", flexDirection:"column", gap:8}}>
240        {rows.map(([k,v]) => (
241          <div key={k}>
242            <div style={{display:"flex", justifyContent:"space-between", fontFamily:"JetBrains Mono", fontSize:10, color, letterSpacing:1.5}}>
243              <span style={{color:dim}}>{k}</span><span>{v}</span>
244            </div>
245            <div style={{height:6, background:`${color}22`, marginTop:3, position:"relative"}}>
246              <div style={{position:"absolute", inset:0, width:`${v}%`, background:color, boxShadow:`0 0 8px ${color}`}}/>
247              {Array.from({length:9}).map((_,i)=>(
248                <div key={i} style={{position:"absolute", left:`${(i+1)*10}%`, top:0, bottom:0, width:1, background:"#040b14"}}/>
249              ))}
250            </div>
251          </div>
252        ))}
253      </div>
254    );
255  }
256  
257  Object.assign(window, { Concept1_Tactical });