Files
cs249r_book/site/landing-v3.css
Vijay Janapa Reddi 00c10e4413 fix(site): remove scroll-snap from landing page
`scroll-snap-type: y mandatory` was set on <html> globally (landing.css)
and re-asserted with !important when the v3 landing class was present
(landing-v3.css). The intended mobile escape hatch — disabling
scroll-snap-align inside @media (max-width: 768px) — never worked:

  1. Specificity mismatch. Enable rules used `.mls-landing-v3
     .mls-section-richcards` (0,2,0); the disable used `.mls-section-
     richcards` (0,1,0). Media queries don't bump specificity, so the
     enable rule won and snap stayed active on phones for two of three
     sections.
  2. The mandatory `scroll-snap-type` on <html> was never disabled, so
     even with all snap-aligns removed, mandatory snap remained active
     on iOS — fighting Safari's momentum scroll.

Both bugs combined to produce the jittery, half-snap behavior on phones.
Even fixed, mandatory snap on a content-rich landing page locks readers
into one section at a time on small viewports — the polish wasn't worth
the friction. Removed entirely.

Kept: scroll-behavior: smooth and scroll-padding-top: 60px on <html> for
in-page anchor smoothness.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 19:39:51 -04:00

684 lines
14 KiB
CSS
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* =============================================================================
Landing V3 — Hero → Rich Cards → Impact/Support.
Layered on top of landing.css (inherits all base styles + demo component CSS).
Note: scroll-snap was removed (was: y mandatory across the three sections).
`mandatory` snap fights iOS Safari momentum scroll and yanks readers away
from mid-section content on phones. The desktop polish wasn't worth the
mobile friction. `scroll-behavior: smooth` and `scroll-padding-top: 60px`
from landing.css cover the in-page anchor smoothness we still want.
============================================================================= */
/* ─── Hero (identical to V2) ─── */
.mls-landing-v3 .mls-section-hero {
min-height: calc(100vh - 60px);
display: flex;
flex-direction: column;
justify-content: center;
padding-top: 1rem;
padding-bottom: 1rem;
}
.mls-landing-v3 .mls-section-hero .mls-landing-grid {
flex: 1;
align-items: center;
margin-top: -3rem;
}
.mls-landing-v3 .mls-hero-intro {
max-width: 440px;
}
.mls-hero-badge {
font-size: 0.8rem;
font-weight: 600;
color: var(--mls-text-muted);
letter-spacing: 0.04em;
margin: 0;
opacity: 0.8;
}
/* Freshness/edition indicator — signals the book is actively maintained */
.mls-hero-edition {
display: inline-flex;
align-items: center;
gap: 0.5em;
flex-wrap: wrap;
font-size: 0.78rem;
font-weight: 500;
color: var(--mls-text-muted);
letter-spacing: 0.02em;
margin: 0.5rem 0 0 0;
opacity: 0.85;
}
.mls-edition-dot {
width: 0.55em;
height: 0.55em;
border-radius: 50%;
background: #2d8a4e; /* "alive" green */
box-shadow: 0 0 0 0 rgba(45, 138, 78, 0.55);
animation: mlsEditionPulse 2.4s ease-out infinite;
flex-shrink: 0;
}
@keyframes mlsEditionPulse {
0% { box-shadow: 0 0 0 0 rgba(45, 138, 78, 0.55); }
70% { box-shadow: 0 0 0 0.55em rgba(45, 138, 78, 0); }
100% { box-shadow: 0 0 0 0 rgba(45, 138, 78, 0); }
}
.mls-edition-sep {
opacity: 0.5;
}
.mls-edition-link {
color: inherit;
text-decoration: underline;
text-decoration-color: rgba(0, 0, 0, 0.2);
text-underline-offset: 0.18em;
transition: text-decoration-color 0.15s ease;
}
.mls-edition-link:hover {
text-decoration-color: var(--mls-accent, #A51C30);
color: var(--mls-accent, #A51C30);
}
@media (prefers-reduced-motion: reduce) {
.mls-edition-dot { animation: none; }
}
/* Scroll indicator — clickable */
.mls-landing-v3 .mls-scroll-indicator {
pointer-events: auto;
cursor: pointer;
animation: none !important;
transform: translateX(-50%);
}
.mls-landing-v3 .mls-scroll-indicator:hover {
opacity: 1;
}
.mls-landing-v3 .mls-scroll-indicator:hover span {
color: var(--mls-accent);
}
.mls-landing-v3 .mls-scroll-arrow {
animation: bounce-arrow 2s infinite;
}
@keyframes bounce-arrow {
0%, 20%, 50%, 80%, 100% { transform: translateY(0); }
40% { transform: translateY(-10px); }
60% { transform: translateY(-5px); }
}
/* ─── Snap 2: Rich card grid section ─── */
.mls-section-richcards {
min-height: calc(100vh - 60px);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 1.5rem 2rem 3.5rem;
max-width: 1200px;
margin: 0 auto;
position: relative;
}
.mls-section-richcards > :first-child {
margin-top: -1.5rem;
}
.mls-section-richcards .mls-cards-header {
text-align: center;
margin-bottom: 1.25rem;
}
.mls-cards-title {
font-size: clamp(1.3rem, 3vw, 1.7rem);
font-weight: 700;
color: var(--mls-text);
margin: 0;
letter-spacing: -0.02em;
border: none !important;
border-bottom: none !important;
padding: 0;
}
/* 4×2 rich card grid */
.mls-rich-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 0.85rem;
width: 100%;
max-width: 1100px;
}
/* ─── Row labels ─── */
.mls-row-label {
grid-column: 1 / -1;
font-size: 0.95rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.14em;
color: var(--mls-text);
margin: 0.2rem 0 0.5rem;
padding: 0;
opacity: 0.72;
}
/* Second+ row label: divider rule + extra breathing room,
so the two audience groups read as distinct visual bands */
.mls-row-label:not(:first-of-type) {
margin-top: 2.4rem;
padding-top: 1.4rem;
border-top: 1px solid var(--mls-glass-border);
}
/* ─── Card color accents (WCAG AA compliant) ─── */
:root {
--card-explore: #2563EB;
--card-build: #D4740C;
--card-deploy: #148F77;
--card-model: #0284C7;
--card-practice: #475569;
--card-adopt: #6366f1;
--card-teach: #A51C30;
--card-follow: #475569;
}
[data-bs-theme="dark"] {
--card-explore: #60a5fa;
--card-build: #f59e0b;
--card-deploy: #34d399;
--card-model: #38bdf8;
--card-practice: #94a3b8;
--card-adopt: #a5b4fc;
--card-teach: #f87171;
--card-follow: #94a3b8;
}
/* ─── Rich card — vertical: demo thumbnail on top, text below ─── */
.mls-rich-card {
display: flex;
flex-direction: column;
border-radius: 16px;
background: var(--mls-glass-bg);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid var(--mls-glass-border);
box-shadow: var(--mls-card-shadow);
text-decoration: none;
color: var(--mls-text);
transition: transform 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease;
cursor: pointer;
position: relative;
overflow: hidden;
}
/* Top accent bar — disabled, demos fill edge-to-edge */
/* Per-card accent colors via data attribute */
.mls-rich-card[data-accent="explore"] { --card-accent: var(--card-explore); }
.mls-rich-card[data-accent="build"] { --card-accent: var(--card-build); }
.mls-rich-card[data-accent="deploy"] { --card-accent: var(--card-deploy); }
.mls-rich-card[data-accent="model"] { --card-accent: var(--card-model); }
.mls-rich-card[data-accent="practice"]{ --card-accent: var(--card-practice); }
.mls-rich-card[data-accent="adopt"] { --card-accent: var(--card-adopt); }
.mls-rich-card[data-accent="teach"] { --card-accent: var(--card-teach); }
.mls-rich-card[data-accent="follow"] { --card-accent: var(--card-follow); }
/* Hover — lift + shadow, no border change */
.mls-rich-card:hover {
transform: translateY(-4px);
box-shadow: var(--mls-card-shadow-hover);
}
.mls-rich-card:hover .mls-cur-name {
color: var(--card-accent, var(--mls-accent));
}
/* Active press feedback */
.mls-rich-card:active {
transform: translateY(-1px);
transition-duration: 0.05s;
}
/* Focus visible for keyboard nav */
.mls-rich-card:focus-visible {
outline: 2px solid var(--card-accent, var(--mls-accent));
outline-offset: 2px;
transform: translateY(-4px);
}
/* ─── Card info (below demo via order) ─── */
.mls-rich-card-info {
display: flex;
flex-direction: column;
padding: 0.75rem 1rem 0.85rem;
flex-shrink: 0;
order: 2;
}
.mls-rich-card-info .mls-cur-verb {
font-size: 0.6rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--card-accent, var(--mls-accent));
margin: 0 0 0.2rem;
}
.mls-rich-card-info .mls-cur-name {
font-size: 0.95rem;
font-weight: 700;
color: var(--mls-text);
margin: 0 0 0.25rem;
transition: color 0.2s ease;
}
.mls-rich-card-info .mls-cur-desc {
font-size: 0.75rem;
color: var(--mls-text-muted);
margin: 0;
line-height: 1.4;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
/* ─── Card demo (top visual via order) ─── */
.mls-rich-card-demo {
width: 100%;
height: 140px;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
padding: 0;
border-bottom: 1px solid var(--mls-glass-border);
order: 1;
}
.mls-rich-card-demo > svg {
width: 100%;
height: 100%;
display: block;
}
/* Hardware kits image */
.mls-rich-card-img {
width: 100%;
height: 100%;
object-fit: contain;
border-radius: 0;
background: #d5f0eb;
padding: 10px;
}
/* ─── Accessibility: visually hidden ─── */
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
/* ─── Snap 2: Scroll indicator ─── */
.mls-scroll-2 {
position: relative;
margin-top: 3rem;
text-align: center;
width: 100%;
color: var(--mls-text-muted);
font-size: 0.85rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.1em;
pointer-events: auto;
cursor: pointer;
animation: none !important;
}
.mls-scroll-2 .mls-scroll-arrow {
font-size: 1.5rem;
margin-top: 0.25rem;
color: var(--mls-accent);
animation: bounce-arrow 2s infinite;
}
.mls-scroll-2:hover span {
color: var(--mls-accent);
}
/* ─── Snap 3: Impact & Mission (identical to V2) ─── */
.mls-section-impact {
min-height: calc(100vh - 60px);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 2rem 2rem 1.5rem;
max-width: 950px;
margin: 0 auto;
gap: 1.5rem;
text-align: center;
}
.mls-impact-top {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.75rem;
max-width: 650px;
background: var(--mls-glass-bg);
border: 1px solid var(--mls-glass-border);
box-shadow: var(--mls-card-shadow);
padding: 1.5rem 2.5rem;
border-radius: 16px;
}
.mls-impact-eyebrow {
font-size: 0.7rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.15em;
color: var(--mls-accent);
margin: 0;
}
.mls-impact-headline {
font-size: clamp(1.6rem, 4vw, 2.4rem);
font-weight: 800;
color: var(--mls-text);
letter-spacing: -0.03em;
line-height: 1.15;
margin: 0 0 0.25rem;
border: none !important;
border-bottom: none !important;
padding: 0;
}
.mls-impact-mission {
font-size: 0.92rem;
color: var(--mls-text-muted);
margin: 0;
line-height: 1.6;
}
.mls-impact-mission strong {
color: var(--mls-accent);
font-weight: 700;
}
.mls-reader-map {
width: 100%;
max-width: 820px;
}
.mls-looker-wrap {
position: relative;
width: 100%;
padding-bottom: 48%;
border-radius: 12px;
overflow: hidden;
border: 1px solid var(--mls-glass-border);
box-shadow: var(--mls-card-shadow);
background: var(--mls-glass-bg);
}
.mls-looker-wrap iframe {
position: absolute;
top: -25%;
left: -25%;
width: 150%;
height: 150%;
border: 0;
pointer-events: none;
}
.mls-looker-wrap:hover iframe {
pointer-events: auto;
}
.mls-map-caption {
font-size: 0.75rem;
color: var(--mls-text);
text-align: center;
margin: 0.5rem 0 0;
font-weight: 600;
letter-spacing: 0.03em;
}
.mls-impact-bottom {
display: flex;
flex-direction: column;
align-items: center;
gap: 1rem;
background: var(--mls-glass-bg);
border: 1px solid var(--mls-glass-border);
box-shadow: var(--mls-card-shadow);
padding: 1.25rem 2.5rem;
border-radius: 16px;
}
.mls-impact-stats-line {
font-size: 0.9rem;
font-weight: 600;
color: var(--mls-text-muted);
margin: 0;
letter-spacing: 0.02em;
}
.mls-goal-block {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.3rem;
}
.mls-impact-goal {
font-size: 0.95rem;
color: var(--mls-text);
margin: 0;
font-weight: 600;
}
.mls-impact-goal strong {
color: var(--mls-accent);
}
.mls-impact-goal-sub {
font-size: 0.82rem;
color: var(--mls-text-muted);
margin: 0;
max-width: 500px;
line-height: 1.5;
}
.mls-star-row {
display: flex;
align-items: center;
gap: 0.6rem;
}
.mls-impact-sponsors {
font-size: 0.75rem;
color: var(--mls-text-muted);
margin: 0;
opacity: 0.7;
}
.mls-impact-sponsors a {
color: var(--mls-accent);
font-weight: 600;
text-decoration: none;
}
.mls-impact-sponsors a:hover {
opacity: 0.8;
}
/* Button styles */
.mls-footer-btn {
display: inline-flex;
align-items: center;
gap: 0.4rem;
padding: 0.6rem 1.3rem;
border-radius: 8px;
font-size: 0.9rem;
font-weight: 600;
text-decoration: none;
transition: all 0.2s ease;
border: 1px solid var(--mls-card-border);
}
.mls-footer-btn svg {
flex-shrink: 0;
}
.mls-btn-star {
background: rgba(0, 0, 0, 0.06);
color: var(--mls-text);
border-color: rgba(0, 0, 0, 0.15);
padding: 0.7rem 1.8rem;
font-size: 1rem;
}
.mls-btn-star:hover {
background: rgba(0, 0, 0, 0.1);
border-color: rgba(0, 0, 0, 0.25);
color: var(--mls-text);
}
[data-bs-theme="dark"] .mls-btn-star {
background: rgba(255, 255, 255, 0.08);
border-color: rgba(255, 255, 255, 0.15);
}
[data-bs-theme="dark"] .mls-btn-star:hover {
background: rgba(255, 255, 255, 0.15);
border-color: rgba(255, 255, 255, 0.25);
}
/* ═══ Responsive: Tablet (≤900px) ═══ */
@media (max-width: 900px) {
.mls-rich-grid {
grid-template-columns: repeat(2, 1fr);
gap: 0.85rem;
}
.mls-rich-card-demo {
height: 120px;
}
.mls-section-richcards {
padding: 2rem 1.5rem 4rem;
}
.mls-impact-headline {
font-size: 1.8rem;
}
}
/* ═══ Responsive: Phone (≤768px) ═══ */
@media (max-width: 768px) {
/* Cards become single column, info on top, demo below */
.mls-rich-grid {
grid-template-columns: 1fr;
gap: 1.25rem;
}
.mls-rich-card {
flex-direction: column;
min-height: auto;
}
.mls-rich-card-info {
width: 100%;
padding: 1.25rem 1.25rem 0.5rem;
}
.mls-rich-card-demo {
width: 100%;
padding: 0.5rem 1rem 1rem;
justify-content: center;
}
.mls-rich-card-demo {
height: 110px;
}
/* Phone: collapse the section min-height so content packs tightly. */
.mls-landing-v3 .mls-section-hero,
.mls-landing-v3 .mls-section-richcards,
.mls-landing-v3 .mls-section-impact {
min-height: auto;
}
.mls-cards-title {
font-size: 1.2rem;
}
.mls-hero-badge {
font-size: 0.7rem;
}
.mls-impact-headline {
font-size: 1.4rem;
}
.mls-impact-goal {
font-size: 0.8rem;
}
.mls-impact-stats-line {
font-size: 0.78rem;
}
.mls-footer-btn {
padding: 0.45rem 0.9rem;
font-size: 0.8rem;
}
.mls-section-impact {
padding: 1.5rem 1rem 1rem;
gap: 0.6rem;
}
.mls-scroll-2 {
display: none;
}
}
/* ═══ Responsive: Small phone (≤480px) ═══ */
@media (max-width: 480px) {
.mls-rich-card-demo {
height: 100px;
}
.mls-rich-card-info .mls-cur-desc {
font-size: 0.75rem;
}
.mls-rich-card-info .mls-cur-name {
font-size: 0.95rem;
}
}