The local admin stays private. Content is created here, passed to the Tailscale API, then synchronized through the service that owns each type of data.
+ +Sends one real request to the online Vercel chatbot using the current portfolio content.
diff --git a/admin/src/style.css b/admin/src/style.css index 40c798b..ab41699 100644 --- a/admin/src/style.css +++ b/admin/src/style.css @@ -433,3 +433,97 @@ button{color:inherit} grid-column:auto; } } + + +/* Private admin integration map */ +.admin-pipeline-panel{ + grid-column:1 / -1; +} + +.admin-pipeline-map{ + display:grid; + grid-template-columns:minmax(130px,.8fr) auto minmax(150px,.9fr) auto minmax(0,2fr); + gap:10px; + align-items:center; + margin-top:16px; +} + +.pipeline-services{ + display:grid; + grid-template-columns:repeat(2,minmax(0,1fr)); + gap:8px; +} + +.pipeline-node{ + display:grid; + gap:4px; + min-height:88px; + padding:13px; + border:1px solid var(--line); + border-radius:11px; + background:#0f0c13; +} + +.pipeline-node.primary{ + border-color:rgba(242,168,212,.28); + background:linear-gradient(145deg,rgba(242,168,212,.08),transparent),#0f0c13; +} + +.pipeline-node small{ + color:#786b7e; + font:700 8px/1.2 monospace; +} + +.pipeline-node strong{ + color:#f0e6f2; + font-size:12px; +} + +.pipeline-node span{ + color:#8f8296; + font-size:9px; + line-height:1.4; +} + +.pipeline-arrow{ + color:#5bcefa; + font:700 18px/1 monospace; +} + +.pipeline-note-grid{ + display:grid; + grid-template-columns:repeat(2,minmax(0,1fr)); + gap:7px; + margin-top:12px; +} + +.pipeline-note-grid span{ + padding:8px 10px; + border:1px solid var(--line); + border-radius:8px; + background:#0e0b12; + color:#918596; + font-size:9px; +} + +.pipeline-note-grid b{ + color:#d8cbdc; +} + +@media(max-width:900px){ + .admin-pipeline-map{ + grid-template-columns:1fr; + } + + .pipeline-arrow{ + transform:rotate(90deg); + justify-self:center; + } +} + +@media(max-width:620px){ + .pipeline-services, + .pipeline-note-grid{ + grid-template-columns:1fr; + } +} diff --git a/client/blog-astro/src/pages/index.astro b/client/blog-astro/src/pages/index.astro index 6638d23..0e6cbe9 100644 --- a/client/blog-astro/src/pages/index.astro +++ b/client/blog-astro/src/pages/index.astro @@ -16,6 +16,12 @@ const comics = Array.isArray(webcomicIndex?.comics) ? webcomicIndex.comics : []; +const featured = [ + { title: 'Digital Forensics', category: 'DFIR', description: 'From evidence collection to timelines and incident reconstruction.', icon: '◈', href: '#ctf-writeups' }, + { title: 'Computer Systems', category: 'SYSTEMS', description: 'Networks, operating systems and how things work beneath the interface.', icon: '⌘', href: '#systems-notes' }, + { title: 'Creative Side Quests', category: 'WEBCOMIC', description: 'A softer illustrated corner for stories and tiny experiments.', icon: '✿', href: '#webcomic' }, +]; + const recent = [ ...blogPosts.map((item) => ({ ...item, @@ -283,13 +289,19 @@ const hrefFor = (item, kind) => {Explore practical computer systems, cybersecurity, and creative side quests while the published notebook grows.
+{item.description}
+ Explore collection ↗ + + ))} +Published posts and writeups are still empty right now. New entries will appear automatically after they're published through the private content studio.
+
Challenge notes, evidence,
@@ -507,7 +547,7 @@ const hrefFor = (item, kind) => {
>
Computer systems, software,
@@ -633,7 +673,7 @@ const hrefFor = (item, kind) => {
>
Small illustrated stories,
diff --git a/client/blog-astro/src/styles/blog.css b/client/blog-astro/src/styles/blog.css
index 117b7b5..1a6a7a6 100644
--- a/client/blog-astro/src/styles/blog.css
+++ b/client/blog-astro/src/styles/blog.css
@@ -698,3 +698,72 @@ main{
transition:none!important;
}
}
+
+
+/* Editorial entrance: real navigation before the first article is published */
+.featured-section{padding:55px 0 10px}
+.featured-heading{max-width:680px;margin-bottom:22px}
+.featured-kicker{font-size:10px;font-weight:800;letter-spacing:.16em;color:var(--blue)}
+.featured-heading h2{margin:9px 0;color:var(--text);font-size:clamp(30px,4vw,50px);letter-spacing:-.04em}
+.featured-heading p{color:var(--muted);font-size:13px;line-height:1.65}
+.featured-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:15px}
+.featured-card{position:relative;display:flex;flex-direction:column;min-height:235px;padding:23px;border:1px solid var(--line);border-radius:18px;background:linear-gradient(145deg,rgba(91,206,250,.06),transparent 55%),var(--panel);text-decoration:none;transition:transform .2s,border-color .2s}
+.featured-card:nth-child(2){background:linear-gradient(145deg,rgba(242,168,212,.08),transparent 55%),var(--panel)}
+.featured-card:nth-child(3){background:linear-gradient(145deg,rgba(255,255,255,.05),transparent 55%),var(--panel)}
+.featured-card:hover,.featured-card:focus-visible{transform:translateY(-4px);border-color:rgba(91,206,250,.4);outline:none}
+.featured-icon{display:grid;place-items:center;width:39px;height:39px;margin-bottom:15px;border:1px solid rgba(91,206,250,.2);border-radius:12px;color:var(--pink);font-size:24px}
+.featured-card small{color:var(--blue);font-size:9px;letter-spacing:.12em}
+.featured-card h3{margin:8px 0;color:var(--text);font-size:21px}
+.featured-card p{margin:0 0 18px;color:var(--muted);font-size:12px;line-height:1.65}
+.featured-link{margin-top:auto;color:var(--pink);font-size:11px;font-weight:700}
+.welcome-note{display:flex;align-items:center;gap:15px;margin-top:25px;padding:20px 23px;border:1px solid rgba(242,168,212,.16);border-radius:16px;background:rgba(242,168,212,.035)}
+.welcome-signal{flex:none;width:10px;height:10px;border-radius:50%;background:var(--pink);box-shadow:0 0 15px rgba(242,168,212,.35)}
+.welcome-note strong{font-size:13px;color:var(--text)}
+.welcome-note p{margin:5px 0 0;color:var(--muted);font-size:11px;line-height:1.6}
+.welcome-note>a{flex:none;margin-left:auto;color:var(--blue);text-decoration:none;font-size:11px;font-weight:700}
+@media(max-width:760px){.featured-grid{grid-template-columns:1fr}.featured-card{min-height:190px}.welcome-note{align-items:flex-start;flex-wrap:wrap}.welcome-note>a{margin-left:25px}}
+
+
+/* Finish placeholder cards as image-led cards rather than empty markup. */
+.empty-art.image-placeholder{
+ position:relative;
+ display:block;
+ background:#0d0b10;
+}
+
+.empty-art.image-placeholder>img{
+ width:100%;
+ height:100%;
+ object-fit:cover;
+ filter:saturate(.72) brightness(.58);
+ opacity:.9;
+}
+
+.empty-caption{
+ position:absolute;
+ inset:0;
+ display:grid;
+ place-content:center;
+ gap:6px;
+ text-align:center;
+ background:linear-gradient(0deg,rgba(10,8,12,.7),rgba(10,8,12,.08));
+}
+
+.empty-caption span{
+ color:#f0d9e8;
+ font-size:25px;
+ text-shadow:0 5px 20px rgba(0,0,0,.4);
+}
+
+.empty-caption small{
+ color:#d6c9d8;
+ font-size:7px;
+ letter-spacing:.11em;
+ text-transform:uppercase;
+}
+
+.shelf,
+.featured-section{
+ content-visibility:auto;
+ contain-intrinsic-size:720px;
+}
Systems & field notes
Webcomic