Files
cs249r_book/shared/styles/_book-only.scss
Vijay Janapa Reddi 4b840ff957 refactor(site): shared styles system and fix subscribe modal for subsites
- Create shared/ directory with centralized SCSS partials and site-head.html
  so site subsites (about, community, newsletter) no longer duplicate
  inline header config or reference book-only styles
- Fix subscribe modal: change script src from broken relative path
  (../../book/quarto/assets/scripts/subscribe-modal.js) to absolute URL
  (https://mlsysbook.ai/vol1/assets/scripts/subscribe-modal.js) which
  the rewrite-dev-urls.sh script converts for dev preview automatically
2026-03-21 12:50:25 -04:00

638 lines
15 KiB
SCSS

// =============================================================================
// BOOK-ONLY STYLES — Textbook-specific styles (Vol1 & Vol2 only)
// =============================================================================
// These styles are NOT shared with kits, labs, instructors, or site pages.
// They handle foldbox callout exclusions, margin chapter connections, code
// listings, announcement bars, and other textbook-specific UI.
// =============================================================================
/* Remove any interfering styles from definition callouts - let foldbox handle everything */
/* Hide empty paragraphs in custom callouts that are generated by the extension */
.callout-definition>p:empty,
.callout-definition>p:first-child:empty,
details.callout-definition p:empty,
details.callout-definition>div>p:empty,
details.callout-definition>div>p:first-child:empty,
details.callout-definition>div>p:last-child:empty,
.callout-colab>p:empty,
.callout-colab>p:first-child:empty,
details.callout-colab p:empty,
details.callout-colab>div>p:empty,
details.callout-colab>div>p:first-child:empty,
details.callout-colab>div>p:last-child:empty {
display: none !important;
margin: 0 !important;
padding: 0 !important;
height: 0 !important;
line-height: 0 !important;
}
/* Exclude all custom foldbox callouts from general callout styling - let foldbox handle everything */
.callout.callout-quiz-question,
.callout.callout-quiz-answer,
.callout.callout-definition,
.callout.callout-example,
.callout.callout-colab,
.callout.callout-notebook,
.callout.callout-lighthouse,
.callout.callout-perspective,
.callout.callout-checkpoint,
.callout.callout-theorem,
.callout.callout-principle,
.callout.callout-takeaways,
.callout.callout-chapter-connection,
.callout.callout-chapter-forward,
.callout.callout-chapter-recall,
.callout.callout-resource-slides,
.callout.callout-resource-videos,
.callout.callout-resource-exercises,
.callout.callout-code {
margin: 0 !important;
/* Let foldbox.css handle the margin */
border: none !important;
/* Remove any borders from wrapper */
box-shadow: none !important;
/* Remove any shadows from wrapper */
background: transparent !important;
/* Make wrapper transparent */
text-align: left !important;
/* Ensure left alignment */
}
/* Ensure content inside foldbox callouts is left-aligned */
/* Note: Most alignment is handled by foldbox.css; this is minimal override for Quarto defaults */
.callout.callout-quiz-question div,
.callout.callout-quiz-answer div,
.callout.callout-definition div,
.callout.callout-example div,
.callout.callout-colab div,
.callout.callout-notebook div,
.callout.callout-lighthouse div,
.callout.callout-perspective div,
.callout.callout-checkpoint div,
.callout.callout-theorem div,
.callout.callout-principle div,
.callout.callout-takeaways div,
.callout.callout-chapter-connection div,
.callout.callout-chapter-forward div,
.callout.callout-chapter-recall div,
.callout.callout-resource-slides div,
.callout.callout-resource-videos div,
.callout.callout-resource-exercises div,
.callout.callout-code div {
text-align: left !important;
}
/* Override slimcontent layout to match regular floating layout */
@media (min-width: 992px) {
body.floating.slimcontent .page-columns {
grid-template-columns: [screen-start] 1.5em [screen-start-inset] 5fr [page-start] minmax(25px, 50px) [page-start-inset] minmax(50px, 150px) [body-start-outset] minmax(25px, 50px) [body-start] 1.5em [body-content-start] minmax(500px, calc(800px - 3em)) [body-content-end] 1.5em [body-end] minmax(25px, 50px) [body-end-outset] minmax(50px, 150px) [page-end-inset] minmax(25px, 50px) [page-end] 5fr [screen-end-inset] 1.5em [screen-end] !important;
}
}
// Fix Hypothesis margin that prevents full-width elements
body.hypothesis-enabled #quarto-header,
body.hypothesis-enabled .headroom-target,
body.hypothesis-enabled header.headroom {
margin-right: 0 !important;
}
// Enhanced announcement styling with solid background (no transparency)
.alert-primary,
.announcement {
background: linear-gradient(135deg,
lighten($accent, 52%) 0%,
lighten($accent, 54%) 100%) !important;
border-color: rgba($accent, 0.4) !important;
border-left: 4px solid $accent !important;
color: darken($accent, 25%) !important;
// Break out of parent container to span full viewport width
// Transform-based centering ignores parent margins
position: relative !important;
left: 50% !important;
transform: translateX(-50%) !important;
width: 100vw !important;
max-width: 100vw !important;
margin-left: 0 !important;
margin-right: 0 !important;
box-sizing: border-box !important;
// Dismiss button (X)
.btn-close {
opacity: 0.6 !important;
&:hover {
opacity: 1 !important;
}
}
a {
color: $accent !important;
font-weight: 500;
&:hover {
color: darken($accent, 15%) !important;
text-decoration: underline;
}
}
// Typography hierarchy for better readability
strong,
b {
color: darken($accent, 30%) !important;
font-weight: 600;
}
// Ensure icons and other elements inherit the color scheme
.bi,
i {
color: $accent !important;
}
// Callout icons override the global accent color (more specific selectors)
.callout .callout-icon .bi,
.callout .callout-icon i,
div[class*="callout"] .callout-icon .bi,
div[class*="callout"] .callout-icon i {
color: inherit !important;
}
// Remove background from ::before pseudo-elements on icon fonts
i.callout-icon::before,
.callout-icon i::before {
background-color: transparent !important;
background: none !important;
}
}
// Abstract section styles for homepage
.abstract-section {
display: flex;
gap: 40px;
align-items: flex-start;
margin: 30px 0;
}
.abstract-content {
flex: 1;
}
.book-card {
flex-shrink: 0;
width: 300px;
text-align: center;
padding: 25px 15px;
background: linear-gradient(135deg, #fefefe 0%, #f8f9fa 50%, #f0f2f5 100%);
border: 1px solid #e8eaed;
border-radius: 16px;
box-shadow: 0 8px 32px rgba($accent, 0.08), 0 2px 8px rgba(0, 0, 0, 0.04);
}
.book-image {
width: 100%;
max-width: 240px;
height: auto;
margin-bottom: 18px;
}
.book-card-link {
text-decoration: none;
color: inherit;
display: block;
transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
}
.book-card-link:hover {
transform: scale(1.02);
}
.book-card-link:hover .book-card {
box-shadow: 0 12px 40px rgba($accent, 0.15), 0 4px 12px rgba(0, 0, 0, 0.08);
}
.book-title {
margin: 0 0 6px 0;
color: #495057;
font-size: 1em;
font-weight: 600;
text-shadow: none;
}
.book-subtitle {
margin: 0;
color: #6c757d;
font-size: 0.9em;
font-weight: 600;
letter-spacing: 0.3px;
}
// Responsive styles for abstract section
@media (max-width: 768px) {
.abstract-section {
flex-direction: column;
gap: 20px;
}
.abstract-content {
margin-bottom: 20px;
}
.book-card-link {
width: 100%;
max-width: 300px;
margin: 0 auto;
}
.book-card {
padding: 15px 10px;
}
.book-image {
max-width: 200px;
margin-bottom: 12px;
}
.book-title {
font-size: 1em;
}
.book-subtitle {
font-size: 0.85em;
}
}
// Support mission section - call-to-action box
.support-mission {
background-color: #f8f9fa;
border: 1px solid #e9ecef;
border-radius: 8px;
padding: 1.5rem;
margin: 2rem 0;
p {
color: #495057;
line-height: 1.6;
margin-bottom: 1.5rem;
&:first-child {
margin-top: 0;
}
&.support-note {
margin: 1rem 0 0 0;
font-size: 0.9rem;
color: #6c757d;
}
}
a {
color: $accent;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
}
// Clean podcast section for homepage
.podcast-section {
background-color: #f8f9fa;
border: 1px solid #e9ecef;
border-radius: 8px;
padding: 1.5rem;
margin: 2rem 0;
p {
color: #495057;
line-height: 1.6;
margin-bottom: 1.5rem;
&:first-child {
margin-top: 0;
}
}
a {
color: $accent;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
audio {
width: 100%;
height: 36px;
margin-top: 0.5rem;
}
}
.support-actions {
display: flex;
align-items: center;
gap: 1rem;
margin: 1.5rem 0;
.star-count {
background-color: #ffffff;
border: 1px solid #e9ecef;
border-radius: 6px;
padding: 0.5rem 1rem;
font-weight: 600;
color: #495057;
font-size: 0.9rem;
&::before {
content: "";
color: #6c757d;
}
}
.github-star-btn {
background-color: $accent !important;
color: white !important;
padding: 0.5rem 1rem;
border-radius: 6px;
text-decoration: none;
font-weight: 500;
font-size: 0.9rem;
transition: all 0.2s ease;
border: none;
&:hover {
background-color: darken($accent, 8%) !important;
color: white !important;
text-decoration: none;
transform: translateY(-1px);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
}
}
// Mobile responsive for book-only sections
@media (max-width: 768px) {
.support-mission,
.podcast-section {
padding: 1.25rem;
margin: 1.5rem 0;
}
.support-actions {
flex-direction: column;
align-items: stretch;
gap: 0.75rem;
.github-star-btn {
text-align: center;
}
}
}
// Chapter connections in margin for HTML - clean and minimal
.margin-container {
position: relative;
.margin-chapter-connection {
// Position in the right margin, avoiding footnote conflicts
position: absolute;
right: -250px; // Adjust based on your layout's margin width
top: -20px; // Offset upward to avoid footnotes below
width: 220px; // Slightly smaller than the positioning offset
background-color: transparent;
border: none;
border-left: 2px solid rgba($accent, 0.4);
border-radius: 0;
padding: 6px 0 6px 10px;
font-size: 0.7rem; // Made even smaller
line-height: 1.2;
color: #777; // Slightly lighter
z-index: 5; // Lower z-index than footnotes
// Alternative positioning to avoid footnotes completely
&.avoid-footnotes {
position: sticky;
top: 100px;
float: right;
clear: both;
margin: -30px -250px 20px 20px;
background-color: rgba(255, 255, 255, 0.95);
padding: 8px 10px;
border-radius: 4px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
// Make it collapse nicely on smaller screens
@media (max-width: 1400px) {
position: static;
right: auto;
width: auto;
margin: 1rem 0;
&.avoid-footnotes {
position: static;
float: none;
margin: 1rem 0;
background: transparent;
box-shadow: none;
border-radius: 0;
}
}
// Style the header more subtly
.callout-header {
font-weight: 500;
color: #999; // Even more subtle
font-size: 0.65rem; // Smaller header
text-transform: uppercase;
letter-spacing: 0.5px;
margin-bottom: 4px; // Tighter spacing
display: block;
opacity: 0.8;
}
// Style the connection list
ul,
ol {
margin: 0;
padding-left: 12px; // Tighter indent
li {
margin-bottom: 4px; // Tighter spacing
font-size: 0.7rem; // Smaller text
&:last-child {
margin-bottom: 0;
}
}
}
// Style paragraph content
p {
margin: 0 0 4px 0;
font-size: 0.7rem;
line-height: 1.2;
&:last-child {
margin-bottom: 0;
}
}
// Style links within connections - more subtle
a {
color: #777;
text-decoration: none;
&:hover {
color: $accent;
text-decoration: underline;
}
}
}
}
/* Enhanced styling for code listings - more prominent */
.listing figure {
margin: 2.5rem 0 !important;
/* Even more space around listings */
border: 2px solid #D1D7E0;
/* Slate border */
border-radius: 10px;
overflow: hidden;
box-shadow: 0 2px 8px rgba($accent, 0.1) !important;
/* Match callout subtle shadow */
background: linear-gradient(135deg, #F2F4F8 0%, #ffffff 100%);
/* Light blue-gray background */
position: relative;
}
/* Code block within listings */
.listing pre {
margin: 0 !important;
border-radius: 0 !important;
border: none !important;
}
/* Listing captions - base style */
.listing figcaption,
.listing .listing-caption {
background: linear-gradient(135deg, #F7F9FC 0%, #EDF2F7 100%) !important;
/* Very light cool gray-blue gradient */
border-bottom: 2px solid #D1D7E0 !important;
/* Soft slate gray border */
padding: 1rem 1.25rem !important;
/* More padding */
margin: 0 !important;
font-size: 0.95rem !important;
/* Slightly larger text */
color: #1a202c !important;
/* Darker text */
font-family: var(--bs-body-font-family, system-ui, sans-serif) !important;
font-weight: 400 !important;
/* Default = normal weight */
line-height: 1.4 !important;
text-align: left !important;
order: -1;
/* Place caption at top */
position: relative;
}
/* Override global inheritance */
.listing figcaption *,
.listing .listing-caption * {
color: inherit !important;
font-weight: 400 !important;
/* Ensure normal unless overridden below */
}
/* Normal caption */
.listing figcaption {
font-weight: 400 !important;
}
/* Bold only first strong (label Listing X:) */
.listing figcaption strong:first-of-type {
font-weight: 700 !important;
}
/* Code content styling within listings */
.listing .sourceCode {
padding: 0.75rem 1rem !important;
/* Reduced padding to eliminate dead space */
background-color: #f1f3f4 !important;
/* More prominent gray background */
margin: 0 !important;
border: none !important;
}
/* Ensure no extra spacing in code blocks */
.listing .sourceCode pre,
.listing .sourceCode code {
margin: 0 !important;
padding: 0 !important;
}
/* Special styling for listings with bold/emphasized content in captions */
.listing figcaption strong,
.listing .listing-caption strong {
color: #1a202c !important;
/* Darker gray for better emphasis and hierarchy */
font-weight: 700 !important;
}
/* Minimal Video Styling */
.video-container {
margin: 1.5rem 0;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
border: 1px solid rgba(0, 0, 0, 0.05);
}
.video-container iframe {
border-radius: 8px;
}
/* Video in margin */
.margin-video {
margin: 1rem 0;
border-radius: 6px;
overflow: hidden;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
width: 100%;
}
/* Auto-numbering for margin videos */
body {
counter-reset: margin-video;
}
.margin-video {
counter-increment: margin-video;
}
.margin-video+p em::before {
content: "Video " counter(margin-video) ": ";
}
svg text {
font-family: "Nimbus Sans", "Helvetica", "Arial", sans-serif !important;
}
/* Chapter connection callouts - ensure left alignment */
.callout-chapter-connection {
text-align: left !important;
}
.callout-chapter-connection .callout-body {
text-align: left !important;
}
.callout-chapter-connection p {
text-align: left !important;
margin-bottom: 0.5rem;
}