/* Outfit, self-hosted.

   Served from our own origin, never from fonts.gstatic.com: loading a webfont
   from Google's CDN transmits the visitor's IP address to Google, which German
   courts have held requires consent (LG München I, 3 O 17493/20). A heading
   face is not worth a consent gate - least of all on the landing page, whose
   whole job is to not lose the visitor - and self-hosting removes the question
   entirely. See docs/design/landing_page.md §5.

   Two files, both variable across the whole 100-900 weight axis, so every
   weight the design uses costs one download rather than one per weight. The
   unicode-range split is Google's own: a visitor who never renders an accented
   character never fetches the latin-ext file. Licensed under the SIL Open Font
   License 1.1 - app/assets/fonts/OFL.txt travels with the font files, which is
   what that license asks for.

   Outfit has no CJK coverage, so anything Chinese falls through to the next
   family in the stack whatever this says. It is a face for headings, not for
   the characters the site teaches. */
@font-face {
    font-family: 'Outfit';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url("/assets/outfit-latin-ext-e51c1c3c.woff2") format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: 'Outfit';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url("/assets/outfit-latin-c0a8d111.woff2") format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
    --bs-primary: #5942c1;
    --bs-primary-rgb: 89, 66, 193;
    --bs-link-color: var(--bs-primary);
    --bs-link-hover-color: #5b58e6;
    --bs-pagination-active-bg: #ab96d3;

    --primary: var(--bs-primary);
    --gray-100: #f8f9fa;
    --gray-200: #e9ecef;
    --gray-300: #dee2e6;
    --gray-400: #ced4da;
    --gray-500: #adb5bd;
    --gray-600: #6c757d;
    --gray-700: #495057;
    --gray-800: #343a40;
    --gray-900: #212529;
    --gray-850: #2a2d2f;
    --border-width: 1px;
    --border-color: var(--gray-300);
    --border-radius: 0.375rem;
}

.btn-primary {
    --bs-btn-color: #fff !important;
    --bs-btn-hover-color: #fff !important;
    --bs-btn-active-color: #fff !important;
    --bs-btn-bg: var(--bs-primary) !important;
    --bs-btn-border-color: var(--bs-primary) !important;
    --bs-btn-hover-bg: var(--bs-link-hover-color) !important;
    --bs-btn-hover-border-color: var(--bs-link-hover-color) !important;
    --bs-btn-active-bg: var(--bs-link-hover-color) !important;
    --bs-btn-active-border-color: var(--bs-link-hover-color) !important;
    --bs-btn-disabled-bg: var(--bs-primary) !important;
    --bs-btn-disabled-border-color: var(--bs-primary) !important;
}

.btn-outline-primary {
    --bs-btn-color: var(--bs-primary) !important;
    --bs-btn-border-color: var(--bs-primary) !important;
    --bs-btn-hover-bg: var(--bs-primary) !important;
    --bs-btn-hover-border-color: var(--bs-primary) !important;
    --bs-btn-hover-color: #fff !important;
    --bs-btn-active-bg: var(--bs-primary) !important;
    --bs-btn-active-border-color: var(--bs-primary) !important;
    --bs-btn-active-color: #fff !important;
}

.progress-bar {
    background-color: var(--bs-primary) !important;
}

.border-top {
    border-top: var(--border-width) solid var(--border-color);
}

.border-bottom {
    border-bottom: var(--border-width) solid var(--border-color);
}

.border-top-0 {
    border-top: 0 !important;
}

.border-bottom-0 {
    border-bottom: 0 !important;
}

.border-x {
    border-left: var(--border-width) solid var(--border-color);
    border-right: var(--border-width) solid var(--border-color);
}

.border-y {
    border-top: var(--border-width) solid var(--border-color);
    border-bottom: var(--border-width) solid var(--border-color);
}

.rounded-top {
    border-top-left-radius: var(--border-radius);
    border-top-right-radius: var(--border-radius);
}

.rounded-bottom {
    border-bottom-left-radius: var(--border-radius);
    border-bottom-right-radius: var(--border-radius);
}

.rounded-top-0 {
    border-top-left-radius: 0 !important;
    border-top-right-radius: 0 !important;
}

.rounded-bottom-0 {
    border-bottom-left-radius: 0 !important;
    border-bottom-right-radius: 0 !important;
}

@media (min-width: 576px) {
    .border-sm-top {
        border-top: var(--border-width) solid var(--border-color);
    }

    .border-sm-bottom {
        border-bottom: var(--border-width) solid var(--border-color);
    }

    .border-sm-top-0 {
        border-top: 0 !important;
    }

    .border-sm-bottom-0 {
        border-bottom: 0 !important;
    }

    .border-sm-x {
        border-left: var(--border-width) solid var(--border-color);
        border-right: var(--border-width) solid var(--border-color);
    }

    .border-sm-y {
        border-top: var(--border-width) solid var(--border-color);
        border-bottom: var(--border-width) solid var(--border-color);
    }

    .rounded-sm-top {
        border-top-left-radius: var(--border-radius);
        border-top-right-radius: var(--border-radius);
    }

    .rounded-sm-bottom {
        border-bottom-left-radius: var(--border-radius);
        border-bottom-right-radius: var(--border-radius);
    }

    .rounded-sm-top-0 {
        border-top-left-radius: 0 !important;
        border-top-right-radius: 0 !important;
    }

    .rounded-sm-bottom-0 {
        border-bottom-left-radius: 0 !important;
        border-bottom-right-radius: 0 !important;
    }
}

@media (min-width: 768px) {
    .border-md-top {
        border-top: var(--border-width) solid var(--border-color);
    }

    .border-md-bottom {
        border-bottom: var(--border-width) solid var(--border-color);
    }

    .border-md-top-0 {
        border-top: 0 !important;
    }

    .border-md-bottom-0 {
        border-bottom: 0 !important;
    }

    .border-md-x {
        border-left: var(--border-width) solid var(--border-color);
        border-right: var(--border-width) solid var(--border-color);
    }

    .border-md-y {
        border-top: var(--border-width) solid var(--border-color);
        border-bottom: var(--border-width) solid var(--border-color);
    }

    .rounded-md-top {
        border-top-left-radius: var(--border-radius);
        border-top-right-radius: var(--border-radius);
    }

    .rounded-md-bottom {
        border-bottom-left-radius: var(--border-radius);
        border-bottom-right-radius: var(--border-radius);
    }

    .rounded-md-top-0 {
        border-top-left-radius: 0 !important;
        border-top-right-radius: 0 !important;
    }

    .rounded-md-bottom-0 {
        border-bottom-left-radius: 0 !important;
        border-bottom-right-radius: 0 !important;
    }
}

@media (min-width: 992px) {
    .border-lg-top {
        border-top: var(--border-width) solid var(--border-color);
    }

    .border-lg-bottom {
        border-bottom: var(--border-width) solid var(--border-color);
    }

    .border-lg-top-0 {
        border-top: 0 !important;
    }

    .border-lg-bottom-0 {
        border-bottom: 0 !important;
    }

    .border-lg-x {
        border-left: var(--border-width) solid var(--border-color);
        border-right: var(--border-width) solid var(--border-color);
    }

    .border-lg-y {
        border-top: var(--border-width) solid var(--border-color);
        border-bottom: var(--border-width) solid var(--border-color);
    }

    .rounded-lg-top {
        border-top-left-radius: var(--border-radius);
        border-top-right-radius: var(--border-radius);
    }

    .rounded-lg-bottom {
        border-bottom-left-radius: var(--border-radius);
        border-bottom-right-radius: var(--border-radius);
    }

    .rounded-lg-top-0 {
        border-top-left-radius: 0 !important;
        border-top-right-radius: 0 !important;
    }

    .rounded-lg-bottom-0 {
        border-bottom-left-radius: 0 !important;
        border-bottom-right-radius: 0 !important;
    }
}

@media (min-width: 1200px) {
    .border-xl-top {
        border-top: var(--border-width) solid var(--border-color);
    }

    .border-xl-bottom {
        border-bottom: var(--border-width) solid var(--border-color);
    }

    .border-xl-top-0 {
        border-top: 0 !important;
    }

    .border-xl-bottom-0 {
        border-bottom: 0 !important;
    }

    .border-xl-x {
        border-left: var(--border-width) solid var(--border-color);
        border-right: var(--border-width) solid var(--border-color);
    }

    .border-xl-y {
        border-top: var(--border-width) solid var(--border-color);
        border-bottom: var(--border-width) solid var(--border-color);
    }

    .rounded-xl-top {
        border-top-left-radius: var(--border-radius);
        border-top-right-radius: var(--border-radius);
    }

    .rounded-xl-bottom {
        border-bottom-left-radius: var(--border-radius);
        border-bottom-right-radius: var(--border-radius);
    }

    .rounded-xl-top-0 {
        border-top-left-radius: 0 !important;
        border-top-right-radius: 0 !important;
    }

    .rounded-xl-bottom-0 {
        border-bottom-left-radius: 0 !important;
        border-bottom-right-radius: 0 !important;
    }
}

@media (min-width: 1400px) {
    .border-xxl-top {
        border-top: var(--border-width) solid var(--border-color);
    }

    .border-xxl-bottom {
        border-bottom: var(--border-width) solid var(--border-color);
    }

    .border-xxl-top-0 {
        border-top: 0 !important;
    }

    .border-xxl-bottom-0 {
        border-bottom: 0 !important;
    }

    .border-xxl-x {
        border-left: var(--border-width) solid var(--border-color);
        border-right: var(--border-width) solid var(--border-color);
    }

    .border-xxl-y {
        border-top: var(--border-width) solid var(--border-color);
        border-bottom: var(--border-width) solid var(--border-color);
    }

    .rounded-xxl-top {
        border-top-left-radius: var(--border-radius);
        border-top-right-radius: var(--border-radius);
    }

    .rounded-xxl-bottom {
        border-bottom-left-radius: var(--border-radius);
        border-bottom-right-radius: var(--border-radius);
    }

    .rounded-xxl-top-0 {
        border-top-left-radius: 0 !important;
        border-top-right-radius: 0 !important;
    }

    .rounded-xxl-bottom-0 {
        border-bottom-left-radius: 0 !important;
        border-bottom-right-radius: 0 !important;
    }
}

a:not(.btn):not(.nav-link):not(.page-link),
a:not(.btn):not(.nav-link):not(.page-link):link,
a:not(.btn):not(.nav-link):not(.page-link):visited,
a:not(.btn):not(.nav-link):not(.page-link):active {
    color: var(--bs-primary);
    text-decoration: none;
}

a:not(.btn):not(.nav-link):not(.page-link):hover {
    color: var(--bs-link-hover-color);
    text-decoration: underline;
}

.color1,
.color1:hover {
    color: red !important;
}

.color2,
.color2:hover {
    color: #d80 !important;
}

.color3,
.color3:hover {
    color: green !important;
}

.color4,
.color4:hover {
    color: blue !important;
}

.color5,
.color5:hover {
    color: gray !important;
}

.uncolored,
a.uncolored,
a:link.uncolored,
a:visited.uncolored,
a:hover.uncolored,
a:active.uncolored {
    color: unset !important;
}

.bg-gray-100 {
    background-color: var(--gray-100);
}

.bg-gray-200 {
    background-color: var(--gray-200);
}

.bg-gray-300 {
    background-color: var(--gray-300);
}

.bg-gray-400 {
    background-color: var(--gray-400);
}

.bg-gray-500 {
    background-color: var(--gray-500);
}

.bg-gray-600 {
    background-color: var(--gray-600);
}

.bg-gray-700 {
    background-color: var(--gray-700);
}

.bg-gray-800 {
    background-color: var(--gray-800);
}

.bg-gray-850 {
    background-color: var(--gray-850);
}

.bg-gray-900 {
    background-color: var(--gray-900);
}

.border-gray-800 {
    border-color: var(--gray-800) !important;
}

.border-black {
    border-color: #000000 !important;
}

.bg-tile {
    background-image: url("/assets/bg_tile-0229beb0.png");
}

a.external:after {
    color: var(--primary);
    padding-left: 2px;
    content: "🛪";
}

.pagination {
    --bs-pagination-active-bg: var(--bs-pagination-active-bg);
    --bs-pagination-active-border-color: var(--bs-pagination-active-bg);
    --bs-pagination-active-color: var(--bs-primary);
    --bs-pagination-color: var(--bs-primary);
    --bs-pagination-hover-color: var(--bs-link-hover-color);
}



/* Place all the styles related to the hanzi tree here. */

.hanzi_tree {
    text-align: center;
    overflow-x: auto;
    padding: 20px 0;
    width: 100%;
    display: block;
}

.hanzi_tree ul {
    display: inline-flex;
    flex-direction: row;
    justify-content: center;
    align-items: flex-start;
    padding-top: 24px;
    position: relative;
    margin: 0;
    padding-left: 0;
}

.hanzi_tree>ul {
    padding-top: 0;
}

/* Downward line from parent */
.hanzi_tree ul::before {
    content: '';
    position: absolute;
    top: 0;
    left: 50%;
    border-left: 2px solid var(--gray-500);
    width: 0;
    height: 24px;
}

.hanzi_tree>ul::before {
    display: none;
}

.hanzi_tree li {
    display: flex;
    flex-direction: column;
    align-items: center;
    position: relative;
    padding: 24px 4px 0px 4px;
    list-style-type: none;
    margin: 0;
}

/* Horizontal connectors between sibling nodes */
.hanzi_tree li::before,
.hanzi_tree li::after {
    content: '';
    position: absolute;
    top: 0;
    right: 50%;
    border-top: 2px solid var(--gray-500);
    width: 50%;
    height: 24px;
    box-sizing: border-box;
}

.hanzi_tree li::after {
    right: auto;
    left: 50%;
}

/* Vertical line going up from child center */
.hanzi_tree li::before {
    border-right: 2px solid var(--gray-500);
}

/* Remove connectors for single children */
.hanzi_tree li:only-child::after,
.hanzi_tree li:only-child::before {
    display: none;
}

.hanzi_tree li:only-child {
    padding-top: 0;
}

/* Remove horizontal line to the left of first child */
.hanzi_tree li:first-child::before {
    border-top: 0 none;
}

/* Remove horizontal line to the right of last child */
.hanzi_tree li:last-child::after {
    border-top: 0 none;
}

/* Inside element styling */
.hanzi_tree li span {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    text-decoration: none;
    background: transparent;
    transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
    z-index: 10;
    padding: 2px 4px;
}

.hanzi_tree li span:hover {
    /* transform: scale(1.15); */
}

.hanzi_tree li span a {
    color: var(--bs-primary);
    text-decoration: none;
    /* font-weight: bold; */
    transition: color 0.2s ease-in-out;
}

.hanzi_tree li span a:hover {
    text-decoration: none;
    color: var(--bs-link-hover-color, #4338ca);
}

/* Alternative decomposition intermediate node */
.hanzi_tree .alt-node {
    background: linear-gradient(135deg, var(--gray-100) 0%, var(--gray-200) 100%);
    border: 1px dashed var(--bs-primary) !important;
    border-radius: 16px;
    padding: 2px 10px;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--bs-primary);
    box-shadow: none;
    min-width: unset;
    height: auto;
    display: inline-block;
    text-align: center;
    z-index: 10;
}

.hanzi_tree .alt-node.canon {
    background: linear-gradient(135deg, #e8e5f8 0%, #dcd7f5 100%);
    border: 1px solid var(--bs-primary) !important;
    color: var(--bs-primary);
}

.hanzi_tree .alt-node.alt-circle {
    width: 14px;
    height: 14px;
    min-width: 14px;
    padding: 0;
    border-radius: 50% !important;
    background: var(--bs-primary);
    border: 2px solid var(--bs-body-bg) !important;
    box-shadow: 0 0 0 1px var(--bs-primary);
    z-index: 10;
    display: inline-flex;
    margin: 4px 0;
}

.hanzi_tree .tree-dec-buttons {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    z-index: 20;
    position: relative;
}

.hanzi_tree .btn-dec {
    background: var(--bs-body-bg);
    border: 1px dashed var(--bs-primary);
    border-radius: 16px;
    padding: 2px 8px;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--bs-primary);
    cursor: pointer;
    transition: all 0.2s ease-in-out;
    outline: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.hanzi_tree .btn-dec:hover {
    background: var(--gray-100);
    border-color: var(--bs-primary);
}

.hanzi_tree .btn-dec.active {
    background: var(--bs-primary);
    border: 1px solid var(--bs-primary);
    color: #fff;
}

.hanzi_tree ul.progress-vertical-ul {
    display: inline-flex !important;
    flex-direction: column !important;
    align-items: center !important;
    padding-top: 0 !important;
    padding-left: 0 !important;
    position: relative;
    margin: 0;
}

.hanzi_tree ul.progress-vertical-ul::before {
    display: none !important;
}

.hanzi_tree li.marilyn-column {
    padding-left: 0 !important;
    padding-right: 0 !important;
}

.hanzi_tree ul.progress-vertical-ul>li {
    padding: 16px 0 0 0 !important;
    display: flex !important;
    flex-direction: column !important;
    align-items: center !important;
    position: relative;
    list-style-type: none;
    margin: 0;
}

.hanzi_tree ul.progress-vertical-ul>li::before {
    display: none !important;
}

.hanzi_tree ul.progress-vertical-ul>li::after {
    content: '' !important;
    display: block !important;
    position: absolute !important;
    top: 0 !important;
    right: 50% !important;
    border-right: 2px solid var(--gray-500) !important;
    height: 16px !important;
    width: 0 !important;
    z-index: 1;
}


.spinner-sm {
    width: 20px;
    height: 20px;
}

.spinner-image {
    max-width: 100%;
    height: auto;
}

.text-truncate-4 {
    display: -webkit-box;
    -webkit-line-clamp: 4;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* AI Image Cards and Grid */
.ai-image-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 1.5rem;
    margin-bottom: 2rem;
}

.ai-image-card {
    transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
    border: 1px solid var(--gray-200);
    overflow: hidden;
    background: var(--bs-body-bg);
}

.ai-image-card:hover {
    /* transform: translateY(-4px); */
    box-shadow: 0 0.5rem 1.5rem rgba(0, 0, 0, 0.08) !important;
}

.ai-image-card .card-img-wrapper {
    position: relative;
    width: 100%;
    padding-top: 100%;
    /* 1:1 Aspect Ratio */
    background-color: var(--gray-100);
    overflow: hidden;
}

.ai-image-card .card-img-wrapper img,
.ai-image-card .card-img-wrapper .placeholder-spinner {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.ai-image-batch-badge {
    position: absolute;
    top: 0.75rem;
    left: 0.75rem;
    background: rgba(255, 193, 7, 0.9);
    /* yellow warning */
    backdrop-filter: blur(4px);
    color: #000;
    font-size: 0.75rem;
    padding: 0.25rem 0.5rem;
    border-radius: 20px;
    font-weight: 500;
}

@keyframes pulse {
    0% {
        box-shadow: 0 0 0 0 rgba(89, 66, 193, 0.4);
    }

    70% {
        box-shadow: 0 0 0 10px rgba(89, 66, 193, 0);
    }

    100% {
        box-shadow: 0 0 0 0 rgba(89, 66, 193, 0);
    }
}

.pulsing-border {
    animation: pulse 2s infinite;
}

@keyframes confetti-fall {
    0% {
        transform: translateY(-100vh) rotate(0deg);
        opacity: 1;
    }

    100% {
        transform: translateY(100vh) rotate(720deg);
        opacity: 0;
    }
}

.confetti-piece {
    position: fixed;
    width: 10px;
    height: 10px;
    top: -10px;
    z-index: 9999;
    animation: confetti-fall 3s ease-in-out forwards;
}

.hover-scale {
    transition: transform 0.2s ease-in-out;
}

.hover-scale:hover {
    transform: scale(1.05);
}

/* Linear Timeline Styles */
.sticky-timeline {
    position: sticky;
    top: 54px;
    z-index: 1020;
}

.no-scrollbar::-webkit-scrollbar {
    display: none;
}

.no-scrollbar {
    -ms-overflow-style: none;
    scrollbar-width: none;
}

@keyframes pulse-timeline {
    0% {
        box-shadow: 0 0 0 0 rgba(89, 66, 193, 0.4);
    }

    70% {
        box-shadow: 0 0 0 8px rgba(89, 66, 193, 0);
    }

    100% {
        box-shadow: 0 0 0 0 rgba(89, 66, 193, 0);
    }
}

/* Linear Timeline Responsiveness */
.timeline-wrapper {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.25rem 0;
    transition: max-height 0.3s ease-in-out;
}

.timeline-wrapper:not(.is-expanded) {
    flex-wrap: nowrap;
    overflow: hidden;
    max-height: 38px;
}

.timeline-wrapper:not(.is-expanded) .btn-success {
    display: none !important;
}

.timeline-wrapper.is-expanded {
    flex-wrap: wrap;
    max-height: 500px;
}

/* Learning-target cards: the three suggestions on the home page
   (static_pages/_landing_targets) and the single "make this your target" card
   on a character or comic page. These used to be an inline style plus a :css
   block inside the home page's partial, which only worked while the card lived
   on one page. */
.target-card {
    background: linear-gradient(135deg, var(--bs-body-bg) 0%, var(--bs-tertiary-bg) 100%);
    transition: transform 0.2s, box-shadow 0.2s;
}

.target-card:hover {
    transform: translateY(-5px);
    box-shadow: 0 .5rem 1.5rem rgba(0, 0, 0, .15) !important;
}

/* Decorative only, and knowingly so: this element holds a single Chinese
   character, and Outfit carries no CJK glyphs, so the browser falls through to
   the sans-serif behind it either way. Kept because the fallback is what the
   card has always rendered - and because deleting the rule would invite
   somebody to "restore" it as a real change later. */
.target-card-hanzi {
    font-family: 'Outfit', sans-serif;
}

/* A block of explanatory prose above a section: kept to a readable measure
   rather than the full container width. */
.lead-prose {
    max-width: 40rem;
}

/* ---------------------------------------------------------------------------
   Landing page (static_pages/_landing*)

   The page a visitor with no learning target sees at "/". The design and the
   reasoning behind it are in docs/design/landing_page.md; the
   rules that matter to this stylesheet:

   - Three accent colours carry one idea each, and the same three are used by
     the hero's prose, the annotations over the artwork and nothing else. They
     are declared once here so a change cannot land in one place only.
   - Sections are transparent and the cards inside them are white, rather than
     each section being a card: the layout already puts this page inside a
     container on a grey body, and banding every section reads as noise.
--------------------------------------------------------------------------- */
/* Outfit is the landing page's heading face and nothing else's. It is a
   display face: it earns its place on eight headings a stranger reads once,
   and would only slow down the pages a learner uses every day. The body text
   stays on the system stack, which costs nothing and matches the rest of the
   site. Every heading below is Latin-only, so the 32 KB latin subset covers
   the whole page. */
.landing-hero-title,
.landing-h2,
.landing-step-title,
.landing-tile-title,
.landing-price-title,
.landing-closer-title {
    font-family: 'Outfit', system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    letter-spacing: -0.015em;
}

.landing {
    --landing-person: var(--bs-primary);
    --landing-place: #b45309;
    --landing-part: #2e7d32;
    --landing-tint: #f4f1fb;
    --landing-card-shadow: 0 .25rem 1rem rgba(33, 37, 41, .07);
}

/* Hero ---------------------------------------------------------------- */
.landing-hero {
    padding: 1rem 0 2.5rem;
}

.landing-hero-title {
    font-weight: 700;
    font-size: clamp(2rem, 1.2rem + 2.6vw, 3.25rem);
    line-height: 1.12;
    text-wrap: balance;
    margin-bottom: 1rem;
}

.landing-hero-lead {
    font-size: 1.15rem;
    line-height: 1.6;
    color: var(--gray-700);
    max-width: 34rem;
    margin-bottom: 1.5rem;
}

.landing-key-person {
    color: var(--landing-person);
}

.landing-key-place {
    color: var(--landing-place);
}

.landing-key-part {
    color: var(--landing-part);
}

.landing-hero-trust {
    display: flex;
    align-items: center;
    gap: .5rem;
    color: var(--gray-600);
    font-size: .9375rem;
    margin-bottom: 0;
}

.landing-tick {
    color: var(--landing-part);
    flex-shrink: 0;
}

/* Hero artwork and its annotations ------------------------------------- */
.landing-figure {
    position: relative;
    margin: 0 0 1rem;
}

.landing-figure-frame {
    border-radius: 1rem;
    overflow: hidden;
    box-shadow: 0 .75rem 2.5rem rgba(33, 37, 41, .18);
}

.landing-figure-img {
    display: block;
    width: 100%;
    height: auto;
}

.landing-annotations {
    display: flex;
    flex-direction: column;
    gap: .5rem;
    margin: 1rem 0 0;
}

.landing-annotation {
    display: flex;
    align-items: baseline;
    gap: .5rem;
    font-size: .9375rem;
    line-height: 1.35;
}

.landing-annotation-dot {
    display: inline-block;
    width: .5625rem;
    height: .5625rem;
    border-radius: 50%;
    flex-shrink: 0;
    transform: translateY(-.0625rem);
}

.landing-annotation-dot--person {
    background: var(--landing-person);
}

.landing-annotation-dot--place {
    background: var(--landing-place);
}

.landing-annotation-dot--part {
    background: var(--landing-part);
}

/* Wide enough to lay the annotations over the artwork they point at. Below
   this they stay a plain legend under the image: at narrow widths the chips
   cover the drawing they are explaining. The offsets are hand-placed against
   app/assets/images/landing/de5_comic.webp and have to be redone if that
   image is ever replaced. */
@media (min-width: 992px) {
    .landing-annotations {
        position: absolute;
        inset: 0;
        display: block;
        margin: 0;
    }

    .landing-annotation {
        position: absolute;
        align-items: center;
        max-width: 62%;
        background: rgba(255, 255, 255, .95);
        border-radius: 2rem;
        padding: .3125rem .75rem;
        font-size: .8125rem;
        box-shadow: 0 .125rem .5rem rgba(0, 0, 0, .2);
    }

    .landing-annotation--person {
        top: 4%;
        left: 3%;
    }

    .landing-annotation--bai {
        top: 4%;
        right: 3%;
    }

    .landing-annotation--shao {
        top: 46%;
        left: 3%;
    }

    .landing-annotation--place {
        bottom: 4%;
        left: 50%;
        transform: translateX(-50%);
        max-width: 80%;
    }
}

/* 白 + 勺 = 的, under the artwork. */
.landing-equation {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: .625rem;
    background: var(--bs-body-bg, #fff);
    border: var(--border-width) solid var(--border-color);
    border-radius: .75rem;
    padding: .875rem 1.25rem;
    box-shadow: var(--landing-card-shadow);
}

.landing-equation-part {
    font-size: 1.75rem;
    font-weight: 600;
    color: var(--landing-part);
    line-height: 1;
}

.landing-equation-op {
    color: var(--gray-500);
}

.landing-equation-target {
    font-size: 2.25rem;
    font-weight: 700;
    color: var(--landing-person);
    line-height: 1;
}

.landing-equation-gloss {
    color: var(--gray-600);
    font-size: .9375rem;
}

/* Sections -------------------------------------------------------------- */
.landing-section {
    padding: 2.5rem 0;
}

.landing-section--tinted {
    background: var(--landing-tint);
    border-radius: 1rem;
    padding: 2.5rem 1.5rem;
    margin: 1rem 0;
}

.landing-section-head {
    text-align: center;
    max-width: 44rem;
    margin: 0 auto 2rem;
}

.landing-h2 {
    font-weight: 700;
    font-size: clamp(1.5rem, 1.1rem + 1.3vw, 2.125rem);
    margin-bottom: .75rem;
    text-wrap: balance;
}

.landing-section-sub,
.landing-body {
    color: var(--gray-700);
    line-height: 1.6;
    margin-bottom: 0;
}

.landing-body + .landing-body {
    margin-top: 1rem;
}

.landing-section-closer {
    text-align: center;
    color: var(--gray-700);
    margin: 2rem 0 0;
}

/* The three method steps ------------------------------------------------ */
.landing-step {
    height: 100%;
    background: var(--bs-body-bg, #fff);
    border-radius: 1rem;
    padding: 1.75rem;
    box-shadow: var(--landing-card-shadow);
}

.landing-step-head {
    display: flex;
    align-items: center;
    gap: .75rem;
    margin-bottom: .875rem;
}

.landing-step-number {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    flex-shrink: 0;
    border-radius: 50%;
    background: var(--bs-primary);
    color: #fff;
    font-weight: 700;
}

.landing-step-title {
    font-size: 1.1875rem;
    font-weight: 600;
    margin: 0;
}

.landing-step-body {
    color: var(--gray-700);
    line-height: 1.6;
    margin-bottom: 0;
}

/* Route preview --------------------------------------------------------- */
.landing-route-card {
    background: var(--bs-body-bg, #fff);
    border-radius: 1rem;
    padding: 1.75rem;
    box-shadow: var(--landing-card-shadow);
}

.landing-route-label {
    text-transform: uppercase;
    letter-spacing: .04em;
    font-size: .8125rem;
    font-weight: 600;
    color: var(--gray-600);
    margin-bottom: 1rem;
}

.landing-route-pills {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem;
}

/* Every pill in the real timeline is a link; here they illustrate one, and
   the only thing worth clicking on this page is the target picker. */
.landing-route-pill {
    cursor: default;
    pointer-events: none;
}

.landing-route-ellipsis {
    color: var(--gray-500);
    letter-spacing: .1em;
}

.landing-route-caption {
    color: var(--gray-700);
    font-size: .9375rem;
    line-height: 1.55;
    margin: 1rem 0 0;
}

.landing-route-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
    margin: 1rem 0 0;
    font-size: .8125rem;
    color: var(--gray-600);
}

.landing-route-legend li {
    display: flex;
    align-items: center;
    gap: .375rem;
}

.landing-legend-swatch {
    display: inline-block;
    width: .625rem;
    height: .625rem;
    border-radius: 50%;
}

.landing-legend-swatch--done {
    background: var(--bs-success, #198754);
}

.landing-legend-swatch--active {
    background: var(--bs-primary);
}

.landing-legend-swatch--ahead {
    border: var(--border-width) solid var(--gray-400);
}

/* Depth tiles ----------------------------------------------------------- */
.landing-tile {
    height: 100%;
    background: var(--bs-body-bg, #fff);
    border-radius: 1rem;
    padding: 1.5rem;
    box-shadow: var(--landing-card-shadow);
}

.landing-tile-icon {
    color: var(--bs-primary);
    margin-bottom: .75rem;
}

.landing-tile-title {
    font-size: 1.0625rem;
    font-weight: 600;
    margin-bottom: .5rem;
}

.landing-tile-body {
    color: var(--gray-700);
    font-size: .9375rem;
    line-height: 1.55;
    margin-bottom: 0;
}

/* Pricing --------------------------------------------------------------- */
.landing-price {
    height: 100%;
    border: var(--border-width) solid var(--border-color);
    border-radius: 1rem;
    padding: 1.75rem;
    background: var(--bs-body-bg, #fff);
}

.landing-price--paid {
    border: 2px solid var(--bs-primary);
    background: var(--landing-tint);
}

.landing-price-title {
    font-weight: 700;
    font-size: 1.3125rem;
    margin-bottom: .75rem;
}

.landing-price-body {
    color: var(--gray-700);
    line-height: 1.6;
    margin-bottom: 0;
}

/* Closing band ---------------------------------------------------------- */
.landing-closer {
    text-align: center;
    border-radius: 1rem;
    padding: 3rem 1.5rem;
    margin: 1rem 0 2rem;
    background: linear-gradient(180deg, var(--bs-primary) 0%, #47339e 100%);
    color: #fff;
}

.landing-closer-title {
    font-weight: 700;
    font-size: clamp(1.5rem, 1.1rem + 1.4vw, 2.25rem);
    margin-bottom: .75rem;
    text-wrap: balance;
}

.landing-closer-sub {
    color: rgba(255, 255, 255, .85);
    margin-bottom: 1.5rem;
}

.landing-closer-btn {
    background: #fff;
    color: var(--bs-primary);
}

.landing-closer-btn:hover,
.landing-closer-btn:focus {
    background: var(--gray-100);
    color: var(--bs-link-hover-color);
}
