docs: establish approved Phase 1 design + Phase 2 spec as project foundation

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
cesnimda
2026-07-03 21:07:25 +02:00
commit 1f695d3932
39 changed files with 2686 additions and 0 deletions
@@ -0,0 +1,148 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 1420" font-family="Segoe UI, Arial, sans-serif">
<defs>
<radialGradient id="halo" cx="30%" cy="18%" r="55%">
<stop offset="0%" stop-color="#3ECFAE" stop-opacity="0.07"/>
<stop offset="100%" stop-color="#3ECFAE" stop-opacity="0"/>
</radialGradient>
<pattern id="dots" width="24" height="24" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="1" fill="#E8ECF2" opacity="0.05"/>
</pattern>
</defs>
<!-- page -->
<rect width="1440" height="1420" fill="#0B0E14"/>
<rect width="1440" height="640" fill="url(#dots)"/>
<rect width="1440" height="640" fill="url(#halo)"/>
<!-- ===== HEADER 72px ===== -->
<line x1="0" y1="72" x2="1440" y2="72" stroke="#E8ECF2" stroke-opacity="0.08"/>
<!-- monogram -->
<rect x="120" y="20" width="32" height="32" rx="8" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.16"/>
<text x="136" y="41" fill="#E8ECF2" font-family="Consolas, monospace" font-size="13" font-weight="bold" text-anchor="middle">CB</text>
<circle cx="148" cy="24" r="2" fill="#3ECFAE"/>
<!-- nav -->
<text x="420" y="41" fill="#9AA4B2" font-size="14">Projects</text>
<text x="510" y="41" fill="#9AA4B2" font-size="14">Experience</text>
<text x="620" y="41" fill="#9AA4B2" font-size="14">About</text>
<text x="695" y="41" fill="#9AA4B2" font-size="14">Contact</text>
<!-- language segmented -->
<rect x="1000" y="22" width="88" height="28" rx="14" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.08"/>
<rect x="1003" y="25" width="41" height="22" rx="11" fill="#171C26" stroke="#E8ECF2" stroke-opacity="0.16"/>
<text x="1023" y="40" fill="#E8ECF2" font-family="Consolas, monospace" font-size="11" text-anchor="middle">EN</text>
<text x="1066" y="40" fill="#9AA4B2" font-family="Consolas, monospace" font-size="11" text-anchor="middle">NO</text>
<!-- theme toggle -->
<circle cx="1122" cy="36" r="14" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.08"/>
<path d="M1126 30 a7 7 0 1 0 3 9 a6 6 0 0 1 -3 -9" fill="#9AA4B2"/>
<!-- CV split button -->
<rect x="1156" y="20" width="164" height="32" rx="8" fill="#3ECFAE"/>
<text x="1216" y="41" fill="#062A22" font-size="13" font-weight="600" text-anchor="middle">Download CV</text>
<line x1="1290" y1="26" x2="1290" y2="46" stroke="#062A22" stroke-opacity="0.3"/>
<path d="M1300 33 l6 6 l6 -6" fill="none" stroke="#062A22" stroke-width="1.8"/>
<!-- ===== HERO ===== -->
<text x="120" y="196" fill="#3ECFAE" font-family="Consolas, monospace" font-size="12" letter-spacing="2">SYSTEMS DEVELOPER · TØNSBERG, NORWAY</text>
<text x="120" y="262" fill="#E8ECF2" font-size="61" font-weight="600" letter-spacing="-1">Connor Babbington</text>
<text x="120" y="316" fill="#E8ECF2" font-size="26" font-weight="500">I design, build and run web systems.</text>
<text x="120" y="356" fill="#9AA4B2" font-size="18">Eight-plus years delivering internal software for UK local government —</text>
<text x="120" y="384" fill="#9AA4B2" font-size="18">now building full-stack products in Norway.</text>
<!-- trace motif -->
<path d="M120 424 H360 l12 12 H560" fill="none" stroke="#3ECFAE" stroke-width="1.5"/>
<circle cx="566" cy="436" r="4" fill="#3ECFAE"/>
<text x="582" y="441" fill="#9AA4B2" font-family="Consolas, monospace" font-size="12">status: open to work</text>
<!-- chips -->
<g font-family="Consolas, monospace" font-size="12">
<rect x="120" y="466" width="150" height="30" rx="15" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.08"/>
<text x="195" y="485" fill="#9AA4B2" text-anchor="middle">Tønsberg, Norway</text>
<rect x="282" y="466" width="128" height="30" rx="15" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.08"/>
<text x="346" y="485" fill="#9AA4B2" text-anchor="middle">Work permit ✓</text>
<rect x="422" y="466" width="200" height="30" rx="15" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.08"/>
<text x="522" y="485" fill="#9AA4B2" text-anchor="middle">Remote / hybrid / on-site</text>
<rect x="634" y="466" width="212" height="30" rx="15" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.08"/>
<text x="740" y="485" fill="#9AA4B2" text-anchor="middle">English native · Norsk B1</text>
</g>
<!-- CTAs -->
<rect x="120" y="530" width="156" height="44" rx="8" fill="#3ECFAE"/>
<text x="198" y="557" fill="#062A22" font-size="15" font-weight="600" text-anchor="middle">View projects</text>
<rect x="292" y="530" width="196" height="44" rx="8" fill="none" stroke="#E8ECF2" stroke-opacity="0.16"/>
<text x="390" y="557" fill="#E8ECF2" font-size="15" text-anchor="middle">Download CV · pdf</text>
<!-- portrait -->
<rect x="1020" y="150" width="300" height="375" rx="16" fill="#171C26" stroke="#E8ECF2" stroke-opacity="0.16"/>
<circle cx="1170" cy="290" r="72" fill="#242B38"/>
<path d="M1080 525 q90 -110 180 0" fill="#242B38"/>
<text x="1170" y="300" fill="#5C6675" font-size="13" text-anchor="middle">[ outdoor headshot ]</text>
<text x="1020" y="552" fill="#5C6675" font-family="Consolas, monospace" font-size="12">tønsberg, norway · 2025</text>
<!-- ===== PROOF STRIP ===== -->
<g>
<rect x="120" y="620" width="285" height="96" rx="12" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.08"/>
<text x="144" y="662" fill="#E8ECF2" font-size="28" font-weight="600">8+ yrs</text>
<text x="144" y="692" fill="#5C6675" font-family="Consolas, monospace" font-size="11" letter-spacing="1.5">EXPERIENCE</text>
<rect x="425" y="620" width="285" height="96" rx="12" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.08"/>
<text x="449" y="662" fill="#E8ECF2" font-size="22" font-weight="600">UK public sector</text>
<text x="449" y="692" fill="#5C6675" font-family="Consolas, monospace" font-size="11" letter-spacing="1.5">BACKGROUND</text>
<rect x="730" y="620" width="285" height="96" rx="12" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.08"/>
<text x="754" y="662" fill="#E8ECF2" font-size="22" font-weight="600">.NET · React · Docker</text>
<text x="754" y="692" fill="#5C6675" font-family="Consolas, monospace" font-size="11" letter-spacing="1.5">CORE STACK</text>
<rect x="1035" y="620" width="285" height="96" rx="12" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.08"/>
<text x="1059" y="662" fill="#E8ECF2" font-size="22" font-weight="600">Based in Norway</text>
<text x="1059" y="692" fill="#5C6675" font-family="Consolas, monospace" font-size="11" letter-spacing="1.5">WORK PERMIT ✓</text>
</g>
<!-- ===== SKILLS SECTION ===== -->
<text x="120" y="828" fill="#3ECFAE" font-family="Consolas, monospace" font-size="12" letter-spacing="2">01 — SKILLS</text>
<text x="120" y="880" fill="#E8ECF2" font-size="39" font-weight="600">What I work with</text>
<text x="120" y="916" fill="#9AA4B2" font-size="16">A practical profile: business value, maintainability, dependable delivery.</text>
<!-- three cards -->
<g>
<rect x="120" y="956" width="384" height="360" rx="12" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.08"/>
<text x="144" y="996" fill="#5C6675" font-family="Consolas, monospace" font-size="11" letter-spacing="1.5">01 — DEVELOPMENT</text>
<text x="144" y="1032" fill="#9AA4B2" font-size="14">Backend-leaning full-stack work in the</text>
<text x="144" y="1052" fill="#9AA4B2" font-size="14">.NET ecosystem.</text>
<g font-family="Consolas, monospace" font-size="12" fill="#E8ECF2">
<rect x="144" y="1080" width="52" height="28" rx="14" fill="#171C26"/><text x="170" y="1098" text-anchor="middle">C#</text>
<rect x="204" y="1080" width="64" height="28" rx="14" fill="#171C26"/><text x="236" y="1098" text-anchor="middle">.NET</text>
<rect x="276" y="1080" width="76" height="28" rx="14" fill="#171C26"/><text x="314" y="1098" text-anchor="middle">Python</text>
<rect x="144" y="1118" width="110" height="28" rx="14" fill="#171C26"/><text x="199" y="1136" text-anchor="middle">TypeScript</text>
<rect x="262" y="1118" width="66" height="28" rx="14" fill="#171C26"/><text x="295" y="1136" text-anchor="middle">React</text>
<rect x="144" y="1156" width="56" height="28" rx="14" fill="#171C26"/><text x="172" y="1174" text-anchor="middle">SQL</text>
<rect x="208" y="1156" width="110" height="28" rx="14" fill="#171C26"/><text x="263" y="1174" text-anchor="middle">JavaScript</text>
</g>
<rect x="528" y="956" width="384" height="360" rx="12" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.08"/>
<text x="552" y="996" fill="#5C6675" font-family="Consolas, monospace" font-size="11" letter-spacing="1.5">02 — DEVOPS &amp; INFRASTRUCTURE</text>
<text x="552" y="1032" fill="#9AA4B2" font-size="14">I deploy and operate what I build —</text>
<text x="552" y="1052" fill="#9AA4B2" font-size="14">professionally and at home.</text>
<g font-family="Consolas, monospace" font-size="12" fill="#E8ECF2">
<rect x="552" y="1080" width="76" height="28" rx="14" fill="#171C26"/><text x="590" y="1098" text-anchor="middle">Docker</text>
<rect x="636" y="1080" width="66" height="28" rx="14" fill="#171C26"/><text x="669" y="1098" text-anchor="middle">Linux</text>
<rect x="710" y="1080" width="66" height="28" rx="14" fill="#171C26"/><text x="743" y="1098" text-anchor="middle">CI/CD</text>
<rect x="552" y="1118" width="130" height="28" rx="14" fill="#171C26"/><text x="617" y="1136" text-anchor="middle">Azure DevOps</text>
<rect x="690" y="1118" width="150" height="28" rx="14" fill="#171C26"/><text x="765" y="1136" text-anchor="middle">Reverse proxies</text>
<rect x="552" y="1156" width="120" height="28" rx="14" fill="#171C26"/><text x="612" y="1174" text-anchor="middle">Monitoring</text>
<rect x="680" y="1156" width="130" height="28" rx="14" fill="#171C26"/><text x="745" y="1174" text-anchor="middle">Self-hosting</text>
</g>
<rect x="936" y="956" width="384" height="360" rx="12" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.08"/>
<text x="960" y="996" fill="#5C6675" font-family="Consolas, monospace" font-size="11" letter-spacing="1.5">03 — PRACTICES</text>
<text x="960" y="1032" fill="#9AA4B2" font-size="14">Production thinking: testing, security,</text>
<text x="960" y="1052" fill="#9AA4B2" font-size="14">and honest communication.</text>
<g font-family="Consolas, monospace" font-size="12" fill="#E8ECF2">
<rect x="960" y="1080" width="86" height="28" rx="14" fill="#171C26"/><text x="1003" y="1098" text-anchor="middle">Testing</text>
<rect x="1054" y="1080" width="130" height="28" rx="14" fill="#171C26"/><text x="1119" y="1098" text-anchor="middle">OAuth2 flows</text>
<rect x="960" y="1118" width="180" height="28" rx="14" fill="#171C26"/><text x="1050" y="1136" text-anchor="middle">Security hardening</text>
<rect x="1148" y="1118" width="150" height="28" rx="14" fill="#171C26"/><text x="1223" y="1136" text-anchor="middle">Prod. support</text>
<rect x="960" y="1156" width="220" height="28" rx="14" fill="#171C26"/><text x="1070" y="1174" text-anchor="middle">Stakeholder comms</text>
</g>
</g>
<!-- annotations -->
<g font-family="Consolas, monospace" font-size="11" fill="#E5A93D">
<text x="120" y="106">A1: trace draws on load (700ms), dot blinks once → stays lit</text>
<text x="920" y="106">hover: nav underline draw · CV button = locale default + chevron menu</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

@@ -0,0 +1,94 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 760" font-family="Segoe UI, Arial, sans-serif">
<defs>
<radialGradient id="haloL" cx="30%" cy="18%" r="55%">
<stop offset="0%" stop-color="#0E8C72" stop-opacity="0.06"/>
<stop offset="100%" stop-color="#0E8C72" stop-opacity="0"/>
</radialGradient>
<pattern id="dotsL" width="24" height="24" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="1" fill="#171A20" opacity="0.05"/>
</pattern>
<filter id="cardShadow" x="-10%" y="-10%" width="120%" height="130%">
<feDropShadow dx="0" dy="2" stdDeviation="4" flood-color="#171A20" flood-opacity="0.06"/>
</filter>
</defs>
<rect width="1440" height="760" fill="#FAFAF8"/>
<rect width="1440" height="640" fill="url(#dotsL)"/>
<rect width="1440" height="640" fill="url(#haloL)"/>
<!-- HEADER -->
<line x1="0" y1="72" x2="1440" y2="72" stroke="#171A20" stroke-opacity="0.1"/>
<rect x="120" y="20" width="32" height="32" rx="8" fill="#FFFFFF" stroke="#171A20" stroke-opacity="0.2"/>
<text x="136" y="41" fill="#171A20" font-family="Consolas, monospace" font-size="13" font-weight="bold" text-anchor="middle">CB</text>
<circle cx="148" cy="24" r="2" fill="#0E8C72"/>
<text x="420" y="41" fill="#555E6B" font-size="14">Projects</text>
<text x="510" y="41" fill="#555E6B" font-size="14">Experience</text>
<text x="620" y="41" fill="#555E6B" font-size="14">About</text>
<text x="695" y="41" fill="#555E6B" font-size="14">Contact</text>
<rect x="1000" y="22" width="88" height="28" rx="14" fill="#F1F2EF" stroke="#171A20" stroke-opacity="0.1"/>
<rect x="1003" y="25" width="41" height="22" rx="11" fill="#FFFFFF" stroke="#171A20" stroke-opacity="0.2"/>
<text x="1023" y="40" fill="#171A20" font-family="Consolas, monospace" font-size="11" text-anchor="middle">EN</text>
<text x="1066" y="40" fill="#555E6B" font-family="Consolas, monospace" font-size="11" text-anchor="middle">NO</text>
<circle cx="1122" cy="36" r="14" fill="#F1F2EF" stroke="#171A20" stroke-opacity="0.1"/>
<circle cx="1122" cy="36" r="5" fill="#555E6B"/>
<g stroke="#555E6B" stroke-width="1.4">
<line x1="1122" y1="26" x2="1122" y2="29"/><line x1="1122" y1="43" x2="1122" y2="46"/>
<line x1="1112" y1="36" x2="1115" y2="36"/><line x1="1129" y1="36" x2="1132" y2="36"/>
</g>
<rect x="1156" y="20" width="164" height="32" rx="8" fill="#0E8C72"/>
<text x="1216" y="41" fill="#FFFFFF" font-size="13" font-weight="600" text-anchor="middle">Download CV</text>
<line x1="1290" y1="26" x2="1290" y2="46" stroke="#FFFFFF" stroke-opacity="0.4"/>
<path d="M1300 33 l6 6 l6 -6" fill="none" stroke="#FFFFFF" stroke-width="1.8"/>
<!-- HERO (Norwegian locale shown — demonstrates NO string lengths + light theme) -->
<text x="120" y="196" fill="#0E8C72" font-family="Consolas, monospace" font-size="12" letter-spacing="2">SYSTEMUTVIKLER · TØNSBERG</text>
<text x="120" y="262" fill="#171A20" font-size="61" font-weight="600" letter-spacing="-1">Connor Babbington</text>
<text x="120" y="316" fill="#171A20" font-size="26" font-weight="500">Jeg utvikler og drifter websystemer.</text>
<text x="120" y="356" fill="#555E6B" font-size="18">Åtte års erfaring med fagsystemer i britisk offentlig sektor —</text>
<text x="120" y="384" fill="#555E6B" font-size="18">nå bygger jeg fullstack-løsninger fra Tønsberg.</text>
<path d="M120 424 H360 l12 12 H560" fill="none" stroke="#0E8C72" stroke-width="1.5"/>
<circle cx="566" cy="436" r="4" fill="#0E8C72"/>
<text x="582" y="441" fill="#555E6B" font-family="Consolas, monospace" font-size="12">status: åpen for muligheter</text>
<g font-family="Consolas, monospace" font-size="12">
<rect x="120" y="466" width="158" height="30" rx="15" fill="#FFFFFF" stroke="#171A20" stroke-opacity="0.1"/>
<text x="199" y="485" fill="#555E6B" text-anchor="middle">Bosatt i Tønsberg</text>
<rect x="290" y="466" width="200" height="30" rx="15" fill="#FFFFFF" stroke="#171A20" stroke-opacity="0.1"/>
<text x="390" y="485" fill="#555E6B" text-anchor="middle">Gyldig oppholdstillatelse</text>
<rect x="502" y="466" width="230" height="30" rx="15" fill="#FFFFFF" stroke="#171A20" stroke-opacity="0.1"/>
<text x="617" y="485" fill="#555E6B" text-anchor="middle">Remote / hybrid / oppmøte</text>
<rect x="744" y="466" width="230" height="30" rx="15" fill="#FFFFFF" stroke="#171A20" stroke-opacity="0.1"/>
<text x="859" y="485" fill="#555E6B" text-anchor="middle">Engelsk morsmål · Norsk B1</text>
</g>
<rect x="120" y="530" width="156" height="44" rx="8" fill="#0E8C72"/>
<text x="198" y="557" fill="#FFFFFF" font-size="15" font-weight="600" text-anchor="middle">Se prosjekter</text>
<rect x="292" y="530" width="196" height="44" rx="8" fill="none" stroke="#171A20" stroke-opacity="0.2"/>
<text x="390" y="557" fill="#171A20" font-size="15" text-anchor="middle">Last ned CV · pdf</text>
<!-- portrait -->
<rect x="1020" y="150" width="300" height="375" rx="16" fill="#FFFFFF" stroke="#171A20" stroke-opacity="0.1" filter="url(#cardShadow)"/>
<circle cx="1170" cy="290" r="72" fill="#E4E6E1"/>
<path d="M1080 525 q90 -110 180 0" fill="#E4E6E1"/>
<text x="1170" y="300" fill="#8A93A0" font-size="13" text-anchor="middle">[ outdoor headshot — natural grade ]</text>
<text x="1020" y="552" fill="#8A93A0" font-family="Consolas, monospace" font-size="12">tønsberg, norge · 2025</text>
<!-- proof strip -->
<g filter="url(#cardShadow)">
<rect x="120" y="620" width="285" height="96" rx="12" fill="#FFFFFF" stroke="#171A20" stroke-opacity="0.1"/>
<rect x="425" y="620" width="285" height="96" rx="12" fill="#FFFFFF" stroke="#171A20" stroke-opacity="0.1"/>
<rect x="730" y="620" width="285" height="96" rx="12" fill="#FFFFFF" stroke="#171A20" stroke-opacity="0.1"/>
<rect x="1035" y="620" width="285" height="96" rx="12" fill="#FFFFFF" stroke="#171A20" stroke-opacity="0.1"/>
</g>
<text x="144" y="662" fill="#171A20" font-size="28" font-weight="600">8+ år</text>
<text x="144" y="692" fill="#8A93A0" font-family="Consolas, monospace" font-size="11" letter-spacing="1.5">ERFARING</text>
<text x="449" y="662" fill="#171A20" font-size="22" font-weight="600">Offentlig sektor (UK)</text>
<text x="449" y="692" fill="#8A93A0" font-family="Consolas, monospace" font-size="11" letter-spacing="1.5">BAKGRUNN</text>
<text x="754" y="662" fill="#171A20" font-size="22" font-weight="600">.NET · React · Docker</text>
<text x="754" y="692" fill="#8A93A0" font-family="Consolas, monospace" font-size="11" letter-spacing="1.5">KJERNESTACK</text>
<text x="1059" y="662" fill="#171A20" font-size="22" font-weight="600">Bosatt i Norge</text>
<text x="1059" y="692" fill="#8A93A0" font-family="Consolas, monospace" font-size="11" letter-spacing="1.5">OPPHOLDSTILLATELSE ✓</text>
<text x="120" y="106" fill="#8A6114" font-family="Consolas, monospace" font-size="11">M2: light theme + Norwegian locale — same geometry as M1, token swap only; accent deepened to #0E8C72 for AA contrast</text>
</svg>

After

Width:  |  Height:  |  Size: 6.9 KiB

@@ -0,0 +1,125 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 1720" font-family="Segoe UI, Arial, sans-serif">
<rect width="1440" height="1720" fill="#0B0E14"/>
<!-- header (compressed 56px scrolled state) -->
<rect width="1440" height="56" fill="#0B0E14" fill-opacity="0.9"/>
<line x1="0" y1="56" x2="1440" y2="56" stroke="#E8ECF2" stroke-opacity="0.08"/>
<rect x="120" y="14" width="28" height="28" rx="7" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.16"/>
<text x="134" y="33" fill="#E8ECF2" font-family="Consolas, monospace" font-size="12" font-weight="bold" text-anchor="middle">CB</text>
<text x="430" y="34" fill="#E8ECF2" font-size="13">Projects</text>
<line x1="430" y1="40" x2="478" y2="40" stroke="#3ECFAE" stroke-width="2"/>
<text x="510" y="34" fill="#9AA4B2" font-size="13">Experience</text>
<text x="610" y="34" fill="#9AA4B2" font-size="13">About</text>
<text x="680" y="34" fill="#9AA4B2" font-size="13">Contact</text>
<rect x="1176" y="13" width="144" height="30" rx="8" fill="#3ECFAE"/>
<text x="1238" y="33" fill="#062A22" font-size="12" font-weight="600" text-anchor="middle">Download CV ▾</text>
<!-- case study header -->
<text x="120" y="140" fill="#3ECFAE" font-family="Consolas, monospace" font-size="12" letter-spacing="2">CASE STUDY · PERSONAL PRODUCT</text>
<text x="120" y="204" fill="#E8ECF2" font-size="49" font-weight="600" letter-spacing="-0.7">JobTrack</text>
<rect x="340" y="172" width="92" height="28" rx="14" fill="#11151D" stroke="#3ECFAE" stroke-opacity="0.4"/>
<circle cx="358" cy="186" r="3.5" fill="#3ECFAE"/>
<text x="370" y="191" fill="#3ECFAE" font-family="Consolas, monospace" font-size="11">ACTIVE</text>
<text x="120" y="248" fill="#9AA4B2" font-size="18">A job-application workspace covering the full journey from application to follow-up.</text>
<g font-family="Consolas, monospace" font-size="12" fill="#E8ECF2">
<rect x="120" y="276" width="72" height="28" rx="14" fill="#171C26"/><text x="156" y="294" text-anchor="middle">.NET 9</text>
<rect x="200" y="276" width="66" height="28" rx="14" fill="#171C26"/><text x="233" y="294" text-anchor="middle">React</text>
<rect x="274" y="276" width="110" height="28" rx="14" fill="#171C26"/><text x="329" y="294" text-anchor="middle">TypeScript</text>
<rect x="392" y="276" width="76" height="28" rx="14" fill="#171C26"/><text x="430" y="294" text-anchor="middle">SQLite</text>
<rect x="476" y="276" width="86" height="28" rx="14" fill="#171C26"/><text x="519" y="294" text-anchor="middle">FastAPI</text>
<rect x="570" y="276" width="76" height="28" rx="14" fill="#171C26"/><text x="608" y="294" text-anchor="middle">Ollama</text>
<rect x="654" y="276" width="76" height="28" rx="14" fill="#171C26"/><text x="692" y="294" text-anchor="middle">Docker</text>
</g>
<text x="1200" y="294" fill="#3ECFAE" font-size="14">Repository ↗</text>
<!-- hero screenshot: browser frame -->
<rect x="120" y="336" width="1200" height="520" rx="16" fill="#171C26" stroke="#E8ECF2" stroke-opacity="0.16"/>
<rect x="120" y="336" width="1200" height="40" rx="16" fill="#11151D"/>
<rect x="120" y="360" width="1200" height="16" fill="#11151D"/>
<circle cx="148" cy="356" r="5" fill="#5C6675"/><circle cx="166" cy="356" r="5" fill="#5C6675"/><circle cx="184" cy="356" r="5" fill="#5C6675"/>
<rect x="560" y="346" width="320" height="20" rx="10" fill="#171C26"/>
<text x="720" y="360" fill="#5C6675" font-family="Consolas, monospace" font-size="11" text-anchor="middle">jobtrack.local</text>
<!-- mock app content -->
<rect x="150" y="400" width="220" height="426" rx="8" fill="#11151D"/>
<rect x="390" y="400" width="900" height="60" rx="8" fill="#11151D"/>
<text x="410" y="436" fill="#9AA4B2" font-size="14">Applications · filters · search</text>
<g fill="#11151D">
<rect x="390" y="474" width="900" height="52" rx="6"/>
<rect x="390" y="534" width="900" height="52" rx="6"/>
<rect x="390" y="594" width="900" height="52" rx="6"/>
<rect x="390" y="654" width="900" height="52" rx="6"/>
<rect x="390" y="714" width="900" height="52" rx="6"/>
</g>
<g font-family="Consolas, monospace" font-size="11">
<rect x="1160" y="488" width="92" height="24" rx="12" fill="#0F2B24"/><text x="1206" y="504" fill="#3ECFAE" text-anchor="middle">INTERVIEW</text>
<rect x="1160" y="548" width="92" height="24" rx="12" fill="#2E2410"/><text x="1206" y="564" fill="#E5A93D" text-anchor="middle">WAITING</text>
<rect x="1160" y="608" width="92" height="24" rx="12" fill="#171C26"/><text x="1206" y="624" fill="#9AA4B2" text-anchor="middle">APPLIED</text>
</g>
<text x="720" y="800" fill="#5C6675" font-size="13" text-anchor="middle">[ 2× capture: applications table with status filters — seeded demo data ]</text>
<!-- TL;DR box -->
<rect x="120" y="896" width="800" height="180" rx="12" fill="#171C26"/>
<rect x="120" y="896" width="3" height="180" fill="#3ECFAE"/>
<text x="148" y="932" fill="#5C6675" font-family="Consolas, monospace" font-size="11" letter-spacing="1.5">TL;DR</text>
<text x="148" y="964" fill="#E8ECF2" font-size="15"><tspan font-weight="600">What</tspan> Full-stack job-application tracker: pipeline, correspondence, attachments, analytics</text>
<text x="148" y="992" fill="#E8ECF2" font-size="15"><tspan font-weight="600">Why</tspan> Real problem — my own job search needed production-grade tooling</text>
<text x="148" y="1020" fill="#E8ECF2" font-size="15"><tspan font-weight="600">Stack</tspan> React + ASP.NET Core + SQLite · FastAPI/Ollama AI service · Docker Compose</text>
<text x="148" y="1048" fill="#E8ECF2" font-size="15"><tspan font-weight="600">Role</tspan> Everything: product, backend, frontend, ops, security</text>
<!-- mini TOC -->
<g font-size="13">
<text x="1080" y="932" fill="#5C6675" font-family="Consolas, monospace" font-size="11" letter-spacing="1.5">ON THIS PAGE</text>
<text x="1080" y="964" fill="#9AA4B2">Problem</text>
<rect x="1064" y="982" width="2" height="16" fill="#3ECFAE"/>
<text x="1080" y="994" fill="#E8ECF2">Architecture</text>
<text x="1080" y="1024" fill="#9AA4B2">Decisions</text>
<text x="1080" y="1054" fill="#9AA4B2">Security</text>
<text x="1080" y="1084" fill="#9AA4B2">Screenshots</text>
<text x="1080" y="1114" fill="#9AA4B2">What's next</text>
</g>
<!-- Architecture section -->
<text x="120" y="1160" fill="#3ECFAE" font-family="Consolas, monospace" font-size="12" letter-spacing="2">ARCHITECTURE</text>
<text x="120" y="1204" fill="#E8ECF2" font-size="31" font-weight="600">Four services, one compose file</text>
<!-- diagram -->
<rect x="120" y="1240" width="1200" height="300" rx="12" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.08"/>
<!-- nodes -->
<g>
<rect x="170" y="1330" width="180" height="72" rx="8" fill="#171C26" stroke="#E8ECF2" stroke-opacity="0.16"/>
<text x="260" y="1360" fill="#E8ECF2" font-size="14" text-anchor="middle">React SPA</text>
<text x="260" y="1382" fill="#5C6675" font-family="Consolas, monospace" font-size="11" text-anchor="middle">nginx · PWA</text>
<rect x="440" y="1330" width="200" height="72" rx="8" fill="#171C26" stroke="#3ECFAE" stroke-opacity="0.5"/>
<text x="540" y="1360" fill="#E8ECF2" font-size="14" text-anchor="middle">ASP.NET Core API</text>
<text x="540" y="1382" fill="#5C6675" font-family="Consolas, monospace" font-size="11" text-anchor="middle">.NET 9 · auth · rules</text>
<rect x="730" y="1276" width="180" height="64" rx="8" fill="#171C26" stroke="#E8ECF2" stroke-opacity="0.16"/>
<text x="820" y="1302" fill="#E8ECF2" font-size="14" text-anchor="middle">SQLite + files</text>
<text x="820" y="1322" fill="#5C6675" font-family="Consolas, monospace" font-size="11" text-anchor="middle">EF Core · attachments</text>
<rect x="730" y="1364" width="180" height="64" rx="8" fill="#171C26" stroke="#E8ECF2" stroke-opacity="0.16"/>
<text x="820" y="1390" fill="#E8ECF2" font-size="14" text-anchor="middle">AI service</text>
<text x="820" y="1410" fill="#5C6675" font-family="Consolas, monospace" font-size="11" text-anchor="middle">FastAPI → Ollama</text>
<rect x="1000" y="1330" width="180" height="72" rx="8" fill="#171C26" stroke="#E5A93D" stroke-opacity="0.5"/>
<text x="1090" y="1360" fill="#E8ECF2" font-size="14" text-anchor="middle">Gmail API</text>
<text x="1090" y="1382" fill="#8A6114" font-family="Consolas, monospace" font-size="11" text-anchor="middle">external · OAuth2</text>
</g>
<!-- edges -->
<g stroke="#3ECFAE" stroke-width="1.5" fill="none">
<path d="M350 1366 H440"/>
<path d="M640 1352 L730 1308"/>
<path d="M640 1380 L730 1396"/>
</g>
<path d="M640 1366 H960 M960 1366 H1000" stroke="#E5A93D" stroke-width="1.5" stroke-dasharray="4 4" fill="none"/>
<text x="380" y="1356" fill="#5C6675" font-family="Consolas, monospace" font-size="10">/api</text>
<text x="930" y="1356" fill="#8A6114" font-family="Consolas, monospace" font-size="10">import</text>
<text x="148" y="1276" fill="#5C6675" font-family="Consolas, monospace" font-size="11">hover: node highlights its edges, others dim to 60% (desktop only — fully legible static)</text>
<!-- decisions preview -->
<text x="120" y="1600" fill="#3ECFAE" font-family="Consolas, monospace" font-size="12" letter-spacing="2">KEY DECISIONS &amp; TRADE-OFFS</text>
<text x="120" y="1644" fill="#E8ECF2" font-size="16"><tspan fill="#3ECFAE" font-family="Consolas, monospace">01</tspan> Local AI (Ollama) over a cloud API — privacy of job-search data + zero per-call cost, traded against setup complexity.</text>
<text x="120" y="1676" fill="#E8ECF2" font-size="16"><tspan fill="#3ECFAE" font-family="Consolas, monospace">02</tspan> No offline cache in the PWA — deliberate: frequent deploys made stale builds a worse failure than offline gaps.</text>
</svg>

After

Width:  |  Height:  |  Size: 9.7 KiB

+133
View File
@@ -0,0 +1,133 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 1240" font-family="Segoe UI, Arial, sans-serif">
<rect width="900" height="1240" fill="#05070B"/>
<text x="60" y="48" fill="#E5A93D" font-family="Consolas, monospace" font-size="12">M4: mobile 390px — homepage (left) · nav overlay open (right)</text>
<!-- ============ PHONE 1: homepage ============ -->
<rect x="60" y="80" width="390" height="1100" rx="24" fill="#0B0E14" stroke="#E8ECF2" stroke-opacity="0.16"/>
<!-- slim header 56 -->
<line x1="60" y1="136" x2="450" y2="136" stroke="#E8ECF2" stroke-opacity="0.08"/>
<rect x="84" y="94" width="28" height="28" rx="7" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.16"/>
<text x="98" y="113" fill="#E8ECF2" font-family="Consolas, monospace" font-size="11" font-weight="bold" text-anchor="middle">CB</text>
<!-- CV icon button -->
<rect x="330" y="94" width="40" height="28" rx="7" fill="#3ECFAE"/>
<path d="M350 100 v10 m-4 -4 l4 4 l4 -4 M344 114 h12" stroke="#062A22" stroke-width="1.6" fill="none"/>
<!-- burger -->
<g stroke="#E8ECF2" stroke-width="1.6">
<line x1="390" y1="102" x2="414" y2="102"/><line x1="390" y1="110" x2="414" y2="110"/><line x1="390" y1="118" x2="414" y2="118"/>
</g>
<!-- hero -->
<text x="84" y="192" fill="#3ECFAE" font-family="Consolas, monospace" font-size="10" letter-spacing="1.5">SYSTEMS DEVELOPER · NORWAY</text>
<text x="84" y="234" fill="#E8ECF2" font-size="34" font-weight="600">Connor</text>
<text x="84" y="272" fill="#E8ECF2" font-size="34" font-weight="600">Babbington</text>
<text x="84" y="308" fill="#9AA4B2" font-size="15">I design, build and run web systems.</text>
<text x="84" y="332" fill="#9AA4B2" font-size="15">8+ years in UK local government —</text>
<text x="84" y="356" fill="#9AA4B2" font-size="15">now building full-stack in Norway.</text>
<path d="M84 384 H240 l8 8 H330" fill="none" stroke="#3ECFAE" stroke-width="1.5"/>
<circle cx="335" cy="392" r="3.5" fill="#3ECFAE"/>
<!-- chips 2 rows -->
<g font-family="Consolas, monospace" font-size="10.5">
<rect x="84" y="410" width="128" height="26" rx="13" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.08"/>
<text x="148" y="427" fill="#9AA4B2" text-anchor="middle">Tønsberg, Norway</text>
<rect x="220" y="410" width="108" height="26" rx="13" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.08"/>
<text x="274" y="427" fill="#9AA4B2" text-anchor="middle">Work permit ✓</text>
<rect x="84" y="444" width="150" height="26" rx="13" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.08"/>
<text x="159" y="461" fill="#9AA4B2" text-anchor="middle">Remote/hybrid/on-site</text>
<rect x="242" y="444" width="150" height="26" rx="13" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.08"/>
<text x="317" y="461" fill="#9AA4B2" text-anchor="middle">EN native · NO B1</text>
</g>
<!-- stacked CTAs full width, 48px -->
<rect x="84" y="494" width="342" height="48" rx="8" fill="#3ECFAE"/>
<text x="255" y="524" fill="#062A22" font-size="15" font-weight="600" text-anchor="middle">View projects</text>
<rect x="84" y="552" width="342" height="48" rx="8" fill="none" stroke="#E8ECF2" stroke-opacity="0.16"/>
<text x="255" y="582" fill="#E8ECF2" font-size="15" text-anchor="middle">Download CV · pdf</text>
<!-- proof 2x2 -->
<g>
<rect x="84" y="628" width="165" height="72" rx="10" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.08"/>
<text x="100" y="660" fill="#E8ECF2" font-size="18" font-weight="600">8+ yrs</text>
<text x="100" y="682" fill="#5C6675" font-family="Consolas, monospace" font-size="9" letter-spacing="1">EXPERIENCE</text>
<rect x="261" y="628" width="165" height="72" rx="10" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.08"/>
<text x="277" y="660" fill="#E8ECF2" font-size="15" font-weight="600">Public sector</text>
<text x="277" y="682" fill="#5C6675" font-family="Consolas, monospace" font-size="9" letter-spacing="1">BACKGROUND</text>
<rect x="84" y="710" width="165" height="72" rx="10" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.08"/>
<text x="100" y="742" fill="#E8ECF2" font-size="15" font-weight="600">.NET · React</text>
<text x="100" y="764" fill="#5C6675" font-family="Consolas, monospace" font-size="9" letter-spacing="1">CORE STACK</text>
<rect x="261" y="710" width="165" height="72" rx="10" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.08"/>
<text x="277" y="742" fill="#E8ECF2" font-size="15" font-weight="600">In Norway</text>
<text x="277" y="764" fill="#5C6675" font-family="Consolas, monospace" font-size="9" letter-spacing="1">PERMIT ✓</text>
</g>
<!-- project card -->
<text x="84" y="836" fill="#3ECFAE" font-family="Consolas, monospace" font-size="10" letter-spacing="1.5">02 — PROJECTS</text>
<rect x="84" y="856" width="342" height="290" rx="12" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.08"/>
<rect x="84" y="856" width="342" height="170" rx="12" fill="#171C26"/>
<rect x="84" y="1010" width="342" height="16" fill="#171C26"/>
<text x="255" y="948" fill="#5C6675" font-size="11" text-anchor="middle">[ JobTrack screenshot 16:10 ]</text>
<rect x="342" y="872" width="70" height="24" rx="12" fill="#0B0E14" stroke="#3ECFAE" stroke-opacity="0.4"/>
<circle cx="356" cy="884" r="3" fill="#3ECFAE"/>
<text x="366" y="889" fill="#3ECFAE" font-family="Consolas, monospace" font-size="9.5">ACTIVE</text>
<text x="104" y="1058" fill="#E8ECF2" font-size="18" font-weight="600">JobTrack</text>
<text x="104" y="1082" fill="#9AA4B2" font-size="13">A workspace for the whole job-application journey.</text>
<g font-family="Consolas, monospace" font-size="10" fill="#9AA4B2">
<rect x="104" y="1096" width="56" height="22" rx="11" fill="#171C26"/><text x="132" y="1111" text-anchor="middle">.NET 9</text>
<rect x="168" y="1096" width="52" height="22" rx="11" fill="#171C26"/><text x="194" y="1111" text-anchor="middle">React</text>
<rect x="228" y="1096" width="60" height="22" rx="11" fill="#171C26"/><text x="258" y="1111" text-anchor="middle">Docker</text>
</g>
<text x="104" y="1136" fill="#3ECFAE" font-size="13">Read case study →</text>
<!-- ============ PHONE 2: nav overlay ============ -->
<rect x="480" y="80" width="390" height="1100" rx="24" fill="#0B0E14" stroke="#E8ECF2" stroke-opacity="0.16"/>
<rect x="480" y="80" width="390" height="1100" rx="24" fill="#11151D" fill-opacity="0.98"/>
<!-- overlay header -->
<rect x="504" y="94" width="28" height="28" rx="7" fill="#171C26" stroke="#E8ECF2" stroke-opacity="0.16"/>
<text x="518" y="113" fill="#E8ECF2" font-family="Consolas, monospace" font-size="11" font-weight="bold" text-anchor="middle">CB</text>
<g stroke="#E8ECF2" stroke-width="1.8">
<line x1="812" y1="98" x2="832" y2="118"/><line x1="832" y1="98" x2="812" y2="118"/>
</g>
<!-- language + theme row -->
<rect x="504" y="152" width="240" height="44" rx="22" fill="#171C26" stroke="#E8ECF2" stroke-opacity="0.08"/>
<rect x="508" y="156" width="116" height="36" rx="18" fill="#0B0E14" stroke="#E8ECF2" stroke-opacity="0.16"/>
<text x="566" y="179" fill="#E8ECF2" font-family="Consolas, monospace" font-size="13" text-anchor="middle">EN</text>
<text x="686" y="179" fill="#9AA4B2" font-family="Consolas, monospace" font-size="13" text-anchor="middle">NO</text>
<circle cx="800" cy="174" r="22" fill="#171C26" stroke="#E8ECF2" stroke-opacity="0.08"/>
<path d="M806 166 a9 9 0 1 0 4 12 a8 8 0 0 1 -4 -12" fill="#9AA4B2"/>
<!-- nav stack: large targets -->
<g font-size="28" font-weight="600">
<text x="504" y="292" fill="#E8ECF2">Home</text>
<text x="504" y="368" fill="#E8ECF2">Projects</text>
<text x="504" y="444" fill="#E8ECF2">Experience</text>
<text x="504" y="520" fill="#E8ECF2">About</text>
<text x="504" y="596" fill="#E8ECF2">Contact</text>
</g>
<g font-family="Consolas, monospace" font-size="11" fill="#5C6675">
<text x="504" y="316">/</text>
<text x="504" y="392">/projects · 3</text>
<text x="504" y="468">/experience</text>
<text x="504" y="544">/about</text>
<text x="504" y="620">/contact</text>
</g>
<line x1="504" y1="660" x2="846" y2="660" stroke="#E8ECF2" stroke-opacity="0.08"/>
<!-- CV buttons -->
<rect x="504" y="692" width="342" height="48" rx="8" fill="#3ECFAE"/>
<text x="675" y="722" fill="#062A22" font-size="15" font-weight="600" text-anchor="middle">Download CV — English</text>
<rect x="504" y="752" width="342" height="48" rx="8" fill="none" stroke="#E8ECF2" stroke-opacity="0.16"/>
<text x="675" y="782" fill="#E8ECF2" font-size="15" text-anchor="middle">Last ned CV — Norsk</text>
<!-- contact shortcuts -->
<g font-family="Consolas, monospace" font-size="13" fill="#9AA4B2">
<text x="504" y="852">connor.babbington@cesnimda.co.uk ⧉</text>
<text x="504" y="888">linkedin ↗</text>
<text x="504" y="924">git.cesnimda.uk ↗</text>
</g>
<text x="504" y="1150" fill="#5C6675" font-family="Consolas, monospace" font-size="11">overlay: full-screen, body scroll locked, Esc/× closes,</text>
<text x="504" y="1168" fill="#5C6675" font-family="Consolas, monospace" font-size="11">focus trapped · targets ≥ 44px</text>
</svg>

After

Width:  |  Height:  |  Size: 9.1 KiB

+132
View File
@@ -0,0 +1,132 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 1040" font-family="Segoe UI, Arial, sans-serif">
<rect width="1440" height="1040" fill="#05070B"/>
<text x="60" y="44" fill="#E5A93D" font-family="Consolas, monospace" font-size="12">M5: navigation &amp; control states</text>
<!-- (a) default header -->
<text x="60" y="86" fill="#5C6675" font-family="Consolas, monospace" font-size="11">(a) default · 72px</text>
<rect x="60" y="100" width="1320" height="72" fill="#0B0E14" stroke="#E8ECF2" stroke-opacity="0.08"/>
<rect x="90" y="120" width="32" height="32" rx="8" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.16"/>
<text x="106" y="141" fill="#E8ECF2" font-family="Consolas, monospace" font-size="13" font-weight="bold" text-anchor="middle">CB</text>
<text x="380" y="141" fill="#9AA4B2" font-size="14">Projects</text>
<text x="470" y="141" fill="#9AA4B2" font-size="14">Experience</text>
<text x="580" y="141" fill="#9AA4B2" font-size="14">About</text>
<text x="655" y="141" fill="#9AA4B2" font-size="14">Contact</text>
<rect x="960" y="122" width="88" height="28" rx="14" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.08"/>
<rect x="963" y="125" width="41" height="22" rx="11" fill="#171C26" stroke="#E8ECF2" stroke-opacity="0.16"/>
<text x="983" y="140" fill="#E8ECF2" font-family="Consolas, monospace" font-size="11" text-anchor="middle">EN</text>
<text x="1026" y="140" fill="#9AA4B2" font-family="Consolas, monospace" font-size="11" text-anchor="middle">NO</text>
<circle cx="1082" cy="136" r="14" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.08"/>
<rect x="1116" y="120" width="164" height="32" rx="8" fill="#3ECFAE"/>
<text x="1176" y="141" fill="#062A22" font-size="13" font-weight="600" text-anchor="middle">Download CV</text>
<line x1="1250" y1="126" x2="1250" y2="146" stroke="#062A22" stroke-opacity="0.3"/>
<path d="M1258 133 l6 6 l6 -6" fill="none" stroke="#062A22" stroke-width="1.8"/>
<!-- (b) scrolled -->
<text x="60" y="216" fill="#5C6675" font-family="Consolas, monospace" font-size="11">(b) scrolled · 56px · backdrop blur + hairline · hover on "Projects" (underline draw) · current page "About"</text>
<rect x="60" y="230" width="1320" height="56" fill="#0B0E14" fill-opacity="0.85" stroke="#E8ECF2" stroke-opacity="0.12"/>
<rect x="90" y="244" width="28" height="28" rx="7" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.16"/>
<text x="104" y="263" fill="#E8ECF2" font-family="Consolas, monospace" font-size="12" font-weight="bold" text-anchor="middle">CB</text>
<text x="380" y="264" fill="#E8ECF2" font-size="13">Projects</text>
<line x1="380" y1="271" x2="410" y2="271" stroke="#3ECFAE" stroke-width="2"/>
<text x="470" y="264" fill="#9AA4B2" font-size="13">Experience</text>
<text x="570" y="264" fill="#E8ECF2" font-size="13">About</text>
<line x1="570" y1="271" x2="608" y2="271" stroke="#3ECFAE" stroke-width="2" stroke-opacity="0.6"/>
<text x="645" y="264" fill="#9AA4B2" font-size="13">Contact</text>
<rect x="1136" y="243" width="144" height="30" rx="8" fill="#3ECFAE"/>
<text x="1198" y="263" fill="#062A22" font-size="12" font-weight="600" text-anchor="middle">Download CV ▾</text>
<!-- (c) CV split open -->
<text x="60" y="336" fill="#5C6675" font-family="Consolas, monospace" font-size="11">(c) CV split-button open · locale default first · file sizes · keyboard: ↓↑ Esc</text>
<rect x="60" y="350" width="164" height="32" rx="8" fill="#3ECFAE"/>
<text x="120" y="371" fill="#062A22" font-size="13" font-weight="600" text-anchor="middle">Download CV</text>
<line x1="194" y1="356" x2="194" y2="376" stroke="#062A22" stroke-opacity="0.3"/>
<path d="M202 366 l6 -6 l6 6" fill="none" stroke="#062A22" stroke-width="1.8"/>
<rect x="60" y="392" width="280" height="104" rx="12" fill="#171C26" stroke="#E8ECF2" stroke-opacity="0.16"/>
<rect x="68" y="402" width="264" height="40" rx="8" fill="#11151D"/>
<rect x="80" y="412" width="30" height="20" rx="10" fill="#0F2B24"/>
<text x="95" y="426" fill="#3ECFAE" font-family="Consolas, monospace" font-size="10" text-anchor="middle">EN</text>
<text x="122" y="427" fill="#E8ECF2" font-size="13">English CV</text>
<text x="322" y="427" fill="#5C6675" font-family="Consolas, monospace" font-size="11" text-anchor="end">pdf · 180 kB</text>
<rect x="80" y="454" width="30" height="20" rx="10" fill="#171C26" stroke="#E8ECF2" stroke-opacity="0.16"/>
<text x="95" y="468" fill="#9AA4B2" font-family="Consolas, monospace" font-size="10" text-anchor="middle">NO</text>
<text x="122" y="469" fill="#9AA4B2" font-size="13">Norsk CV</text>
<text x="322" y="469" fill="#5C6675" font-family="Consolas, monospace" font-size="11" text-anchor="end">pdf · 172 kB</text>
<!-- (d) language switch states -->
<text x="480" y="336" fill="#5C6675" font-family="Consolas, monospace" font-size="11">(d) language switch · EN active / NO active / focus-visible · thumb slides 160ms · aria toggle group</text>
<g>
<rect x="480" y="352" width="88" height="28" rx="14" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.08"/>
<rect x="483" y="355" width="41" height="22" rx="11" fill="#171C26" stroke="#E8ECF2" stroke-opacity="0.16"/>
<text x="503" y="370" fill="#E8ECF2" font-family="Consolas, monospace" font-size="11" text-anchor="middle">EN</text>
<text x="546" y="370" fill="#9AA4B2" font-family="Consolas, monospace" font-size="11" text-anchor="middle">NO</text>
<rect x="600" y="352" width="88" height="28" rx="14" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.08"/>
<rect x="644" y="355" width="41" height="22" rx="11" fill="#171C26" stroke="#E8ECF2" stroke-opacity="0.16"/>
<text x="620" y="370" fill="#9AA4B2" font-family="Consolas, monospace" font-size="11" text-anchor="middle">EN</text>
<text x="664" y="370" fill="#E8ECF2" font-family="Consolas, monospace" font-size="11" text-anchor="middle">NO</text>
<rect x="720" y="352" width="88" height="28" rx="14" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.08"/>
<rect x="718" y="350" width="92" height="32" rx="16" fill="none" stroke="#3ECFAE" stroke-width="2"/>
<rect x="723" y="355" width="41" height="22" rx="11" fill="#171C26" stroke="#E8ECF2" stroke-opacity="0.16"/>
<text x="743" y="370" fill="#E8ECF2" font-family="Consolas, monospace" font-size="11" text-anchor="middle">EN</text>
<text x="786" y="370" fill="#9AA4B2" font-family="Consolas, monospace" font-size="11" text-anchor="middle">NO</text>
</g>
<!-- (e) first-visit language hint -->
<text x="480" y="430" fill="#5C6675" font-family="Consolas, monospace" font-size="11">(e) first-visit hint (browser prefers nb-NO) · shown once · dismissible · never auto-redirects</text>
<rect x="480" y="444" width="620" height="44" rx="8" fill="#171C26" stroke="#3ECFAE" stroke-opacity="0.3"/>
<text x="500" y="471" fill="#E8ECF2" font-size="13">Denne siden finnes på norsk</text>
<rect x="700" y="452" width="66" height="28" rx="8" fill="#3ECFAE"/>
<text x="733" y="471" fill="#062A22" font-size="12" font-weight="600" text-anchor="middle">Bytt</text>
<text x="1076" y="472" fill="#9AA4B2" font-size="14" text-anchor="end"></text>
<!-- (f) buttons row -->
<text x="60" y="560" fill="#5C6675" font-family="Consolas, monospace" font-size="11">(f) buttons: primary rest/hover/focus · secondary · ghost · disabled</text>
<rect x="60" y="576" width="150" height="44" rx="8" fill="#3ECFAE"/>
<text x="135" y="603" fill="#062A22" font-size="14" font-weight="600" text-anchor="middle">Primary</text>
<rect x="230" y="572" width="150" height="44" rx="8" fill="#54DBBC"/>
<text x="305" y="599" fill="#062A22" font-size="14" font-weight="600" text-anchor="middle">Hover +1px ↑</text>
<rect x="400" y="576" width="150" height="44" rx="8" fill="#3ECFAE"/>
<rect x="396" y="572" width="158" height="52" rx="10" fill="none" stroke="#3ECFAE" stroke-width="2"/>
<text x="475" y="603" fill="#062A22" font-size="14" font-weight="600" text-anchor="middle">Focus ring</text>
<rect x="590" y="576" width="150" height="44" rx="8" fill="none" stroke="#E8ECF2" stroke-opacity="0.16"/>
<text x="665" y="603" fill="#E8ECF2" font-size="14" text-anchor="middle">Secondary</text>
<text x="790" y="603" fill="#9AA4B2" font-size="14">Ghost link</text>
<line x1="790" y1="610" x2="856" y2="610" stroke="#3ECFAE" stroke-width="2"/>
<rect x="900" y="576" width="150" height="44" rx="8" fill="#171C26"/>
<text x="975" y="603" fill="#5C6675" font-size="14" text-anchor="middle">Disabled</text>
<!-- (g) chips & status -->
<text x="60" y="690" fill="#5C6675" font-family="Consolas, monospace" font-size="11">(g) status semantics: accent=active · amber=in development · muted=archived (dot + label, never colour-only)</text>
<g font-family="Consolas, monospace" font-size="11">
<rect x="60" y="706" width="92" height="28" rx="14" fill="#11151D" stroke="#3ECFAE" stroke-opacity="0.4"/>
<circle cx="78" cy="720" r="3.5" fill="#3ECFAE"/>
<text x="90" y="725" fill="#3ECFAE">ACTIVE</text>
<rect x="168" y="706" width="150" height="28" rx="14" fill="#11151D" stroke="#E5A93D" stroke-opacity="0.4"/>
<circle cx="186" cy="720" r="3.5" fill="#E5A93D"/>
<text x="198" y="725" fill="#E5A93D">IN DEVELOPMENT</text>
<rect x="334" y="706" width="104" height="28" rx="14" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.16"/>
<circle cx="352" cy="720" r="3.5" fill="#5C6675"/>
<text x="364" y="725" fill="#9AA4B2">ARCHIVED</text>
</g>
<!-- (h) form states -->
<text x="60" y="800" fill="#5C6675" font-family="Consolas, monospace" font-size="11">(h) form: rest · focus · error (icon + message, danger ≥4.5:1) · submit-sending · success panel</text>
<text x="60" y="832" fill="#9AA4B2" font-size="13">E-mail</text>
<rect x="60" y="842" width="260" height="44" rx="8" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.16"/>
<text x="340" y="832" fill="#E8ECF2" font-size="13">E-mail</text>
<rect x="340" y="842" width="260" height="44" rx="8" fill="#11151D" stroke="#3ECFAE" stroke-width="2"/>
<text x="620" y="832" fill="#E8ECF2" font-size="13">E-mail</text>
<rect x="620" y="842" width="260" height="44" rx="8" fill="#11151D" stroke="#E5606B" stroke-width="2"/>
<text x="620" y="908" fill="#E5606B" font-size="12">⚠ Please enter a valid e-mail address</text>
<rect x="920" y="842" width="180" height="44" rx="8" fill="#3ECFAE"/>
<text x="1010" y="869" fill="#062A22" font-family="Consolas, monospace" font-size="14" text-anchor="middle">···</text>
<rect x="1130" y="830" width="250 " height="70" rx="12" fill="#171C26" stroke="#3ECFAE" stroke-opacity="0.4"/>
<text x="1156" y="860" fill="#3ECFAE" font-size="14">✓ Message sent</text>
<text x="1156" y="882" fill="#9AA4B2" font-size="12">I usually reply within a day.</text>
<!-- (i) skip link -->
<text x="60" y="972" fill="#5C6675" font-family="Consolas, monospace" font-size="11">(i) skip-link, visible on first Tab</text>
<rect x="60" y="984" width="220" height="40" rx="8" fill="#3ECFAE"/>
<text x="170" y="1009" fill="#062A22" font-size="13" font-weight="600" text-anchor="middle">Skip to content ↵</text>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

@@ -0,0 +1,91 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 1560" font-family="Segoe UI, Arial, sans-serif">
<rect width="1440" height="1560" fill="#0B0E14"/>
<text x="120" y="44" fill="#E5A93D" font-family="Consolas, monospace" font-size="12">M6: homepage lower half — projects · experience timeline · about teaser · contact band</text>
<!-- ===== PROJECTS ===== -->
<text x="120" y="110" fill="#3ECFAE" font-family="Consolas, monospace" font-size="12" letter-spacing="2">02 — PROJECTS</text>
<text x="120" y="162" fill="#E8ECF2" font-size="39" font-weight="600">Built, shipped, and running</text>
<!-- card 1: JobTrack (hover state shown) -->
<rect x="120" y="200" width="588" height="470" rx="12" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.16"/>
<rect x="120" y="200" width="588" height="280" rx="12" fill="#171C26"/>
<rect x="120" y="464" width="588" height="16" fill="#171C26"/>
<text x="414" y="348" fill="#5C6675" font-size="12" text-anchor="middle">[ JobTrack — applications table screenshot, 4px hover shift ]</text>
<rect x="600" y="220" width="88" height="26" rx="13" fill="#0B0E14" stroke="#3ECFAE" stroke-opacity="0.4"/>
<circle cx="616" cy="233" r="3.5" fill="#3ECFAE"/>
<text x="628" y="238" fill="#3ECFAE" font-family="Consolas, monospace" font-size="10">ACTIVE</text>
<text x="148" y="524" fill="#E8ECF2" font-size="24" font-weight="600">JobTrack</text>
<line x1="148" y1="532" x2="248" y2="532" stroke="#3ECFAE" stroke-width="2"/>
<text x="148" y="556" fill="#9AA4B2" font-size="14">One workspace for the whole job-application journey —</text>
<text x="148" y="576" fill="#9AA4B2" font-size="14">pipeline, correspondence, attachments, AI summaries.</text>
<g font-family="Consolas, monospace" font-size="11" fill="#9AA4B2">
<rect x="148" y="594" width="60" height="24" rx="12" fill="#171C26"/><text x="178" y="610" text-anchor="middle">.NET 9</text>
<rect x="216" y="594" width="56" height="24" rx="12" fill="#171C26"/><text x="244" y="610" text-anchor="middle">React</text>
<rect x="280" y="594" width="66" height="24" rx="12" fill="#171C26"/><text x="313" y="610" text-anchor="middle">SQLite</text>
<rect x="354" y="594" width="66" height="24" rx="12" fill="#171C26"/><text x="387" y="610" text-anchor="middle">Ollama</text>
<rect x="428" y="594" width="66" height="24" rx="12" fill="#171C26"/><text x="461" y="610" text-anchor="middle">Docker</text>
</g>
<text x="148" y="646" fill="#3ECFAE" font-size="14">Read case study →→</text>
<!-- card 2: InboxIntel (rest state) -->
<rect x="732" y="200" width="588" height="470" rx="12" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.08"/>
<rect x="732" y="200" width="588" height="280" rx="12" fill="#171C26"/>
<rect x="732" y="464" width="588" height="16" fill="#171C26"/>
<text x="1026" y="348" fill="#5C6675" font-size="12" text-anchor="middle">[ InboxIntel — draggable analytics dashboard screenshot ]</text>
<rect x="1156" y="220" width="146" height="26" rx="13" fill="#0B0E14" stroke="#E5A93D" stroke-opacity="0.4"/>
<circle cx="1172" cy="233" r="3.5" fill="#E5A93D"/>
<text x="1184" y="238" fill="#E5A93D" font-family="Consolas, monospace" font-size="10">IN DEVELOPMENT</text>
<text x="760" y="524" fill="#E8ECF2" font-size="24" font-weight="600">InboxIntel</text>
<text x="760" y="556" fill="#9AA4B2" font-size="14">Gmail analytics and safe bulk cleanup — Clean Architecture,</text>
<text x="760" y="576" fill="#9AA4B2" font-size="14">encrypted OAuth tokens, preview-before-delete by design.</text>
<g font-family="Consolas, monospace" font-size="11" fill="#9AA4B2">
<rect x="760" y="594" width="60" height="24" rx="12" fill="#171C26"/><text x="790" y="610" text-anchor="middle">.NET 8</text>
<rect x="828" y="594" width="100" height="24" rx="12" fill="#171C26"/><text x="878" y="610" text-anchor="middle">PostgreSQL</text>
<rect x="936" y="594" width="56" height="24" rx="12" fill="#171C26"/><text x="964" y="610" text-anchor="middle">React</text>
<rect x="1000" y="594" width="96" height="24" rx="12" fill="#171C26"/><text x="1048" y="610" text-anchor="middle">Gmail API</text>
</g>
<text x="760" y="646" fill="#3ECFAE" font-size="14">Read case study →</text>
<!-- slim homelab card -->
<rect x="120" y="694" width="1200" height="92" rx="12" fill="#11151D" stroke="#E8ECF2" stroke-opacity="0.08"/>
<g stroke="#3ECFAE" stroke-width="1.3" fill="none" opacity="0.8">
<rect x="152" y="722" width="24" height="16" rx="2"/><rect x="152" y="744" width="24" height="16" rx="2"/>
<path d="M176 730 h20 v22 h-20 M186 730 v-8 h30"/>
</g>
<text x="240" y="732" fill="#E8ECF2" font-size="18" font-weight="600">Self-hosted infrastructure lab</text>
<text x="240" y="758" fill="#9AA4B2" font-size="14">Ubuntu · Docker services · reverse proxy · auth · monitoring · Gitea (this site's own git remote)</text>
<text x="1180" y="746" fill="#3ECFAE" font-size="14">Explore →</text>
<!-- ===== EXPERIENCE ===== -->
<text x="120" y="884" fill="#3ECFAE" font-family="Consolas, monospace" font-size="12" letter-spacing="2">03 — EXPERIENCE</text>
<text x="120" y="936" fill="#E8ECF2" font-size="39" font-weight="600">Where I've worked</text>
<!-- timeline spine -->
<line x1="160" y1="972" x2="160" y2="1270" stroke="#E8ECF2" stroke-opacity="0.12" stroke-width="1.5"/>
<!-- featured -->
<circle cx="160" cy="990" r="5" fill="#3ECFAE"/>
<text x="196" y="996" fill="#E8ECF2" font-size="20" font-weight="600">System Developer — Warwickshire County Council</text>
<text x="196" y="1020" fill="#5C6675" font-family="Consolas, monospace" font-size="12">2015 2023 · UK public sector · full-stack</text>
<text x="196" y="1050" fill="#9AA4B2" font-size="15">· Replaced spreadsheet-heavy workflows with reliable internal systems used across the council</text>
<text x="196" y="1076" fill="#9AA4B2" font-size="15">· Built and maintained full-stack applications in C#, Python, Ruby on Rails, SQL and JavaScript</text>
<text x="196" y="1102" fill="#9AA4B2" font-size="15">· Owned deployments, permissions hardening and production troubleshooting on live systems</text>
<!-- compact items -->
<circle cx="160" cy="1150" r="4" fill="#5C6675"/>
<text x="196" y="1156" fill="#9AA4B2" font-size="14">2017 2021 · Sales Representative · Royal Vapes</text>
<circle cx="160" cy="1188" r="4" fill="#5C6675"/>
<text x="196" y="1194" fill="#9AA4B2" font-size="14">2016 2018 · Bartender · The Hodcarrier</text>
<circle cx="160" cy="1226" r="4" fill="#5C6675"/>
<text x="196" y="1232" fill="#9AA4B2" font-size="14">2014 2015 · Receptionist · Nuffield Health</text>
<circle cx="160" cy="1264" r="4" fill="#5C6675"/>
<text x="196" y="1270" fill="#9AA4B2" font-size="14">2012 2015 · Extended Diploma NVQ L3 in ICT · Warwickshire College</text>
<text x="196" y="1300" fill="#5C6675" font-family="Consolas, monospace" font-size="12">earlier customer-facing roles — kept for honesty, de-emphasised · timeline draws on scroll (A8)</text>
<!-- ===== CONTACT BAND ===== -->
<rect x="120" y="1360" width="1200" height="140" rx="16" fill="#171C26"/>
<text x="160" y="1418" fill="#E8ECF2" font-size="28" font-weight="600">Looking for a systems developer in Norway?</text>
<text x="160" y="1450" fill="#9AA4B2" font-size="15">I usually reply within a day — e-mail is fastest.</text>
<rect x="880" y="1404" width="300" height="48" rx="8" fill="#3ECFAE"/>
<text x="1030" y="1434" fill="#062A22" font-size="15" font-weight="600" text-anchor="middle">connor.babbington@cesnimda.co.uk ⧉</text>
<text x="1216" y="1434" fill="#062A22" font-size="0">copy</text>
<text x="1230" y="1432" fill="#9AA4B2" font-size="14">Contact form →</text>
</svg>

After

Width:  |  Height:  |  Size: 7.6 KiB

+116
View File
@@ -0,0 +1,116 @@
# MOCKUPS.md
Master mockup document. High-fidelity SVG boards live beside this file (`M1…M6.svg`); this document specifies every required state, including those not economical to board. All measurements reference SPACING_SYSTEM tokens; colours reference COLOUR_SYSTEM tokens.
Boards:
- **M1** `M1-home-desktop-dark.svg` — homepage hero + proof strip + skills (dark, 1440)
- **M2** `M2-home-desktop-light.svg` — same region, light theme
- **M3** `M3-case-study-dark.svg` — JobTrack case-study page (dark, 1440)
- **M4** `M4-mobile-dark.svg` — mobile homepage + open nav overlay (390)
- **M5** `M5-header-states.svg` — navigation states, language switch, CV split button
- **M6** `M6-projects-experience-contact.svg` — homepage lower half (projects cards, timeline, contact band)
---
## 1. Homepage — hero + narrative flow (M1/M2)
```
┌────────────────────────────────────────────────────────────────────────┐
│ HEADER 72px: [CB●] Projects Experience About Contact │ EN|NO ☾ [CV ▾] │
├────────────────────────────────────────────────────────────────────────┤
│ (faint dot-grid + accent halo, top-left biased) │
│ │
│ mono-label: SYSTEMS DEVELOPER · TØNSBERG, NORWAY ┌──────────┐ │
│ display: Connor Babbington │ portrait │ │
│ h3-weight: I design, build and run web systems. │ hairline │ │
│ body-lg: Eight-plus years delivering internal │ frame, │ │
│ software for UK local government — now │ mono │ │
│ building full-stack products in Norway. │ caption │ │
│ ── trace line ──┐___________ ● status: open to work └──────────┘ │
│ │
│ chips: [Tønsberg, Norway] [Work permit ✓] [Remote/hybrid/on-site] │
│ [English native · Norsk B1] │
│ CTAs: [■ View projects] [□ Download CV · pdf] │
├────────────────────────────────────────────────────────────────────────┤
│ PROOF STRIP (4 tiles, surface-1, hairline): 8+ YRS · PUBLIC SECTOR · │
│ .NET/REACT/DOCKER · BASED IN NORWAY — mono labels, stat numerals │
└────────────────────────────────────────────────────────────────────────┘
```
- Hero text column 7/12 cols; portrait 4/12, offset 1. Portrait: outdoor headshot, 4:5, radius 16, duotone in dark.
- Scroll behaviour: header compresses at 120px; sections reveal per A2.
- Hover states: CTAs per MICRO_INTERACTIONS buttons; portrait has no hover (non-interactive).
## 2. Skills section (M1 lower)
Three `surface-1` cards, 4/12 each, mono-labels `01 — DEVELOPMENT` / `02 — DEVOPS & INFRASTRUCTURE` / `03 — PRACTICES`; one context sentence (ink-muted) + chip rows. Card hover: border-strong. No proficiency bars.
## 3. Projects section — case-study cards (M6)
Two large cards (6/12 each): screenshot bleeding to top frame edge (browser-chrome mock), status chip overlaid top-right (`ACTIVE` accent / `IN DEVELOPMENT` amber), h3 title, 1-line problem statement, stack chips, ghost link `Read case study →`. Third slim full-width card for homelab: no screenshot; small topology glyph + one line. Hover per A3 (4px screenshot shift, border glow, arrow nudge).
## 4. Experience timeline (M6)
Left hairline spine with period dots. Featured item (System Developer, Warwickshire County Council, 20152023): expanded — role h4, employer + location mono-meta, 3 outcome bullets. Earlier roles: compact one-liners at 60% emphasis (`20172021 · Sales Representative · Royal Vapes` etc.). Education node at bottom. Timeline draws on entry (A8).
## 5. About section
7/12 text (3 short paragraphs per CONTENT_STRATEGY), 4/12 photo (same portrait, natural grade in light). Language chips repeated (`English — native` `Norsk — B1, aktiv utvikling`). Interests one mono-meta line, no icons.
## 6. Contact (M6 band + page)
Homepage band: `surface-2`, h2 "Looking for a systems developer in Norway?" / NO: "Ser dere etter en systemutvikler?", primary e-mail button (click-to-copy), secondary "Contact form →".
Contact page: 6/12 form (name/e-mail/message, labels above, per MICRO_INTERACTIONS form), 5/12 direct channels card: e-mail (copy), LinkedIn, git.cesnimda.uk, response-time note. Success state per A9.
## 7. Navigation states (M5)
Boards show: (a) default header, (b) scrolled/compressed with blur, (c) CV split-button open (EN/NO menu with file sizes), (d) language switch EN-active vs NO-active with sliding thumb, (e) focus-visible rings on nav item + toggle, (f) mobile header + full-screen overlay (nav stack, language segmented control, theme toggle, CV buttons, contact shortcuts).
## 8. Mobile layouts (M4)
390px reference. Order: slim header (56px: monogram · CV icon-button · burger) → mono-label + name (40px) → summary → chips (wrap, 2 rows) → CTAs stacked full-width → proof strip 2×2 tiles → skills cards stacked → project cards full-width (screenshot 16:10) → timeline (spine indented 16px) → about → contact band → footer. Touch targets ≥44px; no parallax; reveals opacity-only.
## 9. Dark + light (M1 vs M2)
Identical geometry; token swap only. Light: shadows-card active on cards, dot-grid at 5% instead of 8%, accent `#0E8C72`, portrait natural. Boards demonstrate both to prove parity.
## 10. Loading states
Specified in MOTION_GUIDELINES §4; visually: skeleton = `surface-2` rounded block, aspect-locked, mono caption `loading capture…` bottom-left, no shimmer sweep (shimmer reads as ad-tech; static + cross-fade is calmer). Form submit dots and language cross-fade per A7/A9.
## 11. Language switch UX (M5 detail)
- Segmented `EN | NO` control, header right cluster, thumb slide 160ms.
- Switching maps current page → same page other locale (URL strategy per IA §5); content cross-fade per A7; scroll ratio preserved.
- First-visit hint (browser prefers nb): dismissible one-line banner under header: `Denne siden finnes på norsk → [Bytt] [×]` — shown once, never auto-redirect.
- All chrome strings localise with content (nav labels, CV button, form labels, alt text, skip-link).
## 12. Case-study page (M3)
```
┌ header ────────────────────────────────────────────────────────────────┐
│ mono-label: CASE STUDY · PERSONAL PRODUCT │
│ h1: JobTrack [ACTIVE ●] │
│ body-lg: A job-application workspace covering the full journey │
│ from application to follow-up. │
│ chips: .NET 9 · React · TypeScript · SQLite · FastAPI · Ollama · │
│ Docker links: [Repository ↗] │
├─ hero screenshot (browser frame, full-bleed to 1200) ─────────────────┤
├─ TL;DR box (surface-2, 3px accent left edge): What/Why/Stack/Role ────┤
│ ┌ mini-TOC (sticky) ──┐ │
│ ## Problem & context (72ch) │ Problem │ │
│ ## Architecture │ Architecture ● │ │
│ [diagram breakout 1200px] │ Decisions │ │
│ ## Key decisions & trade-offs │ Security │ │
│ numbered blocks: choice/alt/why │ Outcome │ │
│ ## Security & production notes │ Next │ │
│ ## Screenshots (lightbox gallery) └─────────────────────┘ │
│ ## What I'd improve next │
├─ footer nav: ← InboxIntel | All projects ─────────────────────────────┤
```
Diagram style per COLOUR_SYSTEM §3.5: surface nodes, accent flow, amber external systems (Gmail API), mono labels.
## 13. Asset integration notes
- **Portraits:** outdoor headshot → hero/about; square crop → favicon-adjacent/OG fallback; suit photo → not used on site (kept for LinkedIn/CV).
- **JobTrack media plan** (from `website_details.md`): applications table, job-details dialog, Gmail import view, dashboard analytics — 4 captures + 1 architecture diagram + workflow diagram.
- **InboxIntel media plan:** dashboard grid, cleanup preview/confirm flow, architecture diagram (Clean Architecture layers), sync-worker sequence sketch.
- Screenshots need a capture pass at 2× on seeded demo data — **flagged as a Phase 3 prerequisite task** (no real personal job-hunt data on the public site; seed fictional companies).