@font-face {
    font-family: "Manrope";
    src: local("Manrope");
}

:root {
    --surface: #fbf9f9;
    --on-surface: #1b1c1c;
    --on-surface-variant: #444748;
    --outline-variant: #c4c7c7;
    --primary: #000000;
    --on-primary: #ffffff;
}

* {
    box-sizing: border-box;
}

html,
body {
    margin: 0;
    height: 100%;
    background: var(--surface);
    color: var(--on-surface);
    font-family: "Manrope", -apple-system, BlinkMacSystemFont, sans-serif;
}

.page {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}

.header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 24px;
}

.nav {
    display: flex;
    align-items: center;
    gap: 16px;
}

.nav-link {
    font-size: 14px;
    font-weight: 500;
    letter-spacing: 0.01em;
    color: var(--on-surface);
    text-decoration: none;
    border-bottom: 1px solid transparent;
}

.nav-link:hover {
    border-bottom-color: var(--outline-variant);
}

.btn {
    font-family: inherit;
    font-size: 14px;
    font-weight: 500;
    letter-spacing: 0.01em;
    padding: 8px 16px;
    border-radius: 8px;
    cursor: pointer;
}

.btn-ghost {
    background: transparent;
    color: var(--on-surface);
    border: 1px solid var(--outline-variant);
}

.auth-placeholder {
    height: 37px;
}

.auth-signed-in {
    display: flex;
    align-items: center;
    gap: 12px;
}

.auth-name {
    font-size: 14px;
    font-weight: 500;
    color: var(--on-surface-variant);
}

.btn-primary {
    background: var(--primary);
    color: var(--on-primary);
    border: 1px solid var(--primary);
}

.page-loading {
    flex: 1;
}

.zero-state {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 40px;
    padding: 0 24px;
}

.zero-state-title {
    font-size: 32px;
    font-weight: 600;
    line-height: 1.2;
    letter-spacing: -0.01em;
    margin: 0;
    text-align: center;
}

.zero-state-form {
    display: flex;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
    justify-content: center;
}

.input {
    font-family: inherit;
    font-size: 16px;
    line-height: 1.6;
    color: var(--on-surface);
    background: transparent;
    border: none;
    border-bottom: 1px solid var(--outline-variant);
    padding: 8px 4px;
    min-width: 280px;
}

.input:focus {
    outline: none;
    border-bottom-color: var(--on-surface-variant);
}

.input::placeholder {
    color: var(--on-surface-variant);
    opacity: 0.6;
}

.input:disabled,
.btn:disabled {
    opacity: 0.5;
    cursor: default;
}

.feed-busy {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 14px;
    font-weight: 500;
    letter-spacing: 0.01em;
    color: var(--on-surface-variant);
}

.feed-busy-spinner {
    width: 14px;
    height: 14px;
    border: 2px solid var(--outline-variant);
    border-top-color: var(--on-surface-variant);
    border-radius: 9999px;
    animation: spin 0.9s linear infinite;
}

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

.feed-error {
    font-size: 14px;
    color: var(--error, #ba1a1a);
    margin: 0;
}

/* Feed page — two-pane dashboard (design 1c desktop / 2a phone). */
.podcast {
    width: 100%;
    max-width: 940px;
    margin: 8px auto 40px;
    background: var(--surface-container-lowest, #ffffff);
    border-radius: 8px;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.06);
    overflow: hidden;
    display: flex;
    align-items: stretch;
}

/* Left panel: sticky podcast identity + progress. */
.podcast-panel {
    width: 260px;
    flex: none;
    background: var(--surface-container-low, #f5f3f3);
    border-right: 1px solid var(--surface-container-highest, #e3e2e2);
    padding: 28px 24px;
    display: flex;
    flex-direction: column;
    gap: 20px;
}

.podcast-identity {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.podcast-cover {
    width: 100%;
    aspect-ratio: 1 / 1;
    border-radius: 12px;
    background: var(--surface-container-high, #e9e8e7);
    display: flex;
    align-items: center;
    justify-content: center;
}

.podcast-cover-label {
    font-size: 12px;
    font-weight: 500;
    color: var(--on-surface-variant);
    opacity: 0.7;
}

.podcast-cover-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: inherit;
    display: block;
}

.podcast-title {
    font-size: 20px;
    font-weight: 600;
    line-height: 1.3;
    letter-spacing: -0.01em;
    margin: 0 0 6px;
}

.podcast-publisher {
    font-size: 13px;
    color: var(--on-surface-variant);
    margin: 0 0 2px;
}

.podcast-url {
    font-size: 12px;
    color: var(--outline, #747878);
    margin: 0;
    overflow-wrap: anywhere;
}

.delete-cast-link {
    font-family: inherit;
    font-size: 12px;
    color: var(--outline, #747878);
    background: none;
    border: none;
    padding: 0;
    margin-top: 10px;
    cursor: pointer;
    text-align: left;
    text-decoration: underline;
    text-underline-offset: 2px;
}

.delete-cast-link:hover {
    color: var(--error, #ba1a1a);
}

.delete-cast-confirm {
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px solid var(--surface-container-highest, #e3e2e2);
}

.delete-cast-confirm-text {
    font-size: 12px;
    color: var(--on-surface-variant);
    margin: 0 0 8px;
}

.delete-cast-confirm-actions {
    display: flex;
    gap: 8px;
}

.btn-danger {
    background: var(--error, #ba1a1a);
    color: #fff;
    border: 1px solid var(--error, #ba1a1a);
}

.podcast-divider {
    height: 1px;
    background: var(--surface-container-highest, #e3e2e2);
}

.podcast-progress {
    display: flex;
    align-items: center;
    gap: 16px;
}

.progress-ring {
    position: relative;
    width: 72px;
    height: 72px;
    flex: none;
}

.progress-ring-track {
    width: 72px;
    height: 72px;
    border-radius: 9999px;
}

.progress-ring-inner {
    position: absolute;
    inset: 8px;
    border-radius: 9999px;
    background: var(--surface-container-low, #f5f3f3);
    display: flex;
    align-items: center;
    justify-content: center;
}

.progress-ring-pct {
    font-size: 15px;
    font-weight: 700;
    color: var(--on-surface);
}

.podcast-progress-primary {
    font-size: 13px;
    font-weight: 600;
    margin: 0 0 2px;
}

.podcast-progress-meta {
    font-size: 12px;
    font-weight: 500;
    color: var(--outline, #747878);
    margin: 0;
}

/* Drip cadence summary + inline editor (feature 018), under the progress
   ring. Free accounts (and the delete-cast link's sibling area generally)
   get the plain .cadence-summary paragraph; paid accounts get the
   button variant, which is the click target that reveals the editor. */
.cadence-summary {
    font-size: 12px;
    font-weight: 500;
    color: var(--on-surface-variant);
    margin: 0;
    text-align: left;
}

.cadence-summary-editable {
    font-family: inherit;
    background: none;
    border: none;
    padding: 0;
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 2px;
    text-decoration-color: var(--outline-variant);
}

.cadence-summary-editable:hover {
    color: var(--on-surface);
    text-decoration-color: var(--on-surface);
}

.cadence-editor {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.cadence-mode-toggle {
    display: flex;
    gap: 6px;
}

.cadence-mode-btn {
    font-family: inherit;
    font-size: 12px;
    font-weight: 500;
    color: var(--on-surface-variant);
    background: var(--surface-container-lowest, #ffffff);
    border: 1px solid var(--outline-variant);
    border-radius: 9999px;
    padding: 4px 12px;
    cursor: pointer;
}

.cadence-mode-btn-active {
    color: var(--on-primary);
    background: var(--primary);
    border-color: var(--primary);
}

.cadence-days-picker {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 13px;
    color: var(--on-surface-variant);
}

.cadence-days-picker .select {
    padding: 4px 8px;
}

.cadence-weekdays {
    display: flex;
    gap: 4px;
    flex-wrap: wrap;
}

.cadence-weekday {
    font-family: inherit;
    font-size: 12px;
    font-weight: 500;
    color: var(--on-surface-variant);
    background: var(--surface-container-lowest, #ffffff);
    border: 1px solid var(--outline-variant);
    border-radius: 8px;
    width: 34px;
    padding: 4px 0;
    cursor: pointer;
    text-align: center;
}

.cadence-weekday-checked {
    color: var(--on-primary);
    background: var(--primary);
    border-color: var(--primary);
}

.cadence-error {
    font-size: 12px;
    color: var(--error, #ba1a1a);
    margin: 0;
}

.cadence-editor-actions {
    display: flex;
    gap: 8px;
}

.podcast-feed-link {
    display: flex;
    align-items: center;
    gap: 8px;
    font-family: inherit;
    font-size: 13px;
    font-weight: 500;
    color: var(--secondary, #0060ac);
    background: none;
    border: none;
    padding: 0;
    cursor: pointer;
    text-align: left;
}

.rss-icon {
    width: 14px;
    height: 14px;
    flex: none;
    background: no-repeat center/contain url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230060ac' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 11a9 9 0 0 1 9 9'/%3E%3Cpath d='M4 4a16 16 0 0 1 16 16'/%3E%3Ccircle cx='5' cy='19' r='1'/%3E%3C/svg%3E");
}

/* Feature 014: copy action + one-tap player links. */
.subscribe-block {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.player-links {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.player-link {
    font-size: 12px;
    font-weight: 500;
    color: var(--outline, #747878);
    text-decoration: underline;
    text-underline-offset: 2px;
}

.player-link:hover {
    color: var(--secondary, #0060ac);
}

/* Right pane: toolbar + episode rows. */
.podcast-episodes-pane {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.episodes-toolbar {
    display: flex;
    justify-content: flex-end;
    padding: 10px 24px 0;
}

.hide-all-link {
    font-family: inherit;
    font-size: 12px;
    font-weight: 500;
    color: var(--outline, #747878);
    background: none;
    border: none;
    padding: 0;
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 2px;
}

.hide-all-link:hover {
    color: var(--secondary, #0060ac);
}

.podcast-episodes {
    flex: 1;
    min-width: 0;
    padding: 8px 0;
    max-height: 560px;
    overflow: auto;
}

.episode {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 12px 24px;
    border-bottom: 1px solid var(--surface-container, #efeded);
}

.episode-number {
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.04em;
    color: var(--outline, #747878);
    flex: none;
    width: 26px;
}

.episode-main {
    flex: 1;
    min-width: 0;
}

.episode-title {
    font-size: 15px;
    font-weight: 600;
    line-height: 1.3;
    margin: 0 0 2px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.episode-aired {
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.02em;
    color: var(--outline, #747878);
    margin: 0;
}

.episode-status {
    flex: none;
    text-align: right;
}

.episode-status-replayed {
    font-size: 12px;
    font-weight: 600;
    color: var(--on-surface-variant);
    width: 88px;
}

.episode-status-upcoming {
    font-size: 12px;
    font-weight: 600;
    color: var(--outline-variant, #c4c7c7);
    width: 88px;
}

.episode-next {
    flex: none;
    display: flex;
    align-items: center;
    gap: 10px;
}

.episode-status-next {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.04em;
    color: var(--secondary, #0060ac);
    background: var(--secondary-fixed, #d4e3ff);
    padding: 3px 7px;
    border-radius: 4px;
    white-space: nowrap;
}

.btn-replay {
    font-family: inherit;
    font-size: 12px;
    font-weight: 500;
    color: var(--secondary, #0060ac);
    background: transparent;
    border: 1px solid var(--secondary, #0060ac);
    border-radius: 6px;
    padding: 6px 12px;
    cursor: pointer;
    white-space: nowrap;
}

.btn-replay:hover {
    background: var(--secondary-fixed, #d4e3ff);
}

/* Visibility toggle (feature 015): a two-state icon button, not a
switch. The previous switch filled dark for "on" = hidden, putting the
most visual weight on exactly the episodes being suppressed. Both states
here use the same neutral stroke color and weight; only the icon shape
(open eye / crossed-out eye) changes. */
.visibility-toggle {
    flex: none;
    width: 28px;
    height: 28px;
    padding: 0;
    border: none;
    border-radius: 6px;
    background: transparent;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}

.visibility-toggle:hover {
    background: var(--surface-container, #efeded);
}

.visibility-icon {
    width: 18px;
    height: 18px;
    background: no-repeat center/contain url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23747878' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 12s4-7 11-7 11 7 11 7-4 7-11 7-11-7-11-7z'/%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3C/svg%3E");
}

.visibility-toggle-hidden .visibility-icon {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23747878' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M17.94 17.94A10.94 10.94 0 0 1 12 19c-7 0-11-7-11-7a21.6 21.6 0 0 1 5.06-6.06'/%3E%3Cpath d='M9.9 4.24A10.94 10.94 0 0 1 12 5c7 0 11 7 11 7a21.6 21.6 0 0 1-2.16 3.19'/%3E%3Cpath d='M14.12 14.12a3 3 0 1 1-4.24-4.24'/%3E%3Cline x1='1' y1='1' x2='23' y2='23'/%3E%3C/svg%3E");
}

/* Hidden episodes read as de-emphasized. */
.episode-hidden .episode-title,
.episode-hidden .episode-aired {
    opacity: 0.45;
}

/* Phone width (design 2a): stack the panel above the episode list. */
/* Admin dashboard (feature 010). */
.admin {
    width: 100%;
    max-width: 640px;
    margin: 8px auto 40px;
    display: flex;
    flex-direction: column;
    gap: 16px;
    padding: 0 24px;
}

.admin-panel {
    background: var(--surface-container-lowest, #ffffff);
    border-radius: 8px;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.06);
    padding: 20px 24px;
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.admin-stats {
    display: flex;
    gap: 40px;
}

.admin-plans {
    font-size: 13px;
    color: var(--on-surface-variant);
    margin: 0;
}

.admin-stat {
    display: flex;
    flex-direction: column;
}

.admin-stat-value {
    font-size: 32px;
    font-weight: 700;
    letter-spacing: -0.01em;
}

.admin-stat-label {
    font-size: 13px;
    color: var(--on-surface-variant);
}

.admin-health {
    display: flex;
    align-items: center;
    gap: 10px;
}

.health-dot {
    width: 10px;
    height: 10px;
    border-radius: 9999px;
    background: var(--outline-variant);
}

.health-ok {
    background: #2e7d32;
}

.health-bad {
    background: var(--error, #ba1a1a);
}

.health-unknown {
    background: var(--outline, #747878);
}

.admin-health-label {
    font-size: 15px;
    font-weight: 600;
}

.admin-run {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.admin-run-row {
    font-size: 13px;
    color: var(--on-surface-variant);
    margin: 0;
}

.admin-run-error {
    font-size: 13px;
    color: var(--error, #ba1a1a);
    margin: 4px 0 0;
}

.admin-empty {
    font-size: 13px;
    color: var(--on-surface-variant);
    margin: 0;
}

/* Plan management page (feature 017). */
.admin-accounts-title {
    font-size: 18px;
    font-weight: 600;
    margin: 0;
}

.admin-accounts-search {
    display: flex;
    align-items: center;
    gap: 16px;
}

.admin-accounts-search .input {
    flex: 1;
    min-width: 0;
}

.admin-accounts-table {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.admin-account-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 12px;
    padding: 12px 0;
    border-top: 1px solid var(--outline-variant);
}

.admin-account-row:first-child {
    border-top: none;
}

.admin-account-identity {
    display: flex;
    flex-direction: column;
    flex: 1 1 220px;
    min-width: 0;
}

.admin-account-name {
    font-size: 14px;
    font-weight: 500;
}

.admin-account-email {
    font-size: 13px;
    color: var(--on-surface-variant);
}

.admin-account-feeds {
    font-size: 13px;
    color: var(--on-surface-variant);
    white-space: nowrap;
}

.admin-plan-control {
    display: flex;
    align-items: center;
    gap: 8px;
}

.select {
    font-family: inherit;
    font-size: 14px;
    color: var(--on-surface);
    background: var(--surface-container-lowest, #ffffff);
    border: 1px solid var(--outline-variant);
    border-radius: 8px;
    padding: 6px 10px;
}

.admin-plan-confirm {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 12px;
    flex: 1 1 auto;
    justify-content: flex-end;
}

.admin-plan-confirm-text {
    font-size: 13px;
    margin: 0;
}

.admin-plan-confirm-actions {
    display: flex;
    gap: 8px;
    flex-shrink: 0;
}

.admin-actions-list {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.admin-action-row {
    display: flex;
    justify-content: space-between;
    gap: 16px;
    font-size: 13px;
    padding: 8px 0;
    border-top: 1px solid var(--outline-variant);
    margin: 0;
}

.admin-action-row:first-child {
    border-top: none;
}

.admin-action-time {
    color: var(--on-surface-variant);
    white-space: nowrap;
}

@media (max-width: 720px) {
    .podcast {
        flex-direction: column;
        max-width: 480px;
        margin: 8px auto 24px;
    }

    .podcast-panel {
        width: auto;
        border-right: none;
        border-bottom: 1px solid var(--surface-container-highest, #e3e2e2);
        padding: 20px;
    }

    .podcast-identity {
        flex-direction: row;
        align-items: center;
    }

    .podcast-cover {
        width: 64px;
        height: 64px;
        aspect-ratio: auto;
        border-radius: 10px;
    }

    .podcast-episodes {
        max-height: none;
    }

    /* The eta pill + Replay now button, side by side, squeezed
    .episode-main down to almost nothing at phone width - truncating the
    title to a couple characters and wrapping "Aired ..." across lines,
    which inflated the row's height. Stacking them (button on top, eta
    label underneath - order flipped from the DOM's badge-then-button so
    the label reads as sitting under the button) frees the width back up
    for the title without touching the desktop layout. */
    .episode-next {
        flex-direction: column;
        align-items: flex-end;
        gap: 4px;
    }

    .btn-replay {
        order: 1;
    }

    .episode-status-next {
        order: 2;
    }

    .episode-aired {
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
}

/* ==========================================================================
   Multi-feed rail + master/detail (feature 019). Paid accounts only —
   free accounts never build FeedMulti (see feedStateFromList in Main.elm),
   so none of this ever renders for them. One DOM tree serves both
   presentations: desktop always shows rail + detail side by side; the
   phone breakpoint below picks one or the other via feed-multi-list /
   feed-multi-detail.
   ========================================================================== */
.feed-multi {
    width: 100%;
    max-width: 1200px;
    margin: 8px auto 40px;
    display: flex;
    align-items: flex-start;
    gap: 16px;
    padding: 0 24px;
}

.feed-rail {
    width: 280px;
    flex: none;
    background: var(--surface-container-lowest, #ffffff);
    border-radius: 8px;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.06);
    padding: 16px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.feed-pace {
    font-size: 12px;
    font-weight: 500;
    color: var(--on-surface-variant);
    margin: 0;
    padding: 0 4px 8px;
}

.feed-rail-groups {
    display: flex;
    flex-direction: column;
    max-height: 640px;
    overflow-y: auto;
}

.feed-group-header {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--outline, #747878);
    padding: 12px 4px 4px;
}

.feed-row {
    display: flex;
    align-items: center;
    gap: 4px;
    border-radius: 8px;
}

.feed-row-selected {
    background: var(--surface-container, #efeded);
}

/* The dragged row's own place in the live-reordered list — dimmed so the
   "ghost" reads as picked-up rather than as a normal row that happens to
   be moving around. */
.feed-row-dragging {
    opacity: 0.4;
}

.feed-row-grip {
    flex: none;
    width: 24px;
    height: 40px;
    padding: 0;
    border: none;
    background: transparent;
    cursor: grab;
    display: flex;
    align-items: center;
    justify-content: center;
    /* Both matter for the touch case (feature 019): touch-action stops the
       browser starting its own scroll/zoom gesture from this pointerdown;
       user-select stops a long-press from selecting the row's text — both
       are exactly the "competes with scrolling and text selection" the
       grip handle exists to avoid. */
    touch-action: none;
    -webkit-user-select: none;
    user-select: none;
}

.feed-row-grip-icon {
    width: 12px;
    height: 16px;
    background: no-repeat center/contain url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 16' fill='%23c4c7c7'%3E%3Ccircle cx='3' cy='2' r='1.4'/%3E%3Ccircle cx='9' cy='2' r='1.4'/%3E%3Ccircle cx='3' cy='8' r='1.4'/%3E%3Ccircle cx='9' cy='8' r='1.4'/%3E%3Ccircle cx='3' cy='14' r='1.4'/%3E%3Ccircle cx='9' cy='14' r='1.4'/%3E%3C/svg%3E");
}

.feed-row-link {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 8px 6px 2px;
    text-decoration: none;
    color: inherit;
    border-radius: 8px;
}

.feed-row-cover {
    width: 36px;
    height: 36px;
    flex: none;
    border-radius: 6px;
    background: var(--surface-container-high, #e9e8e7);
    overflow: hidden;
}

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

.feed-row-text {
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.feed-row-title {
    font-size: 13px;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.feed-row-status {
    font-size: 11px;
    color: var(--on-surface-variant);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.feed-add-link {
    font-family: inherit;
    font-size: 13px;
    font-weight: 500;
    color: var(--secondary, #0060ac);
    background: none;
    border: none;
    padding: 8px 4px 0;
    cursor: pointer;
    text-align: left;
}

/* Reads as selected the same way a feed row does, since opening the form
   now swaps the detail pane exactly as picking a feed does. */
.feed-add-link-selected {
    font-weight: 700;
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* The add form renders in the detail pane (.zero-state), not the ~120px
   rail, so it needs no width gymnastics of its own - it inherits the
   classic zero state's layout. Only the pane's own vertical centring is
   relaxed, so the form sits near the top next to the feed list rather
   than floating in the middle of a tall column. */
.feed-detail .zero-state {
    justify-content: flex-start;
    padding-top: 32px;
    gap: 24px;
}

.feed-detail {
    flex: 1;
    min-width: 0;
}

.feed-detail .podcast {
    margin: 0;
}

/* Only meaningful on phone — the rail is always visible on desktop, so a
   "back to the list" control there would be redundant. See the 720px
   block below. */
.feed-back {
    display: none;
    font-size: 13px;
    font-weight: 500;
    color: var(--on-surface-variant);
    text-decoration: none;
    padding: 4px 4px 12px;
}

/* Drag reorder's full-viewport pointer catcher (feature 019) — see
   DragState in Main.elm for why this stands in for setPointerCapture. */
.drag-overlay {
    position: fixed;
    inset: 0;
    z-index: 1000;
    cursor: grabbing;
    touch-action: none;
}

@media (max-width: 720px) {
    .feed-multi {
        flex-direction: column;
        padding: 0 16px;
        max-width: 480px;
    }

    .feed-rail {
        width: 100%;
    }

    .feed-back {
        display: block;
    }

    /* Master/detail (feature 019): the rail is the landing screen at
       /my-feed, the detail is a screen of its own at /my-feed/{id} — only
       one is ever visible at a time on phone. Desktop shows both always,
       so this pair of rules is scoped to the phone breakpoint only. */
    .feed-multi-list .feed-detail {
        display: none;
    }

    .feed-multi-detail .feed-rail {
        display: none;
    }
}

/* ==========================================================================
   Landing page (feature 016). Served as static HTML at / — no Elm — so
   these classes are namespaced .landing-* and never collide with the app
   views above. Same Editorial Clarity tokens as everything else; the
   comps live in design/landing/.
   ========================================================================== */

.landing {
    background: var(--surface);
    color: var(--on-surface);
}

.landing-wrap {
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 24px;
}

.landing-nav {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 24px 0;
}

.landing-brand {
    font-size: 20px;
    font-weight: 700;
    letter-spacing: -0.01em;
    white-space: nowrap;
}

.landing-nav-links {
    display: flex;
    align-items: center;
    gap: 24px;
    font-size: 14px;
    font-weight: 500;
}

.landing-nav-links a:not(.btn) {
    color: var(--on-surface-variant);
    text-decoration: none;
}

.landing-nav-links a:not(.btn):hover {
    color: var(--on-surface);
}

/* The app's .btn is a <button>; as an <a> it needs the text treatment back. */
.landing a.btn {
    display: inline-block;
    text-decoration: none;
    text-align: center;
}

.landing-btn-disabled {
    opacity: 0.5;
    cursor: default;
}

/* --- hero: copy left, photo right (comp D) --- */
.landing-hero {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 56px;
    align-items: center;
    padding: 48px 0 40px;
}

.landing-display {
    font-size: 48px;
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: -0.02em;
    margin: 0 0 16px;
}

.landing-accent { color: var(--secondary, #0060ac); }

.landing-body-lg {
    font-size: 18px;
    line-height: 1.6;
    color: var(--on-surface-variant);
    max-width: 44ch;
    margin: 0 0 24px;
}

.landing-cta-row {
    display: flex;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
}

.landing-cta-note {
    font-size: 13px;
    color: var(--outline, #747878);
}

/* Square slot, portrait source: object-fit crops it, and object-position
   frames on the phone rather than the centre. Tunable here without
   touching the asset. */
.landing-hero-img {
    aspect-ratio: 1 / 1;
    border-radius: 8px;
    overflow: hidden;
    background: var(--surface-container-high, #e9e8e7);
}

.landing-hero-img img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center 62%;
    display: block;
}

/* --- sections --- */
.landing-section { padding: 72px 0; }

.landing-eyebrow {
    font-size: 12px;
    font-weight: 600;
    line-height: 1.2;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--outline, #747878);
    margin: 0 0 16px;
}

.landing-headline {
    font-size: 32px;
    font-weight: 600;
    line-height: 1.2;
    letter-spacing: -0.01em;
    margin: 0 0 16px;
}

.landing-title {
    font-size: 20px;
    font-weight: 600;
    line-height: 1.4;
    margin: 0 0 4px;
}

.landing-body {
    font-size: 16px;
    line-height: 1.6;
    color: var(--on-surface-variant);
    margin: 0;
}

.landing-grid-3 {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 16px;
}

.landing-step-num {
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.04em;
    color: var(--secondary, #0060ac);
    margin-bottom: 8px;
}

.landing-cases {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 16px;
}

.landing-case-title {
    font-size: 17px;
    font-weight: 600;
    line-height: 1.4;
    margin: 0 0 2px;
}

/* Takes content out of the page visually while leaving it in the
   accessibility tree. Not display:none or visibility:hidden - both remove
   it from the tree too, which would defeat the point. */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* Example shows link out to the publisher's own page, in a new tab. The
   trailing arrow is the sighted reader's only signal that a click leaves
   SlowPlay, so it stays even though 18 of them appear on the page - kept
   small and dim so the list still reads as prose rather than as a wall of
   links. Screen reader users get the same warning from the
   .visually-hidden "(opens in new tab)" in each link, since target="_blank"
   is not itself announced. */
.landing-show {
    color: inherit;
    text-decoration: none;
    border-bottom: 1px solid var(--outline-variant);
}

.landing-show:hover {
    color: var(--on-surface);
    border-bottom-color: var(--on-surface);
}

/* The "" after the slash is CSS alt text: it marks the arrow decorative so
   it isn't read out as "north east arrow" on top of the hidden text that
   already says the same thing. Browsers without alt-text support just read
   the glyph - noisy, not broken. */
.landing-show::after {
    content: "↗" / "";
    font-size: 0.75em;
    margin-left: 2px;
    opacity: 0.55;
}

/* --- plans --- */
.landing-tiers {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 16px;
    align-items: start;
}

.landing-tier {
    background: var(--surface-container-lowest, #ffffff);
    border-radius: 8px;
    padding: 24px;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.04);
}

.landing-tier-current {
    outline: 1px solid var(--outline-variant);
}

.landing-price {
    font-size: 32px;
    font-weight: 700;
    letter-spacing: -0.01em;
    margin: 8px 0 16px;
}

/* "Coming soon" is a status, not a number — it shouldn't shout like one. */
.landing-price-soon {
    font-size: 15px;
    font-weight: 600;
    color: var(--outline, #747878);
    margin: 14px 0 22px;
}

.landing-tier ul {
    list-style: none;
    padding: 0;
    margin: 0 0 24px;
}

.landing-tier li {
    font-size: 14px;
    color: var(--on-surface-variant);
    padding: 6px 0;
}

.landing-tier .btn {
    width: 100%;
}

/* --- closer --- */
.landing-closer {
    background: var(--surface-container-lowest, #ffffff);
    border-radius: 8px;
    padding: 56px 40px;
    text-align: center;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.04);
}

.landing-closer .landing-body-lg {
    max-width: 48ch;
    margin: 0 auto 24px;
}

.landing-footer {
    padding: 40px 0;
    color: var(--outline, #747878);
    font-size: 13px;
}

@media (max-width: 860px) {
    .landing-hero {
        grid-template-columns: 1fr;
        gap: 40px;
        padding: 24px 0 40px;
    }

    .landing-display { font-size: 36px; }

    .landing-section { padding: 48px 0; }

    .landing-grid-3,
    .landing-cases,
    .landing-tiers {
        grid-template-columns: 1fr;
        gap: 24px;
    }

    .landing-closer { padding: 40px 24px; }
}

/* Same call as the comps: below 720px the section anchors don't fit
   beside the brand and the nav wraps into ragged stacks. Keep identity
   and the way in. */
@media (max-width: 720px) {
    .landing-nav-links a:not(.btn) { display: none; }
}
