diff --git a/public/assets/lesson.css b/public/assets/lesson.css index 515c241..a5ab66c 100644 --- a/public/assets/lesson.css +++ b/public/assets/lesson.css @@ -14,7 +14,7 @@ body{margin:0; background:var(--bg); color:var(--ink); line-height:1.6; /* ---- hub bar (sticky header with prev/next + theme toggle) ---- */ #hubbar{position:sticky; top:0; z-index:50; display:flex; justify-content:space-between; - align-items:center; gap:1rem; margin:-2.6rem -1.6rem 1.6rem; padding:.6rem clamp(1rem,4vw,1.6rem); + align-items:center; gap:1rem; margin:-2.6rem calc(-1 * clamp(1rem,4vw,1.6rem)) 1.6rem; padding:.6rem clamp(1rem,4vw,1.6rem); background:color-mix(in srgb, var(--bg) 82%, transparent); -webkit-backdrop-filter:blur(10px); backdrop-filter:blur(10px); border-bottom:1px solid var(--line); font-size:.8rem} #hubbar a{color:var(--accent); text-decoration:none; font-weight:600} diff --git a/public/assets/tokens.css b/public/assets/tokens.css index 92540f0..ed6c701 100644 --- a/public/assets/tokens.css +++ b/public/assets/tokens.css @@ -150,8 +150,8 @@ html[data-theme="light"] { --accent-muted: rgba(168,85,8,.12); /* Secondary accent */ - --accent-2: #0891B2; - --accent-2-muted: rgba(8,145,178,.10); + --accent-2: #0E7490; + --accent-2-muted: rgba(14,116,144,.10); /* Links */ --link: #0369A1; @@ -167,21 +167,21 @@ html[data-theme="light"] { --code-text: #E2E8F0; /* Per-track accents */ - --track-agents: #0891B2; - --track-rest: #0891B2; - --track-bloom: #0891B2; - --track-distributed: #0891B2; - --track-storage: #0891B2; - --track-transactions:#0891B2; - --track-streaming: #0891B2; - --track-applied: #0891B2; - --track-context: #0891B2; - --track-eval: #0891B2; - --track-prodai: #0891B2; - --track-aisec: #0891B2; - --track-aiinfra: #0891B2; - --track-domain: #0891B2; - --track-advai: #0891B2; + --track-agents: #0E7490; + --track-rest: #0E7490; + --track-bloom: #0E7490; + --track-distributed: #0E7490; + --track-storage: #0E7490; + --track-transactions:#0E7490; + --track-streaming: #0E7490; + --track-applied: #0E7490; + --track-context: #0E7490; + --track-eval: #0E7490; + --track-prodai: #0E7490; + --track-aisec: #0E7490; + --track-aiinfra: #0E7490; + --track-domain: #0E7490; + --track-advai: #0E7490; /* Migration aliases */ --card: var(--surface); diff --git a/src/pages/index.astro b/src/pages/index.astro index 164d403..6259dcd 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -229,7 +229,7 @@ for (const track of tracks) { gap:1rem; align-items:stretch; margin-top:1.3rem} .tile{background:var(--card); border:1px solid var(--line); border-left:3px solid var(--line); border-radius:14px; padding:1rem 1.1rem 1.05rem; display:flex; flex-direction:column; gap:.7rem; - margin:0; transition:box-shadow .15s, transform .15s, border-color .15s} + margin:0; cursor:pointer; transition:box-shadow .15s, transform .15s, border-color .15s} /* the curated entry point keeps the warm amber edge — the one card that should draw the eye. Every other card stays neutral so amber reads as a highlight, not the structural default. */ @@ -468,15 +468,16 @@ for (const track of tracks) { background:var(--card); color:var(--ink); border-radius:14px; box-shadow:0 20px 60px rgba(0,0,0,.28)} dialog.cardsheet::backdrop{background:rgba(0,0,0,.45)} - .cs-inner{padding:1.1rem 1.15rem 1.25rem; position:relative} + .cs-inner{padding:1.1rem 1.15rem 1.25rem; position:relative; display:flex; flex-direction:column; min-height:0} .cs-close{position:absolute; top:.55rem; right:.55rem; border:0; background:var(--chip); color:var(--ink); - width:2rem; height:2rem; border-radius:50%; font-size:.95rem; line-height:1; cursor:pointer} - .cs-close:hover{background:var(--line)} + width:2rem; height:2rem; border-radius:50%; font-size:.95rem; line-height:1; cursor:pointer; + transition:background .12s, color .12s} + .cs-close:hover{background:var(--accent-soft); color:var(--on-accent)} .cs-name{font-weight:700; font-size:1.15rem; letter-spacing:-.01em; padding-right:2rem; line-height:1.15} .cs-tag{font-size:.63rem; letter-spacing:.11em; text-transform:uppercase; color:var(--muted); margin-top:.12rem} .cs-meta{font-size:.75rem; color:var(--muted); margin-top:.35rem} .cs-lessons{list-style:none; margin:.9rem 0 0; padding:0; display:flex; flex-direction:column; gap:.6rem; - max-height:52vh; overflow:auto} + flex:1 1 auto; min-height:0; max-height:52vh; overflow:auto} .cs-lessons li{display:flex; gap:.6rem; align-items:flex-start} .cs-n{flex:none; min-width:1.6rem; height:1.6rem; padding:0 .35rem; border-radius:6px; display:grid; place-items:center; font-size:.78rem; font-weight:700; background:var(--chip); color:var(--ink)} @@ -488,10 +489,17 @@ for (const track of tracks) { dialog.cardsheet[open]{animation:cs-pop .16s ease-out} @keyframes cs-pop{from{opacity:0; transform:translateY(8px) scale(.985)} to{opacity:1; transform:none}} @media (max-width:640px){ - dialog.cardsheet{inset:auto 0 0 0; margin:0; width:100%; max-width:none; border-radius:16px 16px 0 0} - dialog.cardsheet[open]{animation:cs-up .2s ease-out} + /* bottom sheet: cap at ~70% of the viewport so it never fills the screen + (closes via the ✕ button or Esc, not backdrop tap). List scrolls within. */ + dialog.cardsheet{inset:auto 0 0 0; margin:0; width:100%; max-width:none; max-height:70vh; overflow:hidden; border-radius:16px 16px 0 0} + /* display:flex ONLY when open — must not override the UA dialog:not([open]) + {display:none}, or the sheet stays visible after close (✕/Esc) */ + dialog.cardsheet[open]{animation:cs-up .2s ease-out; display:flex} @keyframes cs-up{from{transform:translateY(100%)} to{transform:translateY(0)}} - .cs-lessons{max-height:60vh} + /* sheet fills the 50vh; header + footer stay fixed, only .cs-lessons scrolls + (same behaviour as desktop) instead of the whole sheet scrolling */ + .cs-inner{flex:1 1 auto} + .cs-lessons{max-height:none} } @media (prefers-reduced-motion:reduce){ html{scroll-behavior:auto} @@ -1050,6 +1058,7 @@ for (const track of tracks) { if (start) csFoot.appendChild(start.cloneNode(true)); // Start/Continue = prominent last element sheet.showModal(); + document.documentElement.style.overflow = 'hidden'; // lock background scroll } grid.addEventListener('click', function (e) { @@ -1059,14 +1068,18 @@ for (const track of tracks) { e.preventDefault(); // cancel the
toggle openSheet(tile); }); - sheet.addEventListener('click', function (e) { - if (e.target === sheet) sheet.close(); - }); // backdrop + // Intentionally NO backdrop-click close: the sheet closes only + // via the ✕ button or Esc (Esc is native to dialog.showModal()), + // so an accidental outside tap can't dismiss it. var closeBtn = sheet.querySelector('.cs-close'); if (closeBtn) closeBtn.addEventListener('click', function () { sheet.close(); }); + // restore background scroll whenever the sheet closes (✕ or Esc) + sheet.addEventListener('close', function () { + document.documentElement.style.overflow = ''; + }); } })();