
:root {
    --ink: #2b1d14;
    --ink-soft: #5a4a3e;
    --paper: #f5ede0;
    --paper-warm: #ede0cc;
    --rose: #c8546b;
    --rose-soft: #e8a4af;
    --olive: #7a8450;
    --gold: #d4a248;
    --shadow: rgba(43, 29, 20, 0.12);
    --line: rgba(43, 29, 20, 0.18);
}

* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

html, body {
    background: var(--paper);
    color: var(--ink);
    font-family: 'Fraunces', Georgia, serif;
    font-weight: 400;
    min-height: 100vh;
    overflow-x: hidden;
}

body {
    background-image: radial-gradient(circle at 20% 10%, rgba(212, 162, 72, 0.08), transparent 40%),
    radial-gradient(circle at 80% 80%, rgba(200, 84, 107, 0.06), transparent 50%);
    background-attachment: fixed;
}

body::before {
    content: '';
    position: fixed;
    inset: 0;
    pointer-events: none;
    opacity: 0.4;
    z-index: 1;
    background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' /%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.18'/%3E%3C/svg%3E");
}

.container {
    max-width: 720px;
    margin: 0 auto;
    padding: 40px 24px 80px;
    position: relative;
    z-index: 2;
}

/* ============ COMMON ============ */
.card {
    background: var(--paper-warm);
    border: 1px solid var(--line);
    border-radius: 4px;
    padding: 36px 32px;
    box-shadow: 0 30px 60px -30px var(--shadow);
}

h1.display {
    font-size: clamp(2.2rem, 5vw, 3rem);
    font-weight: 300;
    font-style: italic;
    letter-spacing: -0.02em;
    line-height: 1.05;
    margin-bottom: 14px;
}

h1.display .accent {
    color: var(--rose);
}

p.lede {
    font-size: 1.05rem;
    color: var(--ink-soft);
    line-height: 1.6;
    margin-bottom: 24px;
    font-style: italic;
}

label {
    display: block;
    font-family: 'DM Mono', monospace;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.16em;
    color: var(--ink-soft);
    margin: 18px 0 8px;
}

input[type="text"], input[type="email"], select, textarea {
    width: 100%;
    padding: 13px 16px;
    border: 1px solid var(--line);
    background: var(--paper);
    font-family: 'Fraunces', serif;
    font-size: 1rem;
    border-radius: 3px;
    color: var(--ink);
}

input[type="email"] {
    font-family: 'DM Mono', monospace;
    font-size: 0.95rem;
}

input:focus, select:focus, textarea:focus {
    outline: none;
    border-color: var(--rose);
}

.btn {
    padding: 13px 26px;
    background: var(--ink);
    color: var(--paper);
    border: none;
    font-family: 'DM Mono', monospace;
    font-size: 0.74rem;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    cursor: pointer;
    border-radius: 3px;
    transition: all 0.2s;
}

.btn:hover {
    background: var(--rose);
    transform: translateY(-1px);
}

.btn:disabled {
    opacity: 0.4;
    cursor: wait;
}

.btn.full {
    width: 100%;
}

.btn.ghost {
    background: transparent;
    color: var(--ink);
    border: 1px solid var(--line);
}

.btn.ghost:hover {
    background: var(--ink);
    color: var(--paper);
    transform: none;
}

.btn.rose {
    background: var(--rose);
}

.btn.rose:hover {
    background: var(--ink);
}

.err {
    color: var(--rose);
    font-size: 0.9rem;
    margin-top: 12px;
    font-style: italic;
    display: none;
}

.err.show {
    display: block;
}

.ok {
    color: var(--olive);
    font-size: 0.9rem;
    margin-top: 12px;
    font-style: italic;
    display: none;
}

.ok.show {
    display: block;
}

.muted-link {
    color: var(--ink-soft);
    text-decoration: underline;
    text-decoration-style: dotted;
    text-underline-offset: 3px;
    cursor: pointer;
    background: none;
    border: none;
    font-family: inherit;
    font-size: inherit;
    padding: 0;
}

.muted-link:hover {
    color: var(--rose);
}

/* ============ LANDING ============ */
.hero {
    text-align: center;
    margin-top: 30px;
    margin-bottom: 40px;
}

.hero .wordmark {
    font-family: 'DM Mono', monospace;
    font-size: 0.7rem;
    letter-spacing: 0.32em;
    text-transform: uppercase;
    color: var(--ink-soft);
    margin-bottom: 18px;
}

.hero h1 {
    font-size: clamp(3rem, 8vw, 5rem);
    font-weight: 300;
    font-style: italic;
    letter-spacing: -0.03em;
    line-height: 0.95;
    margin-bottom: 18px;
}

.hero p {
    font-size: 1.15rem;
    color: var(--ink-soft);
    line-height: 1.55;
    max-width: 480px;
    margin: 0 auto 32px;
}

.hero-actions {
    display: flex;
    gap: 12px;
    justify-content: center;
    flex-wrap: wrap;
}

/* ============ ROLE PICKER ============ */
.role-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
    margin-top: 8px;
}

.role-card {
    padding: 22px 18px;
    border: 1px solid var(--line);
    background: var(--paper);
    border-radius: 4px;
    cursor: pointer;
    text-align: left;
    transition: all 0.2s;
    font-family: 'Fraunces', serif;
}

.role-card:hover {
    border-color: var(--rose);
}

.role-card.active {
    border-color: var(--rose);
    background: rgba(200, 84, 107, 0.08);
}

.role-card .emoji {
    font-size: 1.6rem;
}

.role-card .label {
    display: block;
    margin-top: 8px;
    font-style: italic;
    font-size: 1.1rem;
    font-weight: 500;
}

.role-card .desc {
    display: block;
    margin-top: 4px;
    font-size: 0.85rem;
    color: var(--ink-soft);
    line-height: 1.4;
}

/* ============ DASHBOARD HEADER ============ */
.top-bar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 24px;
    font-family: 'DM Mono', monospace;
    font-size: 0.68rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--ink-soft);
}

.top-bar .greet {
    font-style: normal;
}

.top-bar .menu-btn {
    background: none;
    border: none;
    color: var(--ink-soft);
    cursor: pointer;
    font-family: inherit;
    font-size: inherit;
    letter-spacing: inherit;
    text-transform: inherit;
    padding: 4px 8px;
    border-radius: 3px;
}

.top-bar .menu-btn:hover {
    color: var(--rose);
}

/* Top-bar action buttons live in a flex row so the switcher icon and
   the menu link sit next to each other. */
.top-bar-actions {
    display: flex;
    align-items: center;
    gap: 4px;
}

/* The space-switcher button. Only renders when the user is in 2+ spaces.
   The 4-square SVG inherits currentColor from the button text colour, so
   it picks up ink-soft → rose on hover with no extra fill rules. */
.space-switcher-btn {
    background: none;
    border: none;
    color: var(--ink-soft);
    cursor: pointer;
    padding: 6px 8px;
    border-radius: 3px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: color 0.15s;
}

.space-switcher-btn:hover {
    color: var(--rose);
}

.space-switcher-btn svg {
    display: block;
}

/* Space-switcher panel — opens as a modal listing the user's spaces. */
.space-switch-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.space-switch-item {
    background: var(--paper-warm);
    border: 1px solid var(--line);
    border-radius: 4px;
    padding: 12px 14px;
    text-align: left;
    cursor: pointer;
    font-family: inherit;
    color: var(--ink);
    transition: border-color 0.15s, background 0.15s;
}

.space-switch-item:hover {
    border-color: var(--rose);
}

.space-switch-item.active {
    border-color: var(--rose);
    background: rgba(200, 84, 107, 0.06);
}

.space-switch-label {
    font-size: 1rem;
    font-style: italic;
}

.space-switch-meta {
    font-family: 'DM Mono', monospace;
    font-size: 0.62rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--ink-soft);
    margin-top: 4px;
}

.space-switch-cap {
    font-size: 0.85rem;
    font-style: italic;
    color: var(--ink-soft);
    line-height: 1.55;
    background: rgba(212, 162, 72, 0.1);
    border: 1px dashed var(--gold);
    border-radius: 4px;
    padding: 12px 14px;
    margin: 6px 0 0;
}

/* A small "beta" pill in the dashboard top-bar. Sets expectations for
   early users (it's evolving, things may shift) without the marketing-y
   feel of a banner. Hidden on the landing page so the hero stays clean. */
.beta-pill {
    display: inline-block;
    margin-left: 8px;
    padding: 2px 8px;
    background: var(--rose);
    color: var(--paper);
    border-radius: 999px;
    font-family: 'DM Mono', monospace;
    font-size: 0.58rem;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    vertical-align: 1px;
    font-weight: 500;
}

/* Colophon line at the very bottom of the landing page. Beta marker +
   copyright. Mono caps so it reads as system metadata, not marketing. */
.colophon {
    text-align: center;
    margin: 28px auto 0;
    padding-top: 20px;
    border-top: 1px dashed var(--line);
    max-width: 360px;
    font-family: 'DM Mono', monospace;
    font-size: 0.62rem;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--ink-soft);
    opacity: 0.7;
}

.colophon .sep {
    margin: 0 8px;
    opacity: 0.5;
}

.colophon .beta-mark {
    color: var(--rose);
    opacity: 0.95;
}

header.dash {
    text-align: center;
    margin-bottom: 32px;
}

.date-stamp {
    font-family: 'DM Mono', monospace;
    font-size: 0.7rem;
    letter-spacing: 0.24em;
    text-transform: uppercase;
    color: var(--ink-soft);
    margin-bottom: 12px;
}

.space-name {
    font-family: 'Fraunces', serif;
    font-style: italic;
    font-size: 1rem;
    color: var(--rose);
    margin-bottom: 6px;
    letter-spacing: 0.01em;
}

.space-name::before {
    content: '— ';
    color: var(--ink-soft);
    opacity: 0.6;
}

.space-name::after {
    content: ' —';
    color: var(--ink-soft);
    opacity: 0.6;
}

.pause-banner {
    text-align: center;
    background: rgba(122, 132, 80, 0.12);
    border: 1px dashed var(--olive);
    border-radius: 4px;
    padding: 14px 18px;
    margin-bottom: 24px;
    font-style: italic;
    color: var(--ink);
    font-size: 0.95rem;
    line-height: 1.5;
}

.pause-banner strong {
    color: var(--olive);
    font-style: normal;
    font-family: 'DM Mono', monospace;
    font-size: 0.7rem;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    display: block;
    margin-bottom: 4px;
}

header.dash h1 {
    font-size: clamp(2.4rem, 6vw, 3.4rem);
    font-weight: 300;
    font-style: italic;
    letter-spacing: -0.02em;
    line-height: 1;
    margin-bottom: 10px;
}

header.dash h1 .amp {
    color: var(--rose);
    /* A small upgrade to make the ampersand read more as a brand mark
       than a connecting character. Fraunces' optical-size axis lets us
       request a display-grade glyph specifically for this character. */
    font-size: 1.08em;
    font-variation-settings: "opsz" 29;
    font-style: normal;
    font-weight: 400;
    margin: 0 0.04em;
}


header.dash .subtitle {
    color: var(--ink-soft);
    font-size: 0.95rem;
    font-style: italic;
}

/* A small relationship-flavoured tagline shown above the heading
   on the doer's dashboard. Romantic for partners, gentler elsewhere. */
.doer-tagline {
    font-family: 'Fraunces', serif;
    font-style: italic;
    font-weight: 300;
    font-size: 1rem;
    color: var(--rose);
    margin-bottom: 6px;
    letter-spacing: 0.005em;
    opacity: 0.92;
}

.role-badge {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin-top: 14px;
    padding: 6px 14px;
    background: var(--paper-warm);
    border: 1px solid var(--line);
    border-radius: 999px;
    font-family: 'DM Mono', monospace;
    font-size: 0.66rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--ink-soft);
}

.role-badge .dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--olive);
}

/* ============ STATS ============ */
.stats {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1px;
    background: var(--line);
    border: 1px solid var(--line);
    margin-bottom: 32px;
    border-radius: 3px;
    overflow: hidden;
}

.stat {
    background: var(--paper-warm);
    padding: 18px 14px;
    text-align: center;
}

.stat .num {
    font-size: 2.2rem;
    font-weight: 300;
    line-height: 1;
    color: var(--ink);
}

.stat .num .of {
    color: var(--ink-soft);
    font-size: 1.2rem;
}

.stat .num.flame {
    color: var(--rose);
}

.stat .lbl {
    font-family: 'DM Mono', monospace;
    font-size: 0.6rem;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--ink-soft);
    margin-top: 6px;
}

/* ============ TASKS ============ */
.section-title {
    font-family: 'DM Mono', monospace;
    font-size: 0.7rem;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--ink-soft);
    margin-bottom: 14px;
    display: flex;
    align-items: center;
    gap: 12px;
}

.section-title::after {
    content: '';
    flex: 1;
    height: 1px;
    background: var(--line);
}

.task-list {
    list-style: none;
}

.task {
    display: flex;
    align-items: flex-start;
    gap: 14px;
    padding: 14px 4px;
    border-bottom: 1px dashed var(--line);
   /* animation: fadeIn 0.4s ease both;*/
    /* Smooth slide when rows shift to make room for a dragged item.
       Limited to transform so the fadeIn animation isn't interfered with
       on first paint. Box-shadow is also transitioned for the lift effect
       on the dragged row itself.
    transition: transform 0.18s ease, box-shadow 0.18s ease; */
}

/* Whichever row is currently being dragged: skip the entry animation,
   lift it visually with a soft shadow, and disable the smooth transform
   transition so it tracks the pointer 1:1 instead of lagging. */
.task.task-dragging {
    animation: none;
    transition: box-shadow 0.18s ease;
    z-index: 10;
    position: relative;
    background: var(--paper);
    box-shadow: 0 12px 28px -8px var(--shadow);
    border-radius: 4px;
    /* The bottom dashed border looks odd while floating — hide it. */
    border-bottom-color: transparent;
    /* Slight cursor feedback on desktop. */
    cursor: grabbing;
}

/* "Pressing" state — applied during the touch long-press wait (the
   250ms before drag activation). Without this, mobile users have no
   feedback that holding the handle is doing anything, and they assume
   drag is broken. The animation reaches its peak right when the long-
   press timer fires, naturally teaching the gesture timing: press,
   feel the row "loading", and at the moment it looks fully engaged,
   the actual drag begins. Duration matches LONG_PRESS_MS in JS. */
.task.task-drag-pressing {
    animation: dragPressing 250ms ease-out forwards;
    z-index: 5;
    position: relative;
    border-radius: 4px;
}

@keyframes dragPressing {
    from {
        transform: scale(1);
        background: transparent;
        box-shadow: 0 0 0 0 transparent;
    }
    to {
        transform: scale(1.015);
        background: var(--paper-warm);
        box-shadow: 0 4px 12px -4px var(--shadow);
    }
}

/* While the row is in the pressing state, make the handle fully
   visible so the user can see exactly what they're holding. */
.task.task-drag-pressing .task-drag-handle {
    opacity: 1;
    color: var(--ink);
}

/* While any drag is active, suppress text selection across the page so
   long-press on touch and click-drag on desktop don't accidentally select
   a task's text instead of starting the drag. */
body.task-drag-active {
    user-select: none;
    -webkit-user-select: none;
    /* On iOS Safari, also suppress the callout / magnifier. */
    -webkit-touch-callout: none;
}

/* Drag handle button — sits leftmost on the row. Same hover-fade pattern
   as the existing .task-delete button: invisible until hover, fully
   visible on focus, so it never competes for attention on a quiet row.
   Touch target is padded out (~24×32) so fingers can land it on mobile;
   the visible SVG inside is much smaller. */
.task-drag-handle {
    flex-shrink: 0;
    background: none;
    border: none;
    color: var(--ink-soft);
    padding: 8px 6px;
    margin-top: -2px;
    margin-left: -6px;
    margin-right: -4px;
    cursor: grab;
    opacity: 0;
    transition: opacity 0.2s, color 0.2s;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 3px;
}

.task:hover .task-drag-handle {
    opacity: 0.45;
}

.task-drag-handle:hover {
    opacity: 1 !important;
    color: var(--ink);
}

/* Keyboard focus must always be visible — even on a non-hovered row —
   so screen-reader / keyboard users can find the handle. */
.task-drag-handle:focus-visible {
    opacity: 1;
    outline: 2px solid var(--rose);
    outline-offset: 2px;
}

/* During an active drag the handle's cursor changes to grabbing.
   Applied to the handle inside the dragging row specifically so other
   handles on the page keep their grab cursor. */
.task.task-dragging .task-drag-handle {
    cursor: grabbing;
    opacity: 1;
}

/* On touch devices the hover state never triggers, so the handle would
   never appear. Make it permanently visible at a low opacity on
   coarse-pointer devices instead — discoverable without an interaction. */
@media (hover: none) and (pointer: coarse) {
    .task-drag-handle {
        opacity: 0.35;
    }
}

@keyframes fadeIn {
    from {
        opacity: 0;
        transform: translateY(4px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.task.carryover {
    background: linear-gradient(90deg, rgba(212, 162, 72, 0.1), transparent);
    padding-left: 12px;
    border-left: 2px solid var(--gold);
}

.checkbox {
    flex-shrink: 0;
    width: 22px;
    height: 22px;
    border: 1.5px solid var(--ink);
    border-radius: 4px;
    cursor: pointer;
    background: transparent;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-top: 3px;
    transition: all 0.2s;
}

.checkbox:hover {
    border-color: var(--rose);
}

.checkbox.checked {
    background: var(--rose);
    border-color: var(--rose);
}

.checkbox.checked::after {
    content: '';
    width: 12px;
    height: 6px;
    border-left: 2px solid var(--paper);
    border-bottom: 2px solid var(--paper);
    transform: rotate(-45deg) translate(1px, -1px);
}

.checkbox.readonly {
    cursor: default;
}

.task-text {
    flex: 1;
    font-size: 1.06rem;
    line-height: 1.5;
    color: var(--ink);
    padding-top: 1px;
}

.task.done .task-text {
    text-decoration: line-through;
    text-decoration-color: var(--rose);
    text-decoration-thickness: 1.5px;
    color: var(--ink-soft);
    font-style: italic;
}

.carryover-tag {
    display: inline-block;
    margin-left: 8px;
    font-family: 'DM Mono', monospace;
    font-size: 0.6rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--gold);
    vertical-align: middle;
}

.task-delete {
    background: none;
    border: none;
    color: var(--ink-soft);
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.2s;
    font-size: 1.1rem;
    padding: 0 6px;
}

.task:hover .task-delete {
    opacity: 0.6;
}

.task-delete:hover {
    opacity: 1 !important;
    color: var(--rose);
}

/* Snoozed tag — same shape as the carryover tag but olive-coloured to
   distinguish "set aside on purpose" from "rolled over from yesterday". */
.snoozed-tag {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-left: 8px;
    font-family: 'DM Mono', monospace;
    font-size: 0.6rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--olive);
    vertical-align: middle;
}

/* The inline icon inside the tag — sized to match the tag's letter height. */
.snoozed-tag img {
    width: 0.85rem;
    height: 0.85rem;
    display: block;
}

/* A snoozed task is visibly faded and italicised — present in the list
   but signalling "not active right now". The strike-through from .done
   doesn't apply because a snoozed task can't be done. */
.task.snoozed {
    opacity: 0.55;
}

.task.snoozed .task-text {
    font-style: italic;
}

/* Snoozed tasks sit *outside* the carryover gradient even if they were
   once carried — the snoozed treatment takes priority. */
.task.snoozed.carryover {
    background: none;
    border-left: 2px solid var(--olive);
    padding-left: 12px;
}

/* Snooze toggle button — same hover-fade pattern as the delete button.
   No special colour treatment; the icon (snooze.svg or ↩) carries the meaning. */
.task-snooze {
    background: none;
    border: none;
    color: var(--ink-soft);
    cursor: pointer;
    opacity: 1;
    transition: opacity 0.2s;
    font-size: 0.95rem;
    padding: 0 6px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* The inline image inside the button — sized to match other row icons. */
.task-snooze img {
    width: 1.1rem;
    height: 1.1rem;
    display: block;
}

.task:hover .task-snooze {
    opacity: 0.6;
}

.task-snooze:hover {
    opacity: 1 !important;
}

/* On a snoozed task the "↩ bring back" button is always visible — the
   row otherwise looks dormant, so the affordance to revive it should
   be discoverable without a hover. */
.task.snoozed .task-snooze {
    opacity: 0.7;
}

.task.snoozed:hover .task-snooze {
    opacity: 1;
}

.add-task {
    display: flex;
    gap: 10px;
    margin-top: 18px;
}

.add-task input {
    flex: 1;
    background: var(--paper-warm);
}

.add-task input:focus {
    background: var(--paper);
}

.add-task button {
    padding: 0 22px;
    height: auto;
}

.empty {
    text-align: center;
    padding: 36px 20px;
    color: var(--ink-soft);
    font-style: italic;
    font-size: 1rem;
}

/* ============ NOTES ============ */
.notes-section {
    margin-top: 36px;
    padding: 24px;
    background: var(--paper-warm);
    border: 1px solid var(--line);
    border-radius: 4px;
    position: relative;
}

.notes-section::before {
    content: '♡';
    position: absolute;
    top: -12px;
    left: 24px;
    background: var(--paper);
    padding: 0 10px;
    color: var(--rose);
    font-size: 1.2rem;
}

.note {
    padding: 12px 0;
    border-bottom: 1px dashed var(--line);
    font-size: 1rem;
    line-height: 1.55;
    animation: fadeIn 0.4s ease both;
    display: flex;
    gap: 12px;
    align-items: flex-start;
}

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

.note .note-emoji {
    font-size: 1.4rem;
    line-height: 1.2;
    flex-shrink: 0;
}

.note .note-body {
    flex: 1;
}

.note .meta {
    font-family: 'DM Mono', monospace;
    font-size: 0.62rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--rose);
    margin-bottom: 4px;
}

.note .meta .author {
    color: var(--ink-soft);
    margin-left: 8px;
}

.emoji-strip {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 14px;
    margin-bottom: 8px;
}

.emoji-strip button {
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: 999px;
    padding: 6px 10px;
    cursor: pointer;
    font-size: 1.15rem;
    transition: all 0.15s;
    line-height: 1;
}

.emoji-strip button:hover {
    background: var(--rose);
    border-color: var(--rose);
    transform: translateY(-2px) scale(1.1);
}

.emoji-strip-label {
    font-family: 'DM Mono', monospace;
    font-size: 0.6rem;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--ink-soft);
    margin: 14px 0 4px;
}

.note-input {
    display: flex;
    gap: 10px;
    margin-top: 12px;
}

.note-input textarea {
    flex: 1;
    min-height: 50px;
    resize: none;
    font-style: italic;
    font-size: 0.98rem;
}

.note-input button {
    padding: 0 18px;
    align-self: flex-end;
    height: 50px;
}

/* ============ MENU MODAL ============ */
.modal-bg {
    position: fixed;
    inset: 0;
    background: rgba(43, 29, 20, 0.5);
    z-index: 200;
    display: none;
    align-items: center;
    justify-content: center;
    padding: 20px;
}

.modal-bg.show {
    display: flex;
}

.modal {
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: 6px;
    padding: 32px;
    max-width: 500px;
    width: 100%;
    max-height: 85vh;
    overflow-y: auto;
    box-shadow: 0 40px 80px -30px rgba(0, 0, 0, 0.4);
}

.modal h2 {
    font-size: 1.6rem;
    font-weight: 300;
    font-style: italic;
    margin-bottom: 8px;
}

.modal-section {
    padding: 18px 0;
    border-bottom: 1px dashed var(--line);
}

.modal-section:last-child {
    border-bottom: none;
}

.modal-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    padding: 8px 0;
}

.modal-row .lbl-stack {
    flex: 1;
}

.modal-row .lbl-stack .label-line {
    font-size: 1rem;
    color: var(--ink);
}

.modal-row .lbl-stack .desc-line {
    font-size: 0.85rem;
    color: var(--ink-soft);
    font-style: italic;
    margin-top: 2px;
}

/* toggle */
.toggle {
    position: relative;
    width: 44px;
    height: 24px;
    background: var(--line);
    border-radius: 999px;
    cursor: pointer;
    transition: background 0.2s;
    flex-shrink: 0;
}

.toggle::after {
    content: '';
    position: absolute;
    width: 18px;
    height: 18px;
    background: var(--paper);
    border-radius: 50%;
    top: 3px;
    left: 3px;
    transition: left 0.2s;
}

.toggle.on {
    background: var(--rose);
}

.toggle.on::after {
    left: 23px;
}

.danger {
    color: var(--rose);
}

/* ============ INVITE/SHARE ============ */
.link-box {
    background: var(--paper-warm);
    border: 1px dashed var(--line);
    padding: 14px;
    border-radius: 3px;
    word-break: break-all;
    font-family: 'DM Mono', monospace;
    font-size: 0.78rem;
    color: var(--ink-soft);
    margin: 16px 0;
    line-height: 1.5;
}

.checkmark-circle {
    width: 56px;
    height: 56px;
    border-radius: 50%;
    background: var(--rose);
    margin: 0 auto 18px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.checkmark-circle::after {
    content: '';
    width: 20px;
    height: 10px;
    border-left: 3px solid var(--paper);
    border-bottom: 3px solid var(--paper);
    transform: rotate(-45deg) translate(2px, -3px);
}

/* ============ STATUS ============ */
.sync-status {
    position: fixed;
    bottom: 16px;
    right: 16px;
    font-family: 'DM Mono', monospace;
    font-size: 0.62rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--ink-soft);
    background: var(--paper-warm);
    padding: 7px 13px;
    border-radius: 999px;
    border: 1px solid var(--line);
    z-index: 100;
    transition: opacity 0.4s;
}

.sync-status .dot {
    display: inline-block;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--olive);
    margin-right: 6px;
    vertical-align: middle;
}

.sync-status.syncing .dot {
    background: var(--gold);
    animation: pulse 1s infinite;
}

.sync-status.error .dot {
    background: var(--rose);
}

@keyframes pulse {
    0%, 100% {
        opacity: 1;
    }
    50% {
        opacity: 0.3;
    }
}

/* ============ SAFETY FOOTER ============ */
.safety-footer {
    text-align: center;
    margin-top: 36px;
    padding: 20px;
    font-size: 0.82rem;
    color: var(--ink-soft);
    font-style: italic;
    line-height: 1.6;
    max-width: 460px;
    margin-left: auto;
    margin-right: auto;
}

.safety-footer a {
    color: var(--ink-soft);
    text-decoration: underline;
    text-decoration-style: dotted;
    text-underline-offset: 3px;
}

@media (max-width: 540px) {
    .container {
        padding: 28px 18px 80px;
    }

    .stat .num {
        font-size: 1.7rem;
    }

    .role-grid {
        grid-template-columns: 1fr;
    }

    .modal {
        padding: 24px 20px;
    }
}

/* config screen */
.config-warning {
    background: rgba(212, 162, 72, 0.15);
    border: 1px dashed var(--gold);
    padding: 20px;
    border-radius: 4px;
    margin-top: 20px;
    font-size: 0.95rem;
    line-height: 1.6;
    color: var(--ink);
}

.config-warning code {
    background: var(--paper);
    padding: 2px 6px;
    border-radius: 3px;
    font-family: 'DM Mono', monospace;
    font-size: 0.85em;
}


/* ============================================================
   PRIVACY PAGE STYLES
   Specific to /privacy.html. Shares :root, *, html/body, .container
   with the rest of the app — those live above this block.
   ============================================================ */

/* ── NAV ── */
.nav {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 52px;
}

.wordmark {
    font-family: 'DM Mono', monospace;
    font-size: 0.7rem;
    letter-spacing: 0.32em;
    text-transform: uppercase;
    color: var(--ink-soft);
    text-decoration: none;
}

.wordmark:hover { color: var(--rose); }

.back-link {
    font-family: 'DM Mono', monospace;
    font-size: 0.68rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--ink-soft);
    text-decoration: none;
    border-bottom: 1px dotted var(--ink-soft);
    padding-bottom: 1px;
    transition: color 0.2s;
}

.back-link:hover { color: var(--rose); border-color: var(--rose); }

/* ── HEADER ── */
.page-header {
    margin-bottom: 48px;
}

.page-header .eyebrow {
    font-family: 'DM Mono', monospace;
    font-size: 0.68rem;
    letter-spacing: 0.24em;
    text-transform: uppercase;
    color: var(--rose);
    margin-bottom: 14px;
}

.page-header h1 {
    font-size: clamp(2.4rem, 6vw, 3.4rem);
    font-weight: 300;
    font-style: italic;
    letter-spacing: -0.02em;
    line-height: 1;
    margin-bottom: 16px;
}

.page-header .meta {
    font-family: 'DM Mono', monospace;
    font-size: 0.68rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--ink-soft);
}

/* ── INTRO CARD ── */
.intro-card {
    background: var(--paper-warm);
    border: 1px solid var(--line);
    border-radius: 4px;
    padding: 28px 32px;
    margin-bottom: 48px;
    border-left: 3px solid var(--rose-soft);
}

.intro-card p {
    font-size: 1.05rem;
    color: var(--ink-soft);
    line-height: 1.65;
    font-style: italic;
}

/* ── SECTIONS ── */
.section {
    margin-bottom: 44px;
    padding-bottom: 44px;
    border-bottom: 1px dashed var(--line);
}

.section:last-child {
    border-bottom: none;
}

.section-label {
    font-family: 'DM Mono', monospace;
    font-size: 0.65rem;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--rose);
    margin-bottom: 10px;
}

.section h2 {
    font-size: 1.55rem;
    font-weight: 300;
    font-style: italic;
    letter-spacing: -0.01em;
    margin-bottom: 18px;
    color: var(--ink);
}

.section p {
    font-size: 1rem;
    color: var(--ink-soft);
    line-height: 1.7;
    margin-bottom: 14px;
}

.section p:last-child { margin-bottom: 0; }

.section p a {
    color: var(--rose);
    text-decoration: underline;
    text-decoration-style: dotted;
    text-underline-offset: 3px;
}

.section p a:hover { color: var(--ink); }

/* ── DATA LIST ── */
.data-list {
    list-style: none;
    margin: 14px 0;
}

.data-list li {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 11px 0;
    border-bottom: 1px dashed var(--line);
    font-size: 0.98rem;
    color: var(--ink-soft);
    line-height: 1.5;
}

.data-list li:last-child { border-bottom: none; }

.data-list li::before {
    content: '—';
    color: var(--rose-soft);
    font-family: 'DM Mono', monospace;
    flex-shrink: 0;
    margin-top: 1px;
}

/* ── RIGHTS GRID ── */
.rights-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    margin-top: 18px;
}

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

.right-card {
    background: var(--paper-warm);
    border: 1px solid var(--line);
    border-radius: 4px;
    padding: 16px 18px;
}

.right-card .right-title {
    font-family: 'DM Mono', monospace;
    font-size: 0.66rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--ink);
    margin-bottom: 6px;
}

.right-card p {
    font-size: 0.88rem;
    color: var(--ink-soft);
    line-height: 1.5;
    margin: 0 !important;
}

/* ── HIGHLIGHT BOX ── */
.highlight {
    background: rgba(122, 132, 80, 0.1);
    border: 1px dashed var(--olive);
    border-radius: 4px;
    padding: 18px 22px;
    margin-top: 18px;
}

.highlight p {
    font-size: 0.95rem !important;
    color: var(--ink) !important;
    margin: 0 !important;
}

.highlight strong {
    font-style: normal;
    color: var(--olive);
    font-family: 'DM Mono', monospace;
    font-size: 0.7rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    display: block;
    margin-bottom: 6px;
}

/* ── CONTACT STRIP ── */
.contact-strip {
    background: var(--paper-warm);
    border: 1px solid var(--line);
    border-radius: 4px;
    padding: 28px 32px;
    margin-top: 56px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
    flex-wrap: wrap;
}

.contact-strip p {
    font-size: 1rem;
    color: var(--ink-soft);
    font-style: italic;
    line-height: 1.5;
}

.contact-strip .btn {
    padding: 11px 22px;
    background: var(--ink);
    color: var(--paper);
    border: none;
    font-family: 'DM Mono', monospace;
    font-size: 0.7rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    cursor: pointer;
    border-radius: 3px;
    text-decoration: none;
    white-space: nowrap;
    transition: background 0.2s;
    flex-shrink: 0;
}

.contact-strip .btn:hover { background: var(--rose); }

/* ── FOOTER ── */
.footer {
    margin-top: 64px;
    padding-top: 24px;
    border-top: 1px solid var(--line);
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 12px;
}

.footer span {
    font-family: 'DM Mono', monospace;
    font-size: 0.63rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--ink-soft);
    opacity: 0.7;
}

.footer a {
    font-family: 'DM Mono', monospace;
    font-size: 0.63rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--ink-soft);
    text-decoration: none;
    opacity: 0.7;
}

.footer a:hover { opacity: 1; color: var(--rose); }

/* ── FADE IN ── */
.section {
    opacity: 0;
    transform: translateY(8px);
    animation: rise 0.5s ease forwards;
}

.section:nth-child(1) { animation-delay: 0.05s; }
.section:nth-child(2) { animation-delay: 0.10s; }
.section:nth-child(3) { animation-delay: 0.15s; }
.section:nth-child(4) { animation-delay: 0.20s; }
.section:nth-child(5) { animation-delay: 0.25s; }
.section:nth-child(6) { animation-delay: 0.30s; }
.section:nth-child(7) { animation-delay: 0.35s; }
.section:nth-child(8) { animation-delay: 0.40s; }
.section:nth-child(9) { animation-delay: 0.45s; }

@keyframes rise {
    to { opacity: 1; transform: translateY(0); }
}

/* ── Heart particle effect (gamification) ─────────────────────────

   Used on task completion and other small celebratory moments. See
   particles.js for the JS that spawns these. The CSS does all the
   animation work — JS just sets a few custom properties per
   particle for randomised trajectories.

   Coordinate system: the wrapper is absolutely positioned at the
   origin point (the centre of e.g. a checkbox). Particles inside the
   wrapper start at (0, 0) and animate via translate3d to their final
   offsets (--dx-end, --dy-end). The translate3d hint encourages the
   browser to composite each particle on the GPU, which keeps bursts
   smooth even on weaker mobile devices. */

.heart-burst {
    position: fixed;
    top: 0;
    left: 0;
    width: 0;
    height: 0;
    pointer-events: none;
    /* High z-index so particles always float above the rest of the UI
       — including modals, the dragging row, the sync banner — but
       below browser-level chrome. 9999 is a common ceiling for
       in-content overlays. */
    z-index: 9999;
}

.heart-particle {
    position: absolute;
    /* Particles spawn at the wrapper's origin (the burst point) and
       animate outward. The translate(-50%, -50%) initial centring
       means the visual centre of each heart is at the spawn point,
       so a 6-particle burst radiates symmetrically rather than
       leaning down-and-right. */
    left: 0;
    top: 0;
    transform: translate(-50%, -50%);
    color: var(--rose);
    will-change: transform, opacity;
    animation-name: heartFloat;
    animation-timing-function: cubic-bezier(0.2, 0.6, 0.4, 1);
    animation-fill-mode: forwards;
    /* animation-duration is set per-particle from JS so each heart
       has a slightly different lifetime — they don't all vanish in
       lockstep. */
}

/* A small fraction of hearts use the soft rose variant — adds gentle
   colour variation so a burst looks hand-drawn rather than cloned. */
.heart-particle--soft {
    color: var(--rose-soft);
}

.heart-particle svg {
    width: 100%;
    height: 100%;
    display: block;
}

/* The animation interpolates each particle from spawn point to its
   final offset, with a slight rotation and an opacity fade in the
   second half of its lifetime. Using translate3d hints to the browser
   to composite on the GPU. */
@keyframes heartFloat {
    0% {
        opacity: 0;
        transform: translate(-50%, -50%) translate3d(0, 0, 0) rotate(0deg) scale(0.5);
    }
    /* Pop-in: hit full size and full opacity quickly so the burst
       reads as immediate response to the click, not a slow fade-in. */
    15% {
        opacity: 1;
        transform: translate(-50%, -50%) translate3d(calc(var(--dx-end) * 0.2), calc(var(--dy-end) * 0.2), 0) rotate(calc(var(--rot-end) * 0.2)) scale(1);
    }
    /* Travel: full opacity, particle drifts toward its end position. */
    70% {
        opacity: 1;
        transform: translate(-50%, -50%) translate3d(calc(var(--dx-end) * 0.85), calc(var(--dy-end) * 0.85), 0) rotate(calc(var(--rot-end) * 0.85)) scale(0.95);
    }
    /* Fade-out at the very end — opacity drops while the particle
       finishes its arc. */
    100% {
        opacity: 0;
        transform: translate(-50%, -50%) translate3d(var(--dx-end), var(--dy-end), 0) rotate(var(--rot-end)) scale(0.7);
    }
}

/* ── Daily completion celebration ─────────────────────────────

   When the doer ticks the final task of the day, a soft warm overlay
   washes across the page for a couple of seconds. Calmer than the
   per-tick burst — this is the "you finished today" moment, not a
   high-energy fireworks event.

   The body class is toggled on by main.js; the animation runs once
   and the class is removed when it finishes (animationend in JS).
   Using a body class rather than a fresh DOM element keeps the
   effect global and avoids any layout interaction with the page. */

body.celebrating-completion::before {
    content: '';
    position: fixed;
    inset: 0;
    pointer-events: none;
    background: radial-gradient(
        ellipse at center,
        rgba(212, 162, 72, 0.18) 0%,
        rgba(212, 162, 72, 0.08) 30%,
        transparent 70%
    );
    z-index: 9998;
    animation: completionGlow 2400ms ease-out forwards;
}

@keyframes completionGlow {
    0% {
        opacity: 0;
    }
    20% {
        opacity: 1;
    }
    100% {
        opacity: 0;
    }
}

/* The dashboard subtitle gets a temporary "you did it" message during
   the celebration. The transition makes the text change feel like a
   gentle shift rather than a sudden swap. */
.subtitle.celebrating {
    transition: opacity 0.4s ease, color 0.4s ease;
    color: var(--gold);
}
