/* ============================================================
   globalStyles.css
   ============================================================ */
/* Warm-minimalism design tokens — see the design guide in CLAUDE.md.
   Fonts (Inter + Playfair Display) are loaded via <link> in index.html rather
   than an @import here, so the browser fetches them in parallel with this
   stylesheet instead of discovering them only after parsing it. */
:root {
    --font-primary: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    --font-serif: 'Playfair Display', Georgia, serif;
    --fw-regular: 400;
    --fw-medium: 500;
    --fw-semibold: 600;
    --fw-bold: 700;

    --brand: #849C8A;        /* Faded sage — primary actions, trust badges */
    --brand-dark: #6F8875;   /* hover */
    --brand-darker: #5E7563; /* active */
    /* Inline text links: a darkened sage. Plain --brand (#849C8A) is on-brand
       but only ~2.3:1 on the oat bg — fails WCAG AA for body text. These pass
       AA (~4.8:1) while staying in the sage family. */
    --link: #4F6B58;
    --link-hover: #3E5646;
    --gold: #C6A664;         /* Champagne gold — STRICTLY premium upsells & B2B */
    --ink: #3A3A3A;          /* Deep taupe — softer than black */
    --muted: #6B675F;
    --surface: #FFFFFF;      /* card surfaces only — page bg stays oat */
    --surface-soft: #F4F1EC; /* warm section bands */
    --border-soft: #E6E2DD;  /* warm greige */

    /* Bootstrap 5 overrides */
    --bs-font-sans-serif: 'Inter', system-ui, -apple-system, sans-serif;
    --bs-body-bg: #FAF9F6;   /* oat / warm off-white */
    --bs-body-color: #3A3A3A;
    --bs-primary: #849C8A;
    --bs-primary-rgb: 132, 156, 138;
    --bs-secondary: #C6A664;
    --bs-secondary-rgb: 198, 166, 100;
    --bs-info: #E6E2DD;
    --bs-success: #6B8E6B;   /* moss green */
    --bs-danger: #C27A65;    /* dusty terracotta */
    --bs-border-color: #E6E2DD;
    --bs-border-radius: 0.5rem;
    /* Site-wide link color. Bootstrap builds <a> from the -rgb variants, so both
       forms are set. .btn / .nav-link / .dropdown-item define their own color and
       are unaffected. */
    --bs-link-color: #4F6B58;
    --bs-link-color-rgb: 79, 107, 88;
    --bs-link-hover-color: #3E5646;
    --bs-link-hover-color-rgb: 62, 86, 70;
}

/* Underline only on hover/focus — keeps body copy calm, but colour alone never
   has to carry the affordance once the pointer or keyboard lands on the link. */
a {
    text-decoration: none;
}

a:hover,
a:focus-visible {
    text-decoration: underline;
}

/* Component anchors (buttons, nav items, dropdown entries) signal affordance by
   shape/colour, so they must never pick up the hover underline above. */
.btn:hover,
.btn:focus-visible,
.nav-link:hover,
.nav-link:focus-visible,
.navbar-brand:hover,
.dropdown-item:hover,
.dropdown-item:focus-visible {
    text-decoration: none;
}

html {
    scroll-behavior: smooth;
}

body {
    min-height: 100vh;
    font-family: var(--font-primary);
    font-weight: var(--fw-regular);
    line-height: 1.6;
    color: var(--ink);
    background: var(--bs-body-bg);
}

p {
    margin-bottom: 1em;
}

/* Serif headings carry the bridal-boutique feel; smaller headings and UI text
   stay in Inter for legibility. */
h1,
h2,
h3,
.brand-font {
    font-family: var(--font-serif);
    font-weight: var(--fw-semibold);
    color: var(--ink);
}

h4,
h5,
h6,
strong {
    font-family: var(--font-primary);
}

strong {
    font-weight: var(--fw-bold);
}

h4,
h5,
h6 {
    font-weight: var(--fw-semibold);
}

.text-micro {
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    font-weight: var(--fw-semibold);
}

/* The footer carries `mt-auto`, which only does anything inside a flex column
   that is taller than its content — without this the footer simply sits under
   the last section and floats mid-viewport on short pages. */
.app-shell {
    display: flex;
    min-height: 100vh;
    flex-direction: column;
}

/* Takes the slack so mt-auto has something to push against. min-height:0 lets it
   shrink below its content instead of forcing the shell taller (a flex item's
   default min-height:auto would defeat the point). */
.app-shell > main {
    flex: 1 0 auto;
    min-height: 0;
}

main {
    padding-top: 72px;
}

.container {
    width: 100%;
    max-width: 1180px;
    margin-left: auto;
    margin-right: auto;
}

.text-brand {
    color: var(--brand) !important;
}

.btn-primary {
    --bs-btn-bg: var(--brand);
    --bs-btn-border-color: var(--brand);
    --bs-btn-hover-bg: var(--brand-dark);
    --bs-btn-hover-border-color: var(--brand-dark);
    --bs-btn-active-bg: var(--brand-darker);
    --bs-btn-active-border-color: var(--brand-darker);
}

.view {
    display: none;
    opacity: 0;
    transform: translateY(14px);
    transition: opacity 0.32s ease, transform 0.32s ease;
}

.view.active {
    display: block;
    opacity: 1;
    transform: translateY(0);
}

#landing {
    display: block;
}

.hero-section {
    min-height: calc(100vh - 72px);
    display: flex;
    align-items: center;
    padding: 5rem 0 4rem;
    background:
        radial-gradient(circle at 82% 18%, rgba(132, 156, 138, 0.14), transparent 28rem),
        linear-gradient(180deg, #F4F1EC 0%, #FAF9F6 74%);
}

.page-section {
    padding: 6rem 0;
}

.section-band {
    padding: 4rem 0;
    background: var(--surface-soft);
    border-top: 1px solid var(--border-soft);
    border-bottom: 1px solid var(--border-soft);
}

.eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    color: var(--brand);
    font-weight: var(--fw-semibold);
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
}

.wedding-card,
.feature-panel {
    background: var(--surface);
    border: 1px solid var(--border-soft);
    border-radius: 8px;
    padding: 1.5rem;
}

.feature-panel {
    padding: 2rem;
}

.metric-box {
    display: flex;
    min-height: 112px;
    flex-direction: column;
    justify-content: center;
    gap: 0.35rem;
    padding: 1rem;
    border-radius: 8px;
    background: var(--surface-soft);
    border: 1px solid var(--border-soft);
}

.metric-value {
    font-size: 1.35rem;
    font-weight: var(--fw-bold);
    color: var(--ink);
}

.metric-label {
    color: var(--muted);
    font-size: 0.92rem;
}

.check-list {
    display: grid;
    gap: 0.9rem;
}

.check-list div {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
}

/* Marketplace listing cards — image-focused, white on the oat page background.
   See the component rules in CLAUDE.md. */
.listing-card {
    background: var(--surface);
    border: 1px solid var(--border-soft);
    border-radius: var(--bs-border-radius);
    overflow: hidden;
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.listing-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(58, 58, 58, 0.08);
}

.listing-card .price {
    font-weight: var(--fw-semibold);
    font-size: 1.125rem;
    color: var(--ink);
}

/* Boosted listing (49 DKK upsell) — champagne gold is strictly reserved for
   paid visibility, never standard UI. */
.listing-card.is-boosted {
    border: 2px solid var(--gold);
    background: #FCFBF7; /* very slight golden tint */
}

.badge-premium {
    display: inline-flex;
    align-items: center;
    background-color: var(--gold);
    color: #FFFFFF;
    font-family: var(--font-primary);
    font-size: 0.75rem;
    font-weight: var(--fw-semibold);
    padding: 0.25rem 0.75rem;
    border-radius: 1rem;
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

/* B2B vendor ad — inverted dark card, explicitly labeled via .ad-label. */
.vendor-ad-card {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    padding: 1.5rem;
    border-radius: var(--bs-border-radius);
    background: var(--ink);
    color: #FFFFFF;
}

.vendor-ad-card h4 {
    color: #FFFFFF;
}

.vendor-ad-card .ad-label {
    color: var(--brand); /* sage pops against the dark taupe */
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
}

/* ---- Seller posting view (#sell) ---- */

/* Step indicator for each item's 3-step flow. Each step is a full pill with
   three distinct states — upcoming (muted), active (sage tint), and done (a
   checkmark replaces the number). Driven by goToStep() in the sell section of
   app.js, which toggles .is-active / .is-done. */
.sell-stepper {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0.5rem;
    margin-bottom: 1.6rem;
}

.sell-step-dot {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    min-width: 0;
    min-height: 46px;
    padding: 0.55rem 0.85rem;
    background: var(--surface-soft);
    border: 1px solid var(--border-soft);
    border-radius: 999px;
    color: var(--muted);
    font: inherit;
    cursor: pointer;
    transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}

.sell-step-dot:hover {
    border-color: rgba(132, 156, 138, 0.45);
    color: var(--ink);
}

.sell-step-num {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: #fff;
    border: 1px solid var(--border-soft);
    font-size: 0.74rem;
    font-weight: var(--fw-semibold);
    transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}

.sell-step-name {
    overflow: hidden;
    font-size: 0.85rem;
    font-weight: var(--fw-semibold);
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Active — sage-tinted pill with a solid brand number badge. */
.sell-step-dot.is-active {
    background: rgba(132, 156, 138, 0.14);
    border-color: rgba(132, 156, 138, 0.5);
    color: var(--ink);
}

.sell-step-dot.is-active .sell-step-num {
    background: var(--brand);
    border-color: var(--brand);
    color: #fff;
}

/* Done — softer sage pill; the number badge becomes a checkmark. */
.sell-step-dot.is-done {
    background: rgba(132, 156, 138, 0.07);
    border-color: rgba(132, 156, 138, 0.35);
    color: var(--brand);
}

.sell-step-dot.is-done .sell-step-num {
    background: var(--brand);
    border-color: var(--brand);
    color: #fff;
    font-size: 0; /* hide the digit so only the check shows */
}

.sell-step-dot.is-done .sell-step-num::before {
    content: "\f00c";
    font-family: "Font Awesome 6 Free";
    font-weight: 900;
    font-size: 0.68rem;
}

.sell-step-dot:focus-visible {
    outline: none;
    border-color: var(--brand);
    box-shadow: 0 0 0 3px rgba(132, 156, 138, 0.24);
}

/* Back / Næste row under the active step. */
.sell-step-nav {
    display: flex;
    align-items: center;
    margin-top: 1.4rem;
    padding-top: 1rem;
    border-top: 1px solid var(--border-soft);
}

.sell-step.is-entering-forward {
    animation: sell-step-enter-forward 0.24s ease-out both;
}

.sell-step.is-entering-back {
    animation: sell-step-enter-back 0.24s ease-out both;
}

@keyframes sell-step-enter-forward {
    from {
        opacity: 0;
        transform: translateX(12px);
    }
}

@keyframes sell-step-enter-back {
    from {
        opacity: 0;
        transform: translateX(-12px);
    }
}

/* On narrow phones the step names would crowd the pills — keep just the numbers. */
@media (max-width: 400px) {
    .sell-step-name {
        display: none;
    }
}

/* Category picker — an icon-tile radio grid instead of a long dropdown. The
   selected value lives on a hidden input; see renderCategoryPicker() in app.js. */
.category-picker {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
    gap: 0.6rem;
}

.category-tile {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    min-height: 94px;
    padding: 0.85rem 0.5rem;
    text-align: center;
    color: var(--muted);
    background: var(--surface);
    border: 1px solid var(--border-soft);
    border-radius: var(--bs-border-radius);
    cursor: pointer;
    transition: border-color 0.15s ease, background 0.15s ease, color 0.15s ease, transform 0.15s ease;
}

.category-tile i {
    font-size: 1.5rem;
    color: var(--brand);
}

.category-tile span {
    font-size: 0.75rem;
    font-weight: var(--fw-medium);
    line-height: 1.2;
}

.category-tile:hover {
    border-color: var(--brand);
    color: var(--ink);
    transform: translateY(-1px);
}

.category-tile.is-selected {
    border-color: var(--brand);
    background: rgba(132, 156, 138, 0.1);
    color: var(--ink);
    box-shadow: 0 0 0 1px var(--brand);
}

.category-tile:focus-visible {
    outline: none;
    border-color: var(--brand);
    box-shadow: 0 0 0 3px rgba(132, 156, 138, 0.28);
}

/* Each item the seller is drafting. Turns green when published, terracotta on a
   failed publish — see setSellItemStatus() in the sell section of app.js. */
.sell-item-card {
    transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.sell-item-card.is-done {
    border-color: var(--bs-success);
    box-shadow: 0 0 0 1px var(--bs-success);
}

.sell-item-card.is-error {
    border-color: var(--bs-danger);
    box-shadow: 0 0 0 1px var(--bs-danger);
}

.sell-item-status {
    font-size: 0.72rem;
    font-weight: var(--fw-semibold);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 0.2rem 0.6rem;
    border-radius: 1rem;
}

.sell-item-status--uploading {
    color: var(--muted);
    background: var(--surface-soft);
}

.sell-item-status--done {
    color: #40613F;
    background: rgba(107, 142, 107, 0.16);
}

.sell-item-status--error {
    color: var(--bs-danger);
    background: rgba(194, 122, 101, 0.14);
}

/* Image drop target. Dashed greige frame that warms to sage on hover/drag. */
.image-dropzone {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1.75rem 1rem;
    text-align: center;
    color: var(--muted);
    border: 2px dashed var(--border-soft);
    border-radius: var(--bs-border-radius);
    background: var(--surface-soft);
    cursor: pointer;
    transition: border-color 0.2s ease, background 0.2s ease, color 0.2s ease;
}

.image-dropzone:hover,
.image-dropzone:focus-visible,
.image-dropzone.is-dragover {
    border-color: var(--brand);
    background: rgba(132, 156, 138, 0.08);
    color: var(--ink);
    outline: none;
}

.image-dropzone__prompt i {
    color: var(--brand);
}

/* Thumbnail grid of chosen images. Auto-fills so it reflows from 1 up to 8. */
.image-thumbs {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
    gap: 0.6rem;
}

.image-thumbs:empty {
    display: none;
}

.image-thumb {
    position: relative;
    aspect-ratio: 1;
    border-radius: 0.4rem;
    overflow: hidden;
    border: 1px solid var(--border-soft);
    background: var(--surface-soft);
}

.image-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.image-thumb__remove {
    position: absolute;
    top: 4px;
    right: 4px;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    padding: 0;
    color: #fff;
    border: none;
    border-radius: 50%;
    background: rgba(58, 58, 58, 0.62);
    cursor: pointer;
    transition: background 0.15s ease;
}

.image-thumb__remove:hover {
    background: var(--bs-danger);
}

/* Boost upsell — the one place gold is allowed, framed in a soft champagne tint. */
.sell-boost {
    padding: 0.85rem 1rem;
    border: 1px solid rgba(198, 166, 100, 0.4);
    border-radius: var(--bs-border-radius);
    background: rgba(198, 166, 100, 0.07);
}

.sell-boost .form-check-input:checked {
    background-color: var(--gold);
    border-color: var(--gold);
}

/* Publish bar — sticks to the bottom of the viewport on tall forms so the
   primary action is always reachable without scrolling to the end. */
.sell-submit-bar {
    position: sticky;
    bottom: 0;
    z-index: 5;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 1rem;
    flex-wrap: wrap;
    padding: 1rem 0;
    background: linear-gradient(to top, var(--bs-body-bg) 72%, transparent);
}

/* Favorite buttons — see wedding/favorites.js. renderFavoriteState() adds
   .active and swaps the icon between outline and filled. */
[data-favorite-id] {
    transition: color 0.2s ease, border-color 0.2s ease;
}

[data-favorite-id].active {
    color: var(--bs-danger);
    border-color: currentColor;
}

@media (prefers-reduced-motion: reduce) {
    .sell-step.is-entering-forward,
    .sell-step.is-entering-back,
    [data-favorite-id] {
        animation: none;
        transition: none;
    }
}

/* Password field in the login modal. Collapsed until the user opts into password
   login — see setLoginMode() in login.js. overflow stays hidden while collapsed
   so the field can't be tabbed into, and becomes visible when open so focus
   rings and password-manager popovers aren't clipped. */
.login-password-collapse {
    max-height: 0;
    opacity: 0;
    overflow: hidden;
    transition: max-height 0.3s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.3s ease;
}

.login-password-collapse.open {
    max-height: 220px;
    opacity: 1;
    overflow: visible;
}

/* Eye toggle appended to password inputs by setupPasswordVisibilityToggles(). */
.toggle-password {
    cursor: pointer;
    background: var(--surface);
    color: var(--muted);
}

.toggle-password:hover {
    color: var(--ink);
}

/* In-app-browser notice in the login modal, shown where Google blocks OAuth. */
.in-app-notice {
    display: flex;
    gap: 0.875rem;
    align-items: flex-start;
    padding: 1rem;
    border: 1px solid rgba(132, 156, 138, 0.35);
    border-radius: 12px;
    background: rgba(132, 156, 138, 0.08);
}

.in-app-notice__icon {
    display: flex;
    width: 38px;
    height: 38px;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: var(--brand);
    color: white;
}

@media (prefers-reduced-motion: reduce) {
    .login-password-collapse {
        transition: none;
    }
}

/* Cookie consent — see setupCookieConsent() in utils.js. Sits above the navbar
   but below modals, so a modal opened from the banner still covers it. */
#cookie-consent-banner {
    z-index: 1050;
    padding-bottom: max(1rem, env(safe-area-inset-bottom));
    animation: cookie-slide-up 0.32s ease-out;
}

.cookie-consent-card {
    display: flex;
    max-width: 900px;
    margin: 0 auto;
    flex-direction: column;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1.25rem;
    padding: 1.25rem;
    border: 1px solid var(--border-soft);
    border-radius: 12px;
    background: var(--surface);
    box-shadow: 0 12px 32px rgba(58, 58, 58, 0.14);
}

.cookie-consent-card__icon {
    display: flex;
    width: 48px;
    height: 48px;
    flex-shrink: 0;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(132, 156, 138, 0.15);
    color: var(--brand);
    font-size: 1.25rem;
}

@media (min-width: 992px) {
    .cookie-consent-card {
        flex-direction: row;
        align-items: center;
    }
}

@keyframes cookie-slide-up {
    from {
        opacity: 0;
        transform: translateY(16px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

@media (prefers-reduced-motion: reduce) {
    #cookie-consent-banner {
        animation: none;
    }
}

/* Dev-environment password gate — see requireDevAccessGate() in utils.js. Sits
   above the app loader, since it must gate whatever is behind it. */
#dev-access-gate {
    z-index: 4000;
    background: rgba(250, 249, 246, 0.96);
    backdrop-filter: blur(10px);
}

/* Circular accent icon used at the top of modals and gate screens
   (password nudge, dev access gate). */
.modal-icon-circle {
    display: inline-flex;
    width: 56px;
    height: 56px;
    align-items: center;
    justify-content: center;
    margin-bottom: 1rem;
    border-radius: 50%;
    background: rgba(132, 156, 138, 0.15);
    color: var(--brand);
    font-size: 1.25rem;
}

/* Covers the shell until the SPA has booted. Starts fully transparent: an inline
   script in index.html only reveals it once boot has taken longer than 200ms, so
   a fast load never flashes a spinner. See removeAppLoader() in main.js. */
#app-loader {
    position: fixed;
    inset: 0;
    z-index: 3000;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--surface-soft);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.4s ease-out;
}

#app-loader.show-loader {
    opacity: 1;
    pointer-events: auto;
}

/* Toast notifications — a floating centered capsule under the top edge, ported
   from Andelsbolig Basen (toast/toast.css). Sits above modals (backdrop 1050,
   dialog 1055) so feedback fired from inside a modal is never hidden by it.
   show/hide is display-based (showToast in utils.js); re-showing restarts the
   entry animation because the element re-enters the render tree. */
.toast-capsule {
    position: fixed;
    top: 30px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 9999;
    min-width: 380px;
    max-width: 90vw;
    border-radius: 16px;
    background: rgba(255, 255, 255, 0.98);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    box-shadow:
        0 10px 40px -10px rgba(0, 0, 0, 0.08),
        0 0 0 1px rgba(0, 0, 0, 0.03);
    cursor: pointer;
    animation: toast-slide-down 0.5s cubic-bezier(0.4, 0, 0.2, 1);
}

.toast-capsule--success {
    border-left: 6px solid var(--bs-success);
}

.toast-capsule--error {
    border-left: 6px solid var(--bs-danger);
}

.toast-capsule > .d-flex {
    padding: 1rem 1.5rem;
}

.toast-animation {
    display: block;
    width: 42px;
    height: 42px;
}

.toast-animation svg {
    display: block;
    width: 100%;
    height: 100%;
}

#success-message,
#error-message {
    color: var(--ink);
    font-weight: var(--fw-medium);
    font-size: 1.05rem;
    line-height: 1.5;
}

.toast-capsule .btn-close {
    margin-left: 1rem;
    opacity: 0.3;
    box-shadow: none;
    transition: opacity 0.2s ease, transform 0.2s ease;
}

.toast-capsule .btn-close:hover {
    opacity: 1;
    transform: scale(1.1);
}

/* Exit: showToast adds .fade-out, then hides once this transition has played. */
.toast-capsule.fade-out {
    opacity: 0;
    transform: translate(-50%, -40px) scale(0.95);
    transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}

@keyframes toast-slide-down {
    from {
        opacity: 0;
        transform: translate(-50%, -40px) scale(0.95);
    }
    to {
        opacity: 1;
        transform: translate(-50%, 0) scale(1);
    }
}

/* min-width beats max-width in CSS, so on narrow phones the 380px minimum would
   overflow the viewport — cap it to the screen instead. */
@media (max-width: 480px) {
    .toast-capsule {
        min-width: 0;
        width: calc(100vw - 2rem);
    }
}

@media (prefers-reduced-motion: reduce) {
    .toast-capsule {
        animation: none;
    }

    .toast-capsule.fade-out {
        transition: opacity 0.2s ease;
        transform: translateX(-50%);
    }
}

.site-footer {
    padding: 2rem 0;
    background: var(--ink);
    color: #D9D5D0;
}

.site-footer a {
    color: #D9D5D0;
    text-decoration: none;
}

.site-footer a:hover {
    color: white;
}

.hover-shadow {
    transition: box-shadow 0.24s ease, transform 0.24s ease;
}

.hover-shadow:hover,
.hover-shadow:focus-within {
    transform: translateY(-2px);
    box-shadow: 0 12px 24px rgba(58, 58, 58, 0.08) !important;
}

@media (max-width: 576px) {
    .container {
        padding-left: 1rem;
        padding-right: 1rem;
    }

    .hero-section,
    .page-section {
        padding: 4rem 0 3rem;
    }
}

/* ============================================================
   pages/landingpage/landingpage.css
   ============================================================ */
.hero-section .lead {
    max-width: 680px;
}

.wedding-card h2 {
    color: var(--ink);
}

/* ============================================================
   pages/header_and_footer/header_and_footer.css
   ============================================================ */
.navbar {
    min-height: 72px;
}

.navbar-brand {
    color: var(--ink);
}

.brand-mark {
    display: inline-flex;
    width: 36px;
    height: 36px;
    align-items: center;
    justify-content: center;
    border-radius: 8px;
    background: var(--brand);
    color: white;
    font-size: 0.85rem;
    font-weight: var(--fw-bold);
}

.nav-link {
    color: var(--muted);
    font-weight: var(--fw-medium);
}

.nav-link:hover,
.nav-link.active {
    color: var(--brand) !important;
}

/* ============================================================
   pages/about/about.css
   ============================================================ */
#about .lead {
    max-width: 760px;
}

/* ============================================================
   pages/example/example.css
   ============================================================ */
#example-name {
    overflow-wrap: anywhere;
}

