openfreebooks-bookgenerator/themes/openfreebooks/sass/_catalog.scss

1494 lines
32 KiB
SCSS

// -----------------------------------------------------------------------------
// Shared
// -----------------------------------------------------------------------------
@mixin catalog-chapter-title-link {
display: inline;
color: inherit;
text-decoration: none;
background: linear-gradient(var(--accent), var(--accent)) 0 calc(100% - 2px) / 0% 1px no-repeat;
transition: background-size 180ms ease;
&:hover,
&:focus-visible {
background-size: 100% 1px;
outline: none;
}
}
@mixin catalog-chapter-title-arrow {
display: inline-block;
margin-left: 0.2em;
color: var(--accent);
transition: transform 180ms ease;
}
@mixin catalog-chapter-title-link-with-arrow {
@include catalog-chapter-title-link;
&:hover .catalog-chapter-card__title-arrow,
&:focus-visible .catalog-chapter-card__title-arrow {
transform: translateX(2px);
}
}
// -----------------------------------------------------------------------------
// Page & shell
// -----------------------------------------------------------------------------
.catalog-page {
padding: 24px 0 64px;
min-height: calc(100vh - 120px);
}
.catalog-error {
padding: 48px 24px;
text-align: center;
color: var(--soft-ink);
}
.catalog-shell {
display: grid;
grid-template-columns: minmax(12rem, 18rem) minmax(0, 1fr);
gap: 0;
max-width: 1400px;
margin: 0 auto;
min-height: calc(100vh - 160px);
border: 1px solid var(--card-border);
border-radius: 16px;
overflow: hidden;
background: var(--card-bg);
box-shadow: 0 12px 40px var(--shadow-soft);
}
// -----------------------------------------------------------------------------
// Sidebar
// -----------------------------------------------------------------------------
.catalog-sidebar {
display: flex;
flex-direction: column;
border-right: 1px solid var(--line);
background: var(--paper);
}
.catalog-sidebar__header {
padding: 24px 20px 16px;
border-bottom: 1px solid var(--line);
}
.catalog-sidebar__kicker {
margin: 0;
font-family: var(--mono);
font-size: 0.68rem;
font-weight: 700;
letter-spacing: 0.12em;
text-transform: uppercase;
color: var(--muted);
}
.catalog-sidebar__subtitle {
margin: 8px 0 0;
font-size: 0.85rem;
line-height: 1.45;
color: var(--soft-ink);
}
.catalog-sidebar__nav {
display: flex;
flex-direction: column;
gap: 4px;
padding: 16px 12px 24px;
overflow-y: auto;
}
.catalog-subject-select {
display: none;
}
.catalog-subject-btn {
width: 100%;
text-align: left;
padding: 12px 16px;
border: none;
border-radius: 12px;
font-family: var(--font-body);
font-size: 0.95rem;
font-weight: 500;
color: var(--soft-ink);
background: transparent;
cursor: pointer;
transition: background 200ms ease, color 200ms ease, box-shadow 200ms ease;
&:hover,
&:focus-visible {
background: var(--card-bg);
color: var(--ink);
}
&.is-active {
background: var(--accent);
color: #fff;
box-shadow: 0 4px 14px rgba(154, 107, 46, 0.35);
}
}
[data-theme="dark"] .catalog-subject-btn.is-active {
box-shadow: 0 4px 14px rgba(196, 146, 74, 0.25);
}
// -----------------------------------------------------------------------------
// Main column
// -----------------------------------------------------------------------------
.catalog-main {
display: flex;
flex-direction: column;
min-width: 0;
min-height: 0;
background: var(--card-bg);
}
// -----------------------------------------------------------------------------
// Header
// -----------------------------------------------------------------------------
.catalog-header {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
justify-content: space-between;
gap: 20px 32px;
padding: 28px 32px 24px;
border-bottom: 1px solid var(--line);
background: var(--card-bg);
overflow: visible;
position: relative;
z-index: 10;
}
.catalog-header--has-banner {
flex-direction: column;
align-items: stretch;
gap: 0;
padding-top: 0;
padding-bottom: 20px;
}
.catalog-header--has-banner .catalog-header__head,
.catalog-header--has-banner .catalog-header__filters {
position: relative;
z-index: 1;
}
.catalog-header--has-banner .catalog-header__head {
margin-top: -3rem;
}
.catalog-header--has-banner .catalog-header__filters {
margin-top: 4px;
}
.catalog-header__banner {
position: relative;
width: calc(100% + 64px);
max-height: 220px;
margin: 0 -32px;
aspect-ratio: 2 / 1;
overflow: hidden;
background: var(--card-bg);
img {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
mask-image: linear-gradient(
to bottom,
#000 0%,
#000 38%,
rgb(0 0 0 / 0.55) 72%,
transparent 100%
);
-webkit-mask-image: linear-gradient(
to bottom,
#000 0%,
#000 38%,
rgb(0 0 0 / 0.55) 72%,
transparent 100%
);
}
&::after {
content: "";
position: absolute;
inset: 0;
pointer-events: none;
background: linear-gradient(
to bottom,
transparent 0%,
transparent 58%,
color-mix(in srgb, var(--card-bg) 45%, transparent) 80%,
var(--card-bg) 100%
);
}
}
.catalog-header__head {
display: flex;
justify-content: space-between;
gap: 14px;
min-width: 0;
}
.catalog-header__intro {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: flex-start;
gap: 8px;
width: 100%;
}
.catalog-header__title {
margin: 0;
font-family: var(--font-heading);
font-size: clamp(1.75rem, 3vw, 2.25rem);
font-weight: 400;
color: var(--ink);
line-height: 1.15;
}
.catalog-header__stats {
margin: 0;
font-size: 0.9rem;
color: var(--muted);
}
.catalog-subject-contributors {
display: flex;
align-items: center;
gap: 10px;
}
.catalog-avatar-group {
display: inline-flex;
align-items: center;
margin: 0;
padding: 0;
list-style: none;
}
.catalog-avatar-group__item {
width: 36px;
height: 36px;
margin-left: -8px;
border: 2px solid var(--card-bg);
border-radius: 50%;
overflow: hidden;
background: var(--card-bg);
box-shadow: 0 2px 8px var(--shadow-soft);
&:first-child {
margin-left: 0;
}
img {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
}
}
.catalog-avatar-group__button {
display: block;
width: 100%;
height: 100%;
border: none;
padding: 0;
background: transparent;
cursor: pointer;
}
.catalog-subject-contributors__info {
display: none;
padding: 6px 10px;
border: 1px solid var(--line);
border-radius: 999px;
background: var(--paper);
color: var(--ink);
font-size: 0.82rem;
font-weight: 600;
cursor: pointer;
}
.catalog-contributors-dialog {
max-width: min(92vw, 420px);
}
.catalog-contributors-dialog__title {
margin: 0;
font-size: clamp(1.1rem, 2vw, 1.35rem);
font-family: var(--font-heading);
font-weight: 400;
line-height: 1.25;
}
.catalog-contributors-dialog__contributions {
margin: 0 0 14px;
color: var(--soft-ink);
font-size: 0.98rem;
line-height: 1.65;
}
.catalog-contributors-dialog__list {
margin: 8px 0 0;
padding: 0;
list-style: none;
display: grid;
gap: 10px;
}
.catalog-contributors-dialog__item {
display: flex;
align-items: center;
gap: 10px;
width: 100%;
border: 1px solid var(--line);
border-radius: 10px;
padding: 8px 10px;
color: var(--ink);
background: transparent;
text-align: left;
cursor: pointer;
}
.catalog-contributors-dialog__item:hover,
.catalog-contributors-dialog__item:focus-visible {
border-color: var(--accent);
background: var(--paper);
outline: none;
}
.catalog-contributors-dialog__avatar {
display: block;
border-radius: 50%;
object-fit: cover;
border: 1px solid var(--card-border);
background: var(--paper);
}
.catalog-view-toggle {
display: inline-flex;
align-self: flex-end;
height: 48px;
padding: 4px;
border: 1px solid var(--line);
border-radius: 999px;
background: var(--paper);
}
.catalog-view-toggle__btn {
padding: 6px 18px;
border: none;
border-radius: 999px;
font-family: var(--font-body);
font-size: 0.82rem;
font-weight: 600;
color: var(--soft-ink);
background: transparent;
cursor: pointer;
transition: background 200ms ease, color 200ms ease;
&:hover,
&:focus-visible {
color: var(--ink);
}
&[aria-selected="true"] {
background: var(--ink);
color: var(--paper);
}
}
.catalog-header__filters {
flex: 0 1 auto;
align-self: flex-end;
}
// -----------------------------------------------------------------------------
// Filter menu (glass dropdown — not --card-bg; see panel background)
// -----------------------------------------------------------------------------
.catalog-filter-menu {
position: relative;
width: min(100%, 18rem);
}
.catalog-filter-menu__trigger {
display: flex;
align-items: center;
gap: 10px;
width: 100%;
padding: 8px 12px;
border: 1px solid var(--line);
border-radius: 10px;
font-family: var(--font-body);
color: var(--ink);
background: var(--paper);
cursor: pointer;
transition: border-color 200ms ease, background 200ms ease;
&:hover,
&:focus-visible {
border-color: var(--accent);
outline: none;
}
}
.catalog-filter-menu__trigger-kicker {
font-family: var(--mono);
font-size: 0.62rem;
font-weight: 700;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--muted);
}
.catalog-filter-menu__trigger-value {
flex: 1;
text-align: left;
font-size: 0.88rem;
font-weight: 600;
}
.catalog-filter-menu__chevron {
width: 0.45rem;
height: 0.45rem;
border-right: 2px solid var(--soft-ink);
border-bottom: 2px solid var(--soft-ink);
transform: rotate(45deg) translateY(-2px);
}
.catalog-filter-menu__panel {
position: absolute;
top: calc(100% + 6px);
right: 0;
z-index: 30;
display: flex;
flex-direction: column;
gap: 2px;
min-width: 100%;
padding: 6px;
border: 1px solid var(--card-border);
border-radius: 10px;
background: var(--header-bg-scrolled);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
box-shadow: 0 10px 28px var(--shadow-soft);
}
.catalog-filter-menu__option {
display: flex;
align-items: center;
gap: 10px;
padding: 8px 10px;
border-radius: 8px;
font-size: 0.88rem;
font-weight: 600;
color: var(--ink);
cursor: pointer;
transition: background 150ms ease;
&:hover {
background: color-mix(in srgb, var(--paper) 55%, transparent);
}
}
.catalog-filter-menu__checkbox {
width: 1rem;
height: 1rem;
margin: 0;
accent-color: var(--accent);
cursor: pointer;
}
.catalog-filter-menu__option-label {
flex: 1;
}
// -----------------------------------------------------------------------------
// Content area
// -----------------------------------------------------------------------------
.catalog-content {
flex: 1;
min-width: 0;
overflow-y: auto;
padding: 32px;
}
.catalog-content--tree {
display: flex;
flex-direction: column;
flex: 1 1 0%;
min-height: 0;
padding: 0;
overflow: hidden;
}
.catalog-canvas-loading {
margin: auto;
padding: 48px;
text-align: center;
color: var(--muted);
}
.catalog-mermaid-stage {
position: relative;
flex: 1 1 auto;
width: 100%;
min-height: 0;
background: var(--paper);
}
.catalog-mermaid-controls {
position: absolute;
right: 20px;
top: 20px;
z-index: 2;
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
gap: 8px;
}
.catalog-mermaid-controls__btn {
border: 1px solid var(--card-border);
border-radius: 8px;
padding: 6px 10px;
font-family: var(--mono);
font-size: 0.68rem;
font-weight: 700;
letter-spacing: 0.05em;
text-transform: uppercase;
color: var(--ink);
background: color-mix(in srgb, var(--paper) 88%, transparent);
cursor: pointer;
transition: border-color 180ms ease, color 180ms ease;
&:hover,
&:focus-visible {
border-color: var(--accent);
color: var(--accent);
outline: none;
}
}
.catalog-mermaid-view {
width: 100%;
height: 100%;
min-height: 0;
overflow: hidden;
touch-action: none;
overscroll-behavior: contain;
background:
radial-gradient(circle at 1px 1px, color-mix(in srgb, var(--line) 55%, transparent) 1px, transparent 0)
center / 16px 16px;
:global(.catalog-mermaid-view__svg) {
width: 100%;
height: 100%;
touch-action: none;
}
:global(svg[id^="catalog-mermaid-"]) {
width: 100%;
height: 100%;
}
:global(.catalog-mermaid-view__svg .node rect),
:global(.catalog-mermaid-view__svg .node polygon),
:global(.catalog-mermaid-view__svg .cluster > rect:not(.catalog-mermaid-strand-header)) {
fill: color-mix(in srgb, var(--paper) 92%, transparent);
stroke: color-mix(in srgb, var(--card-border) 88%, var(--line));
stroke-width: 1.3px;
}
:global(.catalog-mermaid-view__svg .cluster-label span),
:global(.catalog-mermaid-view__svg .nodeLabel p),
:global(.catalog-mermaid-view__svg .nodeLabel span) {
color: var(--ink);
font-family: var(--font-body);
}
:global(.catalog-mermaid-view__svg .edgeLabel span) {
background: color-mix(in srgb, var(--card-bg) 94%, transparent);
color: var(--soft-ink);
border: 1px solid var(--line);
border-radius: 6px;
padding: 2px 6px;
font-family: var(--mono);
font-size: 0.68rem;
letter-spacing: 0.05em;
text-transform: uppercase;
}
:global(.catalog-mermaid-view__svg .liveNode rect),
:global(.catalog-mermaid-view__svg .liveNode polygon) {
stroke: var(--accent);
fill: color-mix(in srgb, var(--paper) 94%, var(--accent) 6%);
}
:global(.catalog-mermaid-view__svg .plannedNode rect),
:global(.catalog-mermaid-view__svg .plannedNode polygon) {
stroke: color-mix(in srgb, var(--muted) 70%, var(--line));
fill: color-mix(in srgb, var(--paper) 82%, var(--muted) 18%);
}
:global(.catalog-mermaid-view__svg .plannedNode .catalog-mermaid-node__title) {
color: var(--muted);
}
:global(.catalog-mermaid-view__svg .plannedNode .catalog-mermaid-node__description) {
color: color-mix(in srgb, var(--muted) 88%, var(--soft-ink));
}
:global(.catalog-mermaid-view__svg .plannedNode .catalog-badge:not(.book-chapter-badge--planned)) {
opacity: 0.72;
}
:global(.catalog-mermaid-view__svg .edge-path path) {
stroke: color-mix(in srgb, var(--accent) 65%, var(--muted));
stroke-width: 1.8px;
}
/* Strand cluster fills come from Mermaid themeVariables (clusterBkg / secondaryColor), not CSS. */
:global(.catalog-mermaid-view__svg g.cluster.catalog-mermaid-strand-cluster > rect.catalog-mermaid-strand-header) {
stroke: none;
pointer-events: none;
}
:global(.catalog-mermaid-view__svg .catalog-mermaid-strand-header__rule) {
stroke-width: 1px;
pointer-events: none;
}
:global(.catalog-mermaid-view__svg foreignObject.catalog-mermaid-strand-label-fo) {
overflow: visible;
}
:global(.catalog-mermaid-view__svg g.cluster.catalog-mermaid-strand-cluster .cluster-label foreignObject),
:global(.catalog-mermaid-view__svg g.cluster.catalog-mermaid-strand-cluster .cluster-label foreignObject div),
:global(.catalog-mermaid-view__svg g.cluster.catalog-mermaid-strand-cluster .cluster-label foreignObject span),
:global(.catalog-mermaid-view__svg g.cluster.catalog-mermaid-strand-cluster .cluster-label foreignObject header),
:global(.catalog-mermaid-view__svg g.cluster.catalog-mermaid-strand-cluster .cluster-label .nodeLabel),
:global(.catalog-mermaid-view__svg g.cluster.catalog-mermaid-strand-cluster .cluster-label .label) {
overflow: visible !important;
border: none !important;
border-radius: 0 !important;
background: transparent !important;
box-shadow: none !important;
}
:global(.catalog-mermaid-view__svg g.cluster.catalog-mermaid-strand-cluster .cluster-label .catalog-mermaid-strand__header) {
display: flex;
align-items: center;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: visible;
}
:global(.catalog-mermaid-view__svg g.cluster.catalog-mermaid-strand-cluster .cluster-label .catalog-mermaid-strand__title) {
display: block;
margin: 0;
padding: 2px 0 4px;
font-family: var(--font-heading);
font-size: 0.95rem;
font-weight: 400;
line-height: 1.35;
letter-spacing: 0.01em;
color: var(--ink);
white-space: nowrap;
overflow: visible;
}
:global(.catalog-mermaid-node) {
width: min(300px, 46vw);
display: flex;
flex-direction: column;
gap: 8px;
text-align: left;
}
:global(.catalog-mermaid-node__title) {
margin: 0;
font-family: var(--font-heading);
font-size: 1rem;
line-height: 1.2;
color: var(--ink);
}
:global(.catalog-mermaid-node__description) {
margin: 0;
font-size: 0.82rem;
line-height: 1.4;
color: var(--soft-ink);
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
line-clamp: 3;
overflow: hidden;
}
:global(.catalog-mermaid-node__meta) {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px;
}
:global(.catalog-mermaid-node .catalog-badge) {
font-size: 0.6rem;
}
}
[data-theme="dark"] .catalog-mermaid-view {
:global(.catalog-mermaid-view__svg .node rect),
:global(.catalog-mermaid-view__svg .node polygon),
:global(.catalog-mermaid-view__svg .cluster > rect:not(.catalog-mermaid-strand-header)) {
stroke: color-mix(in srgb, var(--accent) 78%, #ffffff 22%);
}
:global(.catalog-mermaid-view__svg .edge-path path),
:global(.catalog-mermaid-view__svg .arrowheadPath) {
stroke: color-mix(in srgb, var(--accent) 88%, #ffffff 12%);
fill: color-mix(in srgb, var(--accent) 88%, #ffffff 12%);
}
:global(.catalog-mermaid-view__svg .edgeLabel span) {
border-color: color-mix(in srgb, var(--accent) 52%, var(--line));
}
}
// -----------------------------------------------------------------------------
// List layout (strands, tree, cards)
// -----------------------------------------------------------------------------
.catalog-strand {
margin-bottom: 48px;
animation: catalog-fade-in 0.4s ease-out forwards;
&:last-child {
margin-bottom: 0;
}
}
@keyframes catalog-fade-in {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.catalog-strand__title {
display: flex;
align-items: center;
gap: 12px;
margin: 0 0 24px;
font-family: var(--font-heading);
font-size: 1.35rem;
color: var(--ink);
}
.catalog-strand__marker {
display: inline-flex;
align-items: center;
justify-content: center;
width: 2rem;
height: 2rem;
border: 1px solid var(--line);
border-radius: 8px;
font-size: 0.75rem;
color: var(--muted);
background: var(--paper);
}
.catalog-tree {
list-style: none;
margin: 0;
padding: 0 0 0 24px;
position: relative;
&::before {
content: "";
position: absolute;
top: 8px;
bottom: 8px;
left: 11px;
width: 2px;
background: var(--line);
}
}
.catalog-tree__item {
position: relative;
margin-bottom: 16px;
&:last-child {
margin-bottom: 0;
}
&::before {
content: "";
position: absolute;
left: -19px;
top: 50%;
transform: translateY(-50%);
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--line);
box-shadow: 0 0 0 4px var(--card-bg);
transition: background 200ms ease;
}
&:hover::before,
&:focus-within::before {
background: var(--accent);
}
&:has(.catalog-chapter-card--planned)::before {
background: color-mix(in srgb, var(--muted) 45%, var(--line));
box-shadow: 0 0 0 4px var(--card-bg);
}
&:has(.catalog-chapter-card--planned):hover::before,
&:has(.catalog-chapter-card--planned):focus-within::before {
background: color-mix(in srgb, var(--muted) 45%, var(--line));
}
}
.catalog-chapter-card {
display: flex;
flex-direction: column;
gap: 12px;
margin-left: 8px;
padding: 16px 20px;
border: 1px solid var(--card-border);
border-radius: 12px;
background: var(--paper);
text-decoration: none;
color: var(--ink);
transition: border-color 200ms ease, box-shadow 200ms ease;
&--planned {
color: var(--muted);
background: color-mix(in srgb, var(--paper) 86%, var(--muted) 14%);
border-color: color-mix(in srgb, var(--line) 65%, transparent);
border-style: dashed;
cursor: default;
.catalog-chapter-card__number,
.catalog-chapter-card__title,
.catalog-chapter-card__description {
color: var(--muted);
}
.catalog-badge:not(.book-chapter-badge--planned) {
opacity: 0.72;
}
.book-chapter-badge--planned {
color: var(--muted);
background: color-mix(in srgb, var(--muted) 16%, transparent);
border: 1px solid color-mix(in srgb, var(--line) 75%, transparent);
}
}
}
a.catalog-chapter-card {
&:hover,
&:focus-visible {
border-color: var(--accent);
box-shadow: 0 6px 20px var(--shadow-soft);
}
&:hover .catalog-chapter-card__number,
&:focus-visible .catalog-chapter-card__number {
color: var(--accent);
}
}
.catalog-chapter-card__main {
display: flex;
align-items: center;
gap: 16px;
}
.catalog-chapter-card__number {
flex-shrink: 0;
width: 2rem;
font-family: var(--mono);
font-size: 0.8rem;
font-weight: 700;
color: var(--muted);
text-align: center;
}
.catalog-chapter-card__title {
margin: 0;
font-family: var(--font-heading);
font-size: 1.1rem;
font-weight: 400;
line-height: 1.25;
}
.catalog-chapter-card__title-link {
@include catalog-chapter-title-link-with-arrow;
}
.catalog-chapter-card__title-arrow {
@include catalog-chapter-title-arrow;
}
.catalog-map-measure-shell {
overflow: hidden;
}
.catalog-chapter-card__body {
display: flex;
flex-direction: column;
gap: 10px;
width: 100%;
}
.catalog-chapter-card__description {
margin: 0;
font-size: 0.85rem;
line-height: 1.45;
color: var(--soft-ink);
}
.catalog-chapter-card__meta {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px;
padding-left: 0px;
max-height: 0;
opacity: 0;
overflow: hidden;
pointer-events: none;
transform: translateY(-4px);
transition:
max-height 220ms ease,
opacity 180ms ease,
transform 220ms ease;
}
.catalog-chapter-card:is(:hover, :focus-within, :active) .catalog-chapter-card__meta {
max-height: 120px;
opacity: 1;
pointer-events: auto;
transform: translateY(0);
}
// -----------------------------------------------------------------------------
// Badges & empty state
// -----------------------------------------------------------------------------
@mixin catalog-badge-tokens-dark {
--badge-foundation-fg: #5eead4;
--badge-foundation-bg: rgba(45, 212, 191, 0.22);
--badge-foundation-border: rgba(94, 234, 212, 0.45);
--badge-dse-fg: #93c5fd;
--badge-dse-bg: rgba(96, 165, 250, 0.22);
--badge-dse-border: rgba(147, 197, 253, 0.45);
--badge-ib-fg: #c4b5fd;
--badge-ib-bg: rgba(167, 139, 250, 0.22);
--badge-ib-border: rgba(196, 181, 253, 0.45);
--badge-a-level-fg: #6ee7b7;
--badge-a-level-bg: rgba(52, 211, 153, 0.2);
--badge-a-level-border: rgba(110, 231, 183, 0.42);
--badge-ap-fg: #fcd34d;
--badge-ap-bg: rgba(251, 191, 36, 0.2);
--badge-ap-border: rgba(252, 211, 77, 0.45);
--badge-igcse-fg: #fda4af;
--badge-igcse-bg: rgba(251, 113, 133, 0.2);
--badge-igcse-border: rgba(253, 164, 175, 0.45);
--badge-common-core-fg: #93c5fd;
--badge-common-core-bg: rgba(59, 130, 246, 0.22);
--badge-common-core-border: rgba(147, 197, 253, 0.45);
--badge-extension-fg: #fdba74;
--badge-extension-bg: rgba(251, 146, 60, 0.22);
--badge-extension-border: rgba(253, 186, 116, 0.45);
--badge-default-fg: #e7e5e0;
--badge-default-bg: rgba(236, 234, 228, 0.1);
--badge-default-border: rgba(236, 234, 228, 0.28);
}
:root {
--badge-foundation-fg: #0f766e;
--badge-foundation-bg: rgba(20, 184, 166, 0.12);
--badge-foundation-border: rgba(20, 184, 166, 0.28);
--badge-dse-fg: #1d4ed8;
--badge-dse-bg: rgba(59, 130, 246, 0.12);
--badge-dse-border: rgba(59, 130, 246, 0.25);
--badge-ib-fg: #6d28d9;
--badge-ib-bg: rgba(139, 92, 246, 0.12);
--badge-ib-border: rgba(139, 92, 246, 0.25);
--badge-a-level-fg: #047857;
--badge-a-level-bg: rgba(16, 185, 129, 0.12);
--badge-a-level-border: rgba(16, 185, 129, 0.25);
--badge-ap-fg: #b45309;
--badge-ap-bg: rgba(245, 158, 11, 0.12);
--badge-ap-border: rgba(245, 158, 11, 0.25);
--badge-igcse-fg: #be123c;
--badge-igcse-bg: rgba(244, 63, 94, 0.12);
--badge-igcse-border: rgba(244, 63, 94, 0.25);
--badge-common-core-fg: #1e40af;
--badge-common-core-bg: rgba(37, 99, 235, 0.1);
--badge-common-core-border: rgba(37, 99, 235, 0.25);
--badge-extension-fg: #9a3412;
--badge-extension-bg: rgba(234, 88, 12, 0.1);
--badge-extension-border: rgba(234, 88, 12, 0.28);
--badge-default-fg: var(--soft-ink);
--badge-default-bg: var(--paper);
--badge-default-border: var(--line);
}
[data-theme="dark"] {
@include catalog-badge-tokens-dark;
}
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
@include catalog-badge-tokens-dark;
}
}
.catalog-badge {
padding: 4px 8px;
border: 1px solid transparent;
border-radius: 6px;
font-family: var(--mono);
font-size: 0.62rem;
font-weight: 700;
letter-spacing: 0.06em;
text-transform: uppercase;
&--foundation {
color: var(--badge-foundation-fg);
background: var(--badge-foundation-bg);
border-color: var(--badge-foundation-border);
}
&--dse {
color: var(--badge-dse-fg);
background: var(--badge-dse-bg);
border-color: var(--badge-dse-border);
}
&--ib {
color: var(--badge-ib-fg);
background: var(--badge-ib-bg);
border-color: var(--badge-ib-border);
}
&--a-level {
color: var(--badge-a-level-fg);
background: var(--badge-a-level-bg);
border-color: var(--badge-a-level-border);
}
&--ap {
color: var(--badge-ap-fg);
background: var(--badge-ap-bg);
border-color: var(--badge-ap-border);
}
&--igcse {
color: var(--badge-igcse-fg);
background: var(--badge-igcse-bg);
border-color: var(--badge-igcse-border);
}
&--common-core {
color: var(--badge-common-core-fg);
background: var(--badge-common-core-bg);
border-color: var(--badge-common-core-border);
}
&--extension {
color: var(--badge-extension-fg);
background: var(--badge-extension-bg);
border-color: var(--badge-extension-border);
}
&--default {
color: var(--badge-default-fg);
background: var(--badge-default-bg);
border-color: var(--badge-default-border);
}
}
.catalog-empty {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 280px;
padding: 48px 24px;
text-align: center;
}
.catalog-empty__title {
margin: 0;
font-family: var(--font-heading);
font-size: 1.5rem;
color: var(--ink);
}
.catalog-empty__text {
margin: 12px 0 0;
max-width: 28rem;
font-size: 0.95rem;
line-height: 1.6;
color: var(--soft-ink);
}
// -----------------------------------------------------------------------------
// Compare doc (mathematics curricula)
// -----------------------------------------------------------------------------
.catalog-shell--compare .catalog-content {
padding-top: 8px;
overflow-x: hidden;
}
.catalog-compare-doc {
width: min(56rem, 100%);
max-width: 56rem;
min-width: 0;
box-sizing: border-box;
padding: 8px 24px 48px;
overflow-wrap: anywhere;
}
.catalog-compare-doc__lead {
margin: 0 0 24px;
font-size: 1.05rem;
line-height: 1.6;
color: var(--soft-ink);
}
.catalog-compare-doc__section {
margin-top: 32px;
}
.catalog-compare-doc__heading {
margin: 0 0 12px;
font-family: var(--font-heading);
font-size: 1.35rem;
color: var(--ink);
}
.catalog-compare-doc__subheading {
margin: 20px 0 8px;
font-family: var(--font-heading);
font-size: 1.1rem;
color: var(--ink);
}
.catalog-compare-doc__legend {
margin: 0;
padding: 0;
list-style: none;
display: flex;
flex-wrap: wrap;
gap: 12px 20px;
font-size: 0.88rem;
color: var(--soft-ink);
}
.catalog-compare-doc__table-wrap {
max-width: 100%;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
margin-top: 12px;
border: 1px solid var(--line);
border-radius: 12px;
background: var(--paper);
}
.catalog-compare-table {
width: 100%;
min-width: max-content;
border-collapse: collapse;
font-size: 0.82rem;
line-height: 1.45;
th,
td {
padding: 10px 12px;
border-bottom: 1px solid var(--line);
vertical-align: top;
text-align: left;
}
thead th {
position: sticky;
top: 0;
z-index: 1;
background: var(--card-bg);
font-family: var(--mono);
font-size: 0.62rem;
font-weight: 700;
letter-spacing: 0.05em;
text-transform: uppercase;
color: var(--muted);
white-space: nowrap;
}
tbody th[scope="row"] {
font-weight: 600;
color: var(--ink);
min-width: 10rem;
}
&__caption {
padding: 12px 14px;
text-align: left;
font-size: 0.8rem;
color: var(--muted);
caption-side: top;
}
&__chapter a {
color: var(--accent);
text-decoration: none;
&:hover,
&:focus-visible {
text-decoration: underline;
}
}
&__cell {
text-align: center;
}
}
.catalog-compare-cell {
display: inline-block;
min-width: 2.25rem;
padding: 2px 6px;
border-radius: 4px;
font-family: var(--mono);
font-size: 0.62rem;
font-weight: 700;
letter-spacing: 0.04em;
text-transform: uppercase;
&--core {
color: var(--badge-foundation-fg);
background: var(--badge-foundation-bg);
border: 1px solid var(--badge-foundation-border);
}
&--ext {
color: var(--badge-dse-fg);
background: var(--badge-dse-bg);
border: 1px solid var(--badge-dse-border);
}
&--rel {
color: var(--badge-ib-fg);
background: var(--badge-ib-bg);
border: 1px solid var(--badge-ib-border);
}
&--none {
color: var(--muted);
background: transparent;
}
}
.catalog-compare-doc__refs {
margin: 12px 0 0;
padding-left: 1.25rem;
line-height: 1.6;
a {
color: var(--accent);
}
}
.catalog-compare-doc__updated {
margin: 20px 0 0;
font-size: 0.85rem;
color: var(--muted);
}
// -----------------------------------------------------------------------------
// Responsive
// -----------------------------------------------------------------------------
@media (min-width: 640px) {
.catalog-chapter-card:not(.catalog-chapter-card--map) {
flex-direction: row;
align-items: flex-start;
justify-content: space-between;
.catalog-chapter-card__body {
flex: 1;
min-width: 0;
}
}
.catalog-chapter-card__meta {
padding-left: 0;
}
}
@media (min-width: 769px) {
.catalog-shell--tree {
max-width: min(1680px, calc(100% - 48px));
height: calc(100vh - 160px);
max-height: calc(100vh - 160px);
min-height: 0;
}
.catalog-shell--tree .catalog-main {
display: flex;
flex-direction: column;
height: 100%;
min-height: 0;
overflow: hidden;
}
.catalog-shell--tree .catalog-header {
flex-shrink: 0;
}
}
@media (max-width: 768px) {
.catalog-shell {
grid-template-columns: 1fr;
min-height: auto;
}
.catalog-sidebar {
border-right: none;
border-bottom: 1px solid var(--line);
}
.catalog-sidebar__nav {
display: block;
padding: 12px;
}
.catalog-subject-select {
display: block;
width: 100%;
padding: 10px 12px;
border: 1px solid var(--card-border);
border-radius: 10px;
font-family: var(--font-body);
font-size: 0.95rem;
color: var(--ink);
background: var(--card-bg);
}
.catalog-subject-btn {
display: none;
}
.catalog-header {
padding: 20px 20px 16px;
flex-direction: column;
gap: 18px;
}
.catalog-header--has-banner {
padding: 0 0 16px;
gap: 0;
}
.catalog-header--has-banner .catalog-header__head,
.catalog-header--has-banner .catalog-header__filters {
padding-left: 20px;
padding-right: 20px;
}
.catalog-header__banner {
width: calc(100% + 40px);
margin: 0 -20px;
}
.catalog-header__head {
width: 100%;
flex-direction: column;
align-items: flex-start;
}
.catalog-avatar-group {
display: none;
}
.catalog-subject-contributors__info {
display: inline-flex;
align-items: center;
justify-content: center;
}
.catalog-view-toggle {
align-self: stretch;
width: 100%;
justify-content: stretch;
&__btn {
flex: 1;
}
}
.catalog-header__filters {
width: 100%;
align-self: stretch;
}
.catalog-filter-menu {
width: 100%;
}
.catalog-content {
padding: 0px;
}
.catalog-content--tree {
flex: 1 1 0%;
min-height: min(70vh, 560px);
max-height: min(70vh, 560px);
}
.catalog-mermaid-controls {
right: 12px;
top: 12px;
}
}
@media (prefers-reduced-motion: reduce) {
.catalog-strand {
animation: none;
}
}