* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

@keyframes highlight-flash {
    0% {
        outline-color: transparent;
        box-shadow: none;
    }
    10%, 80% {
        outline-color: var(--primary-color);
        box-shadow: 0 0 15px rgba(124, 58, 237, 0.5);
    }
    100% {
        outline-color: transparent;
        box-shadow: none;
    }
}

.task-highlight {
    outline: 3px solid transparent;
    outline-offset: 4px;
    animation: highlight-flash 4s ease-out;
    position: relative;
    z-index: 1;
    border-radius: 8px;
}

/* (2026-09-27, device repro - a comment-match search result used to highlight the whole Entry
   instead of the matched comment): same animation as .task-highlight above (shares the
   highlight-flash keyframe), scoped to one comment row instead of the whole card. */
.comment-highlight {
    outline: 3px solid transparent;
    outline-offset: 2px;
    animation: highlight-flash 4s ease-out;
    position: relative;
    z-index: 1;
    border-radius: 8px;
}

/* (2026-09-27, "the exact same issue needs to be addressed with photo searches"): same treatment,
   scoped to one photo's .attachment-container instead of the whole card. */
.photo-highlight {
    outline: 3px solid transparent;
    outline-offset: 2px;
    animation: highlight-flash 4s ease-out;
    position: relative;
    z-index: 1;
    border-radius: 8px;
}

/* Deleted item toast message */
.deleted-item-toast {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.5);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 2000;
}

.deleted-item-message {
    background: white;
    padding: 32px;
    border-radius: 16px;
    text-align: center;
    max-width: 400px;
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
}

.deleted-item-message .deleted-icon {
    font-size: 3rem;
    display: block;
    margin-bottom: 16px;
}

.deleted-item-message p {
    color: var(--text-color);
    margin-bottom: 12px;
    line-height: 1.5;
}

.deleted-item-message .deleted-item-title {
    color: var(--primary-color);
    font-weight: 600;
    font-style: italic;
}

:root {
    --primary-color: #7c3aed;
    --primary-hover: #6d28d9;
    --bg-color: #f8fafc;
    --sidebar-bg: #1e1b4b;
    --sidebar-text: #e2e8f0;
    --card-bg: #ffffff;
    --text-color: #1e293b;
    --text-muted: #64748b;
    --border-color: #e2e8f0;
    --success-color: #10b981;
    --danger-color: #ef4444;
    --hover-bg: rgba(255, 255, 255, 0.1);
}

body {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
    background-color: var(--bg-color);
    color: var(--text-color);
    line-height: 1.5;
    /* 🔒 FIX (2026-09-28, device repro with a screen recording - "entry cards slide side to
       side... should just be fixed in place"): confirmed via frame-by-frame inspection of the
       recording that this is NOT a CSS layout bug - the entire page (avatar, card, everything)
       moves as one perfectly rigid unit and holds exactly wherever the finger stops, which is how
       the BROWSER'S OWN native "swipe from the edge to go back" gesture preview behaves (both
       Safari and Chrome on iOS have this built in), not how an overflow/scroll CSS bug behaves -
       nothing in render.js/style.css was ever doing this. overscroll-behavior-x is the standard,
       documented way to opt the page out of that gesture being triggered by page content.
       overscroll-behavior-y stays default (auto) - pull-to-refresh/vertical rubber-banding is
       unrelated and untouched. */
    overscroll-behavior-x: none;
}

/* Loading Screen */
.loading-screen {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: linear-gradient(135deg, var(--sidebar-bg) 0%, #312e81 100%);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 4000;
}

.loading-screen.hidden {
    display: none;
}

.loading-spinner {
    font-size: 4rem;
    animation: pulse 1.5s ease-in-out infinite;
}

@keyframes pulse {
    0%, 100% { transform: scale(1); opacity: 1; }
    50% { transform: scale(1.2); opacity: 0.7; }
}

/* Login Screen */
.login-screen {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: linear-gradient(135deg, var(--sidebar-bg) 0%, #312e81 100%);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 3000;
}

.login-screen.hidden {
    display: none;
}

.login-container {
    background: var(--card-bg);
    padding: 20px 28px;
    border-radius: 16px;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
    width: 100%;
    max-width: 380px;
    max-height: 90vh;
    overflow-y: auto;
    text-align: center;
}

.login-container h1 {
    font-size: 1.3rem;
    margin-bottom: 10px;
    color: var(--text-color);
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
}

.login-container h1 .login-icon {
    font-size: 2rem;
}

.login-container h1 .login-subtitle {
    font-size: 2.5rem;
    font-weight: 700;
    background: linear-gradient(135deg, #7c3aed, #ec4899);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
}

/* Login Logo */
.login-logo {
    text-align: center;
    margin-bottom: 12px;
}

.login-logo-img {
    max-width: 80px;
    max-height: 80px;
}

.auth-form {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.auth-form input {
    padding: 8px 12px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    font-size: 0.95rem;
    transition: border-color 0.15s;
    width: 100%;
    box-sizing: border-box;
    background-color: #ffffff !important;
    color: #1e293b !important;
    -webkit-text-fill-color: #1e293b !important;
}

.auth-form input::placeholder {
    color: #94a3b8;
    -webkit-text-fill-color: #94a3b8;
}

.auth-form .form-group {
    display: flex;
    flex-direction: column;
    gap: 0;
}

/* Group name section - centered and prominent */
.group-name-section {
    text-align: center;
    margin-bottom: 8px;
}

.group-name-section label {
    display: block;
    font-size: 1rem;
    font-weight: 600;
    color: var(--text-color);
    margin-bottom: 8px;
}

.group-name-section input {
    font-size: 1.25rem;
    text-align: center;
    padding: 16px 20px;
    font-weight: 500;
}

.field-hint {
    font-size: 0.75rem;
    color: var(--text-muted);
    margin-top: 6px;
    font-style: italic;
}

.group-name-preview {
    font-size: 0.9rem;
    color: #e2e8f0;
    margin-top: 12px;
    font-weight: 500;
    padding: 12px 16px;
    background: var(--sidebar-bg);
    border-radius: 8px;
    text-align: center;
}

/* User info section - left aligned */
.user-info-section {
    text-align: left;
}

.user-info-section .form-group {
    margin-bottom: 2px;
}

.optional-label {
    font-weight: 400;
    color: var(--text-muted);
    font-size: 0.8rem;
}

/* Headshot upload in registration forms */
.headshot-upload-section {
    text-align: center;
    margin-bottom: 4px;
}

.headshot-upload-section label {
    display: block;
    font-size: 0.8rem;
    font-weight: 500;
    color: var(--text-color);
    margin-bottom: 4px;
}

.registration-headshot-preview {
    width: 50px;
    height: 50px;
    border-radius: 50%;
    margin: 0 auto;
    position: relative;
    cursor: pointer;
    overflow: hidden;
    background: var(--bg-color);
    border: 2px dashed var(--border-color);
    transition: border-color 0.2s;
}

.registration-headshot-preview:hover,
.registration-headshot-preview.drag-over {
    border-color: var(--primary-color);
    border-style: solid;
}

.registration-headshot-placeholder {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.5rem;
    color: var(--text-muted);
    pointer-events: none;
}

.registration-headshot-preview img {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    pointer-events: none;
    z-index: 1;
}

.registration-headshot-overlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.5);
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    transition: opacity 0.2s;
    border-radius: 50%;
    pointer-events: none;
    z-index: 2;
}

.registration-headshot-preview:hover .registration-headshot-overlay,
.registration-headshot-preview.drag-over .registration-headshot-overlay {
    opacity: 1;
}

.registration-headshot-overlay span {
    color: white;
    font-size: 0.7rem;
    text-align: center;
}

.user-info-section label {
    display: block;
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--text-muted);
    margin-bottom: 4px;
}

/* Form row for side-by-side fields */
.form-row {
    display: flex;
    gap: 12px;
}

.form-row .form-group {
    flex: 1;
}

/* Primary button style */
.primary-btn {
    padding: 16px 24px !important;
    font-size: 1.1rem !important;
    font-weight: 700 !important;
    background: linear-gradient(135deg, var(--primary-color), #ec4899) !important;
    border: none;
    border-radius: 8px;
    color: white;
    cursor: pointer;
    transition: transform 0.15s, box-shadow 0.15s;
    margin-top: 16px !important;
    width: 100%;
    text-align: center;
}

.primary-btn:hover {
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(124, 58, 237, 0.3);
}

/* Registration success state */
.create-success {
    text-align: center;
    padding: 16px 0;
}

.create-success .success-icon {
    width: 48px;
    height: 48px;
    background: linear-gradient(135deg, #10b981, #34d399);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0 auto 12px;
    font-size: 1.5rem;
    color: white;
}

.create-success h3 {
    font-size: 1.25rem;
    margin-bottom: 8px;
    color: var(--text-color);
}

.create-success .success-message {
    font-size: 0.9rem;
    color: var(--text-muted);
    margin-bottom: 12px;
}

.create-success .success-message span {
    font-weight: 600;
    color: var(--text-color);
}

.create-success .invite-link-container {
    display: flex;
    gap: 8px;
    margin-bottom: 8px;
}

.create-success .invite-link-container input {
    flex: 1;
    padding: 10px 12px;
    font-size: 0.85rem;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: var(--bg-color);
    color: var(--text-color);
}

.create-success .copy-feedback {
    font-size: 0.8rem;
    color: #10b981;
    margin-bottom: 8px;
}

.auth-form input:focus {
    outline: none;
    border-color: var(--primary-color);
}

.password-input-wrapper {
    position: relative;
    display: flex;
    align-items: center;
}

.password-input-wrapper input {
    flex: 1;
    padding-right: 45px !important;
}

/* Override browser autofill styling */
.auth-form input:-webkit-autofill,
.auth-form input:-webkit-autofill:hover,
.auth-form input:-webkit-autofill:focus,
.auth-form input:-webkit-autofill:active {
    -webkit-box-shadow: 0 0 0 30px white inset !important;
    box-shadow: 0 0 0 30px white inset !important;
    -webkit-text-fill-color: var(--text-color) !important;
}

.toggle-password-btn {
    position: absolute;
    right: 8px;
    background: none !important;
    border: none;
    cursor: pointer;
    font-size: 1.2rem;
    opacity: 0.6;
    transition: opacity 0.15s;
    padding: 4px 8px !important;
    width: auto !important;
    margin: 0 !important;
    transform: none !important;
    box-shadow: none !important;
}

.toggle-password-btn:hover {
    opacity: 1;
    transform: none !important;
    box-shadow: none !important;
}

/* Submit buttons only - not toggle buttons */
.auth-form > button[type="button"],
.user-info-section + button[type="button"] {
    padding: 10px 16px;
    border: none;
    border-radius: 8px;
    background: var(--primary-color);
    color: white;
    font-size: 1.1rem;
    font-weight: 700;
    cursor: pointer;
    transition: background-color 0.15s, color 0.15s;
    letter-spacing: 0.5px;
    width: 100%;
    margin-top: 6px;
}

/* Submit button hover - exclude toggle buttons */
.auth-form > button[type="button"]:hover,
.user-info-section + button[type="button"]:hover,
#login-btn:hover,
#create-group-btn:hover,
#join-group-btn:hover {
    background: var(--primary-hover);
    color: #f5f3ff;
}

/* Form field grouping */
.auth-form .form-group {
    margin-bottom: 6px;
}

.auth-form .form-group label {
    display: block;
    font-size: 0.8rem;
    font-weight: 500;
    color: var(--text-muted);
    margin-bottom: 3px;
}

.auth-form .form-divider {
    border-top: 1px solid var(--border-color);
    margin: 20px 0;
    position: relative;
}

.auth-form .form-divider span {
    position: absolute;
    top: -10px;
    left: 50%;
    transform: translateX(-50%);
    background: var(--card-bg);
    padding: 0 12px;
    font-size: 0.8rem;
    color: var(--text-muted);
}

.login-error {
    color: var(--danger-color);
    font-size: 0.875rem;
    min-height: 20px;
}

/* Auth Tabs */
.auth-tabs {
    display: flex;
    gap: 0;
    margin-bottom: 24px;
    border-radius: 8px;
    overflow: hidden;
    border: 1px solid var(--border-color);
}

.auth-tab {
    flex: 1;
    padding: 12px 16px;
    border: none;
    background: var(--bg-color);
    color: var(--text-muted);
    font-size: 0.9rem;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.2s;
}

.auth-tab:hover {
    background: var(--border-color);
}

.auth-tab.active {
    background: var(--primary-color);
    color: white;
}

.auth-form.hidden {
    display: none;
}

.invite-message {
    text-align: center;
    color: var(--primary-color);
    font-weight: 500;
    margin-bottom: 16px;
}

.app-container {
    display: flex;
    height: 100vh;
}

/* Sidebar Styles */
.sidebar {
    width: 280px;
    background: var(--sidebar-bg);
    color: var(--sidebar-text);
    display: flex;
    flex-direction: column;
    flex-shrink: 0;
}

.sidebar-header {
    padding: 20px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    flex-wrap: wrap;
}

.us-logo {
    font-size: 1.1rem;
    font-weight: 700;
    flex-shrink: 0;
    background: linear-gradient(135deg, #ec4899, #a855f7);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
    display: flex;
    flex-direction: column;
    align-items: center;
    line-height: 1;
}

.us-logo-hearts {
    font-size: 1.3rem;
    line-height: 1;
}

.us-logo-text {
    font-size: 1rem;
    letter-spacing: 0.05em;
}

.sidebar-header h1 {
    font-size: 1.5rem;
    font-weight: 600;
    line-height: 1.3;
    text-align: center;
    flex: 1;
    min-width: 0;
}

.sidebar-subtitle {
    display: block;
    font-size: 0.8rem;
    font-weight: 400;
    opacity: 0.85;
    margin-top: 2px;
}



.header-photo-container {
    position: relative;
    margin-top: 0;
    cursor: pointer;
    width: 100%;
}

.header-photo {
    width: 100%;
    max-height: 150px;
    object-fit: cover;
    border-radius: 8px;
}

.header-photo-overlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.5);
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    transition: opacity 0.2s;
    color: white;
    font-size: 0.9rem;
}

.header-photo-container:hover .header-photo-overlay,
.header-photo-container.drag-over .header-photo-overlay {
    opacity: 1;
}

.lists-section {
    flex: 1;
    padding: 20px;
    overflow-y: auto;
}

.lists-section h2 {
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-muted);
    margin-bottom: 12px;
}

#lists-container {
    list-style: none;
}

.list-item {
    padding: 7px 12px;
    border-radius: 6px;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 8px;
    transition: background-color 0.15s;
    margin-bottom: 2px;
    /* 🔒 FIX (2026-09-28, device repro - long-pressing a Book's name to start a drag triggered
       iOS's native text-selection callout (Copy / Search with Google) instead): now that
       SortableJS (render.js) can start a drag from anywhere on the row, not just the ⋮⋮ handle,
       the row's own text needs the same "not selectable" treatment the handle icon already
       implied. -webkit-touch-callout specifically suppresses iOS's long-press popup; user-select
       covers the actual text-selection highlight (desktop browsers included, harmless there). */
    user-select: none;
    -webkit-user-select: none;
    -webkit-touch-callout: none;
}

.list-item:hover {
    background: var(--hover-bg);
}

.list-item.active {
    background: var(--primary-color);
}

.list-item.dragging {
    opacity: 0.5;
}

.list-item.drag-over-list {
    border-top: 2px solid var(--primary-color);
    margin-top: -2px;
}

.drag-handle {
    cursor: grab;
    color: var(--text-muted);
    padding-right: 8px;
    user-select: none;
}

.drag-handle:active {
    cursor: grabbing;
}

/* List color dot - real color+shape emoji now (render.js's getListEmoji), no CSS tint needed. */
.list-color-dot {
    flex-shrink: 0;
    font-size: 16px;
    line-height: 1;
}

/* 📕 A Book's small cover (2026-09-29, automatic covers - utils.js bookThumb, native parity with
   BookThumb.tsx). Size, spine width/colour, corner radius and background are set inline per Book. */
.book-thumb {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    box-sizing: border-box;
    overflow: hidden;
    border-left-style: solid;
    border-top-left-radius: 2px;
    border-bottom-left-radius: 2px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
    vertical-align: middle;
}
.book-thumb > img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.book-thumb-pair {
    display: flex;
    align-items: flex-start;
    transform: translateY(-8%);
}
.book-thumb-face {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    border-radius: 50%;
    border-style: solid;
    border-color: #fff;
    overflow: hidden;
    color: #fff;
    font-family: 'Fredoka', system-ui, sans-serif;
    font-weight: 700;
    line-height: 1;
}
.book-thumb-face > img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.hidden-book-name {
    display: flex;
    align-items: center;
    gap: 10px;
}

/* Edit Book's Cover row - replaced the Color/Shape pickers. */
.edit-cover-row {
    display: flex;
    align-items: center;
    gap: 14px;
    margin-bottom: 16px;
}
.edit-cover-source {
    font-size: 0.9rem;
    margin-top: 2px;
}
.edit-cover-hint {
    font-size: 0.8rem;
    color: var(--text-muted);
    margin-top: 2px;
}

/* 🔒 FEATURE (2026-09-27, "Books in the book list need to take on the stylized appearance as in the
   native app") - the Book title "plate" native's ListItem.tsx/TitlePlate.tsx wraps every title in:
   one treatment per skin (a ribbon banner even when unskinned), built from colors already in that
   skin's palette. Approximated with plain hex values here rather than porting native's
   lightenColor/darkenColor helpers - visually equivalent, not pixel-identical. Ornaments are scaled
   back to what two ::before/::after pseudo-elements can carry (native uses a dedicated absolutely-
   positioned overlay with up to 4 elements) - the border+background+font carries most of each
   skin's identity regardless. */
.list-name-plate {
    position: relative;
    flex: 1;
    min-width: 0;
    display: inline-flex;
    padding: 5px 10.5px;
    border-radius: 10px;
    border: 1.5px solid #6d28d9;
    background: #F1E8FD;
}

.list-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    flex: 1;
    min-width: 0;
    letter-spacing: 0.5px;
}

/* Journal - leather-bound spine: deep crimson with a brass border, embossed gold-cream lettering. */
html[data-skin="journal"] .list-name-plate {
    background: #4D1421;
    border-color: #B08D57;
}
html[data-skin="journal"] .list-name-plate .list-name {
    color: #E8D4AC;
    font-family: 'EB Garamond', serif;
    letter-spacing: 1.5px;
}
html[data-skin="journal"] .list-name-plate::before {
    content: '';
    position: absolute;
    inset: 2px;
    border: 0.75px solid rgba(176, 141, 87, 0.7);
    border-radius: 4px;
    pointer-events: none;
}

/* Scrapbook - paper label, dashed accent border, held on with washi tape. */
html[data-skin="scrapbook"] .list-name-plate {
    background: #FBF6EC;
    border-style: dashed;
    border-color: #A0522D;
    border-radius: 8px;
}
html[data-skin="scrapbook"] .list-name-plate .list-name {
    color: #5C4530;
    font-family: 'Fredoka', sans-serif;
}
html[data-skin="scrapbook"] .list-name-plate::before,
html[data-skin="scrapbook"] .list-name-plate::after {
    content: '';
    position: absolute;
    width: 20px;
    height: 8px;
    opacity: 0.9;
    top: -4px;
}
/* Tape colors vary per Book (2026-09-29, per direct request) - render.js sets --washi-left/--washi-right
   from the Book's id; these are only the fallbacks. */
html[data-skin="scrapbook"] .list-name-plate::before {
    left: -8px;
    background: var(--washi-left, #E8B4BC);
    transform: rotate(-35deg);
}
html[data-skin="scrapbook"] .list-name-plate::after {
    right: -8px;
    background: var(--washi-right, #A9C6D8);
    transform: rotate(35deg);
}

/* Retro - chunky pixel nameplate: dark navy block, lime border, hard offset shadow. */
html[data-skin="retro"] .list-name-plate {
    background: #1E1B4A;
    border-width: 2px;
    border-color: #4ADE80;
    border-radius: 2px;
}
html[data-skin="retro"] .list-name-plate .list-name {
    color: #FFFFFF;
    font-family: 'Press Start 2P', monospace;
    font-size: 0.7em;
}
html[data-skin="retro"] .list-name-plate::after {
    content: '';
    position: absolute;
    right: -4px;
    bottom: -4px;
    width: 6px;
    height: 6px;
    background: #7B2CBF;
    z-index: -1;
}

/* Synthwave - neon sign: dark plate, electric-blue tube outline with a glow. */
html[data-skin="synthwave"] .list-name-plate {
    background: #120B2A;
    border-color: #00D4FF;
    box-shadow: 0 0 6px rgba(0, 212, 255, 0.6);
}
html[data-skin="synthwave"] .list-name-plate .list-name {
    color: #FFFFFF;
    font-family: 'Audiowide', sans-serif;
    letter-spacing: 1px;
    text-shadow: 0 0 8px #00D4FF;
}

.add-list-form {
    display: flex;
    gap: 8px;
    margin-top: 16px;
    align-items: flex-start;
    overflow: visible;
}

/* (2026-09-27, per direct request) collapsed "Add New Book" pill, matching native's ListsScreen.tsx (same icon, same
   warm-purple pill, same text) - and the row it expands into on tap. */
.add-book-pill {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 14px 16px;
    border: none;
    border-radius: 16px;
    background: var(--primary-color);
    color: white;
    font-size: 0.95rem;
    font-weight: 700;
    cursor: pointer;
    box-shadow: 0 2px 8px rgba(124, 58, 237, 0.35);
    transition: background-color 0.15s, transform 0.1s;
}

.add-book-pill:hover {
    background: var(--primary-hover);
}

.add-book-pill:active {
    transform: scale(0.98);
}

.add-book-pill-icon {
    width: 28px;
    height: 28px;
}

.new-list-expanded {
    display: flex;
    gap: 8px;
    align-items: flex-start;
    flex: 1;
}

#new-list-container {
    display: flex;
    flex-direction: column;
    gap: 10px;
    align-self: flex-start;
    flex: 1;
    max-width: 350px;
    overflow: visible;
    position: relative;
}

.add-list-form input,
.add-list-form textarea {
    padding: 8px 12px;
    border: 1px solid transparent;
    border-radius: 6px;
    background: rgba(255, 255, 255, 0.1);
    color: white;
    font-size: 0.875rem;
}

.add-list-form input::placeholder,
.add-list-form textarea::placeholder {
    color: var(--text-muted);
}

.add-list-form input:focus,
.add-list-form textarea:focus {
    outline: 2px solid var(--primary-color);
}

/* Auto-expanding text input for new list */
#new-list-input {
    height: 36px;
    max-height: 150px;
    resize: none;
    overflow-y: hidden;
    padding: 4px 8px;
    line-height: 1.4;
    box-sizing: border-box;
    font-family: inherit;
    width: 100%;
    border: 2px solid #7c3aed !important;
}

.add-list-form button {
    width: 36px;
    height: 36px;
    border: none;
    border-radius: 6px;
    background: var(--primary-color);
    color: white;
    font-size: 1.25rem;
    cursor: pointer;
    transition: all 0.15s;
    display: none;
}

.add-list-form button.visible {
    display: flex;
    align-items: center;
    justify-content: center;
}

.add-list-form button:hover {
    background: var(--primary-hover);
}

/* 🔒 FIX (2026-09-29, "missing the Add New Book button"): the pill sits inside .add-list-form, and
   the older `.add-list-form button` rule above (the small 36px submit button, hidden until .visible)
   out-ranks `.add-book-pill` on specificity - so the pill was display:none and squeezed to 36px.
   Restated here at matching specificity so the pill wins; `.hidden` (display:none !important) still
   collapses it when the input row is open. */
.add-list-form .add-book-pill {
    display: flex;
    width: 100%;
    height: auto;
    font-size: 0.95rem;
    border-radius: 16px;
}
.add-list-form .add-book-pill:hover {
    background: var(--primary-hover);
}
/* ✕ Cancel on the New Book row (2026-09-29, native parity): always shown while the row is open
   (unlike ✓, which waits for text), a muted neutral so ✓ stays the primary action. */
.add-list-form #cancel-list-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    background: #4B5063;
}
.add-list-form #cancel-list-btn:hover {
    background: #5d6278;
}
/* At the Book limit (app.js lockAddBookButton): a 🔒 after the label, slightly dimmed. */
.add-list-form .add-book-pill.locked {
    opacity: 0.85;
}
.add-book-lock {
    font-size: 1rem;
    margin-left: 2px;
}

/* Color select dropdown */
.color-select {
    padding: 6px 24px 6px 8px;
    border: none;
    border-radius: 6px;
    background: rgba(255, 255, 255, 0.1) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='white'/%3E%3C/svg%3E") no-repeat right 8px center;
    color: white;
    font-size: 1rem;
    cursor: pointer;
    width: 52px;
    flex-shrink: 0;
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
}

.color-select:focus {
    outline: 2px solid var(--primary-color);
}

.color-select option {
    background: var(--sidebar-bg);
    color: white;
    font-size: 1rem;
}

.shape-select {
    padding: 6px 24px 6px 8px;
    border: none;
    border-radius: 6px;
    background: rgba(255, 255, 255, 0.1) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='white'/%3E%3C/svg%3E") no-repeat right 8px center;
    color: white;
    font-size: 1rem;
    cursor: pointer;
    width: 52px;
    flex-shrink: 0;
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
}

.shape-select:focus {
    outline: 2px solid var(--primary-color);
}

.shape-select option {
    background: var(--sidebar-bg);
    color: white;
    font-size: 1rem;
}

.sidebar-footer {
    padding: 20px;
    border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.import-btn {
    width: 100%;
    padding: 12px;
    border: 1px dashed rgba(255, 255, 255, 0.3);
    border-radius: 6px;
    background: transparent;
    color: var(--sidebar-text);
    cursor: pointer;
    font-size: 0.875rem;
    transition: all 0.15s;
}

.import-btn:hover {
    background: var(--hover-bg);
    border-color: var(--primary-color);
}

/* User Menu */
.user-menu {
    position: relative;
    flex-shrink: 0;
}

/* (2026-09-27, per direct request - "Make the Avatars look just as they do in the native app with circles surrounding them")
   Matches the native app's own avatar ring treatment (HomeScreen.tsx's profilePhotoContainer: a soft purple glow around every
   circular avatar). Applied to every avatar-shaped element in the app: the header's own avatar, comment authors, Entry
   creators (both the standalone and the Top 10 inline version), and the Our Settings member list. */
.user-avatar,
.comment-avatar,
.task-creator-avatar,
.top10-child .task-creator-avatar-inline,
.group-member-avatar,
.group-member-avatar-placeholder {
    box-shadow: 0 0 0 2px rgba(124, 58, 237, 0.4);
}

.user-avatar {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: var(--primary-color);
    display: flex;
    align-items: center;
    justify-content: center;
    color: white;
    font-size: 0.8rem;
    font-weight: 600;
    cursor: pointer;
    overflow: hidden;
    transition: transform 0.15s, box-shadow 0.15s;
}

.user-avatar:hover {
    transform: scale(1.05);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}

.user-avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.user-dropdown {
    position: absolute;
    top: 100%;
    right: 0;
    margin-top: 8px;
    background: var(--card-bg);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
    z-index: 1000;
    min-width: 140px;
}

.user-dropdown.hidden {
    display: none;
}

.dropdown-menu-btn {
    width: 100%;
    padding: 10px 14px;
    border: none;
    background: none;
    color: var(--text-color);
    cursor: pointer;
    font-size: 0.9rem;
    text-align: left;
    border-radius: 6px;
    transition: background-color 0.15s;
    white-space: nowrap;
}

.dropdown-menu-btn:hover {
    background: rgba(124, 58, 237, 0.1);
}

.dropdown-menu-btn#logout-btn:hover {
    background: rgba(239, 68, 68, 0.1);
    color: #ef4444;
}

.import-status {
    margin-top: 10px;
    font-size: 0.75rem;
    color: var(--text-muted);
    text-align: center;
}

.import-status.loading {
    color: var(--primary-color);
}

.import-status.success {
    color: var(--success-color);
}

.import-status.error {
    color: var(--danger-color);
}

/* Main Content Styles */
.main-content {
    flex: 1;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

/* Sticky Header */
.main-sticky-header {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    padding: 16px 32px;
    gap: 12px;
    background: var(--bg-color);
    border-bottom: 1px solid var(--border-color);
    flex-shrink: 0;
}

.main-sticky-header .list-header {
    margin-bottom: 0;
    flex: 1;
    min-width: 0;
    justify-content: flex-start;
}

.main-sticky-header .list-header h2 {
    /* --title-scale: short Book titles go big (render.js fitBookTitle); capped on wide screens. */
    font-size: min(calc(2.25rem * var(--title-scale, 1)), 3.4rem);
    color: var(--text-color);
    display: inline-block;
    flex: 1;
    text-align: center;
}

.main-sticky-header .list-header-color {
    display: inline-block;
}

.main-sticky-header .search-container {
    margin-bottom: 0;
    flex-shrink: 0;
}

/* Scrollable Content */
.main-scrollable-content {
    flex: 1;
    padding: 24px 32px;
    overflow-y: auto;
    /* 🔒 FIX (2026-09-28) - see body's own comment above for the full story (sliding entry cards =
       the browser's native edge-swipe-back gesture, not a CSS bug). Set here too, on the actual
       scrolling element the touch starts on - gesture recognition can key off either the document
       body or the specific scroll container depending on the engine, so both is the safe bet. */
    overscroll-behavior-x: none;
}

/* Search Box */
/* (2026-09-27, device repro - the old inline header search box was still showing, circled in a
   screenshot, "that needs to go"): fully replaced now that the nav bar's Search button opens a real
   dedicated modal (#search-modal, Phase 3) - the decision 5 intent from the start of this nav bar
   work ("the current top-right search input box... needs to change to fit into the nav bar
   scheme"). #search-input/#clear-search/#search-results stay in the DOM (search.js's own
   performSearch/clearSearch still reference them, and clearSearch() has a couple other callers that
   just reset harmless UI state) - hidden only, not removed, so nothing else has to change. */
.search-container {
    display: none;
}

.search-input {
    width: 100%;
    padding: 12px 40px 12px 16px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    font-size: 0.95rem;
    background: var(--card-bg);
    color: var(--text-color);
    transition: border-color 0.15s;
}

.search-input:focus {
    outline: none;
    border-color: var(--primary-color);
}

.search-input::placeholder {
    color: var(--text-muted);
}

.clear-search-btn {
    position: absolute;
    right: 12px;
    top: 50%;
    transform: translateY(-50%);
    width: 24px;
    height: 24px;
    border: none;
    background: rgba(255, 255, 255, 0.3);
    color: white;
    border-radius: 50%;
    cursor: pointer;
    font-size: 1rem;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background-color 0.15s;
}

.clear-search-btn:hover {
    background: rgba(255, 255, 255, 0.5);
}

.clear-search-btn.hidden {
    display: none;
}

/* Search Results */
.search-results {
    margin-bottom: 24px;
}

.search-results.hidden {
    display: none;
}

.search-results-header {
    font-size: 0.875rem;
    color: var(--text-muted);
    margin-bottom: 12px;
}

.search-result-item {
    background: var(--card-bg);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    padding: 12px 16px;
    margin-bottom: 8px;
    cursor: pointer;
    transition: box-shadow 0.15s, border-color 0.15s;
}

.search-result-item:hover {
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
    border-color: var(--primary-color);
}

.search-result-title {
    font-weight: 500;
    margin-bottom: 4px;
}

.search-result-title mark {
    background: rgba(124, 58, 237, 0.2);
    color: inherit;
    padding: 0 2px;
    border-radius: 2px;
}

.search-result-list {
    font-size: 0.8rem;
    color: var(--text-muted);
}

.search-result-subtask {
    font-size: 0.75rem;
    color: var(--text-muted);
    margin: 4px 0;
    padding-left: 8px;
    border-left: 2px solid var(--secondary-color);
}

.search-result-comment {
    font-size: 0.75rem;
    color: var(--text-muted);
    font-style: italic;
    margin: 4px 0;
    padding-left: 8px;
    border-left: 2px solid var(--primary-color);
}

.search-result-caption {
    font-size: 0.75rem;
    color: var(--text-muted);
    margin: 4px 0;
    padding-left: 8px;
    border-left: 2px solid #10b981;
}

.empty-state {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
    color: var(--text-muted);
    font-size: 1.125rem;
}

.list-view.hidden,
.hidden {
    display: none !important;
}

/* Back to lists button - hidden on desktop */
.back-to-lists-btn {
    display: none;
}

.list-header {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 24px;
    justify-content: center;
}

.list-header-color {
    flex-shrink: 0;
    cursor: pointer;
    transition: transform 0.15s;
    font-size: 27px;
    line-height: 1;
    display: inline-flex;
    align-items: center;
}

.list-header-color:hover {
    transform: scale(1.2);
}

.list-header h2 {
    font-size: 2.25rem;
    font-weight: 600;
    cursor: pointer;
    padding: 4px 8px;
    border-radius: 4px;
    transition: background-color 0.15s;
}

.list-header h2:hover {
    background: var(--border-color);
}

.delete-btn {
    padding: 8px;
    border: none;
    background: transparent;
    cursor: pointer;
    border-radius: 4px;
    transition: background-color 0.15s;
    font-size: 1rem;
}

.delete-btn:hover {
    background: rgba(239, 68, 68, 0.1);
}

/* Sort Control */
.sort-control {
    position: relative;
    flex-shrink: 0;
}

.sort-btn {
    padding: 6px 10px;
    border: 1px solid var(--border-color);
    background: var(--card-bg);
    border-radius: 6px;
    cursor: pointer;
    font-size: 0.85rem;
    color: var(--text-secondary);
    transition: background-color 0.15s, border-color 0.15s;
    display: flex;
    align-items: center;
    gap: 4px;
}

.sort-btn:hover {
    background: var(--border-color);
    border-color: var(--primary-color);
    color: var(--text-color);
}

.sort-btn .sort-label {
    font-size: 0.75rem;
}

.sort-dropdown {
    position: absolute;
    top: 100%;
    right: 0;
    margin-top: 4px;
    background: var(--card-bg);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
    z-index: 100;
    min-width: 150px;
    overflow: hidden;
}

.sort-option {
    display: block;
    width: 100%;
    padding: 10px 14px;
    border: none;
    background: transparent;
    text-align: left;
    cursor: pointer;
    font-size: 0.875rem;
    color: var(--text-color);
    transition: background-color 0.1s;
}

.sort-option:hover {
    background: var(--border-color);
}

.sort-option.active {
    color: var(--primary-color);
    font-weight: 600;
}

/* Tasks Styles */
.tasks-container {
    margin-top: 0;
}

.task-item {
    background: var(--card-bg);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    margin-bottom: 8px;
    transition: box-shadow 0.15s;
    position: relative;
}

.task-item:hover {
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}

.task-content {
    display: flex;
    align-items: center;
    padding: 12px 16px;
    gap: 12px;
}

.task-checkbox {
    width: 20px;
    height: 20px;
    border: 2px solid var(--border-color);
    border-radius: 4px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    transition: all 0.15s;
}

.task-checkbox:hover {
    border-color: var(--primary-color);
}

.task-checkbox.checked {
    background: var(--success-color);
    border-color: var(--success-color);
}

.task-checkbox.checked::after {
    content: "✓";
    color: white;
    font-size: 0.75rem;
    font-weight: bold;
}

/* Top 10 Lists */

/* Parent items (the list titles like "Pete & Carol's Top 10...") */
.top10-parent > .task-content > .task-title {
    font-weight: 600;
    font-size: 1.1rem;
}

/* 🔒 FIX (2026-09-27, per direct request - "There is way too much busy-ness now with horizontal
   rules and the purple vertical line. Clean it up: cards and a vertical line. That's it"): this used
   to be its own separate indent-box treatment (its own border-left, background, rounded corners) -
   now that .top10-group (further down) already draws ONE vertical bar spanning the whole group
   (parent + children), this would just be a second, redundant one right next to it. Flattened to a
   plain block; the group's own bar is the only vertical line now. */
.top10-parent > .subtasks {
    padding-left: 0;
    margin-left: 0;
    border-left: none;
    background: transparent;
    border-radius: 0;
    margin-top: 8px;
    margin-bottom: 0;
    padding-top: 0;
    padding-bottom: 0;
}

/* 🔒 Each Top 10 child is its own enclosed card now (real border + rounded corners + a gap before
   the next one) - not a seamless strip with a divider line between rows. No replacement rule here
   at all, deliberately: the base .task-item rule ALREADY has its own border/border-radius/
   margin-bottom (style.css, ~line 1524), and every skin's own html[data-skin=...] .task-item rule
   already overrides background/border-color/border-width as that skin needs (Retro's asymmetric
   "8-bit shadow" border-width among them) - a same-selector replacement rule here would need to be
   at least as specific as those skin rules to survive the cascade, which would then ALSO beat them
   on any property it touches and silently undo their own card treatment for every Top 10 child, the
   exact style-specificity trap CLAUDE.md's own protocol warns about. Simplest correct fix: just stop
   flattening it (see .top10-parent > .subtasks itself, above) and let the existing rules apply. */

/* Nested subtasks within Top 10 items (checklists, etc) */
.top10-parent > .subtasks .subtasks {
    padding-left: 24px;
    margin-left: 16px;
    border-left: 2px solid var(--primary-color);
    background: rgba(124, 58, 237, 0.05);
    border-radius: 0 6px 6px 0;
    margin-top: 4px;
    margin-bottom: 4px;
    padding-top: 4px;
    padding-bottom: 4px;
}

/* Hide checkbox for Top 10 child items */
.task-checkbox.top10-hidden {
    display: none;
}

/* Top 10 child items - normal weight */
.top10-child > .task-content > .task-title {
    font-weight: 400;
}

/* Checklist headers (e.g., "PETE'S TOP 10") */
.checklist-header > .task-content > .task-title {
    font-weight: 600;
    font-size: 0.95rem;
    color: var(--primary-color);
}

.checklist-header > .task-content > .task-checkbox {
    display: none;
}

/* Ensure collapse button is visible for checklist headers */
.checklist-header > .task-content > .collapse-btn {
    visibility: visible !important;
    display: block !important;
}

/* Checklist header subtasks container */
.checklist-header > .subtasks {
    padding-left: 24px;
    margin-left: 16px;
    border-left: 2px solid var(--primary-color);
    border-top: none;
    margin-top: 4px;
    padding-top: 4px;
    padding-bottom: 4px;
}

.collapse-btn {
    width: 20px;
    height: 20px;
    border: none;
    background: transparent;
    cursor: pointer;
    font-size: 0.75rem;
    color: var(--text-muted);
    transition: transform 0.15s;
    flex-shrink: 0;
}

.collapse-btn.collapsed {
    transform: rotate(-90deg);
}

.collapse-btn.hidden {
    visibility: hidden;
}

.task-title {
    flex: 1;
    cursor: pointer;
    padding: 4px;
    border-radius: 4px;
    transition: background-color 0.15s;
}

.task-title:hover {
    background: var(--bg-color);
}

.task-title.completed {
    text-decoration: line-through;
    color: var(--text-muted);
}

/* (2026-09-27, Top 10 native-parity work) - a fresh Top 10 parent's seed title or a blank Top 10
   child, matching native's own grey-italic hint-text treatment (ItemsView.tsx's parentPlaceholder/
   subRankPlaceholder) instead of showing raw seed text or nothing at all. */
.task-title-placeholder {
    color: var(--text-muted);
    font-style: italic;
}

.inline-task-edit {
    background: var(--card-bg);
    border: 1px solid var(--primary-color);
    border-radius: 4px;
    color: var(--text-color);
    font-size: inherit;
    font-family: inherit;
    padding: 4px 8px;
    width: 100%;
    outline: none;
    resize: none;
    overflow: hidden;
    line-height: 1.4;
    min-height: 1.4em;
}

.inline-task-edit:focus {
    box-shadow: 0 0 0 2px rgba(124, 58, 237, 0.2);
}

/* Cancel(x)/Confirm(check) row under an in-progress title edit (2026-09-27, device repro -
   "the X and check mark are missing from the Top 10 parent and sub entry title edits") - sizing
   and colors copied directly from native's own button pair (ItemsView.tsx, the isInlineFocused
   row: 31x31 circles, #E5E7EB/#6B7280 cancel, #7C3AED/white confirm). */
.inline-task-edit-actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    margin-top: 6px;
}

.inline-task-edit-cancel,
.inline-task-edit-confirm {
    width: 31px;
    height: 31px;
    border-radius: 15.5px;
    border: none;
    cursor: pointer;
    font-size: 0.9rem;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.inline-task-edit-cancel {
    background: #E5E7EB;
    color: #6B7280;
}

.inline-task-edit-confirm {
    background: #7C3AED;
    color: #FFFFFF;
}

/* 🔒 REDESIGN (2026-09-27, per direct request with a screenshot - "mirror the layout of the
   buttons... buttons are skin specific"): task-date used to sit inline to the title's right
   (margin-left:auto pushed it there); it's now the first icon in .task-icon-row, a full-width row
   below the title matching native's own calendar/camera/comment/trash layout.
   🔒 FIX (2026-09-28, per direct request - "PWA displays the date including the year, that is
   good. But then it shows the calendar icon next to it, which is not good... once the date is
   selected, it should be displayed in a pill so it's clear that it's still tappable"): a SET date
   is now a real pill (rounded fill) with no icon at all - the pill shape itself is the "this is
   tappable" affordance, an icon next to real date text was redundant. The empty/no-date state
   keeps a bare calendar icon (no pill fill, no text) - that's the one case an icon genuinely earns
   its place, same as native's own empty-state icon button. */
.task-date {
    display: inline-flex;
    align-items: center;
    font-size: 0.8rem;
    color: var(--text-muted);
    white-space: nowrap;
    cursor: pointer;
    padding: 6px 12px;
    border-radius: 999px;
    background: var(--bg-color);
}

.task-date.no-date {
    background: transparent;
    padding: 6px 8px;
}

.task-date.no-date::before {
    content: '📅';
    font-size: 1rem;
}

.task-date:hover {
    background: var(--bg-color);
    color: var(--primary-color);
}

.task-date.no-date {
    opacity: 0.6;
}

.task-date.no-date:hover {
    opacity: 1;
    color: var(--primary-color);
}

.inline-date-picker {
    display: flex;
    align-items: center;
    /* 🔒 FIX (2026-09-27, per direct request - "leave enough space between them especially for
       phone screen format"): 4px was tight even for the old text-labeled buttons; now that
       Save/Clear are bare icon circles (see below) with no label to visually separate them,
       cramped spacing reads as one blob and invites mis-taps - bumped further still on phones
       in the @media (max-width: 768px) block. */
    gap: 8px;
    margin-left: 8px;
}

.date-picker-input {
    padding: 4px 8px;
    border: 1px solid var(--border-color);
    border-radius: 4px;
    font-size: 0.8rem;
}

/* 🔒 (2026-09-28, per direct request with a screenshot - "there's still a goofy X showing up to
   the right of the date. Get rid of that"): .date-picker-clear (and .date-picker-save before it,
   see git history) is gone now too - the picker is just the native date input on its own. */

/* Task Attachments
   🖼️ (2026-10-01, photo framing on both platforms) Laid out like native's photo rows: two square frames per row, and the
   lone last photo of an odd count spans the row at the same height (aspect 2.05:1 - LONE_PHOTO_FRAME_ASPECT in
   js/lightbox.js; native's subitemPhotoDimensionsFull). Each photo is cropped into its frame ("cover"); the couple's
   chosen framing (photoFocus) moves/zooms it inside the frame via inline object-position/transform - see
   applyPhotoFocusToImg. The frame's own size never changes. */
.task-attachments {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px;
    padding: 8px 16px 12px;
    max-width: 480px;
}

.photo-frame {
    position: relative;
    width: 100%;
    aspect-ratio: 1 / 1;
    overflow: hidden;
    border-radius: 6px;
    transition: box-shadow 0.15s;
}

.attachment-container.lone-photo {
    grid-column: 1 / -1;
}

.attachment-container.lone-photo .photo-frame {
    aspect-ratio: 2.05 / 1;
}

.photo-frame:hover {
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

.task-attachment-img {
    display: block;
    width: 100%;
    height: 100%;
    cursor: pointer;
    object-fit: cover;
}

.photo-frame.video-frame {
    background: #000000;
}

video.task-attachment-img {
    cursor: default;
    object-fit: contain;
}

.attachment-container {
    position: relative;
    min-width: 0;
}

.attachment-delete-btn {
    position: absolute;
    top: 4px;
    right: 4px;
    width: 24px;
    height: 24px;
    border: none;
    background: rgba(0, 0, 0, 0.6);
    color: white;
    border-radius: 50%;
    cursor: pointer;
    font-size: 1.1rem;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    transition: opacity 0.15s, background-color 0.15s;
}

.attachment-container:hover .attachment-delete-btn {
    opacity: 1;
}

.attachment-delete-btn:hover {
    background: var(--danger-color);
}

/* 🔒 FIX (2026-09-27, per direct request - "Make captions fully visible (wrap text to another line
   as needed)"): single-line ellipsis truncation was cutting off longer captions entirely - wraps
   across as many lines as the text needs now, same as native (captions there just wrap, no
   truncation at all). Shared by both Entry-level and comment-level photo captions (render.js). */
.attachment-caption {
    font-size: 0.75rem;
    color: var(--text-muted);
    text-align: center;
    max-width: 100%;
    overflow-wrap: break-word;
    white-space: normal;
    padding: 4px 0;
    cursor: pointer;
    border-radius: 4px;
    transition: background-color 0.15s;
}

.attachment-caption:hover {
    background: var(--bg-color);
}

.attachment-caption.placeholder {
    font-style: italic;
    opacity: 0.6;
}

/* "✨ Writing a caption..." (2026-09-27, AI caption suggestions) - matches native's PhotoCard
   shimmer-pending state; not clickable while pending (see render.js's own guard). */
.attachment-caption.ai-caption-pending {
    font-style: italic;
    color: var(--primary-color);
    cursor: default;
    animation: ai-caption-shimmer 1.4s ease-in-out infinite;
}

@keyframes ai-caption-shimmer {
    0%, 100% { opacity: 0.5; }
    50% { opacity: 1; }
}

.caption-input {
    font-size: 0.75rem;
    text-align: center;
    max-width: 100%;
    width: 100%;
    padding: 4px;
    border: 1px solid var(--primary-color);
    border-radius: 4px;
    outline: none;
}

/* Comments */
.task-comments {
    padding: 8px 16px 12px;
}

.comment-item {
    display: block;
    padding: 12px 32px 12px 12px;
    border-radius: 8px;
    margin-bottom: 8px;
    position: relative;
}

/* Default (unskinned) alternating comment-row colors - moved here from an inline style
   (render.js) so a skin's own html[data-skin=...] .comment-item-even/-odd rules (style.css, THE
   FINAL FRONTIER section) can actually override them; inline styles beat any class selector. */
.comment-item-even {
    background-color: #F3E8FF;
}
.comment-item-odd {
    background-color: #FDF2F8;
}

.comment-avatar {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: white;
    font-size: 0.75rem;
    font-weight: 600;
    overflow: hidden;
    float: left;
    margin-right: 8px;
    margin-bottom: 4px;
}

.comment-avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Task creator avatar - small indicator of who added the task */
.task-creator-avatar {
    width: 24px;
    height: 24px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: var(--primary-color);
    color: white;
    font-size: 0.55rem;
    font-weight: 600;
    flex-shrink: 0;
    overflow: hidden;
}

.task-header {
    display: flex;
    align-items: center;
}

.task-header .task-content {
    flex: 1;
}

.task-creator-avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.comment-date {
    color: #999;
    font-size: 0.65rem;
    display: inline-block;
    margin-right: 8px;
    vertical-align: top;
}

.comment-text {
    font-size: 0.75rem;
    color: #333;
    display: inline-block;
    word-wrap: break-word;
    overflow-wrap: break-word;
    vertical-align: top;
    max-width: 80%;
}

.comment-attachments {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    flex: 1 1 100%;
    margin-top: 4px;
}

/* (2026-10-01) Entry photo captions now fill their grid cell; comment photos keep their caption as narrow as the photo. */
.comment-attachments .attachment-caption,
.comment-attachments .caption-input {
    max-width: 120px;
}

.comment-attachment-img {
    max-width: 120px;
    max-height: 100px;
    border-radius: 6px;
    object-fit: cover;
    cursor: pointer;
    transition: opacity 0.15s;
}

.comment-attachment-img:hover {
    opacity: 0.8;
}

.comment-delete-btn {
    position: absolute;
    top: 8px;
    right: 8px;
    width: 20px;
    height: 20px;
    border: none;
    background: rgba(0, 0, 0, 0.6);
    color: white;
    border-radius: 50%;
    cursor: pointer;
    font-size: 0.9rem;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    opacity: 1;
    transition: background-color 0.2s;
}

.comment-delete-btn:hover {
    background: var(--danger-color);
}

.add-comment-btn {
    background: none;
    border: 1px dashed var(--border-color);
    color: var(--text-muted);
    padding: 8px 12px;
    border-radius: 6px;
    cursor: pointer;
    font-size: 0.8rem;
    width: 100%;
    transition: all 0.15s;
}

.add-comment-btn:hover {
    border-color: var(--primary-color);
    color: var(--primary-color);
}

.add-comment-inline-btn {
    background: none;
    border: none;
    cursor: pointer;
    font-size: 1rem;
    padding: 4px 8px;
    border-radius: 4px;
    transition: transform 0.15s;
}

.add-comment-inline-btn:hover {
    transform: scale(1.3);
    background: rgba(124, 58, 237, 0.1);
}

/* Comment Modal (2026-09-27) - colors/shapes copied directly from the native app's
   CommentModal.tsx so the two feel like the same feature: lavender overlay (#E9D5FF), off-white
   card bordered in that same lavender, purple (#7C3AED) input border/accent, round 60px
   Cancel(#E8E8E8)/Send(#7C3AED) buttons. Native's decorative PNG icon scatter and spring slide-up
   animation don't have a web equivalent worth porting asset-for-asset - a small emoji header
   stands in for the icon scatter, and .modal's own fade-in is this page's normal modal entrance. */
.comment-modal-overlay {
    background: rgba(233, 213, 255, 0.85);
}

.comment-modal-content {
    max-width: 420px;
    border: 2px solid #E9D5FF;
    border-radius: 28px;
    text-align: center;
}

.comment-modal-header-icons {
    font-size: 1.75rem;
    margin-bottom: 8px;
    letter-spacing: 8px;
}

.comment-modal-subtitle {
    font-size: 1.125rem;
    font-weight: 500;
    color: #666;
    margin: 0 0 4px;
}

.comment-modal-title {
    font-size: 1.5rem;
    font-weight: 700;
    color: #7C3AED;
    margin: 0 0 16px;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}

.comment-modal-content textarea.comment-modal-input {
    border: 2px solid #7C3AED;
    border-radius: 24px;
    background: #F3E8FF;
    font-size: 1rem;
    line-height: 1.5;
    padding: 12px 14px;
    min-height: 80px;
    max-height: 270px;
}

.comment-modal-actions {
    display: flex;
    justify-content: center;
    gap: 28px;
    margin-top: 8px;
}

.comment-btn-circle {
    width: 60px;
    height: 60px;
    border-radius: 30px;
    border: none;
    font-size: 1.5rem;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: opacity 0.15s, transform 0.1s;
}

.comment-btn-circle:active {
    transform: scale(0.95);
}

.comment-btn-cancel {
    background: #E8E8E8;
    color: #4B5563;
}

.comment-btn-send {
    background: #7C3AED;
    color: #FFFFFF;
}

.comment-btn-send:disabled {
    opacity: 0.5;
    cursor: default;
}

/* AI Caption Prompt Modal (2026-09-27) - layout mirrors native's AiCaptionPromptModal.tsx: centered
   icon, bold intro line, a Yes!/Maybe Later button pair, small fine print below. */
.ai-caption-prompt-content {
    max-width: 380px;
    text-align: center;
}

.ai-caption-prompt-icon {
    font-size: 2.5rem;
    margin-bottom: 8px;
}

.ai-caption-prompt-body {
    font-size: 1.0625rem;
    line-height: 1.5;
    color: var(--text-color);
    margin: 0 0 20px;
}

.ai-caption-prompt-actions {
    justify-content: center;
}

.ai-caption-prompt-fyi {
    margin: 14px 0 0;
    font-size: 0.75rem;
    line-height: 1.4;
    color: var(--text-muted);
}

/* App version display in Our Settings (2026-09-27, device repro - "Settings screen is out of date") */
.app-version-display {
    text-align: center;
    font-size: 0.75rem;
    color: var(--text-muted);
    margin: 4px 0 0;
}

/* Delete-account link inside Privacy & Security (2026-09-27, device repro - "Settings screen is out
   of date") - a real link, not a button, since it navigates away to the standalone /delete-account
   page rather than doing anything itself here. */
.delete-account-link {
    display: inline-block;
    margin-top: 12px;
    color: var(--danger-color);
    font-size: 0.875rem;
    font-weight: 600;
    text-decoration: underline;
}

/* 🔒 FIX (2026-09-27, device repro - "the current release is now missing the buttons entirely on
   the Entry cards"): these were never actually removed - opacity:0 by default, revealed only on
   .task-content:hover, was always the behavior here, just never very noticeable until the photo/
   comment count badges gave a real reason to look for the icons. On a real touchscreen (no hover
   state at all) or any non-hover-capable browser context, that made them look simply gone. Native
   never hides these - matches that now: always visible, no hover gating. */
/* The full-width row below the title (calendar/camera/comment/trash) - see task-date's own comment
   above for the redesign this belongs to. */
.task-icon-row {
    display: flex;
    align-items: center;
    gap: 16px;
    padding-top: 4px;
    padding-bottom: 8px;
}

/* Top 10 List group indicator (2026-09-27, device repro with a screenshot - "there needs to be a
   vertical indicator identifying the Top 10 List scope and the expand collapse button needs to
   reside to the left of the Parent") - matches native's EntryCard exactly: one accent-colored
   vertical bar spanning the whole group (parent + every child - see renderTaskItem's own comment
   for why wrapping the already-built parent+children div gets this height for free), with the
   collapse arrow living in that same left margin instead of inline before the title. Default/
   unskinned color reuses the app's own primary purple; skin-specific overrides below reuse each
   skin's own accentColor exactly. */
.top10-group {
    position: relative;
    padding-left: 28px;
    border-left: 4px solid var(--primary-color);
    margin-bottom: 8px;
}

/* 🔒 FIX (2026-09-27, per direct request - "Move the expand/collapse button between the vertical
   bar and the Top 10 Cards"): was left:-16px, OUTSIDE/before the bar - now sits in the gutter the
   bar's own padding-left already reserves, between the bar and the card content. */
.top10-group-collapse-btn {
    position: absolute;
    left: 0;
    top: 14px;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    border: none;
    background: transparent;
    color: var(--primary-color);
    font-size: 0.8rem;
    line-height: 1;
    cursor: pointer;
    transition: transform 0.15s;
}

.top10-group-collapse-btn.collapsed {
    transform: rotate(-90deg);
}

html[data-skin="scrapbook"] .top10-group { border-left-color: #A0522D; }
html[data-skin="scrapbook"] .top10-group-collapse-btn { color: #A0522D; }
html[data-skin="journal"] .top10-group { border-left-color: #2E4A34; }
html[data-skin="journal"] .top10-group-collapse-btn { color: #2E4A34; }
html[data-skin="retro"] .top10-group { border-left-color: #4ADE80; }
html[data-skin="retro"] .top10-group-collapse-btn { color: #4ADE80; }
html[data-skin="synthwave"] .top10-group { border-left-color: #FF2EC4; }
html[data-skin="synthwave"] .top10-group-collapse-btn { color: #FF2EC4; }

.task-actions {
    display: flex;
    gap: 16px;
}

.task-actions button {
    position: relative;
    padding: 4px 8px;
    border: none;
    background: transparent;
    cursor: pointer;
    border-radius: 4px;
    font-size: 0.875rem;
    transition: background-color 0.15s;
}

.task-actions button:hover {
    background: var(--bg-color);
}


.task-actions .delete-task-btn:hover {
    background: rgba(239, 68, 68, 0.1);
}

.task-actions .add-photo-btn {
    font-size: 1rem;
    transition: transform 0.15s, background-color 0.15s;
}

/* Photo/comment count badges (2026-09-27, device repro - screenshot of native's own small purple
   circle badge on the camera/comment icons) - matches native's ItemsView.tsx exactly
   (styles.photoBadge/photoBadgeText): purple circle, white border, white bold number. */
.icon-count-badge {
    position: absolute;
    top: -6px;
    right: -6px;
    min-width: 18px;
    height: 18px;
    padding: 0 3px;
    border-radius: 9px;
    background: #7C3AED;
    border: 2px solid #FFFFFF;
    color: #FFFFFF;
    font-size: 0.65rem;
    font-weight: 700;
    line-height: 14px;
    text-align: center;
    pointer-events: none;
}

.task-actions .add-photo-btn:hover {
    background: rgba(124, 58, 237, 0.1);
    transform: scale(1.5);
}

/* Drag and drop styles */
.task-item.drag-over {
    outline: 2px dashed var(--primary-color);
    outline-offset: -2px;
    background: rgba(124, 58, 237, 0.05);
}

.task-item.uploading {
    opacity: 0.7;
    pointer-events: none;
}

.task-item.uploading::after {
    content: 'Uploading...';
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background: var(--primary-color);
    color: white;
    padding: 8px 16px;
    border-radius: 4px;
    font-size: 0.875rem;
}

.add-entry-modal-content.drag-over {
    outline: 2px dashed var(--primary-color);
    outline-offset: 4px;
    background: rgba(124, 58, 237, 0.05);
    border-radius: 8px;
}

/* Subtasks */
.subtasks {
    padding-left: 32px;
    margin-left: 20px;
    border-left: 3px solid var(--primary-color);
    border-top: none;
    background: var(--bg-color);
    border-radius: 0 8px 8px 0;
    margin-top: 4px;
    margin-bottom: 4px;
    padding-top: 4px;
    padding-bottom: 4px;
}

.subtasks.hidden {
    display: none;
}

.subtasks .task-item {
    border: none;
    border-bottom: 1px solid var(--border-color);
    border-radius: 0;
    margin-bottom: 0;
}

.subtasks .task-item:last-child {
    border-bottom: none;
}

/* Header action row (2026-09-27: replaces the old always-expanded inline entry form - see the matching HTML/JS comment - with two
   pill buttons, matching the native app's own header exactly). */
.header-action-row {
    display: flex;
    gap: 8px;
    align-items: center;
    margin-bottom: 0;
}

.main-sticky-header .header-action-row {
    width: 100%;
    order: 4;
}

.header-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 10px 16px;
    border: none;
    border-radius: 24px;
    background: #b45309;
    color: white;
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
    transition: background-color 0.15s, transform 0.1s;
    flex-shrink: 0;
}

.header-pill:hover {
    background: #92400e;
}

.header-pill:active {
    transform: scale(0.97);
}

.header-pill-icon {
    font-size: 1rem;
    line-height: 1;
}

/* The native app's own Top 10 badge image, not an emoji (per direct request). */
.header-pill-icon-img {
    width: 20px;
    height: 20px;
}

.header-pill-primary {
    background: var(--primary-color);
}

.header-pill-primary:hover {
    background: var(--primary-hover);
}

/* (2026-09-27, per direct request - "Make the Add Entry button stretch all the way to the right side") */
.header-pill-stretch {
    flex: 1 1 auto;
    justify-content: center;
}

/* 🎨 THE FINAL FRONTIER - FULL RICHNESS PASS (2026-09-27, per direct request to go beyond the
   Phase 2 colors-only version - "full richness, all 4 skins, in one pass"). Every value below is
   copied EXACTLY from native's own src/theme/skins.ts (verified via a full read of that file plus
   every asset it references), not eyeballed - fonts are the same Google Fonts native bundles as
   static .ttf files (Fredoka, EB Garamond, Press Start 2P, VT323, Special Elite, Audiowide,
   Rajdhani - loaded in index.html's <head>), and image assets are copied from native's own
   src/assets/images/ into public/images/skins/ (oversized ones re-encoded for web: journal-
   background as WebP, four Scrapbook ephemera PNGs downscaled - see that directory's own history).
   Scoped to Book-view elements only (header, buttons, Entry cards, comments, photo captions) via
   html[data-skin="..."] overrides on LOCAL selectors, never the shared --primary-color/--card-bg
   custom properties used app-wide (login, sidebar, Settings) - matches native's own scope exactly.
   Deferred as a real, separate follow-up (flagging rather than silently dropping): Scrapbook's
   paperclip/binder-clip (comments) and postage-stamp/ticket-stub (Entries) ephemera, and skinning
   the Add Entry/Comment modal chrome to match (SCRAPBOOK_MODAL_SKIN etc. in native) - both add
   meaningfully more image-selection/positioning logic on top of everything below, which already
   covers fonts, textures, icon art, card styling, comment alternation, pins, and washi tape. */

/* ── SCRAPBOOK (Keepsake Scrapbook) ── */
html[data-skin="scrapbook"] .main-sticky-header {
    background: #C8AD7F;
}
html[data-skin="scrapbook"] .header-pill-primary {
    background: #A0522D;
}
html[data-skin="scrapbook"] .main-scrollable-content {
    background-color: #C8AD7F;
}
html[data-skin="scrapbook"] .task-item {
    background: #FBF6EC;
    border-color: #8C6A46;
    /* Per-card tilt (render.js sets --card-rotation per Entry, matching native's cardRotationDeg -
       deterministic from the Entry's own id, never re-rolled on re-render). */
    transform: rotate(var(--card-rotation, 0deg));
}
html[data-skin="scrapbook"] .task-title {
    font-family: 'Fredoka', sans-serif;
    font-weight: 700;
}
html[data-skin="scrapbook"] .task-date,
html[data-skin="scrapbook"] .comment-date {
    font-family: 'Special Elite', monospace;
}
html[data-skin="scrapbook"] .comment-text {
    font-family: 'Fredoka', sans-serif;
}
html[data-skin="scrapbook"] .comment-item-even {
    background-color: #C8AD7F;
    border: 1px solid #5C4530;
}
html[data-skin="scrapbook"] .comment-item-odd {
    background-color: #8C6A46;
    border: 1px solid #F4BF11;
}
/* 🔒 (2026-10-01, per the owner - "comments in the journal and scrapbook skin need greater contrast",
   with circled screenshots): the date and text were the base greys on both Scrapbook rows, and the ✕
   was a see-through dark circle on the dark row. Same colours as the native app (CommentItem.tsx):
   dark ink on the tan rows; Top10 Light Yellow on the dark Amber Accent rows, with a cream ✕ button. */
html[data-skin="scrapbook"] .comment-item-even .comment-date,
html[data-skin="scrapbook"] .comment-item-even .comment-text {
    color: #404040;
}
html[data-skin="scrapbook"] .comment-item-odd .comment-date,
html[data-skin="scrapbook"] .comment-item-odd .comment-text {
    color: #FEF3C7;
}
html[data-skin="scrapbook"] .comment-item-odd .comment-delete-btn {
    background: #FBF3E4;
    color: #8C6A46;
}
html[data-skin="scrapbook"] .comment-avatar,
html[data-skin="scrapbook"] .task-creator-avatar {
    box-shadow: 0 0 0 2px #8C6A46;
}
/* Scrapbook's own camera/comment/trash icon art (2026-09-27, device repro with a screenshot -
   "buttons are skin specific") - matches native's ItemsView.tsx exactly (skin === 'scrapbook' ?
   camera-icon.png/comment-icon.png/trash-icon.png), the one gap left when Journal/Synthwave's own
   icon art was ported earlier. Same font-size:0-hides-the-emoji trick as those two. */
html[data-skin="scrapbook"] .add-photo-btn {
    font-size: 0;
    background-image: url('/images/skins/scrapbook-camera-icon.png');
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
}
html[data-skin="scrapbook"] .add-comment-inline-btn {
    font-size: 0;
    background-image: url('/images/skins/scrapbook-comment-icon.png');
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
}
html[data-skin="scrapbook"] .delete-task-btn {
    font-size: 0;
    background-image: url('/images/skins/scrapbook-trash-icon.png');
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
}
/* 🔒 FIX (2026-09-28, per direct request - "remember that the calendar icon is skin dependent...
   you'll find the calendar icons in the native app per skin"): matches ItemsView.tsx's own
   per-skin ternary for the empty-date button exactly - Scrapbook uses the base (not a
   scrapbook-specific) calendar-icon.png there, Journal/Synthwave each have their own real art,
   Retro/default fall through to a plain tinted glyph in native (no custom art built for Retro yet
   either) - kept as the plain emoji here to match that same placeholder status. */
html[data-skin="scrapbook"] .task-date.no-date::before {
    content: none;
}
html[data-skin="scrapbook"] .task-date.no-date {
    background-image: url('/images/skins/calendar-icon.png');
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
    width: 24px;
    height: 24px;
    padding: 0;
}
html[data-skin="scrapbook"] .task-icon-row button {
    width: 32px;
    height: 32px;
}
/* Photo corner mounts - 4 separate PNGs, one per corner, poking slightly past the photo's own edge. */
html[data-skin="scrapbook"] .attachment-container {
    position: relative;
}
html[data-skin="scrapbook"] .attachment-container::before,
html[data-skin="scrapbook"] .attachment-container::after,
html[data-skin="scrapbook"] .photo-corner-bl,
html[data-skin="scrapbook"] .photo-corner-br {
    content: '';
    position: absolute;
    width: 22px;
    height: 22px;
    background-size: contain;
    background-repeat: no-repeat;
    pointer-events: none;
    z-index: 5;
}
html[data-skin="scrapbook"] .attachment-container::before {
    top: -6px;
    left: -6px;
    background-image: url('/images/skins/photo-corner-tl.png');
}
html[data-skin="scrapbook"] .attachment-container::after {
    top: -6px;
    right: -6px;
    background-image: url('/images/skins/photo-corner-tr.png');
}
/* Thumbtack pin - render.js sets data-pin (one of 5 colors) and --pin-left on the card. */
html[data-skin="scrapbook"] .task-item[data-pin] {
    position: relative;
}
html[data-skin="scrapbook"] .task-item[data-pin]::before {
    content: '';
    position: absolute;
    top: -14px;
    left: var(--pin-left, 50%);
    transform: translateX(-50%);
    width: 22px;
    height: 30px;
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
    z-index: 6;
}
html[data-skin="scrapbook"] .task-item[data-pin="red"]::before { background-image: url('/images/skins/pin-red.png'); }
html[data-skin="scrapbook"] .task-item[data-pin="blue"]::before { background-image: url('/images/skins/pin-blue.png'); }
html[data-skin="scrapbook"] .task-item[data-pin="green"]::before { background-image: url('/images/skins/pin-green.png'); }
html[data-skin="scrapbook"] .task-item[data-pin="orange"]::before { background-image: url('/images/skins/pin-orange.png'); }
html[data-skin="scrapbook"] .task-item[data-pin="purple"]::before { background-image: url('/images/skins/pin-purple.png'); }
/* Washi tape - render.js adds up to 2 .washi-tape child divs (left/right corner) with inline
   background-color + position/rotation, matching native's own per-entry hash-based jitter. */
.washi-tape {
    position: absolute;
    top: 0;
    width: 54px;
    height: 20px;
    opacity: 0.8;
    border-radius: 2px;
    pointer-events: none;
    z-index: 6;
}

/* ── JOURNAL (Nostalgic Journal) ── */
html[data-skin="journal"] .main-sticky-header {
    background: #7A1F35;
}
html[data-skin="journal"] .main-sticky-header .list-header h2 {
    color: #F3E9D3;
}
html[data-skin="journal"] .header-pill-primary {
    background: #2E4A34;
}
html[data-skin="journal"] .main-scrollable-content {
    background-color: #A6875F;
    background-image: url('/images/skins/journal-background.webp');
    background-repeat: repeat;
}
html[data-skin="journal"] .task-item {
    background-color: #F3E9D3;
    background-image: url('/images/skins/journal-card-middle.png');
    background-repeat: repeat;
    border-color: #8B7355;
}
html[data-skin="journal"] .task-title {
    font-family: 'EB Garamond', serif;
    font-weight: 700;
}
html[data-skin="journal"] .task-date,
html[data-skin="journal"] .comment-date,
html[data-skin="journal"] .comment-text {
    font-family: 'EB Garamond', serif;
}
html[data-skin="journal"] .comment-item-even {
    background-color: #F8F2E2;
    border: 1px solid #78350F;
}
html[data-skin="journal"] .comment-item-odd {
    background-color: #D9C49C;
    border: 1px solid #E5D5BC;
}
/* 🔒 (2026-10-01, per the owner - more contrast): the date was light grey (#999) on parchment; now the
   skin's Journal Antique Bronze ink, as in the native app. */
html[data-skin="journal"] .comment-date {
    color: #78350F;
}
html[data-skin="journal"] .comment-avatar,
html[data-skin="journal"] .task-creator-avatar {
    box-shadow: 0 0 0 2px #F3E9D3;
}
/* Etched-metal icon art, swapped in for the plain emoji (font-size:0 hides the glyph, the
   background-image shows the real art - same trick used for every icon swap below). */
html[data-skin="journal"] .add-photo-btn {
    font-size: 0;
    background-image: url('/images/skins/journal-camera-icon.png');
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
}
html[data-skin="journal"] .add-comment-inline-btn {
    font-size: 0;
    background-image: url('/images/skins/journal-comment-icon.png');
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
}
html[data-skin="journal"] .delete-task-btn {
    font-size: 0;
    background-image: url('/images/skins/journal-trash-icon.png');
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
}
/* 🔒 FIX (2026-09-28, per direct request - "remember that the calendar icon is skin dependent") -
   see the matching Scrapbook comment above for the full story. */
html[data-skin="journal"] .task-date.no-date::before {
    content: none;
}
html[data-skin="journal"] .task-date.no-date {
    background-image: url('/images/skins/journal-calendar-icon.png');
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
    width: 24px;
    height: 24px;
    padding: 0;
}
html[data-skin="journal"] .task-icon-row button {
    width: 32px;
    height: 32px;
}
/* Pin (gold/silver/bronze) - same mechanism as Scrapbook's, different image set. */
html[data-skin="journal"] .task-item[data-pin] {
    position: relative;
}
html[data-skin="journal"] .task-item[data-pin]::before {
    content: '';
    position: absolute;
    top: -14px;
    left: var(--pin-left, 50%);
    transform: translateX(-50%);
    width: 22px;
    height: 22px;
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
    z-index: 6;
}
html[data-skin="journal"] .task-item[data-pin="gold"]::before { background-image: url('/images/skins/journal-pin-gold.png'); }
html[data-skin="journal"] .task-item[data-pin="silver"]::before { background-image: url('/images/skins/journal-pin-silver.png'); }
html[data-skin="journal"] .task-item[data-pin="bronze"]::before { background-image: url('/images/skins/journal-pin-bronze.png'); }

/* ── RETRO (Retro Pixel Art) ── */
html[data-skin="retro"] .main-sticky-header {
    background: #7B2CBF;
}
html[data-skin="retro"] .main-sticky-header .list-header h2 {
    color: #FFFFFF;
}
html[data-skin="retro"] .header-pill-primary {
    background: #4ADE80;
}
html[data-skin="retro"] .main-scrollable-content {
    background-color: #FFFFFF;
    background-image: url('/images/skins/retro-grid-background.png');
    background-repeat: repeat;
}
html[data-skin="retro"] .task-item {
    background: #DFD2F7;
    /* 8-bit "drop shadow" - thin top/left, thick bottom/right, standing in for a real shadow
       (matches native's own asymmetric-border trick exactly). */
    border-style: solid;
    border-color: #1E1B4A;
    border-width: 2px 4px 4px 2px;
}
html[data-skin="retro"] .task-title {
    font-family: 'Press Start 2P', monospace;
    font-size: 0.85em; /* Press Start 2P runs visually large at the same declared size */
}
html[data-skin="retro"] .task-date,
html[data-skin="retro"] .comment-date,
html[data-skin="retro"] .comment-text {
    font-family: 'VT323', monospace;
    font-size: 1.15em; /* VT323 reads smaller than other faces - native applies the same +15% */
}
html[data-skin="retro"] .comment-item-even {
    background-color: #E0F7FA;
    border: 1px solid #1E1B4A;
}
html[data-skin="retro"] .comment-item-odd {
    background-color: #FEF9C3;
    border: 1px solid #7B2CBF;
}
html[data-skin="retro"] .comment-avatar,
html[data-skin="retro"] .task-creator-avatar {
    box-shadow: 0 0 0 2px #4ADE80;
}

/* ── SYNTHWAVE (Neon Synthwave) ── */
html[data-skin="synthwave"] .main-sticky-header {
    background: #0D0221;
}
html[data-skin="synthwave"] .main-sticky-header .list-header h2 {
    color: #FFFFFF;
}
html[data-skin="synthwave"] .header-pill-primary {
    background: #FF2EC4;
}
html[data-skin="synthwave"] .main-scrollable-content {
    background-color: #0D0221;
    background-image: url('/images/skins/synthwave-grid-background.png');
    background-repeat: repeat;
}
html[data-skin="synthwave"] .task-item {
    /* Violet-tinted "glass" card, no blur library needed on native and none here either - a solid
       neon border stands in for a shadow (a real shadow on a translucent card would show as a
       rectangular halo past the rounded corners). */
    background: rgba(139, 92, 246, 0.14);
    border: 2px solid #00D4FF;
    box-shadow: none;
}
html[data-skin="synthwave"] .task-title,
html[data-skin="synthwave"] .task-date,
html[data-skin="synthwave"] .comment-date,
html[data-skin="synthwave"] .comment-text {
    /* isDarkBackground skin - free-standing text must be white, not the app's default dark gray. */
    color: #FFFFFF;
}
html[data-skin="synthwave"] .task-title {
    font-family: 'Audiowide', sans-serif;
}

/* 🔤 (2026-09-29, per direct request - "the title and the header needs to use the skin font"): the
   open Book's name and the header's Add Top 10 List / Add Entry pills use the same title face as
   that skin's entry titles above, matching the native app's skinned header. Retro's Press Start 2P
   runs large, so its sizes step down; the default skin keeps the system font. */
/* (same day, per direct request - "same change for the title in the list screen"): the Books
   screen's "[Name] and [Name]'s / Shared Scrapbook" header title (#sidebar-title) too. */
html[data-skin="scrapbook"] #current-list-name,
html[data-skin="scrapbook"] .header-pill,
html[data-skin="scrapbook"] #sidebar-title,
html[data-skin="scrapbook"] #sidebar-title *,
html[data-skin="scrapbook"] .cover-note-bubble,
html[data-skin="scrapbook"] .cover-note-dialog .confirm-dialog-btn {
    font-family: 'Fredoka', sans-serif;
    font-weight: 700;
}
html[data-skin="journal"] #current-list-name,
html[data-skin="journal"] .header-pill,
html[data-skin="journal"] #sidebar-title,
html[data-skin="journal"] #sidebar-title *,
html[data-skin="journal"] .cover-note-bubble,
html[data-skin="journal"] .cover-note-dialog .confirm-dialog-btn {
    font-family: 'EB Garamond', serif;
    font-weight: 700;
}
html[data-skin="retro"] #current-list-name,
html[data-skin="retro"] .header-pill,
html[data-skin="retro"] #sidebar-title,
html[data-skin="retro"] #sidebar-title *,
html[data-skin="retro"] .cover-note-bubble,
html[data-skin="retro"] .cover-note-dialog .confirm-dialog-btn {
    font-family: 'Press Start 2P', monospace;
    font-weight: 400;
}
html[data-skin="retro"] .cover-note-bubble { font-size: 0.68rem; line-height: 1.7; }
html[data-skin="retro"] .cover-note-dialog .confirm-dialog-btn { font-size: 0.62rem; line-height: 1.6; }
html[data-skin="retro"] #current-list-name { font-size: calc(1.35rem * var(--title-scale, 1)); line-height: 1.5; }
html[data-skin="retro"] .header-pill { font-size: 0.62rem; }
html[data-skin="retro"] #sidebar-title { font-size: 0.72rem; line-height: 1.6; }
html[data-skin="synthwave"] #current-list-name,
html[data-skin="synthwave"] .header-pill,
html[data-skin="synthwave"] #sidebar-title,
html[data-skin="synthwave"] #sidebar-title *,
html[data-skin="synthwave"] .cover-note-bubble,
html[data-skin="synthwave"] .cover-note-dialog .confirm-dialog-btn {
    font-family: 'Audiowide', sans-serif;
    font-weight: 400;
}
html[data-skin="synthwave"] .task-date,
html[data-skin="synthwave"] .comment-date,
html[data-skin="synthwave"] .comment-text {
    font-family: 'Rajdhani', sans-serif;
}
html[data-skin="synthwave"] .comment-item-even {
    background-color: rgba(45, 27, 105, 0.55);
    border: 1px solid #00D4FF;
}
html[data-skin="synthwave"] .comment-item-odd {
    background-color: rgba(0, 212, 255, 0.10);
    border: 1px solid #FF2EC4;
}
html[data-skin="synthwave"] .comment-avatar,
html[data-skin="synthwave"] .task-creator-avatar {
    box-shadow: 0 0 0 2px #00D4FF;
}
html[data-skin="synthwave"] .add-photo-btn {
    font-size: 0;
    background-image: url('/images/skins/synthwave-camera-icon.png');
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
}
html[data-skin="synthwave"] .add-comment-inline-btn {
    font-size: 0;
    background-image: url('/images/skins/synthwave-comment-icon.png');
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
}
html[data-skin="synthwave"] .delete-task-btn {
    font-size: 0;
    background-image: url('/images/skins/synthwave-trash-icon.png');
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
}
/* 🔒 FIX (2026-09-28, per direct request - "remember that the calendar icon is skin dependent") -
   see the matching Scrapbook comment above for the full story. */
html[data-skin="synthwave"] .task-date.no-date::before {
    content: none;
}
html[data-skin="synthwave"] .task-date.no-date {
    background-image: url('/images/skins/synthwave-calendar-icon.png');
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
    width: 24px;
    height: 24px;
    padding: 0;
}
html[data-skin="synthwave"] .task-icon-row button {
    width: 32px;
    height: 32px;
}
/* Photo captions - Synthwave's own documented gotcha: the base caption style is a light gray text
   on a light background, invisible against this skin's dark glass card. */
html[data-skin="synthwave"] .attachment-caption {
    color: #FFFFFF;
    background: rgba(13, 2, 33, 0.75);
    border-radius: 4px;
}
/* 🔒 FIX (2026-09-27, device repro - "Top 10 List Sub Entries are not properly displaying their
   content in the Neon Synth skin. it is white on white"): the REAL bug wasn't the white text (every
   other synthwave surface is white-on-dark and reads fine) - .subtasks (the container Top10
   children, and any other nested sub-items, render inside) had no skin override at all, so it kept
   its hardcoded light var(--bg-color) fill under this skin's forced-white text. Every other skin's
   sub-items sit on a light .subtasks background with dark text, which is why this was the one skin
   where it broke - darkening the container (Synth Deep Purple, colors.synthDeepPurple) instead of
   lightening the text keeps synthwave's own dark-card/light-text language consistent everywhere. */
html[data-skin="synthwave"] .subtasks {
    background: #2D1B69;
}

/* Appearance skin picker modal */
/* 🔒 REDESIGN (2026-09-27, per direct request - "revise the Appearance button to put up a drop down
   list instead of a modal... mirrors the native app") - a small anchored card (position set inline
   per-open by openAppearanceModal, modals.js, since it can be triggered from either nav bar
   instance) instead of a centered .modal overlay. No backdrop - dismissed by picking an option or
   clicking outside (the outside-click listener modals.js attaches). */
.appearance-dropdown {
    position: fixed;
    z-index: 1000;
    width: 260px;
    max-height: 70vh;
    overflow-y: auto;
    background: var(--card-bg);
    border-radius: 12px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
    padding: 8px;
}

.appearance-skin-list {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.appearance-skin-option {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    padding: 10px 12px;
    border: 2px dashed transparent;
    border-radius: 8px;
    background: var(--card-bg);
    cursor: pointer;
    text-align: left;
    transition: border-color 0.15s, background-color 0.15s;
}

.appearance-skin-option:hover {
    background: var(--bg-color);
}

/* Dashed border marks the current selection (matches native's own dropdown exactly) instead of a
   checkmark - the live font preview on the label already makes each row self-explanatory. */
.appearance-skin-option-active {
    border-color: var(--primary-color);
    background: rgba(124, 58, 237, 0.06);
}

.appearance-skin-swatch {
    width: 32px;
    height: 32px;
    border-radius: 8px;
    border: 1px solid var(--border-color);
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-color);
    overflow: hidden;
}

.appearance-skin-icon-img {
    width: 24px;
    height: 24px;
    object-fit: contain;
}

.appearance-skin-emoji {
    font-size: 1.25rem;
}

.appearance-skin-label {
    flex: 1;
    font-size: 0.95rem;
    color: var(--text-color);
}

.appearance-skin-check {
    color: var(--primary-color);
    font-weight: 700;
}

/* Cross-Book search modal (2026-09-27, PWA Phase 3) - reuses the existing .search-results-header/
   .search-result-item/etc. styling above as-is (identical result markup), just wraps it in a real
   modal card instead of the old inline-panel layout. */
.search-modal-content {
    max-width: 480px;
    max-height: 80vh;
    display: flex;
    flex-direction: column;
}

.search-modal-input-row {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 12px;
}

.search-modal-input-row .search-input {
    flex: 1;
}

.btn-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    flex-shrink: 0;
    border: none;
    border-radius: 50%;
    background: var(--border-color);
    color: var(--text-color);
    font-size: 1rem;
    cursor: pointer;
    transition: background-color 0.15s;
}

.btn-icon:hover {
    background: var(--primary-color);
    color: white;
}

.search-modal-results {
    overflow-y: auto;
    flex: 1;
}

.top10-number {
    font-weight: 700;
    font-size: 0.9rem;
    color: var(--primary-color);
    min-width: 24px;
    flex-shrink: 0;
}

/* Drag handle for top10 sub-items */
.top10-drag-handle {
    cursor: grab;
    color: var(--text-muted);
    font-size: 0.8rem;
    user-select: none;
    flex-shrink: 0;
    padding: 0 2px;
}

.top10-drag-handle:active {
    cursor: grabbing;
}

/* Visible text entry outline for top10 sub-items */
.top10-child .task-title {
    border: 1px solid var(--border-color);
    border-radius: 6px;
    padding: 6px 10px;
    min-height: 32px;
    display: flex;
    align-items: center;
}

.top10-child .task-title:hover {
    border-color: var(--primary-color);
    background: white;
}

.top10-child .task-title:has(.inline-task-edit) {
    border-color: var(--primary-color);
    background: white;
}

.top10-child .inline-task-edit {
    border: none;
    padding: 0;
    min-height: 0;
    box-shadow: none;
    background: transparent;
}

/* Creator avatar inline for top10 children (between # and text) */
.top10-child .task-creator-avatar-inline {
    width: 22px;
    height: 22px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: var(--primary-color);
    color: white;
    font-size: 0.5rem;
    font-weight: 600;
    flex-shrink: 0;
    overflow: hidden;
}

.top10-child .task-creator-avatar-inline img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Add Entry modal's own fields (2026-09-27 - the container that used to hold these was .add-item-form/.add-item-extras;
   Cancel/Add now use the same generic .btn-secondary/.btn-primary + .modal-actions every other modal in this app uses,
   so only the textarea and the date/photo row need their own rules here). */
.add-entry-modal-content textarea#new-item-input {
    width: 100%;
    padding: 12px 16px;
    border: 1px solid var(--border-color);
    border-radius: 12px;
    font-size: 1rem;
    font-family: inherit;
    line-height: 1.4;
    resize: none;
    box-sizing: border-box;
    margin-bottom: 12px;
}

.add-entry-modal-content textarea#new-item-input:focus {
    outline: none;
    box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.2);
    border-color: var(--primary-color);
}

.add-entry-modal-row {
    display: flex;
    gap: 12px;
    align-items: center;
    margin-bottom: 8px;
}

.item-date-input {
    padding: 12px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    font-size: 0.9rem;
    color: var(--text-color);
    background: var(--card-bg);
    cursor: pointer;
}

.task-date-input:focus {
    outline: none;
    border-color: var(--primary-color);
}

.file-input-label {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 12px 16px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: var(--card-bg);
    cursor: pointer;
    transition: border-color 0.15s;
}

.file-input-label:hover {
    border-color: var(--primary-color);
}

.file-input-label input[type="file"] {
    display: none;
}

.file-input-icon {
    font-size: 1.2rem;
}

.file-count {
    font-size: 0.8rem;
    color: var(--primary-color);
    font-weight: 500;
}

/* Modal Styles */
.modal {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.5);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;
}

/* Confirm modal needs higher z-index to appear above other modals */
#confirm-modal {
    z-index: 1100;
}

.modal-content {
    background: var(--card-bg);
    padding: 24px;
    border-radius: 12px;
    width: 100%;
    max-width: 400px;
    box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2);
}

.modal-content h3 {
    margin-bottom: 16px;
    font-size: 1.125rem;
}

.modal-content input,
.modal-content textarea {
    width: 100%;
    padding: 8px;
    border: 1px solid var(--border-color);
    border-radius: 6px;
    font-size: 1.4rem;
    margin-bottom: 16px;
    font-family: inherit;
}

.modal-content textarea {
    height: auto;
    max-height: 300px;
    resize: none;
    line-height: 1.3;
    overflow-y: auto;
    flex: 1;
}

.modal-content input:focus,
.modal-content textarea:focus {
    outline: none;
    border-color: var(--primary-color);
}

/* Edit modal input wrapper with indicator */
.edit-input-wrapper {
    display: flex;
    gap: 12px;
    align-items: flex-start;
    margin-bottom: 16px;
}

.selected-emoji-indicator {
    font-size: 32px;
    width: 50px;
    height: auto;
    display: flex;
    align-items: center;
    justify-content: center;
    padding-top: 12px;
    flex-shrink: 0;
}

/* Color picker in modal */
.color-picker-container {
    margin-bottom: 16px;
}

.color-picker-container label {
    display: block;
    font-size: 0.875rem;
    color: var(--text-muted);
    margin-bottom: 8px;
    white-space: nowrap;
    overflow: visible;
}

.color-picker {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}

.color-swatch {
    width: 32px;
    height: 32px;
    border-radius: 6px;
    border: 2px solid transparent;
    cursor: pointer;
    transition: all 0.15s;
}

.color-swatch:hover {
    transform: scale(1.1);
}

.color-swatch.selected {
    border-color: var(--text-color);
    box-shadow: 0 0 0 2px white, 0 0 0 4px var(--text-color);
}

.shape-picker {
    display: flex;
    gap: 8px;
    margin-top: 12px;
}

.shape-picker-label {
    display: block;
    font-size: 0.875rem;
    color: var(--text-muted);
    margin-bottom: 8px;
}

.shape-btn {
    width: 40px;
    height: 40px;
    border-radius: 8px;
    border: 2px solid transparent;
    background: var(--border-color);
    cursor: pointer;
    font-size: 1.25rem;
    line-height: 1;
    transition: all 0.15s;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-color);
}

.shape-btn:hover {
    transform: scale(1.1);
}

.shape-btn.selected {
    border-color: var(--text-color);
    box-shadow: 0 0 0 2px white, 0 0 0 4px var(--text-color);
}

/* Crop Modal */
.crop-modal-content {
    max-width: 500px;
}

.crop-instructions {
    font-size: 0.85rem;
    color: var(--text-muted);
    margin-bottom: 12px !important;
    text-align: center;
}

.crop-viewport {
    width: 100%;
    aspect-ratio: 26 / 15;
    overflow: hidden;
    border-radius: 8px;
    border: 2px solid var(--border-color);
    position: relative;
    cursor: grab;
    background: #000;
    touch-action: none;
    user-select: none;
    -webkit-user-select: none;
}

.crop-viewport:active {
    cursor: grabbing;
}

.crop-viewport img {
    position: absolute;
    top: 0;
    left: 0;
    transform-origin: 0 0;
    will-change: transform;
    pointer-events: none;
    max-width: none;
}

.crop-zoom-control {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 12px 0;
    padding: 0 16px;
}

.crop-zoom-control span {
    color: var(--text-muted);
    font-size: 1.2rem;
    font-weight: 600;
    user-select: none;
}

.crop-zoom-control input[type="range"] {
    flex: 1;
    accent-color: var(--primary-color);
    margin: 0;
    padding: 0;
    border: none;
}

/* Success toast */
.success-toast {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.5);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 2000;
}

.success-toast-message {
    background: white;
    padding: 32px;
    border-radius: 16px;
    text-align: center;
    max-width: 400px;
    margin: 20px;
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
}

.success-toast-message .success-toast-icon {
    width: 56px;
    height: 56px;
    background: linear-gradient(135deg, #10b981, #34d399);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0 auto 16px;
    font-size: 1.8rem;
    color: white;
}

.success-toast-message h4 {
    font-size: 1.15rem;
    color: var(--text-color);
    margin-bottom: 8px;
}

.success-toast-message p {
    color: var(--text-muted);
    margin-bottom: 16px;
    line-height: 1.5;
    font-size: 0.95rem;
}

.modal-content p {
    color: var(--text-muted);
    margin-bottom: 16px;
}

/* Profile Setup Modal */
.profile-setup-content {
    text-align: center;
}

.profile-setup-content h3 {
    font-size: 1.25rem;
}

.profile-preview {
    width: 120px;
    height: 120px;
    margin: 24px auto;
    border-radius: 50%;
    overflow: hidden;
    background: var(--bg-color);
    display: flex;
    align-items: center;
    justify-content: center;
    border: 3px solid var(--border-color);
}

.profile-preview img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.profile-placeholder {
    font-size: 3rem;
    color: var(--text-muted);
}

.modal-actions {
    display: flex;
    gap: 12px;
    justify-content: flex-start;
    align-items: center;
}

.modal-actions-spacer {
    flex: 1;
}

.btn-hide-list {
    background: transparent;
    border: 2px solid #ef4444;
    color: #ef4444;
    padding: 8px 16px;
    border-radius: 6px;
    font-size: 0.875rem;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.15s;
    flex-shrink: 0;
}

.btn-hide-list:hover {
    background: #ef4444;
    color: #ffffff;
}

.btn-hide-list:active {
    transform: scale(0.98);
}

.btn-primary,
.btn-secondary,
.btn-danger {
    padding: 10px 20px;
    border: none;
    border-radius: 6px;
    cursor: pointer;
    font-size: 0.875rem;
    transition: background-color 0.15s;
}

.btn-primary {
    background: var(--primary-color);
    color: white;
}

.btn-primary:hover {
    background: var(--primary-hover);
}

.btn-secondary {
    background: var(--bg-color);
    color: var(--text-color);
}

.btn-secondary:hover {
    background: var(--border-color);
}

.btn-danger {
    background: var(--danger-color);
    color: white;
}

.btn-danger:hover {
    background: #dc2626;
}

/* Sidebar Footer */
.sidebar-footer {
    padding: 16px;
    border-top: 1px solid rgba(255, 255, 255, 0.1);
    margin-top: auto;
}

.group-settings-btn {
    width: 100%;
    padding: 12px 16px;
    background: linear-gradient(135deg, rgba(124, 58, 237, 0.3), rgba(236, 72, 153, 0.3));
    border: 1px solid rgba(255, 255, 255, 0.15);
    border-radius: 8px;
    font-size: 1.25rem;
    font-weight: 600;
    color: var(--sidebar-text);
    font-size: 0.9rem;
    cursor: pointer;
    transition: background-color 0.15s;
    text-align: left;
}

.group-settings-btn:hover {
    background: linear-gradient(135deg, rgba(124, 58, 237, 0.45), rgba(236, 72, 153, 0.45));
    border-color: rgba(255, 255, 255, 0.25);
}

/* 🧭 Persistent nav bar (2026-09-27, "introduce the nav bar with the exact same functionality of the
   Native app"): shared row/button styling for BOTH instances - the wide sidebar-footer bar
   (Search/Appearance/Settings, id="group-settings-btn" wired via app.js for the Settings button
   specifically) and the narrow #mobile-nav-bar (Books/Search/Appearance/Settings). Two separate DOM
   instances rather than one repositioned element, because one lives inside the sidebar's own flow
   (pushed to its bottom via margin-top:auto) and the other is fixed to the viewport - trying to make
   one element serve both would fight its own positioning at the breakpoint. The @media block below
   shows exactly one of the two at a time, matching native's own single bottom tab bar. */
.app-nav-bar {
    display: flex;
    flex-direction: row;
    align-items: stretch;
    justify-content: space-around;
    gap: 4px;
    padding: 0;
    background: transparent;
    border: none;
}

.nav-bar-btn {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    padding: 8px 4px;
    background: transparent;
    border: none;
    border-radius: 8px;
    color: var(--sidebar-text);
    cursor: pointer;
    transition: background-color 0.15s;
}

.nav-bar-btn:hover {
    background: rgba(255, 255, 255, 0.08);
}

.nav-bar-icon {
    font-size: 1.25rem;
    line-height: 1;
}

/* 🔒 FIX (2026-09-28, per direct request): custom Search/Settings nav icons - font-size (above)
   sizes an emoji glyph but does nothing for an <img>, so this gives the replacement icons an
   explicit box matching that same ~20px visual size. */
.nav-bar-icon-img {
    width: 1.25rem;
    height: 1.25rem;
    display: block;
}

.nav-bar-label {
    font-size: 0.7rem;
    font-weight: 600;
    white-space: nowrap;
}

/* The standalone, viewport-fixed instance only ever appears at the narrow breakpoint (see the
   @media block below) - hidden here so a wide screen never briefly shows it before that rule loads. */
#mobile-nav-bar {
    display: none;
}

/* Group Settings Modal */
.group-settings-content {
    max-width: 450px;
}

.group-settings-section {
    margin-bottom: 20px;
}

.group-settings-section label {
    display: block;
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--text-muted);
    margin-bottom: 8px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

/* About / Privacy section */
.about-section {
    border-top: 1px solid var(--border-color);
    padding-top: 16px;
}

.privacy-policy-btn {
    font-size: 0.85rem;
    color: var(--text-muted);
    cursor: pointer;
    padding: 0;
    border: none;
    background: none;
    text-decoration: underline;
}

.privacy-policy-btn:hover {
    color: var(--primary-color);
}

.about-content {
    background: rgba(124, 58, 237, 0.05);
    border-radius: 8px;
    padding: 16px;
}

.about-heading {
    font-weight: 600;
    font-size: 0.95rem;
    color: var(--text-color);
    margin-bottom: 8px !important;
}

.about-content p {
    font-size: 0.8rem;
    line-height: 1.6;
    color: var(--text-muted);
    margin: 0;
}

#about-modal {
    z-index: 3100;
}

.about-modal-content {
    max-width: 420px;
}

/* Privacy link on login screen */
.privacy-link {
    display: block;
    text-align: center;
    margin-top: 20px;
    font-size: 0.8rem;
    color: var(--text-muted);
    text-decoration: none;
    transition: color 0.15s;
}

.privacy-link:hover {
    color: var(--primary-color);
}

.already-have-account {
    display: block;
    text-align: center;
    margin-top: 16px;
    font-size: 0.85rem;
    color: var(--text-muted);
    text-decoration: none;
    transition: color 0.15s;
}

.already-have-account span {
    color: var(--primary-color);
    font-weight: 500;
}

.already-have-account:hover span {
    text-decoration: underline;
}

/* Verification Screen */
.verification-content {
    text-align: center;
}

.verification-icon {
    font-size: 3rem;
    margin: 16px 0 8px;
}

.verification-heading {
    font-size: 1.3rem;
    color: var(--text-color);
    margin-bottom: 8px;
}

.verification-message {
    color: var(--text-muted);
    font-size: 0.95rem;
    line-height: 1.5;
    margin-bottom: 20px;
}

.verify-resend-btn {
    width: 100%;
    margin-top: 8px;
}

#verify-signout-link {
    display: block;
    margin-top: 16px;
}

.group-name-display {
    font-size: 1.25rem;
    font-weight: 600;
    color: var(--text-color);
    margin: 0;
}

.group-members-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.group-member-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 8px 12px;
    background: var(--bg-color);
    border-radius: 8px;
}

.group-member-avatar {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
}

.group-member-avatar-placeholder {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: var(--primary-color);
    color: white;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.875rem;
    font-weight: 600;
    flex-shrink: 0;
}

.group-member-info {
    flex: 1;
    min-width: 0;
}

.group-member-name {
    font-weight: 500;
    color: var(--text-color);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.group-member-role {
    font-size: 0.75rem;
    color: var(--text-muted);
}

.remove-member-btn {
    width: 28px;
    height: 28px;
    border: none;
    background: transparent;
    color: var(--text-muted);
    font-size: 1rem;
    cursor: pointer;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.15s;
    flex-shrink: 0;
}

.remove-member-btn:hover {
    background: var(--danger-color);
    color: white;
}

/* Profile Edit Section */
.profile-edit-section {
    background: var(--bg-color);
    border-radius: 8px;
    padding: 12px;
}

.profile-edit-row {
    display: flex;
    align-items: center;
    gap: 12px;
}

.profile-label {
    font-size: 0.875rem;
    color: var(--text-muted);
}

.profile-value {
    font-weight: 500;
    color: var(--text-color);
    flex: 1;
}

.btn-small {
    padding: 6px 12px;
    font-size: 0.8rem;
    border-radius: 4px;
    border: none;
    cursor: pointer;
}

.btn-small.btn-primary {
    background: var(--primary-color);
    color: white;
}

.btn-small.btn-secondary {
    background: var(--border-color);
    color: var(--text-color);
}

.profile-edit-form {
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px solid var(--border-color);
}

.profile-edit-form .form-group {
    margin-bottom: 12px;
}

.profile-edit-form label {
    display: block;
    font-size: 0.8rem;
    color: var(--text-muted);
    margin-bottom: 4px;
}

.profile-edit-form input {
    width: 100%;
    padding: 8px 12px;
    border: 1px solid var(--border-color);
    border-radius: 6px;
    font-size: 0.9rem;
}

.profile-edit-actions {
    display: flex;
    gap: 8px;
    justify-content: flex-end;
}

.section-header-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 8px;
}

.section-header-row label {
    margin-bottom: 0;
}

.profile-headshot-preview,
.edit-headshot-preview {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    overflow: hidden;
    background: var(--bg-color);
    flex-shrink: 0;
}

.profile-headshot-preview img,
.edit-headshot-preview img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.profile-headshot-placeholder,
.edit-headshot-placeholder {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--primary-color);
    color: white;
    font-size: 1.1rem;
    font-weight: 600;
}

.profile-info {
    flex: 1;
    display: flex;
    align-items: center;
    gap: 12px;
}

.headshot-edit-section {
    text-align: center;
    margin-bottom: 16px;
}

.edit-headshot-preview {
    width: 80px;
    height: 80px;
    margin: 0 auto 8px;
    position: relative;
    cursor: pointer;
}

.edit-headshot-overlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.4);
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    transition: opacity 0.2s;
    border-radius: 50%;
}

.edit-headshot-preview:hover .edit-headshot-overlay,
.edit-headshot-preview.drag-over .edit-headshot-overlay {
    opacity: 1;
}

.edit-headshot-preview.drag-over {
    border: 2px dashed var(--primary-color);
}

.edit-headshot-overlay span {
    font-size: 1.5rem;
}

.headshot-hint {
    font-size: 0.75rem;
    color: var(--text-muted);
    margin: 0;
}

/* Password Change Section */
.password-change-section {
    margin-top: 16px;
    padding-top: 16px;
    border-top: 1px solid var(--border-color);
}

.btn-link {
    background: none;
    border: none;
    color: var(--primary-color);
    cursor: pointer;
    font-size: 0.875rem;
    padding: 0;
    text-decoration: underline;
}

.btn-link:hover {
    color: var(--secondary-color);
}

.password-change-fields {
    margin-top: 12px;
}

.password-change-fields .form-group {
    margin-bottom: 12px;
}

.password-error {
    color: var(--danger-color);
    font-size: 0.875rem;
    margin: 8px 0 0 0;
}

.password-success {
    color: var(--success-color);
    font-size: 0.875rem;
    margin: 8px 0 0 0;
}

.invite-instructions {
    font-size: 0.875rem;
    color: var(--text-muted);
    margin-bottom: 8px !important;
}

.invite-link-container {
    display: flex;
    gap: 8px;
}

.invite-link-container input {
    flex: 1;
    margin-bottom: 0 !important;
    font-size: 0.875rem;
    background: var(--bg-color);
    color: var(--text-color);
}

.invite-link-container button {
    flex-shrink: 0;
    white-space: nowrap;
}

.copy-feedback {
    font-size: 0.875rem;
    color: var(--success-color);
    margin-top: 8px !important;
    margin-bottom: 0 !important;
}

.copy-feedback.hidden {
    display: none;
}

/* Photo Lightbox (2026-10-01) - full screen and black like native's caption lightbox; behaviour in js/lightbox.js.
   Palette: black (listColors Black #000000), Dark Purple #6d28d9, Light Purple #a78bfa, Purple #7c3aed (native's
   caption-box border / ✓ button), textMuted #9CA3AF, textLight #E5E7EB, textGray #6B7280, white. */
.lightbox {
    position: fixed;
    inset: 0;
    background: #000000;
    z-index: 2000;
    overflow: hidden;
    overscroll-behavior: contain;
}

.lightbox.hidden {
    display: none;
}

body.lightbox-open {
    overflow: hidden;
}

/* Sized to the visible viewport by lbSyncViewport (a phone keyboard shrinks it; the photo gives up the room). */
.lb-shell {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    max-width: 900px;
    margin: 0 auto;
    right: 0;
    background: #000000;
    color: #FFFFFF;
    padding-top: env(safe-area-inset-top, 0px);
    padding-bottom: env(safe-area-inset-bottom, 0px);
    box-sizing: border-box;
}

.lb-shell button {
    font-family: inherit;
}

.lb-top {
    flex: 0 0 auto;
    padding: 12px;
}

.lb-close {
    width: 44px;
    height: 44px;
    border: none;
    border-radius: 50%;
    background: #7c3aed;
    color: #FFFFFF;
    font-size: 1.4rem;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
}

.lb-close:hover {
    background: #6d28d9;
}

.lb-photo-area {
    position: relative;
    flex: 1 1 auto;
    min-height: 72px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(255, 255, 255, 0.06);
    overflow: hidden;
}

.lb-photo-area.hidden,
.lb-photo-area img.hidden,
.lb-photo-area video.hidden {
    display: none;
}

#lightbox-image,
#lb-video {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
}

.lb-frame-btn {
    position: absolute;
    right: 12px;
    bottom: 10px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 32px;
    padding: 0 12px;
    border-radius: 16px;
    border: 1.5px solid #a78bfa;
    background: rgba(109, 40, 217, 0.9);
    color: #FFFFFF;
    font-size: 0.82rem;
    font-weight: 600;
    cursor: pointer;
}

.lb-frame-btn.hidden {
    display: none;
}

.lb-nav {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 20px;
}

.lb-nav.hidden {
    display: none;
}

.lb-nav-btn {
    width: 44px;
    height: 44px;
    border: none;
    background: transparent;
    color: #FFFFFF;
    font-size: 1.9rem;
    line-height: 1;
    cursor: pointer;
}

.lb-counter {
    color: #9CA3AF;
    font-size: 0.75rem;
}

.lb-caption-view {
    flex: 0 0 auto;
    padding: 16px 20px;
}

.lb-caption-view.hidden,
.lb-caption-edit.hidden,
.lb-framing.hidden {
    display: none;
}

.lb-caption-display {
    display: flex;
    align-items: flex-start;
    gap: 4px;
    width: 100%;
    padding: 0;
    border: none;
    background: transparent;
    text-align: left;
    cursor: pointer;
}

.lb-caption-text {
    flex: 1;
    color: #9CA3AF;
    font-size: 0.9rem;
    font-style: italic;
    line-height: 1.4;
    white-space: pre-wrap;
    overflow-wrap: break-word;
}

.lb-caption-text.placeholder {
    color: #6B7280;
}

.lb-pencil {
    flex: 0 0 auto;
    margin-top: 3px;
    color: #C8AD7F;
    font-size: 0.85rem;
}

.lb-caption-edit {
    flex: 0 0 auto;
    display: flex;
    gap: 12px;
    align-items: flex-start;
    padding: 16px 20px 20px;
}

#lb-caption-input {
    flex: 1;
    min-height: 100px;
    max-height: 40vh;
    resize: none;
    box-sizing: border-box;
    padding: 12px;
    border-radius: 8px;
    border: 1px solid #7c3aed;
    background: rgba(255, 255, 255, 0.08);
    color: #FFFFFF;
    font-family: inherit;
    font-size: 16px; /* 16px stops iOS Safari zooming the page when the box gets focus */
    line-height: 1.4;
    outline: none;
}

#lb-caption-input::placeholder {
    color: #6B7280;
}

.lb-edit-buttons {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.lb-edit-cancel,
.lb-edit-save {
    width: 44px;
    height: 44px;
    border: none;
    border-radius: 50%;
    font-size: 1.1rem;
    font-weight: 700;
    cursor: pointer;
}

.lb-edit-cancel {
    background: #E5E7EB;
    color: #6B7280;
}

.lb-edit-save {
    background: #7c3aed;
    color: #FFFFFF;
}

/* Move & zoom */
.lb-framing {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-height: 0;
}

.lb-framing-stage {
    position: relative;
    width: 100%;
    overflow: hidden;
    touch-action: none;
    cursor: grab;
    user-select: none;
    -webkit-user-select: none;
}

.lb-framing-stage:active {
    cursor: grabbing;
}

.lb-ghost,
.lb-frame img {
    position: absolute;
    max-width: none;
    pointer-events: none;
    -webkit-user-drag: none;
}

.lb-ghost {
    opacity: 0.28;
}

.lb-frame {
    position: absolute;
    overflow: hidden;
    border-radius: 8px;
    background: rgba(255, 255, 255, 0.08);
}

.lb-frame-edge {
    position: absolute;
    border: 2px solid #a78bfa;
    border-radius: 8px;
    box-sizing: border-box;
    pointer-events: none;
}

.lb-framing-hint {
    margin: 4px 20px 0;
    color: #9CA3AF;
    font-size: 0.82rem;
    text-align: center;
}

.lb-zoom-row {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 16px;
    margin-top: 12px;
}

.lb-round-btn {
    width: 44px;
    height: 44px;
    border: none;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.15);
    color: #FFFFFF;
    font-size: 1.6rem;
    line-height: 1;
    cursor: pointer;
}

.lb-round-btn:disabled {
    opacity: 0.35;
    cursor: default;
}

.lb-zoom-label {
    min-width: 48px;
    text-align: center;
    color: #E5E7EB;
    font-size: 0.82rem;
}

.lb-framing-actions {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px 20px 12px;
}

.lb-framing-actions-right {
    display: flex;
    gap: 10px;
}

.lb-pill {
    height: 40px;
    padding: 0 16px;
    border-radius: 20px;
    font-size: 0.88rem;
    font-weight: 600;
    cursor: pointer;
}

.lb-pill:disabled {
    opacity: 0.4;
    cursor: default;
}

.lb-pill-outline {
    border: 1.5px solid #a78bfa;
    background: transparent;
    color: #a78bfa;
}

.lb-pill-quiet {
    border: none;
    background: rgba(255, 255, 255, 0.15);
    color: #FFFFFF;
}

.lb-pill-primary {
    border: none;
    background: #6d28d9;
    color: #FFFFFF;
    font-weight: 700;
}

/* Skin fonts for photo captions - in the cards and in the lightbox - like native's PhotoCard caption list. */
html[data-skin="scrapbook"] .attachment-caption,
html[data-skin="scrapbook"] .lb-caption-text,
html[data-skin="scrapbook"] #lb-caption-input {
    font-family: 'Fredoka', system-ui, sans-serif;
    font-style: normal;
}
html[data-skin="journal"] .attachment-caption,
html[data-skin="journal"] .lb-caption-text,
html[data-skin="journal"] #lb-caption-input {
    font-family: 'EB Garamond', Georgia, serif;
    font-style: normal;
}
html[data-skin="retro"] .attachment-caption,
html[data-skin="retro"] .lb-caption-text,
html[data-skin="retro"] #lb-caption-input {
    font-family: 'VT323', monospace;
    font-style: normal;
}
html[data-skin="retro"] .attachment-caption,
html[data-skin="retro"] .lb-caption-text {
    font-size: 1.15em; /* VT323 reads smaller - native applies the same +15% */
}
html[data-skin="synthwave"] .attachment-caption,
html[data-skin="synthwave"] .lb-caption-text,
html[data-skin="synthwave"] #lb-caption-input {
    font-family: 'Rajdhani', system-ui, sans-serif;
    font-style: normal;
}

/* Walkthrough Overlay */
.walkthrough-overlay {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 10000;
    pointer-events: auto;
    overflow: visible;
}

.walkthrough-overlay.hidden {
    display: none;
}

.walkthrough-title {
    position: fixed;
    top: 40px;
    left: 50%;
    transform: translateX(-50%);
    text-align: center;
    color: white;
    z-index: 10002;
    pointer-events: none;
}

.walkthrough-title h2 {
    font-size: 1.5rem;
    font-weight: 700;
    margin: 0 0 8px 0;
}

.walkthrough-title p {
    font-size: 1rem;
    margin: 0;
    opacity: 0.85;
}

.walkthrough-title.hidden {
    display: none;
}

.walkthrough-highlight {
    position: absolute;
    border: 3px solid #a855f7;
    border-radius: 12px;
    box-shadow: 0 0 20px #a855f7, 0 0 0 9999px rgba(0, 0, 0, 0.7);
    pointer-events: none;
    transition: top 0.3s ease, left 0.3s ease, width 0.3s ease, height 0.3s ease;
    animation: walkthrough-pulse 2s ease-in-out infinite;
    z-index: 1;
}

@keyframes walkthrough-pulse {
    0%, 100% {
        box-shadow: 0 0 15px #a855f7, 0 0 0 9999px rgba(0, 0, 0, 0.7);
    }
    50% {
        box-shadow: 0 0 35px #a855f7, 0 0 0 9999px rgba(0, 0, 0, 0.7);
    }
}

.walkthrough-tooltip {
    position: absolute;
    background: var(--card-bg);
    border-radius: 12px;
    padding: 20px;
    max-width: 320px;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
    z-index: 10001;
}

.walkthrough-step-indicator {
    font-size: 0.75rem;
    color: var(--text-muted);
    margin-bottom: 8px;
}

.walkthrough-step-indicator span {
    color: #a855f7;
    font-weight: 600;
}

.walkthrough-tooltip p {
    margin: 0 0 16px 0;
    font-size: 1rem;
    line-height: 1.5;
    color: var(--text-color);
}

.walkthrough-actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
}

/* Notifications status in settings */
.notifications-status-text {
    font-size: 0.85rem;
    color: var(--text-secondary);
    margin-top: 4px;
}

.btn-disabled {
    opacity: 0.5;
    cursor: default;
}

/* Branded App Message (cumulative notifications) */
.app-message-container {
    position: fixed;
    top: 20px;
    right: 20px;
    max-width: 360px;
    z-index: 10001;
    display: flex;
    flex-direction: column;
    gap: 8px;
    pointer-events: none;
}

.app-message-box {
    background: white;
    border-radius: 12px;
    padding: 16px 16px;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
    border-left: 4px solid #7c3aed;
    animation: slideInRight 0.3s ease-out;
    pointer-events: auto;
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 12px;
}

@keyframes slideInRight {
    from {
        transform: translateX(400px);
        opacity: 0;
    }
    to {
        transform: translateX(0);
        opacity: 1;
    }
}

.app-message-text {
    color: var(--text-color);
    font-size: 0.9rem;
    line-height: 1.5;
    flex: 1;
    white-space: pre-wrap;
    word-break: break-word;
}

.app-message-close {
    background: none;
    border: none;
    color: #9ca3af;
    cursor: pointer;
    padding: 0;
    font-size: 1rem;
    line-height: 1;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.app-message-close:hover {
    color: #6b7280;
}

/* Legacy overlay style (kept for backward compatibility) */
.app-message-overlay {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.5);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 10001;
}

.app-message-ok {
    min-width: 100px;
}

/* Offline Bar */
.offline-bar {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    background: linear-gradient(135deg, #f97316, #ef4444);
    color: white;
    text-align: center;
    padding: 6px 16px;
    font-size: 0.8rem;
    font-weight: 600;
    z-index: 9999;
}

/* Push Notification Toast */
.push-toast {
    position: fixed;
    top: 16px;
    right: 16px;
    background: linear-gradient(135deg, #1e1b4b, #312e81);
    color: white;
    padding: 12px 16px;
    border-radius: 12px;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
    z-index: 10000;
    max-width: 360px;
    cursor: pointer;
    animation: toast-slide-in 0.3s ease-out;
    display: flex;
    gap: 12px;
    align-items: flex-start;
}

.push-toast.hidden {
    display: none;
}

@keyframes toast-slide-in {
    from {
        transform: translateX(100%);
        opacity: 0;
    }
    to {
        transform: translateX(0);
        opacity: 1;
    }
}

/* Avatar with 💕 overlay */
.toast-avatar-container {
    position: relative;
    width: 56px;
    height: 56px;
    flex-shrink: 0;
}

.toast-avatar-image {
    width: 100%;
    height: 100%;
    border-radius: 50%;
    object-fit: cover;
    border: 2px solid rgba(255, 255, 255, 0.3);
}

.toast-avatar-initial {
    width: 100%;
    height: 100%;
    border-radius: 50%;
    background: linear-gradient(135deg, #7c3aed, #ec4899);
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 1.2rem;
    border: 2px solid rgba(255, 255, 255, 0.3);
}

.toast-avatar-heart {
    position: absolute;
    bottom: -4px;
    right: -4px;
    font-size: 1.4rem;
    background: rgba(0, 0, 0, 0.6);
    border-radius: 50%;
    width: 28px;
    height: 28px;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Toast content */
.toast-content {
    flex: 1;
    min-width: 0;
}

.toast-title {
    font-weight: 600;
    font-size: 0.95rem;
    margin-bottom: 4px;
    line-height: 1.3;
}

.toast-body {
    font-size: 0.8rem;
    opacity: 0.85;
    line-height: 1.4;
    word-break: break-word;
}

/* Collapse button */
.toast-collapse {
    flex-shrink: 0;
    background: none;
    border: none;
    color: white;
    font-size: 1.2rem;
    cursor: pointer;
    padding: 4px 8px;
    opacity: 0.6;
    transition: opacity 0.2s;
}

.toast-collapse:hover {
    opacity: 1;
}

/* Notification Permission Prompt */
.notification-prompt {
    position: fixed;
    bottom: 24px;
    left: 50%;
    transform: translateX(-50%);
    background: var(--card-bg);
    border-radius: 16px;
    padding: 20px 24px;
    box-shadow: 0 8px 40px rgba(0, 0, 0, 0.2);
    z-index: 9999;
    max-width: 360px;
    width: calc(100% - 32px);
    text-align: center;
}

.notification-prompt-text {
    font-size: 0.95rem;
    color: var(--text-color);
    margin-bottom: 16px;
    line-height: 1.5;
}

.notification-prompt-actions {
    display: flex;
    gap: 8px;
    justify-content: center;
}

.notification-prompt .btn-enable {
    background: linear-gradient(135deg, #7c3aed, #ec4899);
    color: white;
    border: none;
    padding: 10px 24px;
    border-radius: 8px;
    font-size: 0.9rem;
    font-weight: 600;
    cursor: pointer;
}

.notification-prompt .btn-skip {
    background: transparent;
    color: var(--text-muted);
    border: 1px solid var(--border-color);
    padding: 10px 20px;
    border-radius: 8px;
    font-size: 0.9rem;
    cursor: pointer;
}

/* Responsive - Mobile exclusive views */
@media (max-width: 768px) {
    .crop-modal-content {
        margin: 8px;
        max-width: calc(100% - 16px);
    }

    .app-container {
        flex-direction: column;
    }

    /* Default mobile state: sidebar visible, main hidden */
    /* 🔒 FIX (2026-09-29, phone repro - "either showing the header or the navbar but not both when
       there are a lot of books"): 100vh on mobile Chrome is the height with the address bar HIDDEN,
       taller than the visible screen while it shows - so a long Book list made the whole page scroll
       (header off the top) instead of just .lists-section. 100dvh is the visible height and follows
       the address bar; 100vh stays as the fallback for browsers without dvh. */
    .sidebar {
        width: 100%;
        height: 100vh;
        height: 100dvh;
        max-height: 100vh;
        max-height: 100dvh;
        min-height: unset;
        display: flex;
        flex-direction: column;
    }

    .main-content {
        display: none;
        padding: 12px;
        padding-bottom: 80px;
    }

    /* When a list is selected: sidebar hidden, main visible */
    .app-container.mobile-list-selected .sidebar {
        display: none;
    }

    .app-container.mobile-list-selected .main-content {
        display: flex;
        flex-direction: column;
        height: 100vh;
        height: 100dvh; /* same fix as .sidebar above */
    }

    /* 🧭 Persistent nav bar, narrow screens (2026-09-27, per direct decision - "On narrow PWA, 'Books'
       always means 'back to the Books list'... show it always, even deep inside a Book"): the
       sidebar's OWN nav bar never shows here, even while the sidebar itself is visible for browsing
       Books (the case just above, .mobile-list-selected NOT set) - #mobile-nav-bar covers every
       narrow-screen case on its own, so there's never a moment with two bars stacked or none at all. */
    .sidebar-footer.app-nav-bar {
        display: none !important;
    }

    #mobile-nav-bar:not(.hidden) {
        display: flex;
        position: fixed;
        bottom: 0;
        left: 0;
        right: 0;
        z-index: 500;
        padding: 4px 8px calc(4px + env(safe-area-inset-bottom, 0px));
        background: var(--card-bg);
        border-top: 1px solid var(--border-color);
        box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.06);
    }

    /* The mobile bar sits on --card-bg (white), not the sidebar's own dark background - .nav-bar-btn's
       default color (--sidebar-text, a light gray meant for the dark sidebar) would be nearly
       invisible here. */
    #mobile-nav-bar .nav-bar-btn {
        color: var(--text-color);
    }

    #mobile-nav-bar .nav-bar-btn:hover {
        background: var(--border-color);
    }

    /* Keeps the sidebar's own last Book from hiding behind the fixed bar, same treatment
       .main-content already has just below for the Book-content case.
       🔒 FIX (2026-09-29, phone repro - "a big open space between the Add New Book button and the nav
       bar"): was a flat 80px plus a 100dvh height. The bar's real height varies (59px on a plain
       412px screen, more with the gesture-bar inset), and 100dvh did not end where the fixed bar's
       bottom:0 sits, leaving a white strip too. Now pinned to the same viewport edges as the bar
       (position: fixed, top/bottom 0) and padded by the bar's MEASURED height, --mobile-nav-h, set by
       a ResizeObserver on #mobile-nav-bar (app.js). */
    .sidebar {
        position: fixed;
        top: 0;
        bottom: 0;
        left: 0;
        right: 0;
        height: auto;
        max-height: none;
        padding-bottom: calc(var(--mobile-nav-h, 64px) + 8px);
    }

    /* (2026-09-27, device repro, circled - "eliminate this books button as well so we get a clean
       header"): the "← Books" in-header back button used to be re-shown here on narrow screens - now
       redundant, since the persistent nav bar's own Books button (always visible, per decision 2 -
       "On narrow PWA, 'Books' always means 'back to the Books list'") already does this exact job.
       Removed the override entirely; the base rule (.back-to-lists-btn, "hidden on desktop", further
       up this file) now applies everywhere, narrow included. Button and its #back-to-lists click
       handler are left in place, just permanently hidden - same pattern as the old search box. */

    .sidebar-header {
        display: flex;
        align-items: center;
        gap: 12px;
        padding: 12px;
        text-align: left;
    }

    .us-logo {
        margin-bottom: 0;
        flex-shrink: 0;
    }

    .us-logo-hearts {
        font-size: 1.1rem;
    }

    .us-logo-text {
        font-size: 0.85rem;
    }

    .sidebar-header h1 {
        font-size: 0.95rem;
        flex: 1;
        line-height: 1.3;
    }

    .header-photo-container {
        margin-top: 0;
        flex-shrink: 0;
        width: 50px;
        height: 50px;
    }

    .header-photo {
        width: 50px;
        height: 50px;
        max-height: 50px;
        border-radius: 50%;
        object-fit: cover;
    }

    .header-photo-overlay {
        border-radius: 50%;
        font-size: 0.6rem;
    }

    .header-photo-overlay span {
        display: none;
    }

    .lists-section {
        padding: 8px 12px;
        overflow-y: scroll;
        -webkit-overflow-scrolling: touch;
        flex: 1;
    }

    /* Always show scrollbar on mobile */
    .lists-section::-webkit-scrollbar {
        width: 6px;
    }

    .lists-section::-webkit-scrollbar-track {
        background: rgba(255, 255, 255, 0.1);
        border-radius: 3px;
    }

    .lists-section::-webkit-scrollbar-thumb {
        background: rgba(255, 255, 255, 0.4);
        border-radius: 3px;
    }

    .lists-section h2 {
        font-size: 0.75rem;
        margin-bottom: 6px;
    }

    .list-item {
        padding: 10px 12px;
        font-size: 0.95rem;
    }

    .header-action-row {
        gap: 6px;
    }

    .header-pill {
        flex: 1;
        justify-content: center;
        padding: 10px 8px;
    }

    .add-entry-modal-row {
        flex-wrap: wrap;
        gap: 6px;
    }

    .add-entry-modal-row input[type="date"],
    .file-input-label {
        flex: 1;
        min-width: 0;
    }

    /* Stack task content vertically on mobile */
    .task-content {
        flex-wrap: wrap;
        padding: 10px 12px;
        gap: 6px;
    }

    .task-title {
        flex: 1 1 100%;
        order: 1;
    }

    /* 🔒 FIX (2026-09-28, device repro with a screenshot - "the avatar is overlaid by the entry
       title... I suspect it has to do with dates changing"): the padding-left:32px/margin-left:-32px
       "reserve space, then pull back" trick only makes sense when a .collapse-btn is actually
       sitting next to .task-title to reserve that space FOR - collapseBtn is only added to the DOM
       for Entries that have real nested sub-items (render.js), so any Entry without one had
       nothing there to compensate for, and the bare negative margin just pulled the title 32px left
       into the avatar's own space in the parent .task-header. Not date-related at all - it's
       whether the Entry has sub-items, which understandably looked coincidental. Scoped to only
       apply when a real .collapse-btn immediately precedes .task-title in the DOM. */
    .collapse-btn + .task-title {
        padding-left: 32px;
        margin-left: -32px;
    }

    .collapse-btn {
        order: 0;
        flex-shrink: 0;
        position: relative;
        z-index: 2;
    }

    /* 🔒 FIX (2026-09-28, device repro with a screenshot - "still no calendar icons showing... even
       after multiple reloads" - the empty-date calendar button, per direct request "when there is
       no date, there needs to be a button to summon the calendar picker"): .task-date.no-date used
       to be display:none on mobile - another leftover from the same pre-2026-09-27-redesign mobile
       block as the .task-actions margin-left:auto fixed earlier tonight (see that fix's own
       comment just below). No amount of per-skin icon art (also added tonight) could ever have
       shown through a flat display:none - removed. */

    /* 🔒 FIX (2026-09-28, device repro - "buttons are being jammed to the right side... when a
       date is displayed the buttons are even being pushed outside the right border"): this block's
       order/margin-left:auto on .task-date/.task-actions predates the 2026-09-27 icon-row redesign
       - back when they shared a flex container with .collapse-btn and needed reordering. They now
       live together in their own dedicated .task-icon-row (render.js) - the stale margin-left:auto
       on .task-actions had nothing to push against except .task-date's own width, shoving the
       buttons hard right and off the card entirely once a long date string made .task-date wide.
       Removed; .task-icon-row's own plain flex (style.css, no justify-content override) already
       lays date+buttons out correctly with no help needed here. */

    .task-actions button {
        padding: 6px 10px;
        font-size: 0.9rem;
    }

    .task-comments {
        padding-left: 12px !important;
    }

    .search-container {
        max-width: 100%;
    }

    .list-header h2 {
        font-size: 1.2rem;
    }

    /* Sticky header on mobile - two rows:
       Row 1: back + list name + avatar
       Row 2: search (full width) */
    .main-sticky-header {
        flex-wrap: wrap;
        gap: 8px;
        padding: 8px 12px;
        align-items: center;
    }

    .main-sticky-header .list-header {
        flex: 1 1 auto;
        min-width: 0;
        order: 1;
    }

    .main-sticky-header .user-menu {
        order: 2;
        flex-shrink: 0;
    }

    .main-sticky-header .search-container {
        order: 3;
        flex: 1 1 100%;
        min-width: 0;
        max-width: none;
    }

    .main-sticky-header .list-header h2 {
        font-size: calc(1rem * var(--title-scale, 1));
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        padding: 2px 4px;
    }

    .main-sticky-header .list-header-color {
        font-size: 21px;
    }

    .main-sticky-header .delete-btn {
        display: none;
    }

    .main-sticky-header .search-input {
        padding: 8px 12px;
        font-size: 0.85rem;
    }

    .modal-content {
        margin: 16px;
        max-width: calc(100% - 32px);
    }


    /* Login screen mobile */
    .login-container {
        margin: 16px;
        padding: 24px;
    }

    /* 🔒 (2026-09-27, per direct request - "leave enough space between them especially for phone
       screen format") - the Cancel/Confirm icon pairs sit closer together on a phone's narrower
       task-list column than they do on desktop; widen the gap here specifically rather than
       bumping the base value (which desktop doesn't need). */
    .inline-task-edit-actions {
        gap: 14px;
    }

    .inline-date-picker {
        gap: 12px;
    }
}

/* Touch-friendly improvements */
@media (hover: none) and (pointer: coarse) {
    .task-actions {
        opacity: 1;
    }

    .attachment-delete-btn {
        opacity: 0.8;
        width: 28px;
        height: 28px;
    }

    .list-item {
        padding: 12px;
    }

    .drag-handle {
        padding-right: 12px;
        font-size: 1.2rem;
    }
}

/* PWA Installation Prompt */
.install-prompt {
    position: fixed !important;
    top: 0 !important;
    left: 0 !important;
    right: 0 !important;
    background: linear-gradient(135deg, #7c3aed 0%, #a855f7 100%) !important;
    color: white !important;
    z-index: 9999 !important;
    padding: 12px 16px !important;
    box-shadow: 0 4px 12px rgba(124, 58, 237, 0.3) !important;
    width: 100% !important;
    height: auto !important;
}

.install-prompt.hidden {
    display: none;
}

.install-prompt-content {
    display: flex;
    align-items: center;
    gap: 12px;
    max-width: 100%;
}

.install-prompt-icon {
    font-size: 1.5rem;
    flex-shrink: 0;
}

.install-prompt-text {
    flex: 1;
    min-width: 0;
}

.install-prompt-title {
    font-weight: 600;
    font-size: 0.95rem;
    margin: 0;
    padding: 0;
}

.install-prompt-description {
    font-size: 0.85rem;
    opacity: 0.95;
    margin: 2px 0 0 0;
    padding: 0;
}

.install-btn {
    background: white;
    color: #7c3aed;
    border: none;
    padding: 6px 14px;
    border-radius: 4px;
    font-weight: 600;
    font-size: 0.85rem;
    cursor: pointer;
    flex-shrink: 0;
    transition: all 0.2s ease;
    text-decoration: none; /* (2026-10-01) now a link to Google Play, not a button */
    white-space: nowrap;
}

.install-btn:active {
    opacity: 0.8;
    transform: scale(0.98);
}

.dismiss-install-btn {
    background: transparent;
    border: none;
    color: white;
    font-size: 1.2rem;
    cursor: pointer;
    padding: 0 4px;
    flex-shrink: 0;
    opacity: 0.8;
    transition: opacity 0.2s ease;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.dismiss-install-btn:active {
    opacity: 0.6;
}

/* Open in App Banner (Mobile) */
.open-in-app-banner {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    background: linear-gradient(135deg, #7c3aed 0%, #ec4899 100%);
    color: white;
    padding: 12px 16px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    z-index: 999;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
    animation: slideDown 0.3s ease-out;
}

@keyframes slideDown {
    from {
        transform: translateY(-100%);
        opacity: 0;
    }
    to {
        transform: translateY(0);
        opacity: 1;
    }
}

.open-in-app-banner.hidden {
    display: none;
}

.banner-content {
    display: flex;
    align-items: center;
    gap: 12px;
    flex: 1;
}

.banner-text {
    font-size: 0.95rem;
    font-weight: 500;
}

.banner-button {
    background: white;
    color: #7c3aed;
    border: none;
    padding: 6px 14px;
    border-radius: 4px;
    font-weight: 600;
    font-size: 0.85rem;
    cursor: pointer;
    flex-shrink: 0;
    transition: all 0.2s ease;
}

.banner-button:active {
    opacity: 0.8;
    transform: scale(0.98);
}

.banner-close {
    background: transparent;
    border: none;
    color: white;
    font-size: 1.2rem;
    cursor: pointer;
    padding: 0 8px;
    margin-left: 8px;
    opacity: 0.9;
    transition: opacity 0.2s ease;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.banner-close:active {
    opacity: 0.6;
}

/* ==========================================
   Emoji Grid Picker Styles
   ========================================== */

.emoji-grid-picker {
    background: #0f1119;
    border: 1px solid #2a2e42;
    border-radius: 8px;
    padding: 12px;
    display: flex;
    flex-direction: column;
    gap: 12px;
    position: absolute;
    bottom: 100%;
    left: 0;
    z-index: 10;
    width: 100%;
    margin-bottom: 8px;
}

.emoji-section {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.emoji-section-label {
    font-size: 10px;
    font-weight: 600;
    color: #999;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.emoji-grid {
    display: grid;
    grid-template-columns: repeat(3, 42px);
    gap: 8px;
    justify-content: center;
}

.emoji-tile {
    width: 42px;
    height: 42px;
    background: transparent;
    border: 2px solid transparent;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    font-size: 21px;
    transition: all 150ms;
    padding: 0;
    font-family: inherit;
    outline: none;
}

.emoji-tile:hover {
    background: transparent;
}

.emoji-tile:active {
    transform: scale(0.95);
}

.emoji-tile.active {
    border-color: #7c3aed;
    background: transparent;
}

.emoji-section-divider {
    height: 1px;
    background: #2a2e42;
}

/* Hide List Button */
.btn-outline-danger {
    background: transparent;
    border: 2px solid #ef4444;
    color: #ef4444;
    padding: 8px 16px;
    border-radius: 6px;
    font-size: 0.875rem;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.15s;
    width: 100%;
    margin-top: 8px;
}

.btn-outline-danger:hover {
    background: #ef4444;
    color: #ffffff;
}

.btn-outline-danger:active {
    transform: scale(0.98);
}

/* Empty Lists State */
.empty-lists-state {
    padding: 48px 24px;
    text-align: center;
    color: var(--text-muted);
}

.empty-lists-icon {
    font-size: 48px;
    margin-bottom: 16px;
}

.empty-lists-state h3 {
    font-size: 1.125rem;
    margin-bottom: 8px;
    color: var(--text-color);
}

.empty-lists-state p {
    font-size: 0.875rem;
}

/* Toast Notifications */
@keyframes slideUp {
    from {
        transform: translateX(-50%) translateY(100px);
        opacity: 0;
    }
    to {
        transform: translateX(-50%) translateY(0);
        opacity: 1;
    }
}

@keyframes slideDown {
    from {
        transform: translateX(-50%) translateY(0);
        opacity: 1;
    }
    to {
        transform: translateX(-50%) translateY(100px);
        opacity: 0;
    }
}

/* Custom Confirmation Dialog */
.confirm-dialog-overlay {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.5);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 9998;
}

.confirm-dialog {
    background: #1a1f3a;
    border-radius: 16px;
    padding: 32px;
    max-width: 500px;
    width: 90%;
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
}

.confirm-dialog-title {
    font-size: 1.5rem;
    font-weight: 600;
    color: #ffffff;
    margin-bottom: 16px;
}

/* Bookshelf cover note (app.js showBookNoteDialog, 2026-09-29): the leather-bound book centred above
   the sentence, which is the heading - a notch smaller than a one-word title so it reads as a line. */
.cover-note-dialog {
    text-align: center;
}
.cover-note-book {
    display: block;
    width: 104px;
    height: 130px;
    margin: 0 auto 16px;
}
.cover-note-dialog .cover-note-book {
    width: 80px;
    height: 100px;
    margin-bottom: 12px;
}
/* The two-person conversation (2026-09-29): person A on the left, person B on the right, each with
   a speech bubble whose tail points at them. */
.cover-note-chat {
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin-bottom: 22px;
    text-align: left;
}
.cover-note-line {
    display: flex;
    align-items: flex-end;
    gap: 10px;
}
.cover-note-line-b {
    flex-direction: row-reverse;
}
.cover-note-person {
    width: 52px;
    height: 52px;
    flex-shrink: 0;
}
.cover-note-bubble {
    position: relative;
    max-width: 78%;
    padding: 10px 14px;
    border-radius: 16px;
    font-size: 1.02rem;
    line-height: 1.35;
    font-weight: 600;
}
/* (2026-09-29) Pink for the question, lavender for the answer - the answer's 💕 disappeared on pink. */
.cover-note-line-a .cover-note-bubble {
    background: #FF4081;
    color: #fff;
    border-bottom-left-radius: 4px;
}
.cover-note-line-b .cover-note-bubble {
    background: #F1E8FD;
    color: #3b2466;
    border-bottom-right-radius: 4px;
}
/* Her reply: portrait on the left, the button(s) beside it. */
.cover-note-reply {
    display: flex;
    align-items: center;
    gap: 10px;
}
.cover-note-reply .confirm-dialog-buttons {
    flex: 1;
    min-width: 0;
    margin: 0;
}
.cover-note-reply .confirm-dialog-btn {
    flex: 1;
}
/* (2026-09-29, per direct request - "needs to look like a button with a distinct border") */
.cover-note-reply .confirm-dialog-btn-confirm {
    background: #FFFFFF;
    color: #B4235A;
    border: 2.5px solid #FF4081;
    box-shadow: 0 3px 0 #B4235A;
    font-weight: 700;
    transition: transform 0.1s, box-shadow 0.1s;
}
.cover-note-reply .confirm-dialog-btn-confirm:hover {
    background: #FFF0F5;
}
.cover-note-reply .confirm-dialog-btn-confirm:active {
    transform: translateY(2px);
    box-shadow: 0 1px 0 #B4235A;
}
.cover-note-reply .confirm-dialog-btn-cancel {
    border: 2px solid #8A7FA8;
}
.cover-note-bubble::after {
    content: '';
    position: absolute;
    bottom: 0;
    width: 12px;
    height: 12px;
}
.cover-note-line-a .cover-note-bubble::after {
    left: -6px;
    background: radial-gradient(circle at 0 0, transparent 11px, #FF4081 12px);
}
.cover-note-line-b .cover-note-bubble::after {
    right: -6px;
    background: radial-gradient(circle at 100% 0, transparent 11px, #F1E8FD 12px);
}

.confirm-dialog-message {
    font-size: 1rem;
    color: #ffffff;
    margin-bottom: 32px;
    line-height: 1.5;
}

.confirm-dialog-buttons {
    display: flex;
    gap: 16px;
    justify-content: flex-end;
}

.confirm-dialog-btn {
    padding: 12px 32px;
    border-radius: 8px;
    border: none;
    font-size: 1rem;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.15s;
    flex: 1;
}

.confirm-dialog-btn-cancel {
    background: #3a3f4a;
    color: #ffffff;
}

.confirm-dialog-btn-cancel:hover {
    background: #4a4f5a;
}

.confirm-dialog-btn-danger {
    background: #ef4444;
    color: #ffffff;
}

.confirm-dialog-btn-danger:hover {
    background: #dc2626;
}

.confirm-dialog-btn:active {
    transform: scale(0.98);
}
