/* Pozivnica - Eventspark-derived theme (light default, dark via [data-theme="dark"]) */

/* ==========================================
   CSS Variables (Design Tokens)
   ========================================== */
:root {
    color-scheme: light;

    /* Colors - light theme (default) */
    --bg-base: #FAFAFA;
    --bg-elevated: #FFFFFF;
    --bg-highlight: #EEEEF1;
    --bg-press: #E2E2E7;
    --bg-card: #FFFFFF;
    --bg-card-hover: #F4F4F6;

    --text-base: #19192E;
    --text-subdued: #6F6F7B;
    --text-secondary: #45455A;
    --text-disabled: #A0A0AC;

    --accent-primary: #E44479;
    --accent-primary-hover: #DF2060;
    --accent-secondary: #19192E;

    --essential-negative: #EF4343;
    --essential-warning: #E8A530;
    --essential-positive: #33998B;

    --border-color: #E8E8E8;
    --border-color-light: #D6D6D6;

    /* Shadows - light theme (default) */
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
    --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1);
    --shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1);
    --shadow-card: 0 10px 15px rgba(0, 0, 0, 0.1);

    /* Typography */
    --font-primary: 'DM Sans', -apple-system, BlinkMacSystemFont, sans-serif;
    --font-secondary: 'DM Sans', -apple-system, BlinkMacSystemFont, sans-serif;
    --font-display: 'Bricolage Grotesque', -apple-system, BlinkMacSystemFont, sans-serif;

    /* Spacing */
    --spacing-xs: 4px;
    --spacing-sm: 8px;
    --spacing-md: 16px;
    --spacing-lg: 24px;
    --spacing-xl: 32px;
    --spacing-2xl: 48px;
    --spacing-3xl: 64px;

    /* Border Radius */
    --radius-sm: 4px;
    --radius-md: 6px;
    --radius-lg: 8px;
    --radius-xl: 12px;
    --radius-full: 9999px;

    /* Transitions - signature easing curve applied everywhere */
    --transition-fast: 200ms cubic-bezier(0.22, 1, 0.36, 1);
    --transition-base: 400ms cubic-bezier(0.22, 1, 0.36, 1);
    --transition-slow: 700ms cubic-bezier(0.22, 1, 0.36, 1);

    /* Layout */
    --sidebar-width: 280px;
    --header-height: 64px;
    --mobile-nav-height: 64px;
    --content-max-width: 1400px;
}

/* Dark theme - opted into via <html data-theme="dark">, set from the
   "theme" cookie (see getTheme() in internal/server/htmx_helpers.go).
   Light (:root above) is the default for logged-out/first-visit users.
   --accent-primary/--accent-primary-hover/--accent-secondary are NOT
   overridden here - the brand pink stays fixed across themes, matching
   the style guide's explicit "primary/ring stay fixed" principle.
   --essential-warning/--essential-positive/--shadow-* are also not
   overridden - the guide's own dark block never varies them either, so
   they're now theme-invariant (a real behavior change from before, when
   this app varied almost everything between themes). */
[data-theme="dark"] {
    color-scheme: dark;

    --bg-base: #0F0F1A;
    --bg-elevated: #151523;
    --bg-highlight: #272735;
    --bg-press: #1A1A28;
    --bg-card: #151523;
    --bg-card-hover: #272735;

    --text-base: #F2F2F3;
    --text-subdued: #878792;
    --text-secondary: #B8B8C0;
    --text-disabled: #4A4A5A;

    --essential-negative: #7C1D1D;

    --border-color: #2B2B3B;
    --border-color-light: #3D3D4F;
}

/* ==========================================
   Reset & Base Styles
   ========================================== */
*, *::before, *::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

html {
    font-size: 16px;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* Smooth hash-link scrolling is a compositor tax on phones (and
   ignored under prefers-reduced-motion). Desktop-only. */
@media (prefers-reduced-motion: no-preference) and (hover: hover) and (pointer: fine) {
    html {
        scroll-behavior: smooth;
    }
}

body {
    font-family: var(--font-primary);
    background-color: var(--bg-base);
    color: var(--text-base);
    line-height: 1.5;
    min-height: 100vh;
    min-height: 100dvh;
    overflow-x: hidden;
}

a {
    color: inherit;
    text-decoration: none;
}

button {
    font-family: inherit;
    cursor: pointer;
    border: none;
    background: none;
}

input, textarea, select {
    font-family: inherit;
    font-size: inherit;
}

img, svg {
    display: block;
    max-width: 100%;
}

ul, ol {
    list-style: none;
}

[hidden] {
    display: none !important;
}

/* ==========================================
   Typography
   ========================================== */
h1, h2, h3, h4, h5, h6 {
    font-family: var(--font-display);
    font-weight: 700;
    line-height: 1.2;
    letter-spacing: -0.02em;
}

h1 { font-size: 2.5rem; }
h2 { font-size: 1.75rem; }
h3 { font-size: 1.25rem; }
h4 { font-size: 1rem; }

.text-sm { font-size: 0.875rem; }
.text-xs { font-size: 0.75rem; }
.text-subdued { color: var(--text-subdued); }

/* ==========================================
   App Layout
   ========================================== */
.app-container {
    display: flex;
    min-height: 100vh;
    min-height: 100dvh;
}

.main-content {
    flex: 1;
    min-width: 0;
    margin-left: var(--sidebar-width);
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    min-height: 100dvh;
    padding-bottom: var(--mobile-nav-height);
}

.content-area {
    flex: 1;
    min-width: 0;
    padding: var(--spacing-lg);
    max-width: var(--content-max-width);
    width: 100%;
    margin: 0 auto;
}

@media (max-width: 1024px) {
    .main-content {
        margin-left: 0;
    }
}

/* ==========================================
   Sidebar
   ========================================== */
.sidebar {
    width: var(--sidebar-width);
    height: 100vh;
    height: 100dvh;
    position: fixed;
    left: 0;
    top: 0;
    background: var(--bg-base);
    border-right: 1px solid var(--border-color);
    display: flex;
    flex-direction: column;
    /* Above .mobile-nav (also z-index 100) - as an off-canvas drawer on
       mobile, the sidebar needs to sit in front of the fixed bottom nav
       bar, not tie with it and lose on DOM order. */
    z-index: 150;
    transition: transform var(--transition-slow);
}

.sidebar-header {
    padding: var(--spacing-lg);
    border-bottom: 1px solid var(--border-color);
}

.sidebar-logo {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
}

.logo-icon {
    width: 32px;
    height: 32px;
    fill: var(--accent-primary);
}

.logo-text {
    font-size: 1.25rem;
    font-weight: 700;
    font-family: var(--font-secondary);
}

.sidebar-nav {
    flex: 1;
    padding: var(--spacing-md);
    overflow-y: auto;
}

.nav-list {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-xs);
}

.nav-link {
    display: flex;
    align-items: center;
    gap: var(--spacing-md);
    padding: var(--spacing-sm) var(--spacing-md);
    border-radius: var(--radius-md);
    color: var(--text-subdued);
    font-weight: 500;
    transition: all var(--transition-fast);
}

.nav-link:hover {
    color: var(--text-base);
    background: var(--bg-highlight);
}

.nav-link.active {
    color: var(--text-base);
    background: var(--bg-highlight);
}

/* Same look as .nav-link but reset for a <button> (inside the logout
   <form>) instead of an <a> - buttons don't inherit font/width/cursor
   the way anchors do. */
.nav-link-btn {
    display: flex;
    align-items: center;
    gap: var(--spacing-md);
    width: 100%;
    padding: var(--spacing-sm) var(--spacing-md);
    border: none;
    border-radius: var(--radius-md);
    background: none;
    color: var(--text-subdued);
    font-family: inherit;
    font-size: 1rem;
    font-weight: 500;
    text-align: left;
    cursor: pointer;
    transition: all var(--transition-fast);
}

.nav-link-btn:hover {
    color: var(--text-base);
    background: var(--bg-highlight);
}

.nav-icon {
    width: 24px;
    height: 24px;
    flex-shrink: 0;
}

.nav-divider {
    height: 1px;
    background: var(--border-color);
    margin: var(--spacing-md) 0;
}

.nav-section-title {
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--text-subdued);
    padding: var(--spacing-sm) var(--spacing-md);
}

.sidebar-footer {
    position: relative;
    padding: var(--spacing-md);
    border-top: 1px solid var(--border-color);
}

.user-menu {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    padding: var(--spacing-sm);
    cursor: pointer;
    border-radius: var(--radius-md);
    transition: background var(--transition-fast);
}

.user-menu:hover {
    background: var(--bg-highlight);
}

.user-avatar {
    width: 32px;
    height: 32px;
    border-radius: var(--radius-full);
    overflow: hidden;
    background: var(--bg-highlight);
    display: flex;
    align-items: center;
    justify-content: center;
}

.user-avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.avatar-initials {
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--text-base);
}

.avatar-initials.small {
    font-size: 0.625rem;
}

.user-info {
    flex: 1;
    min-width: 0;
}

.user-name {
    display: block;
    font-size: 0.875rem;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.user-email {
    display: block;
    font-size: 0.75rem;
    color: var(--text-subdued);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.user-menu-btn {
    width: 24px;
    height: 24px;
    color: var(--text-subdued);
    transition: color var(--transition-fast);
}

.user-menu-btn:hover {
    color: var(--text-base);
}

.user-menu-btn svg {
    width: 100%;
    height: 100%;
}

.user-dropdown {
    display: none;
    position: absolute;
    bottom: 100%;
    left: var(--spacing-md);
    right: var(--spacing-md);
    background: var(--bg-elevated);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    padding: var(--spacing-xs);
    margin-bottom: var(--spacing-sm);
    box-shadow: var(--shadow-lg);
}

.user-dropdown.active {
    display: block;
}

.dropdown-item {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    padding: var(--spacing-sm) var(--spacing-md);
    border-radius: var(--radius-sm);
    color: var(--text-subdued);
    font-size: 0.875rem;
    transition: all var(--transition-fast);
    width: 100%;
    text-align: left;
}

.dropdown-item:hover {
    background: var(--bg-highlight);
    color: var(--text-base);
}

.dropdown-item svg {
    width: 18px;
    height: 18px;
}

.logout-form {
    display: contents;
}

@media (max-width: 1024px) {
    .sidebar {
        transform: translateX(-100%);
    }
    
    .sidebar.open {
        transform: translateX(0);
    }
}

/* ==========================================
   Header
   ========================================== */
.main-header {
    height: var(--header-height);
    padding: 0 var(--spacing-lg);
    display: flex;
    align-items: center;
    justify-content: space-between;
    background: var(--bg-base);
    position: sticky;
    top: 0;
    z-index: 50;
}

.header-left {
    display: flex;
    align-items: center;
    gap: var(--spacing-md);
}

.nav-toggle {
    display: none;
    width: 40px;
    height: 40px;
    align-items: center;
    justify-content: center;
    color: var(--text-base);
}

.nav-toggle svg {
    width: 24px;
    height: 24px;
}

@media (max-width: 1024px) {
    .nav-toggle {
        display: flex;
    }
}

.lang-switch {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-xs);
    height: 32px;
    padding: 0 var(--spacing-sm);
    border-radius: var(--radius-full);
    background: var(--bg-press);
    color: var(--text-subdued);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    transition: all var(--transition-fast);
}

.lang-switch:hover {
    color: var(--text-base);
    transform: scale(1.05);
}

.lang-switch-icon {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
}

.landing-nav-actions .lang-switch {
    margin-right: var(--spacing-sm);
}

.sidebar-switches {
    display: flex;
    justify-content: center;
    gap: var(--spacing-sm);
    padding: var(--spacing-sm) var(--spacing-md);
}

.theme-switch {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-xs);
    height: 32px;
    padding: 0 var(--spacing-sm);
    border-radius: var(--radius-full);
    background: var(--bg-press);
    color: var(--text-subdued);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    transition: all var(--transition-fast);
}

.theme-switch:hover {
    color: var(--text-base);
    transform: scale(1.05);
}

.theme-switch-icon {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
}

.header-center {
    flex: 1;
    max-width: 400px;
    margin: 0 var(--spacing-lg);
}

.search-form {
    position: relative;
}

.admin-search-form {
    max-width: 400px;
    margin-bottom: var(--spacing-lg);
}

.search-icon {
    position: absolute;
    left: var(--spacing-md);
    top: 50%;
    transform: translateY(-50%);
    width: 20px;
    height: 20px;
    color: var(--text-subdued);
}

.search-input {
    width: 100%;
    height: 40px;
    padding: 0 var(--spacing-md) 0 44px;
    background: var(--bg-highlight);
    border: none;
    border-radius: var(--radius-full);
    color: var(--text-base);
    font-size: 0.875rem;
    transition: all var(--transition-fast);
}

.search-input:focus {
    background: var(--bg-card-hover);
}

.search-input::placeholder {
    color: var(--text-subdued);
}

.header-right {
    display: flex;
    align-items: center;
    gap: var(--spacing-md);
}

.header-user {
    position: relative;
    cursor: pointer;
}

.header-avatar {
    width: 36px;
    height: 36px;
    border-radius: var(--radius-full);
    overflow: hidden;
    background: var(--bg-highlight);
    display: flex;
    align-items: center;
    justify-content: center;
}

/* .user-dropdown's base rule opens upward (bottom:100%) and stretches
   full-width, which suits the sidebar footer it was built for - flip it
   to open downward from the header avatar and anchor to its right edge
   instead of stretching across the header. */
.header-user .user-dropdown {
    top: 100%;
    bottom: auto;
    left: auto;
    right: 0;
    width: 220px;
    margin-top: var(--spacing-sm);
    margin-bottom: 0;
}

.header-auth-buttons {
    display: flex;
    gap: var(--spacing-sm);
}

@media (max-width: 768px) {
    .header-center {
        display: none;
    }
}

/* ==========================================
   Mobile Navigation
   ========================================== */
.mobile-nav {
    display: none;
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    height: var(--mobile-nav-height);
    background: var(--bg-base);
    border-top: 1px solid var(--border-color);
    z-index: 100;
}

@media (max-width: 1024px) {
    .mobile-nav {
        display: flex;
        justify-content: space-around;
        align-items: center;
    }
}

.mobile-nav-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--spacing-xs);
    padding: var(--spacing-sm);
    color: var(--text-subdued);
    font-size: 0.625rem;
    font-weight: 500;
    transition: color var(--transition-fast);
}

.mobile-nav-item:hover,
.mobile-nav-item.active {
    color: var(--text-base);
}

.mobile-nav-item svg {
    width: 24px;
    height: 24px;
}

/* ==========================================
   Buttons
   ========================================== */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--spacing-sm);
    padding: var(--spacing-sm) var(--spacing-lg);
    border-radius: var(--radius-full);
    font-size: 0.875rem;
    font-weight: 600;
    transition: all var(--transition-fast);
    white-space: nowrap;
    position: relative;
    overflow: hidden;
}

.btn svg {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
}

.btn:disabled {
    opacity: 0.6;
    cursor: not-allowed;
    transform: none;
}

.btn:hover:not(:disabled) {
    transform: translateY(-1px);
}

.btn:active:not(:disabled) {
    transform: scale(0.97);
}

.btn-primary {
    background: var(--accent-primary);
    color: #fff;
}

.btn-primary:hover {
    background: var(--accent-primary-hover);
}

.btn-ghost {
    background: transparent;
    color: var(--text-base);
}

.btn-ghost:hover {
    background: var(--bg-highlight);
}

.btn-outline {
    background: transparent;
    color: var(--text-base);
    border: 1px solid var(--border-color-light);
}

.btn-outline:hover {
    background: var(--bg-highlight);
    border-color: var(--text-base);
}

.btn-danger,
.btn-ghost.btn-danger,
.btn-outline.btn-danger {
    background: transparent;
    color: var(--essential-negative);
}

.btn-danger:hover,
.btn-ghost.btn-danger:hover,
.btn-outline.btn-danger:hover {
    background: var(--essential-negative);
    color: var(--text-base);
}

.btn-lg {
    padding: var(--spacing-md) var(--spacing-xl);
    font-size: 1rem;
}

.btn-sm {
    padding: var(--spacing-xs) var(--spacing-md);
    font-size: 0.75rem;
}

.btn-block {
    width: 100%;
}

/* .btn-icon marks an icon-only button (e.g. a remove "X"), sizing the
   button itself - not just its svg. .btn's own padding (8px 24px) is
   meant for pill-shaped label buttons; left in place here it consumes
   the entire 18px box under border-box sizing, leaving 0 content width
   for the icon, so it silently disappears while the button stays
   clickable. Zero the padding and size the square to fit the icon plus
   a comfortable tap target, matching .modal-close's convention. */
.btn-icon {
    width: 32px;
    height: 32px;
    padding: 0;
}

.btn-icon-right {
    width: 18px;
    height: 18px;
    margin-left: var(--spacing-xs);
}

.btn-spinner {
    display: none;
}

.htmx-request .btn-text {
    opacity: 0;
}

.htmx-request .btn-spinner {
    display: block;
    position: absolute;
}

.btn-oauth {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--spacing-sm);
    width: 100%;
    padding: var(--spacing-md);
    background: var(--bg-highlight);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    color: var(--text-base);
    font-weight: 500;
    transition: all var(--transition-fast);
}

.btn-oauth:hover {
    background: var(--bg-card-hover);
}

.oauth-icon {
    width: 20px;
    height: 20px;
}

/* ==========================================
   Forms
   ========================================== */
.form-group {
    min-width: 0;
    margin-bottom: var(--spacing-lg);
}

.form-group label {
    display: block;
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--text-base);
    margin-bottom: var(--spacing-sm);
}

.form-group input[type="text"],
.form-group input[type="email"],
.form-group input[type="password"],
.form-group input[type="tel"],
.form-group input[type="search"],
.form-group input[type="date"],
.form-group input[type="datetime-local"],
.form-group textarea,
.form-group select {
    width: 100%;
    min-width: 0;
    max-width: 100%;
    padding: var(--spacing-md);
    background: var(--bg-highlight);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    color: var(--text-base);
    font-size: 1rem;
    transition: all var(--transition-fast);
}

/* Safari renders date/time inputs with its own native text-field chrome
   (extra reserved padding, a differently-sized control) instead of
   respecting the same box model our other inputs use, making them
   visibly bigger than the rest of the form both horizontally and
   vertically. Stripping the native appearance forces Safari to lay it
   out using only our own CSS, same as every other input. */
.form-group input[type="date"],
.form-group input[type="datetime-local"] {
    -webkit-appearance: none;
    appearance: none;
    padding-top: var(--spacing-sm);
    padding-bottom: var(--spacing-sm);
}

.form-group input:focus,
.form-group textarea:focus,
.form-group select:focus {
    outline: none;
    border-color: var(--accent-primary);
}

/* Global keyboard-focus ring - two layers (page-bg gap + accent ring) so
   it reads clearly against any background. Scoped ancestor override below
   re-tints this to each invitation's own highlight color on the public
   RSVP page, instead of leaking the fixed brand pink onto a couple's own
   color scheme. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible {
    outline: none;
    box-shadow: 0 0 0 2px var(--bg-base), 0 0 0 4px var(--accent-primary);
}

.invitation-body a:focus-visible,
.invitation-body button:focus-visible,
.invitation-body input:focus-visible,
.invitation-body textarea:focus-visible,
.invitation-body select:focus-visible {
    outline: none;
    box-shadow: 0 0 0 2px var(--invitation-bg, var(--bg-base)),
                0 0 0 4px var(--invitation-highlight, var(--accent-primary));
}

.form-group input::placeholder,
.form-group textarea::placeholder {
    color: var(--text-subdued);
}

.form-hint {
    display: block;
    font-size: 0.75rem;
    color: var(--text-subdued);
    margin-top: var(--spacing-xs);
}

.form-row {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: var(--spacing-md);
}

@media (max-width: 640px) {
    .form-row {
        grid-template-columns: 1fr;
    }
}

.form-section {
    margin-bottom: var(--spacing-2xl);
    padding-bottom: var(--spacing-xl);
    border-bottom: 1px solid var(--border-color);
}

.form-section:last-of-type {
    border-bottom: none;
}

.form-section-title {
    font-size: 1.125rem;
    font-weight: 600;
    margin-bottom: var(--spacing-lg);
    color: var(--text-base);
}

.form-actions {
    display: flex;
    justify-content: flex-end;
    gap: var(--spacing-md);
    padding-top: var(--spacing-lg);
}

@media (max-width: 480px) {
    .form-actions {
        flex-direction: column-reverse;
    }

    .form-actions .btn {
        width: 100%;
    }
}

.checkbox-group {
    margin-bottom: var(--spacing-md);
}

/* Qualified with the element type (not just .checkbox-label) so this ties
   .form-group label's specificity and wins on source order - .form-group
   label's plain "display: block" otherwise silently wins over a bare
   class selector whenever this sits inside a .form-group, collapsing the
   flex row into a block and stacking the checkbox above its text. */
label.checkbox-label {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    cursor: pointer;
    font-size: 0.875rem;
}

.checkbox-label input[type="checkbox"] {
    display: none;
}

/* For a consent-sized label the text runs to several lines, so the box
   aligns to the first line instead of floating in the vertical middle. */
label.checkbox-label--block {
    align-items: flex-start;
    font-size: 0.8125rem;
    line-height: 1.55;
}

.checkbox-label--block .checkbox-custom {
    margin-top: 2px;
}

.checkbox-custom {
    width: 20px;
    height: 20px;
    /* Without this the 20px box is squeezed by a long label, which is how
       a multi-line consent checkbox ends up a thin sliver. */
    flex-shrink: 0;
    border: 2px solid var(--border-color-light);
    border-radius: var(--radius-sm);
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all var(--transition-fast);
}

.checkbox-label input:checked + .checkbox-custom {
    background: var(--accent-primary);
    border-color: var(--accent-primary);
}

.checkbox-label input:checked + .checkbox-custom::after {
    content: '';
    width: 8px;
    height: 5px;
    border: 2px solid #fff;
    border-top: none;
    border-right: none;
    transform: rotate(-45deg);
    margin-bottom: 2px;
}

.radio-group {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
}

/* Qualified with the element type - see the .checkbox-label comment above
   for why a bare .radio-label loses to .form-group label's display:block. */
label.radio-label {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    cursor: pointer;
    padding: var(--spacing-md);
    background: var(--bg-highlight);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    transition: all var(--transition-fast);
}

.radio-label:hover {
    border-color: var(--border-color-light);
}

.radio-label input[type="radio"] {
    display: none;
}

.radio-custom {
    width: 20px;
    height: 20px;
    border: 2px solid var(--border-color-light);
    border-radius: var(--radius-full);
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all var(--transition-fast);
}

.radio-label input:checked + .radio-custom {
    border-color: var(--accent-primary);
}

.radio-label input:checked + .radio-custom::after {
    content: '';
    width: 10px;
    height: 10px;
    background: var(--accent-primary);
    border-radius: var(--radius-full);
}

.color-input-group {
    display: flex;
    gap: var(--spacing-sm);
}

.color-input-group input[type="color"] {
    width: 48px;
    height: 48px;
    flex-shrink: 0;
    padding: 0;
    border: none;
    border-radius: var(--radius-md);
    cursor: pointer;
}

.color-input-group .color-text {
    flex: 1;
    min-width: 0;
    padding: var(--spacing-md);
    background: var(--bg-highlight);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    color: var(--text-subdued);
    font-family: monospace;
}

.upload-icon {
    width: 48px;
    height: 48px;
}

.cover-upload-hint {
    font-size: 0.75rem;
    color: var(--text-subdued);
    opacity: 0.7;
}

/* Circle photo picker (Instagram/LinkedIn-style avatar cropper trigger) */
.circle-photo-picker {
    display: flex;
    align-items: center;
    gap: var(--spacing-lg);
    flex-wrap: wrap;
    margin-bottom: var(--spacing-sm);
}

.circle-photo-preview {
    position: relative;
    width: 96px;
    height: 96px;
    flex-shrink: 0;
    border-radius: 50%;
    overflow: hidden;
    background: var(--bg-elevated);
    border: 2px dashed var(--border-color);
}

.circle-photo-picker.has-image .circle-photo-preview {
    border-style: solid;
}

#circle-photo-preview-img {
    display: none;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.circle-photo-picker.has-image #circle-photo-preview-img {
    display: block;
}

.circle-photo-empty {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-subdued);
    cursor: pointer;
}

.circle-photo-picker.has-image .circle-photo-empty {
    display: none;
}

.circle-photo-empty .upload-icon {
    width: 32px;
    height: 32px;
}

.circle-photo-spinner {
    position: absolute;
    inset: 0;
    display: none;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.55);
    color: var(--text-base);
}

.circle-photo-picker.uploading .circle-photo-spinner {
    display: flex;
}

.circle-photo-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-sm);
}

/* Cropper modal (drag to pan, slider to zoom, like a profile-photo editor) */
.cropper-modal {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--spacing-lg);
    background: rgba(0, 0, 0, 0.75);
}

.cropper-dialog {
    width: 100%;
    max-width: 420px;
    max-height: 90vh;
    overflow-y: auto;
    background: var(--bg-elevated);
    border-radius: var(--radius-lg);
    padding: var(--spacing-lg);
    display: flex;
    flex-direction: column;
    gap: var(--spacing-lg);
}

.cropper-title {
    font-size: 1.125rem;
    font-weight: 600;
}

.cropper-stage {
    position: relative;
    width: 100%;
    max-width: 320px;
    aspect-ratio: 1 / 1;
    flex-shrink: 0;
    margin: 0 auto;
    overflow: hidden;
    border-radius: var(--radius-md);
    background: #000;
    touch-action: none;
    cursor: grab;
}

.cropper-stage:active {
    cursor: grabbing;
}

#cropper-image {
    position: absolute;
    top: 0;
    left: 0;
    max-width: none;
    max-height: none;
    transform-origin: 0 0;
    will-change: transform;
    user-select: none;
    pointer-events: none;
}

.cropper-mask {
    position: absolute;
    inset: 0;
    border-radius: 50%;
    box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.6);
    pointer-events: none;
}

.cropper-zoom-row {
    display: flex;
    align-items: center;
    gap: var(--spacing-md);
}

.cropper-zoom-icon {
    width: 16px;
    height: 16px;
    color: var(--text-subdued);
    flex-shrink: 0;
}

.cropper-zoom-icon-lg {
    width: 22px;
    height: 22px;
}

.cropper-zoom-row input[type="range"] {
    flex: 1;
    min-width: 0;
    accent-color: var(--accent-primary);
}

.cropper-actions {
    display: flex;
    justify-content: flex-end;
    gap: var(--spacing-sm);
}

.input-prefix-group {
    display: flex;
}

.input-prefix {
    flex-shrink: 0;
    padding: var(--spacing-md);
    background: var(--bg-press);
    border: 1px solid var(--border-color);
    border-right: none;
    border-radius: var(--radius-md) 0 0 var(--radius-md);
    color: var(--text-subdued);
    font-size: 0.875rem;
    white-space: nowrap;
}

.input-prefix-group input {
    flex: 1;
    min-width: 0;
    border-radius: 0 var(--radius-md) var(--radius-md) 0 !important;
}

@media (max-width: 480px) {
    .input-prefix {
        padding: var(--spacing-sm);
        font-size: 0.75rem;
    }
}

/* ==========================================
   Cards
   ========================================== */
.event-card {
    background: var(--bg-card);
    border-radius: var(--radius-lg);
    overflow: hidden;
    transition: all var(--transition-base);
    position: relative;
}

.event-card:hover {
    background: var(--bg-card-hover);
    transform: translateY(-4px);
}

.event-card-link {
    display: block;
}

/* Mirrors the .event-hero banner on the single-event overview page
   (event-detail.html), scaled down to fit a grid card, so an invitation
   is recognizable by its own colors/emblem/photo at a glance in the list
   instead of a generic placeholder. */
.event-card-hero {
    padding: var(--spacing-lg);
    min-height: 220px;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
}

.event-card-emblem {
    font-size: 1.5rem;
    font-weight: 400;
    margin-bottom: var(--spacing-sm);
    display: flex;
    align-items: center;
    gap: var(--spacing-xs);
}

.event-card-emblem-separator {
    font-size: 1.1rem;
}

.event-card-hero-title {
    font-size: 1.25rem;
    font-weight: 700;
    margin-bottom: var(--spacing-sm);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.event-card-photo-wrap {
    margin-bottom: var(--spacing-sm);
}

.event-card-photo {
    width: 64px;
    height: 64px;
    border-radius: 50%;
    object-fit: cover;
    border: 3px solid var(--bg-base);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.35);
}

.event-card-hero-meta {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-xs);
    color: inherit;
    opacity: 0.78;
    font-size: 0.8125rem;
}

.event-card-hero-date,
.event-card-hero-location {
    display: flex;
    align-items: center;
    gap: var(--spacing-xs);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.event-card-hero-date svg,
.event-card-hero-location svg {
    width: 14px;
    height: 14px;
    flex-shrink: 0;
}

.event-card-actions {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: var(--spacing-md);
    font-size: 0.75rem;
}

.event-guest-count {
    display: flex;
    align-items: center;
    gap: var(--spacing-xs);
    color: var(--text-subdued);
}

.event-guest-count svg {
    width: 16px;
    height: 16px;
}

.event-status {
    display: flex;
    align-items: center;
    gap: var(--spacing-xs);
    padding: var(--spacing-xs) var(--spacing-sm);
    border-radius: var(--radius-full);
    font-weight: 500;
}

.event-status.active {
    background: rgba(228, 68, 121, 0.15);
    color: var(--accent-primary);
}

.event-status.unpaid {
    background: rgba(232, 165, 48, 0.15);
    color: var(--essential-warning);
}

/* Neutral, not a warning: a draft is not a problem to fix, it is work in
   progress. Distinct from .unpaid, which means finished but not activated. */
.event-status.draft {
    background: var(--bg-elevated);
    color: var(--text-subdued);
}

.event-status svg {
    width: 14px;
    height: 14px;
}

/* ==========================================
   Events Grid
   ========================================== */
.events-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: var(--spacing-lg);
}

@media (min-width: 768px) {
    .events-grid {
        grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    }
}

/* ==========================================
   Dashboard
   ========================================== */
.dashboard-welcome {
    margin-bottom: var(--spacing-xl);
}

.welcome-title {
    font-size: 2rem;
    margin-bottom: var(--spacing-xs);
}

.welcome-subtitle {
    color: var(--text-subdued);
}

.dashboard-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: var(--spacing-md);
    margin-bottom: var(--spacing-2xl);
}

.stat-card {
    display: flex;
    align-items: center;
    gap: var(--spacing-md);
    padding: var(--spacing-lg);
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    transition: background var(--transition-fast);
}

.stat-card:hover {
    background: var(--bg-card-hover);
}

.stat-icon {
    width: 48px;
    height: 48px;
    border-radius: var(--radius-md);
    display: flex;
    align-items: center;
    justify-content: center;
}

.stat-icon svg {
    width: 24px;
    height: 24px;
}

.stat-icon.events {
    background: rgba(228, 68, 121, 0.15);
    color: var(--accent-primary);
}

.stat-icon.upcoming {
    background: rgba(228, 68, 121, 0.15);
    color: var(--accent-primary);
}

.stat-icon.guests {
    background: rgba(99, 179, 237, 0.15);
    color: #63b3ed;
}

.stat-icon.attending {
    background: rgba(228, 68, 121, 0.15);
    color: var(--accent-primary);
}

.stat-value {
    font-size: 1.75rem;
    font-weight: 700;
}

.stat-label {
    font-size: 0.875rem;
    color: var(--text-subdued);
}

.dashboard-section {
    margin-bottom: var(--spacing-2xl);
}

.section-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: var(--spacing-lg);
}

.section-title {
    font-size: 1.25rem;
}

.section-link {
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--text-subdued);
    transition: color var(--transition-fast);
}

.section-link:hover {
    color: var(--text-base);
}

.guests-table th.col-when,
.guests-table td.col-when {
    color: var(--text-subdued);
    white-space: nowrap;
}

.pagination {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--spacing-md);
    margin-top: var(--spacing-lg);
}

.pagination-btn {
    padding: var(--spacing-sm) var(--spacing-md);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    background: var(--bg-elevated);
    color: var(--text-base);
    font-size: 0.875rem;
    font-weight: 500;
    transition: background var(--transition-fast);
}

.pagination-btn:hover:not(:disabled) {
    background: var(--bg-card-hover);
}

.pagination-btn:disabled {
    color: var(--text-disabled);
    cursor: not-allowed;
    opacity: 0.5;
}

.pagination-info {
    font-size: 0.875rem;
    color: var(--text-subdued);
}

/* ==========================================
   Page Header
   ========================================== */
.page-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: var(--spacing-xl);
    flex-wrap: wrap;
    gap: var(--spacing-md);
}

.page-title {
    font-size: 1.75rem;
}

.page-subtitle {
    color: var(--text-subdued);
    margin-top: var(--spacing-xs);
}

/* ==========================================
   Filter Bar
   ========================================== */
.filter-bar {
    margin-bottom: var(--spacing-lg);
}

.filter-chips {
    display: flex;
    gap: var(--spacing-sm);
    flex-wrap: wrap;
}

.chip {
    padding: var(--spacing-sm) var(--spacing-md);
    background: var(--bg-highlight);
    border-radius: var(--radius-full);
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--text-subdued);
    transition: all var(--transition-fast);
}

.chip:hover {
    background: var(--bg-card-hover);
    color: var(--text-base);
}

.chip.active {
    background: var(--text-base);
    color: var(--bg-base);
}

.filter-select {
    padding: var(--spacing-sm) var(--spacing-md);
    background: var(--bg-highlight);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    color: var(--text-base);
    font-size: 0.875rem;
}

/* ==========================================
   Template Gallery
   ========================================== */
.tpl-gallery-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: var(--spacing-lg);
}

.tpl-card {
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    overflow: hidden;
    transition: all var(--transition-base);
}

.tpl-card:hover {
    background: var(--bg-card-hover);
    transform: translateY(-4px);
    box-shadow: var(--shadow-card);
}

.tpl-card-preview-bordered {
    outline: var(--tpl-border);
    outline-offset: -14px;
}

.tpl-card-preview {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--spacing-md);
    aspect-ratio: 3 / 4;
    padding: var(--spacing-xl) var(--spacing-lg);
    text-align: center;
    text-decoration: none;
}

.tpl-card-emblem {
    font-size: 1.375rem;
    letter-spacing: 0.08em;
}

.tpl-card-sample {
    font-size: 1.25rem;
    line-height: 1.35;
    max-width: 100%;
    overflow-wrap: break-word;
}

.tpl-card-line {
    width: 36px;
    height: 3px;
    border-radius: var(--radius-full);
}

.tpl-card-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-sm);
    padding: var(--spacing-md);
    border-top: 1px solid var(--border-color);
}

.tpl-card-name {
    font-weight: 600;
    font-size: 0.875rem;
    color: var(--text-base);
}

.tpl-card-cta {
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--accent-primary);
    white-space: nowrap;
}

.tpl-card-cta:hover {
    text-decoration: underline;
}

.tpl-active-banner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-md);
    flex-wrap: wrap;
    padding: var(--spacing-md) var(--spacing-lg);
    background: var(--bg-highlight);
    border-radius: var(--radius-md);
    margin-bottom: var(--spacing-lg);
    color: var(--text-subdued);
    font-size: 0.875rem;
}

.tpl-active-banner strong {
    color: var(--text-base);
}

.tpl-gallery-blank {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-md);
    flex-wrap: wrap;
    padding: var(--spacing-lg);
    background: var(--bg-card);
    border: 1px dashed var(--border-color-light);
    border-radius: var(--radius-lg);
    margin-bottom: var(--spacing-xl);
}

.tpl-gallery-blank-text strong {
    display: block;
    color: var(--text-base);
    font-size: 1rem;
    margin-bottom: 2px;
}

.tpl-gallery-blank-text span {
    color: var(--text-subdued);
    font-size: 0.875rem;
}

/* Homepage templates showcase (light-on-dark landing section) */
.templates-showcase {
    padding: var(--spacing-3xl) var(--spacing-2xl);
    max-width: 1400px;
    margin: 0 auto;
}

.showcase-head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--spacing-lg);
    flex-wrap: wrap;
    margin-bottom: var(--spacing-2xl);
}

.showcase-head-text {
    max-width: 46ch;
}

.showcase-head-text .section-title {
    font-size: 2rem;
    margin-bottom: var(--spacing-xs);
}

.showcase-head-cta {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-sm);
    font-weight: 600;
    font-size: 0.9375rem;
    color: var(--accent-primary);
    flex-shrink: 0;
}

.showcase-head-cta-arrow {
    width: 36px;
    height: 36px;
    border-radius: var(--radius-full);
    background: var(--accent-primary);
    color: #fff;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: transform var(--transition-fast);
}

.showcase-head-cta-arrow svg {
    width: 18px;
    height: 18px;
}

.showcase-head-cta:hover .showcase-head-cta-arrow {
    transform: translateX(3px);
}

.showcase-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--spacing-lg);
}

@media (max-width: 1024px) {
    .showcase-grid {
        grid-template-columns: repeat(2, 1fr);
    }
}

/* Two up, not one. A phone-shaped card at full phone width is a whole
   screen each, and four of them turn the showcase into several thousand
   pixels of scrolling. Two up reads as a gallery and still shows the
   hero type. */
@media (max-width: 640px) {
    .showcase-grid {
        grid-template-columns: repeat(2, 1fr);
        gap: var(--spacing-md);
    }
}

/* Capped so the phone ratio cannot run away with the section height: at
   two columns a grid cell gets wide, and 84/39 of "wide" is very tall. */
.showcase-card {
    width: 100%;
    max-width: 280px;
    margin-inline: auto;
}

.showcase-card-media {
    position: relative;
    /* Phone-shaped on purpose. The poster's first screen is a real 390x844
       viewport, and a hero declaring 100svh fills all of it - in a 4:5
       window the photo-led templates showed nothing but photograph, with
       the couple's names cropped off below the fold. Matching the device
       ratio is the only shape that shows a whole first screen, and it
       reads as a phone, which is where these are opened. */
    aspect-ratio: 39 / 84;
    border-radius: var(--radius-xl);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--spacing-md);
    padding: var(--spacing-lg);
    text-align: center;
    margin-bottom: var(--spacing-md);
    box-shadow: var(--shadow-sm);
    transition: transform var(--transition-base);
}

.showcase-card:hover .showcase-card-media {
    transform: translateY(-4px);
    box-shadow: var(--shadow-card);
}

/* The poster is a tall capture of the real invitation - roughly the first
   three sections - shown through a 4:5 window. Hovering pans it from the
   hero down through the story, which is what tells a visitor this is a
   page rather than a swatch. object-position animates without needing to
   know each poster's pixel height, so nothing here has to be kept in sync
   with the generator. */
.showcase-card-poster {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: 50% 0%;
    /* Quick on the way back, slow on the way down - the pan is the point,
       the return is not. */
    transition: object-position 700ms var(--ease-out, ease);
}

.showcase-card:hover .showcase-card-poster,
.showcase-card:focus-visible .showcase-card-poster {
    object-position: 50% 100%;
    transition: object-position 6s linear;
}

/* Touch has no hover, and the card is a link to the live preview anyway,
   so the top of the poster is the right still to leave showing. */
@media (hover: none) {
    .showcase-card:hover .showcase-card-poster {
        object-position: 50% 0%;
        transition: none;
    }
}

@media (prefers-reduced-motion: reduce) {
    .showcase-card-poster,
    .showcase-card:hover .showcase-card-poster,
    .showcase-card:focus-visible .showcase-card-poster {
        object-position: 50% 0%;
        transition: none;
    }
}

.showcase-card-badge {
    position: absolute;
    top: var(--spacing-md);
    left: var(--spacing-md);
    background: rgba(250, 250, 250, 0.95);
    backdrop-filter: blur(4px);
    color: var(--text-base);
    font-size: 0.625rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    padding: var(--spacing-xs) var(--spacing-sm);
    border-radius: var(--radius-full);
    box-shadow: var(--shadow-sm);
}

.showcase-card-eyebrow {
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--accent-primary);
    margin-bottom: 4px;
}

.showcase-card-title {
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 1.05rem;
    color: var(--text-base);
    transition: color var(--transition-fast);
}

.showcase-card:hover .showcase-card-title {
    color: var(--accent-primary);
}

/* ==========================================
   Event Detail
   ========================================== */
.event-hero {
    border-radius: var(--radius-xl);
    padding: var(--spacing-xl);
    margin-bottom: var(--spacing-lg);
}

.event-hero-info {
    max-width: 600px;
}

.event-emblem {
    font-size: 3rem;
    font-weight: 400;
    margin-bottom: var(--spacing-md);
    display: flex;
    align-items: center;
    gap: var(--spacing-md);
}

.emblem-separator {
    font-size: 2rem;
}

.event-title {
    font-size: 2rem;
    margin-bottom: var(--spacing-sm);
}

.event-meta {
    display: flex;
    gap: var(--spacing-lg);
    color: inherit;
    opacity: 0.78;
    flex-wrap: wrap;
}

.event-meta span {
    display: flex;
    align-items: center;
    gap: var(--spacing-xs);
}

.event-meta svg {
    width: 18px;
    height: 18px;
}

.event-actions-bar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: var(--spacing-md) 0;
    border-bottom: 1px solid var(--border-color);
    margin-bottom: var(--spacing-xl);
    flex-wrap: wrap;
    gap: var(--spacing-md);
}

.event-status-info {
    display: flex;
    gap: var(--spacing-md);
    flex-wrap: wrap;
}

.status-tag {
    display: flex;
    align-items: center;
    gap: var(--spacing-xs);
    padding: var(--spacing-xs) var(--spacing-md);
    border-radius: var(--radius-full);
    font-size: 0.875rem;
    font-weight: 500;
}

.status-tag.active {
    background: rgba(228, 68, 121, 0.15);
    color: var(--accent-primary);
}

.status-tag.unpaid {
    background: rgba(232, 165, 48, 0.15);
    color: var(--essential-warning);
}

.status-tag svg {
    width: 16px;
    height: 16px;
}

.tier-tag {
    padding: var(--spacing-xs) var(--spacing-md);
    background: var(--bg-highlight);
    border-radius: var(--radius-full);
    font-size: 0.875rem;
    color: var(--text-subdued);
}

.event-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-sm);
}

@media (max-width: 480px) {
    .event-actions {
        width: 100%;
    }

    .event-actions .btn {
        flex: 1 1 auto;
        min-width: calc(50% - var(--spacing-sm) / 2);
    }
}

.event-stats-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: var(--spacing-md);
    margin-bottom: var(--spacing-2xl);
}

.event-stats-grid .stat-card {
    flex-direction: column;
    text-align: center;
    gap: var(--spacing-sm);
}

.event-stats-grid .stat-value {
    font-size: 2rem;
}

.event-stats-grid .stat-value.attending {
    color: var(--accent-primary);
}

.event-stats-grid .stat-value.not-attending {
    color: var(--essential-negative);
}

/* ==========================================
   Tabs
   ========================================== */
.event-tabs,
.tabs {
    display: flex;
    gap: var(--spacing-sm);
    border-bottom: 1px solid var(--border-color);
    margin-bottom: var(--spacing-xl);
}

.tab-btn {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    padding: var(--spacing-md) var(--spacing-lg);
    color: var(--text-subdued);
    font-weight: 500;
    border-bottom: 2px solid transparent;
    transition: all var(--transition-fast);
    margin-bottom: -1px;
}

.tab-btn:hover {
    color: var(--text-base);
}

.tab-btn.active {
    color: var(--text-base);
    border-bottom-color: var(--accent-primary);
}

.tab-btn svg {
    width: 20px;
    height: 20px;
}

.tab-content {
    display: none;
}

.tab-content.active {
    display: block;
}

/* ==========================================
   Guests List
   ========================================== */
.guests-header {
    display: flex;
    justify-content: space-between;
    gap: var(--spacing-md);
    margin-bottom: var(--spacing-lg);
    flex-wrap: wrap;
}

.search-container {
    position: relative;
    flex: 1;
    min-width: 200px;
    max-width: 400px;
}

.guests-filters {
    display: flex;
    gap: var(--spacing-sm);
}

.guests-list {
    display: flex;
    flex-direction: column;
}

/* Real <table>-based guest list */
.table-responsive {
    overflow-x: auto;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
}

.guests-table {
    width: 100%;
    min-width: 640px;
    border-collapse: collapse;
    font-size: 0.875rem;
}

.guests-table thead th {
    padding: var(--spacing-md);
    text-align: left;
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-subdued);
    background: var(--bg-elevated);
    border-bottom: 1px solid var(--border-color);
    white-space: nowrap;
}

.guests-table tbody tr {
    border-bottom: 1px solid var(--border-color);
    transition: background var(--transition-fast);
}

.guests-table tbody tr:last-child {
    border-bottom: none;
}

.guests-table tbody tr:hover {
    background: var(--bg-highlight);
}

.guests-table tbody tr.additional-guest {
    background: rgba(255, 255, 255, 0.015);
}

.guests-table td {
    padding: var(--spacing-md);
    vertical-align: middle;
}

.guests-table th.col-number,
.guests-table td.col-number {
    width: 1%;
    text-align: center;
    color: var(--text-subdued);
    font-size: 0.875rem;
}

.guests-table td.col-number.sub {
    font-size: 0.75rem;
    color: var(--text-disabled);
}

.guests-table th.col-actions,
.guests-table td.col-actions {
    width: 1%;
    text-align: right;
}

.guest-cell {
    display: flex;
    align-items: center;
    gap: var(--spacing-md);
}

.guest-cell .avatar-initials {
    width: 32px;
    height: 32px;
    flex-shrink: 0;
    border-radius: 50%;
    background: var(--bg-highlight);
    display: flex;
    align-items: center;
    justify-content: center;
}

.guest-cell .avatar-initials.secondary {
    background: var(--bg-card-hover);
    color: var(--text-subdued);
}

.guest-row.additional-guest .guest-cell {
    padding-left: var(--spacing-xl);
    position: relative;
}

.guest-row.additional-guest .guest-cell::before {
    content: '';
    position: absolute;
    left: var(--spacing-md);
    top: 50%;
    width: var(--spacing-md);
    height: 1px;
    background: var(--border-color-light);
}

.guest-extras {
    margin-top: var(--spacing-sm);
    font-size: 0.8125rem;
    color: var(--text-subdued);
}

.guest-extras summary {
    cursor: pointer;
    color: var(--text-muted);
    list-style: none;
}

.guest-extras summary::-webkit-details-marker {
    display: none;
}

.guest-extras-list {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 2px var(--spacing-md);
    margin: var(--spacing-xs) 0 0;
}

.guest-extras-list dt {
    color: var(--text-muted);
}

.guest-extras-list dd {
    margin: 0;
}

.guest-info {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.guest-name {
    font-weight: 500;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.guest-email,
.guest-note {
    font-size: 0.75rem;
    color: var(--text-subdued);
}

.guest-message {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    margin-left: auto;
    width: 32px;
    height: 32px;
    cursor: pointer;
    border-radius: var(--radius-full);
    transition: background var(--transition-fast);
}

.guest-message:hover,
.guest-message:focus-visible {
    background: var(--bg-highlight);
}

.guest-message svg {
    width: 14px;
    height: 14px;
    color: var(--text-subdued);
}

.guest-message-text {
    white-space: pre-wrap;
    line-height: 1.6;
    color: var(--text-base);
}

.status-badge {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-xs);
    padding: var(--spacing-xs) var(--spacing-sm);
    border-radius: var(--radius-full);
    font-size: 0.75rem;
    font-weight: 500;
    white-space: nowrap;
}

.status-badge.attending {
    background: rgba(228, 68, 121, 0.15);
    color: var(--accent-primary);
}

.status-badge.not-attending {
    background: rgba(239, 67, 67, 0.15);
    color: var(--essential-negative);
}

.status-badge svg {
    width: 12px;
    height: 12px;
}

.status-badge.small {
    padding: 2px var(--spacing-xs);
    font-size: 0.625rem;
}

/* ==========================================
   Admin
   ========================================== */
.back-link {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-xs);
    color: var(--text-subdued);
    font-size: 0.875rem;
    margin-bottom: var(--spacing-lg);
    transition: color var(--transition-fast);
}

.back-link:hover {
    color: var(--text-base);
}

.back-link svg {
    width: 18px;
    height: 18px;
}

.admin-user-summary {
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    padding: var(--spacing-lg);
    margin-bottom: var(--spacing-xl);
}

.admin-user-summary-header {
    display: flex;
    align-items: center;
    gap: var(--spacing-md);
    margin-bottom: var(--spacing-md);
}

.admin-user-summary-header .user-avatar {
    width: 56px;
    height: 56px;
}

.admin-user-summary-header .avatar-initials {
    font-size: 1.125rem;
}

.admin-user-badges {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    margin-bottom: var(--spacing-md);
}

.admin-user-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-sm);
}

.admin-event-card-wrap {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-xs);
}

.admin-event-card-link {
    align-self: flex-start;
}

.admin-event-controls {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-md);
    margin-top: var(--spacing-md);
}

.admin-event-controls .form-group {
    max-width: 320px;
}

.admin-danger-zone {
    margin-top: var(--spacing-lg);
    padding-top: var(--spacing-md);
    border-top: 1px solid var(--essential-negative);
}

.admin-danger-zone-title {
    color: var(--essential-negative);
    font-size: 0.875rem;
    margin-bottom: var(--spacing-xs);
}

/* Qualified with .icon-picker-grid (both classes are on the same element in
   the markup) so this reliably beats .icon-picker-grid's own
   grid-template-columns - a bare .admin-svg-tag-grid selector has the same
   specificity as .icon-picker-grid and loses on source order, since
   .icon-picker-grid is defined later in this file. */
.icon-picker-grid.admin-svg-tag-grid {
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    max-height: none;
}

.admin-svg-tag-grid .icon-picker-grid-item {
    aspect-ratio: auto;
    flex-direction: column;
    gap: var(--spacing-xs);
    padding: var(--spacing-md) var(--spacing-sm) var(--spacing-sm);
}

.admin-svg-tag-grid .icon-picker-grid-shape {
    width: 44px;
    height: 44px;
    flex-shrink: 0;
}

.admin-svg-tag-form {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-xs);
    width: 100%;
}

.admin-svg-tag-select {
    width: 100%;
    padding: var(--spacing-xs);
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    color: var(--text-base);
    font-size: 0.75rem;
}

@media (max-width: 480px) {
    .icon-picker-grid.admin-svg-tag-grid {
        grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    }
}

.admin-palette-create {
    padding: var(--spacing-lg);
    margin-bottom: var(--spacing-lg);
    background: var(--bg-elevated, var(--bg-highlight));
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
}

.admin-palette-create-title {
    font-size: 1.125rem;
    margin-bottom: var(--spacing-xs);
}

.admin-palette-hint {
    color: var(--text-subdued);
    font-size: 0.8125rem;
    margin-bottom: var(--spacing-md);
}

.admin-palette-fields {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: var(--spacing-md);
    margin-bottom: var(--spacing-sm);
}

.admin-palette-field {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-xs);
    font-size: 0.8125rem;
    color: var(--text-subdued);
}

.admin-palette-field input[type="text"] {
    width: 100%;
    padding: var(--spacing-sm);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    background: var(--bg-base);
    color: var(--text-base);
}

.admin-palette-tokens {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-sm) var(--spacing-md);
    margin: var(--spacing-md) 0;
}

.admin-palette-token {
    display: flex;
    flex-direction: column;
    gap: 4px;
    font-size: 0.75rem;
    color: var(--text-subdued);
}

.admin-palette-token input[type="color"] {
    width: 44px;
    height: 32px;
    padding: 0;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    background: transparent;
    cursor: pointer;
}

.admin-palette-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: var(--spacing-lg);
}

.admin-palette-card {
    padding: var(--spacing-md);
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
    background: var(--bg-elevated, var(--bg-highlight));
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
}

.admin-palette-preview {
    border-radius: var(--radius-md);
    padding: var(--spacing-md);
    min-height: 88px;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    gap: 4px;
    background: var(--sec-bg);
    border: 1px solid var(--sec-border);
}

.admin-palette-preview-kicker {
    font-size: 0.6875rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--sec-muted);
}

.admin-palette-preview-title {
    font-size: 1.125rem;
    font-weight: 700;
    color: var(--sec-text);
}

.admin-palette-preview-chip {
    align-self: flex-start;
    margin-top: var(--spacing-xs);
    padding: 2px 8px;
    border-radius: var(--radius-sm);
    background: var(--sec-accent);
    color: var(--sec-accent-text);
    font-size: 0.75rem;
}

.admin-palette-card-actions {
    display: flex;
    gap: var(--spacing-sm);
}

@media (max-width: 640px) {
    .admin-palette-fields {
        grid-template-columns: 1fr;
    }
}

.feedback-stars {
    color: var(--accent-gold, #d4af37);
    letter-spacing: 1px;
}

.admin-feedback-text {
    max-width: 320px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.table-badge {
    padding: var(--spacing-xs) var(--spacing-sm);
    background: var(--bg-highlight);
    border-radius: var(--radius-sm);
    font-size: 0.75rem;
}

.table-badge.unassigned {
    color: var(--text-subdued);
}

.table-select {
    padding: var(--spacing-xs) var(--spacing-sm);
    background: var(--bg-highlight);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    color: var(--text-base);
    font-size: 0.75rem;
    max-width: 160px;
}

.action-btn {
    width: 32px;
    height: 32px;
    border-radius: var(--radius-full);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-subdued);
    transition: all var(--transition-fast);
}

.action-btn:hover {
    background: var(--bg-card-hover);
    color: var(--text-base);
}

.action-btn svg {
    width: 18px;
    height: 18px;
}

.action-btn.action-mark-attending {
    background: rgba(228, 68, 121, 0.15);
    color: var(--accent-primary);
}

.action-btn.action-mark-attending:hover {
    background: rgba(228, 68, 121, 0.28);
    color: var(--accent-primary);
}

.action-btn.action-mark-not-attending {
    background: rgba(239, 67, 67, 0.12);
    color: var(--essential-negative);
}

.action-btn.action-mark-not-attending:hover {
    background: rgba(239, 67, 67, 0.22);
    color: var(--essential-negative);
}

.guests-table .skeleton-guest-number {
    width: 16px;
    height: 14px;
    margin: 0 auto;
}

.guests-table .skeleton-guest-avatar {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    flex-shrink: 0;
}

.guests-table .skeleton-guest-name {
    height: 14px;
    width: 120px;
    margin-bottom: var(--spacing-xs);
}

.guests-table .skeleton-guest-email {
    height: 12px;
    width: 160px;
}

.guests-table .skeleton-guest-badge {
    height: 24px;
    width: 90px;
    border-radius: var(--radius-full);
}

@media (max-width: 768px) {
    .guests-table {
        min-width: 560px;
    }
}

/* ==========================================
   Timeline
   ========================================== */
.timeline {
    position: relative;
    padding-left: var(--spacing-xl);
}

.timeline::before {
    content: '';
    position: absolute;
    left: 12px;
    top: 0;
    bottom: 0;
    width: 2px;
    background: var(--border-color);
}

.timeline-item,
.timeline-event {
    position: relative;
    padding-bottom: var(--spacing-xl);
}

.timeline-marker {
    position: absolute;
    left: calc(-1 * var(--spacing-xl) + 4px);
    width: 18px;
    height: 18px;
    background: var(--invitation-highlight, var(--accent-primary));
    border-radius: var(--radius-full);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.75rem;
}

.timeline-marker svg {
    width: 10px;
    height: 10px;
    fill: #000;
}

.timeline-icon-shape {
    width: 10px;
    height: 10px;
    -webkit-mask-size: contain;
    mask-size: contain;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
}

.timeline-content h4,
.timeline-name {
    font-weight: 600;
    margin-bottom: var(--spacing-xs);
}

.timeline-time {
    font-size: 0.875rem;
    color: var(--invitation-highlight, var(--accent-primary));
    margin-bottom: var(--spacing-xs);
}

.timeline-location {
    font-size: 0.875rem;
    color: var(--text-subdued);
}

/* ==========================================
   Empty State
   ========================================== */
.empty-state {
    text-align: center;
    padding: var(--spacing-3xl) var(--spacing-lg);
}

.empty-state.small {
    padding: var(--spacing-xl);
}

.empty-icon {
    width: 80px;
    height: 80px;
    margin: 0 auto var(--spacing-lg);
    background: var(--bg-highlight);
    border-radius: var(--radius-full);
    display: flex;
    align-items: center;
    justify-content: center;
}

.empty-icon svg {
    width: 40px;
    height: 40px;
    color: var(--text-subdued);
}

.empty-title {
    font-size: 1.25rem;
    margin-bottom: var(--spacing-sm);
}

.empty-description {
    color: var(--text-subdued);
    margin-bottom: var(--spacing-lg);
}

/* ==========================================
   Seating
   ========================================== */
.seating-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: var(--spacing-md);
    margin: var(--spacing-lg) 0;
}

.table-card {
    padding: var(--spacing-lg);
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    transition: background var(--transition-fast);
}

.table-card:hover {
    background: var(--bg-card-hover);
}

.table-card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: var(--spacing-sm);
}

.table-card-header h3 {
    font-size: 1rem;
    font-weight: 600;
}

.table-occupancy {
    font-size: 0.875rem;
    color: var(--text-subdued);
}

.table-occupancy-bar {
    height: 4px;
    border-radius: var(--radius-full);
    background: var(--bg-highlight);
    margin-top: var(--spacing-xs);
    overflow: hidden;
}

.table-occupancy-fill {
    height: 100%;
    background: var(--accent-primary);
    border-radius: var(--radius-full);
}

.seating-add-form {
    max-width: 420px;
    padding-top: var(--spacing-lg);
    border-top: 1px solid var(--border-color);
}

/* ==========================================
   Loading States
   ========================================== */
.loading-spinner {
    display: flex;
    justify-content: center;
    padding: var(--spacing-xl);
}

.spinner {
    width: 32px;
    height: 32px;
    animation: spin 1s linear infinite;
}

.spinner circle {
    stroke-dasharray: 80;
    stroke-dashoffset: 60;
}

@keyframes spin {
    to { transform: rotate(360deg); }
}

.skeleton {
    background: linear-gradient(
        90deg,
        var(--bg-highlight) 25%,
        var(--bg-card-hover) 50%,
        var(--bg-highlight) 75%
    );
    background-size: 200% 100%;
    animation: shimmer 1.5s infinite;
}

@keyframes shimmer {
    0% { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

.skeleton-box {
    border-radius: var(--radius-sm);
}

.skeleton-hero-title {
    height: 24px;
    width: 70%;
    margin: var(--spacing-lg) var(--spacing-lg) var(--spacing-sm);
}

.skeleton-hero-photo {
    width: 64px;
    height: 64px;
    border-radius: 50%;
    margin: 0 var(--spacing-lg) var(--spacing-sm);
}

.skeleton-hero-meta {
    height: 14px;
    width: 50%;
    margin: 0 var(--spacing-lg) var(--spacing-lg);
}

/* ==========================================
   Alerts & Toasts
   ========================================== */
.alert {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    padding: var(--spacing-md);
    border-radius: var(--radius-md);
    margin-bottom: var(--spacing-md);
}

.alert-error {
    background: rgba(239, 67, 67, 0.15);
    color: var(--essential-negative);
}

.alert-success {
    background: rgba(228, 68, 121, 0.15);
    color: var(--essential-positive);
}

.alert-warning {
    background: rgba(232, 165, 48, 0.15);
    color: var(--essential-warning);
}

.alert-icon {
    width: 20px;
    height: 20px;
    flex-shrink: 0;
}

.alert-message {
    flex: 1;
    min-width: 0;
    font-size: 0.875rem;
}

.alert-close {
    width: 24px;
    height: 24px;
    color: inherit;
    opacity: 0.7;
    transition: opacity var(--transition-fast);
}

.alert-close:hover {
    opacity: 1;
}

.alert-close svg {
    width: 100%;
    height: 100%;
}

.toast-container {
    position: fixed;
    bottom: calc(var(--mobile-nav-height) + var(--spacing-md));
    left: var(--spacing-md);
    right: var(--spacing-md);
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
    z-index: 1000;
    pointer-events: none;
}

.verify-banner {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--spacing-sm);
    padding: var(--spacing-md);
    border-radius: var(--radius-md);
    margin-bottom: var(--spacing-md);
    background: rgba(232, 165, 48, 0.15);
    color: var(--essential-warning);
}

.verify-banner-icon {
    width: 20px;
    height: 20px;
    flex-shrink: 0;
}

.verify-banner span {
    flex: 1;
    min-width: 200px;
}

.toast {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    padding: var(--spacing-md);
    background: var(--text-base);
    color: var(--bg-base);
    border-radius: var(--radius-md);
    font-size: 0.875rem;
    box-shadow: var(--shadow-lg);
    animation: slideUp 0.3s ease;
    pointer-events: auto;
}

@keyframes slideUp {
    from {
        opacity: 0;
        transform: translateY(20px);
    }
}

.toast-icon {
    width: 20px;
    height: 20px;
    flex-shrink: 0;
}

.toast-success .toast-icon {
    color: var(--accent-primary);
}

.toast-error .toast-icon {
    color: var(--essential-negative);
}

/* ==========================================
   Auth Pages
   ========================================== */
.auth-body {
    min-height: 100vh;
    min-height: 100dvh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--spacing-lg);
}

.landing-body {
    min-height: 100vh;
    min-height: 100dvh;
    background: var(--bg-base);
}

.auth-container {
    width: 100%;
    max-width: 440px;
}

.auth-background {
    position: fixed;
    inset: 0;
    z-index: -1;
}

.auth-gradient {
    width: 100%;
    height: 100%;
    background: linear-gradient(
        135deg,
        rgba(228, 68, 121, 0.2) 0%,
        transparent 50%,
        rgba(228, 68, 121, 0.1) 100%
    );
}

.auth-content {
    display: flex;
    flex-direction: column;
    align-items: center;
}

.auth-logo {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    margin-bottom: var(--spacing-2xl);
}

.auth-logo .logo-icon {
    width: 40px;
    height: 40px;
}

.auth-logo .logo-text {
    font-size: 1.5rem;
}

.auth-card {
    width: 100%;
    background: var(--bg-elevated);
    border-radius: var(--radius-xl);
    padding: var(--spacing-2xl);
    box-shadow: var(--shadow-lg);
}

.auth-header {
    text-align: center;
    margin-bottom: var(--spacing-xl);
}

.auth-header h1 {
    font-size: 1.75rem;
    margin-bottom: var(--spacing-xs);
}

.auth-header p {
    color: var(--text-subdued);
}

.health-version {
    font-size: 0.75rem;
    margin-top: var(--spacing-xs);
}

.health-version a {
    color: var(--text-subdued);
    text-decoration: underline;
}

.health-version a:hover {
    color: var(--text-base);
}

.health-checks {
    display: flex;
    flex-direction: column;
}

.health-check {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-md);
    padding: var(--spacing-md) 0;
    border-bottom: 1px solid var(--border-color);
}

.health-check:last-child {
    border-bottom: none;
    padding-bottom: 0;
}

.health-check-label {
    font-weight: 500;
}

.auth-divider {
    display: flex;
    align-items: center;
    gap: var(--spacing-md);
    margin: var(--spacing-lg) 0;
    color: var(--text-subdued);
    font-size: 0.875rem;
}

.auth-divider::before,
.auth-divider::after {
    content: '';
    flex: 1;
    height: 1px;
    background: var(--border-color);
}

.auth-form {
    margin-bottom: var(--spacing-lg);
}

.form-footer {
    display: flex;
    justify-content: flex-end;
    margin-bottom: var(--spacing-lg);
}

.form-link {
    font-size: 0.875rem;
    color: var(--text-subdued);
    transition: color var(--transition-fast);
}

.form-link:hover {
    color: var(--text-base);
}

.auth-footer {
    text-align: center;
    padding-top: var(--spacing-lg);
    border-top: 1px solid var(--border-color);
}

.auth-footer p {
    color: var(--text-subdued);
    font-size: 0.875rem;
}

.auth-footer a {
    color: var(--text-base);
    font-weight: 500;
}

.auth-footer a:hover {
    color: var(--accent-primary);
}

.auth-terms {
    text-align: center;
    font-size: 0.75rem;
    color: var(--text-subdued);
    margin-top: var(--spacing-lg);
}

.auth-terms a {
    color: var(--text-subdued);
    text-decoration: underline;
}

/* ==========================================
   Landing Page
   ========================================== */
.landing {
    min-height: 100vh;
    min-height: 100dvh;
}

/* Fixed, not sticky - taken out of flow entirely so the hero section
   behind it starts at the true top of the page and its gradient/glow
   can show through while the nav is still transparent (rest state).
   .hero-inner adds matching top padding so its content clears the nav's
   own height instead of rendering underneath it. Full-bleed bar so its
   background/blur spans the whole viewport width even on ultra-wide
   screens - .landing-nav-inner below is what actually caps to the
   shared 1400px content width. */
.landing-nav {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 10;
    background: transparent;
    border-bottom: 1px solid transparent;
    transition: background var(--transition-base), border-color var(--transition-base);
}

/* Toggled by a scroll listener in app.js once the page passes 80px -
   transparent-over-hero at rest, opaque once content scrolls under it.
   Backdrop blur is desktop-only (see the min-width rule below). */
.landing-nav.scrolled {
    background: var(--bg-base);
    border-bottom: 1px solid var(--border-color);
}

/* backdrop-filter snapshots everything under the nav on every scroll
   frame. Fine on desktop; on phones it is the difference between a
   native-feeling scroll and a 30fps one. */
@media (min-width: 1025px) {
    .landing-nav.scrolled {
        background: rgba(250, 250, 250, 0.85);
        backdrop-filter: blur(8px);
    }
}

.landing-nav-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    max-width: 1400px;
    margin: 0 auto;
    padding: var(--spacing-md) var(--spacing-2xl);
}

.landing-nav-logo {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    color: var(--text-base);
}

.landing-nav-links {
    display: flex;
    align-items: center;
    gap: var(--spacing-xl);
}

.landing-nav-links a {
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--text-subdued);
    transition: color var(--transition-fast);
}

.landing-nav-links a:hover {
    color: var(--text-base);
}

.landing-nav-actions {
    display: flex;
    align-items: center;
    gap: var(--spacing-md);
}

@media (max-width: 768px) {
    .landing-nav-links {
        display: none;
    }
}

@media (max-width: 480px) {
    .landing-nav-inner {
        padding: var(--spacing-md) var(--spacing-lg);
    }

    .landing-nav-logo .logo-text {
        display: none;
    }
}

/* Full-bleed so the blur-blob glow (.landing-body .hero::before/::after
   below) reaches the true viewport edges on wide screens - .hero-inner
   is what actually caps to the shared 1400px content width. */
.hero {
    min-height: 100vh;
    min-height: 100dvh;
    width: 100%;
    display: flex;
    align-items: center;
}

/* .landing-nav is now fixed and overlaps page content (see above), so
   an in-page anchor jump (#how-it-works etc.) would otherwise land
   the target flush against the viewport top, hidden behind the nav. */
.landing [id] {
    scroll-margin-top: 90px;
}

.hero-inner {
    /* Top padding covers the now-fixed .landing-nav's own rendered
       height (~76px) plus the usual section padding, so hero content
       clears the floating nav instead of rendering underneath it. */
    padding: calc(76px + var(--spacing-3xl)) var(--spacing-2xl) var(--spacing-3xl);
    max-width: 1400px;
    margin: 0 auto;
    width: 100%;
}

.hero-inner-centered {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 620px;
}

.hero-content {
    max-width: 600px;
}

.hero-content-centered {
    position: relative;
    z-index: 2;
    text-align: center;
    margin: 0 auto;
}

.hero-badge {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-xs);
    padding: var(--spacing-xs) var(--spacing-md);
    border-radius: var(--radius-full);
    background: rgba(228, 68, 121, 0.1);
    color: var(--accent-primary);
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    margin-bottom: var(--spacing-lg);
}

.hero-badge-dot {
    width: 6px;
    height: 6px;
    border-radius: var(--radius-full);
    background: currentColor;
    flex-shrink: 0;
}

.hero-title {
    font-size: 3.5rem;
    line-height: 1.1;
    margin-bottom: var(--spacing-lg);
}

@media (max-width: 768px) {
    .hero-title {
        font-size: 2.5rem;
    }
}

.hero-title .highlight {
    color: var(--accent-primary);
    font-style: italic;
}

.hero-subtitle {
    font-size: 1.25rem;
    color: var(--text-subdued);
    margin-bottom: var(--spacing-xl);
    line-height: 1.6;
    max-width: 46ch;
    margin-inline: auto;
}

.hero-actions {
    display: flex;
    gap: var(--spacing-md);
    flex-wrap: wrap;
    justify-content: center;
}

/* Four tilted preview cards scattered around the centered hero text,
   matching the reference site's corner-photo treatment - swapped for
   real invitation-template previews since we have no stock event
   photography. Hidden below 1024px, same as the reference's own
   `hidden md:block`, to keep the mobile hero clean. */
.hero-photo {
    display: none;
    position: absolute;
    z-index: 1;
    width: 200px;
}

@media (min-width: 1025px) {
    .hero-photo {
        display: block;
    }
}

.hero-photo-0 {
    left: -40px;
    top: 10px;
    transform: rotate(6deg);
}

.hero-photo-1 {
    left: -60px;
    bottom: 10px;
    transform: rotate(-5deg);
}

.hero-photo-2 {
    right: -40px;
    top: 10px;
    transform: rotate(-6deg);
}

.hero-photo-3 {
    right: -60px;
    bottom: 10px;
    transform: rotate(5deg);
}

@media (max-width: 1300px) {
    .hero-photo-0, .hero-photo-1 { left: -10px; }
    .hero-photo-2, .hero-photo-3 { right: -10px; }
}

.hero-photo-card {
    aspect-ratio: 4 / 3;
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-lg);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--spacing-md);
    text-align: center;
}

.hero-photo-name {
    font-size: 1.1rem;
    font-weight: 500;
    line-height: 1.3;
}

.hero-confetti {
    position: absolute;
    pointer-events: none;
}

.hero-confetti-a {
    top: -10px;
    right: 18px;
    width: 16px;
    height: 16px;
    border-radius: 3px;
    background: #FFD93D;
    transform: rotate(20deg);
}

.hero-confetti-b {
    top: 24px;
    right: -14px;
    width: 10px;
    height: 10px;
    border-radius: var(--radius-full);
    background: #4D96FF;
}

.hero-confetti-c {
    bottom: -12px;
    left: 22px;
    width: 20px;
    height: 14px;
    border-radius: var(--radius-full);
    background: #FF6BCB;
}

.hero-photo-1 .hero-confetti-a,
.hero-photo-3 .hero-confetti-a {
    background: #6BCB77;
}

.hero-photo-2 .hero-confetti-c,
.hero-photo-3 .hero-confetti-c {
    background: #FF9F43;
}

.how-it-works {
    padding: var(--spacing-3xl) var(--spacing-2xl);
    background: var(--bg-elevated);
}

.steps-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--spacing-xl);
    max-width: 1000px;
    margin: var(--spacing-2xl) auto 0;
}

@media (max-width: 768px) {
    .steps-grid {
        grid-template-columns: 1fr;
    }
}

.step-card {
    text-align: center;
}

.step-number {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 48px;
    height: 48px;
    border-radius: var(--radius-full);
    background: var(--bg-elevated);
    border: 1px solid var(--border-color-light);
    font-family: var(--font-display);
    font-size: 1.25rem;
    color: var(--accent-primary);
    box-shadow: var(--shadow-sm);
    margin-bottom: var(--spacing-md);
}

.step-card h3 {
    margin-bottom: var(--spacing-sm);
}

.step-card p {
    color: var(--text-subdued);
    font-size: 0.9375rem;
}

.section-title.centered {
    text-align: center;
    margin-bottom: var(--spacing-xl);
}

.section-subtitle.centered {
    text-align: center;
    color: var(--text-subdued);
    margin-top: calc(-1 * var(--spacing-md));
    margin-bottom: var(--spacing-2xl);
}

.features {
    padding: var(--spacing-3xl) var(--spacing-2xl);
    background: var(--bg-elevated);
    border-top: 1px solid var(--border-color);
}

.bento-grid {
    display: grid;
    gap: var(--spacing-lg);
    max-width: 1100px;
    margin: 0 auto;
}

.bento-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--spacing-lg);
}

.bento-card {
    border-radius: var(--radius-xl);
    padding: var(--spacing-2xl);
    min-height: 260px;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    gap: var(--spacing-sm);
}

.bento-card--dark {
    position: relative;
    overflow: hidden;
    background: var(--text-base);
    color: var(--bg-base);
}

/* Deck of preview cards + confetti sit as a full-card background layer
   behind the title/desc (z-index below), instead of stacked above the
   text in normal flow. */
.bento-card--dark .bento-title,
.bento-card--dark .bento-desc {
    position: relative;
    z-index: 2;
}

/* Gradient scrim so the text stays legible over whatever decoration
   happens to sit behind it, regardless of card content changes. */
.bento-card--dark::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 1;
    background: linear-gradient(to top, rgba(15, 15, 26, 0.92) 0%, rgba(15, 15, 26, 0.55) 45%, transparent 75%);
    pointer-events: none;
}

.bento-card--tint {
    background: rgba(228, 68, 121, 0.1);
    color: var(--text-base);
}

.bento-card--neutral {
    background: var(--bg-highlight);
    color: var(--text-base);
}

.bento-card--brand {
    background: var(--accent-primary);
    color: #fff;
}

.bento-tag {
    align-self: flex-start;
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    padding: var(--spacing-xs) var(--spacing-sm);
    border-radius: var(--radius-full);
    background: rgba(255, 255, 255, 0.2);
}

.bento-card--neutral .bento-tag {
    background: var(--bg-base);
    color: var(--text-subdued);
}

.bento-title {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 1.25rem;
}

.bento-desc {
    font-size: 0.9rem;
    opacity: 0.8;
    line-height: 1.5;
}

/* Small illustrative mockups filling the top of each bento card (matching
   the reference layout's per-card visuals rather than plain text-only
   cards) - flex:1 pushes the tag/title/desc block down to the bottom. */
.bento-visual {
    flex: 1;
    display: flex;
    align-items: center;
}

/* A small fanned "deck" of mini invitation-preview cards - a richer,
   more on-theme visual for "customizable templates" than plain color
   dots. Cards spread apart slightly on hover for a light interactive
   touch. */
.bento-visual-deck {
    position: absolute;
    inset: 0;
    z-index: 0;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding-top: var(--spacing-xl);
}

.bento-deck-card {
    position: absolute;
    width: 84px;
    height: 108px;
    border-radius: var(--radius-md);
    box-shadow: 0 14px 28px rgba(0, 0, 0, 0.35);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-end;
    gap: 6px;
    padding-bottom: var(--spacing-sm);
    transition: transform var(--transition-slow);
}

.bento-deck-emblem {
    font-size: 0.6875rem;
    letter-spacing: 0.06em;
}

.bento-deck-line {
    width: 22px;
    height: 3px;
    border-radius: var(--radius-full);
}

.bento-deck-card-0 {
    transform: rotate(-11deg) translate(-30px, 14px);
    z-index: 1;
}

.bento-deck-card-1 {
    transform: rotate(0deg) translateY(4px);
    z-index: 3;
}

.bento-deck-card-2 {
    transform: rotate(11deg) translate(30px, 14px);
    z-index: 2;
}

.bento-card--dark:hover .bento-deck-card-0 {
    transform: rotate(-16deg) translate(-42px, 8px);
}

.bento-card--dark:hover .bento-deck-card-1 {
    transform: rotate(0deg) translateY(-4px);
}

.bento-card--dark:hover .bento-deck-card-2 {
    transform: rotate(16deg) translate(42px, 8px);
}

/* Extra confetti scattered across the deck layer - dots, a pill, a
   rounded square, and two small rounded-corner triangles - all
   pointer-events:none so they never interfere with the card's own
   link/hover target. */
.bento-deck-shape {
    position: absolute;
    pointer-events: none;
}

.bento-deck-shape-rect {
    top: 14%;
    right: 16%;
    width: 26px;
    height: 12px;
    border-radius: var(--radius-full);
    background: #6BCB77;
    transform: rotate(-18deg);
}

.bento-deck-shape-square {
    bottom: 30%;
    left: 10%;
    width: 16px;
    height: 16px;
    border-radius: 5px;
    background: #4D96FF;
    transform: rotate(20deg);
}

.bento-deck-shape-triangle-a {
    top: 10%;
    left: 20%;
    width: 18px;
    height: 18px;
    transform: rotate(-15deg);
    opacity: 0.9;
}

.bento-deck-shape-triangle-b {
    bottom: 34%;
    right: 12%;
    width: 14px;
    height: 14px;
    transform: rotate(25deg);
    opacity: 0.85;
}

.bento-deck-sparkle {
    position: absolute;
    border-radius: var(--radius-full);
    background: var(--accent-primary);
    pointer-events: none;
}

.bento-deck-sparkle-a {
    top: 18%;
    left: 12%;
    width: 8px;
    height: 8px;
    opacity: 0.8;
}

.bento-deck-sparkle-b {
    bottom: 16%;
    right: 14%;
    width: 6px;
    height: 6px;
    background: #FFD93D;
}

.bento-deck-sparkle-c {
    top: 32%;
    right: 8%;
    width: 5px;
    height: 5px;
    background: #FF9F43;
    opacity: 0.75;
}

.bento-deck-sparkle-d {
    bottom: 42%;
    left: 6%;
    width: 7px;
    height: 7px;
    background: #FF6BCB;
    opacity: 0.7;
}

.bento-visual-rsvp {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--spacing-sm);
    width: 100%;
}

.bento-mock-line {
    height: 10px;
    width: 60%;
    border-radius: var(--radius-full);
    background: rgba(25, 25, 46, 0.15);
}

.bento-mock-line-light {
    background: rgba(255, 255, 255, 0.35);
}

.bento-mock-buttons {
    display: flex;
    gap: var(--spacing-xs);
    width: 100%;
}

.bento-mock-btn {
    flex: 1;
    padding: var(--spacing-xs) var(--spacing-sm);
    border-radius: var(--radius-full);
    background: var(--bg-base);
    color: var(--text-subdued);
    font-size: 0.68rem;
    font-weight: 600;
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.bento-mock-btn-active {
    background: var(--accent-primary);
    color: #fff;
}

.bento-visual-seating {
    flex-wrap: wrap;
    gap: var(--spacing-xs);
    align-content: center;
}

.bento-seat-avatar {
    width: 32px;
    height: 32px;
    border-radius: var(--radius-full);
    background: var(--bg-base);
    color: var(--text-subdued);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.7rem;
    font-weight: 700;
    flex-shrink: 0;
}

.bento-seat-avatar-more {
    background: var(--accent-primary);
    color: #fff;
}

.bento-visual-email {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--spacing-sm);
}

.bento-mock-bell {
    width: 28px;
    height: 28px;
    opacity: 0.9;
}

@media (max-width: 640px) {
    .bento-row {
        grid-template-columns: 1fr;
    }
}

.pricing {
    padding: var(--spacing-3xl) var(--spacing-2xl);
    max-width: 1200px;
    margin: 0 auto;
}

.pricing-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: var(--spacing-lg);
}

.pricing-card {
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-sm);
    padding: var(--spacing-xl);
    position: relative;
    transition: all var(--transition-base);
}

.pricing-card:hover {
    border-color: var(--border-color-light);
}

.pricing-card.featured {
    border-color: var(--accent-primary);
    background: linear-gradient(135deg, rgba(228, 68, 121, 0.1) 0%, transparent 50%);
}

.pricing-card.selectable {
    display: block;
    cursor: pointer;
}

.pricing-card-radio {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}

.pricing-card.selectable:has(.pricing-card-radio:checked) {
    border-color: var(--accent-primary);
    background: linear-gradient(135deg, rgba(228, 68, 121, 0.1) 0%, transparent 50%);
    box-shadow: 0 0 0 1px var(--accent-primary);
}

.pricing-badge {
    position: absolute;
    top: calc(-1 * var(--spacing-sm));
    left: 50%;
    transform: translateX(-50%);
    padding: var(--spacing-xs) var(--spacing-md);
    background: var(--accent-primary);
    color: #fff;
    font-size: 0.75rem;
    font-weight: 600;
    border-radius: var(--radius-full);
}

.pricing-header {
    text-align: center;
    padding-bottom: var(--spacing-lg);
    border-bottom: 1px solid var(--border-color);
    margin-bottom: var(--spacing-lg);
}

.pricing-header h3 {
    font-size: 1.25rem;
    margin-bottom: var(--spacing-md);
}

.price {
    display: flex;
    justify-content: center;
    align-items: baseline;
}

.currency {
    font-size: 1.25rem;
    color: var(--text-subdued);
}

.amount {
    font-size: 3rem;
    font-weight: 700;
}

.price-period {
    font-size: 0.875rem;
    color: var(--text-subdued);
}

.pricing-features {
    margin-bottom: var(--spacing-xl);
}

.pricing-features li {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    padding: var(--spacing-sm) 0;
    font-size: 0.875rem;
}

.pricing-features svg {
    width: 18px;
    height: 18px;
    color: var(--accent-primary);
    flex-shrink: 0;
}

.reviews {
    padding: var(--spacing-3xl) var(--spacing-2xl);
    max-width: var(--content-max-width);
    margin: 0 auto;
}

.reviews-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: var(--spacing-lg);
    margin-top: var(--spacing-xl);
}

.review-card {
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    padding: var(--spacing-lg);
}

.review-header {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    margin-bottom: var(--spacing-md);
}

.review-avatar {
    width: 40px;
    height: 40px;
    border-radius: var(--radius-full);
    overflow: hidden;
    background: var(--bg-highlight);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.review-avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.review-author {
    display: flex;
    flex-direction: column;
}

.review-name {
    font-weight: 600;
    font-size: 0.9rem;
}

.review-stars {
    color: var(--accent-primary);
    font-size: 0.8rem;
}

.review-text {
    color: var(--text-subdued);
    font-size: 0.9rem;
    line-height: 1.5;
}

.faq {
    padding: var(--spacing-3xl) var(--spacing-2xl);
    background: var(--bg-elevated);
}

.faq-list {
    max-width: 760px;
    margin: var(--spacing-2xl) auto 0;
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
}

.faq-item {
    background: var(--bg-elevated);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    padding: var(--spacing-md) var(--spacing-lg);
}

.faq-item summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-md);
    font-weight: 600;
    cursor: pointer;
    list-style: none;
}

.faq-item summary::-webkit-details-marker {
    display: none;
}

.faq-icon {
    flex-shrink: 0;
    width: 24px;
    height: 24px;
    border-radius: var(--radius-full);
    background: rgba(25, 25, 46, 0.08);
    color: var(--accent-secondary);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1rem;
    transition: transform var(--transition-fast);
}

.faq-item[open] .faq-icon {
    transform: rotate(45deg);
}

.faq-item p {
    margin-top: var(--spacing-md);
    color: var(--text-subdued);
    line-height: 1.6;
    font-size: 0.9375rem;
}

.cta {
    position: relative;
    overflow: hidden;
    max-width: 1200px;
    margin: 0 auto;
    padding: var(--spacing-3xl) var(--spacing-2xl);
    background: var(--text-base);
    color: var(--bg-base);
    border-radius: var(--radius-xl);
    text-align: center;
}

.cta-glow {
    position: absolute;
    top: -8rem;
    right: -6rem;
    width: 22rem;
    height: 22rem;
    border-radius: var(--radius-full);
    background: radial-gradient(circle, var(--accent-primary) 0%, transparent 70%);
    opacity: 0.45;
    pointer-events: none;
}

.cta-content {
    position: relative;
    max-width: 600px;
    margin: 0 auto;
}

.cta-badge {
    position: relative;
    width: 56px;
    height: 56px;
    margin: 0 auto var(--spacing-lg);
    border-radius: var(--radius-lg);
    background: var(--accent-primary);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 10px 30px rgba(228, 68, 121, 0.45);
}

.cta-badge svg {
    width: 26px;
    height: 26px;
}

.cta-badge-dot {
    position: absolute;
    width: 6px;
    height: 6px;
    border-radius: var(--radius-full);
    background: var(--accent-primary);
}

.cta-badge-dot-1 { top: -14px; left: -18px; }
.cta-badge-dot-2 { top: 6px; right: -22px; width: 4px; height: 4px; opacity: 0.7; }
.cta-badge-dot-3 { bottom: -12px; left: 4px; width: 5px; height: 5px; opacity: 0.85; }

.cta h2 {
    font-size: 2rem;
    margin-bottom: var(--spacing-md);
}

.cta p {
    opacity: 0.75;
    margin-bottom: var(--spacing-xl);
}

.landing-footer {
    background: var(--bg-elevated);
    border-top: 1px solid var(--border-color);
    padding: var(--spacing-xl) var(--spacing-2xl);
}

.footer-grid {
    max-width: 1100px;
    margin: 0 auto;
    display: grid;
    grid-template-columns: 2fr 1fr;
    gap: var(--spacing-2xl);
    text-align: left;
}

@media (max-width: 640px) {
    .footer-grid {
        grid-template-columns: 1fr;
        text-align: center;
    }
}

.footer-logo {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-sm);
    margin-bottom: var(--spacing-md);
    font-size: 1.25rem;
    font-weight: 600;
}

.footer-logo .logo-icon {
    width: 32px;
    height: 32px;
}

.footer-tagline {
    color: var(--text-subdued);
    font-size: 0.875rem;
    margin-bottom: var(--spacing-md);
}

.footer-social {
    display: flex;
    gap: var(--spacing-lg);
}

@media (max-width: 640px) {
    .footer-social {
        justify-content: center;
    }
}

.footer-social a {
    color: var(--text-subdued);
    transition: color var(--transition-fast);
}

.footer-social a:hover {
    color: var(--text-base);
}

.footer-social svg {
    width: 20px;
    height: 20px;
}

.footer-column h4 {
    font-size: 0.8125rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-subdued);
    margin-bottom: var(--spacing-md);
}

.footer-column a {
    display: block;
    color: var(--text-base);
    font-size: 0.875rem;
    margin-bottom: var(--spacing-sm);
    transition: color var(--transition-fast);
}

.footer-column a:hover {
    color: var(--accent-primary);
}

.footer-copyright {
    max-width: 1100px;
    margin: var(--spacing-xl) auto 0;
    padding-top: var(--spacing-lg);
    border-top: 1px solid var(--border-color);
    text-align: center;
    color: var(--text-subdued);
    font-size: 0.875rem;
}

/* ==========================================
   Landing Page
   Unified onto the same global tokens as the rest of the app (no more
   bespoke bronze/sage palette) - .landing-body just needed a few
   structural rules (hero blur-blobs, nav glass, pricing-card highlight)
   that reference the shared --accent-primary/--bg-base/etc. tokens
   directly rather than a separate override block.
   ========================================== */
.landing-body .section-eyebrow {
    display: block;
    text-align: center;
    font-family: var(--font-secondary);
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--accent-primary);
    margin-bottom: var(--spacing-sm);
}

.landing-nav-actions .btn-ghost {
    border: 2px solid var(--accent-primary);
    color: var(--accent-primary);
}

.landing-nav-actions .btn-ghost:hover {
    background: transparent;
    border-color: var(--accent-primary-hover);
    color: var(--accent-primary-hover);
}

.landing-body .lang-switch:hover {
    background: rgba(228, 68, 121, 0.12);
    color: var(--accent-primary);
}

.landing-body .hero {
    position: relative;
    overflow: hidden;
    isolation: isolate;
}

/* Soft washes via radial-gradient, not filter:blur on an 880px layer —
   a live gaussian blur that also scales is a known mobile GPU stall
   (Safari especially). Animation stays desktop-only. */
.landing-body .hero::before,
.landing-body .hero::after {
    content: '';
    position: absolute;
    z-index: -1;
    width: 42rem;
    height: 42rem;
    border-radius: 50%;
    pointer-events: none;
    transform-origin: center;
}

.landing-body .hero::before {
    top: -14rem;
    right: -10rem;
    background: radial-gradient(circle, rgba(228, 68, 121, 0.28) 0%, rgba(228, 68, 121, 0.08) 42%, transparent 70%);
}

.landing-body .hero::after {
    top: -18rem;
    left: -12rem;
    background: radial-gradient(circle, rgba(25, 25, 46, 0.10) 0%, transparent 70%);
}

@media (max-width: 1024px) {
    .landing-body .hero::before,
    .landing-body .hero::after {
        width: 22rem;
        height: 22rem;
    }
}

@keyframes hero-glow-pulse {
    0%, 100% {
        opacity: 0.75;
        transform: scale(1);
    }
    50% {
        opacity: 1;
        transform: scale(1.12);
    }
}

@media (prefers-reduced-motion: no-preference) and (min-width: 1025px) {
    .landing-body .hero::before,
    .landing-body .hero::after {
        animation: hero-glow-pulse 10s ease-in-out infinite;
    }
    .landing-body .hero::after {
        animation-delay: -5s;
    }
}

.landing-body .hero-title .highlight {
    color: var(--accent-primary);
}

.landing-body .hero-actions .btn-primary {
    box-shadow: 0 25px 50px -12px rgba(228, 68, 121, 0.35);
}

.landing-body .hero-actions .btn-ghost {
    border: 1px solid var(--border-color-light);
}

.landing-body .review-stars {
    color: var(--accent-primary);
}

.cta-microcopy,
.hero-trust-note {
    margin-top: var(--spacing-md);
    font-size: 0.8125rem;
    color: var(--text-subdued);
}

/* .cta's background is now the dark text-base slab (see .cta above) -
   text-subdued is tuned for a light surface and reads too low-contrast
   there, so this overrides to a translucent version of the slab's own
   inherited (light) text color instead. */
.cta .cta-microcopy {
    color: inherit;
    opacity: 0.6;
}

/* ==========================================
   Public Invitation Page
   ========================================== */
/* The ground behind the framed invitation card. --invitation-ground is
   minted per-invitation in public.html; the literal is only reached by the
   no-RSVP branch of that layout, which has no token block at all. */
.invitation-body {
    min-height: 100vh;
    min-height: 100dvh;
    background: var(--invitation-ground, var(--invitation-bg, #121212));
}

.invitation {
    min-height: 100vh;
    min-height: 100dvh;
}

/* Same breakpoint as sections.css's width cap: below it the invitation is
   full-bleed on a real phone and must not be inset. */
@media (min-width: 480px) {
    .invitation {
        padding-block: 2.5rem;
    }
}

/* Optional animated gradient background (RSVP.AnimatedGradientBg), tinted
   with the couple's own --invitation-gradient-color (RSVP.GradientColor -
   a dedicated color, separate from --invitation-highlight, since the
   accent color is reserved for accents/actionable elements and a couple
   may want a different mood for the gradient wash than for their accent).
   color-mix against --invitation-bg keeps it working for any of the 12
   templates, light or dark. A slow background-position drift reads as a
   gentle color wash rather than a distracting animation. */
.invitation-animated-bg {
    background: linear-gradient(
        120deg,
        var(--invitation-bg),
        color-mix(in srgb, var(--invitation-gradient-color) 22%, var(--invitation-bg)),
        var(--invitation-bg),
        color-mix(in srgb, var(--invitation-gradient-color) 14%, var(--invitation-bg))
    );
    background-size: 300% 300%;
    animation: invitation-gradient-shift 22s ease-in-out infinite;
}

@keyframes invitation-gradient-shift {
    0% { background-position: 0% 50%; }
    50% { background-position: 100% 50%; }
    100% { background-position: 0% 50%; }
}

@media (prefers-reduced-motion: reduce) {
    .invitation-animated-bg {
        animation: none;
    }
}

.invitation-hero {
    position: relative;
    min-height: 50vh;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

.invitation-decoration {
    position: absolute;
    width: 160px;
    pointer-events: none;
    z-index: 1;
}

.invitation-decoration-shape {
    display: block;
    width: 100%;
    height: 100%;
    -webkit-mask-size: contain;
    mask-size: contain;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
}

/* Editor-only interactive layer: injected by app.js as a sibling overlay
   that tracks each decoration's position/rotation/scale. Kept separate
   from .invitation-decoration itself (and its low z-index) so the click
   target and drag handles stay reachable even when the decoration is
   layered behind text or another decoration in the actual design. */
.invitation-decoration-controls {
    position: absolute;
    width: 160px;
    z-index: 30;
    pointer-events: auto;
    cursor: grab;
    touch-action: none;
}

.invitation-decoration-controls:active {
    cursor: grabbing;
}

.invitation-decoration-controls.deco-selected {
    outline: 2px dashed var(--accent-primary);
    outline-offset: 6px;
}

.invitation-decoration-remove {
    position: absolute;
    top: -10px;
    right: -10px;
    width: 24px;
    height: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--essential-negative);
    color: var(--text-base);
    border-radius: var(--radius-full);
    box-shadow: var(--shadow-sm);
    pointer-events: auto;
}

.invitation-decoration-remove svg {
    width: 14px;
    height: 14px;
}

.invitation-decoration-handle {
    position: absolute;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    background: var(--accent-primary);
    color: var(--text-base);
    border: 2px solid var(--bg-base);
    border-radius: var(--radius-full);
    box-shadow: var(--shadow-sm);
    touch-action: none;
    pointer-events: auto;
}

.invitation-decoration-handle svg {
    width: 13px;
    height: 13px;
}

.invitation-decoration-handle-rotate {
    top: -34px;
    left: 50%;
    cursor: grab;
}

.invitation-decoration-handle-scale {
    bottom: -11px;
    right: -11px;
    cursor: nwse-resize;
}

.invitation-hero-content {
    position: relative;
    z-index: 2;
    text-align: center;
    padding: var(--spacing-2xl);
    max-width: 800px;
}

@media (max-width: 480px) {
    .invitation-hero-content {
        padding: var(--spacing-xl) var(--spacing-lg);
    }
}

.invitation-hero-bordered {
    margin: var(--spacing-lg);
}

@media (max-width: 480px) {
    .invitation-hero-bordered {
        margin: var(--spacing-sm);
    }
}

.invitation-emblem {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--spacing-md);
    margin-bottom: var(--spacing-lg);
}

.emblem-amp {
    font-size: 0.6em;
}

.invitation-title {
    margin-bottom: var(--spacing-lg);
}

.invitation-quote {
    font-style: italic;
    opacity: 0.9;
    max-width: 500px;
    margin: 0 auto;
}

.invitation-quote cite {
    display: block;
    margin-top: var(--spacing-sm);
    font-size: 0.875em;
    opacity: 0.8;
}

.invitation-photo-wrap {
    display: flex;
    justify-content: center;
    margin-bottom: var(--spacing-lg);
}

.invitation-photo-wrap-left {
    justify-content: flex-start;
}

.invitation-photo {
    width: 140px;
    height: 140px;
    border-radius: 50%;
    object-fit: cover;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.35);
}

.invitation-photo-sm {
    width: 100px;
    height: 100px;
}

.invitation-content {
    padding: var(--spacing-2xl);
    max-width: 800px;
    margin: 0 auto;
}

@media (max-width: 480px) {
    .invitation-content {
        padding: var(--spacing-sm);
    }

    .invitation-rsvp {
        padding: var(--spacing-md);
    }
}

.invitation-countdown {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--spacing-lg);
    padding: var(--spacing-2xl) 0;
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
    margin-bottom: var(--spacing-2xl);
}

.countdown-item {
    text-align: center;
    min-width: 56px;
}

.countdown-value {
    display: block;
    font-size: 2.5rem;
    font-weight: 700;
    line-height: 1;
    margin-bottom: var(--spacing-xs);
}

.countdown-label {
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    opacity: 0.7;
}

@media (max-width: 480px) {
    .invitation-countdown {
        gap: var(--spacing-md);
        padding: var(--spacing-xl) 0;
    }

    .countdown-value {
        font-size: 1.75rem;
    }
}

.countdown-passed {
    font-size: 1.25rem;
    color: var(--accent-primary);
}

.invitation-details {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    gap: var(--spacing-lg);
    margin-bottom: var(--spacing-2xl);
}

.detail-card {
    display: flex;
    align-items: flex-start;
    gap: var(--spacing-md);
    padding: var(--spacing-lg);
    background: rgba(255, 255, 255, 0.05);
    border-radius: var(--radius-lg);
}

.detail-icon {
    width: 48px;
    height: 48px;
    background: rgba(255, 255, 255, 0.1);
    border-radius: var(--radius-md);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.detail-icon svg {
    width: 24px;
    height: 24px;
}

.detail-label {
    display: block;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    opacity: 0.7;
    margin-bottom: var(--spacing-xs);
}

.detail-value {
    display: block;
    font-size: 1.125rem;
    font-weight: 500;
}

.detail-subvalue {
    display: block;
    font-size: 0.875rem;
    opacity: 0.7;
}

.invitation-message {
    text-align: center;
    padding: var(--spacing-xl);
    background: rgba(255, 255, 255, 0.05);
    border-radius: var(--radius-lg);
    margin-bottom: var(--spacing-2xl);
}

.invitation-timeline {
    margin-bottom: var(--spacing-2xl);
}

.timeline-title {
    text-align: center;
    margin-bottom: var(--spacing-xl);
    font-size: 1.5rem;
}

.invitation-map {
    height: 300px;
    background: var(--bg-highlight);
    border-radius: var(--radius-lg);
    margin-bottom: var(--spacing-2xl);
    overflow: hidden;
}

.map-placeholder {
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--spacing-sm);
    color: var(--text-subdued);
}

.map-canvas {
    width: 100%;
    height: 100%;
}

/* Google renders the marker InfoWindow bubble into its own DOM classes we
   don't control the markup of, so theming it means targeting those
   classes directly rather than styling our own content wrapper - the
   bubble background (gm-style-iw-c) and its tail/pointer triangle
   (gm-style-iw-t::after) both need the same color to read as one shape. */
.gm-style .gm-style-iw-c {
    background: var(--invitation-bg, #121212);
    border-radius: var(--radius-md);
}

.gm-style .gm-style-iw-t::after {
    background: var(--invitation-bg, #121212);
}

.gm-style .gm-style-iw-d {
    color: var(--invitation-text, #ffffff);
}

.gm-style .gm-style-iw-d a {
    color: var(--invitation-highlight, var(--accent-primary));
}

.map-placeholder svg {
    width: 48px;
    height: 48px;
}

.invitation-rsvp {
    background: rgba(255, 255, 255, 0.05);
    border-radius: var(--radius-xl);
    padding: var(--spacing-2xl);
}

.invitation-rsvp.inactive {
    text-align: center;
    opacity: 0.7;
}

.rsvp-title {
    text-align: center;
    margin-bottom: var(--spacing-sm);
}

.rsvp-subtitle {
    text-align: center;
    opacity: 0.8;
    margin-bottom: var(--spacing-xl);
}

.rsvp-inactive-message {
    opacity: 0.8;
}

.rsvp-form {
    max-width: 500px;
    margin: 0 auto;
}

.rsvp-form .form-group label {
    color: inherit;
}

.rsvp-form input,
.rsvp-form input[type="text"],
.rsvp-form input[type="email"],
.rsvp-form input[type="tel"],
.rsvp-form textarea {
    background: rgba(255, 255, 255, 0.1);
    border-color: var(--invitation-text, var(--text-base));
    color: inherit;
}

.rsvp-form input::placeholder,
.rsvp-form textarea::placeholder {
    color: var(--invitation-text, var(--text-base));
}

.rsvp-form input:focus,
.rsvp-form textarea:focus {
    border-color: var(--invitation-text, var(--text-base));
    box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.1);
}

.rsvp-form .radio-label {
    background: rgba(255, 255, 255, 0.05);
    border-color: var(--invitation-text, var(--text-base));
}

.rsvp-form .radio-label:hover {
    border-color: var(--invitation-text, var(--text-base));
}

.rsvp-form .radio-custom,
.rsvp-form .checkbox-custom {
    border-color: var(--invitation-text, var(--text-base));
}

.rsvp-form .radio-label input:checked + .radio-custom {
    border-color: var(--invitation-highlight, var(--accent-primary));
}

.rsvp-form .radio-label input:checked + .radio-custom::after,
.rsvp-form .checkbox-label input:checked + .checkbox-custom {
    background: var(--invitation-highlight, var(--accent-primary));
}

.rsvp-form .checkbox-label input:checked + .checkbox-custom {
    border-color: var(--invitation-highlight, var(--accent-primary));
}

.rsvp-form .btn-ghost {
    color: var(--invitation-text, var(--text-base));
}

.additional-guests-section {
    margin-bottom: var(--spacing-lg);
}

.additional-guests-section .section-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: var(--spacing-md);
    font-size: 0.875rem;
    font-weight: 500;
}

.additional-guest-input {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    margin-bottom: var(--spacing-sm);
}

.additional-guest-input input {
    flex: 1;
    min-width: 0;
    padding: var(--spacing-md);
    background: rgba(255, 255, 255, 0.1);
    border: 1px solid rgba(255, 255, 255, 0.2);
    border-radius: var(--radius-md);
    color: inherit;
    font-size: 1rem;
    transition: all var(--transition-fast);
}

.additional-guest-input input::placeholder {
    color: rgba(255, 255, 255, 0.5);
}

.additional-guest-input input:focus {
    outline: none;
    border-color: var(--invitation-highlight, var(--accent-primary));
    box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.1);
}

.timeline-item-input {
    padding: var(--spacing-md);
    margin-bottom: var(--spacing-sm);
    background: var(--bg-elevated);
    border-radius: var(--radius-md);
}

.timeline-item-fields {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
}

.timeline-item-fields input[type="text"] {
    width: 100%;
    min-width: 0;
    padding: var(--spacing-md);
    background: var(--bg-highlight);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    color: var(--text-base);
    font-size: 1rem;
    transition: all var(--transition-fast);
}

/* Google Places dropdown is appended to <body>, outside .inv-canvas. */
.pac-container {
    z-index: 1100;
}

.timeline-item-fields input[type="text"]:focus {
    outline: none;
    border-color: var(--accent-primary);
}

.timeline-item-fields input[type="text"]::placeholder {
    color: var(--text-subdued);
}

.timeline-item-row-bottom {
    display: flex;
    align-items: stretch;
    gap: var(--spacing-sm);
}

.timeline-item-row-bottom input[type="text"] {
    flex: 1;
    min-width: 0;
}

.timeline-item-row-bottom .icon-picker {
    flex-shrink: 0;
    width: 52px;
}

.timeline-item-row-bottom .btn-danger {
    width: 44px;
    height: 44px;
    padding: 0;
    flex-shrink: 0;
    align-self: center;
}

.icon-picker {
    position: relative;
}

.icon-picker-trigger {
    width: 100%;
    height: 100%;
    min-height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.25rem;
    background: var(--bg-highlight);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    color: var(--text-subdued);
    transition: background var(--transition-fast);
}

.icon-picker-trigger:hover {
    background: var(--bg-card-hover);
}

.icon-picker-swatch {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    -webkit-mask-size: contain;
    mask-size: contain;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
}

.icon-picker-modal-overlay .modal {
    max-width: 720px;
}

.icon-picker-filters {
    display: flex;
    gap: var(--spacing-sm);
    margin-bottom: var(--spacing-md);
}

.icon-picker-filters select {
    flex: 1;
    padding: var(--spacing-sm) var(--spacing-md);
    background: var(--bg-highlight);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    color: var(--text-base);
}

.icon-picker-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(48px, 1fr));
    gap: var(--spacing-sm);
    max-height: 340px;
    overflow-y: auto;
    padding: var(--spacing-xs);
    margin-bottom: var(--spacing-md);
}

.icon-picker-grid-item {
    aspect-ratio: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--spacing-sm);
    background: var(--bg-highlight);
    border-radius: var(--radius-md);
    border: 1px solid var(--border-color);
    transition: transform var(--transition-fast), border-color var(--transition-fast);
}

.icon-picker-grid-item:hover {
    transform: translateY(-2px);
    border-color: var(--accent-primary);
}

.icon-picker-grid-shape {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: contain;
    /* Black by default (light theme's --bg-highlight is light gray);
       inverted to white in dark mode below, where --bg-highlight is dark. */
    filter: brightness(0);
}

[data-theme="dark"] .icon-picker-grid-shape {
    filter: brightness(0) invert(1);
}

.icon-picker-inspector {
    display: flex;
    gap: var(--spacing-lg);
    flex-wrap: wrap;
    padding: var(--spacing-md);
    background: var(--bg-highlight);
    border-radius: var(--radius-md);
}

.icon-picker-inspector label {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    font-size: 0.875rem;
    color: var(--text-subdued);
}

/* ==========================================
   Invitation Decorations (drag/scale/rotate SVGs
   directly on the live preview iframe)
   ========================================== */
.decoration-editor {
    display: grid;
    grid-template-columns: minmax(220px, 320px) 1fr;
    gap: var(--spacing-lg);
    align-items: start;
}

@media (max-width: 900px) {
    .decoration-editor {
        grid-template-columns: 1fr;
    }
}





.decoration-palette-shape {
    display: block;
    width: 100%;
    height: 100%;
    background-color: #2b2b2b;
    -webkit-mask-size: contain;
    mask-size: contain;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
}

.decoration-preview {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
    position: sticky;
    top: var(--spacing-lg);
}

.decoration-preview-frame {
    width: 100%;
    height: 600px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    background: var(--bg-base);
}

.invitation-footer {
    text-align: center;
    padding: var(--spacing-xl);
    opacity: 0.5;
    font-size: 0.75rem;
}

.invitation-footer a {
    color: inherit;
    text-decoration: underline;
}

/* ==========================================
   Modal
   ========================================== */
.modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.8);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--spacing-lg);
    z-index: 200;
    animation: fadeIn 0.2s ease;
}

@keyframes fadeIn {
    from { opacity: 0; }
}

.modal {
    background: var(--bg-elevated);
    border-radius: var(--radius-xl);
    width: 100%;
    max-width: 500px;
    max-height: 90vh;
    overflow-y: auto;
    animation: slideUp 0.3s ease;
}

.modal-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: var(--spacing-lg);
    border-bottom: 1px solid var(--border-color);
}

.modal-title {
    font-size: 1.25rem;
}

.modal-close {
    width: 32px;
    height: 32px;
    border-radius: var(--radius-full);
    color: var(--text-subdued);
    transition: all var(--transition-fast);
}

.modal-close:hover {
    background: var(--bg-highlight);
    color: var(--text-base);
}

.modal-close svg {
    width: 100%;
    height: 100%;
}

.modal-body {
    padding: var(--spacing-lg);
}

.modal-footer {
    display: flex;
    justify-content: flex-end;
    gap: var(--spacing-sm);
    padding: var(--spacing-lg);
    border-top: 1px solid var(--border-color);
}

/* ==========================================
   Utilities
   ========================================== */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.hidden {
    display: none !important;
}

.htmx-indicator {
    display: none;
}

.htmx-request .htmx-indicator {
    display: inline;
}

.htmx-request.htmx-indicator {
    display: inline;
}

/* ==========================================
   Admin templates: "clone from event" picker
   ========================================== */
.event-picker {
    position: relative;
}

.event-picker-results {
    position: relative;
    z-index: 5;
    display: flex;
    flex-direction: column;
    gap: 2px;
    max-height: 260px;
    overflow-y: auto;
    margin-top: var(--spacing-xs);
}

.event-picker-results:empty {
    margin-top: 0;
}

.event-picker-result {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    width: 100%;
    padding: var(--spacing-sm) var(--spacing-md);
    background: var(--bg-elevated);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    text-align: left;
    cursor: pointer;
    transition: border-color var(--transition-fast);
}

.event-picker-result:hover {
    border-color: var(--accent-primary);
}

.event-picker-result strong {
    font-size: 0.9rem;
}

.event-picker-result span {
    font-size: 0.78rem;
    color: var(--text-subdued);
}

.event-picker-empty {
    padding: var(--spacing-sm) var(--spacing-md);
    color: var(--text-subdued);
    font-size: 0.85rem;
}

.event-picker-selected {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-sm);
    margin-top: var(--spacing-xs);
    padding: var(--spacing-sm) var(--spacing-md);
    background: var(--bg-highlight);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
}

/* ==========================================
   Legal pages (impressum, and the privacy/terms
   pages once their text exists). Rendered in the
   landing layout, so they inherit its palette.
   ========================================== */
.legal-page {
    padding: calc(var(--topbar-height, 64px) + var(--spacing-3xl)) var(--spacing-lg) var(--spacing-3xl);
}

.legal-container {
    max-width: 720px;
    margin: 0 auto;
}

.legal-title {
    font-family: var(--font-display);
    margin-bottom: var(--spacing-sm);
}

.legal-subtitle {
    font-family: var(--font-display);
    margin: var(--spacing-2xl) 0 var(--spacing-sm);
}

.legal-intro {
    color: var(--text-subdued);
    margin-bottom: var(--spacing-2xl);
}

/* Long-form documents (privacy, terms + DPA annex, cookies). These are
   the only pages in the app with real prose, so they get element
   selectors - scoped under .legal-prose so nothing leaks into the
   dashboard or an invitation section. */
.legal-prose p,
.legal-prose li {
    line-height: 1.7;
    margin-bottom: var(--spacing-md);
}

.legal-prose ul,
.legal-prose ol {
    padding-left: var(--spacing-lg);
    margin-bottom: var(--spacing-md);
}

.legal-prose li {
    margin-bottom: var(--spacing-xs);
}

.legal-heading {
    font-family: var(--font-display);
    font-size: 1.05rem;
    margin: var(--spacing-xl) 0 var(--spacing-sm);
}

.legal-rule {
    border: 0;
    border-top: 1px solid var(--border-subtle, rgba(0, 0, 0, 0.12));
    margin: var(--spacing-3xl) 0 var(--spacing-2xl);
}

.legal-prose code {
    font-size: 0.9em;
    padding: 0.1em 0.35em;
    border-radius: var(--radius-sm, 4px);
    background: rgba(0, 0, 0, 0.06);
}

/* Tables carry the sub-processor and legal-basis lists, which are wider
   than a phone. The wrapper scrolls, never the page body. */
.legal-table-wrap {
    overflow-x: auto;
    margin-bottom: var(--spacing-lg);
}

.legal-table {
    border-collapse: collapse;
    width: 100%;
    min-width: 32rem;
    font-size: 0.95rem;
}

.legal-table th,
.legal-table td {
    border: 1px solid var(--border-subtle, rgba(0, 0, 0, 0.12));
    padding: var(--spacing-sm);
    text-align: left;
    vertical-align: top;
}

.legal-table th {
    font-weight: 600;
    background: rgba(0, 0, 0, 0.03);
}

.legal-dl {
    display: grid;
    grid-template-columns: minmax(0, 14rem) 1fr;
    gap: var(--spacing-sm) var(--spacing-lg);
    margin: 0;
}

.legal-dl dt {
    color: var(--text-subdued);
    font-weight: 500;
}

.legal-dl dd {
    margin: 0;
}

@media (max-width: 640px) {
    .legal-dl {
        grid-template-columns: 1fr;
        gap: 0;
    }

    .legal-dl dd {
        margin-bottom: var(--spacing-md);
    }
}

/* Failure reason under a /health row - e.g. the SMTP relay's rejection
   message, which used to be visible only in container logs. */
.health-detail {
    margin-top: calc(-1 * var(--spacing-sm));
}

.health-detail-text {
    font-family: var(--font-mono, ui-monospace, monospace);
    font-size: 0.78rem;
    color: var(--essential-negative);
    word-break: break-word;
}

/* Admin pricing rows */
.admin-pricing-row {
    padding: var(--spacing-lg) 0;
    border-bottom: 1px solid var(--border-color);
}

.admin-pricing-row:last-child {
    border-bottom: none;
}

.admin-pricing-name {
    font-family: var(--font-display);
    font-size: 1.05rem;
    margin: 0 0 var(--spacing-sm);
}

.admin-pricing-actions {
    display: flex;
    align-items: flex-end;
}

.admin-pricing-mono {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.78rem;
    color: var(--text-subdued);
    word-break: break-all;
}

/* ==========================================
   Create-flow stepper
   Shown on the four pages of the invitation create flow only. Deliberately
   plain: it is orientation, not decoration, and it sits above content that
   is already visually busy.
   ========================================== */
.wizard-steps {
    display: flex;
    align-items: center;
    gap: var(--spacing-xs);
    list-style: none;
    margin: 0 0 var(--spacing-lg);
    padding: 0;
    overflow-x: auto;
}

.wizard-step {
    display: flex;
    align-items: center;
    gap: var(--spacing-xs);
    flex: none;
    padding: 6px 12px;
    border-radius: var(--radius-full);
    color: var(--text-subdued);
    font-size: 0.8125rem;
    white-space: nowrap;
}

.wizard-step-num {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    flex: none;
    border-radius: 50%;
    border: 1px solid currentColor;
    font-size: 0.75rem;
}

.wizard-step.is-current {
    background: var(--bg-elevated);
    color: var(--text-base);
}

.wizard-step.is-current .wizard-step-num {
    background: var(--accent-primary);
    border-color: var(--accent-primary);
    color: #fff;
}

.wizard-step.is-done .wizard-step-num {
    border-color: var(--accent-primary);
    color: var(--accent-primary);
}

/* The labels are the first thing worth dropping on a narrow screen - the
   numbered dots still communicate position. */
@media (max-width: 640px) {
    .wizard-step-label { display: none; }
    .wizard-step { padding: 6px; }
}

/* ==========================================
   Template preview bar (/templates/{key})
   ==========================================
   Pinned to the bottom of a public template preview. Deliberately outside
   .invitation so it paints from the dashboard tokens rather than the
   template's --sec-* palette: it is our chrome, not part of the design
   being previewed, and it has to stay legible on a near-black template as
   well as a cream one. */
.tpl-preview-bar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 60;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 12px 20px calc(12px + env(safe-area-inset-bottom, 0px));
    background: var(--bg-surface, #fff);
    border-top: 1px solid var(--border-subtle, #e5e0d8);
    box-shadow: 0 -8px 24px -18px rgba(0, 0, 0, 0.5);
}
.tpl-preview-bar-text { display: grid; gap: 2px; min-width: 0; }
.tpl-preview-bar-eyebrow {
    font-size: 0.68rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--text-subdued, #666);
}
.tpl-preview-bar-name { font-size: 1rem; color: var(--text-base, #1a1a1a); }
.tpl-preview-bar-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.tpl-preview-bar-actions .btn { min-height: 40px; }
/* The bar overlays the closing section, which is the one place an
   invitation deliberately ends in air. Give the page room to scroll past
   it so nothing is left permanently hidden underneath. */
body:has(.tpl-preview-bar) .inv-footer { padding-bottom: 96px; }
